serv/bench/servant_tb.cpp
2019-06-24 13:18:34 +02:00

128 lines
2.7 KiB
C++

#include <stdint.h>
#include <signal.h>
#include "verilated_vcd_c.h"
#include "Vservant.h"
using namespace std;
static bool done;
vluint64_t main_time = 0; // Current simulation time
// This is a 64-bit integer to reduce wrap over issues and
// allow modulus. You can also use a double, if you wish.
double sc_time_stamp () { // Called by $time in Verilog
return main_time; // converts to double, to match
// what SystemC does
}
void INThandler(int signal)
{
printf("\nCaught ctrl-c\n");
done = true;
}
typedef struct {
bool last_value;
} gpio_context_t;
void do_gpio(gpio_context_t *context, bool gpio) {
if (context->last_value != gpio) {
context->last_value = gpio;
printf("%lu output q is %s\n", main_time, gpio ? "ON" : "OFF");
}
}
typedef struct {
uint8_t state;
char ch;
uint32_t baud_t;
vluint64_t last_update;
} uart_context_t;
void uart_init(uart_context_t *context, uint32_t baud_rate) {
context->baud_t = 1000*1000*1000/baud_rate;
}
void do_uart(uart_context_t *context, bool rx) {
if (context->state == 0) {
if (!rx) {
context->last_update = main_time + context->baud_t/2;
context->state++;
}
}
else if(context->state == 1) {
if (main_time > context->last_update) {
context->last_update += context->baud_t;
context->ch = 0;
context->state++;
}
}
else if (context->state < 10) {
if (main_time > context->last_update) {
context->last_update += context->baud_t;
context->ch |= rx << (context->state-2);
context->state++;
}
}
else {
if (main_time > context->last_update) {
context->last_update += context->baud_t;
putchar(context->ch);
context->state=0;
}
}
}
int main(int argc, char **argv, char **env)
{
vluint64_t sample_time = 0;
uint32_t insn = 0;
uint32_t ex_pc = 0;
int baud_rate = 0;
gpio_context_t gpio_context;
uart_context_t uart_context;
Verilated::commandArgs(argc, argv);
Vservant* top = new Vservant;
const char *arg = Verilated::commandArgsPlusMatch("uart_baudrate=");
if (arg[0]) {
baud_rate = atoi(arg+15);
if (baud_rate) {
uart_init(&uart_context, baud_rate);
}
}
VerilatedVcdC * tfp = 0;
const char *vcd = Verilated::commandArgsPlusMatch("vcd=");
if (vcd[0]) {
Verilated::traceEverOn(true);
tfp = new VerilatedVcdC;
top->trace (tfp, 99);
tfp->open ("trace.vcd");
}
signal(SIGINT, INThandler);
top->wb_clk = 1;
bool q = top->q;
while (!(done || Verilated::gotFinish())) {
top->wb_rst = main_time < 100;
top->eval();
if (tfp)
tfp->dump(main_time);
if (baud_rate)
do_uart(&uart_context, top->q);
else
do_gpio(&gpio_context, top->q);
top->wb_clk = !top->wb_clk;
main_time+=31.25;
}
if (tfp)
tfp->close();
exit(0);
}