diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index cb972de..28d0a13 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -93,3 +93,17 @@ jobs: steps: - uses: actions/checkout@v2 - run: make DOCKER=1 microwatt.v + + verilator: + runs-on: ubuntu-latest + env: + DOCKER: 1 + FPGA_TARGET: verilator + RAM_INIT_FILE: micropython/firmware.hex + MEMORY_SIZE: 524288 + steps: + - uses: actions/checkout@v2 + - run: | + sudo apt update + sudo apt install -y python3-pexpect + make -j$(nproc) test_micropython_verilator test_micropython_verilator_long diff --git a/Makefile b/Makefile index a4b8df5..9f308ba 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,8 @@ GHDL ?= ghdl GHDLFLAGS=--std=08 CFLAGS=-O3 -Wall -VERILATOR_FLAGS=-O3 #--trace +# Need to investigate why yosys is hitting verilator warnings, and eventually turn on -Wall +VERILATOR_FLAGS=-O3 -Wno-fatal -Wno-CASEOVERLAP -Wno-UNOPTFLAT #--trace # It takes forever to build with optimisation, so disable by default #VERILATOR_CFLAGS=-O3 @@ -11,6 +12,7 @@ NEXTPNR ?= nextpnr-ecp5 ECPPACK ?= ecppack OPENOCD ?= openocd VUNITRUN ?= python3 ./run.py +VERILATOR ?= verilator # We need a version of GHDL built with either the LLVM or gcc backend. # Fedora provides this, but other distros may not. Another option is to use @@ -39,6 +41,7 @@ NEXTPNR = $(DOCKERBIN) $(DOCKERARGS) hdlc/nextpnr:ecp5 nextpnr-ecp5 ECPPACK = $(DOCKERBIN) $(DOCKERARGS) hdlc/prjtrellis ecppack OPENOCD = $(DOCKERBIN) $(DOCKERARGS) --device /dev/bus/usb hdlc/prog openocd VUNITRUN = $(DOCKERBIN) $(DOCKERARGS) ghdl/vunit:llvm python3 ./run.py +VERILATOR = $(DOCKERBIN) $(DOCKERARGS) verilator/verilator:latest endif VUNITARGS += -p10 @@ -138,8 +141,8 @@ $(soc_dram_tbs): %: $(soc_dram_files) $(soc_dram_sim_files) $(soc_dram_sim_obj_f endif # Hello world -MEMORY_SIZE=8192 -RAM_INIT_FILE=hello_world/hello_world.hex +MEMORY_SIZE ?=8192 +RAM_INIT_FILE ?=hello_world/hello_world.hex # Micropython #MEMORY_SIZE=393216 @@ -201,10 +204,8 @@ microwatt.json: $(synth_files) $(RAM_INIT_FILE) microwatt.v: $(synth_files) $(RAM_INIT_FILE) $(YOSYS) -m $(GHDLSYNTH) -p "ghdl --std=08 --no-formal $(GHDL_IMAGE_GENERICS) $(synth_files) -e toplevel; write_verilog $@" -# Need to investigate why yosys is hitting verilator warnings, and eventually turn on -Wall microwatt-verilator: microwatt.v verilator/microwatt-verilator.cpp verilator/uart-verilator.c - verilator $(VERILATOR_FLAGS) -CFLAGS "$(VERILATOR_CFLAGS) -DCLK_FREQUENCY=$(CLK_FREQUENCY)" --assert --cc $< --exe verilator/microwatt-verilator.cpp verilator/uart-verilator.c -o $@ -Iuart16550 -Wno-fatal -Wno-CASEOVERLAP -Wno-UNOPTFLAT - make -C obj_dir -f Vmicrowatt.mk + $(VERILATOR) $(VERILATOR_FLAGS) -CFLAGS "$(VERILATOR_CFLAGS) -DCLK_FREQUENCY=$(CLK_FREQUENCY)" -Iuart16550 --assert --cc --exe --build $^ -o $@ -top-module toplevel @cp -f obj_dir/microwatt-verilator microwatt-verilator microwatt_out.config: microwatt.json $(LPF) @@ -240,9 +241,15 @@ $(tests_console): core_tb test_micropython: core_tb @./scripts/test_micropython.py +test_micropython_verilator: microwatt-verilator + @./scripts/test_micropython_verilator.py + test_micropython_long: core_tb @./scripts/test_micropython_long.py +test_micropython_verilator_long: microwatt-verilator + @./scripts/test_micropython_verilator_long.py + tests_soc_tb = $(patsubst %_tb,%_tb_test,$(soc_tbs)) %_test: % diff --git a/scripts/test_micropython_verilator.py b/scripts/test_micropython_verilator.py new file mode 100755 index 0000000..fe94d52 --- /dev/null +++ b/scripts/test_micropython_verilator.py @@ -0,0 +1,31 @@ +#!/usr/bin/python3 + +import os +import subprocess +from pexpect import fdpexpect +import sys +import signal + +cmd = [ './microwatt-verilator' ] + +devNull = open(os.devnull, 'w') +p = subprocess.Popen(cmd, stdout=subprocess.PIPE, + stdin=subprocess.PIPE, stderr=devNull) + +exp = fdpexpect.fdspawn(p.stdout) +exp.logfile = sys.stdout.buffer + +exp.expect('Type "help\(\)" for more information.') +exp.expect('>>>') + +p.stdin.write(b'print("foo")\r\n') +p.stdin.flush() + +# Catch the command echoed back to the console +exp.expect('foo', timeout=600) + +# Now catch the output +exp.expect('foo', timeout=600) +exp.expect('>>>') + +os.kill(p.pid, signal.SIGKILL) diff --git a/scripts/test_micropython_verilator_long.py b/scripts/test_micropython_verilator_long.py new file mode 100755 index 0000000..36175f9 --- /dev/null +++ b/scripts/test_micropython_verilator_long.py @@ -0,0 +1,39 @@ +#!/usr/bin/python3 + +import os +import subprocess +from pexpect import fdpexpect +import sys +import signal + +cmd = [ './microwatt-verilator' ] + +devNull = open(os.devnull, 'w') +p = subprocess.Popen(cmd, stdout=subprocess.PIPE, + stdin=subprocess.PIPE, stderr=devNull) + +exp = fdpexpect.fdspawn(p.stdout) +exp.logfile = sys.stdout.buffer + +exp.expect('Type "help\(\)" for more information.') +exp.expect('>>>') + +p.stdin.write(b'n2=0\r\n') +p.stdin.write(b'n1=1\r\n') +p.stdin.write(b'for i in range(5):\r\n') +p.stdin.write(b' n0 = n1 + n2\r\n') +p.stdin.write(b' print(n0)\r\n') +p.stdin.write(b' n2 = n1\r\n') +p.stdin.write(b' n1 = n0\r\n') +p.stdin.write(b'\r\n') +p.stdin.flush() + +exp.expect('n1 = n0', timeout=600) +exp.expect('1', timeout=600) +exp.expect('2', timeout=600) +exp.expect('3', timeout=600) +exp.expect('5', timeout=600) +exp.expect('8', timeout=600) +exp.expect('>>>', timeout=600) + +os.kill(p.pid, signal.SIGKILL) diff --git a/verilator/microwatt-verilator.cpp b/verilator/microwatt-verilator.cpp index 1e82820..3c37f0a 100644 --- a/verilator/microwatt-verilator.cpp +++ b/verilator/microwatt-verilator.cpp @@ -1,5 +1,5 @@ #include -#include "Vmicrowatt.h" +#include "Vtoplevel.h" #include "verilated.h" #include "verilated_vcd_c.h" @@ -24,7 +24,7 @@ double sc_time_stamp(void) VerilatedVcdC *tfp; #endif -void tick(Vmicrowatt *top) +void tick(Vtoplevel *top) { top->ext_clk = 1; top->eval(); @@ -51,7 +51,7 @@ int main(int argc, char **argv) Verilated::commandArgs(argc, argv); // init top verilog instance - Vmicrowatt* top = new Vmicrowatt; + Vtoplevel* top = new Vtoplevel; #if VM_TRACE // init trace dump