diff --git a/.gitignore b/.gitignore index 0d8423d82..3a6dad8b0 100644 --- a/.gitignore +++ b/.gitignore @@ -243,3 +243,4 @@ tests/functcov/* tests/functcov/*/* sim/vcs/simprofile* sim/verilator/verilator.log +/fpga/rvvidaemon/rvvidaemon diff --git a/.gitmodules b/.gitmodules index ca097a125..69054d830 100644 --- a/.gitmodules +++ b/.gitmodules @@ -30,3 +30,7 @@ [submodule "addins/ahbsdc"] path = addins/ahbsdc url = http://github.com/JacobPease/ahbsdc.git +[submodule "addins/verilog-ethernet"] + sparseCheckout = true + path = addins/verilog-ethernet + url = https://github.com/ross144/verilog-ethernet.git diff --git a/addins/README.md b/addins/README.md new file mode 100644 index 000000000..ba04e05eb --- /dev/null +++ b/addins/README.md @@ -0,0 +1,3 @@ +verilog-ethernet contains many ethernet devices. Wally's synthesizable RVVI interface only requires a small subset of these files. +To do a sparse checkout of this repo copy sparse-checkout to cvw/.git/modules/addins/verilog-ethernet/info +This will make the working directory only contain the necessary files. diff --git a/addins/sparse-checkout b/addins/sparse-checkout new file mode 100644 index 000000000..74cc3f25a --- /dev/null +++ b/addins/sparse-checkout @@ -0,0 +1,17 @@ +rtl/eth_mac_mii_fifo.sv +rtl/eth_mac_mii.sv +rtl/mii_phy_if.sv +rtl/ssio_ddr_in.sv +rtl/ssio_sdr_in.sv +rtl/eth_mac_1g.sv +rtl/axis_gmii_rx.sv +rtl/lfsr.sv +rtl/eth_axis_tx.sv +rtl/mac_ctrl_tx.sv +rtl/axis_gmii_tx.sv +rtl/mac_ctrl_rx.sv +rtl/mac_pause_ctrl_tx.sv +rtl/mac_pause_ctrl_rx.sv +lib/axis/rtl/axis_async_fifo_adapter.sv +lib/axis/rtl/axis_adapter.sv +lib/axis/rtl/axis_async_fifo.sv diff --git a/addins/verilog-ethernet b/addins/verilog-ethernet new file mode 160000 index 000000000..c180b22ed --- /dev/null +++ b/addins/verilog-ethernet @@ -0,0 +1 @@ +Subproject commit c180b22ed5f4112d0ef35b2c5ac1acc45f9ebb5d diff --git a/bin/wsim b/bin/wsim index b70d0e26f..b2288deb4 100755 --- a/bin/wsim +++ b/bin/wsim @@ -33,6 +33,7 @@ parser.add_argument("--vcd", "-v", help="Generate testbench.vcd", action="store_ parser.add_argument("--lockstep", "-l", help="Run ImperasDV lock, step, and compare.", action="store_true") parser.add_argument("--locksteplog", "-b", help="Retired instruction number to be begin logging.", default=0) parser.add_argument("--covlog", "-d", help="Log coverage after n instructions.", default=0) +parser.add_argument("--rvvi", "-r", help="Simulate rvvi hardware interface and ethernet.", action="store_true") args = parser.parse_args() print("Config=" + args.config + " tests=" + args.testsuite + " sim=" + args.sim + " gui=" + str(args.gui) + " args='" + args.args + "'") ElfFile="" @@ -64,6 +65,9 @@ if (args.gui or args.ccov or args.fcov or args.lockstep): if (args.vcd): args.args += " -DMAKEVCD=1" +if (args.rvvi): + args.args += " -GRVVI_SYNTH_SUPPORTED=1" + # if lockstep is enabled, then we need to pass the Imperas lockstep arguments if(int(args.locksteplog) >= 1): EnableLog = 1 else: EnableLog = 0 diff --git a/config/derivlist.txt b/config/derivlist.txt index 9d864f1f5..ab9ee703f 100644 --- a/config/derivlist.txt +++ b/config/derivlist.txt @@ -1658,7 +1658,7 @@ IDIV_ON_FPU 1 # imperas used for a smart memory # VCS doesn't like removing the bootrom, but make it tiny in a random unused location -derive imperas rv64gc +derive ImperasTG rv64gc ICACHE_SUPPORTED 0 DCACHE_SUPPORTED 0 VIRTMEM_SUPPORTED 0 @@ -1669,6 +1669,13 @@ ZICBOM_SUPPORTED 0 ZICBOZ_SUPPORTED 0 SVPBMT_SUPPORTED 0 SVNAPOT_SUPPORTED 0 -BOOTROM_BASE 64'h700012340010 +BOOTROM_BASE 64'h700012340080 BOOTROM_RANGE 64'h10 +CLINT_SUPPORTED 0 +GPIO_SUPPORTED 0 +UART_SUPPORTED 0 +PLIC_SUPPORTED 0 +SPI_SUPPORTED 0 + + diff --git a/fpga/constraints/constraints-ArtyA7.xdc b/fpga/constraints/constraints-ArtyA7.xdc index 394c58dda..e4774280f 100644 --- a/fpga/constraints/constraints-ArtyA7.xdc +++ b/fpga/constraints/constraints-ArtyA7.xdc @@ -10,6 +10,32 @@ create_generated_clock -name SPISDCClock -source [get_pins clk_out3_xlnx_mmcm] - set_property PACKAGE_PIN E3 [get_ports {default_100mhz_clk}] set_property IOSTANDARD LVCMOS33 [get_ports {default_100mhz_clk}] +##### RVVI Ethernet #### +# taken from https://github.com/alexforencich/verilog-ethernet/blob/master/example/Arty/fpga/fpga.xdc +set_property -dict {LOC F15 IOSTANDARD LVCMOS33} [get_ports phy_rx_clk] +set_property -dict {LOC D18 IOSTANDARD LVCMOS33} [get_ports {phy_rxd[0]}] +set_property -dict {LOC E17 IOSTANDARD LVCMOS33} [get_ports {phy_rxd[1]}] +set_property -dict {LOC E18 IOSTANDARD LVCMOS33} [get_ports {phy_rxd[2]}] +set_property -dict {LOC G17 IOSTANDARD LVCMOS33} [get_ports {phy_rxd[3]}] +set_property -dict {LOC G16 IOSTANDARD LVCMOS33} [get_ports phy_rx_dv] +set_property -dict {LOC C17 IOSTANDARD LVCMOS33} [get_ports phy_rx_er] +set_property -dict {LOC H16 IOSTANDARD LVCMOS33} [get_ports phy_tx_clk] +set_property -dict {LOC H14 IOSTANDARD LVCMOS33 SLEW FAST DRIVE 12} [get_ports {phy_txd[0]}] +set_property -dict {LOC J14 IOSTANDARD LVCMOS33 SLEW FAST DRIVE 12} [get_ports {phy_txd[1]}] +set_property -dict {LOC J13 IOSTANDARD LVCMOS33 SLEW FAST DRIVE 12} [get_ports {phy_txd[2]}] +set_property -dict {LOC H17 IOSTANDARD LVCMOS33 SLEW FAST DRIVE 12} [get_ports {phy_txd[3]}] +set_property -dict {LOC H15 IOSTANDARD LVCMOS33 SLEW FAST DRIVE 12} [get_ports phy_tx_en] +set_property -dict {LOC D17 IOSTANDARD LVCMOS33} [get_ports phy_col] +set_property -dict {LOC G14 IOSTANDARD LVCMOS33} [get_ports phy_crs] +set_property -dict {LOC G18 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 12} [get_ports phy_ref_clk] +set_property -dict {LOC C16 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 12} [get_ports phy_reset_n] + +create_clock -period 40.000 -name phy_rx_clk [get_ports phy_rx_clk] +create_clock -period 40.000 -name phy_tx_clk [get_ports phy_tx_clk] + +set_false_path -to [get_ports {phy_ref_clk phy_reset_n}] +set_output_delay 0 [get_ports {phy_ref_clk phy_reset_n}] + ##### GPI #### set_property PACKAGE_PIN A8 [get_ports {GPI[0]}] set_property PACKAGE_PIN C9 [get_ports {GPI[1]}] diff --git a/fpga/constraints/marked_debug.txt b/fpga/constraints/marked_debug.txt index 5217067eb..afed3dd23 100644 --- a/fpga/constraints/marked_debug.txt +++ b/fpga/constraints/marked_debug.txt @@ -7,3 +7,4 @@ lsu/lsu.sv: logic PAdrM lsu/lsu.sv: logic ReadDataM lsu/lsu.sv: logic WriteDataM lsu/lsu.sv: logic MemRWM +privileged/csrc.sv: logic HPMCOUNTER_REGW diff --git a/fpga/constraints/small-debug-rvvi.xdc b/fpga/constraints/small-debug-rvvi.xdc new file mode 100644 index 000000000..629cde561 --- /dev/null +++ b/fpga/constraints/small-debug-rvvi.xdc @@ -0,0 +1,72 @@ +create_debug_core u_ila_0 ila +set_property C_DATA_DEPTH 4096 [get_debug_cores u_ila_0] +set_property C_TRIGIN_EN true [get_debug_cores u_ila_0] +set_property C_TRIGOUT_EN false [get_debug_cores u_ila_0] +set_property C_INPUT_PIPE_STAGES 0 [get_debug_cores u_ila_0] +set_property ALL_PROBE_SAME_MU true [get_debug_cores u_ila_0] +set_property C_EN_STRG_QUAL true [get_debug_cores u_ila_0 ] +set_property C_ADV_TRIGGER true [get_debug_cores u_ila_0 ] +set_property ALL_PROBE_SAME_MU true [get_debug_cores u_ila_0 ] +set_property ALL_PROBE_SAME_MU_CNT 4 [get_debug_cores u_ila_0 ] +create_debug_port u_ila_0 trig_in +create_debug_port u_ila_0 trig_in_ack +#set_property port_width 1 [get_debug_ports u_ila_0/trig_in] +#set_property port_width 1 [get_debug_ports u_ila_0/trig_in_ack] +#set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/trig_in] +connect_debug_port u_ila_0/trig_in [get_nets IlaTrigger] +#connect_debug_port u_ila_0/trig_in_ack [get_nets IlaTriggerAck] +connect_debug_port u_ila_0/clk [get_nets CPUCLK] + +set_property port_width 64 [get_debug_ports u_ila_0/probe0] +set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe0] +connect_debug_port u_ila_0/probe0 [get_nets [list {wallypipelinedsoc/core/PCM[0]} {wallypipelinedsoc/core/PCM[1]} {wallypipelinedsoc/core/PCM[2]} {wallypipelinedsoc/core/PCM[3]} {wallypipelinedsoc/core/PCM[4]} {wallypipelinedsoc/core/PCM[5]} {wallypipelinedsoc/core/PCM[6]} {wallypipelinedsoc/core/PCM[7]} {wallypipelinedsoc/core/PCM[8]} {wallypipelinedsoc/core/PCM[9]} {wallypipelinedsoc/core/PCM[10]} {wallypipelinedsoc/core/PCM[11]} {wallypipelinedsoc/core/PCM[12]} {wallypipelinedsoc/core/PCM[13]} {wallypipelinedsoc/core/PCM[14]} {wallypipelinedsoc/core/PCM[15]} {wallypipelinedsoc/core/PCM[16]} {wallypipelinedsoc/core/PCM[17]} {wallypipelinedsoc/core/PCM[18]} {wallypipelinedsoc/core/PCM[19]} {wallypipelinedsoc/core/PCM[20]} {wallypipelinedsoc/core/PCM[21]} {wallypipelinedsoc/core/PCM[22]} {wallypipelinedsoc/core/PCM[23]} {wallypipelinedsoc/core/PCM[24]} {wallypipelinedsoc/core/PCM[25]} {wallypipelinedsoc/core/PCM[26]} {wallypipelinedsoc/core/PCM[27]} {wallypipelinedsoc/core/PCM[28]} {wallypipelinedsoc/core/PCM[29]} {wallypipelinedsoc/core/PCM[30]} {wallypipelinedsoc/core/PCM[31]} {wallypipelinedsoc/core/PCM[32]} {wallypipelinedsoc/core/PCM[33]} {wallypipelinedsoc/core/PCM[34]} {wallypipelinedsoc/core/PCM[35]} {wallypipelinedsoc/core/PCM[36]} {wallypipelinedsoc/core/PCM[37]} {wallypipelinedsoc/core/PCM[38]} {wallypipelinedsoc/core/PCM[39]} {wallypipelinedsoc/core/PCM[40]} {wallypipelinedsoc/core/PCM[41]} {wallypipelinedsoc/core/PCM[42]} {wallypipelinedsoc/core/PCM[43]} {wallypipelinedsoc/core/PCM[44]} {wallypipelinedsoc/core/PCM[45]} {wallypipelinedsoc/core/PCM[46]} {wallypipelinedsoc/core/PCM[47]} {wallypipelinedsoc/core/PCM[48]} {wallypipelinedsoc/core/PCM[49]} {wallypipelinedsoc/core/PCM[50]} {wallypipelinedsoc/core/PCM[51]} {wallypipelinedsoc/core/PCM[52]} {wallypipelinedsoc/core/PCM[53]} {wallypipelinedsoc/core/PCM[54]} {wallypipelinedsoc/core/PCM[55]} {wallypipelinedsoc/core/PCM[56]} {wallypipelinedsoc/core/PCM[57]} {wallypipelinedsoc/core/PCM[58]} {wallypipelinedsoc/core/PCM[59]} {wallypipelinedsoc/core/PCM[60]} {wallypipelinedsoc/core/PCM[61]} {wallypipelinedsoc/core/PCM[62]} {wallypipelinedsoc/core/PCM[63]} ]] + +create_debug_port u_ila_0 probe +set_property port_width 1 [get_debug_ports u_ila_0/probe1] +set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe1] +connect_debug_port u_ila_0/probe1 [get_nets [list wallypipelinedsoc/core/TrapM ]] + +create_debug_port u_ila_0 probe +set_property port_width 1 [get_debug_ports u_ila_0/probe2] +set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe2] +connect_debug_port u_ila_0/probe2 [get_nets [list wallypipelinedsoc/core/InstrValidM ]] + +create_debug_port u_ila_0 probe +set_property port_width 32 [get_debug_ports u_ila_0/probe3] +set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe3] +connect_debug_port u_ila_0/probe3 [get_nets [list {wallypipelinedsoc/core/InstrM[0]} {wallypipelinedsoc/core/InstrM[1]} {wallypipelinedsoc/core/InstrM[2]} {wallypipelinedsoc/core/InstrM[3]} {wallypipelinedsoc/core/InstrM[4]} {wallypipelinedsoc/core/InstrM[5]} {wallypipelinedsoc/core/InstrM[6]} {wallypipelinedsoc/core/InstrM[7]} {wallypipelinedsoc/core/InstrM[8]} {wallypipelinedsoc/core/InstrM[9]} {wallypipelinedsoc/core/InstrM[10]} {wallypipelinedsoc/core/InstrM[11]} {wallypipelinedsoc/core/InstrM[12]} {wallypipelinedsoc/core/InstrM[13]} {wallypipelinedsoc/core/InstrM[14]} {wallypipelinedsoc/core/InstrM[15]} {wallypipelinedsoc/core/InstrM[16]} {wallypipelinedsoc/core/InstrM[17]} {wallypipelinedsoc/core/InstrM[18]} {wallypipelinedsoc/core/InstrM[19]} {wallypipelinedsoc/core/InstrM[20]} {wallypipelinedsoc/core/InstrM[21]} {wallypipelinedsoc/core/InstrM[22]} {wallypipelinedsoc/core/InstrM[23]} {wallypipelinedsoc/core/InstrM[24]} {wallypipelinedsoc/core/InstrM[25]} {wallypipelinedsoc/core/InstrM[26]} {wallypipelinedsoc/core/InstrM[27]} {wallypipelinedsoc/core/InstrM[28]} {wallypipelinedsoc/core/InstrM[29]} {wallypipelinedsoc/core/InstrM[30]} {wallypipelinedsoc/core/InstrM[31]} ]] + +create_debug_port u_ila_0 probe +set_property port_width 2 [get_debug_ports u_ila_0/probe4] +set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe4] +connect_debug_port u_ila_0/probe4 [get_nets [list {wallypipelinedsoc/core/lsu/MemRWM[0]} {wallypipelinedsoc/core/lsu/MemRWM[1]} ]] + +create_debug_port u_ila_0 probe +set_property port_width 64 [get_debug_ports u_ila_0/probe5] +set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe5] +connect_debug_port u_ila_0/probe5 [get_nets [list {wallypipelinedsoc/core/lsu/IEUAdrM[0]} {wallypipelinedsoc/core/lsu/IEUAdrM[1]} {wallypipelinedsoc/core/lsu/IEUAdrM[2]} {wallypipelinedsoc/core/lsu/IEUAdrM[3]} {wallypipelinedsoc/core/lsu/IEUAdrM[4]} {wallypipelinedsoc/core/lsu/IEUAdrM[5]} {wallypipelinedsoc/core/lsu/IEUAdrM[6]} {wallypipelinedsoc/core/lsu/IEUAdrM[7]} {wallypipelinedsoc/core/lsu/IEUAdrM[8]} {wallypipelinedsoc/core/lsu/IEUAdrM[9]} {wallypipelinedsoc/core/lsu/IEUAdrM[10]} {wallypipelinedsoc/core/lsu/IEUAdrM[11]} {wallypipelinedsoc/core/lsu/IEUAdrM[12]} {wallypipelinedsoc/core/lsu/IEUAdrM[13]} {wallypipelinedsoc/core/lsu/IEUAdrM[14]} {wallypipelinedsoc/core/lsu/IEUAdrM[15]} {wallypipelinedsoc/core/lsu/IEUAdrM[16]} {wallypipelinedsoc/core/lsu/IEUAdrM[17]} {wallypipelinedsoc/core/lsu/IEUAdrM[18]} {wallypipelinedsoc/core/lsu/IEUAdrM[19]} {wallypipelinedsoc/core/lsu/IEUAdrM[20]} {wallypipelinedsoc/core/lsu/IEUAdrM[21]} {wallypipelinedsoc/core/lsu/IEUAdrM[22]} {wallypipelinedsoc/core/lsu/IEUAdrM[23]} {wallypipelinedsoc/core/lsu/IEUAdrM[24]} {wallypipelinedsoc/core/lsu/IEUAdrM[25]} {wallypipelinedsoc/core/lsu/IEUAdrM[26]} {wallypipelinedsoc/core/lsu/IEUAdrM[27]} {wallypipelinedsoc/core/lsu/IEUAdrM[28]} {wallypipelinedsoc/core/lsu/IEUAdrM[29]} {wallypipelinedsoc/core/lsu/IEUAdrM[30]} {wallypipelinedsoc/core/lsu/IEUAdrM[31]} {wallypipelinedsoc/core/lsu/IEUAdrM[32]} {wallypipelinedsoc/core/lsu/IEUAdrM[33]} {wallypipelinedsoc/core/lsu/IEUAdrM[34]} {wallypipelinedsoc/core/lsu/IEUAdrM[35]} {wallypipelinedsoc/core/lsu/IEUAdrM[36]} {wallypipelinedsoc/core/lsu/IEUAdrM[37]} {wallypipelinedsoc/core/lsu/IEUAdrM[38]} {wallypipelinedsoc/core/lsu/IEUAdrM[39]} {wallypipelinedsoc/core/lsu/IEUAdrM[40]} {wallypipelinedsoc/core/lsu/IEUAdrM[41]} {wallypipelinedsoc/core/lsu/IEUAdrM[42]} {wallypipelinedsoc/core/lsu/IEUAdrM[43]} {wallypipelinedsoc/core/lsu/IEUAdrM[44]} {wallypipelinedsoc/core/lsu/IEUAdrM[45]} {wallypipelinedsoc/core/lsu/IEUAdrM[46]} {wallypipelinedsoc/core/lsu/IEUAdrM[47]} {wallypipelinedsoc/core/lsu/IEUAdrM[48]} {wallypipelinedsoc/core/lsu/IEUAdrM[49]} {wallypipelinedsoc/core/lsu/IEUAdrM[50]} {wallypipelinedsoc/core/lsu/IEUAdrM[51]} {wallypipelinedsoc/core/lsu/IEUAdrM[52]} {wallypipelinedsoc/core/lsu/IEUAdrM[53]} {wallypipelinedsoc/core/lsu/IEUAdrM[54]} {wallypipelinedsoc/core/lsu/IEUAdrM[55]} {wallypipelinedsoc/core/lsu/IEUAdrM[56]} {wallypipelinedsoc/core/lsu/IEUAdrM[57]} {wallypipelinedsoc/core/lsu/IEUAdrM[58]} {wallypipelinedsoc/core/lsu/IEUAdrM[59]} {wallypipelinedsoc/core/lsu/IEUAdrM[60]} {wallypipelinedsoc/core/lsu/IEUAdrM[61]} {wallypipelinedsoc/core/lsu/IEUAdrM[62]} {wallypipelinedsoc/core/lsu/IEUAdrM[63]} ]] + +create_debug_port u_ila_0 probe +set_property port_width 64 [get_debug_ports u_ila_0/probe6] +set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe6] +connect_debug_port u_ila_0/probe6 [get_nets [list {wallypipelinedsoc/core/lsu/ReadDataM[0]} {wallypipelinedsoc/core/lsu/ReadDataM[1]} {wallypipelinedsoc/core/lsu/ReadDataM[2]} {wallypipelinedsoc/core/lsu/ReadDataM[3]} {wallypipelinedsoc/core/lsu/ReadDataM[4]} {wallypipelinedsoc/core/lsu/ReadDataM[5]} {wallypipelinedsoc/core/lsu/ReadDataM[6]} {wallypipelinedsoc/core/lsu/ReadDataM[7]} {wallypipelinedsoc/core/lsu/ReadDataM[8]} {wallypipelinedsoc/core/lsu/ReadDataM[9]} {wallypipelinedsoc/core/lsu/ReadDataM[10]} {wallypipelinedsoc/core/lsu/ReadDataM[11]} {wallypipelinedsoc/core/lsu/ReadDataM[12]} {wallypipelinedsoc/core/lsu/ReadDataM[13]} {wallypipelinedsoc/core/lsu/ReadDataM[14]} {wallypipelinedsoc/core/lsu/ReadDataM[15]} {wallypipelinedsoc/core/lsu/ReadDataM[16]} {wallypipelinedsoc/core/lsu/ReadDataM[17]} {wallypipelinedsoc/core/lsu/ReadDataM[18]} {wallypipelinedsoc/core/lsu/ReadDataM[19]} {wallypipelinedsoc/core/lsu/ReadDataM[20]} {wallypipelinedsoc/core/lsu/ReadDataM[21]} {wallypipelinedsoc/core/lsu/ReadDataM[22]} {wallypipelinedsoc/core/lsu/ReadDataM[23]} {wallypipelinedsoc/core/lsu/ReadDataM[24]} {wallypipelinedsoc/core/lsu/ReadDataM[25]} {wallypipelinedsoc/core/lsu/ReadDataM[26]} {wallypipelinedsoc/core/lsu/ReadDataM[27]} {wallypipelinedsoc/core/lsu/ReadDataM[28]} {wallypipelinedsoc/core/lsu/ReadDataM[29]} {wallypipelinedsoc/core/lsu/ReadDataM[30]} {wallypipelinedsoc/core/lsu/ReadDataM[31]} {wallypipelinedsoc/core/lsu/ReadDataM[32]} {wallypipelinedsoc/core/lsu/ReadDataM[33]} {wallypipelinedsoc/core/lsu/ReadDataM[34]} {wallypipelinedsoc/core/lsu/ReadDataM[35]} {wallypipelinedsoc/core/lsu/ReadDataM[36]} {wallypipelinedsoc/core/lsu/ReadDataM[37]} {wallypipelinedsoc/core/lsu/ReadDataM[38]} {wallypipelinedsoc/core/lsu/ReadDataM[39]} {wallypipelinedsoc/core/lsu/ReadDataM[40]} {wallypipelinedsoc/core/lsu/ReadDataM[41]} {wallypipelinedsoc/core/lsu/ReadDataM[42]} {wallypipelinedsoc/core/lsu/ReadDataM[43]} {wallypipelinedsoc/core/lsu/ReadDataM[44]} {wallypipelinedsoc/core/lsu/ReadDataM[45]} {wallypipelinedsoc/core/lsu/ReadDataM[46]} {wallypipelinedsoc/core/lsu/ReadDataM[47]} {wallypipelinedsoc/core/lsu/ReadDataM[48]} {wallypipelinedsoc/core/lsu/ReadDataM[49]} {wallypipelinedsoc/core/lsu/ReadDataM[50]} {wallypipelinedsoc/core/lsu/ReadDataM[51]} {wallypipelinedsoc/core/lsu/ReadDataM[52]} {wallypipelinedsoc/core/lsu/ReadDataM[53]} {wallypipelinedsoc/core/lsu/ReadDataM[54]} {wallypipelinedsoc/core/lsu/ReadDataM[55]} {wallypipelinedsoc/core/lsu/ReadDataM[56]} {wallypipelinedsoc/core/lsu/ReadDataM[57]} {wallypipelinedsoc/core/lsu/ReadDataM[58]} {wallypipelinedsoc/core/lsu/ReadDataM[59]} {wallypipelinedsoc/core/lsu/ReadDataM[60]} {wallypipelinedsoc/core/lsu/ReadDataM[61]} {wallypipelinedsoc/core/lsu/ReadDataM[62]} {wallypipelinedsoc/core/lsu/ReadDataM[63]} ]] + +create_debug_port u_ila_0 probe +set_property port_width 64 [get_debug_ports u_ila_0/probe7] +set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe7] +connect_debug_port u_ila_0/probe7 [get_nets [list {wallypipelinedsoc/core/lsu/WriteDataM[0]} {wallypipelinedsoc/core/lsu/WriteDataM[1]} {wallypipelinedsoc/core/lsu/WriteDataM[2]} {wallypipelinedsoc/core/lsu/WriteDataM[3]} {wallypipelinedsoc/core/lsu/WriteDataM[4]} {wallypipelinedsoc/core/lsu/WriteDataM[5]} {wallypipelinedsoc/core/lsu/WriteDataM[6]} {wallypipelinedsoc/core/lsu/WriteDataM[7]} {wallypipelinedsoc/core/lsu/WriteDataM[8]} {wallypipelinedsoc/core/lsu/WriteDataM[9]} {wallypipelinedsoc/core/lsu/WriteDataM[10]} {wallypipelinedsoc/core/lsu/WriteDataM[11]} {wallypipelinedsoc/core/lsu/WriteDataM[12]} {wallypipelinedsoc/core/lsu/WriteDataM[13]} {wallypipelinedsoc/core/lsu/WriteDataM[14]} {wallypipelinedsoc/core/lsu/WriteDataM[15]} {wallypipelinedsoc/core/lsu/WriteDataM[16]} {wallypipelinedsoc/core/lsu/WriteDataM[17]} {wallypipelinedsoc/core/lsu/WriteDataM[18]} {wallypipelinedsoc/core/lsu/WriteDataM[19]} {wallypipelinedsoc/core/lsu/WriteDataM[20]} {wallypipelinedsoc/core/lsu/WriteDataM[21]} {wallypipelinedsoc/core/lsu/WriteDataM[22]} {wallypipelinedsoc/core/lsu/WriteDataM[23]} {wallypipelinedsoc/core/lsu/WriteDataM[24]} {wallypipelinedsoc/core/lsu/WriteDataM[25]} {wallypipelinedsoc/core/lsu/WriteDataM[26]} {wallypipelinedsoc/core/lsu/WriteDataM[27]} {wallypipelinedsoc/core/lsu/WriteDataM[28]} {wallypipelinedsoc/core/lsu/WriteDataM[29]} {wallypipelinedsoc/core/lsu/WriteDataM[30]} {wallypipelinedsoc/core/lsu/WriteDataM[31]} {wallypipelinedsoc/core/lsu/WriteDataM[32]} {wallypipelinedsoc/core/lsu/WriteDataM[33]} {wallypipelinedsoc/core/lsu/WriteDataM[34]} {wallypipelinedsoc/core/lsu/WriteDataM[35]} {wallypipelinedsoc/core/lsu/WriteDataM[36]} {wallypipelinedsoc/core/lsu/WriteDataM[37]} {wallypipelinedsoc/core/lsu/WriteDataM[38]} {wallypipelinedsoc/core/lsu/WriteDataM[39]} {wallypipelinedsoc/core/lsu/WriteDataM[40]} {wallypipelinedsoc/core/lsu/WriteDataM[41]} {wallypipelinedsoc/core/lsu/WriteDataM[42]} {wallypipelinedsoc/core/lsu/WriteDataM[43]} {wallypipelinedsoc/core/lsu/WriteDataM[44]} {wallypipelinedsoc/core/lsu/WriteDataM[45]} {wallypipelinedsoc/core/lsu/WriteDataM[46]} {wallypipelinedsoc/core/lsu/WriteDataM[47]} {wallypipelinedsoc/core/lsu/WriteDataM[48]} {wallypipelinedsoc/core/lsu/WriteDataM[49]} {wallypipelinedsoc/core/lsu/WriteDataM[50]} {wallypipelinedsoc/core/lsu/WriteDataM[51]} {wallypipelinedsoc/core/lsu/WriteDataM[52]} {wallypipelinedsoc/core/lsu/WriteDataM[53]} {wallypipelinedsoc/core/lsu/WriteDataM[54]} {wallypipelinedsoc/core/lsu/WriteDataM[55]} {wallypipelinedsoc/core/lsu/WriteDataM[56]} {wallypipelinedsoc/core/lsu/WriteDataM[57]} {wallypipelinedsoc/core/lsu/WriteDataM[58]} {wallypipelinedsoc/core/lsu/WriteDataM[59]} {wallypipelinedsoc/core/lsu/WriteDataM[60]} {wallypipelinedsoc/core/lsu/WriteDataM[61]} {wallypipelinedsoc/core/lsu/WriteDataM[62]} {wallypipelinedsoc/core/lsu/WriteDataM[63]} ]] + +create_debug_port u_ila_0 probe +set_property port_width 32 [get_debug_ports u_ila_0/probe8] +set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe8] +connect_debug_port u_ila_0/probe8 [get_nets [list {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][0]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][1]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][2]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][3]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][4]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][5]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][6]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][7]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][8]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][9]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][10]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][11]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][12]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][13]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][14]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][15]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][16]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][17]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][18]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][19]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][20]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][21]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][22]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][23]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][24]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][25]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][26]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][27]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][28]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][29]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][30]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][31]} ]] + +create_debug_port u_ila_0 probe +set_property port_width 1 [get_debug_ports u_ila_0/probe9] +set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe9] +connect_debug_port u_ila_0/probe9 [get_nets [list {RVVIStall}]] + +# the debug hub has issues with the clocks from the mmcm so lets give up an connect to the 100Mhz input clock. +#connect_debug_port dbg_hub/clk [get_nets default_100mhz_clk] +connect_debug_port dbg_hub/clk [get_nets CPUCLK] + diff --git a/fpga/generator/Makefile b/fpga/generator/Makefile index 7865d33ee..5fbbfec33 100644 --- a/fpga/generator/Makefile +++ b/fpga/generator/Makefile @@ -51,6 +51,8 @@ PreProcessFiles: $(MAKE) -C ../../sim deriv rm -rf ../src/CopiedFiles_do_not_add_to_repo/ cp -r ../../src/ ../src/CopiedFiles_do_not_add_to_repo/ + cp -r ../../addins/verilog-ethernet/*/*.sv ../src/CopiedFiles_do_not_add_to_repo/rvvi + cp -r ../../addins/verilog-ethernet/*/*/*/*.sv ../src/CopiedFiles_do_not_add_to_repo/rvvi mkdir ../src/CopiedFiles_do_not_add_to_repo/config/ cp ../../config/deriv/fpga/config.vh ../src/CopiedFiles_do_not_add_to_repo/config/ ./insert_debug_comment.sh diff --git a/fpga/generator/wally.tcl b/fpga/generator/wally.tcl index 9acdad4b6..465d0c73a 100644 --- a/fpga/generator/wally.tcl +++ b/fpga/generator/wally.tcl @@ -90,7 +90,7 @@ write_verilog -force -mode funcsim sim/syn-funcsim.v if {$board=="ArtyA7"} { #source ../constraints/small-debug.xdc - source ../constraints/medium-debug.xdc + source ../constraints/small-debug-rvvi.xdc } else { # source ../constraints/vcu-small-debug.xdc source ../constraints/debug6.xdc diff --git a/fpga/generator/xlnx_mmcm.tcl b/fpga/generator/xlnx_mmcm.tcl index 2f003e7a5..146a9cf41 100644 --- a/fpga/generator/xlnx_mmcm.tcl +++ b/fpga/generator/xlnx_mmcm.tcl @@ -12,10 +12,11 @@ set_property -dict [list CONFIG.PRIM_IN_FREQ {100.000} \ CONFIG.NUM_OUT_CLKS {3} \ CONFIG.CLKOUT2_USED {true} \ CONFIG.CLKOUT3_USED {true} \ - CONFIG.CLKOUT4_USED {false} \ + CONFIG.CLKOUT4_USED {true} \ CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {166.66667} \ CONFIG.CLKOUT2_REQUESTED_OUT_FREQ {200} \ CONFIG.CLKOUT3_REQUESTED_OUT_FREQ {20} \ + CONFIG.CLKOUT4_REQUESTED_OUT_FREQ {25} \ CONFIG.CLKIN1_JITTER_PS {10.0} \ ] [get_ips $ipName] diff --git a/fpga/rvvidaemon/Makefile b/fpga/rvvidaemon/Makefile new file mode 100644 index 000000000..26f705a20 --- /dev/null +++ b/fpga/rvvidaemon/Makefile @@ -0,0 +1,10 @@ +all: rvvidaemon + +rvvidaemon: rvvidaemon.o + gcc $^ /opt/riscv/ImperasDV-OpenHW/lib/Linux64/ImperasLib/imperas.com/verification/riscv/1.0/model.so -o rvvidaemon + +%.o:%.c + gcc -I/opt/riscv/ImperasDV-OpenHW/ImpProprietary/include/host -I/opt/riscv/ImperasDV-OpenHW/ImpPublic/include/host/rvvi/ -c $^ -o $@ + +clean: + rm *.o rvvidaemon diff --git a/fpga/rvvidaemon/rvvidaemon.c b/fpga/rvvidaemon/rvvidaemon.c new file mode 100644 index 000000000..1e9d17f66 --- /dev/null +++ b/fpga/rvvidaemon/rvvidaemon.c @@ -0,0 +1,500 @@ +/////////////////////////////////////////// +// rvvi daemon +// +// Written: Rose Thomposn ross1728@gmail.com +// Created: 31 May 2024 +// Modified: 31 May 2024 +// +// Purpose: Converts raw socket into rvvi interface to connect into ImperasDV +// +// Documentation: +// +// A component of the CORE-V-WALLY configurable RISC-V project. +// https://github.com/openhwgroup/cvw +// +// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University +// +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// Licensed under the Solderpad Hardware License v 2.1 (the “License”); you may not use this file +// except in compliance with the License, or, at your option, the Apache License version 2.0. You +// may obtain a copy of the License at +// +// https://solderpad.org/licenses/SHL-2.1/ +// +// Unless required by applicable law or agreed to in writing, any work distributed under the +// License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +// either express or implied. See the License for the specific language governing permissions +// and limitations under the License. +//////////////////////////////////////////////////////////////////////////////////////////////// + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "rvviApi.h" // *** bug fix me when this file gets included into the correct directory. +#include "idv/idv.h" + + +#define DEST_MAC0 0x43 +#define DEST_MAC1 0x68 +#define DEST_MAC2 0x11 +#define DEST_MAC3 0x11 +#define DEST_MAC4 0x02 +#define DEST_MAC5 0x45 + +#define SRC_MAC0 0x54 +#define SRC_MAC1 0x16 +#define SRC_MAC2 0x00 +#define SRC_MAC3 0x00 +#define SRC_MAC4 0x54 +#define SRC_MAC5 0x8F + +#define BUF_SIZ 1024 + +//#define ETHER_TYPE 0x0801 // The type defined in packetizer.sv +#define ETHER_TYPE 0x5c00 // The type defined in packetizer.sv +//#define ETHER_TYPE 0x0000 // The type defined in packetizer.sv +#define DEFAULT_IF "eno1" + +struct sockaddr_ll socket_address; +uint8_t sendbuf[BUF_SIZ]; +struct ether_header *sendeh = (struct ether_header *) sendbuf; +int tx_len = 0; +int sockfd; + +typedef struct { + uint64_t PC; + uint32_t insn; + uint64_t Mcycle; + uint64_t Minstret; + uint8_t Trap : 1; + uint8_t PrivilegeMode : 2; + uint8_t GPREn : 1; + uint8_t FPREn : 1; + uint16_t CSRCount : 12; + uint8_t GPRReg : 5; + uint64_t GPRValue; + uint8_t FPRReg : 5; + uint64_t FPRValue; + uint8_t CSRWen[3]; + uint16_t CSRReg[3]; + uint64_t CSRValue[3]; + +} RequiredRVVI_t; // total size is 241 bits or 30.125 bytes + +typedef struct { + uint8_t RegAddress : 5; + uint64_t RegValue; +} Reg_t; + +void DecodeRVVI(uint8_t *payload, ssize_t payloadsize, RequiredRVVI_t *InstructionData); +void BitShiftArray(uint8_t *dst, uint8_t *src, uint8_t ShiftAmount, int Length); +void PrintInstructionData(RequiredRVVI_t *InstructionData); +int ProcessRvviAll(RequiredRVVI_t *InstructionData); +void set_gpr(int hart, int reg, uint64_t value); +void set_fpr(int hart, int reg, uint64_t value); +int state_compare(int hart, uint64_t Minstret); + +int main(int argc, char **argv){ + + if(argc != 2){ + printf("Wrong number of arguments.\n"); + printf("rvvidaemon \n"); + return -1; + } + + uint8_t buf[BUF_SIZ]; + int sockopt; + struct ifreq ifopts; /* set promiscuous mode */ + struct ether_header *eh = (struct ether_header *) buf; + ssize_t headerbytes, numbytes, payloadbytes; + + /* Open RAW socket to receive frames */ + if ((sockfd = socket(AF_PACKET, SOCK_RAW, htons(ETHER_TYPE))) == -1) { + perror("socket"); + } + printf("Here 0\n"); + + /* Set interface to promiscuous mode - do we need to do this every time? */ + strncpy(ifopts.ifr_name, argv[1], IFNAMSIZ-1); + ioctl(sockfd, SIOCGIFFLAGS, &ifopts); + printf("Here 1\n"); + ifopts.ifr_flags |= IFF_PROMISC; + ioctl(sockfd, SIOCSIFFLAGS, &ifopts); + printf("Here 2\n"); + if (ioctl(sockfd, SIOCGIFINDEX, &ifopts) < 0) + perror("SIOCGIFINDEX"); + + /* Allow the socket to be reused - incase connection is closed prematurely */ + if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof sockopt) == -1) { + perror("setsockopt"); + close(sockfd); + exit(EXIT_FAILURE); + } + printf("Here 3\n"); + + /* Bind to device */ + if (setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE, argv[1], IFNAMSIZ-1) == -1) { + perror("SO_BINDTODEVICE"); + close(sockfd); + exit(EXIT_FAILURE); + } + printf("Here 4\n"); + + if(!rvviVersionCheck(RVVI_API_VERSION)){ + printf("Bad RVVI_API_VERSION\n"); + } + + /* Construct the Ethernet header */ + memset(sendbuf, 0, BUF_SIZ); + sendbuf[0] = DEST_MAC0; + sendbuf[1] = DEST_MAC1; + sendbuf[2] = DEST_MAC2; + sendbuf[3] = DEST_MAC3; + sendbuf[4] = DEST_MAC4; + sendbuf[5] = DEST_MAC5; + sendbuf[6] = SRC_MAC0; + sendbuf[7] = SRC_MAC1; + sendbuf[8] = SRC_MAC2; + sendbuf[9] = SRC_MAC3; + sendbuf[10] = SRC_MAC4; + sendbuf[11] = SRC_MAC5; + + sendeh->ether_type = htons(ETHER_TYPE); + tx_len += sizeof(struct ether_header); + /* Packet data */ + sendbuf[tx_len++] = 't'; + sendbuf[tx_len++] = 'r'; + sendbuf[tx_len++] = 'i'; + sendbuf[tx_len++] = 'g'; + sendbuf[tx_len++] = 'i'; + sendbuf[tx_len++] = 'n'; + + rvviRefConfigSetString(IDV_CONFIG_MODEL_VENDOR, "riscv.ovpworld.org"); + rvviRefConfigSetString(IDV_CONFIG_MODEL_NAME,"riscv"); + rvviRefConfigSetString(IDV_CONFIG_MODEL_VARIANT, "RV64GC"); + rvviRefConfigSetInt(IDV_CONFIG_MODEL_ADDRESS_BUS_WIDTH, 56); + rvviRefConfigSetInt(IDV_CONFIG_MAX_NET_LATENCY_RETIREMENTS, 6); + + /* Index of the network device */ + socket_address.sll_ifindex = ifopts.ifr_ifindex; + /* Address length*/ + socket_address.sll_halen = ETH_ALEN; + /* Destination MAC */ + socket_address.sll_addr[0] = DEST_MAC0; + socket_address.sll_addr[1] = DEST_MAC1; + socket_address.sll_addr[2] = DEST_MAC2; + socket_address.sll_addr[3] = DEST_MAC3; + socket_address.sll_addr[4] = DEST_MAC4; + socket_address.sll_addr[5] = DEST_MAC5; + + int i; + printf("buffer: "); + for(i=0;iether_dhost[0] == DEST_MAC0 && + eh->ether_dhost[1] == DEST_MAC1 && + eh->ether_dhost[2] == DEST_MAC2 && + eh->ether_dhost[3] == DEST_MAC3 && + eh->ether_dhost[4] == DEST_MAC4 && + eh->ether_dhost[5] == DEST_MAC5) { + //printf("Correct destination MAC address\n"); + uint64_t PC; + uint32_t insn; + RequiredRVVI_t InstructionData; + DecodeRVVI(buf + headerbytes, payloadbytes, &InstructionData); + // now let's drive IDV + // start simple just drive and compare PC. + PrintInstructionData(&InstructionData); + result = ProcessRvviAll(&InstructionData); + if(result == -1) break; + } + } + + printf("Simulation halted due to mismatch\n"); + + close(sockfd); + + + + return 0; +} + +int ProcessRvviAll(RequiredRVVI_t *InstructionData){ + long int found; + uint64_t time = InstructionData->Mcycle; + uint8_t trap = InstructionData->Trap; + uint64_t order = InstructionData->Minstret; + int result; + + result = 0; + if(InstructionData->GPREn) set_gpr(0, InstructionData->GPRReg, InstructionData->GPRValue); + if(InstructionData->FPREn) set_fpr(0, InstructionData->FPRReg, InstructionData->FPRValue); + + if (trap) { + rvviDutTrap(0, InstructionData->PC, InstructionData->insn); + } else { + rvviDutRetire(0, InstructionData->PC, InstructionData->insn, 0); + } + + if(!trap) result = state_compare(0, InstructionData->Minstret); + // *** set is for nets like interrupts come back to this. + //found = rvviRefNetIndexGet("pc_rdata"); + //rvviRefNetSet(found, InstructionData->PC, time); + return result; + +} + +int state_compare(int hart, uint64_t Minstret){ + uint8_t result = 1; + uint8_t stepOk = 0; + char buf[80]; + rvviDutCycleCountSet(Minstret); + if(rvviRefEventStep(hart) != 0) { + stepOk = 1; + result &= rvviRefPcCompare(hart); + result &= rvviRefInsBinCompare(hart); + result &= rvviRefGprsCompare(hart); + result &= rvviRefFprsCompare(hart); + result &= rvviRefCsrsCompare(hart); + } else { + result = 0; + } + + if (result == 0) { + /* Send packet */ + if (sendto(sockfd, sendbuf, tx_len, 0, (struct sockaddr*)&socket_address, sizeof(struct sockaddr_ll)) < 0){ + printf("Send failed\n"); + }else { + printf("send success!\n"); + } + + sprintf(buf, "MISMATCH @ instruction # %ld\n", Minstret); + idvMsgError(buf); + return -1; + } + +} + +void set_gpr(int hart, int reg, uint64_t value){ + rvviDutGprSet(hart, reg, value); +} + +void set_fpr(int hart, int reg, uint64_t value){ + rvviDutFprSet(hart, reg, value); +} + +void DecodeRVVI(uint8_t *payload, ssize_t payloadsize, RequiredRVVI_t *InstructionData){ + // you know this actually easiser in assembly. :( + uint8_t buf2[BUF_SIZ], buf3[BUF_SIZ]; + uint8_t * buf2ptr, *buf3ptr; + buf2ptr = buf2; + buf3ptr = buf3; + //int PayloadSize = sizeof(RequiredRVVI_t) - 1; + int PayloadSize = 30; + int Buf2Size = BUF_SIZ - PayloadSize; + uint64_t Mcycle, Minstret; + uint64_t PC; + uint32_t insn; + // unforunately the struct appoarch does not work?!? + PC = * (uint64_t *) payload; + payload += 8; + insn = * (uint32_t *) payload; + payload += 4; + Mcycle = * (uint64_t *) payload; + payload += 8; + Minstret = * (uint64_t *) payload; + payload += 8; + // the next 4 bytes contain CSRCount (12), FPRWen(1), GPRWen(1), PrivilegeMode(2), Trap(1) + uint32_t RequiredFlags; + RequiredFlags = * (uint32_t *) payload; + uint8_t Trap, PrivilegeMode, GPRWen, FPRWen; + uint16_t CSRCount = 0; + uint8_t GPRReg = 0; + uint64_t GPRData = 0; + uint8_t FPRReg = 0; + uint64_t FPRData = 0; + uint8_t CSRWen[3] = {0, 0, 0}; + uint16_t CSRReg[3]; + uint64_t CSRValue[3]; + int CSRIndex; + + Trap = RequiredFlags & 0x1; + PrivilegeMode = (RequiredFlags >> 1) & 0x3; + GPRWen = (RequiredFlags >> 3) & 0x1; + FPRWen = (RequiredFlags >> 4) & 0x1; + CSRCount = (RequiredFlags >> 5) & 0xFFF; + payload += 2; + + if(GPRWen || FPRWen || (CSRCount != 0)){ + // the first bit of payload is the last bit of CSRCount. + ssize_t newPayloadSize = payloadsize - 30; + BitShiftArray(buf2, payload, 1, newPayloadSize); + int index; + if(GPRWen){ + GPRReg = * (uint8_t *) buf2ptr; + GPRReg = GPRReg & 0x1F; + BitShiftArray(buf3, buf2ptr, 5, newPayloadSize); + GPRData = * (uint64_t *) buf3; + if(FPRWen){ + buf3ptr += 8; + FPRReg = * (uint8_t *) buf3ptr; + BitShiftArray(buf2, buf3ptr, 5, newPayloadSize - 8); + FPRReg = FPRReg & 0x1F; + FPRData = * (uint64_t *) buf2; + } + }else if(FPRWen){ + FPRReg = * (uint8_t *) buf2; + FPRReg = FPRReg & 0x1F; + BitShiftArray(buf3, buf2, 5, newPayloadSize); + FPRData = * (uint64_t *) buf3; + } + if(GPRWen ^ FPRWen){ + payload += 8; + Buf2Size = payloadsize - 38; + BitShiftArray(buf2, payload, 6, Buf2Size); + }else if(GPRWen & FPRWen){ + payload += 17; + Buf2Size = payloadsize - 47; + BitShiftArray(buf2, payload, 3, Buf2Size); + }else{ + Buf2Size = payloadsize - 30; + BitShiftArray(buf2, payload, 1, Buf2Size); + } + buf2ptr = buf2; + for(CSRIndex = 0; CSRIndex < CSRCount; CSRIndex++){ + CSRReg[CSRIndex] = (*(uint16_t *) buf2ptr) & 0xFFF; + Buf2Size -= 1; + BitShiftArray(buf3, buf2ptr + 1, 4, Buf2Size); + CSRValue[CSRIndex] = (*(uint64_t *) buf3); + CSRWen[CSRIndex] = 1; + buf2ptr = buf3; + } + } + InstructionData->PC = PC; + InstructionData->insn = insn; + InstructionData->Mcycle = Mcycle; + InstructionData->Minstret = Minstret; + InstructionData->Trap = Trap; + InstructionData->PrivilegeMode = PrivilegeMode; + InstructionData->GPREn = GPRWen; + InstructionData->FPREn = FPRWen; + InstructionData->CSRCount = CSRCount; + InstructionData->GPRReg = GPRReg; + InstructionData->GPRValue = GPRData; + InstructionData->FPRReg = FPRReg; + InstructionData->FPRValue = FPRData; + for(CSRIndex = 0; CSRIndex < 3; CSRIndex++){ + InstructionData->CSRWen[CSRIndex] = CSRWen[CSRIndex]; + InstructionData->CSRReg[CSRIndex] = CSRReg[CSRIndex]; + InstructionData->CSRValue[CSRIndex] = CSRValue[CSRIndex]; + } +} + +void PrintInstructionData(RequiredRVVI_t *InstructionData){ + int CSRIndex; + printf("PC = %lx, insn = %x, Mcycle = %lx, Minstret = %lx, Trap = %hhx, PrivilegeMode = %hhx", + InstructionData->PC, InstructionData->insn, InstructionData->Mcycle, InstructionData->Minstret, InstructionData->Trap, InstructionData->PrivilegeMode); + if(InstructionData->GPREn){ + printf(", GPR[%d] = %lx", InstructionData->GPRReg, InstructionData->GPRValue); + } + if(InstructionData->FPREn){ + printf(", FPR[%d] = %lx", InstructionData->FPRReg, InstructionData->FPRValue); + } + for(CSRIndex = 0; CSRIndex < 3; CSRIndex++){ + if(InstructionData->CSRWen[CSRIndex]){ + printf(", CSR[%x] = %lx", InstructionData->CSRReg[CSRIndex], InstructionData->CSRValue[CSRIndex]); + } + } + printf("\n"); +} + +void BitShiftArray(uint8_t *dst, uint8_t *src, uint8_t ShiftAmount, int Length){ + // always shift right by ShiftAmount (0 to 7 bit positions). + // *** this implemenation is very inefficient. improve later. + if(ShiftAmount < 0 || ShiftAmount > 7) return; + /* Read the first source byte + Read the second source byte + Right Shift byte 1 by ShiftAmount + Right Rotate byte 2 by ShiftAmount + Mask byte 2 by ~(2^ShiftAmount -1) + OR together the two bytes to form the final next byte + + repeat this for each byte + On the last byte we don't do the last steps + */ + int Index; + for(Index = 0; Index < Length - 1; Index++){ + uint8_t byte1 = src[Index]; + uint8_t byte2 = src[Index+1]; + byte1 = byte1 >> ShiftAmount; + uint8_t byte2rot = (byte2 << (unsigned) (8 - ShiftAmount)) & 0xff; + uint8_t byte1final = byte2rot | byte1; + dst[Index] = byte1final; + } + // fence post + // For last one there is only one source byte + uint8_t byte1 = src[Length-1]; + byte1 = byte1 >> ShiftAmount; + dst[Length-1] = byte1; +} diff --git a/fpga/src/fpgaTopArtyA7.sv b/fpga/src/fpgaTopArtyA7.sv index 5d038ad0f..fa2aa59a9 100644 --- a/fpga/src/fpgaTopArtyA7.sv +++ b/fpga/src/fpgaTopArtyA7.sv @@ -28,10 +28,10 @@ import cvw::*; -module fpgaTop - (input default_100mhz_clk, - input resetn, - input south_reset, +module fpgaTop #(parameter logic RVVI_SYNTH_SUPPORTED = 1) + (input default_100mhz_clk, +(* mark_debug = "true" *) input resetn, + input south_reset, // GPIO signals input [3:0] GPI, @@ -48,23 +48,36 @@ module fpgaTop output SDCCS, input SDCCD, input SDCWP, + /* + * Ethernet: 100BASE-T MII + */ + output phy_ref_clk, + input phy_rx_clk, + input [3:0] phy_rxd, + input phy_rx_dv, + input phy_rx_er, + input phy_tx_clk, + output [3:0] phy_txd, + output phy_tx_en, + input phy_col, // nc + input phy_crs, // nc + output phy_reset_n, - // Memory signals - inout [15:0] ddr3_dq, - inout [1:0] ddr3_dqs_n, - inout [1:0] ddr3_dqs_p, - output [13:0] ddr3_addr, - output [2:0] ddr3_ba, - output ddr3_ras_n, - output ddr3_cas_n, - output ddr3_we_n, - output ddr3_reset_n, - output [0:0] ddr3_ck_p, - output [0:0] ddr3_ck_n, - output [0:0] ddr3_cke, - output [0:0] ddr3_cs_n, - output [1:0] ddr3_dm, - output [0:0] ddr3_odt + inout [15:0] ddr3_dq, + inout [1:0] ddr3_dqs_n, + inout [1:0] ddr3_dqs_p, + output [13:0] ddr3_addr, + output [2:0] ddr3_ba, + output ddr3_ras_n, + output ddr3_cas_n, + output ddr3_we_n, + output ddr3_reset_n, + output [0:0] ddr3_ck_p, + output [0:0] ddr3_ck_n, + output [0:0] ddr3_cke, + output [0:0] ddr3_cs_n, + output [1:0] ddr3_dm, + output [0:0] ddr3_odt ); // MMCM Signals @@ -193,7 +206,8 @@ module fpgaTop wire mmcm_locked; wire [11:0] device_temp; wire mmcm1_locked; - + +(* mark_debug = "true" *) logic RVVIStall; assign GPIOIN = {25'b0, SDCCD, SDCWP, 1'b0, GPI}; assign GPO = GPIOOUT[4:0]; @@ -214,6 +228,7 @@ module fpgaTop xlnx_mmcm xln_mmcm(.clk_out1(clk167), .clk_out2(clk200), .clk_out3(CPUCLK), + .clk_out4(phy_ref_clk), .reset(1'b0), .locked(mmcm1_locked), .clk_in1(default_100mhz_clk)); @@ -243,7 +258,7 @@ module fpgaTop .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT, .HTRANS, .HMASTLOCK, .HREADY, .TIMECLK(1'b0), .GPIOIN, .GPIOOUT, .GPIOEN, - .UARTSin, .UARTSout, .SDCIn, .SDCCmd, .SDCCS(SDCCSin), .SDCCLK); + .UARTSin, .UARTSout, .SDCIn, .SDCCmd, .SDCCS(SDCCSin), .SDCCLK, .ExternalStall(RVVIStall)); // ahb lite to axi bridge @@ -461,7 +476,146 @@ module fpgaTop .init_calib_complete(c0_init_calib_complete), .device_temp(device_temp)); - + (* mark_debug = "true" *) logic IlaTrigger; + + + if(RVVI_SYNTH_SUPPORTED) begin : rvvi_synth + localparam MAX_CSRS = 3; + localparam TOTAL_CSRS = 36; + localparam [31:0] RVVI_INIT_TIME_OUT = 32'd100000000; + localparam [31:0] RVVI_PACKET_DELAY = 32'd400; + + // pipeline controlls + logic StallE, StallM, StallW, FlushE, FlushM, FlushW; + // required + logic [P.XLEN-1:0] PCM; + logic InstrValidM; + logic [31:0] InstrRawD; + logic [63:0] Mcycle, Minstret; + logic TrapM; + logic [1:0] PrivilegeModeW; + // registers gpr and fpr + logic GPRWen, FPRWen; + logic [4:0] GPRAddr, FPRAddr; + logic [P.XLEN-1:0] GPRValue, FPRValue; + logic [P.XLEN-1:0] CSRArray [TOTAL_CSRS-1:0]; + + logic valid; + logic [187+(3*P.XLEN) + MAX_CSRS*(P.XLEN+12)-1:0] rvvi; + + assign StallE = fpgaTop.wallypipelinedsoc.core.StallE; + assign StallM = fpgaTop.wallypipelinedsoc.core.StallM; + assign StallW = fpgaTop.wallypipelinedsoc.core.StallW; + assign FlushE = fpgaTop.wallypipelinedsoc.core.FlushE; + assign FlushM = fpgaTop.wallypipelinedsoc.core.FlushM; + assign FlushW = fpgaTop.wallypipelinedsoc.core.FlushW; + assign InstrValidM = fpgaTop.wallypipelinedsoc.core.ieu.InstrValidM; + assign InstrRawD = fpgaTop.wallypipelinedsoc.core.ifu.InstrRawD; + assign PCM = fpgaTop.wallypipelinedsoc.core.ifu.PCM; + assign Mcycle = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.counters.counters.HPMCOUNTER_REGW[0]; + assign Minstret = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.counters.counters.HPMCOUNTER_REGW[2]; + assign TrapM = fpgaTop.wallypipelinedsoc.core.TrapM; + assign PrivilegeModeW = fpgaTop.wallypipelinedsoc.core.priv.priv.privmode.PrivilegeModeW; + assign GPRAddr = fpgaTop.wallypipelinedsoc.core.ieu.dp.regf.a3; + assign GPRWen = fpgaTop.wallypipelinedsoc.core.ieu.dp.regf.we3; + assign GPRValue = fpgaTop.wallypipelinedsoc.core.ieu.dp.regf.wd3; + assign FPRAddr = fpgaTop.wallypipelinedsoc.core.fpu.fpu.fregfile.a4; + assign FPRWen = fpgaTop.wallypipelinedsoc.core.fpu.fpu.fregfile.we4; + assign FPRValue = fpgaTop.wallypipelinedsoc.core.fpu.fpu.fregfile.wd4; + + assign CSRArray[0] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MSTATUS_REGW; // 12'h300 + assign CSRArray[1] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MSTATUSH_REGW; // 12'h310 + assign CSRArray[2] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MTVEC_REGW; // 12'h305 + assign CSRArray[3] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MEPC_REGW; // 12'h341 + assign CSRArray[4] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MCOUNTEREN_REGW; // 12'h306 + assign CSRArray[5] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MCOUNTINHIBIT_REGW; // 12'h320 + assign CSRArray[6] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MEDELEG_REGW; // 12'h302 + assign CSRArray[7] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MIDELEG_REGW; // 12'h303 + assign CSRArray[8] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MIP_REGW; // 12'h344 + assign CSRArray[9] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MIE_REGW; // 12'h304 + assign CSRArray[10] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MISA_REGW; // 12'h301 + assign CSRArray[11] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MENVCFG_REGW; // 12'h30A + assign CSRArray[12] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MHARTID_REGW; // 12'hF14 + assign CSRArray[13] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MSCRATCH_REGW; // 12'h340 + assign CSRArray[14] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MCAUSE_REGW; // 12'h342 + assign CSRArray[15] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MTVAL_REGW; // 12'h343 + assign CSRArray[16] = 0; // 12'hF11 + assign CSRArray[17] = 0; // 12'hF12 + assign CSRArray[18] = {{P.XLEN-12{1'b0}}, 12'h100}; //P.XLEN'h100; // 12'hF13 + assign CSRArray[19] = 0; // 12'hF15 + assign CSRArray[20] = 0; // 12'h34A + // supervisor CSRs + assign CSRArray[21] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrs.csrs.SSTATUS_REGW; // 12'h100 + assign CSRArray[22] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MIE_REGW & 12'h222; // 12'h104 + assign CSRArray[23] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrs.csrs.STVEC_REGW; // 12'h105 + assign CSRArray[24] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrs.csrs.SEPC_REGW; // 12'h141 + assign CSRArray[25] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrs.csrs.SCOUNTEREN_REGW; // 12'h106 + assign CSRArray[26] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrs.csrs.SENVCFG_REGW; // 12'h10A + assign CSRArray[27] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrs.csrs.SATP_REGW; // 12'h180 + assign CSRArray[28] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrs.csrs.SSCRATCH_REGW; // 12'h140 + assign CSRArray[29] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrs.csrs.STVAL_REGW; // 12'h143 + assign CSRArray[30] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrs.csrs.SCAUSE_REGW; // 12'h142 + assign CSRArray[31] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MIP_REGW & 12'h222 & fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MIDELEG_REGW; // 12'h144 + assign CSRArray[32] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrs.csrs.STIMECMP_REGW; // 12'h14D + // user CSRs + assign CSRArray[33] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csru.csru.FFLAGS_REGW; // 12'h001 + assign CSRArray[34] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csru.csru.FRM_REGW; // 12'h002 + assign CSRArray[35] = {fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csru.csru.FRM_REGW, fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csru.csru.FFLAGS_REGW}; // 12'h003 + + rvvisynth #(P, MAX_CSRS) rvvisynth(.clk(CPUCLK), .reset(bus_struct_reset), .StallE, .StallM, .StallW, .FlushE, .FlushM, .FlushW, + .PCM, .InstrValidM, .InstrRawD, .Mcycle, .Minstret, .TrapM, + .PrivilegeModeW, .GPRWen, .FPRWen, .GPRAddr, .FPRAddr, .GPRValue, .FPRValue, .CSRArray, + .valid, .rvvi); + + // axi 4 write data channel + logic [31:0] RvviAxiWdata; + logic [3:0] RvviAxiWstrb; + logic RvviAxiWlast; + logic RvviAxiWvalid; + logic RvviAxiWready; + + logic [31:0] RvviAxiRdata; + logic [3:0] RvviAxiRstrb; + logic RvviAxiRlast; + logic RvviAxiRvalid; + + logic tx_error_underflow, tx_fifo_overflow, tx_fifo_bad_frame, tx_fifo_good_frame, rx_error_bad_frame; + logic rx_error_bad_fcs, rx_fifo_overflow, rx_fifo_bad_frame, rx_fifo_good_frame; + + packetizer #(P, MAX_CSRS, RVVI_INIT_TIME_OUT, RVVI_PACKET_DELAY) packetizer(.rvvi, .valid, .m_axi_aclk(CPUCLK), .m_axi_aresetn(~bus_struct_reset), .RVVIStall, + .RvviAxiWdata, .RvviAxiWstrb, .RvviAxiWlast, .RvviAxiWvalid, .RvviAxiWready); + + eth_mac_mii_fifo #(.TARGET("XILINX"), .CLOCK_INPUT_STYLE("BUFG"), .AXIS_DATA_WIDTH(32), .TX_FIFO_DEPTH(1024)) ethernet(.rst(bus_struct_reset), .logic_clk(CPUCLK), .logic_rst(bus_struct_reset), + .tx_axis_tdata(RvviAxiWdata), .tx_axis_tkeep(RvviAxiWstrb), .tx_axis_tvalid(RvviAxiWvalid), .tx_axis_tready(RvviAxiWready), + .tx_axis_tlast(RvviAxiWlast), .tx_axis_tuser('0), .rx_axis_tdata(RvviAxiRdata), + .rx_axis_tkeep(RvviAxiRstrb), .rx_axis_tvalid(RvviAxiRvalid), .rx_axis_tready(1'b1), + .rx_axis_tlast(RvviAxiRlast), .rx_axis_tuser(), + + .mii_rx_clk(phy_rx_clk), + .mii_rxd(phy_rxd), + .mii_rx_dv(phy_rx_dv), + .mii_rx_er(phy_rx_er), + .mii_tx_clk(phy_tx_clk), + .mii_txd(phy_txd), + .mii_tx_en(phy_tx_en), + .mii_tx_er(), + + // status + .tx_error_underflow, .tx_fifo_overflow, .tx_fifo_bad_frame, .tx_fifo_good_frame, .rx_error_bad_frame, + .rx_error_bad_fcs, .rx_fifo_overflow, .rx_fifo_bad_frame, .rx_fifo_good_frame, + .cfg_ifg(8'd12), .cfg_tx_enable(1'b1), .cfg_rx_enable(1'b1) + ); + + triggergen triggergen(.clk(CPUCLK), .reset(bus_struct_reset), .RvviAxiRdata, + .RvviAxiRstrb, .RvviAxiRlast, .RvviAxiRvalid, .IlaTrigger); + end else begin // if (P.RVVI_SYNTH_SUPPORTED) + assign IlaTrigger = '0; + assign RVVIStall = '0; + end + + //assign phy_reset_n = ~bus_struct_reset; + assign phy_reset_n = ~1'b0; + endmodule diff --git a/sim/questa/wally.do b/sim/questa/wally.do index c7cba4925..632e2c156 100644 --- a/sim/questa/wally.do +++ b/sim/questa/wally.do @@ -197,7 +197,7 @@ set temp3 [lindex $PlusArgs 3] # "Extra checking for conflicts with always_comb done at vopt time" # because vsim will run vopt -vlog -lint -work ${WKDIR} +incdir+${CONFIG}/${CFG} +incdir+${CONFIG}/deriv/${CFG} +incdir+${CONFIG}/shared ${lockstepvoptstring} ${FCdefineIDV_INCLUDE_TRACE2COV} ${FCdefineINCLUDE_TRACE2COV} ${ImperasPubInc} ${ImperasPrivInc} ${rvviFiles} ${FCdefineCOVER_BASE_RV64I} ${FCdefineCOVER_LEVEL_DV_PR_EXT} ${FCdefineCOVER_RV64I} ${FCdefineCOVER_RV64M} ${FCdefineCOVER_RV64A} ${FCdefineCOVER_RV64F} ${FCdefineCOVER_RV64D} ${FCdefineCOVER_RV64ZICSR} ${FCdefineCOVER_RV64C} ${idvFiles} ${riscvISACOVsrc} ${SRC}/cvw.sv ${TB}/${TESTBENCH}.sv ${TB}/common/*.sv ${SRC}/*/*.sv ${SRC}/*/*/*.sv -suppress 2583 -suppress 7063,2596,13286 +vlog -lint -work ${WKDIR} +incdir+${CONFIG}/${CFG} +incdir+${CONFIG}/deriv/${CFG} +incdir+${CONFIG}/shared ${lockstepvoptstring} ${FCdefineIDV_INCLUDE_TRACE2COV} ${FCdefineINCLUDE_TRACE2COV} ${ImperasPubInc} ${ImperasPrivInc} ${rvviFiles} ${FCdefineCOVER_BASE_RV64I} ${FCdefineCOVER_LEVEL_DV_PR_EXT} ${FCdefineCOVER_RV64I} ${FCdefineCOVER_RV64M} ${FCdefineCOVER_RV64A} ${FCdefineCOVER_RV64F} ${FCdefineCOVER_RV64D} ${FCdefineCOVER_RV64ZICSR} ${FCdefineCOVER_RV64C} ${idvFiles} ${riscvISACOVsrc} ${SRC}/cvw.sv ${TB}/${TESTBENCH}.sv ${TB}/common/*.sv ${SRC}/*/*.sv ${SRC}/*/*/*.sv ${WALLY}/addins/verilog-ethernet/*/*.sv ${WALLY}/addins/verilog-ethernet/*/*/*/*.sv -suppress 2583 -suppress 7063,2596,13286 # start and run simulation # remove +acc flag for faster sim during regressions if there is no need to access internal signals diff --git a/sim/questa/wave.do b/sim/questa/wave.do index c6cc26f9c..201002d7d 100644 --- a/sim/questa/wave.do +++ b/sim/questa/wave.do @@ -657,9 +657,25 @@ add wave -noupdate -group wfi /testbench/dut/core/priv/priv/pmd/WFITimeoutM add wave -noupdate -expand -group testbench /testbench/DCacheFlushStart add wave -noupdate /testbench/dut/core/lsu/hptw/hptw/HPTWLoadPageFault add wave -noupdate /testbench/dut/core/lsu/hptw/hptw/HPTWLoadPageFaultDelay +add wave -noupdate -expand -group rvvi /testbench/rvvi_synth/rvvisynth/clk +add wave -noupdate -expand -group rvvi /testbench/rvvi_synth/rvvisynth/rvvi +add wave -noupdate -expand -group rvvi /testbench/rvvi_synth/rvvisynth/valid +add wave -noupdate -group packetizer -color Gold /testbench/rvvi_synth/packetizer/CurrState +add wave -noupdate -group packetizer -radix unsigned /testbench/rvvi_synth/packetizer/WordCount +add wave -noupdate -group packetizer /testbench/rvvi_synth/packetizer/RVVIStall +add wave -noupdate -group packetizer /testbench/rvvi_synth/packetizer/rvviDelay +add wave -noupdate -group packetizer -expand -group axi-write-interface /testbench/rvvi_synth/packetizer/RvviAxiWdata +add wave -noupdate -group packetizer -expand -group axi-write-interface /testbench/rvvi_synth/packetizer/RvviAxiWlast +add wave -noupdate -group packetizer -expand -group axi-write-interface /testbench/rvvi_synth/packetizer/RvviAxiWstrb +add wave -noupdate -group packetizer -expand -group axi-write-interface /testbench/rvvi_synth/packetizer/RvviAxiWvalid +add wave -noupdate -group packetizer -expand -group axi-write-interface /testbench/rvvi_synth/packetizer/RvviAxiWready +add wave -noupdate -expand -group eth /testbench/rvvi_synth/ethernet/mii_tx_clk +add wave -noupdate -expand -group eth /testbench/rvvi_synth/ethernet/mii_txd +add wave -noupdate -expand -group eth /testbench/rvvi_synth/ethernet/mii_tx_en +add wave -noupdate -expand -group eth /testbench/rvvi_synth/ethernet/mii_tx_er TreeUpdate [SetDefaultTree] -WaveRestoreCursors {{Cursor 4} {6586 ns} 1} {{Cursor 4} {2112952 ns} 0} {{Cursor 3} {403021 ns} 1} -quietly wave cursor active 2 +WaveRestoreCursors {{Cursor 4} {640 ns} 1} {{Cursor 4} {2400 ns} 1} {{Cursor 3} {554 ns} 0} {{Cursor 4} {120089 ns} 0} +quietly wave cursor active 4 configure wave -namecolwidth 250 configure wave -valuecolwidth 194 configure wave -justifyvalue left @@ -674,4 +690,4 @@ configure wave -griddelta 40 configure wave -timeline 0 configure wave -timelineunits ns update -WaveRestoreZoom {2039338 ns} {2323972 ns} +WaveRestoreZoom {0 ns} {1033211 ns} diff --git a/sim/verilator/Makefile b/sim/verilator/Makefile index 576ecf2b7..a7a57244e 100644 --- a/sim/verilator/Makefile +++ b/sim/verilator/Makefile @@ -25,7 +25,7 @@ TARGET=$(WORKING_DIR)/target # INCLUDE_PATH are pathes that Verilator should search for files it needs INCLUDE_PATH="-I${WALLY}/config/shared" "-I${WALLY}/config/$(WALLYCONF)" "-I${WALLY}/config/deriv/$(WALLYCONF)" # SOURCES are source files -SOURCES=${WALLY}/src/cvw.sv ${WALLY}/testbench/${TESTBENCH}.sv ${WALLY}/testbench/common/*.sv ${WALLY}/src/*/*.sv ${WALLY}/src/*/*/*.sv +SOURCES=${WALLY}/src/cvw.sv ${WALLY}/testbench/${TESTBENCH}.sv ${WALLY}/testbench/common/*.sv ${WALLY}/src/*/*.sv ${WALLY}/src/*/*/*.sv ${WALLY}/addins/verilog-ethernet/*/*.sv ${WALLY}/addins/verilog-ethernet/*/*/*/*.sv # DEPENDENCIES are configuration files and source files, which leads to recompilation of executables DEPENDENCIES=${WALLY}/config/shared/*.vh $(SOURCES) diff --git a/src/cvw.sv b/src/cvw.sv index 2e50ca8b9..ed0493484 100644 --- a/src/cvw.sv +++ b/src/cvw.sv @@ -296,7 +296,6 @@ typedef struct packed { int DIVBLEN ; // integer division/remainder constants int INTDIVb ; - } cvw_t; endpackage diff --git a/src/fpu/fctrl.sv b/src/fpu/fctrl.sv index 8595fd29e..ab9cad093 100755 --- a/src/fpu/fctrl.sv +++ b/src/fpu/fctrl.sv @@ -81,6 +81,7 @@ module fctrl import cvw::*; #(parameter cvw_t P) ( logic [1:0] Fmt, Fmt2; // format - before possible reduction logic SupportedFmt; // is the format supported logic SupportedFmt2; // is the source format supported for fp -> fp + logic SupportedRM; // is the rounding mode supported logic FCvtIntD, FCvtIntM; // convert to integer operation logic ZfaD; // Zfa variants of instructions logic ZfaFRoundNXD; // Zfa froundnx instruction @@ -93,14 +94,19 @@ module fctrl import cvw::*; #(parameter cvw_t P) ( (Fmt == 2'b10 & P.ZFH_SUPPORTED) | (Fmt == 2'b11 & P.Q_SUPPORTED)); assign SupportedFmt2 = (Fmt2 == 2'b00 | (Fmt2 == 2'b01 & P.D_SUPPORTED) | (Fmt2 == 2'b10 & P.ZFH_SUPPORTED) | (Fmt2 == 2'b11 & P.Q_SUPPORTED)); - + // rounding modes 5 and 6 are reserved. Rounding mode 7 is dynamic, and is reserved if FRM is 5, 6, or 7 + assign SupportedRM = ~(Funct3D == 3'b101 | Funct3D == 3'b110 | (Funct3D == 3'b111 & (FRM_REGW == 3'b101 | FRM_REGW == 3'b110 | FRM_REGW == 3'b111))) | + (OpD == 7'b1010011 & Funct3D == 3'b101 & Funct7D[6:2] == 5'b10100 & P.ZFA_SUPPORTED); // Zfa fltq has a funny rounding mode + /*assign SupportedRM = ~(Funct3D == 3'b101 | Funct3D == 3'b110 | (Funct3D == 3'b111 & (FRM_REGW == 3'b101 | FRM_REGW == 3'b110 | FRM_REGW == 3'b111))) | + (OpD == 7'b1010011 & P.ZFA_SUPPORTED); +*/ // decode the instruction // FRegWrite_FWriteInt_FResSel_PostProcSel_FOpCtrl_FDivStart_IllegalFPUInstr_FCvtInt_Zfa_FroundNX always_comb if (STATUS_FS == 2'b00) // FPU instructions are illegal when FPU is disabled ControlsD = `FCTRLW'b0_0_00_00_000_0_1_0_0_0; - else if (OpD != 7'b0000111 & OpD != 7'b0100111 & ~SupportedFmt) - ControlsD = `FCTRLW'b0_0_00_00_000_0_1_0_0_0; // for anything other than loads and stores, check for supported format + else if (OpD != 7'b0000111 & OpD != 7'b0100111 & (~SupportedFmt | ~SupportedRM)) + ControlsD = `FCTRLW'b0_0_00_00_000_0_1_0_0_0; // for anything other than loads and stores, check for supported format and rounding mode else begin ControlsD = `FCTRLW'b0_0_00_00_000_0_1_0_0_0; // default: non-implemented instruction /* verilator lint_off CASEINCOMPLETE */ // default value above has priority so no other default needed diff --git a/src/hazard/hazard.sv b/src/hazard/hazard.sv index a5b6e319d..895a6e92f 100644 --- a/src/hazard/hazard.sv +++ b/src/hazard/hazard.sv @@ -31,7 +31,7 @@ module hazard import cvw::*; #(parameter cvw_t P) ( input logic BPWrongE, CSRWriteFenceM, RetM, TrapM, input logic StructuralStallD, input logic LSUStallM, IFUStallF, - input logic FPUStallD, + input logic FPUStallD, ExternalStall, input logic DivBusyE, FDivBusyE, input logic wfiM, IntPendingM, // Stall & flush outputs @@ -89,7 +89,7 @@ module hazard import cvw::*; #(parameter cvw_t P) ( // Need to gate IFUStallF when the equivalent FlushFCause = FlushDCause = 1. // assign StallWCause = ((IFUStallF & ~FlushDCause) | LSUStallM) & ~FlushWCause; // Because FlushWCause is a strict subset of FlushDCause, FlushWCause is factored out. - assign StallWCause = (IFUStallF & ~FlushDCause) | (LSUStallM & ~FlushWCause); + assign StallWCause = (IFUStallF & ~FlushDCause) | (LSUStallM & ~FlushWCause) | ExternalStall; // Stall each stage for cause or if the next stage is stalled // coverage off: StallFCause is always 0 diff --git a/src/ieu/bmu/bmuctrl.sv b/src/ieu/bmu/bmuctrl.sv index d482616ef..d4a8afe23 100644 --- a/src/ieu/bmu/bmuctrl.sv +++ b/src/ieu/bmu/bmuctrl.sv @@ -238,7 +238,7 @@ module bmuctrl import cvw::*; #(parameter cvw_t P) ( if ((P.ZKND_SUPPORTED | P.ZKNE_SUPPORTED) & P.XLEN == 64) begin // ZKND and ZKNE shared instructions casez({OpD, Funct7D, Funct3D}) - 17'b0010011_0011000_001: if (Rs2D[4] == 1'b1) + 17'b0010011_0011000_001: if (Rs2D[4] == 1'b1 & $unsigned(Rs2D[3:0]) <= 10) BMUControlsD = `BMUCTRLW'b000_0111_0010_1_0_0_0_1_0_0_0_0_0; // aes64ks1i - key schedule istr1 17'b0110011_0111111_000: BMUControlsD = `BMUCTRLW'b000_0111_0011_1_0_0_0_1_0_0_0_0_0; // aes64ks2 - key schedule istr2 endcase diff --git a/src/privileged/csrm.sv b/src/privileged/csrm.sv index f86b3f6d6..24132ab93 100644 --- a/src/privileged/csrm.sv +++ b/src/privileged/csrm.sv @@ -106,7 +106,10 @@ module csrm import cvw::*; #(parameter cvw_t P) ( genvar i; if (P.PMP_ENTRIES > 0) begin:pmp logic [P.PMP_ENTRIES-1:0] WritePMPCFGM; - logic [P.PMP_ENTRIES-1:0] WritePMPADDRM ; + logic [P.PMP_ENTRIES-1:0] WritePMPADDRM; + logic [7:0] CSRPMPWriteValM[P.PMP_ENTRIES-1:0]; + logic [7:0] CSRPMPLegalizedWriteValM[P.PMP_ENTRIES-1:0]; + logic [1:0] CSRPMPWRLegalizedWriteValM[P.PMP_ENTRIES-1:0]; logic [P.PMP_ENTRIES-1:0] ADDRLocked, CFGLocked; for(i=0; i 4'd4; + assign Threshold = Counter >= 4'd4; + assign Mismatch = (mem[Counter] != RvviAxiRdataDelay) & (CurrState == STATE_COMPARE) & RvviAxiRvalidDelay; + assign IlaTriggerOneCycle = CurrState == STATE_TRIGGER; + assign CounterRst = CurrState == STATE_RST; + assign CounterEn = RvviAxiRvalid; + +/* -----\/----- EXCLUDED -----\/----- + always_ff @(posedge clk) begin + if(reset) IlaTrigger <= '0; + else if (IlaTriggerOneCycle) IlaTrigger <= '1; + else if (IlaTriggerAck) IlaTrigger <= '0; + else IlaTrigger <= IlaTrigger; + end + -----/\----- EXCLUDED -----/\----- */ + + // this is a bit hacky, but it works! + logic [3:0] TriggerCount; + logic TriggerReset, TriggerEn; + counter #(4) triggercounter(clk, reset | TriggerReset, TriggerEn, TriggerCount); + assign TriggerReset = TriggerCount == 4'd10; + assign TriggerEn = IlaTriggerOneCycle | (TriggerCount != 4'd0 & TriggerCount < 4'd10); + assign IlaTrigger = TriggerEn; + +endmodule diff --git a/src/wally/wallypipelinedcore.sv b/src/wally/wallypipelinedcore.sv index d3589a93a..8158a1cfb 100644 --- a/src/wally/wallypipelinedcore.sv +++ b/src/wally/wallypipelinedcore.sv @@ -44,7 +44,8 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) ( output logic [2:0] HBURST, output logic [3:0] HPROT, output logic [1:0] HTRANS, - output logic HMASTLOCK + output logic HMASTLOCK, + input logic ExternalStall ); logic StallF, StallD, StallE, StallM, StallW; @@ -274,7 +275,7 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) ( .BPWrongE, .CSRWriteFenceM, .RetM, .TrapM, .StructuralStallD, .LSUStallM, .IFUStallF, - .FPUStallD, + .FPUStallD, .ExternalStall, .DivBusyE, .FDivBusyE, .wfiM, .IntPendingM, // Stall & flush outputs diff --git a/src/wally/wallypipelinedsoc.sv b/src/wally/wallypipelinedsoc.sv index 77845aff3..2e534ba59 100644 --- a/src/wally/wallypipelinedsoc.sv +++ b/src/wally/wallypipelinedsoc.sv @@ -32,9 +32,11 @@ module wallypipelinedsoc import cvw::*; #(parameter cvw_t P) ( input logic reset_ext, // external asynchronous reset pin output logic reset, // reset synchronized to clk to prevent races on release // AHB Interface - input logic [P.AHBW-1:0] HRDATAEXT, + input logic [P.AHBW-1:0] HRDATAEXT, input logic HREADYEXT, HRESPEXT, output logic HSELEXT, + // fpga debug signals + input logic ExternalStall, // outputs to external memory, shared with uncore memory output logic HCLK, HRESETn, output logic [P.PA_BITS-1:0] HADDR, @@ -78,7 +80,7 @@ module wallypipelinedsoc import cvw::*; #(parameter cvw_t P) ( wallypipelinedcore #(P) core(.clk, .reset, .MTimerInt, .MExtInt, .SExtInt, .MSwInt, .MTIME_CLINT, .HRDATA, .HREADY, .HRESP, .HCLK, .HRESETn, .HADDR, .HWDATA, .HWSTRB, - .HWRITE, .HSIZE, .HBURST, .HPROT, .HTRANS, .HMASTLOCK + .HWRITE, .HSIZE, .HBURST, .HPROT, .HTRANS, .HMASTLOCK, .ExternalStall ); // instantiate uncore if a bus interface exists @@ -93,4 +95,5 @@ module wallypipelinedsoc import cvw::*; #(parameter cvw_t P) ( MTIME_CLINT, GPIOOUT, GPIOEN, UARTSout, SPIOut, SPICS, SPICLK, SDCCmd, SDCCS, SDCCLK} = '0; end + endmodule diff --git a/testbench/common/rvvitbwrapper.sv b/testbench/common/rvvitbwrapper.sv new file mode 100644 index 000000000..708cd0e7b --- /dev/null +++ b/testbench/common/rvvitbwrapper.sv @@ -0,0 +1,170 @@ +/////////////////////////////////////////// +// loggers.sv +// +// Written: Rose Thompson ross1728@gmail.com +// Modified: 24 July 2024 +// +// Purpose: Wraps all the synthesizable rvvi hardware into a single module for the testbench. +// +// A component of the Wally configurable RISC-V project. +// +// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University +// +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// Licensed under the Solderpad Hardware License v 2.1 (the “License”); you may not use this file +// except in compliance with the License, or, at your option, the Apache License version 2.0. You +// may obtain a copy of the License at +// +// https://solderpad.org/licenses/SHL-2.1/ +// +// Unless required by applicable law or agreed to in writing, any work distributed under the +// License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +// either express or implied. See the License for the specific language governing permissions +// and limitations under the License. +//////////////////////////////////////////////////////////////////////////////////////////////// + +module rvvitbwrapper import cvw::*; #(parameter cvw_t P, + parameter MAX_CSRS = 5, + parameter logic [31:0] RVVI_INIT_TIME_OUT = 32'd4, + parameter logic [31:0] RVVI_PACKET_DELAY = 32'd2)( + input logic clk, + input logic reset, + output logic RVVIStall, + input logic mii_tx_clk, + output logic [3:0] mii_txd, + output logic mii_tx_en, mii_tx_er, + input logic mii_rx_clk, + input logic [3:0] mii_rxd, + input logic mii_rx_dv, + input logic mii_rx_er +); + + logic valid; + logic [187+(3*P.XLEN) + MAX_CSRS*(P.XLEN+12)-1:0] rvvi; + + localparam TOTAL_CSRS = 36; + + // pipeline controlls + logic StallE, StallM, StallW, FlushE, FlushM, FlushW; + // required + logic [P.XLEN-1:0] PCM; + logic InstrValidM; + logic [31:0] InstrRawD; + logic [63:0] Mcycle, Minstret; + logic TrapM; + logic [1:0] PrivilegeModeW; + // registers gpr and fpr + logic GPRWen, FPRWen; + logic [4:0] GPRAddr, FPRAddr; + logic [P.XLEN-1:0] GPRValue, FPRValue; + logic [P.XLEN-1:0] CSRArray [TOTAL_CSRS-1:0]; + + // axi 4 write data channel + logic [31:0] RvviAxiWdata; + logic [3:0] RvviAxiWstrb; + logic RvviAxiWlast; + logic RvviAxiWvalid; + logic RvviAxiWready; + + logic tx_error_underflow, tx_fifo_overflow, tx_fifo_bad_frame, tx_fifo_good_frame, rx_error_bad_frame; + logic rx_error_bad_fcs, rx_fifo_overflow, rx_fifo_bad_frame, rx_fifo_good_frame; + + logic MiiTxEnDelay; + logic EthernetTXCounterEn; + logic [31:0] EthernetTXCount; + + assign StallE = dut.core.StallE; + assign StallM = dut.core.StallM; + assign StallW = dut.core.StallW; + assign FlushE = dut.core.FlushE; + assign FlushM = dut.core.FlushM; + assign FlushW = dut.core.FlushW; + assign InstrValidM = dut.core.ieu.InstrValidM; + assign InstrRawD = dut.core.ifu.InstrRawD; + assign PCM = dut.core.ifu.PCM; + assign Mcycle = dut.core.priv.priv.csr.counters.counters.HPMCOUNTER_REGW[0]; + assign Minstret = dut.core.priv.priv.csr.counters.counters.HPMCOUNTER_REGW[2]; + assign TrapM = dut.core.TrapM; + assign PrivilegeModeW = dut.core.priv.priv.privmode.PrivilegeModeW; + assign GPRAddr = dut.core.ieu.dp.regf.a3; + assign GPRWen = dut.core.ieu.dp.regf.we3; + assign GPRValue = dut.core.ieu.dp.regf.wd3; + assign FPRAddr = dut.core.fpu.fpu.fregfile.a4; + assign FPRWen = dut.core.fpu.fpu.fregfile.we4; + assign FPRValue = dut.core.fpu.fpu.fregfile.wd4; + + assign CSRArray[0] = dut.core.priv.priv.csr.csrm.MSTATUS_REGW; // 12'h300 + assign CSRArray[1] = dut.core.priv.priv.csr.csrm.MSTATUSH_REGW; // 12'h310 + assign CSRArray[2] = dut.core.priv.priv.csr.csrm.MTVEC_REGW; // 12'h305 + assign CSRArray[3] = dut.core.priv.priv.csr.csrm.MEPC_REGW; // 12'h341 + assign CSRArray[4] = dut.core.priv.priv.csr.csrm.MCOUNTEREN_REGW; // 12'h306 + assign CSRArray[5] = dut.core.priv.priv.csr.csrm.MCOUNTINHIBIT_REGW; // 12'h320 + assign CSRArray[6] = dut.core.priv.priv.csr.csrm.MEDELEG_REGW; // 12'h302 + assign CSRArray[7] = dut.core.priv.priv.csr.csrm.MIDELEG_REGW; // 12'h303 + assign CSRArray[8] = dut.core.priv.priv.csr.csrm.MIP_REGW; // 12'h344 + assign CSRArray[9] = dut.core.priv.priv.csr.csrm.MIE_REGW; // 12'h304 + assign CSRArray[10] = dut.core.priv.priv.csr.csrm.MISA_REGW; // 12'h301 + assign CSRArray[11] = dut.core.priv.priv.csr.csrm.MENVCFG_REGW; // 12'h30A + assign CSRArray[12] = dut.core.priv.priv.csr.csrm.MHARTID_REGW; // 12'hF14 + assign CSRArray[13] = dut.core.priv.priv.csr.csrm.MSCRATCH_REGW; // 12'h340 + assign CSRArray[14] = dut.core.priv.priv.csr.csrm.MCAUSE_REGW; // 12'h342 + assign CSRArray[15] = dut.core.priv.priv.csr.csrm.MTVAL_REGW; // 12'h343 + assign CSRArray[16] = 0; // 12'hF11 + assign CSRArray[17] = 0; // 12'hF12 + assign CSRArray[18] = {{P.XLEN-12{1'b0}}, 12'h100}; //P.XLEN'h100; // 12'hF13 + assign CSRArray[19] = 0; // 12'hF15 + assign CSRArray[20] = 0; // 12'h34A + // supervisor CSRs + assign CSRArray[21] = dut.core.priv.priv.csr.csrs.csrs.SSTATUS_REGW; // 12'h100 + assign CSRArray[22] = dut.core.priv.priv.csr.csrm.MIE_REGW & 12'h222; // 12'h104 + assign CSRArray[23] = dut.core.priv.priv.csr.csrs.csrs.STVEC_REGW; // 12'h105 + assign CSRArray[24] = dut.core.priv.priv.csr.csrs.csrs.SEPC_REGW; // 12'h141 + assign CSRArray[25] = dut.core.priv.priv.csr.csrs.csrs.SCOUNTEREN_REGW; // 12'h106 + assign CSRArray[26] = dut.core.priv.priv.csr.csrs.csrs.SENVCFG_REGW; // 12'h10A + assign CSRArray[27] = dut.core.priv.priv.csr.csrs.csrs.SATP_REGW; // 12'h180 + assign CSRArray[28] = dut.core.priv.priv.csr.csrs.csrs.SSCRATCH_REGW; // 12'h140 + assign CSRArray[29] = dut.core.priv.priv.csr.csrs.csrs.STVAL_REGW; // 12'h143 + assign CSRArray[30] = dut.core.priv.priv.csr.csrs.csrs.SCAUSE_REGW; // 12'h142 + assign CSRArray[31] = dut.core.priv.priv.csr.csrm.MIP_REGW & 12'h222 & dut.core.priv.priv.csr.csrm.MIDELEG_REGW; // 12'h144 + assign CSRArray[32] = dut.core.priv.priv.csr.csrs.csrs.STIMECMP_REGW; // 12'h14D + // user CSRs + assign CSRArray[33] = dut.core.priv.priv.csr.csru.csru.FFLAGS_REGW; // 12'h001 + assign CSRArray[34] = dut.core.priv.priv.csr.csru.csru.FRM_REGW; // 12'h002 + assign CSRArray[35] = {dut.core.priv.priv.csr.csru.csru.FRM_REGW, dut.core.priv.priv.csr.csru.csru.FFLAGS_REGW}; // 12'h003 + + rvvisynth #(P, MAX_CSRS, TOTAL_CSRS) rvvisynth(.clk, .reset, .StallE, .StallM, .StallW, .FlushE, .FlushM, .FlushW, + .PCM, .InstrValidM, .InstrRawD, .Mcycle, .Minstret, .TrapM, + .PrivilegeModeW, .GPRWen, .FPRWen, .GPRAddr, .FPRAddr, .GPRValue, .FPRValue, .CSRArray, + .valid, .rvvi); + + packetizer #(P, MAX_CSRS, RVVI_INIT_TIME_OUT, RVVI_PACKET_DELAY) packetizer(.rvvi, .valid, .m_axi_aclk(clk), .m_axi_aresetn(~reset), .RVVIStall, + .RvviAxiWdata, .RvviAxiWstrb, .RvviAxiWlast, .RvviAxiWvalid, .RvviAxiWready); + + eth_mac_mii_fifo #("GENERIC", "BUFG", 32) ethernet(.rst(reset), .logic_clk(clk), .logic_rst(reset), + .tx_axis_tdata(RvviAxiWdata), .tx_axis_tkeep(RvviAxiWstrb), .tx_axis_tvalid(RvviAxiWvalid), .tx_axis_tready(RvviAxiWready), + .tx_axis_tlast(RvviAxiWlast), .tx_axis_tuser('0), .rx_axis_tdata(), .rx_axis_tkeep(), .rx_axis_tvalid(), .rx_axis_tready(1'b1), + .rx_axis_tlast(), .rx_axis_tuser(), + + .mii_rx_clk(clk), + .mii_rxd('0), + .mii_rx_dv('0), + .mii_rx_er('0), + .mii_tx_clk(clk), + .mii_txd, + .mii_tx_en, + .mii_tx_er, + + // status + .tx_error_underflow, .tx_fifo_overflow, .tx_fifo_bad_frame, .tx_fifo_good_frame, .rx_error_bad_frame, + .rx_error_bad_fcs, .rx_fifo_overflow, .rx_fifo_bad_frame, .rx_fifo_good_frame, + .cfg_ifg(8'd12), .cfg_tx_enable(1'b1), .cfg_rx_enable(1'b1)); + + flopr #(1) txedgereg(clk, reset, mii_tx_en, MiiTxEnDelay); + assign EthernetTXCounterEn = ~mii_tx_en & MiiTxEnDelay; + counter #(32) ethernexttxcounter(clk, reset, EthernetTXCounterEn, EthernetTXCount); + +endmodule + + + diff --git a/testbench/common/wallyTracer.sv b/testbench/common/wallyTracer.sv index 8c72a6816..80f7af651 100644 --- a/testbench/common/wallyTracer.sv +++ b/testbench/common/wallyTracer.sv @@ -274,7 +274,7 @@ module wallyTracer import cvw::*; #(parameter cvw_t P) (rvviTrace rvvi); // Initially connecting the writeback stage signals, but may need to use M stage // and gate on ~FlushW. - assign valid = InstrValidW & ~StallW; + assign valid = InstrValidW & ~StallW & ~reset; assign rvvi.clk = clk; assign rvvi.valid[0][0] = valid; assign rvvi.order[0][0] = CSRArray[12'hB02]; // TODO: IMPERAS Should be event order diff --git a/testbench/testbench.sv b/testbench/testbench.sv index c8e659670..89d3b06d5 100644 --- a/testbench/testbench.sv +++ b/testbench/testbench.sv @@ -33,7 +33,6 @@ `include "idv/idv.svh" `endif - import cvw::*; module testbench; @@ -44,6 +43,7 @@ module testbench; parameter BPRED_LOGGER=0; parameter I_CACHE_ADDR_LOGGER=0; parameter D_CACHE_ADDR_LOGGER=0; + parameter RVVI_SYNTH_SUPPORTED=0; `ifdef USE_IMPERAS_DV import idvPkg::*; @@ -117,6 +117,7 @@ module testbench; logic SelectTest; logic TestComplete; logic PrevPCZero; + logic RVVIStall; initial begin // look for arguments passed to simulation, or use defaults @@ -614,7 +615,8 @@ module testbench; end - wallypipelinedsoc #(P) dut(.clk, .reset_ext, .reset, .HRDATAEXT, .HREADYEXT, .HRESPEXT, .HSELEXT, + wallypipelinedsoc #(P) dut(.clk, .reset_ext, .reset, .ExternalStall(RVVIStall), + .HRDATAEXT, .HREADYEXT, .HRESPEXT, .HSELEXT, .HCLK, .HRESETn, .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT, .HTRANS, .HMASTLOCK, .HREADY, .TIMECLK(1'b0), .GPIOIN, .GPIOOUT, .GPIOEN, .UARTSin, .UARTSout, .SPIIn, .SPIOut, .SPICS, .SPICLK, .SDCIn, .SDCCmd, .SDCCS, .SDCCLK); @@ -624,6 +626,22 @@ module testbench; clk = 1'b1; # 5; clk = 1'b0; # 5; end + if(RVVI_SYNTH_SUPPORTED) begin : rvvi_synth + localparam MAX_CSRS = 5; + localparam logic [31:0] RVVI_INIT_TIME_OUT = 32'd4; + localparam logic [31:0] RVVI_PACKET_DELAY = 32'd2; + + logic [3:0] mii_txd; + logic mii_tx_en, mii_tx_er; + + rvvitbwrapper #(P, MAX_CSRS, RVVI_INIT_TIME_OUT, RVVI_PACKET_DELAY) + rvvitbwrapper(.clk, .reset, .RVVIStall, .mii_tx_clk(clk), .mii_txd, .mii_tx_en, .mii_tx_er, + .mii_rx_clk(clk), .mii_rxd('0), .mii_rx_dv('0), .mii_rx_er('0)); + end else begin + assign RVVIStall = '0; + end + + /* // Print key info each cycle for debugging always @(posedge clk) begin diff --git a/testbench/wallywrapper.sv b/testbench/wallywrapper.sv index b326bb810..62c7b67e7 100644 --- a/testbench/wallywrapper.sv +++ b/testbench/wallywrapper.sv @@ -64,7 +64,8 @@ module wallywrapper import cvw::*;( logic HREADY; logic HSELEXT; - + + logic ExternalStall; // instantiate device to be tested assign GPIOIN = 0; @@ -74,10 +75,11 @@ module wallywrapper import cvw::*;( assign HRESPEXT = 0; assign HRDATAEXT = 0; + assign ExternalStall = '0; - wallypipelinedsoc #(P) dut(.clk, .reset_ext, .reset, .HRDATAEXT, .HREADYEXT, .HRESPEXT, .HSELEXT, - .HCLK, .HRESETn, .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT, - .HTRANS, .HMASTLOCK, .HREADY, .TIMECLK(1'b0), .GPIOIN, .GPIOOUT, .GPIOEN, - .UARTSin, .UARTSout, .SPIIn, .SPIOut, .SPICS, .SPICLK, .SDCIn, .SDCCmd, .SDCCS, .SDCCLK); + wallypipelinedsoc #(P) dut(.clk, .reset_ext, .reset, .ExternalStall, .HRDATAEXT,.HREADYEXT, .HRESPEXT,.HSELEXT, + .HCLK, .HRESETn, .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT, + .HTRANS, .HMASTLOCK, .HREADY, .TIMECLK(1'b0), .GPIOIN, .GPIOOUT, .GPIOEN, + .UARTSin, .UARTSout, .SPIIn, .SPIOut, .SPICS, .SPICLK, .SDCIn, .SDCCmd, .SDCCS, .SDCCLK); endmodule