add uart save/restore state to microwatt-verilator
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Fri, 21 Jan 2022 15:01:11 +0000 (15:01 +0000)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Fri, 21 Jan 2022 15:01:11 +0000 (15:01 +0000)
verilator/microwatt-verilator.cpp
verilator/uart-verilator.c
verilator/uart-verilator.h [new file with mode: 0644]

index 485b23c8d68622651dcfeb45d6b3f63db34363ec..5c91f92d949249e15d8718845fdf02ad37ca8c2f 100644 (file)
@@ -8,6 +8,7 @@
 #include "Vmicrowatt.h"
 #include "verilated.h"
 #include "verilated_vcd_c.h"
+#include "uart-verilated.h"
 
 /*
  * Current simulation time
@@ -49,14 +50,6 @@ void tick(Vmicrowatt *top, bool dump)
        main_time++;
 }
 
-// simulated uart tx/rx, assumes a baud rate of 115200 based on CLK_FREQUENCY
-void uart_tx(unsigned char tx);
-unsigned char uart_rx(void);
-
-// true if the uart tx and rx are both idle
-// (saves having to save/restore/sync the uart state)
-bool uart_idle(void);
-
 // pretty-print dumped data in ASCII (to help identify strings)
 static void ascii_dump(unsigned char *data, int len, FILE *dump)
 {
@@ -75,8 +68,11 @@ void save_model(vluint64_t time, Vmicrowatt* topp)
     char fname[128];
     sprintf(fname, "verilator.save.%ld", time);
     VerilatedSave os;
+    struct uart_tx_state *uart = uart_get_state();
+
     os.open(fname);
     os << main_time;  // user code must save the timestamp, etc
+    os << *uart;
     os << *topp;
 }
 
@@ -85,9 +81,12 @@ void restore_model(vluint64_t time, Vmicrowatt* topp)
     char fname[128];
     sprintf(fname, "verilator.save.%ld", time);
     VerilatedRestore os;
+    struct uart_tx_state uart;
     os.open(fname);
     os >> main_time;
+    os >> uart;
     os >> *topp;
+    uart_restore(&uart);
 }
 
 //save bram memory out to a file. use for snapshots
index 79c055628d725a23df300ad9e54276dfadc227b0..5f04ceea7f25b19ed3a2fc5d9b444edf2a353f46 100644 (file)
@@ -5,6 +5,7 @@
 #include <stdio.h>
 #include <termios.h>
 #include <stdlib.h>
+#include "uart-verilator.h"
 
 /* Should we exit simulation on ctrl-c or pass it through? */
 #define EXIT_ON_CTRL_C
 /* Round to nearest */
 #define BITWIDTH ((CLK_FREQUENCY+(BAUD/2))/BAUD)
 
-enum state {
-       IDLE, START_BIT, BITS, STOP_BIT, ERROR
-};
-
-/*
- * Our UART uses 16x oversampling, so at 50 MHz and 115200 baud
- * each sample is: 50000000/(115200*16) = 27 clock cycles. This
- * means each bit is off by 0.47% so for 8 bits plus a start and
- * stop bit the errors add to be 4.7%.
- */
-struct uart_tx_state {
-    double error = 0.05;
-
-    enum state tx_state = IDLE;
-    unsigned long tx_countbits;
-    unsigned char tx_bits;
-    unsigned char tx_byte;
-    unsigned char tx_prev;
-
-    enum state rx_state = IDLE;
-    unsigned char rx_char;
-    unsigned long rx_countbits;
-    unsigned char rx_bit;
-    unsigned char rx = 1;
-};
-
 static struct uart_tx_state uart;
 
 /*
@@ -256,10 +231,12 @@ unsigned char uart_rx(void)
        return uart.rx;
 }
 
-// cheating, here: to avoid having to save the uart state, check if it
-// is idle (both tx and rx)
-bool uart_state(void)
+struct uart_tx_state * uart_get_state(void)
 {
-       return (uart.tx_state == IDLE && uart.rx_state == IDLE);
+    return &uart;
 }
 
+void uart_restore(struct uart_tx_state *new_state)
+{
+    uart = *new_state;
+}
diff --git a/verilator/uart-verilator.h b/verilator/uart-verilator.h
new file mode 100644 (file)
index 0000000..10ae8aa
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Our UART uses 16x oversampling, so at 50 MHz and 115200 baud
+ * each sample is: 50000000/(115200*16) = 27 clock cycles. This
+ * means each bit is off by 0.47% so for 8 bits plus a start and
+ * stop bit the errors add to be 4.7%.
+ */
+
+enum state {
+    IDLE, START_BIT, BITS, STOP_BIT, ERROR
+};
+
+struct uart_tx_state {
+    double error = 0.05;
+
+    enum state tx_state = IDLE;
+    unsigned long tx_countbits;
+    unsigned char tx_bits;
+    unsigned char tx_byte;
+    unsigned char tx_prev;
+
+    enum state rx_state = IDLE;
+    unsigned char rx_char;
+    unsigned long rx_countbits;
+    unsigned char rx_bit;
+    unsigned char rx = 1;
+};
+
+void uart_tx(unsigned char tx);
+unsigned char uart_rx(void);
+struct uart_tx_state * uart_get_state(void);
+void uart_restore(struct uart_tx_state *);
+