Merge branch 'main' of github.com:openhwgroup/cvw into spiboot

This commit is contained in:
Jacob Pease 2024-08-06 17:09:39 -05:00
commit 11ca2567b8
36 changed files with 1632 additions and 54 deletions

1
.gitignore vendored
View File

@ -243,3 +243,4 @@ tests/functcov/*
tests/functcov/*/* tests/functcov/*/*
sim/vcs/simprofile* sim/vcs/simprofile*
sim/verilator/verilator.log sim/verilator/verilator.log
/fpga/rvvidaemon/rvvidaemon

4
.gitmodules vendored
View File

@ -30,3 +30,7 @@
[submodule "addins/ahbsdc"] [submodule "addins/ahbsdc"]
path = addins/ahbsdc path = addins/ahbsdc
url = http://github.com/JacobPease/ahbsdc.git 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

3
addins/README.md Normal file
View File

@ -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.

17
addins/sparse-checkout Normal file
View File

@ -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

@ -0,0 +1 @@
Subproject commit c180b22ed5f4112d0ef35b2c5ac1acc45f9ebb5d

View File

@ -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("--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("--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("--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() args = parser.parse_args()
print("Config=" + args.config + " tests=" + args.testsuite + " sim=" + args.sim + " gui=" + str(args.gui) + " args='" + args.args + "'") print("Config=" + args.config + " tests=" + args.testsuite + " sim=" + args.sim + " gui=" + str(args.gui) + " args='" + args.args + "'")
ElfFile="" ElfFile=""
@ -64,6 +65,9 @@ if (args.gui or args.ccov or args.fcov or args.lockstep):
if (args.vcd): if (args.vcd):
args.args += " -DMAKEVCD=1" 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 lockstep is enabled, then we need to pass the Imperas lockstep arguments
if(int(args.locksteplog) >= 1): EnableLog = 1 if(int(args.locksteplog) >= 1): EnableLog = 1
else: EnableLog = 0 else: EnableLog = 0

View File

@ -1658,7 +1658,7 @@ IDIV_ON_FPU 1
# imperas used for a smart memory # imperas used for a smart memory
# VCS doesn't like removing the bootrom, but make it tiny in a random unused location # 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 ICACHE_SUPPORTED 0
DCACHE_SUPPORTED 0 DCACHE_SUPPORTED 0
VIRTMEM_SUPPORTED 0 VIRTMEM_SUPPORTED 0
@ -1669,6 +1669,13 @@ ZICBOM_SUPPORTED 0
ZICBOZ_SUPPORTED 0 ZICBOZ_SUPPORTED 0
SVPBMT_SUPPORTED 0 SVPBMT_SUPPORTED 0
SVNAPOT_SUPPORTED 0 SVNAPOT_SUPPORTED 0
BOOTROM_BASE 64'h700012340010 BOOTROM_BASE 64'h700012340080
BOOTROM_RANGE 64'h10 BOOTROM_RANGE 64'h10
CLINT_SUPPORTED 0
GPIO_SUPPORTED 0
UART_SUPPORTED 0
PLIC_SUPPORTED 0
SPI_SUPPORTED 0

View File

@ -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 PACKAGE_PIN E3 [get_ports {default_100mhz_clk}]
set_property IOSTANDARD LVCMOS33 [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 #### ##### GPI ####
set_property PACKAGE_PIN A8 [get_ports {GPI[0]}] set_property PACKAGE_PIN A8 [get_ports {GPI[0]}]
set_property PACKAGE_PIN C9 [get_ports {GPI[1]}] set_property PACKAGE_PIN C9 [get_ports {GPI[1]}]

View File

@ -7,3 +7,4 @@ lsu/lsu.sv: logic PAdrM
lsu/lsu.sv: logic ReadDataM lsu/lsu.sv: logic ReadDataM
lsu/lsu.sv: logic WriteDataM lsu/lsu.sv: logic WriteDataM
lsu/lsu.sv: logic MemRWM lsu/lsu.sv: logic MemRWM
privileged/csrc.sv: logic HPMCOUNTER_REGW

View File

@ -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]

View File

@ -51,6 +51,8 @@ PreProcessFiles:
$(MAKE) -C ../../sim deriv $(MAKE) -C ../../sim deriv
rm -rf ../src/CopiedFiles_do_not_add_to_repo/ rm -rf ../src/CopiedFiles_do_not_add_to_repo/
cp -r ../../src/ ../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/ mkdir ../src/CopiedFiles_do_not_add_to_repo/config/
cp ../../config/deriv/fpga/config.vh ../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 ./insert_debug_comment.sh

View File

@ -90,7 +90,7 @@ write_verilog -force -mode funcsim sim/syn-funcsim.v
if {$board=="ArtyA7"} { if {$board=="ArtyA7"} {
#source ../constraints/small-debug.xdc #source ../constraints/small-debug.xdc
source ../constraints/medium-debug.xdc source ../constraints/small-debug-rvvi.xdc
} else { } else {
# source ../constraints/vcu-small-debug.xdc # source ../constraints/vcu-small-debug.xdc
source ../constraints/debug6.xdc source ../constraints/debug6.xdc

View File

@ -12,10 +12,11 @@ set_property -dict [list CONFIG.PRIM_IN_FREQ {100.000} \
CONFIG.NUM_OUT_CLKS {3} \ CONFIG.NUM_OUT_CLKS {3} \
CONFIG.CLKOUT2_USED {true} \ CONFIG.CLKOUT2_USED {true} \
CONFIG.CLKOUT3_USED {true} \ CONFIG.CLKOUT3_USED {true} \
CONFIG.CLKOUT4_USED {false} \ CONFIG.CLKOUT4_USED {true} \
CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {166.66667} \ CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {166.66667} \
CONFIG.CLKOUT2_REQUESTED_OUT_FREQ {200} \ CONFIG.CLKOUT2_REQUESTED_OUT_FREQ {200} \
CONFIG.CLKOUT3_REQUESTED_OUT_FREQ {20} \ CONFIG.CLKOUT3_REQUESTED_OUT_FREQ {20} \
CONFIG.CLKOUT4_REQUESTED_OUT_FREQ {25} \
CONFIG.CLKIN1_JITTER_PS {10.0} \ CONFIG.CLKIN1_JITTER_PS {10.0} \
] [get_ips $ipName] ] [get_ips $ipName]

10
fpga/rvvidaemon/Makefile Normal file
View File

@ -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

View File

@ -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 <arpa/inet.h>
#include <linux/if_packet.h>
#include <linux/ip.h>
#include <linux/udp.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <net/if.h>
#include <netinet/ether.h>
#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 <ethernet device>\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;i<tx_len;i++){
printf("%02hhx ", sendbuf[i]);
}
printf("\n");
printf("sockfd %x\n", sockfd);
// eventually we want to put the elffiles here
rvviRefInit(NULL);
rvviRefPcSet(0, 0x1000);
// Volatile CSRs
rvviRefCsrSetVolatile(0, 0xC00); // CYCLE
rvviRefCsrSetVolatile(0, 0xB00); // MCYCLE
rvviRefCsrSetVolatile(0, 0xC02); // INSTRET
rvviRefCsrSetVolatile(0, 0xB02); // MINSTRET
rvviRefCsrSetVolatile(0, 0xC01); // TIME
int iter;
for (iter = 0xC03; iter <= 0xC1F; iter++) {
rvviRefCsrSetVolatile(0, iter); // HPMCOUNTERx
}
// Machine MHPMCOUNTER3 - MHPMCOUNTER31
for (iter = 0xB03; iter <= 0xB1F; iter++) {
rvviRefCsrSetVolatile(0, iter); // MHPMCOUNTERx
}
// cannot predict this register due to latency between
// pending and taken
rvviRefCsrSetVolatile(0, 0x344); // MIP
rvviRefCsrSetVolatile(0, 0x144); // SIP
// set bootrom and bootram as volatile memory
rvviRefMemorySetVolatile(0x1000, 0x1FFF);
rvviRefMemorySetVolatile(0x2000, 0x2FFF);
// Privileges for PMA are set in the imperas.ic
// volatile (IO) regions are defined here
// only real ROM/RAM areas are BOOTROM and UNCORE_RAM
rvviRefMemorySetVolatile(0x2000000, 0x2000000 + 0xFFFF);
rvviRefMemorySetVolatile(0x10060000, 0x10060000 + 0xFF);
rvviRefMemorySetVolatile(0x10000000, 0x10000000 + 0x7);
rvviRefMemorySetVolatile(0x0C000000, 0x0C000000 + 0x03FFFFFF);
rvviRefMemorySetVolatile(0x00013000, 0x00013000 + 0x7F);
rvviRefMemorySetVolatile(0x10040000, 0x10040000 + 0xFFF);
while(1) {
//printf("listener: Waiting to recvfrom...\n");
numbytes = recvfrom(sockfd, buf, BUF_SIZ, 0, NULL, NULL);
headerbytes = (sizeof(struct ether_header));
payloadbytes = numbytes - headerbytes;
int result;
//printf("listener: got frame %lu bytes\n", numbytes);
//printf("payload size: %lu bytes\n", payloadbytes);
if (eh->ether_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;
}

View File

@ -28,10 +28,10 @@
import cvw::*; import cvw::*;
module fpgaTop module fpgaTop #(parameter logic RVVI_SYNTH_SUPPORTED = 1)
(input default_100mhz_clk, (input default_100mhz_clk,
input resetn, (* mark_debug = "true" *) input resetn,
input south_reset, input south_reset,
// GPIO signals // GPIO signals
input [3:0] GPI, input [3:0] GPI,
@ -48,23 +48,36 @@ module fpgaTop
output SDCCS, output SDCCS,
input SDCCD, input SDCCD,
input SDCWP, 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 [15:0] ddr3_dq, inout [1:0] ddr3_dqs_n,
inout [1:0] ddr3_dqs_n, inout [1:0] ddr3_dqs_p,
inout [1:0] ddr3_dqs_p, output [13:0] ddr3_addr,
output [13:0] ddr3_addr, output [2:0] ddr3_ba,
output [2:0] ddr3_ba, output ddr3_ras_n,
output ddr3_ras_n, output ddr3_cas_n,
output ddr3_cas_n, output ddr3_we_n,
output ddr3_we_n, output ddr3_reset_n,
output ddr3_reset_n, output [0:0] ddr3_ck_p,
output [0:0] ddr3_ck_p, output [0:0] ddr3_ck_n,
output [0:0] ddr3_ck_n, output [0:0] ddr3_cke,
output [0:0] ddr3_cke, output [0:0] ddr3_cs_n,
output [0:0] ddr3_cs_n, output [1:0] ddr3_dm,
output [1:0] ddr3_dm, output [0:0] ddr3_odt
output [0:0] ddr3_odt
); );
// MMCM Signals // MMCM Signals
@ -193,7 +206,8 @@ module fpgaTop
wire mmcm_locked; wire mmcm_locked;
wire [11:0] device_temp; wire [11:0] device_temp;
wire mmcm1_locked; wire mmcm1_locked;
(* mark_debug = "true" *) logic RVVIStall;
assign GPIOIN = {25'b0, SDCCD, SDCWP, 1'b0, GPI}; assign GPIOIN = {25'b0, SDCCD, SDCWP, 1'b0, GPI};
assign GPO = GPIOOUT[4:0]; assign GPO = GPIOOUT[4:0];
@ -214,6 +228,7 @@ module fpgaTop
xlnx_mmcm xln_mmcm(.clk_out1(clk167), xlnx_mmcm xln_mmcm(.clk_out1(clk167),
.clk_out2(clk200), .clk_out2(clk200),
.clk_out3(CPUCLK), .clk_out3(CPUCLK),
.clk_out4(phy_ref_clk),
.reset(1'b0), .reset(1'b0),
.locked(mmcm1_locked), .locked(mmcm1_locked),
.clk_in1(default_100mhz_clk)); .clk_in1(default_100mhz_clk));
@ -243,7 +258,7 @@ module fpgaTop
.HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT, .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT,
.HTRANS, .HMASTLOCK, .HREADY, .TIMECLK(1'b0), .HTRANS, .HMASTLOCK, .HREADY, .TIMECLK(1'b0),
.GPIOIN, .GPIOOUT, .GPIOEN, .GPIOIN, .GPIOOUT, .GPIOEN,
.UARTSin, .UARTSout, .SDCIn, .SDCCmd, .SDCCS(SDCCSin), .SDCCLK); .UARTSin, .UARTSout, .SDCIn, .SDCCmd, .SDCCS(SDCCSin), .SDCCLK, .ExternalStall(RVVIStall));
// ahb lite to axi bridge // ahb lite to axi bridge
@ -461,7 +476,146 @@ module fpgaTop
.init_calib_complete(c0_init_calib_complete), .init_calib_complete(c0_init_calib_complete),
.device_temp(device_temp)); .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 endmodule

View File

@ -197,7 +197,7 @@ set temp3 [lindex $PlusArgs 3]
# "Extra checking for conflicts with always_comb done at vopt time" # "Extra checking for conflicts with always_comb done at vopt time"
# because vsim will run vopt # 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 # start and run simulation
# remove +acc flag for faster sim during regressions if there is no need to access internal signals # remove +acc flag for faster sim during regressions if there is no need to access internal signals

View File

@ -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 -expand -group testbench /testbench/DCacheFlushStart
add wave -noupdate /testbench/dut/core/lsu/hptw/hptw/HPTWLoadPageFault add wave -noupdate /testbench/dut/core/lsu/hptw/hptw/HPTWLoadPageFault
add wave -noupdate /testbench/dut/core/lsu/hptw/hptw/HPTWLoadPageFaultDelay 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] TreeUpdate [SetDefaultTree]
WaveRestoreCursors {{Cursor 4} {6586 ns} 1} {{Cursor 4} {2112952 ns} 0} {{Cursor 3} {403021 ns} 1} 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 2 quietly wave cursor active 4
configure wave -namecolwidth 250 configure wave -namecolwidth 250
configure wave -valuecolwidth 194 configure wave -valuecolwidth 194
configure wave -justifyvalue left configure wave -justifyvalue left
@ -674,4 +690,4 @@ configure wave -griddelta 40
configure wave -timeline 0 configure wave -timeline 0
configure wave -timelineunits ns configure wave -timelineunits ns
update update
WaveRestoreZoom {2039338 ns} {2323972 ns} WaveRestoreZoom {0 ns} {1033211 ns}

View File

@ -25,7 +25,7 @@ TARGET=$(WORKING_DIR)/target
# INCLUDE_PATH are pathes that Verilator should search for files it needs # 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)" INCLUDE_PATH="-I${WALLY}/config/shared" "-I${WALLY}/config/$(WALLYCONF)" "-I${WALLY}/config/deriv/$(WALLYCONF)"
# SOURCES are source files # 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 are configuration files and source files, which leads to recompilation of executables
DEPENDENCIES=${WALLY}/config/shared/*.vh $(SOURCES) DEPENDENCIES=${WALLY}/config/shared/*.vh $(SOURCES)

View File

@ -296,7 +296,6 @@ typedef struct packed {
int DIVBLEN ; int DIVBLEN ;
// integer division/remainder constants // integer division/remainder constants
int INTDIVb ; int INTDIVb ;
} cvw_t; } cvw_t;
endpackage endpackage

View File

@ -81,6 +81,7 @@ module fctrl import cvw::*; #(parameter cvw_t P) (
logic [1:0] Fmt, Fmt2; // format - before possible reduction logic [1:0] Fmt, Fmt2; // format - before possible reduction
logic SupportedFmt; // is the format supported logic SupportedFmt; // is the format supported
logic SupportedFmt2; // is the source format supported for fp -> fp 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 FCvtIntD, FCvtIntM; // convert to integer operation
logic ZfaD; // Zfa variants of instructions logic ZfaD; // Zfa variants of instructions
logic ZfaFRoundNXD; // Zfa froundnx instruction 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)); (Fmt == 2'b10 & P.ZFH_SUPPORTED) | (Fmt == 2'b11 & P.Q_SUPPORTED));
assign SupportedFmt2 = (Fmt2 == 2'b00 | (Fmt2 == 2'b01 & P.D_SUPPORTED) | assign SupportedFmt2 = (Fmt2 == 2'b00 | (Fmt2 == 2'b01 & P.D_SUPPORTED) |
(Fmt2 == 2'b10 & P.ZFH_SUPPORTED) | (Fmt2 == 2'b11 & P.Q_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 // decode the instruction
// FRegWrite_FWriteInt_FResSel_PostProcSel_FOpCtrl_FDivStart_IllegalFPUInstr_FCvtInt_Zfa_FroundNX // FRegWrite_FWriteInt_FResSel_PostProcSel_FOpCtrl_FDivStart_IllegalFPUInstr_FCvtInt_Zfa_FroundNX
always_comb always_comb
if (STATUS_FS == 2'b00) // FPU instructions are illegal when FPU is disabled 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; ControlsD = `FCTRLW'b0_0_00_00_000_0_1_0_0_0;
else if (OpD != 7'b0000111 & OpD != 7'b0100111 & ~SupportedFmt) 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 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 else begin
ControlsD = `FCTRLW'b0_0_00_00_000_0_1_0_0_0; // default: non-implemented instruction 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 /* verilator lint_off CASEINCOMPLETE */ // default value above has priority so no other default needed

View File

@ -31,7 +31,7 @@ module hazard import cvw::*; #(parameter cvw_t P) (
input logic BPWrongE, CSRWriteFenceM, RetM, TrapM, input logic BPWrongE, CSRWriteFenceM, RetM, TrapM,
input logic StructuralStallD, input logic StructuralStallD,
input logic LSUStallM, IFUStallF, input logic LSUStallM, IFUStallF,
input logic FPUStallD, input logic FPUStallD, ExternalStall,
input logic DivBusyE, FDivBusyE, input logic DivBusyE, FDivBusyE,
input logic wfiM, IntPendingM, input logic wfiM, IntPendingM,
// Stall & flush outputs // 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. // Need to gate IFUStallF when the equivalent FlushFCause = FlushDCause = 1.
// assign StallWCause = ((IFUStallF & ~FlushDCause) | LSUStallM) & ~FlushWCause; // assign StallWCause = ((IFUStallF & ~FlushDCause) | LSUStallM) & ~FlushWCause;
// Because FlushWCause is a strict subset of FlushDCause, FlushWCause is factored out. // 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 // Stall each stage for cause or if the next stage is stalled
// coverage off: StallFCause is always 0 // coverage off: StallFCause is always 0

View File

@ -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 if ((P.ZKND_SUPPORTED | P.ZKNE_SUPPORTED) & P.XLEN == 64) begin // ZKND and ZKNE shared instructions
casez({OpD, Funct7D, Funct3D}) 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 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 17'b0110011_0111111_000: BMUControlsD = `BMUCTRLW'b000_0111_0011_1_0_0_0_1_0_0_0_0_0; // aes64ks2 - key schedule istr2
endcase endcase

View File

@ -106,7 +106,10 @@ module csrm import cvw::*; #(parameter cvw_t P) (
genvar i; genvar i;
if (P.PMP_ENTRIES > 0) begin:pmp if (P.PMP_ENTRIES > 0) begin:pmp
logic [P.PMP_ENTRIES-1:0] WritePMPCFGM; 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; logic [P.PMP_ENTRIES-1:0] ADDRLocked, CFGLocked;
for(i=0; i<P.PMP_ENTRIES; i++) begin for(i=0; i<P.PMP_ENTRIES; i++) begin
// when the lock bit is set, don't allow writes to the PMPCFG or PMPADDR // when the lock bit is set, don't allow writes to the PMPCFG or PMPADDR
@ -121,11 +124,15 @@ module csrm import cvw::*; #(parameter cvw_t P) (
flopenr #(P.PA_BITS-2) PMPADDRreg(clk, reset, WritePMPADDRM[i], CSRWriteValM[P.PA_BITS-3:0], PMPADDR_ARRAY_REGW[i]); flopenr #(P.PA_BITS-2) PMPADDRreg(clk, reset, WritePMPADDRM[i], CSRWriteValM[P.PA_BITS-3:0], PMPADDR_ARRAY_REGW[i]);
if (P.XLEN==64) begin if (P.XLEN==64) begin
assign WritePMPCFGM[i] = (CSRMWriteM & (CSRAdrM == (PMPCFG0+2*(i/8)))) & ~CFGLocked[i]; assign WritePMPCFGM[i] = (CSRMWriteM & (CSRAdrM == (PMPCFG0+2*(i/8)))) & ~CFGLocked[i];
flopenr #(8) PMPCFGreg(clk, reset, WritePMPCFGM[i], CSRWriteValM[(i%8)*8+7:(i%8)*8], PMPCFG_ARRAY_REGW[i]); assign CSRPMPWriteValM[i] = CSRWriteValM[(i%8)*8+7:(i%8)*8];
end else begin end else begin
assign WritePMPCFGM[i] = (CSRMWriteM & (CSRAdrM == (PMPCFG0+i/4))) & ~CFGLocked[i]; assign WritePMPCFGM[i] = (CSRMWriteM & (CSRAdrM == (PMPCFG0+i/4))) & ~CFGLocked[i];
flopenr #(8) PMPCFGreg(clk, reset, WritePMPCFGM[i], CSRWriteValM[(i%4)*8+7:(i%4)*8], PMPCFG_ARRAY_REGW[i]); assign CSRPMPWriteValM[i] = CSRWriteValM[(i%4)*8+7:(i%4)*8];
end end
assign CSRPMPWRLegalizedWriteValM[i] = {(CSRPMPWriteValM[i][1] & CSRPMPWriteValM[i][0]), CSRPMPWriteValM[i][0]}; // legalize WR fields (reserved 10 written as 00)
assign CSRPMPLegalizedWriteValM[i] = {CSRPMPWriteValM[i][7], 2'b00, CSRPMPWriteValM[i][4:2], CSRPMPWRLegalizedWriteValM[i]};
flopenr #(8) PMPCFGreg(clk, reset, WritePMPCFGM[i], CSRPMPWriteValM[i], PMPCFG_ARRAY_REGW[i]);
end end
end end

View File

@ -0,0 +1,77 @@
///////////////////////////////////////////
// csrindextoaddr.sv
//
// Written: Rose Thompson ross1728@gmail.com
// Created: 24 January 2024
// Modified: 24 January 2024
//
// Purpose: Converts the rvvi CSR index into the CSR address
//
// Documentation:
//
// A component of the CORE-V-WALLY configurable RISC-V project.
//
// 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.
////////////////////////////////////////////////////////////////////////////////////////////////
module csrindextoaddr #(parameter TOTAL_CSRS = 36) (
input logic [TOTAL_CSRS-1:0] CSRWen,
output logic [11:0] CSRAddr);
always_comb begin
case(CSRWen)
36'h0_0000_0000: CSRAddr = 12'h000;
36'h0_0000_0001: CSRAddr = 12'h300;
36'h0_0000_0002: CSRAddr = 12'h310;
36'h0_0000_0004: CSRAddr = 12'h305;
36'h0_0000_0008: CSRAddr = 12'h341;
36'h0_0000_0010: CSRAddr = 12'h306;
36'h0_0000_0020: CSRAddr = 12'h320;
36'h0_0000_0040: CSRAddr = 12'h302;
36'h0_0000_0080: CSRAddr = 12'h303;
36'h0_0000_0100: CSRAddr = 12'h344;
36'h0_0000_0200: CSRAddr = 12'h304;
36'h0_0000_0400: CSRAddr = 12'h301;
36'h0_0000_0800: CSRAddr = 12'h30A;
36'h0_0000_1000: CSRAddr = 12'hF14;
36'h0_0000_2000: CSRAddr = 12'h340;
36'h0_0000_4000: CSRAddr = 12'h342;
36'h0_0000_8000: CSRAddr = 12'h343;
36'h0_0001_0000: CSRAddr = 12'hF11;
36'h0_0002_0000: CSRAddr = 12'hF12;
36'h0_0004_0000: CSRAddr = 12'hF13;
36'h0_0008_0000: CSRAddr = 12'hF15;
36'h0_0010_0000: CSRAddr = 12'h34A;
36'h0_0020_0000: CSRAddr = 12'h100;
36'h0_0040_0000: CSRAddr = 12'h104;
36'h0_0080_0000: CSRAddr = 12'h105;
36'h0_0100_0000: CSRAddr = 12'h141;
36'h0_0200_0000: CSRAddr = 12'h106;
36'h0_0400_0000: CSRAddr = 12'h10A;
36'h0_0800_0000: CSRAddr = 12'h180;
36'h0_1000_0000: CSRAddr = 12'h140;
36'h0_2000_0000: CSRAddr = 12'h143;
36'h0_4000_0000: CSRAddr = 12'h142;
36'h0_8000_0000: CSRAddr = 12'h144;
36'h1_0000_0000: CSRAddr = 12'h14D;
36'h2_0000_0000: CSRAddr = 12'h001;
36'h4_0000_0000: CSRAddr = 12'h002;
36'h8_0000_0000: CSRAddr = 12'h003;
default : CSRAddr = 12'h000;
endcase
end
endmodule

141
src/rvvi/packetizer.sv Normal file
View File

@ -0,0 +1,141 @@
///////////////////////////////////////////
// packetizer.sv
//
// Written: Rose Thompson ross1728@gmail.com
// Created: 21 May 2024
// Modified: 21 May 2024
//
// Purpose: Converts the compressed RVVI format into AXI 4 burst write transactions.
//
// Documentation:
//
// A component of the CORE-V-WALLY configurable RISC-V project.
//
// 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.
////////////////////////////////////////////////////////////////////////////////////////////////
module packetizer import cvw::*; #(parameter cvw_t P,
parameter integer MAX_CSRS,
parameter logic [31:0] RVVI_INIT_TIME_OUT = 32'd4,
parameter logic [31:0] RVVI_PACKET_DELAY = 32'd2
)(
input logic [187+(3*P.XLEN) + MAX_CSRS*(P.XLEN+12)-1:0] rvvi,
input logic valid,
input logic m_axi_aclk, m_axi_aresetn,
output logic RVVIStall,
// axi 4 write address channel
// axi 4 write data channel
output logic [31:0] RvviAxiWdata,
output logic [3:0] RvviAxiWstrb,
output logic RvviAxiWlast,
output logic RvviAxiWvalid,
input logic RvviAxiWready
);
localparam TotalFrameLengthBits = 2*48+17+16+187+(3*P.XLEN) + MAX_CSRS*(P.XLEN+12);
localparam TotalFrameLengthBytes = TotalFrameLengthBits / 8;
logic [9:0] WordCount;
logic [11:0] BytesInFrame;
logic TransReady;
logic BurstDone;
logic WordCountReset;
logic WordCountEnable;
logic [47:0] SrcMac, DstMac;
logic [15:0] EthType, Length;
logic [31:0] Tag;
logic [TotalFrameLengthBits-1:0] TotalFrame;
logic [31:0] TotalFrameWords [TotalFrameLengthBytes/4-1:0];
logic [187+(3*P.XLEN) + MAX_CSRS*(P.XLEN+12)-1:0] rvviDelay;
typedef enum {STATE_RST, STATE_COUNT, STATE_RDY, STATE_WAIT, STATE_TRANS, STATE_TRANS_INSERT_DELAY} statetype;
(* mark_debug = "true" *) statetype CurrState, NextState;
logic [31:0] RstCount;
(* mark_debug = "true" *) logic [31:0] FrameCount;
logic RstCountRst, RstCountEn, CountFlag, DelayFlag;
always_ff @(posedge m_axi_aclk) begin
if(~m_axi_aresetn) CurrState <= STATE_RST;
else CurrState <= NextState;
end
always_comb begin
case(CurrState)
STATE_RST: NextState = STATE_COUNT;
STATE_COUNT: if (CountFlag) NextState = STATE_RDY;
else NextState = STATE_COUNT;
STATE_RDY: if (TransReady & valid) NextState = STATE_TRANS;
else if(~TransReady & valid) NextState = STATE_WAIT;
else NextState = STATE_RDY;
STATE_WAIT: if(TransReady) NextState = STATE_TRANS;
else NextState = STATE_WAIT;
STATE_TRANS: if(BurstDone & TransReady) NextState = STATE_TRANS_INSERT_DELAY;
else NextState = STATE_TRANS;
STATE_TRANS_INSERT_DELAY: if(DelayFlag) NextState = STATE_RDY;
else NextState = STATE_TRANS_INSERT_DELAY;
default: NextState = STATE_RDY;
endcase
end
assign RVVIStall = CurrState != STATE_RDY;
assign TransReady = RvviAxiWready;
assign WordCountEnable = (CurrState == STATE_RDY & valid) | (CurrState == STATE_TRANS & TransReady);
assign WordCountReset = CurrState == STATE_RDY;
assign RstCountEn = CurrState == STATE_COUNT | CurrState == STATE_TRANS_INSERT_DELAY;
assign RstCountRst = CurrState == STATE_RST | CurrState == STATE_TRANS;
// have to count at least 250 ms after reset pulled to wait for the phy to actually be ready
// at 20MHz 250 ms is 250e-3 / (1/20e6) = 5,000,000.
counter #(32) rstcounter(m_axi_aclk, RstCountRst, RstCountEn, RstCount);
assign CountFlag = RstCount == RVVI_INIT_TIME_OUT;
assign DelayFlag = RstCount == RVVI_PACKET_DELAY;
counter #(32) framecounter(m_axi_aclk, ~m_axi_aresetn, (RvviAxiWready & RvviAxiWlast), FrameCount);
flopenr #(187+(3*P.XLEN) + MAX_CSRS*(P.XLEN+12)) rvvireg(m_axi_aclk, ~m_axi_aresetn, valid, rvvi, rvviDelay);
counter #(10) WordCounter(m_axi_aclk, WordCountReset, WordCountEnable, WordCount);
// *** BUG BytesInFrame will eventually depend on the length of the data stored into the ethernet frame
// for now this will be exactly 608 bits (76 bytes, 19 words) + the ethernet frame overhead and 2-byte padding = 92-bytes
assign BytesInFrame = 12'd2 + 12'd76 + 12'd6 + 12'd6 + 12'd2;
assign BurstDone = WordCount == (BytesInFrame[11:2] - 1'b1);
genvar index;
for (index = 0; index < TotalFrameLengthBytes/4; index++) begin
assign TotalFrameWords[index] = TotalFrame[(index*32)+32-1 : (index*32)];
end
assign Length = {4'b0, BytesInFrame};
assign TotalFrame = {17'b0, rvviDelay, EthType, DstMac, SrcMac};
// *** fix me later
assign DstMac = 48'h8F54_0000_1654; // made something up
assign SrcMac = 48'h4502_1111_6843;
assign Tag = 32'b0;
assign EthType = 16'h005c;
assign RvviAxiWdata = TotalFrameWords[WordCount[4:0]];
assign RvviAxiWstrb = '1;
assign RvviAxiWlast = BurstDone & (CurrState == STATE_TRANS);
assign RvviAxiWvalid = (CurrState == STATE_TRANS);
endmodule

46
src/rvvi/priorityaomux.sv Normal file
View File

@ -0,0 +1,46 @@
///////////////////////////////////////////
// priorityaomux.sv
//
// Written: Rose Thompson ross1728@gmail.com
// Created: 24 January 2024
// Modified: 24 January 2024
//
// Purpose: priority AND-OR MUX.
//
// Documentation:
//
// A component of the CORE-V-WALLY configurable RISC-V project.
//
// 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.
////////////////////////////////////////////////////////////////////////////////////////////////
module priorityaomux #(parameter ROWS = 8, COLS = 64) (
input logic [ROWS-1:0] Sel,
input var logic [COLS-1:0] A [ROWS-1:0],
output logic [COLS-1:0] Y,
output logic [ROWS-1:0] SelPriority);
logic [COLS-1:0] AMasked [ROWS-1:0];
genvar index;
priorityonehot #(ROWS) priorityonehot(Sel, SelPriority);
for(index = 0; index < ROWS; index = index + 1) begin
assign AMasked[index] = SelPriority[index] ? A[index] : '0;
end
or_rows #(ROWS, COLS) or_rows(AMasked, Y);
endmodule

View File

@ -0,0 +1,41 @@
///////////////////////////////////////////
// regchangedetect.sv
//
// Written: Rose Thompson ross1728@gmail.com
// Created: 24 January 2024
// Modified: 24 January 2024
//
// Purpose:
//
// Documentation:
//
// A component of the CORE-V-WALLY configurable RISC-V project.
//
// 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.
////////////////////////////////////////////////////////////////////////////////////////////////
module regchangedetect #(parameter XLEN = 64) (
input clk, reset,
input logic [XLEN-1:0] Value,
output logic Change);
logic [XLEN-1:0] ValueD;
flopr #(XLEN) register(clk, reset, Value, ValueD);
assign Change = |(Value ^ ValueD);
endmodule

138
src/rvvi/rvvisynth.sv Normal file
View File

@ -0,0 +1,138 @@
///////////////////////////////////////////
// rvvisynth.sv
//
// Written: Rose Thompson ross1728@gmail.com
// Created: 23 January 2024
// Modified: 23 January 2024
//
// Purpose: Synthesizable rvvi bridge from Wally to generic compressed format.
//
// Documentation:
//
// A component of the CORE-V-WALLY configurable RISC-V project.
//
// 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.
////////////////////////////////////////////////////////////////////////////////////////////////
module rvvisynth import cvw::*; #(parameter cvw_t P,
parameter integer MAX_CSRS = 5,
parameter integer TOTAL_CSRS = 36)(
input logic clk, reset,
input logic StallE, StallM, StallW, FlushE, FlushM, FlushW,
// required
input logic [P.XLEN-1:0] PCM,
input logic InstrValidM,
input logic [31:0] InstrRawD,
input logic [63:0] Mcycle, Minstret,
input logic TrapM,
input logic [1:0] PrivilegeModeW,
// registers gpr and fpr
input logic GPRWen, FPRWen,
input logic [4:0] GPRAddr, FPRAddr,
input logic [P.XLEN-1:0] GPRValue, FPRValue,
input var logic [P.XLEN-1:0] CSRArray [TOTAL_CSRS-1:0],
output logic valid,
output logic [187+(3*P.XLEN) + MAX_CSRS*(P.XLEN+12)-1:0] rvvi
);
// pipeline controlls
// required
logic [P.XLEN-1:0] PCW;
logic InstrValidW;
logic [31:0] InstrRawE, InstrRawM, InstrRawW;
logic TrapW;
// registers gpr and fpr
logic [P.XLEN-1:0] XLENZeros;
logic [TOTAL_CSRS-1:0] CSRArrayWen;
logic [P.XLEN-1:0] CSRValue [MAX_CSRS-1:0];
logic [TOTAL_CSRS-1:0] CSRWen [MAX_CSRS-1:0];
logic [11:0] CSRAddr [MAX_CSRS-1:0];
logic [MAX_CSRS-1:0] EnabledCSRs;
logic [MAX_CSRS-1:0] CSRCountShort;
logic [11:0] CSRCount;
logic [177+P.XLEN-1:0] Required;
logic [10+2*P.XLEN-1:0] Registers;
logic [MAX_CSRS*(P.XLEN+12)-1:0] CSRs;
assign XLENZeros = '0;
// start out easy and just populate Required
// PC, inst, mcycle, minstret, trap, mode
flopenrc #(1) InstrValidMReg (clk, reset, FlushW, ~StallW, InstrValidM, InstrValidW);
flopenrc #(P.XLEN) PCWReg (clk, reset, FlushW, ~StallW, PCM, PCW);
flopenrc #(32) InstrRawEReg (clk, reset, FlushE, ~StallE, InstrRawD, InstrRawE);
flopenrc #(32) InstrRawMReg (clk, reset, FlushM, ~StallM, InstrRawE, InstrRawM);
flopenrc #(32) InstrRawWReg (clk, reset, FlushW, ~StallW, InstrRawM, InstrRawW);
flopenrc #(1) TrapWReg (clk, reset, 1'b0, ~StallW, TrapM, TrapW);
assign valid = InstrValidW & ~StallW;
assign Required = {CSRCount, FPRWen, GPRWen, PrivilegeModeW, TrapW, Minstret, Mcycle, InstrRawW, PCW};
assign Registers = {FPRWen, GPRWen} == 2'b11 ? {FPRValue, FPRAddr, GPRValue, GPRAddr} :
{FPRWen, GPRWen} == 2'b01 ? {XLENZeros, 5'b0, GPRValue, GPRAddr} :
{FPRWen, GPRWen} == 2'b10 ? {XLENZeros, 5'b0, FPRValue, FPRAddr} :
'0;
/* verilator lint_off UNOPTFLAT */
// For some reason verilator complains about CSRWenFilterMatrix being in a circular loop when it is not.
// the CSRs are complex
// 1. we need to get the CSR values
// 2. we check if the CSR value changes by registering the value then XORing with the old value.
// 3. Then use priorityaomux to collect CSR values and addresses for compating into the compressed rvvi format
// step 2
genvar index;
for (index = 0; index < TOTAL_CSRS; index = index + 1) begin
regchangedetect #(P.XLEN) changedetect(clk, reset, CSRArray[index], CSRArrayWen[index]);
end
// step 3a
logic [TOTAL_CSRS-1:0] CSRWenPriorityMatrix [MAX_CSRS-1:0];
logic [TOTAL_CSRS-1:0] CSRWenFilterMatrix [MAX_CSRS-1:0];
priorityaomux #(TOTAL_CSRS, P.XLEN) firstpriorityaomux(CSRArrayWen, CSRArray, CSRValue[0], CSRWenPriorityMatrix[0]);
assign CSRWenFilterMatrix[0] = CSRArrayWen;
for(index = 1; index < MAX_CSRS; index = index + 1) begin
priorityaomux #(TOTAL_CSRS, P.XLEN) priorityaomux(CSRWenFilterMatrix[index], CSRArray, CSRValue[index], CSRWenPriorityMatrix[index]);
assign CSRWenFilterMatrix[index] = CSRWenFilterMatrix[index-1] & ~CSRWenPriorityMatrix[index-1];
end
for(index = 0; index < MAX_CSRS; index = index + 1) begin
// step 3b
csrindextoaddr #(TOTAL_CSRS) csrindextoaddr(CSRWenPriorityMatrix[index], CSRAddr[index]);
assign CSRs[(index+1) * (P.XLEN + 12)- 1: index * (P.XLEN + 12)] = {CSRValue[index], CSRAddr[index]};
assign EnabledCSRs[index] = |CSRWenPriorityMatrix[index];
end
integer index2;
always_comb begin
CSRCountShort = '0;
for(index2 = 0; index2 < MAX_CSRS; index2++) begin
/* verilator lint_off WIDTHEXPAND */
CSRCountShort += EnabledCSRs[index2];
/* verilator lint_on WIDTHEXPAND */
end
end
/* verilator lint_on UNOPTFLAT */
assign CSRCount = {{{12-MAX_CSRS}{1'b0}}, CSRCountShort};
assign rvvi = {CSRs, Registers, Required};
endmodule

110
src/rvvi/triggergen.sv Normal file
View File

@ -0,0 +1,110 @@
///////////////////////////////////////////
// triggergen.sv
//
// Written: Rose Thompson ross1728@gmail.com
// Created: June 26, 2024
// Modified: June 26, 2024
//
// Purpose: Scans for specific ethernet frame to generate an ila trigger.
//
// Documentation:
//
// A component of the CORE-V-WALLY configurable RISC-V project.
//
// 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.
////////////////////////////////////////////////////////////////////////////////////////////////
module triggergen import cvw::*; (
input logic clk, reset,
input logic [31:0] RvviAxiRdata,
input logic [3:0] RvviAxiRstrb,
input logic RvviAxiRlast,
input logic RvviAxiRvalid,
output logic IlaTrigger);
typedef enum {STATE_RST, STATE_COMPARE, STATE_MISMATCH, STATE_TRIGGER, STATE_TRIGGER_DONE} statetype;
(* mark_debug = "true" *) statetype CurrState, NextState;
logic [31:0] mem [4:0];
logic [2:0] Counter;
logic CounterEn, CounterRst;
logic [31:0] RvviAxiRdataDelay;
logic [3:0] RvviAxiRstrbDelay;
logic RvviAxiRvalidDelay;
logic Match, Overflow, Mismatch, Threshold;
logic IlaTriggerOneCycle;
assign mem[0] = 32'h1111_6843; // dst mac [31:0]
assign mem[1] = 32'h1654_4502; // src mac [15:0], dst mac [47:32]
assign mem[2] = 32'h8f54_0000; // src mac [47:16]
assign mem[3] = 32'h7274_005c; // "rt", ether type 005c
assign mem[4] = 32'h6e69_6769; // "igin" (trigin)
flopenr #(32) rvviaxirdatareg(clk, reset, RvviAxiRvalid, RvviAxiRdata, RvviAxiRdataDelay);
flopenr #(4) rvviaxirstrbreg(clk, reset, RvviAxiRvalid, RvviAxiRstrb, RvviAxiRstrbDelay);
flopr #(1) rvviaxirvalidreg(clk, reset, RvviAxiRvalid, RvviAxiRvalidDelay);
counter #(3) counter(clk, CounterRst, CounterEn, Counter);
always_ff @(posedge clk) begin
if(reset) CurrState <= STATE_RST;
else CurrState <= NextState;
end
always_comb begin
case(CurrState)
STATE_RST: if(RvviAxiRvalid) NextState = STATE_COMPARE;
else NextState = STATE_RST;
STATE_COMPARE: if(RvviAxiRlast) NextState = STATE_RST;
else if(Mismatch | Overflow) NextState = STATE_MISMATCH;
else if(Threshold & Match) NextState = STATE_TRIGGER;
else NextState = STATE_COMPARE;
STATE_MISMATCH: if(RvviAxiRlast) NextState = STATE_RST;
else NextState = STATE_MISMATCH;
STATE_TRIGGER: if(RvviAxiRlast) NextState = STATE_RST;
else NextState = STATE_TRIGGER_DONE;
STATE_TRIGGER_DONE: if(RvviAxiRlast) NextState = STATE_RST;
else NextState = STATE_TRIGGER_DONE;
default: NextState = STATE_RST;
endcase
end
assign Match = (mem[Counter] == RvviAxiRdataDelay) & (CurrState == STATE_COMPARE) & RvviAxiRvalidDelay;
assign Overflow = Counter > 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

View File

@ -44,7 +44,8 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) (
output logic [2:0] HBURST, output logic [2:0] HBURST,
output logic [3:0] HPROT, output logic [3:0] HPROT,
output logic [1:0] HTRANS, output logic [1:0] HTRANS,
output logic HMASTLOCK output logic HMASTLOCK,
input logic ExternalStall
); );
logic StallF, StallD, StallE, StallM, StallW; logic StallF, StallD, StallE, StallM, StallW;
@ -274,7 +275,7 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) (
.BPWrongE, .CSRWriteFenceM, .RetM, .TrapM, .BPWrongE, .CSRWriteFenceM, .RetM, .TrapM,
.StructuralStallD, .StructuralStallD,
.LSUStallM, .IFUStallF, .LSUStallM, .IFUStallF,
.FPUStallD, .FPUStallD, .ExternalStall,
.DivBusyE, .FDivBusyE, .DivBusyE, .FDivBusyE,
.wfiM, .IntPendingM, .wfiM, .IntPendingM,
// Stall & flush outputs // Stall & flush outputs

View File

@ -32,9 +32,11 @@ module wallypipelinedsoc import cvw::*; #(parameter cvw_t P) (
input logic reset_ext, // external asynchronous reset pin input logic reset_ext, // external asynchronous reset pin
output logic reset, // reset synchronized to clk to prevent races on release output logic reset, // reset synchronized to clk to prevent races on release
// AHB Interface // AHB Interface
input logic [P.AHBW-1:0] HRDATAEXT, input logic [P.AHBW-1:0] HRDATAEXT,
input logic HREADYEXT, HRESPEXT, input logic HREADYEXT, HRESPEXT,
output logic HSELEXT, output logic HSELEXT,
// fpga debug signals
input logic ExternalStall,
// outputs to external memory, shared with uncore memory // outputs to external memory, shared with uncore memory
output logic HCLK, HRESETn, output logic HCLK, HRESETn,
output logic [P.PA_BITS-1:0] HADDR, 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, wallypipelinedcore #(P) core(.clk, .reset,
.MTimerInt, .MExtInt, .SExtInt, .MSwInt, .MTIME_CLINT, .MTimerInt, .MExtInt, .SExtInt, .MSwInt, .MTIME_CLINT,
.HRDATA, .HREADY, .HRESP, .HCLK, .HRESETn, .HADDR, .HWDATA, .HWSTRB, .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 // 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; MTIME_CLINT, GPIOOUT, GPIOEN, UARTSout, SPIOut, SPICS, SPICLK, SDCCmd, SDCCS, SDCCLK} = '0;
end end
endmodule endmodule

View File

@ -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

View File

@ -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 // Initially connecting the writeback stage signals, but may need to use M stage
// and gate on ~FlushW. // and gate on ~FlushW.
assign valid = InstrValidW & ~StallW; assign valid = InstrValidW & ~StallW & ~reset;
assign rvvi.clk = clk; assign rvvi.clk = clk;
assign rvvi.valid[0][0] = valid; assign rvvi.valid[0][0] = valid;
assign rvvi.order[0][0] = CSRArray[12'hB02]; // TODO: IMPERAS Should be event order assign rvvi.order[0][0] = CSRArray[12'hB02]; // TODO: IMPERAS Should be event order

View File

@ -33,7 +33,6 @@
`include "idv/idv.svh" `include "idv/idv.svh"
`endif `endif
import cvw::*; import cvw::*;
module testbench; module testbench;
@ -44,6 +43,7 @@ module testbench;
parameter BPRED_LOGGER=0; parameter BPRED_LOGGER=0;
parameter I_CACHE_ADDR_LOGGER=0; parameter I_CACHE_ADDR_LOGGER=0;
parameter D_CACHE_ADDR_LOGGER=0; parameter D_CACHE_ADDR_LOGGER=0;
parameter RVVI_SYNTH_SUPPORTED=0;
`ifdef USE_IMPERAS_DV `ifdef USE_IMPERAS_DV
import idvPkg::*; import idvPkg::*;
@ -117,6 +117,7 @@ module testbench;
logic SelectTest; logic SelectTest;
logic TestComplete; logic TestComplete;
logic PrevPCZero; logic PrevPCZero;
logic RVVIStall;
initial begin initial begin
// look for arguments passed to simulation, or use defaults // look for arguments passed to simulation, or use defaults
@ -614,7 +615,8 @@ module testbench;
end 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, .HCLK, .HRESETn, .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT,
.HTRANS, .HMASTLOCK, .HREADY, .TIMECLK(1'b0), .GPIOIN, .GPIOOUT, .GPIOEN, .HTRANS, .HMASTLOCK, .HREADY, .TIMECLK(1'b0), .GPIOIN, .GPIOOUT, .GPIOEN,
.UARTSin, .UARTSout, .SPIIn, .SPIOut, .SPICS, .SPICLK, .SDCIn, .SDCCmd, .SDCCS, .SDCCLK); .UARTSin, .UARTSout, .SPIIn, .SPIOut, .SPICS, .SPICLK, .SDCIn, .SDCCmd, .SDCCS, .SDCCLK);
@ -624,6 +626,22 @@ module testbench;
clk = 1'b1; # 5; clk = 1'b0; # 5; clk = 1'b1; # 5; clk = 1'b0; # 5;
end 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 // Print key info each cycle for debugging
always @(posedge clk) begin always @(posedge clk) begin

View File

@ -64,7 +64,8 @@ module wallywrapper import cvw::*;(
logic HREADY; logic HREADY;
logic HSELEXT; logic HSELEXT;
logic ExternalStall;
// instantiate device to be tested // instantiate device to be tested
assign GPIOIN = 0; assign GPIOIN = 0;
@ -74,10 +75,11 @@ module wallywrapper import cvw::*;(
assign HRESPEXT = 0; assign HRESPEXT = 0;
assign HRDATAEXT = 0; assign HRDATAEXT = 0;
assign ExternalStall = '0;
wallypipelinedsoc #(P) dut(.clk, .reset_ext, .reset, .HRDATAEXT, .HREADYEXT, .HRESPEXT, .HSELEXT, wallypipelinedsoc #(P) dut(.clk, .reset_ext, .reset, .ExternalStall, .HRDATAEXT,.HREADYEXT, .HRESPEXT,.HSELEXT,
.HCLK, .HRESETn, .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT, .HCLK, .HRESETn, .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT,
.HTRANS, .HMASTLOCK, .HREADY, .TIMECLK(1'b0), .GPIOIN, .GPIOOUT, .GPIOEN, .HTRANS, .HMASTLOCK, .HREADY, .TIMECLK(1'b0), .GPIOIN, .GPIOOUT, .GPIOEN,
.UARTSin, .UARTSout, .SPIIn, .SPIOut, .SPICS, .SPICLK, .SDCIn, .SDCCmd, .SDCCS, .SDCCLK); .UARTSin, .UARTSout, .SPIIn, .SPIOut, .SPICS, .SPICLK, .SDCIn, .SDCCmd, .SDCCS, .SDCCLK);
endmodule endmodule