summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--aarch64/uart.sail100
1 files changed, 100 insertions, 0 deletions
diff --git a/aarch64/uart.sail b/aarch64/uart.sail
new file mode 100644
index 00000000..442a175e
--- /dev/null
+++ b/aarch64/uart.sail
@@ -0,0 +1,100 @@
+$include "prelude.sail"
+
+val "zero_extend" : forall 'n 'm, 'm >= 'n. (bits('n), atom('m)) -> bits('m)
+
+register _UART_ADDR : bits(52)
+
+val initialize_uart : bits(52) -> unit effect {wreg}
+
+function initialize_uart(base_address) = {
+ _UART_ADDR = base_address;
+}
+
+register UARTDR : bits(12)
+register UARTRSR : bits(4)
+register UARTFR : bits(9)
+register UARTILPR : bits(8)
+register UARTIBRD : bits(16)
+register UARTFBRD : bits(6)
+register UARTLCR_H : bits(8)
+register UARTCR : bits(16)
+register UARTIFLS : bits(6)
+register UARTIMSC : bits(11)
+register UARTRIS : bits(11)
+register UARTMIS : bits(11)
+
+/* write only, so implement as function? */
+val UARTICR : bits(11) -> unit
+function UARTICR(b) = () /* TODO */
+
+register UARTDMACR : bits(3)
+
+val write_uart : forall 'n, 0 <= 'n <= 32. (bits(12), bits('n)) -> unit effect {escape, wreg}
+
+function write_uart(offset, data) = {
+ let data = zero_extend(data, 32);
+ match offset {
+ 0x000 => UARTDR = data[0, 12],
+ 0x004 => UARTRSR = data[0, 4],
+ /* 0x008 - 0x014 Reserved */
+ /* 0x018 UARTFR read only */
+ /* 0x01C Reserved */
+ 0x020 => UARTILPR = data[0, 8],
+ 0x024 => UARTIBRD = data[0, 16],
+ 0x028 => UARTFBRD = data[0, 6],
+ 0x02C => UARTLCR_H = data[0, 8],
+ 0x030 => UARTCR = data[0, 16],
+ 0x034 => UARTIFLS = data[0, 6],
+ 0x038 => UARTIMSC = data[0, 11],
+ /* 0x03C UARTRIS read only */
+ /* 0x040 UARTMIS read only */
+ 0x044 => UARTICR() = data[0, 11],
+ 0x048 => UARTDMACR = data[0, 3],
+
+ _ => throw(Error_Undefined())
+ }
+}
+
+val read_uart : bits(12) -> bits(32) effect {escape, rreg}
+
+function read_uart(offset) = {
+ let data : {'n, 0 <= 'n <= 32. bits('n)} = match offset {
+ 0x000 => UARTDR,
+ 0x004 => UARTRSR,
+ /* 0x008 - 0x014 Reserved */
+ 0x018 => UARTFR,
+ /* 0x01C Reserved */
+ 0x020 => UARTILPR,
+ 0x024 => UARTIBRD,
+ 0x028 => UARTFBRD,
+ 0x02C => UARTLCR_H,
+ 0x030 => UARTCR,
+ 0x034 => UARTIFLS,
+ 0x038 => UARTIMSC,
+ 0x03C => UARTRIS,
+ 0x040 => UARTMIS,
+ /* 0x044 UARTICR write only */
+ 0x048 => UARTDMACR,
+
+ _ => throw(Error_Undefined())
+ };
+ zero_extend(data, 32)
+}
+
+val reset_uart : unit -> unit effect {wreg, undef}
+
+function reset_uart() = {
+ UARTDR = undefined;
+ UARTRSR = 0x0;
+ UARTFR = undefined : bits(1) @ 0b10010 @ undefined : bits(3);
+ UARTILPR = 0x00;
+ UARTIBRD = 0x0000;
+ UARTFBRD = 0b00_0000;
+ UARTLCR_H = 0x00;
+ UARTCR = 0x0300;
+ UARTIFLS = 0b01 @ 0x2;
+ UARTIMSC = 0b000_0000_0000;
+ UARTRIS = 0x00 @ undefined : bits(3);
+ UARTMIS = 0x00 @ undefined : bits(3);
+ UARTDMACR = 0b000
+} \ No newline at end of file