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

This commit is contained in:
Jordan Carlin 2024-07-25 21:21:57 -07:00
commit 42a9bbf28d
No known key found for this signature in database
48 changed files with 2024 additions and 566 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

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

@ -11,6 +11,7 @@
# #
################################## ##################################
import sys,os,shutil import sys,os,shutil
import argparse
import multiprocessing import multiprocessing
from collections import namedtuple from collections import namedtuple
from multiprocessing import Pool, TimeoutError from multiprocessing import Pool, TimeoutError
@ -281,6 +282,22 @@ def addTests(tests, sim):
grepfile = grepfile) grepfile = grepfile)
configs.append(tc) configs.append(tc)
def addLockstepTestsByDir(dir, config, sim):
sim_logdir = WALLY+ "/sim/" + sim + "/logs/"
cmdPrefix="wsim --sim " + sim + " " + coverStr + " " + config
for file in os.listdir(dir):
if file.endswith(".elf"):
fullfile = os.path.join(dir, file)
sim_log = sim_logdir + config + "_" + file + ".log"
grepstring = ""
tc = TestCase(
name=file,
variant=config,
cmd=cmdPrefix + " " + fullfile + " > " + sim_log,
grepstr="Mismatches : 0",
grepfile = sim_log)
configs.append(tc)
def search_log_for_text(text, grepfile): def search_log_for_text(text, grepfile):
"""Search through the given log file for text, returning True if it is found or False if it is not""" """Search through the given log file for text, returning True if it is found or False if it is not"""
grepwarn = "grep -H Warning: " + grepfile grepwarn = "grep -H Warning: " + grepfile
@ -320,22 +337,26 @@ coveragesim = "questa" # Questa is required for code/functional coverage
#defaultsim = "questa" # Default simulator for all other tests; change to Verilator when flow is ready #defaultsim = "questa" # Default simulator for all other tests; change to Verilator when flow is ready
defaultsim = "verilator" # Default simulator for all other tests defaultsim = "verilator" # Default simulator for all other tests
ccov = '--ccov' in sys.argv parser = argparse.ArgumentParser()
fp = '--fp' in sys.argv parser.add_argument("--ccov", help="Code Coverage", action="store_true")
nightly = '--nightly' in sys.argv parser.add_argument("--fcov", help="Functional Coverage", action="store_true")
testfloat = '--testfloat' in sys.argv parser.add_argument("--nightly", help="Run large nightly regression", action="store_true")
buildroot = '--buildroot' in sys.argv parser.add_argument("--buildroot", help="Include Buildroot Linux boot test (takes many hours, done along with --nightly)", action="store_true")
parser.add_argument("--testfloat", help="Include Testfloat floating-point unit tests", action="store_true")
parser.add_argument("--fp", help="Include floating-point tests in coverage (slower runtime)", action="store_true")
args = parser.parse_args()
if (nightly): if (args.nightly):
nightMode = "--nightly"; nightMode = "--nightly";
# sims = [defaultsim] # uncomment to use only the default simulator sims = ["questa", "verilator", "vcs"] # exercise all simulators; can omit a sim if no license is available
sims = ["questa", "verilator", "vcs"] # uncomment to exercise all simulators
else: else:
nightMode = "" nightMode = ""
sims = [defaultsim] sims = [defaultsim]
if (ccov): # only run RV64GC tests in coverage mode if (args.ccov): # only run RV64GC tests in coverage mode
coverStr = '--ccov' coverStr = '--ccov'
elif (args.fcov): # only run RV64GC tests in lockstep in coverage mode
coverStr = '--fcov'
else: else:
coverStr = '' coverStr = ''
@ -353,25 +374,34 @@ configs = [
# run full buildroot boot simulation (slow) if buildroot flag is set. Start it early to overlap with other tests # run full buildroot boot simulation (slow) if buildroot flag is set. Start it early to overlap with other tests
if (buildroot): if (args.buildroot):
# addTests(tests_buildrootboot, defaultsim) # non-lockstep with Verilator runs in about 2 hours # addTests(tests_buildrootboot, defaultsim) # non-lockstep with Verilator runs in about 2 hours
addTests(tests_buildrootbootlockstep, "questa") # lockstep with Questa and ImperasDV runs overnight addTests(tests_buildrootbootlockstep, "questa") # lockstep with Questa and ImperasDV runs overnight
if (ccov): # only run RV64GC tests on Questa in code coverage mode if (args.ccov): # only run RV64GC tests on Questa in code coverage mode
addTests(tests64gc_nofp, "questa") addTests(tests64gc_nofp, coveragesim)
if (fp): if (args.fp):
addTests(tests64gc_fp, "questa") addTests(tests64gc_fp, coveragesim)
elif (args.fcov): # only run RV64GC tests on Questa in lockstep in functional coverage mode
addLockstepTestsByDir(WALLY+"/tests/functcov/rv64/I", "rv64gc", coveragesim)
#sim_log = WALLY + "/sim/questa/logs/fcov.log"
#tc = TestCase(
# name="lockstep_functcov",
# variant="rv64gc",
# cmd="iterelf " + WALLY + "/tests/functcov/rv64/I > " + sim_log,
# grepstr="SUCCESS! All tests ran without failures",
# grepfile = sim_log)
#configs.append(tc)
else: else:
for sim in sims: for sim in sims:
if (not (buildroot and sim == defaultsim)): # skip shot buildroot sim if running long one if (not (args.buildroot and sim == defaultsim)): # skip short buildroot sim if running long one
addTests(tests_buildrootshort, sim) addTests(tests_buildrootshort, sim)
addTests(tests, sim) addTests(tests, sim)
addTests(tests64gc_nofp, sim) addTests(tests64gc_nofp, sim)
addTests(tests64gc_fp, sim) addTests(tests64gc_fp, sim)
# run derivative configurations and lockstep tests in nightly regression # run derivative configurations and lockstep tests in nightly regression
if (nightly): if (args.nightly):
addTests(derivconfigtests, defaultsim)
sim_log = WALLY + "/sim/questa/logs/lockstep_coverage.log" sim_log = WALLY + "/sim/questa/logs/lockstep_coverage.log"
tc = TestCase( tc = TestCase(
name="lockstep_coverage", name="lockstep_coverage",
@ -389,11 +419,12 @@ if (nightly):
grepstr="SUCCESS! All tests ran without failures", grepstr="SUCCESS! All tests ran without failures",
grepfile = sim_log) grepfile = sim_log)
configs.append(tc) configs.append(tc)
addTests(derivconfigtests, defaultsim)
# testfloat tests # testfloat tests
if (testfloat): # for testfloat alone, just run testfloat tests if (args.testfloat): # for testfloat alone, just run testfloat tests
configs = [] configs = []
if (testfloat or nightly): # for nightly, run testfloat along with others if (args.testfloat or args.nightly): # for nightly, run testfloat along with others
testfloatsim = "questa" # change to Verilator when Issue #707 about testfloat not running Verilator is resolved testfloatsim = "questa" # change to Verilator when Issue #707 about testfloat not running Verilator is resolved
testfloatconfigs = ["fdqh_ieee_rv64gc", "fdq_ieee_rv64gc", "fdh_ieee_rv64gc", "fd_ieee_rv64gc", "fh_ieee_rv64gc", "f_ieee_rv64gc", "fdqh_ieee_rv32gc", "f_ieee_rv32gc"] testfloatconfigs = ["fdqh_ieee_rv64gc", "fdq_ieee_rv64gc", "fdh_ieee_rv64gc", "fd_ieee_rv64gc", "fh_ieee_rv64gc", "f_ieee_rv64gc", "fdqh_ieee_rv32gc", "f_ieee_rv32gc"]
for config in testfloatconfigs: for config in testfloatconfigs:
@ -458,7 +489,7 @@ if (testfloat or nightly): # for nightly, run testfloat along with others
def main(): def main():
"""Run the tests and count the failures""" """Run the tests and count the failures"""
global configs, ccov global configs, args
os.chdir(regressionDir) os.chdir(regressionDir)
dirs = ["questa/logs", "questa/wkdir", "verilator/logs", "verilator/wkdir", "vcs/logs", "vcs/wkdir"] dirs = ["questa/logs", "questa/wkdir", "verilator/logs", "verilator/wkdir", "vcs/logs", "vcs/wkdir"]
for d in dirs: for d in dirs:
@ -467,24 +498,27 @@ def main():
os.mkdir(d) os.mkdir(d)
except: except:
pass pass
if args.ccov:
if '--makeTests' in sys.argv:
os.chdir(regressionDir)
os.system('./make-tests.sh | tee ./logs/make-tests.log')
elif '--ccov' in sys.argv:
TIMEOUT_DUR = 20*60 # seconds TIMEOUT_DUR = 20*60 # seconds
os.system('rm -f questa/cov/*.ucdb') os.system('rm -f questa/cov/*.ucdb')
elif '--nightly' in sys.argv: elif args.fcov:
TIMEOUT_DUR = 1*60
os.system('rm -f questa/fcov_ucdb/* questa/fcov_logs/* questa/fcov/*')
elif args.nightly:
TIMEOUT_DUR = 60*1440 # 1 day TIMEOUT_DUR = 60*1440 # 1 day
elif '--testfloat' in sys.argv: elif args.testfloat:
TIMEOUT_DUR = 30*60 # seconds TIMEOUT_DUR = 30*60 # seconds
else: else:
TIMEOUT_DUR = 10*60 # seconds TIMEOUT_DUR = 10*60 # seconds
# Scale the number of concurrent processes to the number of test cases, but # Scale the number of concurrent processes to the number of test cases, but
# max out at a limited number of concurrent processes to not overwhelm the system # max out at a limited number of concurrent processes to not overwhelm the system
with Pool(processes=min(len(configs),multiprocessing.cpu_count())) as pool: # right now fcov, ccov, nightly all use Imperas
if (args.ccov or args.fcov or args.nightly):
ImperasDVLicenseCount = 8 # limit number of concurrent processes to avoid overloading ImperasDV licenses
else:
ImperasDVLicenseCount = 10000 # effectively no license limit for non-lockstep tests
with Pool(processes=min(len(configs),multiprocessing.cpu_count(), ImperasDVLicenseCount)) as pool:
num_fail = 0 num_fail = 0
results = {} results = {}
for config in configs: for config in configs:
@ -497,8 +531,10 @@ def main():
print(f"{bcolors.FAIL}%s_%s: Timeout - runtime exceeded %d seconds{bcolors.ENDC}" % (config.variant, config.name, TIMEOUT_DUR)) print(f"{bcolors.FAIL}%s_%s: Timeout - runtime exceeded %d seconds{bcolors.ENDC}" % (config.variant, config.name, TIMEOUT_DUR))
# Coverage report # Coverage report
if ccov: if args.ccov:
os.system('make QuestaCodeCoverage') os.system('make QuestaCodeCoverage')
if args.fcov:
os.system('make QuestaFunctCoverage')
# Count the number of failures # Count the number of failures
if num_fail: if num_fail:
print(f"{bcolors.FAIL}Regression failed with %s failed configurations{bcolors.ENDC}" % num_fail) print(f"{bcolors.FAIL}Regression failed with %s failed configurations{bcolors.ENDC}" % num_fail)

View file

@ -27,12 +27,13 @@ parser.add_argument("--sim", "-s", help="Simulator", choices=["questa", "verilat
parser.add_argument("--tb", "-t", help="Testbench", choices=["testbench", "testbench_fp"], default="testbench") parser.add_argument("--tb", "-t", help="Testbench", choices=["testbench", "testbench_fp"], default="testbench")
parser.add_argument("--gui", "-g", help="Simulate with GUI", action="store_true") parser.add_argument("--gui", "-g", help="Simulate with GUI", action="store_true")
parser.add_argument("--ccov", "-c", help="Code Coverage", action="store_true") parser.add_argument("--ccov", "-c", help="Code Coverage", action="store_true")
parser.add_argument("--fcov", "-f", help="Functional Coverage", action="store_true") parser.add_argument("--fcov", "-f", help="Functional Coverage, implies lockstep", action="store_true")
parser.add_argument("--args", "-a", help="Optional arguments passed to simulator via $value$plusargs", default="") parser.add_argument("--args", "-a", help="Optional arguments passed to simulator via $value$plusargs", default="")
parser.add_argument("--vcd", "-v", help="Generate testbench.vcd", action="store_true") parser.add_argument("--vcd", "-v", help="Generate testbench.vcd", action="store_true")
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

@ -1657,15 +1657,24 @@ 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
ZICCLSM_SUPPORTED 0
ZAAMO_SUPPORTED 0 ZAAMO_SUPPORTED 0
ZALRSC_SUPPORTED 0 ZALRSC_SUPPORTED 0
ZICBOM_SUPPORTED 0 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

@ -9,6 +9,32 @@
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

@ -89,7 +89,8 @@ report_clock_interaction -file re
write_verilog -force -mode funcsim sim/syn-funcsim.v 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/small-debug-rvvi.xdc
} else { } else {
# source ../constraints/vcu-small-debug.xdc # source ../constraints/vcu-small-debug.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,7 +28,7 @@
import cvw::*; import cvw::*;
module fpgaTop module fpgaTop #(parameter logic RVVI_SYNTH_SUPPORTED = 1)
(input default_100mhz_clk, (input default_100mhz_clk,
(* mark_debug = "true" *) input resetn, (* mark_debug = "true" *) input resetn,
input south_reset, input south_reset,
@ -44,6 +44,21 @@ module fpgaTop
inout SDCCmd, inout SDCCmd,
input SDCCD, input SDCCD,
/*
* 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,
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,
@ -429,6 +444,7 @@ module fpgaTop
wire [11:0] device_temp; wire [11:0] device_temp;
wire mmcm1_locked; wire mmcm1_locked;
(* mark_debug = "true" *) logic RVVIStall;
assign GPIOIN = {28'b0, GPI}; assign GPIOIN = {28'b0, GPI};
assign GPO = GPIOOUT[4:0]; assign GPO = GPIOOUT[4:0];
@ -446,6 +462,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));
@ -496,7 +513,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, .SDCIntr); .UARTSin, .UARTSout, .SDCIntr, .ExternalStall(RVVIStall));
// ahb lite to axi bridge // ahb lite to axi bridge
@ -1097,6 +1114,145 @@ 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

@ -30,6 +30,13 @@ QuestaCodeCoverage: questa/ucdb/rv64gc_arch64i.ucdb
# vcover report -recursive questa/ucdb/cov.ucdb > questa/cov/rv64gc_recursive.rpt # vcover report -recursive questa/ucdb/cov.ucdb > questa/cov/rv64gc_recursive.rpt
vcover report -details -threshH 100 -html questa/ucdb/cov.ucdb vcover report -details -threshH 100 -html questa/ucdb/cov.ucdb
QuestaFunctCoverage: ${SIM}/questa/fcov_ucdb/rv64gc_WALLY-COV-add.elf.ucdb
vcover merge -out ${SIM}/questa/fcov_ucdb/fcov.ucdb ${SIM}/questa/fcov_ucdb/rv64gc_WALLY-COV-add.elf.ucdb ${SIM}/questa/fcov_ucdb/rv64gc_WALLY*.ucdb -logfile ${SIM}/questa/fcov_logs/log
vcover report -details -html ${SIM}/questa/fcov_ucdb/fcov.ucdb
vcover report ${SIM}/questa/fcov_ucdb/fcov.ucdb -details -cvg > ${SIM}/questa/fcov/fcov.log
vcover report ${SIM}/questa/fcov_ucdb/fcov.ucdb -testdetails -cvg > ${SIM}/questa/fcov/fcov.testdetails.log
vcover report ${SIM}/questa/fcov_ucdb/fcov.ucdb -details -cvg | egrep "Coverpoint|Covergroup|Cross|TYPE" > ${SIM}/questa/fcov/fcov.summary.log
grep "TOTAL COVERGROUP COVERAGE" ${SIM}/questa/fcov/fcov.log
imperasdv_cov: imperasdv_cov:
touch ${SIM}/seed0.txt touch ${SIM}/seed0.txt
@ -91,6 +98,7 @@ combine_functcov:
cd ${SIM}/questa/fcov && rm -rf * cd ${SIM}/questa/fcov && rm -rf *
cd ${SIM}/questa/fcov_ucdb && rm -rf * cd ${SIM}/questa/fcov_ucdb && rm -rf *
wsim rv64gc ${WALLY}/tests/functcov/rv64/I/WALLY-COV-add.elf --fcov > ${SIM}/questa/fcov_logs/add.log 2>&1 wsim rv64gc ${WALLY}/tests/functcov/rv64/I/WALLY-COV-add.elf --fcov > ${SIM}/questa/fcov_logs/add.log 2>&1
wsim rv64gc ${WALLY}/tests/functcov/rv64/I/WALLY-COV-and.elf --fcov > ${SIM}/questa/fcov_logs/and.log 2>&1
#run-elf-cov.bash --seed ${SIM}/questa/seed0.txt --verbose --coverdb ${SIM}/questa/fcov/add.ucdb --elf ${WALLY}/tests/functcov/rv64/I/WALLY-COV-add.elf >> ${SIM}/questa/fcov_logs/add.log 2>&1 #run-elf-cov.bash --seed ${SIM}/questa/seed0.txt --verbose --coverdb ${SIM}/questa/fcov/add.ucdb --elf ${WALLY}/tests/functcov/rv64/I/WALLY-COV-add.elf >> ${SIM}/questa/fcov_logs/add.log 2>&1
#run-elf-cov.bash --seed ${SIM}/questa/seed0.txt --verbose --coverdb ${SIM}/questa/fcov/and.ucdb --elf ${WALLY}/tests/functcov/rv64/I/WALLY-COV-and.elf >> ${SIM}/questa/fcov_logs/add.log 2>&1 #run-elf-cov.bash --seed ${SIM}/questa/seed0.txt --verbose --coverdb ${SIM}/questa/fcov/and.ucdb --elf ${WALLY}/tests/functcov/rv64/I/WALLY-COV-and.elf >> ${SIM}/questa/fcov_logs/add.log 2>&1

View file

@ -1,10 +0,0 @@
#!/bin/bash
#export RISCV=/scratch/moore/RISCV
export IMPERAS_TOOLS=$(pwd)/imperas.ic
export OTHERFLAGS="+TRACE2LOG_ENABLE=1 +TRACE2LOG_AFTER=100"
#export OTHERFLAGS="+TRACE2LOG_ENABLE=1 +TRACE2LOG_AFTER=10500000"
#export OTHERFLAGS=""
vsim -do "do wally.do buildroot buildroot testbench --lockstep +acc -GDEBUG=1"

View file

@ -1,33 +0,0 @@
#!/bin/bash
###########################################
## imperas-one-time.sh
##
## Written: Ross Thompson (ross1728@gmail.com) and Lee Moore (moore@imperas.com)
## Created: 31 January 2023
## Modified: 31 January 2023
##
## Purpose: Run wally with imperas
##
## 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.
################################################################################################
IMPERAS_TOOLS=$(pwd)/imperas.ic \
OTHERFLAGS="+TRACE2LOG_ENABLE=1 VERBOSE=1" \
TESTDIR=${WALLY}/tests/riscof/work/wally-riscv-arch-test/rv64i_m/privilege/src/Lee.S/ \
vsim -do "do wally-imperas.do rv64gc"

View file

@ -1,79 +0,0 @@
# wally.do
# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
#
# Modification by Oklahoma State University & Harvey Mudd College
# Use with Testbench
# James Stine, 2008; David Harris 2021
# Go Cowboys!!!!!!
#
# Takes 1:10 to run RV64IC tests using gui
onbreak {resume}
# create library
if [file exists work] {
vdel -all
}
vlib work
# compile source files
# suppress spurious warnngs about
# "Extra checking for conflicts with always_comb done at vopt time"
# because vsim will run vopt
# start and run simulation
# remove +acc flag for faster sim during regressions if there is no need to access internal signals
# *** modelsim won't take `PA_BITS, but will take other defines for the lengths of DTIM_RANGE and IROM_LEN. For now just live with the warnings.
vlog +incdir+$env(WALLY)/config/$1 \
+incdir+$env(WALLY)/config/deriv/$1 \
+incdir+$env(WALLY)/config/shared \
+define+USE_IMPERAS_DV \
+define+IDV_INCLUDE_TRACE2COV \
+define+INCLUDE_TRACE2COV +define+COVER_BASE_RV64I +define+COVER_LEVEL_DV_PR_EXT \
+define+COVER_RV64I \
+define+COVER_RV64M \
+define+COVER_RV64A \
+define+COVER_RV64F \
+define+COVER_RV64D \
+define+COVER_RV64ZICSR \
+define+COVER_RV64C \
+incdir+$env(IMPERAS_HOME)/ImpPublic/include/host \
+incdir+$env(IMPERAS_HOME)/ImpProprietary/include/host \
$env(IMPERAS_HOME)/ImpPublic/source/host/rvvi/rvviApiPkg.sv \
$env(IMPERAS_HOME)/ImpProprietary/source/host/idv/idvApiPkg.sv \
$env(IMPERAS_HOME)/ImpPublic/source/host/rvvi/rvviTrace.sv \
$env(IMPERAS_HOME)/ImpProprietary/source/host/idv/idvPkg.sv \
$env(IMPERAS_HOME)/ImpProprietary/source/host/idv/trace2bin.sv \
$env(IMPERAS_HOME)/ImpProprietary/source/host/idv/trace2api.sv \
$env(IMPERAS_HOME)/ImpProprietary/source/host/idv/trace2log.sv \
\
+incdir+$env(IMPERAS_HOME)/ImpProprietary/source/host/riscvISACOV/source \
$env(IMPERAS_HOME)/ImpProprietary/source/host/idv/trace2cov.sv \
\
$env(WALLY)/src/cvw.sv \
$env(WALLY)/testbench/testbench.sv \
$env(WALLY)/testbench/common/*.sv \
$env(WALLY)/src/*/*.sv \
$env(WALLY)/src/*/*/*.sv \
-suppress 2583 \
-suppress 7063 \
+acc
vopt +acc work.testbench -G DEBUG=1 -o workopt
eval vsim workopt +nowarn3829 -fatal 7 \
-sv_lib $env(IMPERAS_HOME)/lib/Linux64/ImperasLib/imperas.com/verification/riscv/1.0/model \
+ElfFile=$env(TESTDIR)/ref/ref.elf $env(OTHERFLAGS) +TRACE2COV_ENABLE=1
coverage save -onexit $env(WALLY)/sim/questa/riscv.ucdb
view wave
#-- display input and output signals as hexidecimal values
# add log -recursive /*
# do wave.do
run -all
noview $env(WALLY)/testbench/testbench-imperas.sv
view wave
#quit -f

View file

@ -1,48 +0,0 @@
# wally.do
# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
#
# Modification by Oklahoma State University & Harvey Mudd College
# Use with Testbench
# James Stine, 2008; David Harris 2021
# Go Cowboys!!!!!!
#
# Takes 1:10 to run RV64IC tests using gui
onbreak {resume}
# create library
if [file exists work] {
vdel -all
}
vlib work
# compile source files
# suppress spurious warnngs about
# "Extra checking for conflicts with always_comb done at vopt time"
# because vsim will run vopt
# start and run simulation
# remove +acc flag for faster sim during regressions if there is no need to access internal signals
# *** modelsim won't take `PA_BITS, but will take other defines for the lengths of DTIM_RANGE and IROM_LEN. For now just live with the warnings.
vlog +incdir+../config/$1 \
+incdir+../config/shared \
../../external/ImperasDV-HMC/Imperas/ImpPublic/source/host/rvvi/rvviTrace.sv \
../src/cvw.sv \
../testbench/testbench_imperas.sv \
../testbench/common/*.sv \
../src/*/*.sv \
../src/*/*/*.sv \
-suppress 2583 \
-suppress 7063
vopt +acc work.testbench -G DEBUG=1 -o workopt
eval vsim workopt +nowarn3829 -fatal 7 \
+testDir=$env(TESTDIR) $env(OTHERFLAGS)
view wave
#-- display input and output signals as hexidecimal values
add log -recursive /*
do wave.do
run -all
noview ../testbench/testbench_imperas.sv
view wave

View file

@ -1,64 +0,0 @@
# wally.do
# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
#
# Modification by Oklahoma State University & Harvey Mudd College
# Use with Testbench
# James Stine, 2008; David Harris 2021
# Go Cowboys!!!!!!
#
# Takes 1:10 to run RV64IC tests using gui
onbreak {resume}
# create library
if [file exists work] {
vdel -all
}
vlib work
# compile source files
# suppress spurious warnngs about
# "Extra checking for conflicts with always_comb done at vopt time"
# because vsim will run vopt
# start and run simulation
# remove +acc flag for faster sim during regressions if there is no need to access internal signals
# *** modelsim won't take `PA_BITS, but will take other defines for the lengths of DTIM_RANGE and IROM_LEN. For now just live with the warnings.
vlog +incdir+../config/$1 \
+incdir+../config/shared \
+define+USE_IMPERAS_DV \
+incdir+$env(IMPERAS_HOME)/ImpPublic/include/host \
+incdir+$env(IMPERAS_HOME)/ImpProprietary/include/host \
$env(IMPERAS_HOME)/ImpPublic/source/host/rvvi/rvviApiPkg.sv \
$env(IMPERAS_HOME)/ImpPublic/source/host/rvvi/rvviTrace.sv \
$env(IMPERAS_HOME)/ImpProprietary/source/host/idv/idvApiPkg.sv \
$env(IMPERAS_HOME)/ImpProprietary/source/host/idv/idvPkg.sv \
$env(IMPERAS_HOME)/ImpProprietary/source/host/idv/idvApiPkg.sv \
$env(IMPERAS_HOME)/ImpProprietary/source/host/idv/trace2api.sv \
$env(IMPERAS_HOME)/ImpProprietary/source/host/idv/trace2log.sv \
$env(IMPERAS_HOME)/ImpProprietary/source/host/idv/trace2cov.sv \
$env(IMPERAS_HOME)/ImpProprietary/source/host/idv/trace2bin.sv \
../src/cvw.sv \
../testbench/testbench-imperas.sv \
../testbench/common/*.sv \
../src/*/*.sv \
../src/*/*/*.sv \
-suppress 2583 \
-suppress 7063
vopt +acc work.testbench -G DEBUG=1 -o workopt
eval vsim workopt +nowarn3829 -fatal 7 \
-sv_lib $env(IMPERAS_HOME)/lib/Linux64/ImperasLib/imperas.com/verification/riscv/1.0/model \
+testDir=$env(TESTDIR) $env(OTHERFLAGS)
view wave
#-- display input and output signals as hexidecimal values
add log -recursive /*
do wave.do
run -all
noview ../testbench/testbench_imperas.sv
view wave
#quit -f

View file

@ -122,13 +122,14 @@ if {$FunctCoverageIndex >= 0} {
set FCdefineINCLUDE_TRACE2COV "+define+INCLUDE_TRACE2COV" set FCdefineINCLUDE_TRACE2COV "+define+INCLUDE_TRACE2COV"
set FCdefineCOVER_BASE_RV64I "+define+COVER_BASE_RV64I" set FCdefineCOVER_BASE_RV64I "+define+COVER_BASE_RV64I"
set FCdefineCOVER_LEVEL_DV_PR_EXT "+define+COVER_LEVEL_DV_PR_EXT" set FCdefineCOVER_LEVEL_DV_PR_EXT "+define+COVER_LEVEL_DV_PR_EXT"
# Uncomment various cover statements below to control which extensions get functional coverage
set FCdefineCOVER_RV64I "+define+COVER_RV64I" set FCdefineCOVER_RV64I "+define+COVER_RV64I"
set FCdefineCOVER_RV64M "+define+COVER_RV64M" #set FCdefineCOVER_RV64M "+define+COVER_RV64M"
set FCdefineCOVER_RV64A "+define+COVER_RV64A" #set FCdefineCOVER_RV64A "+define+COVER_RV64A"
set FCdefineCOVER_RV64F "+define+COVER_RV64F" #set FCdefineCOVER_RV64F "+define+COVER_RV64F"
set FCdefineCOVER_RV64D "+define+COVER_RV64D" #set FCdefineCOVER_RV64D "+define+COVER_RV64D"
set FCdefineCOVER_RV64ZICSR "+define+COVER_RV64ZICSR" #set FCdefineCOVER_RV64ZICSR "+define+COVER_RV64ZICSR"
set FCdefineCOVER_RV64C "+define+COVER_RV64C" #set FCdefineCOVER_RV64C "+define+COVER_RV64C"
set FCdefineIDV_INCLUDE_TRACE2COV "+define+IDV_INCLUDE_TRACE2COV" set FCdefineIDV_INCLUDE_TRACE2COV "+define+IDV_INCLUDE_TRACE2COV"
set FCTRACE2COV "+TRACE2COV_ENABLE=1" set FCTRACE2COV "+TRACE2COV_ENABLE=1"
set FCdefineIDV_TRACE2COV "+IDV_TRACE2COV=1" set FCdefineIDV_TRACE2COV "+IDV_TRACE2COV=1"
@ -196,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

@ -33,12 +33,14 @@ module decompress import cvw::*; #(parameter cvw_t P) (
output logic IllegalCompInstrD // Invalid decompressed instruction output logic IllegalCompInstrD // Invalid decompressed instruction
); );
logic [32:0] LInstrD; // decompressed instruction with illegal flag in [32]
logic [15:0] instr16; logic [15:0] instr16;
logic [4:0] rds1, rs2, rs1p, rs2p, rds1p, rdp; logic [4:0] rds1, rs2, rs1p, rs2p, rds1p, rdp;
logic [11:0] immCILSP, immCILSPD, immCSS, immCSSD, immCL, immCLD, immCI, immCS, immCSD, immCB, immCIASP, immCIW; logic [11:0] immCILSP, immCILSPD, immCSS, immCSSD, immCL, immCLD, immCI, immCS, immCSD, immCB, immCIASP, immCIW;
logic [19:0] immCJ, immCILUI; logic [19:0] immCJ, immCILUI;
logic [5:0] immSH; logic [5:0] immSH;
logic [1:0] op; logic [1:0] op;
logic LegalCompInstrD;
// Extract op and register source/destination fields // Extract op and register source/destination fields
assign instr16 = InstrRawD[15:0]; // instruction is already aligned assign instr16 = InstrRawD[15:0]; // instruction is already aligned
@ -62,10 +64,10 @@ module decompress import cvw::*; #(parameter cvw_t P) (
assign immCJ = {instr16[12], instr16[8], instr16[10:9], instr16[6], instr16[7], instr16[2], instr16[11], instr16[5:3], {9{instr16[12]}}}; assign immCJ = {instr16[12], instr16[8], instr16[10:9], instr16[6], instr16[7], instr16[2], instr16[11], instr16[5:3], {9{instr16[12]}}};
assign immCB = {{4{instr16[12]}}, instr16[6:5], instr16[2], instr16[11:10], instr16[4:3], instr16[12]}; assign immCB = {{4{instr16[12]}}, instr16[6:5], instr16[2], instr16[11:10], instr16[4:3], instr16[12]};
assign immCI = {{7{instr16[12]}}, instr16[6:2]}; assign immCI = {{7{instr16[12]}}, instr16[6:2]};
assign immCILUI = {{15{instr16[12]}}, instr16[6:2]}; assign immCILUI = {{15{instr16[12]}}, instr16[6:2]}; // c.lui
assign immCIASP = {{3{instr16[12]}}, instr16[4:3], instr16[5], instr16[2], instr16[6], 4'b0000}; assign immCIASP = {{3{instr16[12]}}, instr16[4:3], instr16[5], instr16[2], instr16[6], 4'b0000}; // c.addi16sp
assign immCIW = {2'b00, instr16[10:7], instr16[12:11], instr16[5], instr16[6], 2'b00}; assign immCIW = {2'b00, instr16[10:7], instr16[12:11], instr16[5], instr16[6], 2'b00};
assign immSH = {instr16[12], instr16[6:2]}; assign immSH = {instr16[12], instr16[6:2]}; // c. shift instructions: c.srli, c.srai, c.slli
// only for RV128 // only for RV128
// assign immCILSPQ = {2{instr16[5]}, instr16[5:2], instr16[12], instr16[6], 4'b0000}; // assign immCILSPQ = {2{instr16[5]}, instr16[5:2], instr16[12], instr16[6], 4'b0000};
@ -75,173 +77,110 @@ module decompress import cvw::*; #(parameter cvw_t P) (
always_comb always_comb
if (op == 2'b11) begin // noncompressed instruction if (op == 2'b11) begin // noncompressed instruction
InstrD = InstrRawD; LInstrD = {1'b1, InstrRawD};
IllegalCompInstrD = '0;
end else begin // convert compressed instruction into uncompressed end else begin // convert compressed instruction into uncompressed
IllegalCompInstrD = '0; LInstrD = {1'b0, 16'b0, instr16}; // if a legal instruction is not decoded, default to illegal and preserve 16-bit value for mtval
case ({op, instr16[15:13]}) case ({op, instr16[15:13]})
5'b00000: if (immCIW != 0) InstrD = {immCIW, 5'b00010, 3'b000, rdp, 7'b0010011}; // c.addi4spn 5'b00000: if (immCIW != 0) LInstrD = {1'b1, immCIW, 5'b00010, 3'b000, rdp, 7'b0010011}; // c.addi4spn
else begin // illegal instruction 5'b00001: if (P.ZCD_SUPPORTED) LInstrD = {1'b1, immCLD, rs1p, 3'b011, rdp, 7'b0000111}; // c.fld
IllegalCompInstrD = 1'b1; 5'b00010: LInstrD = {1'b1, immCL, rs1p, 3'b010, rdp, 7'b0000011}; // c.lw
InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap 5'b00011: if (P.XLEN==32) begin
end if (P.ZCF_SUPPORTED) LInstrD = {1'b1, immCL, rs1p, 3'b010, rdp, 7'b0000111}; // c.flw
5'b00001: if (P.ZCD_SUPPORTED) end else LInstrD = {1'b1, immCLD, rs1p, 3'b011, rdp, 7'b0000011}; // c.ld
InstrD = {immCLD, rs1p, 3'b011, rdp, 7'b0000111}; // c.fld
else begin // unsupported instruction
IllegalCompInstrD = 1'b1;
InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap
end
5'b00010: InstrD = {immCL, rs1p, 3'b010, rdp, 7'b0000011}; // c.lw
5'b00011: if (P.XLEN==32)
if (P.ZCF_SUPPORTED)
InstrD = {immCL, rs1p, 3'b010, rdp, 7'b0000111}; // c.flw
else begin
IllegalCompInstrD = 1'b1;
InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap
end
else
InstrD = {immCLD, rs1p, 3'b011, rdp, 7'b0000011}; // c.ld;
5'b00100: if (P.ZCB_SUPPORTED) 5'b00100: if (P.ZCB_SUPPORTED)
if (instr16[12:10] == 3'b000) if (instr16[12:10] == 3'b000) LInstrD = {1'b1, 10'b0, instr16[5], instr16[6], rs1p, 3'b100, rdp, 7'b0000011}; // c.lbu
InstrD = {10'b0, instr16[5], instr16[6], rs1p, 3'b100, rdp, 7'b0000011}; // c.lbu
else if (instr16[12:10] == 3'b001) begin else if (instr16[12:10] == 3'b001) begin
if (instr16[6]) if (instr16[6]) LInstrD = {1'b1, 10'b0, instr16[5], 1'b0, rs1p, 3'b001, rdp, 7'b0000011}; // c.lh
InstrD = {10'b0, instr16[5], 1'b0, rs1p, 3'b001, rdp, 7'b0000011}; // c.lh else LInstrD = {1'b1, 10'b0, instr16[5], 1'b0, rs1p, 3'b101, rdp, 7'b0000011}; // c.lhu
else
InstrD = {10'b0, instr16[5], 1'b0, rs1p, 3'b101, rdp, 7'b0000011}; // c.lhu
end else if (instr16[12:10] == 3'b010) end else if (instr16[12:10] == 3'b010)
InstrD = {7'b0, rs2p, rs1p, 3'b000, 3'b000, instr16[5], instr16[6], 7'b0100011}; // c.sb LInstrD = {1'b1, 7'b0, rs2p, rs1p, 3'b000, 3'b000, instr16[5], instr16[6], 7'b0100011}; // c.sb
else if (instr16[12:10] == 3'b011 & instr16[6] == 1'b0) else if (instr16[12:10] == 3'b011 & instr16[6] == 1'b0)
InstrD = {7'b0, rs2p, rs1p, 3'b001, 3'b000, instr16[5], 1'b0, 7'b0100011}; // c.sh LInstrD = {1'b1, 7'b0, rs2p, rs1p, 3'b001, 3'b000, instr16[5], 1'b0, 7'b0100011}; // c.sh
else begin 5'b00101: if (P.ZCD_SUPPORTED) LInstrD = {1'b1, immCSD[11:5], rs2p, rs1p, 3'b011, immCSD[4:0], 7'b0100111}; // c.fsd
IllegalCompInstrD = 1'b1; 5'b00110: LInstrD = {1'b1, immCS[11:5], rs2p, rs1p, 3'b010, immCS[4:0], 7'b0100011}; // c.sw
InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap 5'b00111: if (P.XLEN==32) begin
end if (P.ZCF_SUPPORTED) LInstrD = {1'b1, immCS[11:5], rs2p, rs1p, 3'b010, immCS[4:0], 7'b0100111}; // c.fsw
else begin end else LInstrD = {1'b1, immCSD[11:5], rs2p, rs1p, 3'b011, immCSD[4:0], 7'b0100011}; // c.sd
IllegalCompInstrD = 1'b1; 5'b01000: if (rds1 != 5'b0)
InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap if (immCI[5:0] != 0) LInstrD = {1'b1, immCI, rds1, 3'b000, rds1, 7'b0010011}; // c.addi
end else LInstrD = {1'b1, 25'b0, 7'b0010011}; // c.addi with imm = 0 is a HINT, treated as nop
5'b00101: if (P.ZCD_SUPPORTED) else if (immCI[5:0] == 6'b0) LInstrD = {1'b1, 25'b0, 7'b0010011}; // c.nop = addi x0, x0, 0
InstrD = {immCSD[11:5], rs2p, rs1p, 3'b011, immCSD[4:0], 7'b0100111}; // c.fsd else LInstrD = {1'b1, 25'b0, 7'b0010011}; // c.nop with imm != 0 is a HINT, treated as nop
else begin // unsupported instruction 5'b01001: if (P.XLEN==32) LInstrD = {1'b1, immCJ, 5'b00001, 7'b1101111}; // c.jal
IllegalCompInstrD = 1'b1; else if (rds1 != 5'b0) LInstrD = {1'b1, immCI, rds1, 3'b000, rds1, 7'b0011011}; // c.addiw
InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap 5'b01010: if (rds1 != 5'b0) LInstrD = {1'b1, immCI, 5'b00000, 3'b000, rds1, 7'b0010011}; // c.li
end else LInstrD = {1'b1, 25'b0, 7'b0010011}; // c.li with rd = 0 is a HINT, treated as nop
5'b00110: InstrD = {immCS[11:5], rs2p, rs1p, 3'b010, immCS[4:0], 7'b0100011}; // c.sw 5'b01011: if (rds1 == 5'b00010) begin
5'b00111: if (P.XLEN==32) if (immCIASP[9:4] != 6'b0) LInstrD = {1'b1, immCIASP, rds1, 3'b000, rds1, 7'b0010011}; // c.addi16sp
if (P.ZCF_SUPPORTED) end else if (immCILUI[5:0] != 0)
InstrD = {immCS[11:5], rs2p, rs1p, 3'b010, immCS[4:0], 7'b0100111}; // c.fsw if (rds1 != 5'b0) LInstrD = {1'b1, immCILUI, rds1, 7'b0110111}; // c.lui
else begin else LInstrD = {1'b1, 25'b0, 7'b0010011}; // c.lui with rd = 0, imm!=0 is a HINT, treated as nop
IllegalCompInstrD = 1'b1; 5'b01100: if (instr16[11:10] == 2'b00) begin
InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap if (P.XLEN > 32 | ~immSH[5]) LInstrD = {1'b1, 6'b000000, immSH, rds1p, 3'b101, rds1p, 7'b0010011}; // c.srli; shamt[5] must be 0 in RV32C
end end else if (instr16[11:10] == 2'b01) begin
else if (P.XLEN > 32 | ~immSH[5]) LInstrD = {1'b1, 6'b010000, immSH, rds1p, 3'b101, rds1p, 7'b0010011}; // c.srai; shamt[5] must be 0 in RV32C
InstrD = {immCSD[11:5], rs2p, rs1p, 3'b011, immCSD[4:0], 7'b0100011}; //c.sd end else if (instr16[11:10] == 2'b10) LInstrD = {1'b1, immCI, rds1p, 3'b111, rds1p, 7'b0010011}; // c.andi
5'b01000: InstrD = {immCI, rds1, 3'b000, rds1, 7'b0010011}; // c.addi else if (instr16[12:10] == 3'b011) begin
5'b01001: if (P.XLEN==32) if (instr16[6:5] == 2'b00) LInstrD = {1'b1, 7'b0100000, rs2p, rds1p, 3'b000, rds1p, 7'b0110011}; // c.sub
InstrD = {immCJ, 5'b00001, 7'b1101111}; // c.jal else if (instr16[6:5] == 2'b01) LInstrD = {1'b1, 7'b0000000, rs2p, rds1p, 3'b100, rds1p, 7'b0110011}; // c.xor
else else if (instr16[6:5] == 2'b10) LInstrD = {1'b1, 7'b0000000, rs2p, rds1p, 3'b110, rds1p, 7'b0110011}; // c.or
InstrD = {immCI, rds1, 3'b000, rds1, 7'b0011011}; // c.addiw else LInstrD = {1'b1, 7'b0000000, rs2p, rds1p, 3'b111, rds1p, 7'b0110011}; // c.and
5'b01010: InstrD = {immCI, 5'b00000, 3'b000, rds1, 7'b0010011}; // c.li end else begin // (instr16[12:10] == 3'b111)
5'b01011: if (rds1 != 5'b00010)
InstrD = {immCILUI, rds1, 7'b0110111}; // c.lui
else
InstrD = {immCIASP, rds1, 3'b000, rds1, 7'b0010011}; // c.addi16sp
5'b01100: if (instr16[11:10] == 2'b00)
InstrD = {6'b000000, immSH, rds1p, 3'b101, rds1p, 7'b0010011}; // c.srli
else if (instr16[11:10] == 2'b01)
InstrD = {6'b010000, immSH, rds1p, 3'b101, rds1p, 7'b0010011}; // c.srai
else if (instr16[11:10] == 2'b10)
InstrD = {immCI, rds1p, 3'b111, rds1p, 7'b0010011}; // c.andi
else if (instr16[12:10] == 3'b011)
if (instr16[6:5] == 2'b00)
InstrD = {7'b0100000, rs2p, rds1p, 3'b000, rds1p, 7'b0110011}; // c.sub
else if (instr16[6:5] == 2'b01)
InstrD = {7'b0000000, rs2p, rds1p, 3'b100, rds1p, 7'b0110011}; // c.xor
else if (instr16[6:5] == 2'b10)
InstrD = {7'b0000000, rs2p, rds1p, 3'b110, rds1p, 7'b0110011}; // c.or
else // if (instr16[6:5] == 2'b11)
InstrD = {7'b0000000, rs2p, rds1p, 3'b111, rds1p, 7'b0110011}; // c.and
else begin // (instr16[12:10] == 3'b111)
if (instr16[6:5] == 2'b00 & P.XLEN > 32) if (instr16[6:5] == 2'b00 & P.XLEN > 32)
InstrD = {7'b0100000, rs2p, rds1p, 3'b000, rds1p, 7'b0111011}; // c.subw LInstrD = {1'b1, 7'b0100000, rs2p, rds1p, 3'b000, rds1p, 7'b0111011}; // c.subw
else if (instr16[6:5] == 2'b01 & P.XLEN > 32) else if (instr16[6:5] == 2'b01 & P.XLEN > 32)
InstrD = {7'b0000000, rs2p, rds1p, 3'b000, rds1p, 7'b0111011}; // c.addw LInstrD = {1'b1, 7'b0000000, rs2p, rds1p, 3'b000, rds1p, 7'b0111011}; // c.addw
else if (instr16[6:2] == 5'b11000 & P.ZCB_SUPPORTED) else if (instr16[6:2] == 5'b11000 & P.ZCB_SUPPORTED)
InstrD = {12'b000011111111, rds1p, 3'b111, rds1p, 7'b0010011}; // c.zext.b = andi rd, rs1, 255 LInstrD = {1'b1, 12'b000011111111, rds1p, 3'b111, rds1p, 7'b0010011}; // c.zext.b = andi rd, rs1, 255
else if (instr16[6:2] == 5'b11001 & P.ZCB_SUPPORTED & P.ZBB_SUPPORTED) else if (instr16[6:2] == 5'b11001 & P.ZCB_SUPPORTED & P.ZBB_SUPPORTED)
InstrD = {12'b011000000100, rds1p, 3'b001, rds1p, 7'b0010011}; // c.sext.b LInstrD = {1'b1, 12'b011000000100, rds1p, 3'b001, rds1p, 7'b0010011}; // c.sext.b
else if (instr16[6:2] == 5'b11010 & P.ZCB_SUPPORTED & P.ZBB_SUPPORTED) else if (instr16[6:2] == 5'b11010 & P.ZCB_SUPPORTED & P.ZBB_SUPPORTED)
InstrD = {7'b0000100, 5'b00000, rds1p, 3'b100, rds1p, 3'b011, P.XLEN > 32, 3'b011}; // c.zext.h LInstrD = {1'b1, 7'b0000100, 5'b00000, rds1p, 3'b100, rds1p, 3'b011, P.XLEN > 32, 3'b011}; // c.zext.h
else if (instr16[6:2] == 5'b11011 & P.ZCB_SUPPORTED & P.ZBB_SUPPORTED) else if (instr16[6:2] == 5'b11011 & P.ZCB_SUPPORTED & P.ZBB_SUPPORTED)
InstrD = {12'b011000000101, rds1p, 3'b001, rds1p, 7'b0010011}; // c.sext.h LInstrD = {1'b1, 12'b011000000101, rds1p, 3'b001, rds1p, 7'b0010011}; // c.sext.h
else if (instr16[6:2] == 5'b11101 & P.ZCB_SUPPORTED) else if (instr16[6:2] == 5'b11101 & P.ZCB_SUPPORTED)
InstrD = {12'b111111111111, rds1p, 3'b100, rds1p, 7'b0010011}; // c.not = xori LInstrD = {1'b1, 12'b111111111111, rds1p, 3'b100, rds1p, 7'b0010011}; // c.not = xori
else if (instr16[6:2] == 5'b11100 & P.ZCB_SUPPORTED & P.ZBA_SUPPORTED & P.XLEN > 32) else if (instr16[6:2] == 5'b11100 & P.ZCB_SUPPORTED & P.ZBA_SUPPORTED & P.XLEN > 32)
InstrD = {7'b0000100, 5'b00000, rds1p, 3'b000, rds1p, 7'b0111011}; // c.zext.w = add.uw rd, rs1, 0 LInstrD = {1'b1, 7'b0000100, 5'b00000, rds1p, 3'b000, rds1p, 7'b0111011}; // c.zext.w = add.uw rd, rs1, 0
else if (instr16[6:5] == 2'b10 & P.ZCB_SUPPORTED & P.ZMMUL_SUPPORTED) else if (instr16[6:5] == 2'b10 & P.ZCB_SUPPORTED & P.ZMMUL_SUPPORTED)
InstrD = {7'b0000001, rs2p, rds1p, 3'b000, rds1p, 7'b0110011}; // c.mul LInstrD = {1'b1, 7'b0000001, rs2p, rds1p, 3'b000, rds1p, 7'b0110011}; // c.mul
else begin // reserved
IllegalCompInstrD = 1'b1;
InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap
end end
/** end else begin // illegal instruction 5'b01101: LInstrD = {1'b1, immCJ, 5'b00000, 7'b1101111}; // c.j
IllegalCompInstrD = 1'b1; 5'b01110: LInstrD = {1'b1, immCB[11:5], 5'b00000, rs1p, 3'b000, immCB[4:0], 7'b1100011}; // c.beqz
InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap **/ 5'b01111: LInstrD = {1'b1, immCB[11:5], 5'b00000, rs1p, 3'b001, immCB[4:0], 7'b1100011}; // c.bnez
end 5'b10000: if (rds1 != 5'b0) begin
5'b01101: InstrD = {immCJ, 5'b00000, 7'b1101111}; // c.j if (P.XLEN > 32 | ~immSH[5]) LInstrD = {1'b1, 6'b000000, immSH, rds1, 3'b001, rds1, 7'b0010011}; // c.slli; shamt[5] must be 0 in RV32C
5'b01110: InstrD = {immCB[11:5], 5'b00000, rs1p, 3'b000, immCB[4:0], 7'b1100011}; // c.beqz end else if (immSH != 0) LInstrD = {1'b1, 25'b0, 7'b0010011}; // c.slli with rd = 0, immm != 0 is a HINT, treated as nop
5'b01111: InstrD = {immCB[11:5], 5'b00000, rs1p, 3'b001, immCB[4:0], 7'b1100011}; // c.bnez
5'b10000: InstrD = {6'b000000, immSH, rds1, 3'b001, rds1, 7'b0010011}; // c.slli
5'b10001: if (P.ZCD_SUPPORTED) 5'b10001: if (P.ZCD_SUPPORTED)
InstrD = {immCILSPD, 5'b00010, 3'b011, rds1, 7'b0000111}; // c.fldsp if (rds1 != 5'b0) LInstrD = {1'b1, immCILSPD, 5'b00010, 3'b011, rds1, 7'b0000111}; // c.fldsp
else begin // unsupported instruction 5'b10010: if (rds1 != 5'b0) LInstrD = {1'b1, immCILSP, 5'b00010, 3'b010, rds1, 7'b0000011}; // c.lwsp
IllegalCompInstrD = 1'b1; 5'b10011: if (P.XLEN == 32) begin
InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap if (P.ZCF_SUPPORTED) LInstrD = {1'b1, immCILSP, 5'b00010, 3'b010, rds1, 7'b0000111}; // c.flwsp
end end else if (rds1 != 5'b0) LInstrD = {1'b1, immCILSPD, 5'b00010, 3'b011, rds1, 7'b0000011}; // c.ldsp
5'b10010: InstrD = {immCILSP, 5'b00010, 3'b010, rds1, 7'b0000011}; // c.lwsp
5'b10011: if (P.XLEN == 32)
if (P.ZCF_SUPPORTED)
InstrD = {immCILSP, 5'b00010, 3'b010, rds1, 7'b0000111}; // c.flwsp
else begin
IllegalCompInstrD = 1'b1;
InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap
end
else
InstrD = {immCILSPD, 5'b00010, 3'b011, rds1, 7'b0000011}; // c.ldsp
5'b10100: if (instr16[12] == 0) 5'b10100: if (instr16[12] == 0)
if (instr16[6:2] == 5'b00000) if (rs2 == 5'b00000) begin
InstrD = {7'b0000000, 5'b00000, rds1, 3'b000, 5'b00000, 7'b1100111}; // c.jr if (rds1 != 5'b0) LInstrD = {1'b1, 7'b0000000, 5'b00000, rds1, 3'b000, 5'b00000, 7'b1100111}; // c.jr
end else
if (rds1 != 5'b0) LInstrD = {1'b1, 7'b0000000, rs2, 5'b00000, 3'b000, rds1, 7'b0110011}; // c.mv
else LInstrD = {1'b1, 25'b0, 7'b0010011}; // c.mv with rd = 0 is a HINT, treated as nop
else else
InstrD = {7'b0000000, rs2, 5'b00000, 3'b000, rds1, 7'b0110011}; // c.mv if (rs2 == 5'b00000) begin
else if (rds1 == 5'b00000) LInstrD = {1'b1, 12'b1, 5'b00000, 3'b000, 5'b00000, 7'b1110011}; // c.ebreak
if (rs2 == 5'b00000) else if (rds1 != 5'b0) LInstrD = {1'b1, 12'b0, rds1, 3'b000, 5'b00001, 7'b1100111}; // c.jalr
if (rds1 == 5'b00000) end else
InstrD = {12'b1, 5'b00000, 3'b000, 5'b00000, 7'b1110011}; // c.ebreak if (rds1 != 0) LInstrD = {1'b1, 7'b0000000, rs2, rds1, 3'b000, rds1, 7'b0110011}; // c.add
else else LInstrD = {1'b1, 25'b0, 7'b0010011}; // c.add with rd = 0 is a HINT, treated as nop, even if it is a C.NTL
InstrD = {12'b0, rds1, 3'b000, 5'b00001, 7'b1100111}; // c.jalr 5'b10101: if (P.ZCD_SUPPORTED) LInstrD = {1'b1, immCSSD[11:5], rs2, 5'b00010, 3'b011, immCSSD[4:0], 7'b0100111}; // c.fsdsp
else 5'b10110: LInstrD = {1'b1, immCSS[11:5], rs2, 5'b00010, 3'b010, immCSS[4:0], 7'b0100011}; // c.swsp
InstrD = {7'b0000000, rs2, rds1, 3'b000, rds1, 7'b0110011}; // c.add 5'b10111: if (P.XLEN==32) begin
5'b10101: if (P.ZCD_SUPPORTED) if (P.ZCF_SUPPORTED) LInstrD = {1'b1, immCSS[11:5], rs2, 5'b00010, 3'b010, immCSS[4:0], 7'b0100111}; // c.fswsp
InstrD = {immCSSD[11:5], rs2, 5'b00010, 3'b011, immCSSD[4:0], 7'b0100111}; // c.fsdsp end else LInstrD = {1'b1, immCSSD[11:5], rs2, 5'b00010, 3'b011, immCSSD[4:0], 7'b0100011}; // c.sdsp
else begin // unsupported instruction default: ; // illegal instruction
IllegalCompInstrD = 1'b1;
InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap
end
5'b10110: InstrD = {immCSS[11:5], rs2, 5'b00010, 3'b010, immCSS[4:0], 7'b0100011}; // c.swsp
5'b10111: if (P.XLEN==32)
if (P.ZCF_SUPPORTED)
InstrD = {immCSS[11:5], rs2, 5'b00010, 3'b010, immCSS[4:0], 7'b0100111}; // c.fswsp
else begin
IllegalCompInstrD = 1'b1;
InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap
end
else
InstrD = {immCSSD[11:5], rs2, 5'b00010, 3'b011, immCSSD[4:0], 7'b0100011}; // c.sdsp
default: begin // illegal instruction
IllegalCompInstrD = 1'b1;
InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap
end
endcase endcase
end end
// extract instruction and illegal from LInstrD
assign {LegalCompInstrD, InstrD} = LInstrD;
assign IllegalCompInstrD = ~LegalCompInstrD;
endmodule endmodule

View file

@ -57,6 +57,7 @@ module csrm import cvw::*; #(parameter cvw_t P) (
logic [P.XLEN-1:0] MISA_REGW, MHARTID_REGW; logic [P.XLEN-1:0] MISA_REGW, MHARTID_REGW;
logic [P.XLEN-1:0] MSCRATCH_REGW, MTVAL_REGW, MCAUSE_REGW; logic [P.XLEN-1:0] MSCRATCH_REGW, MTVAL_REGW, MCAUSE_REGW;
logic [P.XLEN-1:0] MENVCFGH_REGW; logic [P.XLEN-1:0] MENVCFGH_REGW;
logic [P.XLEN-1:0] TVECWriteValM;
logic WriteMTVECM, WriteMEDELEGM, WriteMIDELEGM; logic WriteMTVECM, WriteMEDELEGM, WriteMIDELEGM;
logic WriteMSCRATCHM, WriteMEPCM, WriteMCAUSEM, WriteMTVALM; logic WriteMSCRATCHM, WriteMEPCM, WriteMCAUSEM, WriteMTVALM;
logic WriteMCOUNTERENM, WriteMCOUNTINHIBITM; logic WriteMCOUNTERENM, WriteMCOUNTINHIBITM;
@ -106,6 +107,9 @@ module csrm import cvw::*; #(parameter cvw_t P) (
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
@ -120,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
@ -152,7 +160,8 @@ module csrm import cvw::*; #(parameter cvw_t P) (
assign IllegalCSRMWriteReadonlyM = UngatedCSRMWriteM & (CSRAdrM == MVENDORID | CSRAdrM == MARCHID | CSRAdrM == MIMPID | CSRAdrM == MHARTID | CSRAdrM == MCONFIGPTR); assign IllegalCSRMWriteReadonlyM = UngatedCSRMWriteM & (CSRAdrM == MVENDORID | CSRAdrM == MARCHID | CSRAdrM == MIMPID | CSRAdrM == MHARTID | CSRAdrM == MCONFIGPTR);
// CSRs // CSRs
flopenr #(P.XLEN) MTVECreg(clk, reset, WriteMTVECM, {CSRWriteValM[P.XLEN-1:2], 1'b0, CSRWriteValM[0]}, MTVEC_REGW); assign TVECWriteValM = CSRWriteValM[0] ? {CSRWriteValM[P.XLEN-1:6], 6'b000001} : {CSRWriteValM[P.XLEN-1:2], 2'b00};
flopenr #(P.XLEN) MTVECreg(clk, reset, WriteMTVECM, TVECWriteValM, MTVEC_REGW);
if (P.S_SUPPORTED) begin:deleg // DELEG registers should exist if (P.S_SUPPORTED) begin:deleg // DELEG registers should exist
flopenr #(16) MEDELEGreg(clk, reset, WriteMEDELEGM, CSRWriteValM[15:0] & MEDELEG_MASK, MEDELEG_REGW); flopenr #(16) MEDELEGreg(clk, reset, WriteMEDELEGM, CSRWriteValM[15:0] & MEDELEG_MASK, MEDELEG_REGW);
flopenr #(12) MIDELEGreg(clk, reset, WriteMIDELEGM, CSRWriteValM[11:0] & MIDELEG_MASK, MIDELEG_REGW); flopenr #(12) MIDELEGreg(clk, reset, WriteMIDELEGM, CSRWriteValM[11:0] & MIDELEG_MASK, MIDELEG_REGW);

View file

@ -78,6 +78,7 @@ module csrs import cvw::*; #(parameter cvw_t P) (
logic [P.XLEN-1:0] SSCRATCH_REGW, STVAL_REGW, SCAUSE_REGW; logic [P.XLEN-1:0] SSCRATCH_REGW, STVAL_REGW, SCAUSE_REGW;
logic [P.XLEN-1:0] SENVCFG_WriteValM; logic [P.XLEN-1:0] SENVCFG_WriteValM;
logic [P.XLEN-1:0] TVECWriteValM;
logic [63:0] STIMECMP_REGW; logic [63:0] STIMECMP_REGW;
@ -100,7 +101,8 @@ module csrs import cvw::*; #(parameter cvw_t P) (
assign WriteSTIMECMPHM = CSRSWriteM & (CSRAdrM == STIMECMPH) & STCE & (P.XLEN == 32); assign WriteSTIMECMPHM = CSRSWriteM & (CSRAdrM == STIMECMPH) & STCE & (P.XLEN == 32);
// CSRs // CSRs
flopenr #(P.XLEN) STVECreg(clk, reset, WriteSTVECM, {CSRWriteValM[P.XLEN-1:2], 1'b0, CSRWriteValM[0]}, STVEC_REGW); assign TVECWriteValM = CSRWriteValM[0] ? {CSRWriteValM[P.XLEN-1:6], 6'b000001} : {CSRWriteValM[P.XLEN-1:2], 2'b00}; // could share this with MTVEC, but reduces to 4-bit AND to mask bits [5:2]
flopenr #(P.XLEN) STVECreg(clk, reset, WriteSTVECM, TVECWriteValM, STVEC_REGW);
flopenr #(P.XLEN) SSCRATCHreg(clk, reset, WriteSSCRATCHM, CSRWriteValM, SSCRATCH_REGW); flopenr #(P.XLEN) SSCRATCHreg(clk, reset, WriteSSCRATCHM, CSRWriteValM, SSCRATCH_REGW);
flopenr #(P.XLEN) SEPCreg(clk, reset, WriteSEPCM, NextEPCM, SEPC_REGW); flopenr #(P.XLEN) SEPCreg(clk, reset, WriteSEPCM, NextEPCM, SEPC_REGW);
flopenr #(P.XLEN) SCAUSEreg(clk, reset, WriteSCAUSEM, {NextCauseM[4], {(P.XLEN-5){1'b0}}, NextCauseM[3:0]}, SCAUSE_REGW); flopenr #(P.XLEN) SCAUSEreg(clk, reset, WriteSCAUSEM, {NextCauseM[4], {(P.XLEN-5){1'b0}}, NextCauseM[3:0]}, SCAUSE_REGW);

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

@ -36,6 +36,8 @@ module wallypipelinedsoc import cvw::*; #(parameter cvw_t P) (
input logic HREADYEXT, HRESPEXT, input logic HREADYEXT, HRESPEXT,
output logic HSELEXT, output logic HSELEXT,
output logic HSELEXTSDC, output logic HSELEXTSDC,
// 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,
@ -75,7 +77,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
@ -90,4 +92,5 @@ module wallypipelinedsoc import cvw::*; #(parameter cvw_t P) (
MTIME_CLINT, GPIOOUT, GPIOEN, UARTSout, SPIOut, SPICS} = '0; MTIME_CLINT, GPIOOUT, GPIOEN, UARTSout, SPIOut, SPICS} = '0;
end end
endmodule endmodule

View file

@ -66,6 +66,7 @@ module riscvassertions import cvw::*; #(parameter cvw_t P);
assert ((P.ZCF_SUPPORTED == 0) | ((P.F_SUPPORTED == 1) & (P.XLEN == 32))) else $fatal(1, "ZCF requires F and XLEN == 32"); assert ((P.ZCF_SUPPORTED == 0) | ((P.F_SUPPORTED == 1) & (P.XLEN == 32))) else $fatal(1, "ZCF requires F and XLEN == 32");
assert ((P.ZCD_SUPPORTED == 0) | (P.D_SUPPORTED == 1)) else $fatal(1, "ZCD requires D"); assert ((P.ZCD_SUPPORTED == 0) | (P.D_SUPPORTED == 1)) else $fatal(1, "ZCD requires D");
assert ((P.LLEN == P.XLEN) | (P.DCACHE_SUPPORTED & P.DTIM_SUPPORTED == 0)) else $fatal(1, "LLEN > XLEN (D on RV32 or Q on RV64) requires data cache"); assert ((P.LLEN == P.XLEN) | (P.DCACHE_SUPPORTED & P.DTIM_SUPPORTED == 0)) else $fatal(1, "LLEN > XLEN (D on RV32 or Q on RV64) requires data cache");
assert ((P.ZICCLSM_SUPPORTED == 0) | (P.DCACHE_SUPPORTED == 1)) else $fatal(1, "ZICCLSM requires DCACHE_SUPPORTED");
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::*;
@ -114,6 +114,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
@ -589,7 +590,8 @@ module testbench;
assign SDCIntr = 1'b0; assign SDCIntr = 1'b0;
end end
wallypipelinedsoc #(P) dut(.clk, .reset_ext, .reset, .HRDATAEXT, .HREADYEXT, .HRESPEXT, .HSELEXT, .HSELEXTSDC, wallypipelinedsoc #(P) dut(.clk, .reset_ext, .reset, .ExternalStall(RVVIStall),
.HRDATAEXT, .HREADYEXT, .HRESPEXT, .HSELEXT, .HSELEXTSDC,
.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, .SDCIntr, .SPIIn, .SPIOut, .SPICS); .UARTSin, .UARTSout, .SDCIntr, .SPIIn, .SPIOut, .SPICS);
@ -599,6 +601,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

@ -60,7 +60,7 @@ module wallywrapper import cvw::*;(
logic HREADY; logic HREADY;
logic HSELEXT; logic HSELEXT;
logic HSELEXTSDC; logic HSELEXTSDC;
logic ExternalStall;
// instantiate device to be tested // instantiate device to be tested
assign GPIOIN = 0; assign GPIOIN = 0;
@ -70,8 +70,9 @@ 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, .HSELEXTSDC, wallypipelinedsoc #(P) dut(.clk, .reset_ext, .reset, .ExternalStall, .HRDATAEXT,.HREADYEXT, .HRESPEXT,.HSELEXT, .HSELEXTSDC,
.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, .SDCIntr); .UARTSin, .UARTSout, .SPIIn, .SPIOut, .SPICS, .SDCIntr);

View file

@ -31,54 +31,89 @@ def signedImm12(imm):
imm = imm - 0x1000 imm = imm - 0x1000
return str(imm) return str(imm)
def signedImm20(imm): def unsignedImm20(imm):
imm = imm % pow(2, 20) imm = imm % pow(2, 20)
if (imm & 0x80000):
imm = imm - 0x100000
return str(imm) return str(imm)
def writeCovVector(desc, rs1, rs2, rd, rs1val, rs2val, immval, rdval, test, storecmd, xlen): def writeCovVector(desc, rs1, rs2, rd, rs1val, rs2val, immval, rdval, test, xlen):
lines = "\n# Testcase " + str(desc) + "\n" lines = "\n# Testcase " + str(desc) + "\n"
if (rs1val < 0): if (rs1val < 0):
rs1val = rs1val + 2**xlen rs1val = rs1val + 2**xlen
if (rs2val < 0): if (rs2val < 0):
rs2val = rs2val + 2**xlen rs2val = rs2val + 2**xlen
lines = lines + "li x" + str(rd) + ", " + formatstr.format(rdval) + " # initialize rd to a random value that should get changed\n" lines = lines + "li x" + str(rd) + ", " + formatstr.format(rdval) + " # initialize rd to a random value that should get changed; helps covering rd_toggle\n"
if (test in rtype): if (test in rtype):
lines = lines + "li x" + str(rs1) + ", " + formatstr.format(rs1val) + " # initialize rs1 to a random value \n" lines = lines + "li x" + str(rs1) + ", " + formatstr.format(rs1val) + " # initialize rs1\n"
lines = lines + "li x" + str(rs2) + ", " + formatstr.format(rs2val) + " # initialize rs2 to a random value\n" lines = lines + "li x" + str(rs2) + ", " + formatstr.format(rs2val) + " # initialize rs2\n"
lines = lines + test + " x" + str(rd) + ", x" + str(rs1) + ", x" + str(rs2) + " # perform operation\n" lines = lines + test + " x" + str(rd) + ", x" + str(rs1) + ", x" + str(rs2) + " # perform operation\n"
elif (test in shiftitype): elif (test in shiftitype):
lines = lines + "li x" + str(rs1) + ", " + formatstr.format(rs1val) + " # initialize rs1 to a random value \n" lines = lines + "li x" + str(rs1) + ", " + formatstr.format(rs1val) + " # initialize rs1\n"
if (test in shiftiwtype):
lines = lines + test + " x" + str(rd) + ", x" + str(rs1) + ", " + shiftImm(immval, 32) + " # perform operation\n"
else:
lines = lines + test + " x" + str(rd) + ", x" + str(rs1) + ", " + shiftImm(immval, xlen) + " # perform operation\n" lines = lines + test + " x" + str(rd) + ", x" + str(rs1) + ", " + shiftImm(immval, xlen) + " # perform operation\n"
elif (test in itype): elif (test in itype):
lines = lines + "li x" + str(rs1) + ", " + formatstr.format(rs1val) + " # initialize rs1 to a random value \n" lines = lines + "li x" + str(rs1) + ", " + formatstr.format(rs1val) + " # initialize rs1\n"
lines = lines + test + " x" + str(rd) + ", x" + str(rs1) + ", " + signedImm12(immval) + " # perform operation\n" lines = lines + test + " x" + str(rd) + ", x" + str(rs1) + ", " + signedImm12(immval) + " # perform operation\n"
elif (test in loaditype):#["lb", "lh", "lw", "ld", "lbu", "lhu", "lwu"] elif (test in loaditype):#["lb", "lh", "lw", "ld", "lbu", "lhu", "lwu"]
lines = lines + "auipc x" + str(rs1) + ", 0x20" + " # add upper immediate value to pc \n" if (rs1 != 0):
lines = lines + "addi x" + str(rs1) + ", x" + str(rs1) + ", " + signedImm12(immval) + " # add immediate to lower part of rs1 \n" lines = lines + "li x" + str(rs2) + ", " + formatstr.format(rs2val) + " # initialize rs2\n"
lines = lines + "la x" + str(rs1) + ", scratch" + " # base address \n"
lines = lines + "addi x" + str(rs1) + ", x" + str(rs1) + ", " + signedImm12(-immval) + " # sub immediate from rs1 to counter offset\n"
if (xlen == 32):
storeop = "sw"
else:
storeop = "sd"
lines = lines + storeop + " x" + str(rs2) + ", " + signedImm12(immval) +" (x" + str(rs1) + ") # store value to put someting in memory\n"
lines = lines + test + " x" + str(rd) + ", " + signedImm12(immval) + "(x" + str(rs1) + ") # perform operation\n" lines = lines + test + " x" + str(rd) + ", " + signedImm12(immval) + "(x" + str(rs1) + ") # perform operation\n"
elif (test in stypes):#["sb", "sh", "sw", "sd"] # lines = lines + test + " x" + str(rd) + ", 0(x" + str(rs1) + ") # perform operation\n"
#lines = lines + test + " x" + str(rs2) + ", " + signedImm12(immval) + "(x" + str(rs1) + ") # perform operation \n" elif (test in stype):#["sb", "sh", "sw", "sd"]
#lines = lines + test + " x" + str(rs2) + ", " "0(x" + str(rs1) + ") # perform operation \n" if (rs1 != 0):
print("Error: %s type not implemented yet" % test) if (rs2 == rs1): # make sure registers are different so they don't conflict
elif (test in btypes):#["beq", "bne", "blt", "bge", "bltu", "bgeu"] rs2 = (rs1 + 1) % 32
if (randint(1,100) > 50): if (rs2 == 0):
rs2 = 1
lines = lines + "li x" + str(rs2) + ", " + formatstr.format(rs2val) + " # initialize rs2\n"
lines = lines + "la x" + str(rs1) + ", scratch" + " # base address \n"
lines = lines + "addi x" + str(rs1) + ", x" + str(rs1) + ", " + signedImm12(-immval) + " # sub immediate from rs1 to counter offset\n"
lines = lines + test + " x" + str(rs2) + ", " + signedImm12(immval) + "(x" + str(rs1) + ") # perform operation \n"
elif (test in btype):#["beq", "bne", "blt", "bge", "bltu", "bgeu"]
for same in range(2):
if (same):
rs1val = rs2val rs1val = rs2val
lines = lines + "# same values in both registers\n" lines = lines + "# same values in both registers\n"
lines = lines + "nop\n" lines = lines + "nop\n"
lines = lines + "li x" + str(rs1) + ", " + formatstr.format(rs1val) + " # initialize rs1 to a random value that should get changed\n" lines = lines + "li x" + str(rs1) + ", " + formatstr.format(rs1val) + " # initialize rs1\n"
lines = lines + "li x" + str(rs2) + ", " + formatstr.format(rs2val) + " # initialize rs2 to a random value that should get changed\n" lines = lines + "li x" + str(rs2) + ", " + formatstr.format(rs2val) + " # initialize rs2\n"
lines = lines + test + " x" + str(rs1) + ", x" + str(rs2) + ", some_label_for_sb_types_" + str(immval) + "+4" + " # perform operation \n" lines = lines + test + " x" + str(rs1) + ", x" + str(rs2) + ", some_label_for_btype_" + str(immval) + str(same) + " # perform operation \n"
lines = lines + "addi x0, x1, 1\n" lines = lines + "addi x0, x1, 1\n"
lines = lines + "some_label_for_sb_types_" + str(immval) + ":\n" lines = lines + "some_label_for_btype_" + str(immval)+ str(same) + ":\n"
lines = lines + "addi x0, x2, 2\n" lines = lines + "addi x0, x2, 2\n"
lines = lines + "nop\nnop\nnop\nnop\nnop\n" lines = lines + "nop\nnop\nnop\nnop\nnop\n"
elif (test in jtype):#["jal"]
lines = lines + "jal x" + str(rd) + ", 1f # perform operation\n"
lines = lines + "nop\n"
lines = lines + "1:\n"
elif (test in jalrtype):#["jalr"]
lines = lines + "la x" + str(rs1) + ", 1f\n"
lines = lines + "addi x" + str(rs1) + ", x" + str(rs1) + ", " + signedImm12(-immval) + " # add immediate to lower part of rs1\n"
lines = lines + "jalr x" + str(rd) + ", x" + str(rs1) + ", " + signedImm12(immval) + " # perform operation\n"
lines = lines + "nop\n"
lines = lines + "1:\n"
elif (test in utype):#["lui", "auipc"]
lines = lines + test + " x" + str(rd) + ", " + unsignedImm20(immval) + " # perform operation\n"
else: else:
pass pass
#print("Error: %s type not implemented yet" % test) #print("Error: %s type not implemented yet" % test)
f.write(lines) f.write(lines)
def writeHazardVector(desc, rs1a, rs2a, rda, rs1b, rs2b, rdb, test):
# consecutive R-type instructions to trigger hazards
lines = "\n# Testcase " + str(desc) + "\n"
lines = lines + test + " x" + str(rda) + ", x" + str(rs1a) + ", x" + str(rs2a) + " # perform first operation\n"
lines = lines + test + " x" + str(rdb) + ", x" + str(rs1b) + ", x" + str(rs2b) + " # perform second operation\n"
f.write(lines)
def randomize(): def randomize():
rs1 = randint(1, 31) rs1 = randint(1, 31)
rs2 = randint(1, 31) rs2 = randint(1, 31)
@ -93,177 +128,257 @@ def randomize():
rdval = randint(0, 2**xlen-1) rdval = randint(0, 2**xlen-1)
return [rs1, rs2, rd, rs1val, rs2val, immval, rdval] return [rs1, rs2, rd, rs1val, rs2val, immval, rdval]
def make_rd(test, storecmd, xlen): def make_rd(test, xlen):
for r in range(32): for r in range(32):
[rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize() [rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize()
desc = "cp_rd (Test destination rd = x" + str(r) + ")" desc = "cp_rd (Test destination rd = x" + str(r) + ")"
writeCovVector(desc, rs1, rs2, r, rs1val, rs2val, immval, rdval, test, storecmd, xlen) writeCovVector(desc, rs1, rs2, r, rs1val, rs2val, immval, rdval, test, xlen)
def make_rs1(test, storecmd, xlen): def make_rs1(test, xlen):
for r in range(32): for r in range(32):
[rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize() [rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize()
desc = "cp_rs1 (Test source rs1 = x" + str(r) + ")" desc = "cp_rs1 (Test source rs1 = x" + str(r) + ")"
writeCovVector(desc, r, rs2, rd, rs1val, rs2val, immval, rdval, test, storecmd, xlen) writeCovVector(desc, r, rs2, rd, rs1val, rs2val, immval, rdval, test, xlen)
def make_rs2(test, storecmd, xlen): def make_rs2(test, xlen):
for r in range(32): for r in range(32):
[rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize() [rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize()
desc = "cp_rs2 (Test source rs2 = x" + str(r) + ")" desc = "cp_rs2 (Test source rs2 = x" + str(r) + ")"
writeCovVector(desc, rs1, r, rd, rs1val, rs2val, immval, rdval, test, storecmd, xlen) writeCovVector(desc, rs1, r, rd, rs1val, rs2val, immval, rdval, test, xlen)
def make_rd_rs1(test, storecmd, xlen): def make_rd_rs1(test, xlen):
for r in range(32): for r in range(32):
[rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize() [rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize()
desc = "cmp_rd_rs1 (Test rd = rs1 = x" + str(r) + ")" desc = "cmp_rd_rs1 (Test rd = rs1 = x" + str(r) + ")"
writeCovVector(desc, r, rs2, r, rs1val, rs2val, immval, rdval, test, storecmd, xlen) writeCovVector(desc, r, rs2, r, rs1val, rs2val, immval, rdval, test, xlen)
def make_rd_rs2(test, storecmd, xlen): def make_rd_rs2(test, xlen):
for r in range(32): for r in range(32):
[rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize() [rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize()
desc = "cmp_rd_rs2 (Test rd = rs1 = x" + str(r) + ")" desc = "cmp_rd_rs2 (Test rd = rs1 = x" + str(r) + ")"
writeCovVector(desc, rs1, r, r, rs1val, rs2val, immval, rdval, test, storecmd, xlen) writeCovVector(desc, rs1, r, r, rs1val, rs2val, immval, rdval, test, xlen)
def make_rd_rs1_rs2(test, storecmd, xlen): def make_rd_rs1_rs2(test, xlen):
for r in range(32): for r in range(32):
[rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize() [rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize()
desc = "cmp_rd_rs1_rs2 (Test rd = rs1 = rs2 = x" + str(r) + ")" desc = "cmp_rd_rs1_rs2 (Test rd = rs1 = rs2 = x" + str(r) + ")"
writeCovVector(desc, r, r, r, rs1val, rs2val, immval, rdval, test, storecmd, xlen) writeCovVector(desc, r, r, r, rs1val, rs2val, immval, rdval, test, xlen)
def make_rs1_rs2(test, storecmd, xlen): def make_rs1_rs2(test, xlen):
for r in range(32): for r in range(32):
[rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize() [rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize()
desc = "cmp_rd_rs1_rs2 (Test rs1 = rs2 = x" + str(r) + ")" desc = "cmp_rs1_rs2 (Test rs1 = rs2 = x" + str(r) + ")"
writeCovVector(desc, r, r, rd, rs1val, rs2val, immval, rdval, test, storecmd, xlen) writeCovVector(desc, r, r, rd, rs1val, rs2val, immval, rdval, test, xlen)
def make_rs1_maxvals(test, storecmd, xlen): def make_rs1_maxvals(test, xlen):
for v in [0, 2**(xlen-1), 2**(xlen-1)-1, 2**xlen-1, 1, 2**(xlen-1)+1]: for v in [0, 2**(xlen-1), 2**(xlen-1)-1, 2**xlen-1, 1, 2**(xlen-1)+1]:
[rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize() [rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize()
desc = "cp_rs1_maxvals (Test source rs1 value = " + hex(v) + ")" desc = "cp_rs1_maxvals (Test source rs1 value = " + hex(v) + ")"
writeCovVector(desc, rs1, rs2, rd, v, rs2val, immval, rdval, test, storecmd, xlen) writeCovVector(desc, rs1, rs2, rd, v, rs2val, immval, rdval, test, xlen)
def make_rs2_maxvals(test, storecmd, xlen): def make_rs2_maxvals(test, xlen):
for v in [0, 2**(xlen-1), 2**(xlen-1)-1, 2**xlen-1, 1, 2**(xlen-1)+1]: for v in [0, 2**(xlen-1), 2**(xlen-1)-1, 2**xlen-1, 1, 2**(xlen-1)+1]:
[rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize() [rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize()
desc = "cp_rs2_maxvals (Test source rs2 value = " + hex(v) + ")" desc = "cp_rs2_maxvals (Test source rs2 value = " + hex(v) + ")"
writeCovVector(desc, rs1, rs2, rd, rs1val, v, immval, rdval, test, storecmd, xlen) writeCovVector(desc, rs1, rs2, rd, rs1val, v, immval, rdval, test, xlen)
def make_rd_maxvals(test, storecmd, xlen): def make_rd_maxvals(test, xlen):
for v in [0, 2**(xlen-1), 2**(xlen-1)-1, 2**xlen-1, 1, 2**(xlen-1)+1]: for v in [0, 2**(xlen-1), 2**(xlen-1)-1, 2**xlen-1, 1, 2**(xlen-1)+1]:
# rs1 = 0, rs2 = v, others are random
[rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize() [rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize()
desc = "cp_rd_maxvals (Test rd value = " + hex(v) + ")" desc = "cp_rd_maxvals (Test rd value = " + hex(v) + ")"
writeCovVector(desc, rs1, 0, rd, v, rs2val, immval, rdval, test, storecmd, xlen) writeCovVector(desc, rs1, 0, rd, v, rs2val, 0, rdval, test, xlen)
# rs1, rs2 = v, others are random
[rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize()
desc = "cp_rd_maxvals (Test rd value = " + hex(v) + ")"
writeCovVector(desc, rs1, rs2, rd, v, v, v, rdval, test, xlen)
# rs1 = all 1s, rs2 = v, others are random
[rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize()
desc = "cp_rd_maxvals (Test rd value = " + hex(v) + ")"
writeCovVector(desc, rs1, rs2, rd, v, -1, -1, rdval, test, xlen)
def make_rd_rs1_eqval(test, storecmd, xlen): def make_rd_rs1_eqval(test, xlen):
[rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize() [rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize()
desc = "cmp_rdm_rs1_eqval (Test rs1 = rd = " + hex(rs1val) + ")" desc = "cmp_rdm_rs1_eqval (Test rs1 = rd = " + hex(rs1val) + ")"
writeCovVector(desc, rs1, 0, rd, rdval, rs2val, immval, rdval, test, storecmd, xlen) writeCovVector(desc, rs1, 0, rd, rdval, rs2val, immval, rdval, test, xlen)
def make_rd_rs2_eqval(test, storecmd, xlen): def make_rd_rs2_eqval(test, xlen):
[rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize() [rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize()
desc = "cmp_rd_rs2_eqval (Test rs2 = rd = " + hex(rs2val) + ")" desc = "cmp_rd_rs2_eqval (Test rs2 = rd = " + hex(rs2val) + ")"
writeCovVector(desc, 0, rs2, rd, rs1val, rdval, immval, rdval, test, storecmd, xlen) writeCovVector(desc, 0, rs2, rd, rs1val, rdval, immval, rdval, test, xlen)
def make_rs1_rs2_eqval(test, storecmd, xlen): def make_rs1_rs2_eqval(test, xlen):
[rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize() [rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize()
desc = "cmp_rs1_rs2_eqval (Test rs1 = rs2 = " + hex(rs1val) + ")" desc = "cmp_rs1_rs2_eqval (Test rs1 = rs2 = " + hex(rs1val) + ")"
writeCovVector(desc, rs1, rs2, rd, rs1val, rs1val, immval, rdval, test, storecmd, xlen) writeCovVector(desc, rs1, rs2, rd, rs1val, rs1val, immval, rdval, test, xlen)
#def make_cp_gpr_hazard(test, storecmd, xlen): def make_cp_gpr_hazard(test, xlen):
# pass # *** to be implemented *** for haz in ["raw", "waw", "war"]:
for src in range(2):
[rs1a, rs2a, rda, rs1vala, rs2vala, immvala, rdvala] = randomize()
[rs1b, rs2b, rdb, rs1valb, rs2valb, immvalb, rdvalb] = randomize()
# set up hazard
if (haz == "raw"):
if (src):
rs2b = rda
else:
rs1b = rda
elif (haz == "waw"):
rdb = rda
elif (haz == "war"):
if (src):
rdb = rs2a
else:
rdb = rs1a
desc = "cmp_gpr_hazard " + haz + " test"
writeHazardVector(desc, rs1a, rs2a, rda, rs1b, rs2b, rdb, test)
def make_rs1_sign(test, storecmd, xlen): def make_rs1_sign(test, xlen):
for v in [1, -1]: for v in [1, -1]:
[rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize() [rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize()
rs1val = abs(rs1val % 2**(xlen-1)) * v; rs1val = abs(rs1val % 2**(xlen-1)) * v;
desc = "cp_rs1_sign (Test source rs1 value = " + hex(rs1val) + ")" desc = "cp_rs1_sign (Test source rs1 value = " + hex(rs1val) + ")"
writeCovVector(desc, rs1, rs2, rd, rs1val, rs2val, immval, rdval, test, storecmd, xlen) writeCovVector(desc, rs1, rs2, rd, rs1val, rs2val, immval, rdval, test, xlen)
def make_rs2_sign(test, storecmd, xlen): def make_rs2_sign(test, xlen):
for v in [1, -1]: for v in [1, -1]:
[rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize() [rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize()
rs2val = abs(rs2val % 2**(xlen-1)) * v; rs2val = abs(rs2val % 2**(xlen-1)) * v;
desc = "cp_rs2_sign (Test source rs2 value = " + hex(rs2val) + ")" desc = "cp_rs2_sign (Test source rs2 value = " + hex(rs2val) + ")"
writeCovVector(desc, rs1, rs2, rd, rs1val, rs2val, immval, rdval, test, storecmd, xlen) writeCovVector(desc, rs1, rs2, rd, rs1val, rs2val, immval, rdval, test, xlen)
def make_cr_rs1_rs2_sign(test, storecmd, xlen): def make_cr_rs1_rs2_sign(test, xlen):
for v1 in [1, -1]: for v1 in [1, -1]:
for v2 in [1, -1]: for v2 in [1, -1]:
[rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize() [rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize()
rs1val = abs(rs1val % 2**(xlen-1)) * v1; rs1val = abs(rs1val % 2**(xlen-1)) * v1;
rs2val = abs(rs2val % 2**(xlen-1)) * v2; rs2val = abs(rs2val % 2**(xlen-1)) * v2;
desc = "cr_rs1_rs2 (Test source rs1 = " + hex(rs1val) + " rs2 = " + hex(rs2val) + ")" desc = "cr_rs1_rs2 (Test source rs1 = " + hex(rs1val) + " rs2 = " + hex(rs2val) + ")"
writeCovVector(desc, rs1, rs2, rd, rs1val, rs2val, immval, rdval, test, storecmd, xlen) writeCovVector(desc, rs1, rs2, rd, rs1val, rs2val, immval, rdval, test, xlen)
def write_tests(coverpoints, test, storecmd, xlen): def make_imm_zero(test, xlen):
[rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize()
desc = "cp_imm_zero"
writeCovVector(desc, rs1, rs2, rd, rs1val, rs2val, 0, rdval, test, xlen)
def make_j_imm_ones_zeros(test, xlen):
for align in range(2,19):
lines = "\n# Testcase cp_imm_ones_zeros " + str(align) + "\n"
lines = lines + "li x1, " + formatstr.format(randint(0, 2**xlen-1)) + "\n"
lines = lines + "jal x20, 1f # jump to aligned address to stress immediate\n"
lines = lines + ".align " + str(align) + "\n"
lines = lines + "1:\n"
f.write(lines)
def make_offset(test, xlen):
if (test in btype):
lines = "\n# Testcase cp_offset\n"
lines = lines + "j 2f # jump past backward branch target\n"
lines = lines + "1: j 3f # backward branch target: jump past backward branch\n"
lines = lines + "2: " + test + " x0, x0, 1b # backward branch\n"
lines = lines + "3: nop # done with sequence\n"
f.write(lines)
def make_mem_hazard(test, xlen):
lines = "\n# Testcase mem_hazard (no dependency)\n"
lines = lines + "la x1, scratch\n"
lines = lines + test + " x2, 0(x1)\n"
f.write(lines)
def make_cr_rs1_imm(test, xlen):
desc = "cp_cr_rs1_imm"
[rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize()
for s1 in range(2):
for s2 in range(3):
if (s1):
rs1v = -abs(rs1val)
else:
rs1v = abs(rs1val)
if (s2 == 0):
immv = 0
elif (s2 == 1):
immv = abs(immval)
else:
immv = -abs(immval)
writeCovVector(desc, rs1, rs2, rd, rs1v, rs2val, immv, rdval, test, xlen)
def make_imm_shift(test, xlen):
desc = "cp_imm_shift"
for shift in range(0, xlen):
[rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize()
writeCovVector(desc, rs1, rs2, rd, rs1val, rs2val, shift, rdval, test, xlen)
def write_tests(coverpoints, test, xlen):
for coverpoint in coverpoints: for coverpoint in coverpoints:
if (coverpoint == "cp_asm_count"): if (coverpoint == "cp_asm_count"):
pass pass
elif (coverpoint == "cp_rd"): elif (coverpoint == "cp_rd"):
make_rd(test, storecmd, xlen) make_rd(test, xlen)
elif (coverpoint == "cp_rs1"): elif (coverpoint == "cp_rs1"):
make_rs1(test, storecmd, xlen) make_rs1(test, xlen)
elif (coverpoint == "cp_rs2"): elif (coverpoint == "cp_rs2"):
make_rs2(test, storecmd, xlen) make_rs2(test, xlen)
elif (coverpoint == "cmp_rd_rs1"): elif (coverpoint == "cmp_rd_rs1"):
make_rd_rs1(test, storecmd, xlen) make_rd_rs1(test, xlen)
elif (coverpoint == "cmp_rd_rs2"): elif (coverpoint == "cmp_rd_rs2"):
make_rd_rs2(test, storecmd, xlen) make_rd_rs2(test, xlen)
elif (coverpoint == "cmp_rd_rs1_rs2"): elif (coverpoint == "cmp_rd_rs1_rs2"):
make_rd_rs1_rs2(test, storecmd, xlen) make_rd_rs1_rs2(test, xlen)
elif (coverpoint == "cmp_rd_rs1_eq"): elif (coverpoint == "cmp_rd_rs1_eq"):
pass # duplicate of cmp_rd_rs1 pass # duplicate of cmp_rd_rs1
elif (coverpoint == "cmp_rd_rs2_eq"): elif (coverpoint == "cmp_rd_rs2_eq"):
pass # duplicate of cmp_rd_rs2 pass # duplicate of cmp_rd_rs2
elif (coverpoint == "cmp_rs1_rs2_eq"): elif (coverpoint == "cmp_rs1_rs2_eq"):
make_rs1_rs2(test, storecmd, xlen) make_rs1_rs2(test, xlen)
elif (coverpoint == "cp_rs1_maxvals"): elif (coverpoint == "cp_rs1_maxvals"):
make_rs1_maxvals(test, storecmd, xlen) make_rs1_maxvals(test, xlen)
elif (coverpoint == "cp_rs2_maxvals"): elif (coverpoint == "cp_rs2_maxvals"):
make_rs2_maxvals(test, storecmd, xlen) make_rs2_maxvals(test, xlen)
elif (coverpoint == "cp_rd_maxvals"): elif (coverpoint == "cp_rd_maxvals"):
make_rd_maxvals(test, storecmd, xlen) make_rd_maxvals(test, xlen)
elif (coverpoint == "cmp_rd_rs1_eqval"): elif (coverpoint == "cmp_rd_rs1_eqval"):
make_rd_rs1_eqval(test, storecmd, xlen) make_rd_rs1_eqval(test, xlen)
elif (coverpoint == "cmp_rd_rs2_eqval"): elif (coverpoint == "cmp_rd_rs2_eqval"):
make_rd_rs2_eqval(test, storecmd, xlen) make_rd_rs2_eqval(test, xlen)
elif (coverpoint == "cmp_rs1_rs2_eqval"): elif (coverpoint == "cmp_rs1_rs2_eqval"):
make_rs1_rs2_eqval(test, storecmd, xlen) make_rs1_rs2_eqval(test, xlen)
elif (coverpoint == "cp_rs1_sign"): elif (coverpoint == "cp_rs1_sign"):
make_rs1_sign(test, storecmd, xlen) make_rs1_sign(test, xlen)
elif (coverpoint == "cp_rs2_sign"): elif (coverpoint == "cp_rs2_sign"):
make_rs2_sign(test, storecmd, xlen) make_rs2_sign(test, xlen)
elif (coverpoint == "cp_rd_sign"): elif (coverpoint == "cp_rd_sign"):
pass #TODO hope already covered by rd_maxvals pass #TODO hope already covered by rd_maxvals
elif (coverpoint == "cr_rs1_rs2"): elif (coverpoint == "cr_rs1_rs2"):
make_cr_rs1_rs2_sign(test, storecmd, xlen) make_cr_rs1_rs2_sign(test, xlen)
elif (coverpoint == "cp_gpr_hazard"):
make_cp_gpr_hazard(test, xlen)
elif (coverpoint == "cp_rs1_toggle"): elif (coverpoint == "cp_rs1_toggle"):
pass #TODO toggle not needed and seems to be covered by other things pass #TODO toggle not needed and seems to be covered by other things
elif (coverpoint == "cp_rs2_toggle"): elif (coverpoint == "cp_rs2_toggle"):
pass #TODO toggle not needed and seems to be covered by other things pass #TODO toggle not needed and seems to be covered by other things
elif (coverpoint == "cp_rd_toggle"): elif (coverpoint == "cp_rd_toggle"):
pass #TODO toggle not needed and seems to be covered by other things pass #TODO toggle not needed and seems to be covered by other things
elif (coverpoint == "cp_gpr_hazard"):
pass #TODO not yet implemented
elif (coverpoint == "cp_imm_sign"): elif (coverpoint == "cp_imm_sign"):
pass #TODO make_imm_zero(test, xlen)
elif (coverpoint == "cr_rs1_imm"): elif (coverpoint == "cr_rs1_imm"):
pass #TODO (not if crosses are not needed) make_cr_rs1_imm(test, xlen)
elif (coverpoint == "cp_imm_ones_zeros"): elif (coverpoint == "cp_imm_ones_zeros"):
pass #TODO if (test in jtype):
make_j_imm_ones_zeros(test, xlen)
elif (coverpoint == "cp_mem_hazard"): elif (coverpoint == "cp_mem_hazard"):
pass #TODO make_mem_hazard(test, xlen)
elif (coverpoint == "cp_imm_zero"): elif (coverpoint == "cp_imm_zero"):
pass #TODO make_imm_zero(test, xlen)
elif (coverpoint == "cp_mem_unaligned"): elif (coverpoint == "cp_mem_unaligned"):
pass #TODO pass # seems this should be part of privileged tests
elif (coverpoint == "cp_offset"): elif (coverpoint == "cp_offset"):
pass #TODO make_offset(test, xlen)
elif (coverpoint == "cr_nord_rs1_rs2"): elif (coverpoint == "cr_nord_rs1_rs2"):
pass #TODO (not if crosses are not needed) pass #TODO (not if crosses are not needed)
elif (coverpoint == "cp_imm_shift"): elif (coverpoint == "cp_imm_shift"):
pass #TODO make_imm_shift(test, xlen)
elif (coverpoint == "cp_rd_boolean"): elif (coverpoint == "cp_rd_boolean"):
pass #TODO pass # covered by other generators
else: else:
print("Warning: " + coverpoint + " not implemented yet for " + test) print("Warning: " + coverpoint + " not implemented yet for " + test)
@ -301,10 +416,14 @@ rtype = ["add", "sub", "sll", "slt", "sltu", "xor", "srl", "sra", "or", "and",
"mul", "mulh", "mulhsu", "mulhu", "div", "divu", "rem", "remu", "mul", "mulh", "mulhsu", "mulhu", "div", "divu", "rem", "remu",
"mulw", "divw", "divuw", "remw", "remuw"] "mulw", "divw", "divuw", "remw", "remuw"]
loaditype = ["lb", "lh", "lw", "ld", "lbu", "lhu", "lwu"] loaditype = ["lb", "lh", "lw", "ld", "lbu", "lhu", "lwu"]
shiftitype = ["slli", "srli", "srai"] shiftitype = ["slli", "srli", "srai", "slliw", "srliw", "sraiw"]
itype = ["addi", "slti", "sltiu", "xori", "ori", "andi"] shiftiwtype = ["slliw", "srliw", "sraiw"]
stypes = ["sb", "sh", "sw", "sd"] itype = ["addi", "slti", "sltiu", "xori", "ori", "andi", "addiw"]
btypes = ["beq", "bne", "blt", "bge", "bltu", "bgeu"] stype = ["sb", "sh", "sw", "sd"]
btype = ["beq", "bne", "blt", "bge", "bltu", "bgeu"]
jtype = ["jal"]
jalrtype = ["jalr"]
utype = ["lui", "auipc"]
# TODO: auipc missing, check whatelse is missing in ^these^ types # TODO: auipc missing, check whatelse is missing in ^these^ types
coverpoints = getcovergroups(coverdefdir, coverfiles) coverpoints = getcovergroups(coverdefdir, coverfiles)
@ -327,12 +446,11 @@ for xlen in xlens:
else: else:
storecmd = "sd" storecmd = "sd"
wordsize = 8 wordsize = 8
for test in coverpoints.keys():
# pathname = "../wally-riscv-arch-test/riscv-test-suite/rv" + str(xlen) + "i_m/I/"
WALLY = os.environ.get('WALLY') WALLY = os.environ.get('WALLY')
pathname = WALLY+"/tests/functcov/rv" + str(xlen) + "/I/" pathname = WALLY+"/tests/functcov/rv" + str(xlen) + "/I/"
cmd = "mkdir -p " + pathname cmd = "mkdir -p " + pathname + " ; rm -f " + pathname + "/*" # make directory and remove old tests in dir
os.system(cmd) os.system(cmd)
for test in coverpoints.keys():
basename = "WALLY-COV-" + test basename = "WALLY-COV-" + test
fname = pathname + "/" + basename + ".S" fname = pathname + "/" + basename + ".S"
@ -340,9 +458,9 @@ for xlen in xlens:
f = open(fname, "w") f = open(fname, "w")
line = "///////////////////////////////////////////\n" line = "///////////////////////////////////////////\n"
f.write(line) f.write(line)
lines="// "+fname+ "\n// " + author + "\n" line="// "+fname+ "\n// " + author + "\n"
f.write(lines) f.write(line)
line ="// Created " + str(datetime.now()) line ="// Created " + str(datetime.now()) + "\n"
f.write(line) f.write(line)
# insert generic header # insert generic header
@ -355,8 +473,8 @@ for xlen in xlens:
#if (test not in rtests): #if (test not in rtests):
# exit("Error: %s not implemented yet" % test) # exit("Error: %s not implemented yet" % test)
#else: #else:
# write_rtype_arith_vectors(test, storecmd, xlen) # write_rtype_arith_vectors(test, xlen)
write_tests(coverpoints[test], test, storecmd, xlen) write_tests(coverpoints[test], test, xlen)
# print footer # print footer
line = "\n.EQU NUMTESTS," + str(1) + "\n\n" line = "\n.EQU NUMTESTS," + str(1) + "\n\n"
@ -366,9 +484,6 @@ for xlen in xlens:
f.write(line) f.write(line)
# Finish # Finish
# lines = ".fill " + str(testnum) + ", " + str(wordsize) + ", -1\n"
# lines = lines + "\nRV_COMPLIANCE_DATA_END\n"
f.write(lines)
f.close() f.close()

View file

@ -2,4 +2,10 @@
self_loop: self_loop:
j self_loop j self_loop
.data
.align 4
scratch:
.bss 8
.end .end