From 7769e63a51d4cc32a2f9334e26a964d66c34c55f Mon Sep 17 00:00:00 2001 From: Luke Kenneth Casson Leighton Date: Fri, 21 Jan 2022 15:01:11 +0000 Subject: [PATCH] add uart save/restore state to microwatt-verilator --- verilator/microwatt-verilator.cpp | 15 ++++++------- verilator/uart-verilator.c | 37 ++++++------------------------- verilator/uart-verilator.h | 32 ++++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 38 deletions(-) create mode 100644 verilator/uart-verilator.h diff --git a/verilator/microwatt-verilator.cpp b/verilator/microwatt-verilator.cpp index 485b23c..5c91f92 100644 --- a/verilator/microwatt-verilator.cpp +++ b/verilator/microwatt-verilator.cpp @@ -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 diff --git a/verilator/uart-verilator.c b/verilator/uart-verilator.c index 79c0556..5f04cee 100644 --- a/verilator/uart-verilator.c +++ b/verilator/uart-verilator.c @@ -5,6 +5,7 @@ #include #include #include +#include "uart-verilator.h" /* Should we exit simulation on ctrl-c or pass it through? */ #define EXIT_ON_CTRL_C @@ -13,32 +14,6 @@ /* 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 index 0000000..10ae8aa --- /dev/null +++ b/verilator/uart-verilator.h @@ -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 *); + -- 2.30.2