diff --git a/.gitignore b/.gitignore index ec5520c64..19dbba458 100644 --- a/.gitignore +++ b/.gitignore @@ -101,6 +101,7 @@ sim/localhistory_m6k10_results_april24.txt sim/cfi/* sim/branch/* sim/covhtmlreport/ +sim/*/*Cache.log # Questa sim/questa/logs diff --git a/.gitmodules b/.gitmodules index 54ed892d3..1dc9e38aa 100644 --- a/.gitmodules +++ b/.gitmodules @@ -31,3 +31,6 @@ [submodule "cvw-arch-verif"] path = addins/cvw-arch-verif url = https://github.com/openhwgroup/cvw-arch-verif +[submodule "addins/riscvISACOV"] + path = addins/riscvISACOV + url = https://github.com/riscv-verification/riscvISACOV.git diff --git a/addins/cvw-arch-verif b/addins/cvw-arch-verif index 9d54f3f8e..189974e49 160000 --- a/addins/cvw-arch-verif +++ b/addins/cvw-arch-verif @@ -1 +1 @@ -Subproject commit 9d54f3f8e902bb85db74305993d2fc03796b57bc +Subproject commit 189974e497d7b8d2c08bb1d151b1ccdeaf3a64c9 diff --git a/addins/riscvISACOV b/addins/riscvISACOV new file mode 160000 index 000000000..ac9fa2d38 --- /dev/null +++ b/addins/riscvISACOV @@ -0,0 +1 @@ +Subproject commit ac9fa2d386c0cb2f44e1e1e83a555d585034dfa3 diff --git a/bin/CacheSim.py b/bin/CacheSim.py index f6b2cb7e1..d07ded9ea 100755 --- a/bin/CacheSim.py +++ b/bin/CacheSim.py @@ -41,7 +41,6 @@ # Add -d or --dist to report the distribution of loads, stores, and atomic ops. # These distributions may not add up to 100; this is because of flushes or invalidations. -import sys import math import argparse import os @@ -193,7 +192,7 @@ class Cache: return self.__str__() -if __name__ == "__main__": +def main(): parser = argparse.ArgumentParser(description="Simulates a L1 cache.") parser.add_argument('numlines', type=int, help="The number of lines per way (a power of 2)", metavar="L") parser.add_argument('numways', type=int, help="The number of ways (a power of 2)", metavar='W') @@ -207,7 +206,7 @@ if __name__ == "__main__": args = parser.parse_args() cache = Cache(args.numlines, args.numways, args.addrlen, args.taglen) extfile = os.path.expanduser(args.file) - nofails = True + mismatches = 0 if args.perf: hits = 0 @@ -269,7 +268,7 @@ if __name__ == "__main__": if not result == lninfo[2]: print("Result mismatch at address", lninfo[0]+ ". Wally:", lninfo[2]+", Sim:", result) - nofails = False + mismatches += 1 if args.dist: percent_loads = str(round(100*loads/totalops)) percent_stores = str(round(100*stores/totalops)) @@ -280,5 +279,9 @@ if __name__ == "__main__": ratio = round(hits/misses,3) print("There were", hits, "hits and", misses, "misses. The hit/miss ratio was", str(ratio)+".") - if nofails: - print("SUCCESS! There were no mismatches between Wally and the sim.") \ No newline at end of file + if mismatches == 0: + print("SUCCESS! There were no mismatches between Wally and the sim.") + return mismatches + +if __name__ == '__main__': + exit(main()) diff --git a/bin/regression-wally b/bin/regression-wally index 1c3cde58e..512856602 100755 --- a/bin/regression-wally +++ b/bin/regression-wally @@ -517,6 +517,8 @@ def main(): TIMEOUT_DUR = 60*1440 # 1 day elif args.testfloat: TIMEOUT_DUR = 30*60 # seconds + elif args.nightly: + TIMEOUT_DUR = 30*60 # seconds else: TIMEOUT_DUR = 10*60 # seconds diff --git a/bin/wsim b/bin/wsim index 986957a3c..3018c5caf 100755 --- a/bin/wsim +++ b/bin/wsim @@ -28,8 +28,10 @@ parser.add_argument("--tb", "-t", help="Testbench", choices=["testbench", "testb 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("--fcov", "-f", help="Functional Coverage, implies lockstep", action="store_true") +parser.add_argument("--fcov2", "-f2", help="Functional Coverage, implies lockstep", action="store_true") parser.add_argument("--fcovrvvi", "-fr", help="Functional Coverage RVVI", action="store_true") parser.add_argument("--args", "-a", help="Optional arguments passed to simulator via $value$plusargs", default="") +parser.add_argument("--params", "-p", help="Optional top-level parameter overrides of the form param=value", default="") 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("--locksteplog", "-b", help="Retired instruction number to be begin logging.", default=0) @@ -66,7 +68,7 @@ if(args.testsuite.endswith('.elf') and args.elf == ""): # No --elf argument; che # Validate arguments -if (args.gui or args.ccov or args.fcov or args.fcovrvvi or args.lockstep): +if (args.gui or args.ccov or args.fcov or args.fcov2 or args.fcovrvvi or args.lockstep): if args.sim not in ["questa", "vcs"]: print("Option only supported for Questa and VCS") exit(1) @@ -75,16 +77,30 @@ if (args.vcd): args.args += " -DMAKEVCD=1" if (args.rvvi): - args.args += " -GRVVI_SYNTH_SUPPORTED=1" + args.params += " RVVI_SYNTH_SUPPORTED=1 " + +if (args.tb == "testbench_fp"): + args.params += " TEST=\"" + args.testsuite + "\" " # if lockstep is enabled, then we need to pass the Imperas lockstep arguments if(int(args.locksteplog) >= 1): EnableLog = 1 else: EnableLog = 0 +if((args.lockstep or args.fcov or args.fcov2) and args.sim == "questa"): + prefix = "IMPERAS_TOOLS=" + WALLY + "/config/"+args.config+"/imperas.ic" + prefix = "MTI_VCO_MODE=64 " + prefix +else: + prefix = "" + if (args.lockstep): - prefix = "IMPERAS_TOOLS=" + WALLY + "/sim/imperas.ic" if(args.locksteplog != 0): ImperasPlusArgs = " +IDV_TRACE2LOG=" + str(EnableLog) + " +IDV_TRACE2LOG_AFTER=" + str(args.locksteplog) else: ImperasPlusArgs = "" if(args.fcov): + CovEnableStr = "1" if int(args.covlog) > 0 else "0" + if(args.covlog >= 1): EnableLog = 1 + else: EnableLog = 0 + ImperasPlusArgs = " +IDV_TRACE2COV=" + str(EnableLog) + " +TRACE2LOG_AFTER=" + str(args.covlog) + " +TRACE2COV_ENABLE=" + CovEnableStr + suffix = "" + if(args.fcov2): CovEnableStr = "1" if int(args.covlog) > 0 else "0"; if(args.covlog >= 1): EnableLog = 1 else: EnableLog = 0 @@ -94,16 +110,19 @@ if (args.lockstep): CovEnableStr = "" suffix = "--lockstep" else: - prefix = "" ImperasPlusArgs = "" suffix = "" -flags = suffix + " " + ImperasPlusArgs +flags = suffix +args.args += ImperasPlusArgs + # other flags if (args.ccov): flags += " --ccov" if (args.fcov): flags += " --fcov" +if (args.fcov2): + flags += " --fcov2" if (args.fcovrvvi): flags += "--fcovrvvi" @@ -119,15 +138,18 @@ cd = "cd $WALLY/sim/" +args.sim # per-simulator launch if (args.sim == "questa"): + if (args.gui) and (args.tb == "testbench"): + args.params += "DEBUG=1" + if (ElfFile != ""): + args.args += " " + ElfFile + if (args.args != ""): + args.args = " --args \\\"" + args.args + "\\\"" + if (args.params != ""): + args.params = " --params \\\"" + args.params + "\\\"" # Questa cannot accept more than 9 arguments. fcov implies lockstep - if (args.tb == "testbench_fp"): - args.args = " -GTEST=\"" + args.testsuite + "\" " + args.args - cmd = "do wally.do " + args.config + " " + args.testsuite + " " + args.tb + " " + args.args + " " + ElfFile + " " + flags + cmd = "do wally.do " + args.config + " " + args.testsuite + " " + args.tb + " " + args.args + " " + args.params + " " + flags if (args.gui): # launch Questa with GUI; add +acc to keep variables accessible - if(args.tb == "testbench"): - cmd = cd + "; " + prefix + " vsim -do \"" + cmd + " +acc -GDEBUG=1\"" - elif(args.tb == "testbench_fp"): - cmd = cd + "; " + prefix + " vsim -do \"" + cmd + " +acc\"" + cmd = cd + "; " + prefix + " vsim -do \"" + cmd + " +acc\"" else: # launch Questa in batch mode cmd = cd + "; " + prefix + " vsim -c -do \"" + cmd + "\"" print("Running Questa with command: " + cmd) @@ -135,17 +157,23 @@ if (args.sim == "questa"): elif (args.sim == "verilator"): # PWD=${WALLY}/sim CONFIG=rv64gc TESTSUITE=arch64i print(f"Running Verilator on {args.config} {args.testsuite}") - os.system(f"/usr/bin/make -C {regressionDir}/verilator WALLYCONF={args.config} TEST={args.testsuite} TESTBENCH={args.tb} EXTRA_ARGS='{args.args}'") + os.system(f"/usr/bin/make -C {regressionDir}/verilator WALLYCONF={args.config} TEST={args.testsuite} TESTBENCH={args.tb} PLUS_ARGS=\"{args.args}\" PARAM_ARGS=\"{args.params}\"") elif (args.sim == "vcs"): + print("wsim params: " + args.params) print(f"Running VCS on " + args.config + " " + args.testsuite) - if (args.gui): - args.args += "gui" + # if (args.gui): + # flags += " --gui" if (args.args == ""): vcsargs = "" else: - vcsargs = " --args " + args.args + vcsargs = " --args \"" + args.args + "\" " + if (args.params == ""): + vcsparams = "" + else: + vcsparams = " --params \"" + args.params + "\" " + print("VCS params: " + vcsparams) if (ElfFile != ""): ElfFile = " --elffile " + ElfFile - cmd = cd + "; " + prefix + " ./run_vcs " + args.config + " " + args.testsuite + vcsargs + ElfFile + " " + flags + cmd = cd + "; " + prefix + " ./run_vcs " + args.config + " " + args.testsuite + " " + " --tb " + args.tb + " " + vcsargs + vcsparams + ElfFile + " " + flags print(cmd) os.system(cmd) diff --git a/config/rv32gc/imperas.ic b/config/rv32gc/imperas.ic new file mode 100644 index 000000000..c9b8292f2 --- /dev/null +++ b/config/rv32gc/imperas.ic @@ -0,0 +1,119 @@ +# imperas.ic +# Initialization file for ImperasDV lock step simulation +# David_Harris@hmc.edu 15 August 2024 +# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 + +#--mpdconsole +#--gdbconsole +#--showoverrides +#--showcommands + +# Core settings +--variant RV32GC # for RV32GC +--override cpu/priv_version=1.12 +--override cpu/user_version=20191213 +# arch +--override cpu/mimpid=0x100 +--override cpu/mvendorid=0x602 +--override cpu/marchid=0x24 +--override refRoot/cpu/tvec_align=64 +--override refRoot/cpu/envcfg_mask=1 # dh 1/26/24 this should be deleted when ImperasDV is updated to allow envcfg.FIOM to be written + +# bit manipulation +--override cpu/add_Extensions=B +--override cpu/bitmanip_version=1.0.0 +--override cpu/misa_B_Zba_Zbb_Zbs=T + +# More extensions +--override cpu/Zcb=T +--override cpu/Zicond=T +--override cpu/Zfh=T +--override cpu/Zfa=T + +# Cache block operations +--override cpu/Zicbom=T +--override cpu/Zicbop=T +--override cpu/Zicboz=T +--override cmomp_bytes=64 # Zic64b +--override cmoz_bytes=64 # Zic64b +--override lr_sc_grain=8 # Za64rs requires <=64; we use native word size + +# 64 KiB continuous huge pages supported +#--override cpu/Svpbmt=F +#--override cpu/Svnapot_page_mask=65536 + +# SV32 supported +--override cpu/Sv_modes=3 +#--showoverrides + +--override cpu/Svinval=T + + +# clarify +#--override refRoot/cpu/mtvec_sext=F + +--override cpu/tval_ii_code=T + +#--override cpu/time_undefined=T +#--override cpu/cycle_undefined=T +#--override cpu/instret_undefined=T +#--override cpu/hpmcounter_undefined=T + +--override cpu/reset_address=0x80000000 + +--override cpu/unaligned=F # Zicclsm (should be true) +--override cpu/ignore_non_leaf_DAU=1 +--override cpu/wfi_is_nop=T +--override cpu/misa_Extensions_mask=0x0 # MISA not writable +--override cpu/Sstc=T + +# Enable SVADU hardware update of A/D bits when menvcfg.ADUE=1 +--override cpu/Svadu=T +#--override cpu/updatePTEA=F +#--override cpu/updatePTED=F + +--override cpu/PMP_registers=16 +--override cpu/PMP_undefined=T + +# mstatus.FS is set dirty on any write to a FPR, or when a fp operation signals an exception +--override cpu/mstatus_fs_mode=write_1 + +# PMA Settings +# 'r': read access allowed +# 'w': write access allowed +# 'x': execute access allowed +# 'a': aligned access required +# 'A': atomic instructions NOT allowed (actually USER1 privilege needed) +# 'P': push/pop instructions NOT allowed (actually USER2 privilege needed) +# '1': 1-byte accesses allowed +# '2': 2-byte accesses allowed +# '4': 4-byte accesses allowed +# '8': 8-byte accesses allowed +# '-', space: ignored (use for input string formatting). +# +# SVxx Memory 0x0000000000 0x7FFFFFFFFF +# +--callcommand refRoot/cpu/setPMA -lo 0x0000000000 -hi 0xFFFFFFFFFFFFFFFFFF -attributes " ---a-- ---- " # All memory inaccessible unless defined otherwise +--callcommand refRoot/cpu/setPMA -lo 0x0000000000 -hi 0x7FFFFFFFFF -attributes " ---a-- ---- " # INITIAL +--callcommand refRoot/cpu/setPMA -lo 0x0000001000 -hi 0x0000001FFF -attributes " r-x-A- 1248 " # BOOTROM +--callcommand refRoot/cpu/setPMA -lo 0x0000012100 -hi 0x000001211F -attributes " rw-aA- --48 " # SDC +--callcommand refRoot/cpu/setPMA -lo 0x0002000000 -hi 0x000200FFFF -attributes " rw-aA- 1248 " # CLINT +--callcommand refRoot/cpu/setPMA -lo 0x000C000000 -hi 0x000FFFFFFF -attributes " rw-aA- --4- " # PLIC +--callcommand refRoot/cpu/setPMA -lo 0x0010000000 -hi 0x0010000007 -attributes " rw-aA- 1--- " # UART0 error - 0x10000000 - 0x100000FF +--callcommand refRoot/cpu/setPMA -lo 0x0010060000 -hi 0x00100600FF -attributes " rw-aA- --4- " # GPIO error - 0x10069000 - 0x100600FF +--callcommand refRoot/cpu/setPMA -lo 0x0010040000 -hi 0x0010040FFF -attributes " rw-aA- --4- " # SPI error - 0x10040000 - 0x10040FFF +--callcommand refRoot/cpu/setPMA -lo 0x0080000000 -hi 0x008FFFFFFF -attributes " rwx--- 1248 " # UNCORE_RAM + +# Enable the Imperas instruction coverage +#-extlib refRoot/cpu/cv=imperas.com/intercept/riscvInstructionCoverage/1.0 +#-override refRoot/cpu/cv/cover=basic +#-override refRoot/cpu/cv/extensions=RV32I + +# Add Imperas simulator application instruction tracing +# uncomment these to provide tracing +--verbose --trace --tracechange --traceshowicount --tracemode -tracemem ASX --monitornetschange # --traceafter 300000000 +--override cpu/debugflags=6 --override cpu/verbose=1 +--override cpu/show_c_prefix=T + +# Store simulator output to logfile +--output imperas.log diff --git a/sim/imperas.ic b/config/rv64gc/imperas.ic similarity index 95% rename from sim/imperas.ic rename to config/rv64gc/imperas.ic index b3485aff7..fa9b56dfc 100644 --- a/sim/imperas.ic +++ b/config/rv64gc/imperas.ic @@ -109,9 +109,9 @@ # Add Imperas simulator application instruction tracing # uncomment these to provide tracing ---verbose --trace --tracechange --traceshowicount --tracemode -tracemem ASX --monitornetschange # --traceafter 300000000 ---override cpu/debugflags=6 --override cpu/verbose=1 ---override cpu/show_c_prefix=T +#--verbose --trace --tracechange --traceshowicount --tracemode -tracemem ASX --monitornetschange # --traceafter 300000000 +#--override cpu/debugflags=6 --override cpu/verbose=1 +#--override cpu/show_c_prefix=T # Store simulator output to logfile --output imperas.log diff --git a/fpga/constraints/constraints-ArtyA7.xdc b/fpga/constraints/constraints-ArtyA7.xdc index 7eb3598f5..924cd1aea 100644 --- a/fpga/constraints/constraints-ArtyA7.xdc +++ b/fpga/constraints/constraints-ArtyA7.xdc @@ -4,7 +4,7 @@ # This clock is not used by wally or the AHB Bus. However it is used by the AXI BUS on the DD3 IP. #create_generated_clock -name CLKDiv64_Gen -source [get_pins wallypipelinedsoc/uncore.uncore/sdc.SDC/sd_top/slow_clk_divider/clkMux/I0] -multiply_by 1 -divide_by 1 [get_pins wallypipelinedsoc/uncore.uncore/sdc.SDC/sd_top/slow_clk_divider/clkMux/O] -create_generated_clock -name SPISDCClock -source [get_pins clk_out3_xlnx_mmcm] -multiply_by 1 -divide_by 1 [get_pins wallypipelinedsoc/uncore.uncore/sdc.sdc/SPICLK] +create_generated_clock -name SPISDCClock -source [get_pins mmcm/clk_out3] -multiply_by 1 -divide_by 1 [get_pins wallypipelinedsoc/uncoregen.uncore/sdc.sdc/SPICLK] ##### clock ##### set_property PACKAGE_PIN E3 [get_ports default_100mhz_clk] @@ -45,8 +45,8 @@ set_property IOSTANDARD LVCMOS33 [get_ports {GPI[3]}] set_property IOSTANDARD LVCMOS33 [get_ports {GPI[2]}] set_property IOSTANDARD LVCMOS33 [get_ports {GPI[1]}] set_property IOSTANDARD LVCMOS33 [get_ports {GPI[0]}] -set_input_delay -clock [get_clocks clk_out3_xlnx_mmcm] -min -add_delay 0.000 [get_ports {GPI[*]}] -set_input_delay -clock [get_clocks clk_out3_xlnx_mmcm] -max -add_delay 0.000 [get_ports {GPI[*]}] +set_input_delay -clock [get_clocks clk_out3_mmcm] -min -add_delay 0.000 [get_ports {GPI[*]}] +set_input_delay -clock [get_clocks clk_out3_mmcm] -max -add_delay 0.000 [get_ports {GPI[*]}] set_max_delay -from [get_ports {GPI[*]}] 20.000 ##### GPO #### @@ -62,8 +62,8 @@ set_property IOSTANDARD LVCMOS33 [get_ports {GPO[1]}] set_property IOSTANDARD LVCMOS33 [get_ports {GPO[0]}] set_max_delay -to [get_ports {GPO[*]}] 20.000 -set_output_delay -clock [get_clocks clk_out3_xlnx_mmcm] -min -add_delay 0.000 [get_ports {GPO[*]}] -set_output_delay -clock [get_clocks clk_out3_xlnx_mmcm] -max -add_delay 0.000 [get_ports {GPO[*]}] +set_output_delay -clock [get_clocks clk_out3_mmcm] -min -add_delay 0.000 [get_ports {GPO[*]}] +set_output_delay -clock [get_clocks clk_out3_mmcm] -max -add_delay 0.000 [get_ports {GPO[*]}] ##### UART ##### @@ -75,24 +75,24 @@ set_max_delay -to [get_ports UARTSout] 20.000 set_property IOSTANDARD LVCMOS33 [get_ports UARTSin] set_property IOSTANDARD LVCMOS33 [get_ports UARTSout] set_property DRIVE 4 [get_ports UARTSout] -set_input_delay -clock [get_clocks clk_out3_xlnx_mmcm] -min -add_delay 0.000 [get_ports UARTSin] -set_input_delay -clock [get_clocks clk_out3_xlnx_mmcm] -max -add_delay 0.000 [get_ports UARTSin] -set_output_delay -clock [get_clocks clk_out3_xlnx_mmcm] -min -add_delay 0.000 [get_ports UARTSout] -set_output_delay -clock [get_clocks clk_out3_xlnx_mmcm] -max -add_delay 0.000 [get_ports UARTSout] +set_input_delay -clock [get_clocks clk_out3_mmcm] -min -add_delay 0.000 [get_ports UARTSin] +set_input_delay -clock [get_clocks clk_out3_mmcm] -max -add_delay 0.000 [get_ports UARTSin] +set_output_delay -clock [get_clocks clk_out3_mmcm] -min -add_delay 0.000 [get_ports UARTSout] +set_output_delay -clock [get_clocks clk_out3_mmcm] -max -add_delay 0.000 [get_ports UARTSout] ##### reset ##### #************** reset is inverted -set_input_delay -clock [get_clocks clk_out3_xlnx_mmcm] -min -add_delay 2.000 [get_ports resetn] -set_input_delay -clock [get_clocks clk_out3_xlnx_mmcm] -max -add_delay 2.000 [get_ports resetn] +set_input_delay -clock [get_clocks clk_out3_mmcm] -min -add_delay 2.000 [get_ports resetn] +set_input_delay -clock [get_clocks clk_out3_mmcm] -max -add_delay 2.000 [get_ports resetn] set_max_delay -from [get_ports resetn] 20.000 set_false_path -from [get_ports resetn] set_property PACKAGE_PIN C2 [get_ports resetn] set_property IOSTANDARD LVCMOS33 [get_ports resetn] -set_input_delay -clock [get_clocks clk_out3_xlnx_mmcm] -min -add_delay 2.000 [get_ports south_reset] -set_input_delay -clock [get_clocks clk_out3_xlnx_mmcm] -max -add_delay 2.000 [get_ports south_reset] +set_input_delay -clock [get_clocks clk_out3_mmcm] -min -add_delay 2.000 [get_ports south_reset] +set_input_delay -clock [get_clocks clk_out3_mmcm] -max -add_delay 2.000 [get_ports south_reset] set_max_delay -from [get_ports south_reset] 20.000 set_false_path -from [get_ports south_reset] set_property PACKAGE_PIN D9 [get_ports south_reset] @@ -220,77 +220,77 @@ set_property IOSTANDARD SSTL135 [get_ports {ddr3_odt[0]}] set_property IOSTANDARD SSTL135 [get_ports {ddr3_cs_n[0]}] -set_properity PACKAGE_PIN K5 [get_ports ddr3_dq[0]] -set_properity PACKAGE_PIN L3 [get_ports ddr3_dq[1]] -set_properity PACKAGE_PIN K3 [get_ports ddr3_dq[2]] -set_properity PACKAGE_PIN L6 [get_ports ddr3_dq[3]] -set_properity PACKAGE_PIN M3 [get_ports ddr3_dq[4]] -set_properity PACKAGE_PIN M1 [get_ports ddr3_dq[5]] -set_properity PACKAGE_PIN L4 [get_ports ddr3_dq[6]] -set_properity PACKAGE_PIN M2 [get_ports ddr3_dq[7]] -set_properity PACKAGE_PIN V4 [get_ports ddr3_dq[8]] -set_properity PACKAGE_PIN T5 [get_ports ddr3_dq[9]] -set_properity PACKAGE_PIN U4 [get_ports ddr3_dq[10]] -set_properity PACKAGE_PIN V5 [get_ports ddr3_dq[11]] -set_properity PACKAGE_PIN V1 [get_ports ddr3_dq[12]] -set_properity PACKAGE_PIN T3 [get_ports ddr3_dq[13]] -set_properity PACKAGE_PIN U3 [get_ports ddr3_dq[14]] -set_properity PACKAGE_PIN R3 [get_ports ddr3_dq[15]] -set_properity PACKAGE_PIN L1 [get_ports ddr3_dm[0]] -set_properity PACKAGE_PIN U1 [get_ports ddr3_dm[1]] -set_properity PACKAGE_PIN N2 [get_ports ddr3_dqs_p[0]] -set_properity PACKAGE_PIN N1 [get_ports ddr3_dqs_n[0]] -set_properity PACKAGE_PIN U2 [get_ports ddr3_dqs_p[1]] -set_properity PACKAGE_PIN V2 [get_ports ddr3_dqs_n[1]] -set_properity PACKAGE_PIN T8 [get_ports ddr3_addr[13]] -set_properity PACKAGE_PIN T6 [get_ports ddr3_addr[12]] -set_properity PACKAGE_PIN U6 [get_ports ddr3_addr[11]] -set_properity PACKAGE_PIN R6 [get_ports ddr3_addr[10]] -set_properity PACKAGE_PIN V7 [get_ports ddr3_addr[9]] -set_properity PACKAGE_PIN R8 [get_ports ddr3_addr[8]] -set_properity PACKAGE_PIN U7 [get_ports ddr3_addr[7]] -set_properity PACKAGE_PIN V6 [get_ports ddr3_addr[6]] -set_properity PACKAGE_PIN R7 [get_ports ddr3_addr[5]] -set_properity PACKAGE_PIN N6 [get_ports ddr3_addr[4]] -set_properity PACKAGE_PIN T1 [get_ports ddr3_addr[3]] -set_properity PACKAGE_PIN N4 [get_ports ddr3_addr[2]] -set_properity PACKAGE_PIN M6 [get_ports ddr3_addr[1]] -set_properity PACKAGE_PIN R2 [get_ports ddr3_addr[0]] -set_properity PACKAGE_PIN P2 [get_ports ddr3_ba[2]] -set_properity PACKAGE_PIN P4 [get_ports ddr3_ba[1]] -set_properity PACKAGE_PIN R1 [get_ports ddr3_ba[0]] -set_properity PACKAGE_PIN U9 [get_ports ddr3_ck_p[0]] -set_properity PACKAGE_PIN V9 [get_ports ddr3_ck_n[0]] -set_properity PACKAGE_PIN P3 [get_ports ddr3_ras_n] -set_properity PACKAGE_PIN M4 [get_ports ddr3_cas_n] -set_properity PACKAGE_PIN P5 [get_ports ddr3_we_n] -set_properity PACKAGE_PIN K6 [get_ports ddr3_reset_n] -set_properity PACKAGE_PIN N5 [get_ports ddr3_cke[0]] -set_properity PACKAGE_PIN R5 [get_ports ddr3_odt[0]] -set_properity PACKAGE_PIN U8 [get_ports ddr3_cs_n[0]] +set_property PACKAGE_PIN K5 [get_ports ddr3_dq[0]] +set_property PACKAGE_PIN L3 [get_ports ddr3_dq[1]] +set_property PACKAGE_PIN K3 [get_ports ddr3_dq[2]] +set_property PACKAGE_PIN L6 [get_ports ddr3_dq[3]] +set_property PACKAGE_PIN M3 [get_ports ddr3_dq[4]] +set_property PACKAGE_PIN M1 [get_ports ddr3_dq[5]] +set_property PACKAGE_PIN L4 [get_ports ddr3_dq[6]] +set_property PACKAGE_PIN M2 [get_ports ddr3_dq[7]] +set_property PACKAGE_PIN V4 [get_ports ddr3_dq[8]] +set_property PACKAGE_PIN T5 [get_ports ddr3_dq[9]] +set_property PACKAGE_PIN U4 [get_ports ddr3_dq[10]] +set_property PACKAGE_PIN V5 [get_ports ddr3_dq[11]] +set_property PACKAGE_PIN V1 [get_ports ddr3_dq[12]] +set_property PACKAGE_PIN T3 [get_ports ddr3_dq[13]] +set_property PACKAGE_PIN U3 [get_ports ddr3_dq[14]] +set_property PACKAGE_PIN R3 [get_ports ddr3_dq[15]] +set_property PACKAGE_PIN L1 [get_ports ddr3_dm[0]] +set_property PACKAGE_PIN U1 [get_ports ddr3_dm[1]] +set_property PACKAGE_PIN N2 [get_ports ddr3_dqs_p[0]] +set_property PACKAGE_PIN N1 [get_ports ddr3_dqs_n[0]] +set_property PACKAGE_PIN U2 [get_ports ddr3_dqs_p[1]] +set_property PACKAGE_PIN V2 [get_ports ddr3_dqs_n[1]] +set_property PACKAGE_PIN T8 [get_ports ddr3_addr[13]] +set_property PACKAGE_PIN T6 [get_ports ddr3_addr[12]] +set_property PACKAGE_PIN U6 [get_ports ddr3_addr[11]] +set_property PACKAGE_PIN R6 [get_ports ddr3_addr[10]] +set_property PACKAGE_PIN V7 [get_ports ddr3_addr[9]] +set_property PACKAGE_PIN R8 [get_ports ddr3_addr[8]] +set_property PACKAGE_PIN U7 [get_ports ddr3_addr[7]] +set_property PACKAGE_PIN V6 [get_ports ddr3_addr[6]] +set_property PACKAGE_PIN R7 [get_ports ddr3_addr[5]] +set_property PACKAGE_PIN N6 [get_ports ddr3_addr[4]] +set_property PACKAGE_PIN T1 [get_ports ddr3_addr[3]] +set_property PACKAGE_PIN N4 [get_ports ddr3_addr[2]] +set_property PACKAGE_PIN M6 [get_ports ddr3_addr[1]] +set_property PACKAGE_PIN R2 [get_ports ddr3_addr[0]] +set_property PACKAGE_PIN P2 [get_ports ddr3_ba[2]] +set_property PACKAGE_PIN P4 [get_ports ddr3_ba[1]] +set_property PACKAGE_PIN R1 [get_ports ddr3_ba[0]] +set_property PACKAGE_PIN U9 [get_ports ddr3_ck_p[0]] +set_property PACKAGE_PIN V9 [get_ports ddr3_ck_n[0]] +set_property PACKAGE_PIN P3 [get_ports ddr3_ras_n] +set_property PACKAGE_PIN M4 [get_ports ddr3_cas_n] +set_property PACKAGE_PIN P5 [get_ports ddr3_we_n] +set_property PACKAGE_PIN K6 [get_ports ddr3_reset_n] +set_property PACKAGE_PIN N5 [get_ports ddr3_cke[0]] +set_property PACKAGE_PIN R5 [get_ports ddr3_odt[0]] +set_property PACKAGE_PIN U8 [get_ports ddr3_cs_n[0]] -create_clock -period 40.000 -name VIRTUAL_clk_out3_mmcm -waveform {0.000 20.000} -set_input_delay -clock [get_clocks VIRTUAL_clk_out3_mmcm] -min -add_delay 10.000 [get_ports {GPI[*]}] -set_input_delay -clock [get_clocks VIRTUAL_clk_out3_mmcm] -max -add_delay 10.000 [get_ports {GPI[*]}] -set_input_delay -clock [get_clocks VIRTUAL_clk_out3_mmcm] -min -add_delay 10.000 [get_ports SDCCD] -set_input_delay -clock [get_clocks VIRTUAL_clk_out3_mmcm] -max -add_delay 10.000 [get_ports SDCCD] -set_input_delay -clock [get_clocks VIRTUAL_clk_out3_mmcm] -min -add_delay 10.000 [get_ports SDCIn] -set_input_delay -clock [get_clocks VIRTUAL_clk_out3_mmcm] -max -add_delay 10.000 [get_ports SDCIn] -set_input_delay -clock [get_clocks VIRTUAL_clk_out3_mmcm] -min -add_delay 10.000 [get_ports SDCWP] -set_input_delay -clock [get_clocks VIRTUAL_clk_out3_mmcm] -max -add_delay 10.000 [get_ports SDCWP] -set_input_delay -clock [get_clocks VIRTUAL_clk_out3_mmcm] -min -add_delay 10.000 [get_ports UARTSin] -set_input_delay -clock [get_clocks VIRTUAL_clk_out3_mmcm] -max -add_delay 10.000 [get_ports UARTSin] -create_clock -period 12.000 -name VIRTUAL_clk_pll_i -waveform {0.000 6.000} -set_output_delay -clock [get_clocks VIRTUAL_clk_out3_mmcm] -min -add_delay 0.000 [get_ports {GPO[*]}] -set_output_delay -clock [get_clocks VIRTUAL_clk_out3_mmcm] -max -add_delay 10.000 [get_ports {GPO[*]}] -set_output_delay -clock [get_clocks VIRTUAL_clk_out3_mmcm] -min -add_delay 0.000 [get_ports SDCCLK] -set_output_delay -clock [get_clocks VIRTUAL_clk_out3_mmcm] -max -add_delay 0.000 [get_ports SDCCLK] -set_output_delay -clock [get_clocks VIRTUAL_clk_out3_mmcm] -min -add_delay 0.000 [get_ports SDCCS] -set_output_delay -clock [get_clocks VIRTUAL_clk_out3_mmcm] -max -add_delay 10.000 [get_ports SDCCS] -set_output_delay -clock [get_clocks VIRTUAL_clk_out3_mmcm] -min -add_delay 0.000 [get_ports SDCCmd] -set_output_delay -clock [get_clocks VIRTUAL_clk_out3_mmcm] -max -add_delay 10.000 [get_ports SDCCmd] -set_output_delay -clock [get_clocks VIRTUAL_clk_out3_mmcm] -min -add_delay 0.000 [get_ports UARTSout] -set_output_delay -clock [get_clocks VIRTUAL_clk_out3_mmcm] -max -add_delay 10.000 [get_ports UARTSout] +#create_clock -period 50.000 -name VIRTUAL_clk_out3_mmcm -waveform {0.000 25.000} +#set_input_delay -clock [get_clocks VIRTUAL_clk_out3_mmcm] -min -add_delay 10.000 [get_ports {GPI[*]}] +#set_input_delay -clock [get_clocks VIRTUAL_clk_out3_mmcm] -max -add_delay 10.000 [get_ports {GPI[*]}] +#set_input_delay -clock [get_clocks VIRTUAL_clk_out3_mmcm] -min -add_delay 10.000 [get_ports SDCCD] +#set_input_delay -clock [get_clocks VIRTUAL_clk_out3_mmcm] -max -add_delay 10.000 [get_ports SDCCD] +#set_input_delay -clock [get_clocks VIRTUAL_clk_out3_mmcm] -min -add_delay 10.000 [get_ports SDCIn] +#set_input_delay -clock [get_clocks VIRTUAL_clk_out3_mmcm] -max -add_delay 10.000 [get_ports SDCIn] +#set_input_delay -clock [get_clocks VIRTUAL_clk_out3_mmcm] -min -add_delay 10.000 [get_ports SDCWP] +#set_input_delay -clock [get_clocks VIRTUAL_clk_out3_mmcm] -max -add_delay 10.000 [get_ports SDCWP] +#set_input_delay -clock [get_clocks VIRTUAL_clk_out3_mmcm] -min -add_delay 10.000 [get_ports UARTSin] +#set_input_delay -clock [get_clocks VIRTUAL_clk_out3_mmcm] -max -add_delay 10.000 [get_ports UARTSin] +#create_clock -period 12.000 -name VIRTUAL_clk_pll_i -waveform {0.000 6.000} +#set_output_delay -clock [get_clocks VIRTUAL_clk_out3_mmcm] -min -add_delay 0.000 [get_ports {GPO[*]}] +#set_output_delay -clock [get_clocks VIRTUAL_clk_out3_mmcm] -max -add_delay 10.000 [get_ports {GPO[*]}] +#set_output_delay -clock [get_clocks VIRTUAL_clk_out3_mmcm] -min -add_delay 0.000 [get_ports SDCCLK] +#set_output_delay -clock [get_clocks VIRTUAL_clk_out3_mmcm] -max -add_delay 0.000 [get_ports SDCCLK] +#set_output_delay -clock [get_clocks VIRTUAL_clk_out3_mmcm] -min -add_delay 0.000 [get_ports SDCCS] +#set_output_delay -clock [get_clocks VIRTUAL_clk_out3_mmcm] -max -add_delay 10.000 [get_ports SDCCS] +#set_output_delay -clock [get_clocks VIRTUAL_clk_out3_mmcm] -min -add_delay 0.000 [get_ports SDCCmd] +#set_output_delay -clock [get_clocks VIRTUAL_clk_out3_mmcm] -max -add_delay 10.000 [get_ports SDCCmd] +#set_output_delay -clock [get_clocks VIRTUAL_clk_out3_mmcm] -min -add_delay 0.000 [get_ports UARTSout] +#set_output_delay -clock [get_clocks VIRTUAL_clk_out3_mmcm] -max -add_delay 10.000 [get_ports UARTSout] #set_output_delay -clock [get_clocks VIRTUAL_clk_pll_i] -min -add_delay 0.000 [get_ports ddr3_reset_n] #set_output_delay -clock [get_clocks VIRTUAL_clk_pll_i] -max -add_delay 80.000 [get_ports ddr3_reset_n] diff --git a/fpga/zsbl/spi.h b/fpga/zsbl/spi.h index d2bf1191c..f9e88fa6d 100644 --- a/fpga/zsbl/spi.h +++ b/fpga/zsbl/spi.h @@ -1,3 +1,32 @@ +/////////////////////////////////////////////////////////////////////// +// spi.h +// +// Written: Jaocb Pease jacob.pease@okstate.edu 7/22/2024 +// +// Purpose: Header file for interfaceing with the SPI peripheral +// +// +// +// A component of the 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. +/////////////////////////////////////////////////////////////////////// + #pragma once #ifndef SPI_HEADER #define SPI_HEADER diff --git a/sim/questa/wally.do b/sim/questa/wally.do index 0f67cee37..f1c432882 100644 --- a/sim/questa/wally.do +++ b/sim/questa/wally.do @@ -1,33 +1,46 @@ -# wally-batch.do +# wally.do # SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 # # Modification by Oklahoma State University & Harvey Mudd College -# Use with Testbench +# Use with Testbench # James Stine, 2008; David Harris 2021 # Go Cowboys!!!!!! # # Takes 1:10 to run RV64IC tests using gui -# Usage: do wally-batch.do [--ccov] [--fcov] [+acc] [any number of +value] [any number of -G VAR=VAL] -# Example: do wally-batch.do rv64gc arch64i testbench +# Usage: do wally.do [--ccov] [--fcov] [+acc] [--args "any number of +value"] [--params "any number of VAR=VAL parameter overrides"] +# Example: do wally.do rv64gc arch64i testbench -# Use this wally-batch.do file to run this example. +# Use this wally.do file to run this example. # Either bring up ModelSim and type the following at the "ModelSim>" prompt: -# do wally-batch.do +# do wally.do # or, to run from a shell, type the following at the shell prompt: -# vsim -do wally-batch.do -c +# vsim -do wally.do -c # (omit the "-c" to see the GUI while running from the shell) -set DEBUG 1 +# lcheck - return 1 if value is in list and remove it from list +proc lcheck {listVariable value} { + upvar 1 $listVariable list + set index [lsearch -exact $list $value] + if {$index >= 0} { + set list [lreplace $list $index $index] + return 1 + } else { + return 0 + } +} +set DEBUG 1 onbreak {resume} onerror {quit -f} +# Initialize variables set CFG ${1} set TESTSUITE ${2} set TESTBENCH ${3} set WKDIR wkdir/${CFG}_${TESTSUITE} set WALLY $::env(WALLY) +set IMPERAS_HOME $::env(IMPERAS_HOME) set CONFIG ${WALLY}/config set SRC ${WALLY}/src set TB ${WALLY}/testbench @@ -38,10 +51,12 @@ if [file exists ${WKDIR}] { vdel -lib ${WKDIR} -all } vlib ${WKDIR} -# Create directory for coverage data -mkdir -p cov # Create directory for functional coverage data -mkdir -p ${WALLY}/addins/cvw-arch-verif/work +mkdir -p ${FCRVVI} + +set PlusArgs "" +set ParamArgs "" +set ExpandedParamArgs {} set ccov 0 set CoverageVoptArg "" @@ -51,47 +66,26 @@ set FuncCovRVVI 0 set FCdefineRVVI_COVERAGE "" set FunctCoverage 0 -set riscvISACOVsrc "" -set FCdefineINCLUDE_TRACE2COV "" -set FCdefineCOVER_BASE_RV64I "" -set FCdefineCOVER_LEVEL_DV_PR_EXT "" -set FCdefineCOVER_RV64I "" -set FCdefineCOVER_RV64M "" -set FCdefineCOVER_RV64A "" -set FCdefineCOVER_RV64F "" -set FCdefineCOVER_RV64D "" -set FCdefineCOVER_RV64ZICSR "" -set FCdefineCOVER_RV64C "" -set FCdefineIDV_INCLUDE_TRACE2COV "" -set FCTRACE2COV "" -set FCdefineIDV_TRACE2COV "" +set FCvlog "" +set FCvopt "" +set FCdefineCOVER_EXTS {} + set lockstep 0 -# ok this is annoying. vlog, vopt, and vsim are very picky about how arguments are passed. -# unforunately it won't allow these to be grouped as one argument per command so they are broken -# apart. -set lockstepvoptstring "" +set lockstepvlog "" set SVLib "" -set SVLibPath "" set OtherFlags "" -set ImperasPubInc "" -set ImperasPrivInc "" -set rvviFiles "" -set idvFiles "" set GUI 0 set accFlag "" # Need to be able to pass arguments to vopt. Unforunately argv does not work because # it takes on different values if vsim and the do file are called from the command line or -# if the do file isd called from questa sim directly. This chunk of code uses the $4 through $n +# if the do file is called from questa sim directly. This chunk of code uses the $4 through $n # variables and compacts into a single list for passing to vopt. -set tbArgs "" set from 4 set step 1 set lst {} -set PlusArgs {} -set ParamArgs {} for {set i 0} true {incr i} { set x [expr {$i*$step + $from}] if {$x > $argc} break @@ -103,84 +97,96 @@ echo "number of args = $argc" echo "lst = $lst" # if +acc found set flag and remove from list -set AccIndex [lsearch -exact $lst "+acc"] -if {$AccIndex >= 0} { +if {[lcheck lst "+acc"]} { set GUI 1 set accFlag "+acc" - set lst [lreplace $lst $AccIndex $AccIndex] } -# if +coverage found set flag and remove from list -set CoverageIndex [lsearch -exact $lst "--ccov"] -if {$CoverageIndex >= 0} { +# if --ccov found set flag and remove from list +if {[lcheck lst "--ccov"]} { set ccov 1 set CoverageVoptArg "+cover=sbecf" set CoverageVsimArg "-coverage" - set lst [lreplace $lst $CoverageIndex $CoverageIndex] } -set FCoverageIndexRVVI [lsearch -exact $lst "--fcovrvvi"] -if {$FCoverageIndexRVVI >= 0} { +# if --fcovrvvi found set flag and remove from list +if {[lcheck lst "--fcovrvvi"]} { set FuncCovRVVI 1 set FCdefineRVVI_COVERAGE "+define+RVVI_COVERAGE" - set lst [lreplace $lst $FCoverageIndexRVVI $FCoverageIndexRVVI] } -# if +coverage found set flag and remove from list -set FunctCoverageIndex [lsearch -exact $lst "--fcov"] -if {$FunctCoverageIndex >= 0} { +# if --fcov found set flag and remove from list +if {[lcheck lst "--fcov"]} { set FunctCoverage 1 - set riscvISACOVsrc +incdir+$env(IMPERAS_HOME)/ImpProprietary/source/host/riscvISACOV/source - - set FCdefineINCLUDE_TRACE2COV "+define+INCLUDE_TRACE2COV" - set FCdefineCOVER_BASE_RV64I "+define+COVER_BASE_RV64I" - set FCdefineCOVER_LEVEL_DV_PR_EXT "+define+COVER_LEVEL_DV_PR_EXT" + set FCvlog "+define+INCLUDE_TRACE2COV \ + +define+IDV_INCLUDE_TRACE2COV \ + +define+COVER_BASE_RV64I \ + +define+COVER_LEVEL_DV_PR_EXT \ + +incdir+${IMPERAS_HOME}/ImpProprietary/source/host/riscvISACOV/source" + set FCvopt "+TRACE2COV_ENABLE=1 +IDV_TRACE2COV=1" # Uncomment various cover statements below to control which extensions get functional coverage - set FCdefineCOVER_RV64I "+define+COVER_RV64I" - #set FCdefineCOVER_RV64M "+define+COVER_RV64M" - #set FCdefineCOVER_RV64A "+define+COVER_RV64A" - #set FCdefineCOVER_RV64F "+define+COVER_RV64F" - #set FCdefineCOVER_RV64D "+define+COVER_RV64D" - #set FCdefineCOVER_RV64ZICSR "+define+COVER_RV64ZICSR" - #set FCdefineCOVER_RV64C "+define+COVER_RV64C" - set FCdefineIDV_INCLUDE_TRACE2COV "+define+IDV_INCLUDE_TRACE2COV" - set FCTRACE2COV "+TRACE2COV_ENABLE=1" - set FCdefineIDV_TRACE2COV "+IDV_TRACE2COV=1" - set lst [lreplace $lst $FunctCoverageIndex $FunctCoverageIndex] -}\ - -set LockStepIndex [lsearch -exact $lst "--lockstep"] -# ugh. can't have more than 9 arguments passed to vsim. why? I'll have to remove --lockstep when running -# functional coverage and imply it. -if {$LockStepIndex >= 0 || $FunctCoverageIndex >= 0} { + lappend FCdefineCOVER_EXTS "+define+COVER_RV64I" + #lappend FCdefineCOVER_EXTS "+define+COVER_RV64M" + #lappend FCdefineCOVER_EXTS "+define+COVER_RV64A" + #lappend FCdefineCOVER_EXTS "+define+COVER_RV64F" + #lappend FCdefineCOVER_EXTS "+define+COVER_RV64D" + #lappend FCdefineCOVER_EXTS "+define+COVER_RV64ZICSR" + #lappend FCdefineCOVER_EXTS "+define+COVER_RV64C" + +} + +# if --fcov2 found set flag and remove from list +if {[lcheck lst "--fcov2"]} { + set FunctCoverage 1 + set FCvlog "+define+INCLUDE_TRACE2COV \ + +define+IDV_INCLUDE_TRACE2COV \ + +define+COVER_BASE_RV32I \ + +define+COVER_LEVEL_DV_PR_EXT \ + +incdir+$env(WALLY)/addins/riscvISACOV/source \ + +incdir+$env(WALLY)/addins/cvw-arch-verif/fcov/RV32" + set FCvopt "+TRACE2COV_ENABLE=1 +IDV_TRACE2COV=1" + # Uncomment various cover statements below to control which extensions get functional coverage + lappend FCdefineCOVER_EXTS "+define+COVER_RV32I" + lappend FCdefineCOVER_EXTS "+define+COVER_RV32M" + #lappend FCdefineCOVER_EXTS "+define+COVER_RV64M" + #lappend FCdefineCOVER_EXTS "+define+COVER_RV64A" + #lappend FCdefineCOVER_EXTS "+define+COVER_RV64F" + #lappend FCdefineCOVER_EXTS "+define+COVER_RV64D" + #lappend FCdefineCOVER_EXTS "+define+COVER_RV64ZICSR" + #lappend FCdefineCOVER_EXTS "+define+COVER_RV64C" +} + +# if --lockstep or --fcov found set flag and remove from list +if {[lcheck lst "--lockstep"] || $FunctCoverage == 1} { set lockstep 1 - - # ideally this would all be one or two variables, but questa is having a real hard time - # with this. For now they have to be separate. - set lockstepvoptstring "+define+USE_IMPERAS_DV" - set ImperasPubInc +incdir+$env(IMPERAS_HOME)/ImpPublic/include/host - set ImperasPrivInc +incdir+$env(IMPERAS_HOME)/ImpProprietary/include/host - set rvviFiles $env(IMPERAS_HOME)/ImpPublic/source/host/rvvi/*.sv - set idvFiles $env(IMPERAS_HOME)/ImpProprietary/source/host/idv/*.sv - set SVLib "-sv_lib" - set SVLibPath $env(IMPERAS_HOME)/lib/Linux64/ImperasLib/imperas.com/verification/riscv/1.0/model + set lockstepvlog "+define+USE_IMPERAS_DV \ + +incdir+${IMPERAS_HOME}/ImpPublic/include/host \ + +incdir+${IMPERAS_HOME}/ImpProprietary/include/host \ + ${IMPERAS_HOME}/ImpPublic/source/host/rvvi/*.sv \ + ${IMPERAS_HOME}/ImpProprietary/source/host/idv/*.sv" + set SVLib "-sv_lib ${IMPERAS_HOME}/lib/Linux64/ImperasLib/imperas.com/verification/riscv/1.0/model" #set OtherFlags $::env(OTHERFLAGS) # not working 7/15/24 dh; this should be the way to pass things like --verbose (Issue 871) - - if {$LockStepIndex >= 0} { - set lst [lreplace $lst $LockStepIndex $LockStepIndex] - } } - -# separate the +args from the -G parameters -foreach otherArg $lst { - if {[string index $otherArg 0] eq "+"} { - lappend PlusArgs $otherArg - } else { - lappend ParamArgs $otherArg - } +# Set PlusArgs passed using the --args flag +set PlusArgsIndex [lsearch -exact $lst "--args"] +if {$PlusArgsIndex >= 0} { + set PlusArgs [lindex $lst [expr {$PlusArgsIndex + 1}]] + set lst [lreplace $lst $PlusArgsIndex [expr {$PlusArgsIndex + 1}]] } +# Set ParamArgs passed using the --params flag and expand into a list of -G arguments +set ParamArgsIndex [lsearch -exact $lst "--params"] +if {$ParamArgsIndex >= 0} { + set ParamArgs [lindex $lst [expr {$ParamArgsIndex + 1}]] + set ParamArgs [regexp -all -inline {\S+} $ParamArgs] + foreach param $ParamArgs { + lappend ExpandedParamArgs -G$param + } + set lst [lreplace $lst $ParamArgsIndex [expr {$ParamArgsIndex + 1}]] +} + +# Debug print statements if {$DEBUG > 0} { echo "GUI = $GUI" echo "ccov = $ccov" @@ -189,41 +195,27 @@ if {$DEBUG > 0} { echo "FunctCoverage = $FunctCoverage" echo "remaining list = $lst" echo "Extra +args = $PlusArgs" - echo "Extra -args = $ParamArgs" + echo "Extra -args = $ExpandedParamArgs" } -foreach x $PlusArgs { - echo "Element is $x" -} - -# need a better solution this is really ugly -# Questa really don't like passing $PlusArgs on the command line to vsim. It treats the whole things -# as one string rather than mutliple separate +args. Is there an automated way to pass these? -set temp0 [lindex $PlusArgs 0] -set temp1 [lindex $PlusArgs 1] -set temp2 [lindex $PlusArgs 2] -set temp3 [lindex $PlusArgs 3] - -#quit - # compile source files -# suppress spurious warnngs about +# suppress spurious warnngs about # "Extra checking for conflicts with always_comb done at vopt time" # because vsim will run vopt - -vlog -lint +nowarnRDGN -suppress 2244 -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} ${FCdefineRVVI_COVERAGE} ${idvFiles} ${riscvISACOVsrc} ${SRC}/cvw.sv ${TB}/${TESTBENCH}.sv ${TB}/common/*.sv ${SRC}/*/*.sv ${SRC}/*/*/*.sv +incdir+${FCRVVI}/common +incdir+${FCRVVI} ${WALLY}/addins/verilog-ethernet/*/*.sv ${WALLY}/addins/verilog-ethernet/*/*/*/*.sv -suppress 2244 -suppress 2282 -suppress 2583 -suppress 7063,2596,13286 +set INC_DIRS "+incdir+${CONFIG}/${CFG} +incdir+${CONFIG}/deriv/${CFG} +incdir+${CONFIG}/shared +incdir+${FCRVVI}/common +incdir+${FCRVVI}" +set SOURCES "${SRC}/cvw.sv ${TB}/${TESTBENCH}.sv ${TB}/common/*.sv ${SRC}/*/*.sv ${SRC}/*/*/*.sv ${WALLY}/addins/verilog-ethernet/*/*.sv ${WALLY}/addins/verilog-ethernet/*/*/*/*.sv" +vlog -lint +nowarnRDGN -work ${WKDIR} {*}${INC_DIRS} {*}${FCvlog} {*}${FCdefineCOVER_EXTS} {*}${lockstepvlog} ${FCdefineRVVI_COVERAGE} {*}${SOURCES} -suppress 2244 -suppress 2282 -suppress 2583 -suppress 7063,2596,13286 # start and run simulation # remove +acc flag for faster sim during regressions if there is no need to access internal signals -vopt $accFlag wkdir/${CFG}_${TESTSUITE}.${TESTBENCH} -work ${WKDIR} ${ParamArgs} -o testbenchopt ${CoverageVoptArg} +vopt $accFlag wkdir/${CFG}_${TESTSUITE}.${TESTBENCH} -work ${WKDIR} {*}${ExpandedParamArgs} -o testbenchopt ${CoverageVoptArg} -#vsim -lib ${WKDIR} testbenchopt +TEST=${TESTSUITE} ${PlusArgs} -fatal 7 ${SVLib} ${SVLibPath} ${OtherFlags} +TRACE2COV_ENABLE=1 -suppress 3829 ${CoverageVsimArg} -#vsim -lib ${WKDIR} testbenchopt +TEST=${TESTSUITE} ${PlusArgs} -fatal 7 ${SVLib} ${SVLibPath} +IDV_TRACE2COV=1 +TRACE2COV_ENABLE=1 -suppress 3829 ${CoverageVsimArg} -vsim -lib ${WKDIR} testbenchopt +TEST=${TESTSUITE} $temp0 $temp1 $temp2 $temp3 -fatal 7 ${SVLib} ${SVLibPath} ${OtherFlags} ${FCTRACE2COV} ${FCdefineIDV_TRACE2COV} -suppress 3829 ${CoverageVsimArg} +vsim -lib ${WKDIR} testbenchopt +TEST=${TESTSUITE} {*}${PlusArgs} -fatal 7 {*}${SVLib} ${OtherFlags} {*}${FCvopt} -suppress 3829 ${CoverageVsimArg} -# vsim -lib wkdir/work_${1}_${2} testbenchopt -fatal 7 -suppress 3829 # power add generates the logging necessary for saif generation. # power add -r /dut/core/* + +# add waveforms if GUI is enabled if { ${GUI} } { add log -recursive /* if { ${TESTBENCH} eq "testbench_fp" } { @@ -265,4 +257,3 @@ if {$ccov} { if { ${GUI} == 0} { quit } - diff --git a/sim/rv64gc_CacheSim.py b/sim/rv64gc_CacheSim.py index bc75fc13a..60dc092b5 100755 --- a/sim/rv64gc_CacheSim.py +++ b/sim/rv64gc_CacheSim.py @@ -6,8 +6,9 @@ ## Written: lserafini@hmc.edu ## Created: 11 April 2023 ## Modified: 12 April 2023 +## Modified: 10 August 2023, jcarlin@hmc.edu ## -## Purpose: Run the cache simulator on each rv64gc test suite in turn. +## Purpose: Run the cache simulator on each rv64gc test suite in turn. ## ## A component of the CORE-V-WALLY configurable RISC-V project. ## https://github.com/openhwgroup/cvw @@ -16,24 +17,24 @@ ## ## 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 +## 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 +## 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. ################################################################################################ -import sys import os import argparse +import subprocess # NOTE: make sure testbench.sv has the ICache and DCache loggers enabled! # This does not check the test output for correctness, run regression for that. -# Add -p or --perf to report the hit/miss ratio. +# Add -p or --perf to report the hit/miss ratio. # Add -d or --dist to report the distribution of loads, stores, and atomic ops. # These distributions may not add up to 100; this is because of flushes or invalidations. @@ -48,36 +49,46 @@ class bcolors: BOLD = '\033[1m' UNDERLINE = '\033[4m' -# tests64gc = ["coverage64gc", "arch64f", "arch64d", "arch64i", "arch64priv", "arch64c", "arch64m", -tests64gc = ["coverage64gc", "arch64i", "arch64priv", "arch64c", "arch64m", - "arch64zi", "wally64a", "wally64periph", "wally64priv", - "arch64zba", "arch64zbb", "arch64zbc", "arch64zbs", - "imperas64f", "imperas64d", "imperas64c", "imperas64i"] +tests64gc = ["coverage64gc", "arch64i", "arch64priv", "arch64c", "arch64m", "arch64zcb", + "arch64zifencei", "arch64zicond", "arch64a_amo", "wally64a_lrsc", "wally64periph", "wally64priv", + "arch64zbkb", "arch64zbkc", "arch64zbkx", "arch64zknd", "arch64zkne", "arch64zknh", + "arch64zba", "arch64zbb", "arch64zbc", "arch64zbs"] # arch64i is the most interesting case. Uncomment line below to run just that case -tests64gc = ["arch64i"] +# tests64gc = ["arch64i"] cachetypes = ["ICache", "DCache"] -simdir = os.path.expanduser("~/cvw/sim") +simdir = os.path.expandvars("$WALLY/sim") -if __name__ == '__main__': +def main(): parser = argparse.ArgumentParser(description="Runs the cache simulator on all rv64gc test suites") parser.add_argument('-p', "--perf", action='store_true', help="Report hit/miss ratio") parser.add_argument('-d', "--dist", action='store_true', help="Report distribution of operations") - + parser.add_argument('-s', "--sim", help="Simulator", choices=["questa", "verilator", "vcs"], default="verilator") args = parser.parse_args() - - testcmd = "vsim -do \"do wally-batch.do rv64gc {}\" -c > /dev/null" + simargs = "I_CACHE_ADDR_LOGGER=1\\\'b1 D_CACHE_ADDR_LOGGER=1\\\'b1" + testcmd = "wsim --sim " + args.sim + " rv64gc {} --params \"" + simargs + "\" > /dev/null" cachecmd = "CacheSim.py 64 4 56 44 -f {}" - + mismatches = 0 + if args.perf: cachecmd += " -p" if args.dist: cachecmd += " -d" - + for test in tests64gc: print(f"{bcolors.HEADER}Commencing test", test+f":{bcolors.ENDC}") + # remove wkdir to force recompile with logging enabled + os.system("rm -rf " + simdir + "/" + args.sim + "/wkdir/rv64gc_" + test) + os.system("rm -rf " + simdir + "/" + args.sim + "/*Cache.log") + print(testcmd.format(test)) os.system(testcmd.format(test)) for cache in cachetypes: print(f"{bcolors.OKCYAN}Running the", cache, f"simulator.{bcolors.ENDC}") - os.system(cachecmd.format(cache+".log")) + result = subprocess.run(cachecmd.format(args.sim+"/"+cache+".log"), shell=True) + mismatches += result.returncode print() + return mismatches + +if __name__ == '__main__': + exit(main()) + diff --git a/sim/vcs/run_vcs b/sim/vcs/run_vcs index 00bfea9c7..02eccc59b 100755 --- a/sim/vcs/run_vcs +++ b/sim/vcs/run_vcs @@ -23,10 +23,12 @@ def runfindcmd(cmd): parser = argparse.ArgumentParser() parser.add_argument("config", help="Configuration file") parser.add_argument("testsuite", help="Test suite (or none, when running a single ELF file) ") +parser.add_argument("--tb", "-t", help="Testbench", choices=["testbench", "testbench_fp"], default="testbench") parser.add_argument("--elffile", "-e", help="ELF file name", default="") parser.add_argument("--coverage", "-c", help="Code & Functional Coverage", action="store_true") parser.add_argument("--fcov", "-f", help="Code & Functional Coverage", action="store_true") parser.add_argument("--args", "-a", help="Optional arguments passed to simulator via $value$plusargs", default="") +parser.add_argument("--params", "-p", help="Optional top-level parameter overrides of the form param=value", default="") parser.add_argument("--lockstep", "-l", help="Run ImperasDV lock, step, and compare.", action="store_true") # GUI not yet implemented #parser.add_argument("--gui", "-g", help="Simulate with GUI", action="store_true") @@ -49,7 +51,8 @@ rtlsrc_cmd = "find " + srcdir + ' -name "*.sv" ! -path "' + srcdir + '/generic/m rtlsrc_files = runfindcmd(rtlsrc_cmd) tbcommon_cmd = 'find ' + tbdir+'/common -name "*.sv" ! -path "' + tbdir+'/common/wallyTracer.sv"' tbcommon_files = runfindcmd(tbcommon_cmd) -RTL_FILES = tbdir+'/testbench.sv ' + str(rtlsrc_files) + ' ' + str(tbcommon_files) +tb_file = tbdir + "/" + args.tb + ".sv" +RTL_FILES = tb_file + ' ' + str(rtlsrc_files) + ' ' + str(tbcommon_files) # Include directories INCLUDE_PATH="+incdir+" + cfgdir + "/" + args.config + " +incdir+" + cfgdir + "/deriv/" + args.config + " +incdir+" + cfgdir + "/shared +incdir+$WALLY/tests +incdir+" + tbdir + " +incdir+" + srcdir @@ -68,10 +71,23 @@ if (args.coverage): else: COV_OPTIONS = "" +# Write parameter overrides to a file +f = open(os.path.expandvars(wkdir) + "/param_overrides.txt", "w") +for param in args.params.split(): + [param, value] = param.split("=") + if "\\'" in value: # for bit values + value = value.replace("\\'", "'") + else: # for strings + value = "\"" + value + "\"" + # print("param=" + param + " value=" + value) + f.write("assign " + value + " " + args.tb + "/" + param + "\n") +f.close() +PARAM_OVERRIDES=" -parameters " + wkdir + "/param_overrides.txt " + # Simulation commands OUTPUT="sim_out" -VCS_CMD="vcs +lint=all,noGCWM,noUI,noSVA-UA,noIDTS,noNS,noULCO,noCAWM-L,noWMIA-L,noSV-PIU,noSTASKW_CO,noSTASKW_CO1,noSTASKW_RMCOF -suppress +warn -sverilog +vc -Mupdate -line -full64 -lca -ntb_opts sensitive_dyn " + INCLUDE_PATH # Disabled Debug flags; add them back for a GUI mode -debug_access+all+reverse -kdb +vcs+vcdpluson -VCS = VCS_CMD + " -Mdir=" + wkdir + " " + srcdir + "/cvw.sv " + LOCKSTEP_OPTIONS + " " + COV_OPTIONS + " " + RTL_FILES + " -o " + wkdir + "/" + OUTPUT + " -work " + wkdir + " -Mlib " + wkdir + " -l " + logdir + "/" + args.config + "_" + args.testsuite + ".log" +VCS_CMD="vcs +lint=all,noGCWM,noUI,noSVA-UA,noIDTS,noNS,noULCO,noCAWM-L,noWMIA-L,noSV-PIU,noSTASKW_CO,noSTASKW_CO1,noSTASKW_RMCOF -suppress +warn -sverilog +vc -Mupdate -line -full64 -lca -ntb_opts sensitive_dyn " + "-top " + args.tb + PARAM_OVERRIDES + INCLUDE_PATH # Disabled Debug flags; add them back for a GUI mode -debug_access+all+reverse -kdb +vcs+vcdpluson +VCS = VCS_CMD + " -Mdir=" + wkdir + " " + srcdir + "/cvw.sv " + LOCKSTEP_OPTIONS + " " + COV_OPTIONS + " " + RTL_FILES + " -o " + wkdir + "/" + OUTPUT + " -work " + wkdir + " -Mlib=" + wkdir + " -l " + logdir + "/" + args.config + "_" + args.testsuite + ".log" SIMV_CMD= wkdir + "/" + OUTPUT + " +TEST=" + args.testsuite + " " + args.elffile + " " + args.args + " -no_save " + LOCKSTEP_SIMV # Run simulation @@ -81,4 +97,3 @@ subprocess.run(SIMV_CMD, shell=True) if (args.coverage): COV_RUN = "urg -dir " + wkdir + "/coverage.vdb -format text -report IndividualCovReport/" + args.config + "_" + args.testsuite subprocess.run(COV_RUN, shell=True) - diff --git a/sim/verilator/Makefile b/sim/verilator/Makefile index a7a57244e..326c397de 100644 --- a/sim/verilator/Makefile +++ b/sim/verilator/Makefile @@ -7,12 +7,13 @@ SHELL := /bin/bash # verilator configurations OPT= -PARAMS?=-DVERILATOR=1 --no-trace-top +PARAMS?=--no-trace-top NONPROF?=--stats VERILATOR_DIR=${WALLY}/sim/verilator SOURCE=${WALLY}/config/shared/*.vh ${WALLY}/config/${WALLYCONF} ${WALLY}/config/deriv/${WALLYCONF} ${WALLY}/src/cvw.sv ${WALLY}/testbench/*.sv ${WALLY}/testbench/common/*.sv ${WALLY}/src/*/*.sv ${WALLY}/src/*/*/*.sv -EXTRA_ARGS= - +PLUS_ARGS= +PARAM_ARGS= +EXPANDED_PARAM_ARGS:=$(patsubst %,-G%,$(PARAM_ARGS)) WALLYCONF?=rv64gc TEST?=arch64i @@ -32,11 +33,9 @@ DEPENDENCIES=${WALLY}/config/shared/*.vh $(SOURCES) # regular testbench requires a wrapper defining getenvval ifeq ($(TESTBENCH), testbench) WRAPPER=${WALLY}/sim/verilator/wrapper.c - GTEST= ARGTEST=+TEST=$(TEST) else WRAPPER= - GTEST=-GTEST="\"${TEST}\"" ARGTEST= endif @@ -44,7 +43,7 @@ default: run run: wkdir/$(WALLYCONF)_$(TEST)/V${TESTBENCH} mkdir -p $(VERILATOR_DIR)/logs - wkdir/$(WALLYCONF)_$(TEST)/V${TESTBENCH} ${ARGTEST} $(EXTRA_ARGS) + wkdir/$(WALLYCONF)_$(TEST)/V${TESTBENCH} ${ARGTEST} $(PLUS_ARGS) profile: obj_dir_profiling/V${TESTBENCH}_$(WALLYCONF) $(VERILATOR_DIR)/obj_dir_profiling/V${TESTBENCH}_$(WALLYCONF) ${ARGTEST} @@ -64,7 +63,7 @@ wkdir/$(WALLYCONF)_$(TEST)/V${TESTBENCH}: $(DEPENDENCIES) --top-module ${TESTBENCH} --relative-includes \ $(INCLUDE_PATH) \ ${WRAPPER} \ - ${GTEST} \ + ${EXPANDED_PARAM_ARGS} \ $(SOURCES) obj_dir_profiling/V${TESTBENCH}_$(WALLYCONF): $(DEPENDENCIES) @@ -76,7 +75,7 @@ obj_dir_profiling/V${TESTBENCH}_$(WALLYCONF): $(DEPENDENCIES) --top-module ${TESTBENCH} --relative-includes \ $(INCLUDE_PATH) \ ${WRAPPER} \ - ${GTEST} \ + ${EXPANDED_PARAM_ARGS} \ $(SOURCES) clean: diff --git a/testbench/common/wallyTracer.sv b/testbench/common/wallyTracer.sv index 80f7af651..5676f6c13 100644 --- a/testbench/common/wallyTracer.sv +++ b/testbench/common/wallyTracer.sv @@ -169,12 +169,17 @@ module wallyTracer import cvw::*; #(parameter cvw_t P) (rvviTrace rvvi); CSRArray[12'h143] = testbench.dut.core.priv.priv.csr.csrs.csrs.STVAL_REGW; CSRArray[12'h142] = testbench.dut.core.priv.priv.csr.csrs.csrs.SCAUSE_REGW; CSRArray[12'h144] = testbench.dut.core.priv.priv.csr.csrm.MIP_REGW & 12'h222 & testbench.dut.core.priv.priv.csr.csrm.MIDELEG_REGW; - CSRArray[12'h14D] = testbench.dut.core.priv.priv.csr.csrs.csrs.STIMECMP_REGW; + CSRArray[12'h14D] = testbench.dut.core.priv.priv.csr.csrs.csrs.STIMECMP_REGW[P.XLEN-1:0]; // user CSRs CSRArray[12'h001] = testbench.dut.core.priv.priv.csr.csru.csru.FFLAGS_REGW; CSRArray[12'h002] = testbench.dut.core.priv.priv.csr.csru.csru.FRM_REGW; CSRArray[12'h003] = {testbench.dut.core.priv.priv.csr.csru.csru.FRM_REGW, testbench.dut.core.priv.priv.csr.csru.csru.FFLAGS_REGW}; + if (P.XLEN == 32) begin + CSRArray[12'h310] = testbench.dut.core.priv.priv.csr.csrsr.MSTATUSH_REGW; + CSRArray[12'h31A] = testbench.dut.core.priv.priv.csr.csrm.MENVCFGH_REGW; + CSRArray[12'h15D] = testbench.dut.core.priv.priv.csr.csrs.csrs.STIMECMP_REGW[63:32]; + end end else begin // hold the old value if the pipeline is stalled. // PMP CFG 3A0 to 3AF diff --git a/testbench/testbench.sv b/testbench/testbench.sv index d214ef3b6..f91bdcc67 100644 --- a/testbench/testbench.sv +++ b/testbench/testbench.sv @@ -762,7 +762,7 @@ end void'(rvviRefConfigSetString(IDV_CONFIG_MODEL_VENDOR, "riscv.ovpworld.org")); void'(rvviRefConfigSetString(IDV_CONFIG_MODEL_NAME, "riscv")); void'(rvviRefConfigSetString(IDV_CONFIG_MODEL_VARIANT, "RV64GCK")); - void'(rvviRefConfigSetInt(IDV_CONFIG_MODEL_ADDRESS_BUS_WIDTH, 56)); + void'(rvviRefConfigSetInt(IDV_CONFIG_MODEL_ADDRESS_BUS_WIDTH, XLEN==64 ? 56 : 34)); void'(rvviRefConfigSetInt(IDV_CONFIG_MAX_NET_LATENCY_RETIREMENTS, 6)); if(elffilename == "buildroot") filename = ""; @@ -824,15 +824,25 @@ end void'(rvviRefCsrSetVolatile(0, 32'hC02)); // INSTRET void'(rvviRefCsrSetVolatile(0, 32'hB02)); // MINSTRET void'(rvviRefCsrSetVolatile(0, 32'hC01)); // TIME - + if (P.XLEN == 32) begin + void'(rvviRefCsrSetVolatile(0, 32'hC80)); // CYCLEH + void'(rvviRefCsrSetVolatile(0, 32'hB80)); // MCYCLEH + void'(rvviRefCsrSetVolatile(0, 32'hC82)); // INSTRETH + void'(rvviRefCsrSetVolatile(0, 32'hB82)); // MINSTRETH + void'(rvviRefCsrSetVolatile(0, 32'hC81)); // TIMEH + end // User HPMCOUNTER3 - HPMCOUNTER31 for (iter='hC03; iter<='hC1F; iter++) begin void'(rvviRefCsrSetVolatile(0, iter)); // HPMCOUNTERx + if (P.XLEN == 32) + void'(rvviRefCsrSetVolatile(0, iter+128)); // HPMCOUNTERxH end // Machine MHPMCOUNTER3 - MHPMCOUNTER31 for (iter='hB03; iter<='hB1F; iter++) begin void'(rvviRefCsrSetVolatile(0, iter)); // MHPMCOUNTERx + if (P.XLEN == 32) + void'(rvviRefCsrSetVolatile(0, iter+128)); // MHPMCOUNTERxH end // cannot predict this register due to latency between diff --git a/testbench/testbench_fp.sv b/testbench/testbench_fp.sv index 61fa12fcc..58d37ba29 100644 --- a/testbench/testbench_fp.sv +++ b/testbench/testbench_fp.sv @@ -637,7 +637,11 @@ module testbench_fp; // check if nothing is being tested if (Tests.size() == 0) begin $display("TEST %s not supported in this configuration", TEST); - $stop; +`ifdef QUESTA + $stop; // if this is changed to $finish for Questa, wally.do terminates without allowing GUI debug +`else + $finish; +`endif end end @@ -987,7 +991,11 @@ module testbench_fp; X[P.FLEN-1:0], Y[P.FLEN-1:0], Z[P.FLEN-1:0], SrcA, Res[P.FLEN-1:0], ResFlg, Ans[P.FLEN-1:0], AnsFlg); //$display(" fma.Xs %h Xe %h Xm %h Ys %h Ye %h Ym %h Ss %h Se %h Sm %h", fma.Xs, fma.Xe, fma.Xm, fma.Ys, fma.Ye, fma.Ym, fma.Ss, fma.Se, fma.Sm); //$display(" readvectors.unpack.X %h Xs %h Xe %h Xm %h", readvectors.unpack.X, readvectors.unpack.Xs, readvectors.unpack.Xe, readvectors.unpack.Xm); - $stop; +`ifdef QUESTA + $stop; // if this is changed to $finish for Questa, wally.do terminates without allowing GUI debug +`else + $finish; +`endif end if (TestVectors[VectorNum] == '1 & Tests[TestNum] !== "") begin // if reached the eof @@ -1013,7 +1021,11 @@ module testbench_fp; // if no more Tests - finish if (Tests[TestNum] === "") begin $display("\nAll Tests completed with %d errors\n", errors); - $stop; +`ifdef QUESTA + $stop; // if this is changed to $finish for Questa, wally.do terminates without allowing GUI debug +`else + $finish; +`endif end $display("Running %s vectors", Tests[TestNum]); end diff --git a/tests/custom/spitest/Makefile b/tests/custom/spitest/Makefile new file mode 100644 index 000000000..34e83a9e4 --- /dev/null +++ b/tests/custom/spitest/Makefile @@ -0,0 +1,112 @@ +CEXT := c +CPPEXT := cpp +AEXT := s +SEXT := S +SRCEXT := \([$(CEXT)$(AEXT)$(SEXT)]\|$(CPPEXT)\) +OBJEXT := o +DEPEXT := d +SRCDIR := . +BUILDDIR := OBJ + +SOURCES ?= $(shell find $(SRCDIR) -type f -regex ".*\.$(SRCEXT)" | sort) +OBJECTS := $(SOURCES:.$(CEXT)=.$(OBJEXT)) +OBJECTS := $(OBJECTS:.$(AEXT)=.$(OBJEXT)) +OBJECTS := $(OBJECTS:.$(SEXT)=.$(OBJEXT)) +OBJECTS := $(OBJECTS:.$(CPPEXT)=.$(OBJEXT)) +OBJECTS := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(OBJECTS)) + +TARGETDIR := bin +TARGET := $(TARGETDIR)/spitest.elf +ROOT := .. +LIBRARY_DIRS := +LIBRARY_FILES := + +MARCH :=-march=rv64imfdc +MABI :=-mabi=lp64d +LINK_FLAGS :=$(MARCH) $(MABI) -nostartfiles +LINKER :=$(ROOT)/linker8000-0000.x + + +AFLAGS =$(MARCH) $(MABI) -W +CFLAGS =$(MARCH) $(MABI) -mcmodel=medany -O2 +AS=riscv64-unknown-elf-as +CC=riscv64-unknown-elf-gcc +AR=riscv64-unknown-elf-ar + + +#Default Make +all: directories $(TARGET).memfile + +#Remake +remake: clean all + +#Make the Directories +directories: + @mkdir -p $(TARGETDIR) + @mkdir -p $(BUILDDIR) + +clean: + rm -rf $(BUILDDIR) $(TARGETDIR) *.memfile *.objdump + + +#Needed for building additional library projects +ifdef LIBRARY_DIRS +LIBS+=${LIBRARY_DIRS:%=-L%} ${LIBRARY_FILES:%=-l%} +INC+=${LIBRARY_DIRS:%=-I%} + +${LIBRARY_DIRS}: + make -C $@ -j 1 + +.PHONY: $(LIBRARY_DIRS) $(TARGET) +endif + + +#Pull in dependency info for *existing* .o files +-include $(OBJECTS:.$(OBJEXT)=.$(DEPEXT)) + +#Link +$(TARGET): $(OBJECTS) $(LIBRARY_DIRS) + $(CC) $(LINK_FLAGS) -g -o $(TARGET) $(OBJECTS) ${LIBS} -T ${LINKER} + + +#Compile +$(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(CEXT) + @mkdir -p $(dir $@) + $(CC) $(CFLAGS) $(INC) -c -o $@ $< > $(BUILDDIR)/$*.list + @$(CC) $(CFLAGS) $(INC) -MM $(SRCDIR)/$*.$(CEXT) > $(BUILDDIR)/$*.$(DEPEXT) + @cp -f $(BUILDDIR)/$*.$(DEPEXT) $(BUILDDIR)/$*.$(DEPEXT).tmp + @sed -e 's|.*:|$(BUILDDIR)/$*.$(OBJEXT):|' < $(BUILDDIR)/$*.$(DEPEXT).tmp > $(BUILDDIR)/$*.$(DEPEXT) + @sed -e 's/.*://' -e 's/\\$$//' < $(BUILDDIR)/$*.$(DEPEXT).tmp | fmt -1 | sed -e 's/^ *//' -e 's/$$/:/' >> $(BUILDDIR)/$*.$(DEPEXT) + @rm -f $(BUILDDIR)/$*.$(DEPEXT).tmp + +# gcc won't output dependencies for assembly files for some reason +# most asm files don't have dependencies so the echo will work for now. +$(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(AEXT) + @mkdir -p $(dir $@) + $(CC) $(CFLAGS) -c -o $@ $< > $(BUILDDIR)/$*.list + @echo $@: $< > $(BUILDDIR)/$*.$(DEPEXT) + +$(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(SEXT) + @mkdir -p $(dir $@) + $(CC) $(CFLAGS) $(INC) -c -o $@ $< > $(BUILDDIR)/$*.list + @echo $@: $< > $(BUILDDIR)/$*.$(DEPEXT) + +# C++ +$(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(CPPEXT) + @mkdir -p $(dir $@) + $(CC) $(CFLAGS) $(INC) -c -o $@ $< > $(BUILDDIR)/$*.list + @$(CC) $(CFLAGS) $(INC) -MM $(SRCDIR)/$*.$(CPPEXT) > $(BUILDDIR)/$*.$(DEPEXT) + @cp -f $(BUILDDIR)/$*.$(DEPEXT) $(BUILDDIR)/$*.$(DEPEXT).tmp + @sed -e 's|.*:|$(BUILDDIR)/$*.$(OBJEXT):|' < $(BUILDDIR)/$*.$(DEPEXT).tmp > $(BUILDDIR)/$*.$(DEPEXT) + @sed -e 's/.*://' -e 's/\\$$//' < $(BUILDDIR)/$*.$(DEPEXT).tmp | fmt -1 | sed -e 's/^ *//' -e 's/$$/:/' >> $(BUILDDIR)/$*.$(DEPEXT) + @rm -f $(BUILDDIR)/$*.$(DEPEXT).tmp + +# convert to hex +$(TARGET).memfile: $(TARGET) + @echo 'Making object dump file.' + @riscv64-unknown-elf-objdump -D $< > $<.objdump + @echo 'Making memory file' + riscv64-unknown-elf-elf2hex --bit-width 64 --input $^ --output $@ + extractFunctionRadix.sh $<.objdump + mkdir -p ../work/ + cp -f $(TARGETDIR)/* ../work/ diff --git a/tests/custom/spitest/spi.h b/tests/custom/spitest/spi.h new file mode 100644 index 000000000..2b1d541da --- /dev/null +++ b/tests/custom/spitest/spi.h @@ -0,0 +1,116 @@ +/////////////////////////////////////////////////////////////////////// +// spi.h +// +// Written: Jaocb Pease jacob.pease@okstate.edu 7/22/2024 +// +// Purpose: Header file for interfaceing with the SPI peripheral +// +// +// +// A component of the 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. +/////////////////////////////////////////////////////////////////////// + +#pragma once +#ifndef SPI_HEADER +#define SPI_HEADER + +#include + +#define SPI_BASE 0x13000 /* Base address of SPI device used for SDC */ + +/* register offsets */ +#define SPI_SCKDIV SPI_BASE + 0x00 /* Serial clock divisor */ +#define SPI_SCKMODE SPI_BASE + 0x04 /* Serial clock mode */ +#define SPI_CSID SPI_BASE + 0x10 /* Chip select ID */ +#define SPI_CSDEF SPI_BASE + 0x14 /* Chip select default */ +#define SPI_CSMODE SPI_BASE + 0x18 /* Chip select mode */ +#define SPI_DELAY0 SPI_BASE + 0x28 /* Delay control 0 */ +#define SPI_DELAY1 SPI_BASE + 0x2c /* Delay control 1 */ +#define SPI_FMT SPI_BASE + 0x40 /* Frame format */ +#define SPI_TXDATA SPI_BASE + 0x48 /* Tx FIFO data */ +#define SPI_RXDATA SPI_BASE + 0x4c /* Rx FIFO data */ +#define SPI_TXMARK SPI_BASE + 0x50 /* Tx FIFO [<35;39;29Mwatermark */ +#define SPI_RXMARK SPI_BASE + 0x54 /* Rx FIFO watermark */ + +/* Non-implemented +#define SPI_FCTRL SPI_BASE + 0x60 // SPI flash interface control +#define SPI_FFMT SPI_BASE + 0x64 // SPI flash instruction format +*/ +#define SPI_IE SPI_BASE + 0x70 /* Interrupt Enable Register */ +#define SPI_IP SPI_BASE + 0x74 /* Interrupt Pendings Register */ + +/* delay0 bits */ +#define SIFIVE_SPI_DELAY0_CSSCK(x) ((uint32_t)(x)) +#define SIFIVE_SPI_DELAY0_CSSCK_MASK 0xffU +#define SIFIVE_SPI_DELAY0_SCKCS(x) ((uint32_t)(x) << 16) +#define SIFIVE_SPI_DELAY0_SCKCS_MASK (0xffU << 16) + +/* delay1 bits */ +#define SIFIVE_SPI_DELAY1_INTERCS(x) ((uint32_t)(x)) +#define SIFIVE_SPI_DELAY1_INTERCS_MASK 0xffU +#define SIFIVE_SPI_DELAY1_INTERXFR(x) ((uint32_t)(x) << 16) +#define SIFIVE_SPI_DELAY1_INTERXFR_MASK (0xffU << 16) + +/* csmode bits */ +#define SIFIVE_SPI_CSMODE_MODE_AUTO 0U +#define SIFIVE_SPI_CSMODE_MODE_HOLD 2U +#define SIFIVE_SPI_CSMODE_MODE_OFF 3U + +// inline void write_reg(uintptr_t addr, uint32_t value); +//inline uint32_t read_reg(uintptr_t addr); +//inline void spi_sendbyte(uint8_t byte); +//inline void waittx(); +//inline void waitrx(); +uint8_t spi_txrx(uint8_t byte); +uint8_t spi_dummy(); +//inline uint8_t spi_readbyte(); +//uint64_t spi_read64(); +void spi_init(); +void spi_set_clock(uint32_t clkin, uint32_t clkout); + +static inline void write_reg(uintptr_t addr, uint32_t value) { + volatile uint32_t * loc = (volatile uint32_t *) addr; + *loc = value; +} + +// Read a register +static inline uint32_t read_reg(uintptr_t addr) { + return *(volatile uint32_t *) addr; +} + +// Queues a single byte in the transfer fifo +static inline void spi_sendbyte(uint8_t byte) { + // Write byte to transfer fifo + write_reg(SPI_TXDATA, byte); +} + +static inline void waittx() { + while(!(read_reg(SPI_IP) & 1)) {} +} + +static inline void waitrx() { + while(read_reg(SPI_IP) & 2) {} +} + +static inline uint8_t spi_readbyte() { + return read_reg(SPI_RXDATA); +} + +#endif diff --git a/tests/custom/spitest/spitest.c b/tests/custom/spitest/spitest.c new file mode 100644 index 000000000..23d408c16 --- /dev/null +++ b/tests/custom/spitest/spitest.c @@ -0,0 +1,107 @@ +/////////////////////////////////////////////////////////////////////// +// spi.c +// +// Written: Jaocb Pease jacob.pease@okstate.edu 8/27/2024 +// +// Purpose: C code to test SPI bugs +// +// +// +// A component of the 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. +/////////////////////////////////////////////////////////////////////// + +#include "spi.h" + +// Testing SPI peripheral in loopback mode +// TODO: Need to make sure the configuration I'm using uses loopback +// mode. This can be specified in derivlists.txt +// TODO: + +uint8_t spi_txrx(uint8_t byte) { + spi_sendbyte(byte); + waittx(); + return spi_readbyte(); +} + +uint8_t spi_dummy() { + return spi_txrx(0xff); +} + +void spi_set_clock(uint32_t clkin, uint32_t clkout) { + uint32_t div = (clkin/(2*clkout)) - 1; + write_reg(SPI_SCKDIV, div); +} + +// Initialize Sifive FU540 based SPI Controller +void spi_init(uint32_t clkin) { + // Enable interrupts + write_reg(SPI_IE, 0x3); + + // Set TXMARK to 1. If the number of entries is < 1 + // IP's txwm field will go high. + // Set RXMARK to 0. If the number of entries is > 0 + // IP's rwxm field will go high. + write_reg(SPI_TXMARK, 1); + write_reg(SPI_RXMARK, 0); + + // Set Delay 0 to default + write_reg(SPI_DELAY0, + SIFIVE_SPI_DELAY0_CSSCK(1) | + SIFIVE_SPI_DELAY0_SCKCS(1)); + + // Set Delay 1 to default + write_reg(SPI_DELAY1, + SIFIVE_SPI_DELAY1_INTERCS(1) | + SIFIVE_SPI_DELAY1_INTERXFR(0)); + + // Initialize the SPI controller clock to + // div = (20MHz/(2*400kHz)) - 1 = 24 = 0x18 + write_reg(SPI_SCKDIV, 0x18); +} + +void main() { + spi_init(100000000); + + spi_set_clock(100000000,50000000); + + volatile uint8_t *p = (uint8_t *)(0x8F000000); + int j; + uint64_t n = 0; + + write_reg(SPI_CSMODE, SIFIVE_SPI_CSMODE_MODE_HOLD); + //n = 512/8; + + n = 4; + do { + // Send 8 dummy bytes (fifo should be empty) + for (j = 0; j < 8; j++) { + spi_sendbyte(0xaa + j); + } + + // Reset counter. Process bytes AS THEY COME IN. + for (j = 0; j < 8; j++) { + while (!(read_reg(SPI_IP) & 2)) {} + uint8_t x = spi_readbyte(); + *p++ = x; + } + } while(--n > 0); + + write_reg(SPI_CSMODE, SIFIVE_SPI_CSMODE_MODE_AUTO); +} diff --git a/tests/custom/spitest/start.s b/tests/custom/spitest/start.s new file mode 100644 index 000000000..57f66ce79 --- /dev/null +++ b/tests/custom/spitest/start.s @@ -0,0 +1,59 @@ +.section .init +.global _start +.type _start, @function + +_start: + # Initialize global pointer + .option push + .option norelax + 1:auipc gp, %pcrel_hi(__global_pointer$) + addi gp, gp, %pcrel_lo(1b) + .option pop + + li x1, 0 + li x2, 0 + li x4, 0 + li x5, 0 + li x6, 0 + li x7, 0 + li x8, 0 + li x9, 0 + li x10, 0 + li x11, 0 + li x12, 0 + li x13, 0 + li x14, 0 + li x15, 0 + li x16, 0 + li x17, 0 + li x18, 0 + li x19, 0 + li x20, 0 + li x21, 0 + li x22, 0 + li x23, 0 + li x24, 0 + li x25, 0 + li x26, 0 + li x27, 0 + li x28, 0 + li x29, 0 + li x30, 0 + li x31, 0 + + + + # set the stack pointer to the top of memory - 8 bytes (pointer size) + li sp, 0x87FFFFF8 + + jal ra, main + jal ra, _halt + +.section .text +.global _halt +.type _halt, @function +_halt: + li gp, 1 + li a0, 0 + ecall + j _halt