merged covergen.py

This commit is contained in:
David Harris 2024-08-08 05:06:47 -07:00
commit 1e05dc5a8e
81 changed files with 4026 additions and 2101 deletions

11
.gitignore vendored
View File

@ -193,13 +193,21 @@ config/deriv
docs/docker/buildroot-config-src
docs/docker/testvector-generation
sim/questa/cov
sim/questa/covhtmlreport/
sim/questa/fcovrvvi
sim/questa/fcovrvvi_logs
sim/questa/fcovrvvi_ucdb
sim/covhtmlreport/
sim/questa/logs
sim/questa/wkdir
sim/questa/ucdb
sim/questa/fcov
sim/questa/fcov_logs
sim/questa/fcov_ucdb
sim/verilator/logs
sim/verilator/wkdir
sim/vcs/logs
sim/vcs/wkdir
sim/vcs/ucdb
benchmarks/coremark/coremark_results.csv
fpga/zsbl/OBJ/*
fpga/zsbl/bin/*
@ -238,3 +246,4 @@ tests/functcov/*
tests/functcov/*/*
sim/vcs/simprofile*
sim/verilator/verilator.log
/fpga/rvvidaemon/rvvidaemon

7
.gitmodules vendored
View File

@ -30,3 +30,10 @@
[submodule "addins/ahbsdc"]
path = addins/ahbsdc
url = http://github.com/JacobPease/ahbsdc.git
[submodule "addins/verilog-ethernet"]
sparseCheckout = true
path = addins/verilog-ethernet
url = https://github.com/ross144/verilog-ethernet.git
[submodule "cvw-arch-verif"]
path = cvw-arch-verif
url = https://github.com/openhwgroup/cvw-arch-verif

View File

@ -25,90 +25,6 @@ verify:
cd ${SIM}/sim; ./sim-testfloat-batch all
make imperasdv
imperasdv:
iter-elf.bash --search ${WALLY}/tests/riscof/work/wally-riscv-arch-test/rv64i_m
iter-elf.bash --search ${WALLY}/tests/riscof/work/riscv-arch-test/rv64i_m
imperasdv_cov:
touch ${SIM}/seed0.txt
echo "0" > ${SIM}/seed0.txt
# /opt/riscv/ImperasDV-OpenHW/scripts/cvw/run-elf-cov.bash --verbose --seed 0 --search ${WALLY}/tests/riscof/work/wally-riscv-arch-test/rv64i_m
# /opt/riscv/ImperasDV-OpenHW/scripts/cvw/run-elf-cov.bash --elf ${WALLY}/tests/riscof/work/riscv-arch-test/rv64i_m/I/src/add-01.S/dut/my.elf --seed ${SIM}/seed0.txt --coverdb ${SIM}/cov/rv64gc_arch64i.ucdb --verbose
# /opt/riscv/ImperasDV-OpenHW/scripts/cvw/run-elf-cov.bash --elf ${WALLY}/tests/riscof/work/riscv-arch-test/rv64i_m/I/src/add-01.S/dut/my.elf --seed ${SIM}/seed0.txt --coverdb ${SIM}/questa/riscv.ucdb --verbose
run-elf-cov.bash --elf ${WALLY}/tests/riscvdv/asm_test/riscv_arithmetic_basic_test_0.elf --seed ${SIM}/questa/seed0.txt --coverdb ${SIM}/questa/riscv.ucdb --verbose
vcover report -details -html ${SIM}/questa/riscv.ucdb
funcovreg:
#iter-elf.bash --search ${WALLY}/tests/riscof/work/wally-riscv-arch-test/rv64i_m --cover
#iter-elf.bash --search ${WALLY}/tests/riscof/work/wally-riscv-arch-test/rv64i_m/I --cover
#iter-elf.bash --search ${WALLY}/tests/riscof/work/wally-riscv-arch-test/rv64i_m/privilege --cover
#iter-elf.bash --search ${WALLY}/tests/riscof/work/wally-riscv-arch-test/rv64i_m/Q --cover
rm -f ${WALLY}/tests/riscof/work/riscv-arch-test/rv64i_m/*/src/*/dut/my.elf
iter-elf.bash --search ${WALLY}/tests/riscof/work/riscv-arch-test/rv64i_m/I --cover
vcover report -details -html ${SIM}/questa/riscv.ucdb
# test_name=riscv_arithmetic_basic_test
riscvdv:
python3 ${WALLY}/addins/riscv-dv/run.py --test ${test_name} --target rv64gc --output tests/riscvdv --iterations 1 -si questa --iss spike --verbose --cov --seed 0 --steps gen,gcc_compile >> ${SIM}/questa/functcov_logs/${test_name}.log 2>&1
# python3 ${WALLY}/addins/riscv-dv/run.py --test ${test_name} --target rv64gc --output tests/riscvdv --iterations 1 -si questa --iss spike --verbose --cov --seed 0 --steps gcc_compile >> ${SIM}/questa/functcov_logs/${test_name}.log 2>&1
# python3 ${WALLY}/addins/riscv-dv/run.py --test ${test_name} --target rv64gc --output tests/riscvdv --iterations 1 -si questa --iss spike --verbose --cov --seed 0 --steps iss_sim >> ${SIM}/questa/functcov_logs/${test_name}.log 2>&1
# run-elf.bash --seed ${SIM}/questa/seed0.txt --verbose --elf ${WALLY}/tests/riscvdv/asm_test/${test_name}_0.o >> ${SIM}/questa/functcov_logs/${test_name}.log 2>&1
#run-elf-cov.bash --seed ${SIM}/questa/seed0.txt --verbose --coverdb ${SIM}/questa/riscv.ucdb --elf ${WALLY}/tests/riscvdv/asm_test/${test_name}_0.o >> ${SIM}/questa/functcov_logs/${test_name}.log 2>&1
#cp ${SIM}/questa/riscv.ucdb ${SIM}/questa/functcov_ucdbs/${test_name}.ucdb
riscvdv_functcov:
mkdir -p ${SIM}/questa/functcov_logs
mkdir -p ${SIM}/questa/functcov_ucdbs
cd ${SIM}/questa/functcov_logs && rm -rf *
cd ${SIM}/questa/functcov_ucdbs && rm -rf *
make riscvdv test_name=riscv_arithmetic_basic_test >> ${SIM}/questa/functcov.log 2>&1
make riscvdv test_name=riscv_amo_test >> ${SIM}/questa/functcov.log 2>&1
make riscvdv test_name=riscv_ebreak_debug_mode_test >> ${SIM}/questa/functcov.log 2>&1
make riscvdv test_name=riscv_ebreak_test >> ${SIM}/questa/functcov.log 2>&1
make riscvdv test_name=riscv_floating_point_arithmetic_test >> ${SIM}/questa/functcov.log 2>&1
make riscvdv test_name=riscv_floating_point_mmu_stress_test >> ${SIM}/questa/functcov.log 2>&1
make riscvdv test_name=riscv_floating_point_rand_test >> ${SIM}/questa/functcov.log 2>&1
make riscvdv test_name=riscv_full_interrupt_test >> ${SIM}/questa/functcov.log 2>&1
make riscvdv test_name=riscv_hint_instr_test >> ${SIM}/questa/functcov.log 2>&1
make riscvdv test_name=riscv_illegal_instr_test >> ${SIM}/questa/functcov.log 2>&1
make riscvdv test_name=riscv_invalid_csr_test >> ${SIM}/questa/functcov.log 2>&1
make riscvdv test_name=riscv_jump_stress_test >> ${SIM}/questa/functcov.log 2>&1
make riscvdv test_name=riscv_loop_test >> ${SIM}/questa/functcov.log 2>&1
make riscvdv test_name=riscv_machine_mode_rand_test >> ${SIM}/questa/functcov.log 2>&1
make riscvdv test_name=riscv_mmu_stress_test >> ${SIM}/questa/functcov.log 2>&1
make riscvdv test_name=riscv_no_fence_test >> ${SIM}/questa/functcov.log 2>&1
make riscvdv test_name=riscv_non_compressed_instr_test >> ${SIM}/questa/functcov.log 2>&1
make riscvdv test_name=riscv_pmp_test >> ${SIM}/questa/functcov.log 2>&1
make riscvdv test_name=riscv_privileged_mode_rand_test >> ${SIM}/questa/functcov.log 2>&1
make riscvdv test_name=riscv_rand_instr_test >> ${SIM}/questa/functcov.log 2>&1
make riscvdv test_name=riscv_rand_jump_test >> ${SIM}/questa/functcov.log 2>&1
make riscvdv test_name=riscv_sfence_exception_test >> ${SIM}/questa/functcov.log 2>&1
make riscvdv test_name=riscv_unaligned_load_store_test >> ${SIM}/questa/functcov.log 2>&1
combine_functcov:
mkdir -p ${SIM}/questa/functcov
mkdir -p ${SIM}/questa/functcov_logs
cd ${SIM}/questa/functcov && rm -rf *
run-elf-cov.bash --seed ${SIM}/questa/seed0.txt --verbose --coverdb ${SIM}/questa/functcov/add.ucdb --elf ${WALLY}/tests/functcov/rv64/I/WALLY-COV-add.elf >> ${SIM}/questa/functcov_logs/add.log 2>&1
run-elf-cov.bash --seed ${SIM}/questa/seed0.txt --verbose --coverdb ${SIM}/questa/functcov/and.ucdb --elf ${WALLY}/tests/functcov/rv64/I/WALLY-COV-and.elf >> ${SIM}/questa/functcov_logs/add.log 2>&1
run-elf-cov.bash --seed ${SIM}/questa/seed0.txt --verbose --coverdb ${SIM}/questa/functcov/ori.ucdb --elf ${WALLY}/tests/functcov/rv64/I/WALLY-COV-ori.elf >> ${SIM}/questa/functcov_logs/add.log 2>&1
vcover merge ${SIM}/questa/functcov/functcov.ucdb ${SIM}/questa/functcov/*.ucdb ${SIM}/questa/functcov_ucdbs/* -suppress 6854 -64
# vcover merge ${SIM}/questa/functcov/functcov.ucdb ${SIM}/questa/functcov_ucdbs/* -suppress 6854 -64
vcover report -details -html ${SIM}/questa/functcov/functcov.ucdb
vcover report ${SIM}/questa/functcov/functcov.ucdb -details -cvg > ${SIM}/questa/functcov/functcov.log
vcover report ${SIM}/questa/functcov/functcov.ucdb -testdetails -cvg > ${SIM}/questa/functcov/functcov.testdetails.log
# vcover report ${SIM}/questa/functcov/functcov.ucdb -details -cvg -below 100 | egrep "Coverpoint|Covergroup|Cross" | grep -v Metric > ${SIM}/questa/functcov/functcov.ucdb.summary.log
vcover report ${SIM}/questa/functcov/functcov.ucdb -details -cvg | egrep "Coverpoint|Covergroup|Cross|TYPE" > ${SIM}/questa/functcov/functcov.summary.log
grep "Total Coverage By Instance" ${SIM}/questa/functcov/functcov.ucdb.log
remove_functcov_artifacts:
rm ${SIM}/questa/riscv.ucdb ${SIM}/questa/functcov.log covhtmlreport/ ${SIM}/questa/functcov_logs/ ${SIM}/questa/functcov_ucdbs/ ${SIM}/questa/functcov/ -rf
collect_functcov: remove_functcov_artifacts riscvdv_functcov combine_functcov
benchmarks:
make coremark
make embench

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 argparse
import multiprocessing
from collections import namedtuple
from multiprocessing import Pool, TimeoutError
@ -281,6 +282,22 @@ def addTests(tests, sim):
grepfile = grepfile)
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):
"""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
@ -320,22 +337,29 @@ 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 = "verilator" # Default simulator for all other tests
coverage = '--coverage' in sys.argv
fp = '--fp' in sys.argv
nightly = '--nightly' in sys.argv
testfloat = '--testfloat' in sys.argv
buildroot = '--buildroot' in sys.argv
parser = argparse.ArgumentParser()
parser.add_argument("--ccov", help="Code Coverage", action="store_true")
parser.add_argument("--fcov", help="Functional Coverage", action="store_true")
parser.add_argument("--fcovrvvi", help="Functional Coverage RVVI", action="store_true")
parser.add_argument("--nightly", help="Run large nightly regression", action="store_true")
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";
# sims = [defaultsim] # uncomment to use only the default simulator
sims = ["questa", "verilator", "vcs"] # uncomment to exercise all simulators
sims = ["questa", "verilator", "vcs"] # exercise all simulators; can omit a sim if no license is available
else:
nightMode = ""
sims = [defaultsim]
if (coverage): # only run RV64GC tests in coverage mode
coverStr = '--coverage'
if (args.ccov): # only run RV64GC tests in coverage mode
coverStr = '--ccov'
elif (args.fcov): # only run RV64GC tests in lockstep in coverage mode
coverStr = '--fcov'
elif (args.fcovrvvi): # only run RV64GC tests in rvvi coverage mode
coverStr = '--fcovrvvi'
else:
coverStr = ''
@ -353,25 +377,38 @@ configs = [
# 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_buildrootbootlockstep, "questa") # lockstep with Questa and ImperasDV runs overnight
if (coverage): # only run RV64GC tests on Questa in coverage mode
addTests(tests64gc_nofp, "questa")
if (fp):
addTests(tests64gc_fp, "questa")
else:
if (args.ccov): # only run RV64GC tests on Questa in code coverage mode
addTests(tests64gc_nofp, coveragesim)
if (args.fp):
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)
elif (args.fcovrvvi): # only run RV64GC tests on Questa in rvvi coverage mode
addTests(tests64gc_nofp, coveragesim)
if (args.fp):
addTests(tests64gc_fp, coveragesim)
else:
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, sim)
addTests(tests64gc_nofp, sim)
addTests(tests64gc_fp, sim)
# run derivative configurations and lockstep tests in nightly regression
if (nightly):
addTests(derivconfigtests, defaultsim)
if (args.nightly):
sim_log = WALLY + "/sim/questa/logs/lockstep_coverage.log"
tc = TestCase(
name="lockstep_coverage",
@ -385,15 +422,16 @@ if (nightly):
tc = TestCase(
name="lockstep_wally-riscv-arch-test",
variant="rv64gc",
cmd="iterelf " + WALLY + "/tests/riscof/work/wally-riscv-arch-test/rv64i_m/privilege > " + sim_log,
cmd="iterelf " + WALLY + "/tests/riscof/work/wally-riscv-arch-test/rv64i_m > " + sim_log,
grepstr="SUCCESS! All tests ran without failures",
grepfile = sim_log)
configs.append(tc)
addTests(derivconfigtests, defaultsim)
# testfloat tests
if (testfloat): # for testfloat alone, just run testfloat tests
if (args.testfloat): # for testfloat alone, just run testfloat tests
configs = []
if (testfloat or nightly): # for nightly, run testfloat along with othres
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
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:
@ -458,7 +496,7 @@ if (testfloat or nightly): # for nightly, run testfloat along with othres
def main():
"""Run the tests and count the failures"""
global configs, coverage
global configs, args
os.chdir(regressionDir)
dirs = ["questa/logs", "questa/wkdir", "verilator/logs", "verilator/wkdir", "vcs/logs", "vcs/wkdir"]
for d in dirs:
@ -467,24 +505,30 @@ def main():
os.mkdir(d)
except:
pass
if '--makeTests' in sys.argv:
os.chdir(regressionDir)
os.system('./make-tests.sh | tee ./logs/make-tests.log')
elif '--coverage' in sys.argv:
if args.ccov:
TIMEOUT_DUR = 20*60 # seconds
os.system('rm -f questa/cov/*.ucdb')
elif '--nightly' in sys.argv:
elif args.fcovrvvi:
TIMEOUT_DUR = 20*60
os.system('rm -f questa/fcovrvvi_ucdb/* questa/fcovrvvi_logs/* questa/fcovrvvi/*')
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
elif '--testfloat' in sys.argv:
elif args.testfloat:
TIMEOUT_DUR = 30*60 # seconds
else:
TIMEOUT_DUR = 10*60 # seconds
# 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
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
results = {}
for config in configs:
@ -497,8 +541,12 @@ def main():
print(f"{bcolors.FAIL}%s_%s: Timeout - runtime exceeded %d seconds{bcolors.ENDC}" % (config.variant, config.name, TIMEOUT_DUR))
# Coverage report
if coverage:
os.system('make QuestaCoverage')
if args.ccov:
os.system('make QuestaCodeCoverage')
if args.fcov:
os.system('make QuestaFunctCoverage')
if args.fcovrvvi:
os.system('make QuestaFunctCoverageRvvi')
# Count the number of failures
if num_fail:
print(f"{bcolors.FAIL}Regression failed with %s failed configurations{bcolors.ENDC}" % num_fail)

View File

@ -26,13 +26,15 @@ parser.add_argument("--elf", "-e", help="ELF File name; use if name does not end
parser.add_argument("--sim", "-s", help="Simulator", choices=["questa", "verilator", "vcs"], default="questa")
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("--coverage", "-c", help="Code & Functional Coverage", action="store_true")
parser.add_argument("--fcov", "-f", help="Code & Functional Coverage", 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("--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("--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)
parser.add_argument("--covlog", "-d", help="Log coverage after n instructions.", default=0)
parser.add_argument("--rvvi", "-r", help="Simulate rvvi hardware interface and ethernet.", action="store_true")
args = parser.parse_args()
print("Config=" + args.config + " tests=" + args.testsuite + " sim=" + args.sim + " gui=" + str(args.gui) + " args='" + args.args + "'")
ElfFile=""
@ -44,10 +46,11 @@ elif (args.elf != ""):
print("ELF file not found: " + args.elf)
exit(1)
if(args.testsuite.endswith('.elf')):
if(args.testsuite.endswith('.elf') and args.elf == ""): # No --elf argument; check if testsuite has a .elf extension and use that instead
if (os.path.isfile(args.testsuite)):
ElfFile = "+ElfFile=" + os.path.abspath(args.testsuite)
args.testsuite=args.testsuite.rsplit('/', 1)[1]
if ('/' in args.testsuite):
args.testsuite=args.testsuite.rsplit('/', 1)[1] # strip off path if present
else:
print("ELF file not found: " + args.testsuite)
exit(1)
@ -55,7 +58,7 @@ if(args.testsuite.endswith('.elf')):
# Validate arguments
if (args.gui or args.coverage or args.fcov or args.lockstep):
if (args.gui or args.ccov or args.fcov or args.fcovrvvi or args.lockstep):
if args.sim not in ["questa", "vcs"]:
print("Option only supported for Questa and VCS")
exit(1)
@ -63,6 +66,9 @@ if (args.gui or args.coverage or args.fcov or args.lockstep):
if (args.vcd):
args.args += " -DMAKEVCD=1"
if (args.rvvi):
args.args += " -GRVVI_SYNTH_SUPPORTED=1"
# if lockstep is enabled, then we need to pass the Imperas lockstep arguments
if(int(args.locksteplog) >= 1): EnableLog = 1
else: EnableLog = 0
@ -86,14 +92,16 @@ else:
flags = suffix + " " + ImperasPlusArgs
# other flags
if (args.coverage):
flags += " --coverage"
if (args.ccov):
flags += " --ccov"
if (args.fcov):
flags += " --fcov"
if (args.fcovrvvi):
flags += "--fcovrvvi"
# create the output sub-directories.
regressionDir = WALLY + '/sim/'
for d in ["logs", "wkdir", "cov"]:
for d in ["logs", "wkdir", "cov", "ucdb", "fcov", "fcov_ucdb", "fcovrvvi", "fcovrvvi_ucdb"]:
try:
os.mkdir(regressionDir+args.sim+"/"+d)
except:

View File

@ -50,7 +50,8 @@ PLIC_NUM_SRC 32'd53
deriv fpga buildroot
BOOTROM_PRELOAD 1
UNCORE_RAM_BASE 64'h2000
UNCORE_RAM_RANGE 64'hFFF
UNCORE_RAM_RANGE 64'h1FFF
BOOTROM_RANGE 64'hFFF
EXT_MEM_SUPPORTED 1
EXT_MEM_BASE 64'h80000000
EXT_MEM_RANGE 64'h0FFFFFFF
@ -1657,15 +1658,24 @@ IDIV_ON_FPU 1
# imperas used for a smart memory
# VCS doesn't like removing the bootrom, but make it tiny in a random unused location
derive imperas rv64gc
derive ImperasTG rv64gc
ICACHE_SUPPORTED 0
DCACHE_SUPPORTED 0
VIRTMEM_SUPPORTED 0
ZICCLSM_SUPPORTED 0
ZAAMO_SUPPORTED 0
ZALRSC_SUPPORTED 0
ZICBOM_SUPPORTED 0
ZICBOZ_SUPPORTED 0
SVPBMT_SUPPORTED 0
SVNAPOT_SUPPORTED 0
BOOTROM_BASE 64'h700012340010
BOOTROM_BASE 64'h700012340080
BOOTROM_RANGE 64'h10
CLINT_SUPPORTED 0
GPIO_SUPPORTED 0
UART_SUPPORTED 0
PLIC_SUPPORTED 0
SPI_SUPPORTED 0

1
cvw-arch-verif Submodule

@ -0,0 +1 @@
Subproject commit 2a4f56ec97db7cdd6fd13fb928122d408fefbf1e

View File

@ -4,11 +4,38 @@
# 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]
##### clock #####
set_property PACKAGE_PIN E3 [get_ports {default_100mhz_clk}]
set_property IOSTANDARD LVCMOS33 [get_ports {default_100mhz_clk}]
##### RVVI Ethernet ####
# taken from https://github.com/alexforencich/verilog-ethernet/blob/master/example/Arty/fpga/fpga.xdc
set_property -dict {LOC F15 IOSTANDARD LVCMOS33} [get_ports phy_rx_clk]
set_property -dict {LOC D18 IOSTANDARD LVCMOS33} [get_ports {phy_rxd[0]}]
set_property -dict {LOC E17 IOSTANDARD LVCMOS33} [get_ports {phy_rxd[1]}]
set_property -dict {LOC E18 IOSTANDARD LVCMOS33} [get_ports {phy_rxd[2]}]
set_property -dict {LOC G17 IOSTANDARD LVCMOS33} [get_ports {phy_rxd[3]}]
set_property -dict {LOC G16 IOSTANDARD LVCMOS33} [get_ports phy_rx_dv]
set_property -dict {LOC C17 IOSTANDARD LVCMOS33} [get_ports phy_rx_er]
set_property -dict {LOC H16 IOSTANDARD LVCMOS33} [get_ports phy_tx_clk]
set_property -dict {LOC H14 IOSTANDARD LVCMOS33 SLEW FAST DRIVE 12} [get_ports {phy_txd[0]}]
set_property -dict {LOC J14 IOSTANDARD LVCMOS33 SLEW FAST DRIVE 12} [get_ports {phy_txd[1]}]
set_property -dict {LOC J13 IOSTANDARD LVCMOS33 SLEW FAST DRIVE 12} [get_ports {phy_txd[2]}]
set_property -dict {LOC H17 IOSTANDARD LVCMOS33 SLEW FAST DRIVE 12} [get_ports {phy_txd[3]}]
set_property -dict {LOC H15 IOSTANDARD LVCMOS33 SLEW FAST DRIVE 12} [get_ports phy_tx_en]
set_property -dict {LOC D17 IOSTANDARD LVCMOS33} [get_ports phy_col]
set_property -dict {LOC G14 IOSTANDARD LVCMOS33} [get_ports phy_crs]
set_property -dict {LOC G18 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 12} [get_ports phy_ref_clk]
set_property -dict {LOC C16 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 12} [get_ports phy_reset_n]
create_clock -period 40.000 -name phy_rx_clk [get_ports phy_rx_clk]
create_clock -period 40.000 -name phy_tx_clk [get_ports phy_tx_clk]
set_false_path -to [get_ports {phy_ref_clk phy_reset_n}]
set_output_delay 0 [get_ports {phy_ref_clk phy_reset_n}]
##### GPI ####
set_property PACKAGE_PIN A8 [get_ports {GPI[0]}]
set_property PACKAGE_PIN C9 [get_ports {GPI[1]}]
@ -34,6 +61,7 @@ set_property IOSTANDARD LVCMOS33 [get_ports {GPO[2]}]
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[*]}]
@ -74,42 +102,52 @@ set_property IOSTANDARD LVCMOS33 [get_ports {south_reset}]
##### SD Card I/O #####
#***** may have to switch to Pmod JB or JC.
set_property PACKAGE_PIN D4 [get_ports {SDCDat[3]}]
set_property PACKAGE_PIN D2 [get_ports {SDCDat[2]}]
set_property PACKAGE_PIN E2 [get_ports {SDCDat[1]}]
set_property PACKAGE_PIN F4 [get_ports {SDCDat[0]}]
set_property PACKAGE_PIN F3 [get_ports SDCCLK]
set_property PACKAGE_PIN D3 [get_ports {SDCCmd}]
set_property PACKAGE_PIN H2 [get_ports {SDCCD}]
#set_property PACKAGE_PIN D4 [get_ports {SDCDat[3]}]
#set_property PACKAGE_PIN D2 [get_ports {SDCDat[2]}]
#set_property PACKAGE_PIN E2 [get_ports {SDCDat[1]}]
#set_property PACKAGE_PIN F4 [get_ports {SDCDat[0]}]
#set_property PACKAGE_PIN F3 [get_ports SDCCLK]
#set_property PACKAGE_PIN D3 [get_ports {SDCCmd}]
#set_property PACKAGE_PIN H2 [get_ports {SDCCD}]
#set_property IOSTANDARD LVCMOS33 [get_ports {SDCDat[3]}]
#set_property IOSTANDARD LVCMOS33 [get_ports {SDCDat[2]}]
#set_property IOSTANDARD LVCMOS33 [get_ports {SDCDat[1]}]
#set_property IOSTANDARD LVCMOS33 [get_ports {SDCDat[0]}]
#set_property IOSTANDARD LVCMOS33 [get_ports SDCCLK]
#set_property IOSTANDARD LVCMOS33 [get_ports {SDCCmd}]
#set_property IOSTANDARD LVCMOS33 [get_ports {SDCCD}]
#set_property PULLUP true [get_ports {SDCDat[3]}]
#set_property PULLUP true [get_ports {SDCDat[2]}]
#set_property PULLUP true [get_ports {SDCDat[1]}]
#set_property PULLUP true [get_ports {SDCDat[0]}]
#set_property PULLUP true [get_ports {SDCCmd}]
#set_property PULLUP true [get_ports {SDCCD}]
# SDCDat[3]
set_property -dict {PACKAGE_PIN D4 IOSTANDARD LVCMOS33 PULLUP true} [get_ports {SDCCS}]
# set_property -dict {PACKAGE_PIN D2 IOSTANDARD LVCMOS33 PULLUP true} [get_ports {SDCDat[2]}]
# set_property -dict {PACKAGE_PIN E2 IOSTANDARD LVCMOS33 PULLUP true} [get_ports {SDCDat[1]}]
# SDCDat[0]
set_property -dict {PACKAGE_PIN F4 IOSTANDARD LVCMOS33 PULLUP true} [get_ports {SDCIn}]
set_property -dict {PACKAGE_PIN F3 IOSTANDARD LVCMOS33 PULLUP true} [get_ports {SDCCLK}]
set_property -dict {PACKAGE_PIN D3 IOSTANDARD LVCMOS33 PULLUP true} [get_ports {SDCCmd}]
set_property -dict {PACKAGE_PIN H2 IOSTANDARD LVCMOS33 PULLUP true} [get_ports {SDCCD}]
set_property -dict {PACKAGE_PIN G2 IOSTANDARD LVCMOS33 PULLUP true} [get_ports {SDCWP}]
set_property IOSTANDARD LVCMOS33 [get_ports {SDCDat[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {SDCDat[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {SDCDat[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {SDCDat[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports SDCCLK]
set_property IOSTANDARD LVCMOS33 [get_ports {SDCCmd}]
set_property IOSTANDARD LVCMOS33 [get_ports {SDCCD}]
set_property PULLUP true [get_ports {SDCDat[3]}]
set_property PULLUP true [get_ports {SDCDat[2]}]
set_property PULLUP true [get_ports {SDCDat[1]}]
set_property PULLUP true [get_ports {SDCDat[0]}]
set_property PULLUP true [get_ports {SDCCmd}]
set_property PULLUP true [get_ports {SDCCD}]
set_input_delay -clock [get_clocks SPISDCClock] -min -add_delay 2.500 [get_ports {SDCCS}]
set_input_delay -clock [get_clocks SPISDCClock] -max -add_delay 10.000 [get_ports {SDCCS}]
set_input_delay -clock [get_clocks SPISDCClock] -min -add_delay 2.500 [get_ports {SDCIn}]
set_input_delay -clock [get_clocks SPISDCClock] -max -add_delay 10.000 [get_ports {SDCIn}]
set_input_delay -clock [get_clocks clk_out3_xlnx_mmcm] -min -add_delay 2.500 [get_ports {SDCDat[*]}]
set_input_delay -clock [get_clocks clk_out3_xlnx_mmcm] -max -add_delay 21.000 [get_ports {SDCDat[*]}]
set_output_delay -clock [get_clocks SPISDCClock] -min -add_delay 2.000 [get_ports {SDCCmd}]
set_output_delay -clock [get_clocks SPISDCClock] -max -add_delay 6.000 [get_ports {SDCCmd}]
set_input_delay -clock [get_clocks clk_out3_xlnx_mmcm] -min -add_delay 2.500 [get_ports {SDCCmd}]
set_input_delay -clock [get_clocks clk_out3_xlnx_mmcm] -max -add_delay 14.000 [get_ports {SDCCmd}]
set_output_delay -clock [get_clocks SPISDCClock] 0.000 [get_ports SDCCLK]
set_output_delay -clock [get_clocks clk_out3_xlnx_mmcm] -min -add_delay 2.000 [get_ports {SDCCmd}]
set_output_delay -clock [get_clocks clk_out3_xlnx_mmcm] -max -add_delay 6.000 [get_ports {SDCCmd}]
set_output_delay -clock [get_clocks clk_out3_xlnx_mmcm] 0.000 [get_ports SDCCLK]
#set_multicycle_path -from [get_pins xlnx_ddr3_c0/u_xlnx_ddr3_mig/u_memc_ui_top_axi/mem_intfc0/ddr_phy_top0/u_ddr_calib_top/init_calib_complete_reg/C] -to [get_pins xlnx_proc_sys_reset_0/U0/EXT_LPF/lpf_int_reg/D] 10
set_max_delay -datapath_only -from [get_pins xlnx_ddr3_c0/u_xlnx_ddr3_mig/u_memc_ui_top_axi/mem_intfc0/ddr_phy_top0/u_ddr_calib_top/init_calib_complete_reg/C] -to [get_pins xlnx_proc_sys_reset_0/U0/EXT_LPF/lpf_int_reg/D] 20.000

View File

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

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

@ -1,14 +1,14 @@
dst := IP
# vcu118
#export XILINX_PART := xcvu9p-flga2104-2L-e
#export XILINX_BOARD := xilinx.com:vcu118:part0:2.4
#export board := vcu118
# export XILINX_PART := xcvu9p-flga2104-2L-e
# export XILINX_BOARD := xilinx.com:vcu118:part0:2.4
# export board := vcu118
# vcu108
#export XILINX_PART := xcvu095-ffva2104-2-e
#export XILINX_BOARD := xilinx.com:vcu108:part0:1.2
#export board := vcu108
# export XILINX_PART := xcvu095-ffva2104-2-e
# export XILINX_BOARD := xilinx.com:vcu108:part0:1.7
# export board := vcu108
# Arty A7
export XILINX_PART := xc7a100tcsg324-1
@ -40,17 +40,19 @@ IP_Arty: $(dst)/xlnx_proc_sys_reset.log \
$(dst)/xlnx_ddr3-$(board).log \
$(dst)/xlnx_mmcm.log \
$(dst)/xlnx_axi_clock_converter.log \
$(dst)/xlnx_ahblite_axi_bridge.log \
$(dst)/xlnx_axi_crossbar.log \
$(dst)/xlnx_axi_dwidth_conv_32to64.log \
$(dst)/xlnx_axi_dwidth_conv_64to32.log \
$(dst)/xlnx_axi_prtcl_conv.log
$(dst)/xlnx_ahblite_axi_bridge.log
#$(dst)/xlnx_axi_crossbar.log \
#$(dst)/xlnx_axi_dwidth_conv_32to64.log \
#$(dst)/xlnx_axi_dwidth_conv_64to32.log \
#$(dst)/xlnx_axi_prtcl_conv.log
PreProcessFiles:
$(MAKE) -C ../../sim deriv
rm -rf ../src/CopiedFiles_do_not_add_to_repo/
cp -r ../../src/ ../src/CopiedFiles_do_not_add_to_repo/
cp -r ../../addins/verilog-ethernet/*/*.sv ../src/CopiedFiles_do_not_add_to_repo/rvvi
cp -r ../../addins/verilog-ethernet/*/*/*/*.sv ../src/CopiedFiles_do_not_add_to_repo/rvvi
mkdir ../src/CopiedFiles_do_not_add_to_repo/config/
cp ../../config/deriv/fpga/config.vh ../src/CopiedFiles_do_not_add_to_repo/config/
./insert_debug_comment.sh
@ -59,6 +61,7 @@ PreProcessFiles:
# This line allows the Bootloader to be loaded in a Block RAM on the FPGA
sed -i "s/bit \[DATA_WIDTH-1:0\].*ROM.*/(\* rom_style=\"block\" \*) &/g" ../src/CopiedFiles_do_not_add_to_repo/generic/mem/rom1p1r.sv
sed -i 's/$$WALLY/\.\.\/\.\.\/\.\.\//g' ../src/CopiedFiles_do_not_add_to_repo/generic/mem/rom1p1r.sv
sed -i 's/$$WALLY/\.\.\/\.\.\/\.\.\//g' ../src/CopiedFiles_do_not_add_to_repo/generic/mem/ram1p1rwbe.sv
$(dst)/%.log: %.tcl
mkdir -p IP

View File

@ -27,10 +27,10 @@ read_ip IP/xlnx_proc_sys_reset.srcs/sources_1/ip/xlnx_proc_sys_reset/xlnx_proc_s
read_ip IP/xlnx_ahblite_axi_bridge.srcs/sources_1/ip/xlnx_ahblite_axi_bridge/xlnx_ahblite_axi_bridge.xci
read_ip IP/xlnx_axi_clock_converter.srcs/sources_1/ip/xlnx_axi_clock_converter/xlnx_axi_clock_converter.xci
# Added crossbar - Jacob Pease <2023-01-12 Thu>
read_ip IP/xlnx_axi_crossbar.srcs/sources_1/ip/xlnx_axi_crossbar/xlnx_axi_crossbar.xci
read_ip IP/xlnx_axi_dwidth_conv_32to64.srcs/sources_1/ip/xlnx_axi_dwidth_conv_32to64/xlnx_axi_dwidth_conv_32to64.xci
read_ip IP/xlnx_axi_dwidth_conv_64to32.srcs/sources_1/ip/xlnx_axi_dwidth_conv_64to32/xlnx_axi_dwidth_conv_64to32.xci
read_ip IP/xlnx_axi_prtcl_conv.srcs/sources_1/ip/xlnx_axi_prtcl_conv/xlnx_axi_prtcl_conv.xci
#read_ip IP/xlnx_axi_crossbar.srcs/sources_1/ip/xlnx_axi_crossbar/xlnx_axi_crossbar.xci
#read_ip IP/xlnx_axi_dwidth_conv_32to64.srcs/sources_1/ip/xlnx_axi_dwidth_conv_32to64/xlnx_axi_dwidth_conv_32to64.xci
#read_ip IP/xlnx_axi_dwidth_conv_64to32.srcs/sources_1/ip/xlnx_axi_dwidth_conv_64to32/xlnx_axi_dwidth_conv_64to32.xci
#read_ip IP/xlnx_axi_prtcl_conv.srcs/sources_1/ip/xlnx_axi_prtcl_conv/xlnx_axi_prtcl_conv.xci
if {$board=="ArtyA7"} {
read_ip IP/xlnx_ddr3.srcs/sources_1/ip/xlnx_ddr3/xlnx_ddr3.xci
@ -89,11 +89,10 @@ report_clock_interaction -file re
write_verilog -force -mode funcsim sim/syn-funcsim.v
if {$board=="ArtyA7"} {
source ../constraints/small-debug.xdc
#source ../constraints/small-debug.xdc
source ../constraints/small-debug-rvvi.xdc
} else {
# source ../constraints/vcu-small-debug.xdc
source ../constraints/debug6.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.CLKOUT2_USED {true} \
CONFIG.CLKOUT3_USED {true} \
CONFIG.CLKOUT4_USED {false} \
CONFIG.CLKOUT4_USED {true} \
CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {166.66667} \
CONFIG.CLKOUT2_REQUESTED_OUT_FREQ {200} \
CONFIG.CLKOUT3_REQUESTED_OUT_FREQ {20} \
CONFIG.CLKOUT4_REQUESTED_OUT_FREQ {25} \
CONFIG.CLKIN1_JITTER_PS {10.0} \
] [get_ips $ipName]

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;
}

File diff suppressed because it is too large Load Diff

View File

@ -17,6 +17,7 @@ OBJECTS := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(OBJECTS))
TARGETDIR := bin
TARGET := $(TARGETDIR)/boot
MEMFILES := $(TARGETDIR/boot.mem $(TARGETDIR)/data.mem
ROOT := ..
LIBRARY_DIRS :=
LIBRARY_FILES :=
@ -37,7 +38,7 @@ AR=riscv64-unknown-elf-ar
#Default Make
all: directories $(TARGET).memfile
all: directories $(TARGET).memfile
#Remake
remake: clean all
@ -48,7 +49,7 @@ directories:
@mkdir -p $(BUILDDIR)
clean:
rm -rf $(BUILDDIR) $(TARGETDIR) *.memfile *.objdump
rm -rf $(BUILDDIR) $(TARGETDIR) *.memfile *.objdump boot.mem data.mem
#Needed for building additional library projects
@ -112,3 +113,7 @@ $(TARGET).memfile: $(TARGET)
extractFunctionRadix.sh $<.objdump
mkdir -p ../../imperas-riscv-tests/work/rv64BP/
cp -f $(TARGETDIR)/* ../../imperas-riscv-tests/work/rv64BP/
@echo 'Splitting memfile.'
./splitfile.sh $@
mv boot.mem ../src/boot.mem
mv data.mem ../src/data.mem

View File

@ -1,422 +1,146 @@
///////////////////////////////////////////////////////////////////////
// boot.c
//
// Written: Jacob Pease jacob.pease@okstate.edu 7/22/2024
//
// Purpose: Main bootloader entry point
//
//
//
// 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 <stddef.h>
#include "boot.h"
#include "gpt.h"
#include "uart.h"
#include "spi.h"
#include "sd.h"
#include "time.h"
#include "riscv.h"
#include "fail.h"
/* Card type flags (card_type) */
#define CT_MMC 0x01 /* MMC ver 3 */
#define CT_SD1 0x02 /* SD ver 1 */
#define CT_SD2 0x04 /* SD ver 2 */
#define CT_SDC (CT_SD1|CT_SD2) /* SD */
#define CT_BLOCK 0x08 /* Block addressing */
int disk_read(BYTE * buf, LBA_t sector, UINT count) {
uint64_t r;
UINT i;
volatile uint8_t *p = buf;
#define CMD0 (0) /* GO_IDLE_STATE */
#define CMD1 (1) /* SEND_OP_COND */
#define CMD2 (2) /* SEND_CID */
#define CMD3 (3) /* RELATIVE_ADDR */
#define CMD4 (4)
#define CMD5 (5) /* SLEEP_WAKE (SDC) */
#define CMD6 (6) /* SWITCH_FUNC */
#define CMD7 (7) /* SELECT */
#define CMD8 (8) /* SEND_IF_COND */
#define CMD9 (9) /* SEND_CSD */
#define CMD10 (10) /* SEND_CID */
#define CMD11 (11)
#define CMD12 (12) /* STOP_TRANSMISSION */
#define CMD13 (13)
#define CMD15 (15)
#define CMD16 (16) /* SET_BLOCKLEN */
#define CMD17 (17) /* READ_SINGLE_BLOCK */
#define CMD18 (18) /* READ_MULTIPLE_BLOCK */
#define CMD19 (19)
#define CMD20 (20)
#define CMD23 (23)
#define CMD24 (24)
#define CMD25 (25)
#define CMD27 (27)
#define CMD28 (28)
#define CMD29 (29)
#define CMD30 (30)
#define CMD32 (32)
#define CMD33 (33)
#define CMD38 (38)
#define CMD42 (42)
#define CMD55 (55) /* APP_CMD */
#define CMD56 (56)
#define ACMD6 (0x80+6) /* define the data bus width */
#define ACMD41 (0x80+41) /* SEND_OP_COND (ACMD) */
UINT modulus = count/50;
// Capability bits
#define SDC_CAPABILITY_SD_4BIT 0x0001
#define SDC_CAPABILITY_SD_RESET 0x0002
#define SDC_CAPABILITY_ADDR 0xff00
// Control bits
#define SDC_CONTROL_SD_4BIT 0x0001
#define SDC_CONTROL_SD_RESET 0x0002
// Card detect bits
#define SDC_CARD_INSERT_INT_EN 0x0001
#define SDC_CARD_INSERT_INT_REQ 0x0002
#define SDC_CARD_REMOVE_INT_EN 0x0004
#define SDC_CARD_REMOVE_INT_REQ 0x0008
// Command status bits
#define SDC_CMD_INT_STATUS_CC 0x0001 // Command complete
#define SDC_CMD_INT_STATUS_EI 0x0002 // Any error
#define SDC_CMD_INT_STATUS_CTE 0x0004 // Timeout
#define SDC_CMD_INT_STATUS_CCRC 0x0008 // CRC error
#define SDC_CMD_INT_STATUS_CIE 0x0010 // Command code check error
// Data status bits
#define SDC_DAT_INT_STATUS_TRS 0x0001 // Transfer complete
#define SDC_DAT_INT_STATUS_ERR 0x0002 // Any error
#define SDC_DAT_INT_STATUS_CTE 0x0004 // Timeout
#define SDC_DAT_INT_STATUS_CRC 0x0008 // CRC error
#define SDC_DAT_INT_STATUS_CFE 0x0010 // Data FIFO underrun or overrun
#define ERR_EOF 30
#define ERR_NOT_ELF 31
#define ERR_ELF_BITS 32
#define ERR_ELF_ENDIANNESS 33
#define ERR_CMD_CRC 34
#define ERR_CMD_CHECK 35
#define ERR_DATA_CRC 36
#define ERR_DATA_FIFO 37
#define ERR_BUF_ALIGNMENT 38
#define FR_DISK_ERR 39
#define FR_TIMEOUT 40
struct sdc_regs {
volatile uint32_t argument;
volatile uint32_t command;
volatile uint32_t response1;
volatile uint32_t response2;
volatile uint32_t response3;
volatile uint32_t response4;
volatile uint32_t data_timeout;
volatile uint32_t control;
volatile uint32_t cmd_timeout;
volatile uint32_t clock_divider;
volatile uint32_t software_reset;
volatile uint32_t power_control;
volatile uint32_t capability;
volatile uint32_t cmd_int_status;
volatile uint32_t cmd_int_enable;
volatile uint32_t dat_int_status;
volatile uint32_t dat_int_enable;
volatile uint32_t block_size;
volatile uint32_t block_count;
volatile uint32_t card_detect;
volatile uint32_t res_50;
volatile uint32_t res_54;
volatile uint32_t res_58;
volatile uint32_t res_5c;
volatile uint64_t dma_addres;
};
#define MAX_BLOCK_CNT 0x1000
#define SDC 0x00013000;
// static struct sdc_regs * const regs __attribute__((section(".rodata"))) = (struct sdc_regs *)0x00013000;
// static int errno __attribute__((section(".bss")));
// static DSTATUS drv_status __attribute__((section(".bss")));
// static BYTE card_type __attribute__((section(".bss")));
// static uint32_t response[4] __attribute__((section(".bss")));
// static int alt_mem __attribute__((section(".bss")));
/*static const char * errno_to_str(void) {
switch (errno) {
case ERR_EOF: return "Unexpected EOF";
case ERR_NOT_ELF: return "Not an ELF file";
case ERR_ELF_BITS: return "Wrong ELF word size";
case ERR_ELF_ENDIANNESS: return "Wrong ELF endianness";
case ERR_CMD_CRC: return "Command CRC error";
case ERR_CMD_CHECK: return "Command code check error";
case ERR_DATA_CRC: return "Data CRC error";
case ERR_DATA_FIFO: return "Data FIFO error";
case ERR_BUF_ALIGNMENT: return "Bad buffer alignment";
case FR_DISK_ERR: return "Disk error";
case FR_TIMEOUT: return "Timeout";
}
return "Unknown error code";
}*/
static void usleep(unsigned us) {
uintptr_t cycles0;
uintptr_t cycles1;
asm volatile ("csrr %0, 0xB00" : "=r" (cycles0));
for (;;) {
asm volatile ("csrr %0, 0xB00" : "=r" (cycles1));
if (cycles1 - cycles0 >= us * 100) break;
}
}
static int sdc_cmd_finish(unsigned cmd, uint32_t * response) {
struct sdc_regs * regs = (struct sdc_regs *)SDC;
uint8_t crc = 0;
crc = crc7(crc, 0x40 | SD_CMD_READ_BLOCK_MULTIPLE);
crc = crc7(crc, (sector >> 24) & 0xff);
crc = crc7(crc, (sector >> 16) & 0xff);
crc = crc7(crc, (sector >> 8) & 0xff);
crc = crc7(crc, sector & 0xff);
crc = crc | 1;
while (1) {
unsigned status = regs->cmd_int_status;
if (status) {
// clear interrupts
regs->cmd_int_status = 0;
while (regs->software_reset != 0) {}
if (status == SDC_CMD_INT_STATUS_CC) {
// get response
response[0] = regs->response1;
response[1] = regs->response2;
response[2] = regs->response3;
response[3] = regs->response4;
return 0;
}
/* errno = FR_DISK_ERR;
if (status & SDC_CMD_INT_STATUS_CTE) errno = FR_TIMEOUT;
if (status & SDC_CMD_INT_STATUS_CCRC) errno = ERR_CMD_CRC;
if (status & SDC_CMD_INT_STATUS_CIE) errno = ERR_CMD_CHECK;*/
break;
}
}
return -1;
}
if ((r = sd_cmd(18, sector & 0xffffffff, crc) & 0xff) != 0x00) {
print_uart("disk_read: CMD18 failed. r = 0x");
print_uart_byte(r);
print_uart("\r\n");
fail();
// return -1;
}
static int sdc_data_finish(void) {
int status;
struct sdc_regs * regs = (struct sdc_regs *)SDC;
print_uart("\r Blocks loaded: ");
print_uart("0");
print_uart("/");
print_uart_dec(count);
// write_reg(SPI_CSMODE, SIFIVE_SPI_CSMODE_MODE_HOLD);
// Begin reading blocks
for (i = 0; i < count; i++) {
uint16_t crc, crc_exp;
uint64_t n = 0;
// Wait for data token
while((r = spi_dummy()) != SD_DATA_TOKEN);
// println_with_byte("Received data token: 0x", r & 0xff);
// println_with_dec("Block ", i);
// Read block into memory.
/* for (int j = 0; j < 64; j++) { */
/* *buf = sd_read64(&crc); */
/* println_with_addr("0x", *buf); */
/* buf = buf + 64; */
/* } */
crc = 0;
n = 512;
do {
uint8_t x = spi_dummy();
*p++ = x;
crc = crc16(crc, x);
} while (--n > 0);
while ((status = regs->dat_int_status) == 0) {}
regs->dat_int_status = 0;
while (regs->software_reset != 0) {}
// Read CRC16 and check
crc_exp = ((uint16_t)spi_dummy() << 8);
crc_exp |= spi_dummy();
if (status == SDC_DAT_INT_STATUS_TRS) return 0;
/* errno = FR_DISK_ERR;
if (status & SDC_DAT_INT_STATUS_CTE) errno = FR_TIMEOUT;
if (status & SDC_DAT_INT_STATUS_CRC) errno = ERR_DATA_CRC;
if (status & SDC_DAT_INT_STATUS_CFE) errno = ERR_DATA_FIFO;*/
return -1;
}
static int send_data_cmd(unsigned cmd, unsigned arg, void * buf, unsigned blocks, uint32_t * response) {
struct sdc_regs * regs = (struct sdc_regs *)SDC;
unsigned command = (cmd & 0x3f) << 8;
switch (cmd) {
case CMD0:
case CMD4:
case CMD15:
// No responce
break;
case CMD11:
case CMD13:
case CMD16:
case CMD17:
case CMD18:
case CMD19:
case CMD23:
case CMD24:
case CMD25:
case CMD27:
case CMD30:
case CMD32:
case CMD33:
case CMD42:
case CMD55:
case CMD56:
case ACMD6:
// R1
command |= 1; // 48 bits
command |= 1 << 3; // resp CRC
command |= 1 << 4; // resp OPCODE
break;
case CMD7:
case CMD12:
case CMD20:
case CMD28:
case CMD29:
case CMD38:
// R1b
command |= 1; // 48 bits
command |= 1 << 2; // busy
command |= 1 << 3; // resp CRC
command |= 1 << 4; // resp OPCODE
break;
case CMD2:
case CMD9:
case CMD10:
// R2
command |= 2; // 136 bits
command |= 1 << 3; // resp CRC
break;
case ACMD41:
// R3
command |= 1; // 48 bits
break;
case CMD3:
// R6
command |= 1; // 48 bits
command |= 1 << 2; // busy
command |= 1 << 3; // resp CRC
command |= 1 << 4; // resp OPCODE
break;
case CMD8:
// R7
command |= 1; // 48 bits
command |= 1 << 3; // resp CRC
command |= 1 << 4; // resp OPCODE
break;
if (crc != crc_exp) {
print_uart("Stinking CRC16 didn't match on block read.\r\n");
print_uart_int(i);
print_uart("\r\n");
//return -1;
fail();
}
if (blocks) {
command |= 1 << 5;
if ((intptr_t)buf & 3) {
// errno = ERR_BUF_ALIGNMENT;
return -1;
}
regs->dma_addres = (uint64_t)(intptr_t)buf;
regs->block_size = 511;
regs->block_count = blocks - 1;
regs->data_timeout = 0x1FFFFFF;
if ( (i % modulus) == 0 ) {
print_uart("\r Blocks loaded: ");
print_uart_dec(i);
print_uart("/");
print_uart_dec(count);
}
regs->command = command;
regs->cmd_timeout = 0xFFFFF;
regs->argument = arg;
}
if (sdc_cmd_finish(cmd, response) < 0) return -1;
if (blocks) return sdc_data_finish();
sd_cmd(SD_CMD_STOP_TRANSMISSION, 0, 0x01);
return 0;
}
#define send_cmd(cmd, arg, response) send_data_cmd(cmd, arg, NULL, 0, response)
static BYTE ini_sd(void) {
struct sdc_regs * regs = (struct sdc_regs *)SDC;
unsigned rca;
BYTE card_type;
uint32_t response[4];
/* Reset controller */
regs->software_reset = 1;
while ((regs->software_reset & 1) == 0) {}
// This clock divider is meant to initialize the card at
// 400kHz
// 22MHz/400kHz = 55 (base 10) = 0x37 - 0x01 = 0x36
regs->clock_divider = 0x36;
regs->software_reset = 0;
while (regs->software_reset) {}
usleep(5000);
card_type = 0;
// drv_status = STA_NOINIT;
if (regs->capability & SDC_CAPABILITY_SD_RESET) {
/* Power cycle SD card */
regs->control |= SDC_CONTROL_SD_RESET;
usleep(1000000);
regs->control &= ~SDC_CONTROL_SD_RESET;
usleep(100000);
}
/* Enter Idle state */
send_cmd(CMD0, 0, response);
card_type = CT_SD1;
if (send_cmd(CMD8, 0x1AA, response) == 0) {
if ((response[0] & 0xfff) != 0x1AA) {
// errno = ERR_CMD_CHECK;
return -1;
}
card_type = CT_SD2;
}
/* Wait for leaving idle state (ACMD41 with HCS bit) */
while (1) {
/* ACMD41, Set Operating Conditions: Host High Capacity & 3.3V */
if (send_cmd(CMD55, 0, response) < 0 || send_cmd(ACMD41, 0x40300000, response) < 0) return -1;
if (response[0] & (1 << 31)) {
if (response[0] & (1 << 30)) card_type |= CT_BLOCK;
break;
}
}
/* Enter Identification state */
if (send_cmd(CMD2, 0, response) < 0) return -1;
/* Get RCA (Relative Card Address) */
rca = 0x1234;
if (send_cmd(CMD3, rca << 16, response) < 0) return -1;
rca = response[0] >> 16;
/* Select card */
if (send_cmd(CMD7, rca << 16, response) < 0) return -1;
/* Clock 25MHz */
// 22Mhz/2 = 11Mhz
regs->clock_divider = 1;
usleep(10000);
/* Bus width 1-bit */
regs->control = 0;
if (send_cmd(CMD55, rca << 16, response) < 0 || send_cmd(ACMD6, 0, response) < 0) return -1;
/* Set R/W block length to 512 */
if (send_cmd(CMD16, 512, response) < 0) return -1;
// drv_status &= ~STA_NOINIT;
return card_type;
}
int disk_read(BYTE * buf, LBA_t sector, UINT count, BYTE card_type) {
/* This is not needed. This has everything to do with the FAT
filesystem stuff that I'm not including. All I need to do is
initialize the SD card and read from it. Anything in here that is
checking for potential errors, I'm going to have to temporarily
do without.
*/
// if (!count) return RES_PARERR;
/* if (drv_status & STA_NOINIT) return RES_NOTRDY; */
uint32_t response[4];
struct sdc_regs * regs = (struct sdc_regs *)SDC;
/* Convert LBA to byte address if needed */
if (!(card_type & CT_BLOCK)) sector *= 512;
while (count > 0) {
UINT bcnt = count > MAX_BLOCK_CNT ? MAX_BLOCK_CNT : count;
unsigned bytes = bcnt * 512;
if (send_data_cmd(bcnt == 1 ? CMD17 : CMD18, sector, buf, bcnt, response) < 0) return 1;
if (bcnt > 1 && send_cmd(CMD12, 0, response) < 0) return 1;
sector += (card_type & CT_BLOCK) ? bcnt : bytes;
count -= bcnt;
buf += bytes;
}
return 0;;
}
void copyFlash(QWORD address, QWORD * Dst, DWORD numBlocks) {
BYTE card_type;
int ret = 0;
card_type = ini_sd();
// BYTE * buf = (BYTE *)Dst;
// if (disk_read(buf, (LBA_t)address, (UINT)numBlocks, card_type) < 0) /* UART Print function?*/;
ret = gpt_load_partitions(card_type);
}
/*
int main() {
ini_sd();
print_uart("\r Blocks loaded: ");
print_uart_dec(count);
print_uart("/");
print_uart_dec(count);
// write_reg(SPI_CSMODE, SIFIVE_SPI_CSMODE_MODE_AUTO);
//spi_txrx(0xff);
print_uart("\r\n");
return 0;
}
*/
// copyFlash: --------------------------------------------------------
// A lot happens in this function:
// * The Wally banner is printed
// * The peripherals are initialized
void copyFlash(QWORD address, QWORD * Dst, DWORD numBlocks) {
int ret = 0;
// Initialize UART for messages
init_uart(20000000, 115200);
// Print the wally banner
print_uart(BANNER);
/* print_uart("System clock speed: "); */
/* print_uart_dec(SYSTEMCLOCK); */
/* print_uart("\r\n"); */
// Intialize the SD card
init_sd(SYSTEMCLOCK, 5000000);
ret = gpt_load_partitions();
}

View File

@ -1,3 +1,32 @@
///////////////////////////////////////////////////////////////////////
// boot.h
//
// Written: Jaocb Pease jacob.pease@okstate.edu 7/22/2024
//
// Purpose: Header for boot.c, main bootloader entry point
//
//
//
// 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.
///////////////////////////////////////////////////////////////////////
#ifndef WALLYBOOT
#define WALLYBOOT 10000
@ -19,8 +48,20 @@ typedef QWORD LBA_t;
#define OPENSBI_ADDRESS 0x80000000 // FW_TEXT_START
#define KERNEL_ADDRESS 0x80200000 // FW_JUMP_ADDR
#define BANNER " █▀█ █▀█ █▀█ █▀▀ █ █\r\n" \
" █ █ █ █▄▀ █▄▄ ▄▄▄ █ █\r\n" \
" █▄█ █▄█ █ █ █▄▄ ▀▄▀\r\n" \
" ____ ____ ____ ___ ___ ____ ___\r\n" \
" \\ \\ / / / \\ | | | | \\ \\ / /\r\n" \
" \\ \\ __ / / / \\ | | | | \\ \\/ /\r\n" \
" \\ \\/ \\/ / / /\\ \\ | | | | \\ /\r\n" \
" \\ / / ____ \\ | |___ | |___ | |\r\n" \
" \\___/\\___/ /___/ \\___\\|_______||_______| |___|\r\n\r\n"
// Export disk_read
int disk_read(BYTE * buf, LBA_t sector, UINT count, BYTE card_type);
int disk_read(BYTE * buf, LBA_t sector, UINT count);
#define SYSTEMCLOCK 20000000
#endif // WALLYBOOT

49
fpga/zsbl/fail.c Normal file
View File

@ -0,0 +1,49 @@
///////////////////////////////////////////////////////////////////////
// fail.c
//
// Written: Jaocb Pease jacob.pease@okstate.edu 7/22/2024
//
// Purpose: Prints information on the uart when a fatal bug is
// encountered. Will expand this later.
//
//
//
// 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 "fail.h"
#include "uart.h"
#include "riscv.h"
#include "time.h"
void fail() {
// Get address that led to failure
register uint64_t addr;
asm volatile ("mv %0, ra" : "=r"(addr) : : "memory");
// Print message
print_time();
println_with_addr("Failed at: 0x", addr);
// Loop forever
while(1) {
}
}

33
fpga/zsbl/fail.h Normal file
View File

@ -0,0 +1,33 @@
///////////////////////////////////////////////////////////////////////
// fail.h
//
// Written: Jaocb Pease jacob.pease@okstate.edu 7/22/2024
//
// Purpose: Function prototype for fail,
//
//
//
// 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
#include <stdint.h>
void fail();

View File

@ -1,19 +1,38 @@
///////////////////////////////////////////////////////////////////////
// gpt.c
//
// Written: Jaocb Pease jacob.pease@okstate.edu 7/22/2024
//
// Purpose: Code to read GPT Partitions off of an SD card.
//
//
//
// 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 "gpt.h"
#include "boot.h"
#include "uart.h"
#include <stddef.h>
/* PSUEDOCODE
Need to load GPT LBA 1 and read through the partition entries.
I need to find each of the relevant partition entries, possibly
by their partition names.
*/
int gpt_load_partitions(BYTE card_type) {
// In this version of the GPT partition code
// I'm going to assume that the SD card is already initialized.
int gpt_load_partitions() {
// size_t block_size = 512/8;
// long int lba1_buf[block_size];
@ -21,26 +40,51 @@ int gpt_load_partitions(BYTE card_type) {
int ret = 0;
//ret = disk_read(/* BYTE * buf, LBA_t sector, UINT count, BYTE card_type */);
ret = disk_read(lba1_buf, 1, 1, card_type);
/* Possible error handling with UART message
if ( ret != 0 ) {
}*/
print_time();
println("Getting GPT information.");
ret = disk_read(lba1_buf, 1, 1);
gpt_pth_t *lba1 = (gpt_pth_t *)lba1_buf;
print_time();
println("Getting partition entries.");
BYTE lba2_buf[512];
ret = disk_read(lba2_buf, (LBA_t)lba1->partition_entries_lba, 1, card_type);
ret = disk_read(lba2_buf, (LBA_t)lba1->partition_entries_lba, 1);
// Load parition entries for the relevant boot partitions.
partition_entries_t *fdt = (partition_entries_t *)(lba2_buf);
partition_entries_t *opensbi = (partition_entries_t *)(lba2_buf + 128);
partition_entries_t *kernel = (partition_entries_t *)(lba2_buf + 256);
ret = disk_read((BYTE *)FDT_ADDRESS, fdt->first_lba, fdt->last_lba - fdt->first_lba + 1, card_type);
ret = disk_read((BYTE *)OPENSBI_ADDRESS, opensbi->first_lba, opensbi->last_lba - opensbi->first_lba + 1, card_type);
ret = disk_read((BYTE *)KERNEL_ADDRESS, kernel->first_lba,kernel->last_lba - kernel->first_lba + 1, card_type);
// Load device tree
print_time();
println_with_int("Loading device tree at: 0x", FDT_ADDRESS);
ret = disk_read((BYTE *)FDT_ADDRESS, fdt->first_lba, fdt->last_lba - fdt->first_lba + 1);
if (ret < 0) {
print_uart("Failed to load device tree!\r\n");
return -1;
}
// Load OpenSBI
print_time();
println_with_int("Loading OpenSBI at: 0x", OPENSBI_ADDRESS);
ret = disk_read((BYTE *)OPENSBI_ADDRESS, opensbi->first_lba, opensbi->last_lba - opensbi->first_lba + 1);
if (ret < 0) {
print_uart("Failed to load OpenSBI!\r\n");
return -1;
}
// Load Linux
print_time();
println_with_int("Loading Linux Kernel at: 0x", KERNEL_ADDRESS);
ret = disk_read((BYTE *)KERNEL_ADDRESS, kernel->first_lba,kernel->last_lba - kernel->first_lba + 1);
if (ret < 0) {
print_uart("Failed to load Linux!\r\n");
return -1;
}
print_time();
println("Done! Flashing LEDs and jumping to OpenSBI...");
return 0;
}

View File

@ -1,3 +1,32 @@
///////////////////////////////////////////////////////////////////////
// gpt.h
//
// Written: Jaocb Pease jacob.pease@okstate.edu 7/22/2024
//
// Purpose: Header for gpt.c, contains gpt structs
//
//
//
// 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
#include <stdint.h>
@ -37,4 +66,4 @@ typedef struct partition_entries
} partition_entries_t;
// Find boot partition and load it to the destination
int gpt_load_partitions(BYTE card_type);
int gpt_load_partitions();

58
fpga/zsbl/riscv.S Normal file
View File

@ -0,0 +1,58 @@
///////////////////////////////////////////////////////////////////////
// riscv.S
//
// Written: Jaocb Pease jacob.pease@okstate.edu 7/22/2024
//
// Purpose: Basic utility functions for reading registers
//
//
//
// 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.
///////////////////////////////////////////////////////////////////////
.section .text
.globl read_mcycle
.type read_mcycle, @function
read_mcycle:
csrr a0, mcycle
ret
.section .text
.globl get_ra
.type get_ra, @function
get_ra:
mv a0, ra
ret
.section .text
.globl set_status_fs
.type set_status_fs, @function
set_status_fs:
lui t1, 0x6
csrs mstatus, t1
ret
.section .text
.globl clear_status_fs
.type clear_status_fs, @function
clear_status_fs:
lui t1, 0x6
csrc mstatus, t1
ret

36
fpga/zsbl/riscv.h Normal file
View File

@ -0,0 +1,36 @@
///////////////////////////////////////////////////////////////////////
// riscv.h
//
// Written: Jaocb Pease jacob.pease@okstate.edu 7/22/2024
//
// Purpose: Function prototypes for riscv utility functions
//
//
//
// 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
#include <stdint.h>
uint64_t read_mcycle();
uint64_t get_ra();
void set_status_fs();
void clear_status_fs();

255
fpga/zsbl/sd.c Normal file
View File

@ -0,0 +1,255 @@
///////////////////////////////////////////////////////////////////////
// sd.c
//
// Written: Jaocb Pease jacob.pease@okstate.edu 7/22/2024
//
// Purpose: SD Card protocol functions
//
//
//
// 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 "sd.h"
#include "spi.h"
#include "uart.h"
#include "fail.h"
#include "time.h"
// Parallel byte update CRC7-CCITT algorithm.
// The result is the CRC7 result, left shifted over by 1
// which is perfect, since we append a 1 at the end anyway
uint8_t crc7(uint8_t prev, uint8_t in) {
// CRC polynomial 0x89
uint8_t remainder = prev ^ in;
remainder ^= (remainder >> 4) ^ (remainder >> 7);
remainder = (remainder << 1) ^ (remainder << 4);
return remainder & 0xff;
}
// Need to check this. This could be wrong as well.
uint16_t crc16(uint16_t crc, uint8_t data) {
// CRC polynomial 0x11021
crc = (uint8_t)(crc >> 8) | (crc << 8);
crc ^= data;
crc ^= (uint8_t)(crc >> 4) & 0xf;
crc ^= crc << 12;
crc ^= (crc & 0xff) << 5;
return crc;
}
// sd_cmd ------------------------------------------------------------
// Sends SD card command using SPI mode.
// This function:
// * Chooses the response length based on the input command
// * Makes use of SPI's full duplex. For every byte sent,
// a byte is received. Thus for every byte sent as part of
// a command, a useless byte must be read from the receive
// FIFO.
// * Takes advantage of the Sifive SPI peripheral spec's
// watermark and interrupt features to determine when a
// transfer is complete. This should save on cycles since
// no arbitrary delays need to be added.
uint64_t sd_cmd(uint8_t cmd, uint32_t arg, uint8_t crc) {
uint8_t response_len;
uint8_t i;
uint8_t shiftAmnt;
uint64_t r;
uint8_t rbyte;
// Initialize the response with 0's.
r = 0;
// Choose response length based on cmd input.
// Most commands return an R1 format response.
switch (cmd) {
case 8:
response_len = R7_RESPONSE;
break;
case 12:
response_len = R1B_RESPONSE;
break;
default:
response_len = R1_RESPONSE;
break;
}
// Make interrupt pending after response fifo receives the correct
// response length. Probably unecessary so let's wait and see what
// happens.
// write_reg(SPI_RXMARK, response_len);
// Chip select must remain asserted during transaction
if (cmd != SD_CMD_STOP_TRANSMISSION) {
write_reg(SPI_CSMODE, SIFIVE_SPI_CSMODE_MODE_HOLD);
}
// Write all 7 bytes into transfer fifo
// spi_sendbyte(0xff);
spi_dummy();
spi_sendbyte(0x40 | cmd);
spi_sendbyte(arg >> 24);
spi_sendbyte(arg >> 16);
spi_sendbyte(arg >> 8);
spi_sendbyte(arg);
spi_sendbyte(crc);
// Wait for command to send
// The Transfer IP bit should go high when the txFIFO is empty
// while(!(read_reg(SPI_IP) & 1)) {}
waittx();
// Read the dummy rxFIFO entries to move the head back to the tail
for (i = 0; i < 7; i++) {
spi_readbyte();
}
// Send "dummy signals". Since SPI is duplex,
// useless bytes must be transferred
/* for (i = 0; i < response_len; i++) { */
/* spi_sendbyte(0xFF); */
/* } */
/* // Wait for transfer fifo again */
/* waittx(); */
// Wait for actual response from SD card
// All responses start with a 0. Output of SDCIn is high, unless
// a message is being transferred.
do {
rbyte = spi_dummy();
} while ( (rbyte & 0x80) != 0 );
// Note about the compiler. In order to compile as sll instead of
// sllw, the number to shift has to be a 64 bit number.
r = ((uint64_t)rbyte) << ((response_len - 1)*8);
// Read rxfifo response
for (i = 1; i < response_len; i++) {
rbyte = spi_dummy();
r = r | (((uint64_t)rbyte) << ((response_len - 1 - i)*8));
}
if (cmd != 18) {
write_reg(SPI_CSMODE, SIFIVE_SPI_CSMODE_MODE_AUTO);
} else {
spi_dummy();
}
return r;
} // sd_cmd
uint64_t sd_read64(uint16_t * crc) {
uint64_t r;
uint8_t rbyte;
int i;
/* for (i = 0; i < 8; i++) { */
/* spi_sendbyte(0xFF); */
/* } */
/* waittx(); */
for (i = 0; i < 8; i++) {
rbyte = spi_dummy();
*crc = crc16(*crc, rbyte);
r = r | ((uint64_t)(rbyte) << ((8 - 1 - i)*8));
}
return r;
}
// Utility defines for CMD0, CMD8, CMD55, and ACMD41
#define CMD0() sd_cmd( 0, 0x00000000, 0x95) // Reset SD card into IDLE state
#define CMD8() sd_cmd( 8, 0x000001aa, 0x87) //
#define CMD55() sd_cmd(55, 0x00000000, 0x65) //
#define ACMD41() sd_cmd(41, 0x40000000, 0x77) //
// init_sd: ----------------------------------------------------------
// This first initializes the SPI peripheral then initializes the SD
// card itself. We use the uart to display anything that goes wrong.
int init_sd(uint32_t freq, uint32_t sdclk){
print_time();
println("Initializing SPI Controller.");
spi_init();
uint64_t r;
uint32_t newClockDiv;
int n;
print_time();
println("Initializing SD Card in SPI mode.");
// This is necessary. This is the card's pre-init state initialization.
write_reg(SPI_CSMODE, SIFIVE_SPI_CSMODE_MODE_OFF);
for (int i = 0; i < 10; i++) {
spi_txrx(0xff);
}
write_reg(SPI_CSMODE, SIFIVE_SPI_CSMODE_MODE_AUTO);
// CMD0 --------------------------------------------------------------
// Reset SD Card command
// Initializes SD card into SPI mode if CS is asserted '0'
// We expect to get the R1 response 0x01 which means that the
// card has been put into the idle state.
print_time();
print_uart("CMD0: ");
n = 0;
do {
r = CMD0();
n++;
if (n == 1000) {
fail();
}
} while ( r != 0x01 );
println_with_r1("Success, r = 0x", r & 0xff);
// CMD8 -------------------------------------------------------------
//
print_time();
print_uart("CMD8: ");
r = CMD8();
if ((r & 0x000000ff0000ffff) != 0x01000001aa) {
println_with_r7("Failed, 0x", r);
fail();
}
println_with_r7("Success, 0x", r);
// ACMD41 -----------------------------------------------------------
print_time();
print_uart("ACMD41: ");
n = 0;
do {
CMD55();
r = ACMD41();
n++;
if (n == 1000) {
fail();
}
} while (r == 0x1);
println_with_r1("Success, r = 0x", r & 0xff);
print_time();
println_with_dec("New clock frequency: ", (uint64_t)sdclk);
spi_set_clock(freq, sdclk);
print_time();
println("SD card is initialized.");
}

49
fpga/zsbl/sd.h Normal file
View File

@ -0,0 +1,49 @@
///////////////////////////////////////////////////////////////////////
// sd.h
//
// Written: Jaocb Pease jacob.pease@okstate.edu 7/22/2024
//
// Purpose: Header file for SD card protocol functions. Defines some
// useful macros.
//
//
//
// 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
#include <stdint.h>
// Command names
#define SD_CMD_STOP_TRANSMISSION 12
#define SD_CMD_READ_BLOCK_MULTIPLE 18
#define SD_DATA_TOKEN 0xfe
// Response lengths in bytes
#define R1_RESPONSE 1
#define R7_RESPONSE 5
#define R1B_RESPONSE 2
uint8_t crc7(uint8_t prev, uint8_t in);
uint16_t crc16(uint16_t crc, uint8_t data);
uint64_t sd_cmd(uint8_t cmd, uint32_t arg, uint8_t crc);
uint64_t sd_read64(uint16_t * crc);
int init_sd(uint32_t freq, uint32_t sdclk);

91
fpga/zsbl/spi.c Normal file
View File

@ -0,0 +1,91 @@
///////////////////////////////////////////////////////////////////////
// spi.c
//
// Written: Jaocb Pease jacob.pease@okstate.edu 7/22/2024
//
// Purpose: SPI Controller API for bootloader
//
//
//
// 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"
uint8_t spi_txrx(uint8_t byte) {
spi_sendbyte(byte);
waittx();
return spi_readbyte();
}
uint8_t spi_dummy() {
return spi_txrx(0xff);
}
uint64_t spi_read64() {
uint64_t r;
uint8_t rbyte;
int i;
for (i = 0; i < 8; i++) {
spi_sendbyte(0xFF);
}
waittx();
for (i = 0; i < 8; i++) {
rbyte = spi_readbyte();
r = r | (rbyte << ((8 - 1 - i)*8));
}
return r;
}
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);
}

87
fpga/zsbl/spi.h Normal file
View File

@ -0,0 +1,87 @@
#pragma once
#ifndef SPI_HEADER
#define SPI_HEADER
#include <stdint.h>
#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

48
fpga/zsbl/splitfile.sh Executable file
View File

@ -0,0 +1,48 @@
#######################################################################
# splitfile.sh
#
# Written: Jaocb Pease jacob.pease@okstate.edu 7/22/2024
#
# Purpose: Used to split boot.mem into two sections for FPGA
#
#
#
# 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.
######################################################################
# Acquired from here.
# https:##stackoverflow.com#questions#3066948#how-to-file-split-at-a-line-number
file_name=$1
# set first K lines:
K=512
# line count (N):
N=$(wc -l < $file_name)
# length of the bottom file:
L=$(( $N - $K ))
# create the top of file:
head -n $K $file_name > boot.mem
# create bottom of file:
tail -n $L $file_name > data.mem

49
fpga/zsbl/time.c Normal file
View File

@ -0,0 +1,49 @@
///////////////////////////////////////////////////////////////////////
// time.c
//
// Written: Jaocb Pease jacob.pease@okstate.edu 7/22/2024
//
// Purpose: Gets and prints the current time.
//
//
//
// 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 "time.h"
#include "boot.h"
#include "riscv.h"
#include "uart.h"
float getTime() {
set_status_fs();
float numCycles = (float)read_mcycle();
float ret = numCycles/SYSTEMCLOCK;
// clear_status_fs();
return ret;
}
void print_time() {
print_uart("[");
set_status_fs();
print_uart_float(getTime(),5);
clear_status_fs();
print_uart("] ");
}

34
fpga/zsbl/time.h Normal file
View File

@ -0,0 +1,34 @@
///////////////////////////////////////////////////////////////////////
// spi.c
//
// Written: Jaocb Pease jacob.pease@okstate.edu 7/22/2024
//
// Purpose: Time function prototypes
//
//
//
// 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
#include <stdint.h>
float getTime();
void print_time();

193
fpga/zsbl/uart.c Normal file
View File

@ -0,0 +1,193 @@
///////////////////////////////////////////////////////////////////////
// uart.c
//
// Written: Jaocb Pease jacob.pease@okstate.edu 7/22/2024
//
// Purpose: Uart printing functions, as well as functions for printing
// hex, decimal, and floating point numbers.
//
//
//
// 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 "uart.h"
void write_reg_u8(uintptr_t addr, uint8_t value)
{
volatile uint8_t *loc_addr = (volatile uint8_t *)addr;
*loc_addr = value;
}
uint8_t read_reg_u8(uintptr_t addr)
{
return *(volatile uint8_t *)addr;
}
int is_transmit_empty()
{
return read_reg_u8(UART_LSR) & 0x20;
}
int is_receive_empty()
{
return !(read_reg_u8(UART_LSR) & 0x1);
}
void write_serial(char a)
{
while (is_transmit_empty() == 0) {};
write_reg_u8(UART_THR, a);
}
void init_uart(uint32_t freq, uint32_t baud)
{
// Alternative divisor calculation. From OpenSBI code.
// Reduces error for every possible frequency.
uint32_t divisor = (freq + 8 * baud) /(baud << 4);
write_reg_u8(UART_IER, 0x00); // Disable all interrupts
write_reg_u8(UART_LCR, 0x80); // Enable DLAB (set baud rate divisor)
write_reg_u8(UART_DLL, divisor & 0xFF); // divisor (lo byte)
write_reg_u8(UART_DLM, (divisor >> 8) & 0xFF); // divisor (hi byte)
write_reg_u8(UART_LCR, 0x03); // 8 bits, no parity, one stop bit
write_reg_u8(UART_FCR, 0xC7); // Enable FIFO, clear them, with 14-byte threshold
}
void print_uart(const char *str)
{
const char *cur = &str[0];
while (*cur != '\0') {
write_serial((uint8_t)*cur);
++cur;
}
}
uint8_t bin_to_hex_table[16] = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
void bin_to_hex(uint8_t inp, uint8_t res[2])
{
res[1] = bin_to_hex_table[inp & 0xf];
res[0] = bin_to_hex_table[(inp >> 4) & 0xf];
return;
}
void print_uart_hex(uint64_t addr, int n)
{
int i;
for (i = n - 1; i > -1; i--) {
uint8_t cur = (addr >> (i * 8)) & 0xff;
uint8_t hex[2];
bin_to_hex(cur, hex);
write_serial(hex[0]);
write_serial(hex[1]);
}
}
void print_uart_dec(uint64_t addr) {
// floor(log(2^64)) = 19
char str[19] = {'\0'};
uint8_t length = 1;
uint64_t cur = addr;
while (cur != 0) {
char digit = bin_to_hex_table[cur % 10];
// write_serial(digit);
str[length] = digit;
cur = cur/10;
length++;
}
for (int i = length; i > -1; i--) {
write_serial(str[i]);
}
}
// Print a floating point number on the UART
void print_uart_float(float num, int precision) {
char str[32] = {'\0'};
char digit;
uint8_t length = precision + 1;
int i;
uint64_t cur;
str[precision] = '.';
int pow = 1;
// Calculate power for precision
for (i = 0; i < precision; i++) {
pow = pow * 10;
}
cur = (uint64_t)(num * pow);
for (i = 0; i < precision; i++) {
digit = bin_to_hex_table[cur % 10];
str[i] = digit;
cur = cur / 10;
}
cur = (uint64_t)num;
do {
digit = bin_to_hex_table[cur % 10];
str[length] = digit;
cur = cur/10;
length++;
} while (cur != 0);
for (i = length; i > -1; i--) {
write_serial(str[i]);
}
}
/* void print_uart_int(uint32_t addr) */
/* { */
/* int i; */
/* for (i = 3; i > -1; i--) { */
/* uint8_t cur = (addr >> (i * 8)) & 0xff; */
/* uint8_t hex[2]; */
/* bin_to_hex(cur, hex); */
/* write_serial(hex[0]); */
/* write_serial(hex[1]); */
/* } */
/* } */
/* void print_uart_addr(uint64_t addr) */
/* { */
/* int i; */
/* for (i = 7; i > -1; i--) { */
/* uint8_t cur = (addr >> (i * 8)) & 0xff; */
/* uint8_t hex[2]; */
/* bin_to_hex(cur, hex); */
/* write_serial(hex[0]); */
/* write_serial(hex[1]); */
/* } */
/* } */
/* void print_uart_byte(uint8_t byte) */
/* { */
/* uint8_t hex[2]; */
/* bin_to_hex(byte, hex); */
/* write_serial(hex[0]); */
/* write_serial(hex[1]); */
/* } */

87
fpga/zsbl/uart.h Normal file
View File

@ -0,0 +1,87 @@
///////////////////////////////////////////////////////////////////////
// uart.h
//
// Written: Jaocb Pease jacob.pease@okstate.edu 7/22/2024
//
// Purpose: Header for the UART functions.
//
//
//
// 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
#include <stdint.h>
#include "riscv.h"
#include "time.h"
// UART register addresses
#define UART_BASE 0x10000000
#define UART_RBR UART_BASE + 0x00
#define UART_THR UART_BASE + 0x00
#define UART_IER UART_BASE + 0x01
#define UART_IIR UART_BASE + 0x02
#define UART_FCR UART_BASE + 0x02
#define UART_LCR UART_BASE + 0x03
#define UART_MCR UART_BASE + 0x04
#define UART_LSR UART_BASE + 0x05
#define UART_MSR UART_BASE + 0x06
#define UART_SCR UART_BASE + 0x07
#define UART_DLL UART_BASE + 0x00
#define UART_DLM UART_BASE + 0x01
// Primary function prototypes
void init_uart(uint32_t freq, uint32_t baud);
void write_reg_u8(uintptr_t addr, uint8_t value);
uint8_t read_reg_u8(uintptr_t addr);
int read_serial(uint8_t *res);
void print_uart(const char* str);
void print_uart_int(uint32_t addr);
void print_uart_dec(uint64_t addr);
void print_uart_addr(uint64_t addr);
void print_uart_hex(uint64_t addr, int n);
void print_uart_byte(uint8_t byte);
void print_uart_float(float num, int precision);
// void print_time();
// Print numbers in hex with specified widths
#define print_uart_int(addr) print_uart_hex(addr, 4)
#define print_uart_addr(addr) print_uart_hex(addr, 8)
#define print_uart_byte(addr) print_uart_hex(addr, 1)
#define print_r7(addr) print_uart_hex(addr, 5)
#define print_r1(addr) print_uart_byte(addr)
// Print line with numbers utility macros
#define println(msg) print_uart(msg "\r\n");
#define println_with_dec(msg, num) print_uart(msg); print_uart_dec(num); print_uart("\r\n")
#define println_with_byte(msg, num) print_uart(msg); print_uart_byte(num); print_uart("\r\n")
#define println_with_int(msg, num) print_uart(msg); print_uart_int(num); print_uart("\r\n")
#define println_with_addr(msg, num) print_uart(msg); print_uart_addr(num); print_uart("\r\n")
#define println_with_r1(msg, num) print_uart(msg); print_r1(num); print_uart("\r\n")
#define println_with_r7(msg, num) print_uart(msg); print_r7(num); print_uart("\r\n")
#define println_with_float(msg, num) print_uart(msg); set_status_fs(); print_uart_float(num,5); clear_status_fs(); print_uart("\r\n")
/* #define print_time() print_uart("["); \ */
/* set_status_fs(); \ */
/* print_uart_float(getTime(),5); \ */
/* clear_status_fs(); \ */
/* print_uart("] ") */

View File

@ -102,7 +102,7 @@ $(IMAGES)/busybox:
# Generating new Buildroot directories --------------------------------
# This directive should be run as: make install BUILDROOT=path/to/buildroot
download: $(BUILDROOT)/package/fpga-axi-sdc $(WALLYBOARD)
download: $(WALLYBOARD)
cp $(WALLYBOARD)/main.config $(BUILDROOT)/.config
# CONFIG DEPENDENCIES 2023.05.1 ---------------------------------------

View File

@ -2,7 +2,7 @@
# Automatically generated file; DO NOT EDIT.
# Linux/riscv 6.6.0 Kernel Configuration
#
CONFIG_CC_VERSION_TEXT="riscv64-buildroot-linux-gnu-gcc.br_real (Buildroot 2023.05.3-dirty) 12.3.0"
CONFIG_CC_VERSION_TEXT="riscv64-buildroot-linux-gnu-gcc.br_real (Buildroot 2023.05.3) 12.3.0"
CONFIG_CC_IS_GCC=y
CONFIG_GCC_VERSION=120300
CONFIG_CLANG_VERSION=0
@ -1042,7 +1042,7 @@ CONFIG_MMC_BLOCK_MINORS=8
#
# CONFIG_MMC_DEBUG is not set
# CONFIG_MMC_SDHCI is not set
# CONFIG_MMC_SPI is not set
CONFIG_MMC_SPI=y
# CONFIG_MMC_DW is not set
# CONFIG_MMC_USDHI6ROL0 is not set
# CONFIG_MMC_CQHCI is not set
@ -1455,7 +1455,7 @@ CONFIG_CRYPTO_HASH2=y
# CONFIG_CRYPTO_POLY1305 is not set
# CONFIG_CRYPTO_RMD160 is not set
# CONFIG_CRYPTO_SHA1 is not set
# CONFIG_CRYPTO_SHA256 is not set
CONFIG_CRYPTO_SHA256=y
# CONFIG_CRYPTO_SHA512 is not set
# CONFIG_CRYPTO_SHA3 is not set
# CONFIG_CRYPTO_SM3_GENERIC is not set
@ -1527,13 +1527,14 @@ CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y
CONFIG_CRYPTO_LIB_POLY1305_RSIZE=1
# CONFIG_CRYPTO_LIB_POLY1305 is not set
# CONFIG_CRYPTO_LIB_CHACHA20POLY1305 is not set
CONFIG_CRYPTO_LIB_SHA256=y
# end of Crypto library routines
# CONFIG_CRC_CCITT is not set
CONFIG_CRC16=y
# CONFIG_CRC_T10DIF is not set
# CONFIG_CRC64_ROCKSOFT is not set
# CONFIG_CRC_ITU_T is not set
CONFIG_CRC_ITU_T=y
CONFIG_CRC32=y
# CONFIG_CRC32_SELFTEST is not set
CONFIG_CRC32_SLICEBY8=y
@ -1542,7 +1543,7 @@ CONFIG_CRC32_SLICEBY8=y
# CONFIG_CRC32_BIT is not set
# CONFIG_CRC64 is not set
# CONFIG_CRC4 is not set
# CONFIG_CRC7 is not set
CONFIG_CRC7=y
# CONFIG_LIBCRC32C is not set
# CONFIG_CRC8 is not set
# CONFIG_RANDOM32_SELFTEST is not set
@ -1599,7 +1600,7 @@ CONFIG_PRINTK_TIME=y
# CONFIG_STACKTRACE_BUILD_ID is not set
CONFIG_CONSOLE_LOGLEVEL_DEFAULT=7
CONFIG_CONSOLE_LOGLEVEL_QUIET=4
CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4
CONFIG_MESSAGE_LOGLEVEL_DEFAULT=7
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_DYNAMIC_DEBUG is not set
# CONFIG_DYNAMIC_DEBUG_CORE is not set

View File

@ -5,11 +5,11 @@
#size-cells = <0x02>;
compatible = "wally-virt";
model = "wally-virt,qemu";
chosen {
linux,initrd-end = <0x85c43a00>;
linux,initrd-start = <0x84200000>;
bootargs = "root=/dev/vda ro console=ttyS0,115200";
bootargs = "root=/dev/vda ro console=ttyS0,115200 loglevel=7";
stdout-path = "/soc/uart@10000000";
};
@ -31,7 +31,9 @@
status = "okay";
compatible = "riscv";
riscv,isa = "rv64imafdcsu";
riscv,isa-extensions = "imafdc", "sstc", "svinval", "svnapot", "svpbmt", "zba", "zbb", "zbc", "zbs", "zicbom", "zicbop", "zicbopz", "zicntr", "zicsr", "zifencei", "zihpm";
riscv,isa-base = "rv64i";
riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "sstc", "svinval", "svnapot", "svpbmt", "zba", "zbb", "zbc", "zbs", "zicbom", "zicbop", "zicbopz", "zicntr", "zicsr", "zifencei", "zihpm";
riscv,cbom-block-size = <64>;
mmu-type = "riscv,sv48";
interrupt-controller {
@ -49,6 +51,25 @@
compatible = "simple-bus";
ranges;
refclk: refclk {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <0x1312D00>;
clock-output-names = "xtal";
};
gpio0: gpio@10060000 {
compatible = "sifive,gpio0";
interrupt-parent = <0x03>;
interrupts = <3>;
reg = <0x00 0x10060000 0x00 0x1000>;
reg-names = "control";
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
};
uart@10000000 {
interrupts = <0x0a>;
interrupt-parent = <0x03>;
@ -68,18 +89,24 @@
#address-cells = <0x00>;
};
mmc@13000 {
interrupts = <0x14>;
compatible = "riscv,axi-sd-card-1.0";
reg = <0x00 0x13000 0x00 0x7F>;
fifo-depth = <256>;
bus-width = <4>;
spi@13000 {
compatible = "sifive,spi0";
interrupt-parent = <0x03>;
clock = <0x1312D00>;
max-frequency = <0x1312D00>;
cap-sd-highspeed;
cap-mmc-highspeed;
no-sdio;
interrupts = <0x14>;
reg = <0x0 0x13000 0x0 0x1000>;
reg-names = "control";
clocks = <&refclk>;
#address-cells = <1>;
#size-cells = <0>;
mmc@0 {
compatible = "mmc-spi-slot";
reg = <0>;
spi-max-frequency = <5000000>;
voltage-ranges = <3300 3300>;
disable-wp;
// gpios = <&gpio0 6 1>;
};
};
clint@2000000 {

View File

@ -1,44 +1,121 @@
# David_Harris@hmc.edu 15 July 2024
# Simulation Makefile for CORE-V-Wally
# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
SIM = ${WALLY}/sim
all: riscoftests memfiles coveragetests deriv
# *** Build old tests/imperas-riscv-tests for now;
# Delete this part when the privileged tests transition over to tests/wally-riscv-arch-test
# DH: 2/27/22 temporarily commented out imperas-riscv-tests because license expired
#make -C ../tests/imperas-riscv-tests --jobs
#make -C ../tests/imperas-riscv-tests XLEN=64 --jobs
# Only compile Imperas tests if they are installed locally.
# They are usually a symlink to $RISCV/imperas-riscv-tests and only
# get compiled there manually during installation
#make -C ../addins/imperas-riscv-tests
#make -C ../addins/imperas-riscv-tests XLEN=64
#cd ../addins/imperas-riscv-tests; elf2hex.sh
#cd ../addins/imperas-riscv-tests; extractFunctionRadix.sh work/*/*/*.elf.objdump
# Link Linux test vectors
#cd ../tests/linux-testgen/linux-testvectors/;./tvLinker.sh
wally-riscv-arch-test: wallyriscoftests memfiles
QuestaCoverage: questa/cov/rv64gc_arch64i.ucdb
#iter-elf.bash --cover --search ../tests/coverage
vcover merge -out questa/cov/cov.ucdb questa/cov/rv64gc_arch64i.ucdb questa/cov/rv64gc*.ucdb -logfile questa/cov/log
# vcover merge -out questa/cov/cov.ucdb questa/cov/rv64gc_arch64i.ucdb questa/cov/rv64gc*.ucdb questa/cov/buildroot_buildroot.ucdb riscv.ucdb -logfile questa/cov/log
vcover report -details questa/cov/cov.ucdb > questa/cov/rv64gc_coverage_details.rpt
vcover report questa/cov/cov.ucdb -details -instance=/core/ebu. > questa/cov/rv64gc_coverage_ebu.rpt
vcover report questa/cov/cov.ucdb -details -instance=/core/priv. > questa/cov/rv64gc_coverage_priv.rpt
vcover report questa/cov/cov.ucdb -details -instance=/core/ifu. > questa/cov/rv64gc_coverage_ifu.rpt
vcover report questa/cov/cov.ucdb -details -instance=/core/lsu. > questa/cov/rv64gc_coverage_lsu.rpt
vcover report questa/cov/cov.ucdb -details -instance=/core/fpu. > questa/cov/rv64gc_coverage_fpu.rpt
vcover report questa/cov/cov.ucdb -details -instance=/core/ieu. > questa/cov/rv64gc_coverage_ieu.rpt
vcover report questa/cov/cov.ucdb -below 100 -details -instance=/core/ebu. > questa/cov/rv64gc_uncovered_ebu.rpt
vcover report questa/cov/cov.ucdb -below 100 -details -instance=/core/priv. > questa/cov/rv64gc_uncovered_priv.rpt
vcover report questa/cov/cov.ucdb -below 100 -details -instance=/core/ifu. > questa/cov/rv64gc_uncovered_ifu.rpt
vcover report questa/cov/cov.ucdb -below 100 -details -instance=/core/lsu. > questa/cov/rv64gc_uncovered_lsu.rpt
vcover report questa/cov/cov.ucdb -below 100 -details -instance=/core/fpu. > questa/cov/rv64gc_uncovered_fpu.rpt
vcover report questa/cov/cov.ucdb -below 100 -details -instance=/core/ieu. > questa/cov/rv64gc_uncovered_ieu.rpt
vcover report -hierarchical questa/cov/cov.ucdb > questa/cov/rv64gc_coverage_hierarchical.rpt
vcover report -below 100 -hierarchical questa/cov/cov.ucdb > questa/cov/rv64gc_uncovered_hierarchical.rpt
# vcover report -below 100 questa/cov/cov.ucdb > questa/cov/rv64gc_coverage.rpt
# vcover report -recursive questa/cov/cov.ucdb > questa/cov/rv64gc_recursive.rpt
vcover report -details -threshH 100 -html questa/cov/cov.ucdb
QuestaCodeCoverage: questa/ucdb/rv64gc_arch64i.ucdb
vcover merge -out questa/ucdb/cov.ucdb questa/ucdb/rv64gc_arch64i.ucdb questa/ucdb/rv64gc*.ucdb -logfile questa/cov/log
# vcover merge -out questa/ucdb/cov.ucdb questa/ucdb/rv64gc_arch64i.ucdb questa/ucdb/rv64gc*.ucdb questa/ucdb/buildroot_buildroot.ucdb riscv.ucdb -logfile questa/cov/log
vcover report -details questa/ucdb/cov.ucdb > questa/cov/rv64gc_coverage_details.rpt
vcover report questa/ucdb/cov.ucdb -details -instance=/core/ebu. > questa/cov/rv64gc_coverage_ebu.rpt
vcover report questa/ucdb/cov.ucdb -details -instance=/core/priv. > questa/cov/rv64gc_coverage_priv.rpt
vcover report questa/ucdb/cov.ucdb -details -instance=/core/ifu. > questa/cov/rv64gc_coverage_ifu.rpt
vcover report questa/ucdb/cov.ucdb -details -instance=/core/lsu. > questa/cov/rv64gc_coverage_lsu.rpt
vcover report questa/ucdb/cov.ucdb -details -instance=/core/fpu. > questa/cov/rv64gc_coverage_fpu.rpt
vcover report questa/ucdb/cov.ucdb -details -instance=/core/ieu. > questa/cov/rv64gc_coverage_ieu.rpt
vcover report questa/ucdb/cov.ucdb -below 100 -details -instance=/core/ebu. > questa/cov/rv64gc_uncovered_ebu.rpt
vcover report questa/ucdb/cov.ucdb -below 100 -details -instance=/core/priv. > questa/cov/rv64gc_uncovered_priv.rpt
vcover report questa/ucdb/cov.ucdb -below 100 -details -instance=/core/ifu. > questa/cov/rv64gc_uncovered_ifu.rpt
vcover report questa/ucdb/cov.ucdb -below 100 -details -instance=/core/lsu. > questa/cov/rv64gc_uncovered_lsu.rpt
vcover report questa/ucdb/cov.ucdb -below 100 -details -instance=/core/fpu. > questa/cov/rv64gc_uncovered_fpu.rpt
vcover report questa/ucdb/cov.ucdb -below 100 -details -instance=/core/ieu. > questa/cov/rv64gc_uncovered_ieu.rpt
vcover report -hierarchical questa/ucdb/cov.ucdb > questa/cov/rv64gc_coverage_hierarchical.rpt
vcover report -below 100 -hierarchical questa/ucdb/cov.ucdb > questa/cov/rv64gc_uncovered_hierarchical.rpt
# vcover report -below 100 questa/ucdb/cov.ucdb > questa/cov/rv64gc_coverage.rpt
# vcover report -recursive questa/ucdb/cov.ucdb > questa/cov/rv64gc_recursive.rpt
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:
touch ${SIM}/seed0.txt
echo "0" > ${SIM}/seed0.txt
# /opt/riscv/ImperasDV-OpenHW/scripts/cvw/run-elf-cov.bash --verbose --seed 0 --search ${WALLY}/tests/riscof/work/wally-riscv-arch-test/rv64i_m
# /opt/riscv/ImperasDV-OpenHW/scripts/cvw/run-elf-cov.bash --elf ${WALLY}/tests/riscof/work/riscv-arch-test/rv64i_m/I/src/add-01.S/dut/my.elf --seed ${SIM}/seed0.txt --coverdb ${SIM}/cov/rv64gc_arch64i.ucdb --verbose
# /opt/riscv/ImperasDV-OpenHW/scripts/cvw/run-elf-cov.bash --elf ${WALLY}/tests/riscof/work/riscv-arch-test/rv64i_m/I/src/add-01.S/dut/my.elf --seed ${SIM}/seed0.txt --coverdb ${SIM}/questa/riscv.ucdb --verbose
run-elf-cov.bash --elf ${WALLY}/tests/riscvdv/asm_test/riscv_arithmetic_basic_test_0.elf --seed ${SIM}/questa/seed0.txt --coverdb ${SIM}/questa/riscv.ucdb --verbose
vcover report -details -html ${SIM}/questa/riscv.ucdb
funcovreg:
#iter-elf.bash --search ${WALLY}/tests/riscof/work/wally-riscv-arch-test/rv64i_m --cover
#iter-elf.bash --search ${WALLY}/tests/riscof/work/wally-riscv-arch-test/rv64i_m/I --cover
#iter-elf.bash --search ${WALLY}/tests/riscof/work/wally-riscv-arch-test/rv64i_m/privilege --cover
#iter-elf.bash --search ${WALLY}/tests/riscof/work/wally-riscv-arch-test/rv64i_m/Q --cover
rm -f ${WALLY}/tests/riscof/work/riscv-arch-test/rv64i_m/*/src/*/dut/my.elf
iter-elf.bash --search ${WALLY}/tests/riscof/work/riscv-arch-test/rv64i_m/I --cover
vcover report -details -html ${SIM}/questa/riscv.ucdb
riscvdv:
python3 ${WALLY}/addins/riscv-dv/run.py --test ${test_name} --target rv64gc --output tests/riscvdv --iterations 1 -si questa --iss spike --verbose --cov --seed 0 --steps gen,gcc_compile >> ${SIM}/questa/fcov_logs/${test_name}.log 2>&1
# python3 ${WALLY}/addins/riscv-dv/run.py --test ${test_name} --target rv64gc --output tests/riscvdv --iterations 1 -si questa --iss spike --verbose --cov --seed 0 --steps gcc_compile >> ${SIM}/questa/fcov_logs/${test_name}.log 2>&1
# python3 ${WALLY}/addins/riscv-dv/run.py --test ${test_name} --target rv64gc --output tests/riscvdv --iterations 1 -si questa --iss spike --verbose --cov --seed 0 --steps iss_sim >> ${SIM}/questa/fcov_logs/${test_name}.log 2>&1
# run-elf.bash --seed ${SIM}/questa/seed0.txt --verbose --elf ${WALLY}/tests/riscvdv/asm_test/${test_name}_0.o >> ${SIM}/questa/fcov_logs/${test_name}.log 2>&1
riscvdv_functcov:
mkdir -p ${SIM}/questa/fcov_logs
mkdir -p ${SIM}/questa/fcov_ucdbs
cd ${SIM}/questa/fcov_logs && rm -rf *
cd ${SIM}/questa/fcov_ucdbs && rm -rf *
make riscvdv test_name=riscv_arithmetic_basic_test >> ${SIM}/questa/fcov.log 2>&1
make riscvdv test_name=riscv_amo_test >> ${SIM}/questa/fcov.log 2>&1
make riscvdv test_name=riscv_ebreak_debug_mode_test >> ${SIM}/questa/fcov.log 2>&1
make riscvdv test_name=riscv_ebreak_test >> ${SIM}/questa/fcov.log 2>&1
make riscvdv test_name=riscv_floating_point_arithmetic_test >> ${SIM}/questa/fcov.log 2>&1
make riscvdv test_name=riscv_floating_point_mmu_stress_test >> ${SIM}/questa/fcov.log 2>&1
make riscvdv test_name=riscv_floating_point_rand_test >> ${SIM}/questa/fcov.log 2>&1
make riscvdv test_name=riscv_full_interrupt_test >> ${SIM}/questa/fcov.log 2>&1
make riscvdv test_name=riscv_hint_instr_test >> ${SIM}/questa/fcov.log 2>&1
make riscvdv test_name=riscv_illegal_instr_test >> ${SIM}/questa/fcov.log 2>&1
make riscvdv test_name=riscv_invalid_csr_test >> ${SIM}/questa/fcov.log 2>&1
make riscvdv test_name=riscv_jump_stress_test >> ${SIM}/questa/fcov.log 2>&1
make riscvdv test_name=riscv_loop_test >> ${SIM}/questa/fcov.log 2>&1
make riscvdv test_name=riscv_machine_mode_rand_test >> ${SIM}/questa/fcov.log 2>&1
make riscvdv test_name=riscv_mmu_stress_test >> ${SIM}/questa/fcov.log 2>&1
make riscvdv test_name=riscv_no_fence_test >> ${SIM}/questa/fcov.log 2>&1
make riscvdv test_name=riscv_non_compressed_instr_test >> ${SIM}/questa/fcov.log 2>&1
make riscvdv test_name=riscv_pmp_test >> ${SIM}/questa/fcov.log 2>&1
make riscvdv test_name=riscv_privileged_mode_rand_test >> ${SIM}/questa/fcov.log 2>&1
make riscvdv test_name=riscv_rand_instr_test >> ${SIM}/questa/fcov.log 2>&1
make riscvdv test_name=riscv_rand_jump_test >> ${SIM}/questa/fcov.log 2>&1
make riscvdv test_name=riscv_sfence_exception_test >> ${SIM}/questa/fcov.log 2>&1
make riscvdv test_name=riscv_unaligned_load_store_test >> ${SIM}/questa/fcov.log 2>&1
combine_functcov:
mkdir -p ${SIM}/questa/fcov
mkdir -p ${SIM}/questa/fcov_logs
cd ${SIM}/questa/fcov && 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-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/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/ori.ucdb --elf ${WALLY}/tests/functcov/rv64/I/WALLY-COV-ori.elf >> ${SIM}/questa/fcov_logs/add.log 2>&1
vcover merge ${SIM}/questa/fcov_ucdb/fcov.ucdb ${SIM}/questa/fcov_ucdb/*.ucdb -suppress 6854 -64
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/fcov.ucdb -details -cvg -below 100 | egrep "Coverpoint|Covergroup|Cross" | grep -v Metric > ${SIM}/questa/fcov/fcov.ucdb.summary.log
vcover report ${SIM}/questa/fcov_ucdb/fcov.ucdb -details -cvg | egrep "Coverpoint|Covergroup|Cross|TYPE" > ${SIM}/questa/fcov/fcov.summary.log
grep "Total Coverage By Instance" ${SIM}/questa/fcov/fcov.log
remove_functcov_artifacts:
rm ${SIM}/questa/riscv.ucdb ${SIM}/questa/fcov.log ${SIM}/questa/covhtmlreport/ ${SIM}/questa/fcov_logs/ ${SIM}/questa/fcov_ucdbs/ ${SIM}/questa/fcov/ -rf
collect_functcov: remove_functcov_artifacts riscvdv_functcov combine_functcov
allclean: clean all

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

@ -8,7 +8,7 @@
#
# Takes 1:10 to run RV64IC tests using gui
# Usage: do wally-batch.do <config> <testcases> <testbench> [-coverage] [+acc] [any number of +value] [any number of -G VAR=VAL]
# Usage: do wally-batch.do <config> <testcases> <testbench> [--ccov] [--fcov] [+acc] [any number of +value] [any number of -G VAR=VAL]
# Example: do wally-batch.do rv64gc arch64i testbench
# Use this wally-batch.do file to run this example.
@ -31,6 +31,7 @@ set WALLY $::env(WALLY)
set CONFIG ${WALLY}/config
set SRC ${WALLY}/src
set TB ${WALLY}/testbench
set FCRVVI ${WALLY}/addins/cvw-arch-verif/fcov
# create library
if [file exists ${WKDIR}] {
@ -39,11 +40,16 @@ if [file exists ${WKDIR}] {
vlib ${WKDIR}
# Create directory for coverage data
mkdir -p cov
# Create directory for functional coverage data
mkdir ${WALLY}/addins/cvw-arch-verif/work
set coverage 0
set ccov 0
set CoverageVoptArg ""
set CoverageVsimArg ""
set FuncCovRVVI 0
set FCdefineRVVI_COVERAGE ""
set FunctCoverage 0
set riscvISACOVsrc ""
set FCdefineINCLUDE_TRACE2COV ""
@ -57,7 +63,8 @@ set FCdefineCOVER_RV64D ""
set FCdefineCOVER_RV64ZICSR ""
set FCdefineCOVER_RV64C ""
set FCdefineIDV_INCLUDE_TRACE2COV ""
set FCTRACE2COV ""
set FCdefineIDV_TRACE2COV ""
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
@ -65,7 +72,7 @@ set lockstep 0
set lockstepvoptstring ""
set SVLib ""
set SVLibPath ""
#set OtherFlags ""
set OtherFlags ""
set ImperasPubInc ""
set ImperasPrivInc ""
set rvviFiles ""
@ -104,14 +111,21 @@ if {$AccIndex >= 0} {
}
# if +coverage found set flag and remove from list
set CoverageIndex [lsearch -exact $lst "--coverage"]
set CoverageIndex [lsearch -exact $lst "--ccov"]
if {$CoverageIndex >= 0} {
set coverage 1
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} {
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} {
@ -121,18 +135,20 @@ if {$FunctCoverageIndex >= 0} {
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"
# 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 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.
@ -148,13 +164,14 @@ if {$LockStepIndex >= 0 || $FunctCoverageIndex >= 0} {
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 OtherFlags $env(OTHERFLAGS)
#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 "+"} {
@ -166,8 +183,9 @@ foreach otherArg $lst {
if {$DEBUG > 0} {
echo "GUI = $GUI"
echo "coverage = $coverage"
echo "ccov = $ccov"
echo "lockstep = $lockstep"
echo "FuncCovRVVI = $FuncCovRVVI"
echo "FunctCoverage = $FunctCoverage"
echo "remaining list = $lst"
echo "Extra +args = $PlusArgs"
@ -193,7 +211,7 @@ set temp3 [lindex $PlusArgs 3]
# "Extra checking for conflicts with always_comb done at vopt time"
# because vsim will run vopt
vlog -lint -work ${WKDIR} +incdir+${CONFIG}/${CFG} +incdir+${CONFIG}/deriv/${CFG} +incdir+${CONFIG}/shared ${lockstepvoptstring} ${FCdefineIDV_INCLUDE_TRACE2COV} ${FCdefineINCLUDE_TRACE2COV} ${ImperasPubInc} ${ImperasPrivInc} ${rvviFiles} ${idvFiles} ${FCdefineCOVER_BASE_RV64I} ${FCdefineCOVER_LEVEL_DV_PR_EXT} ${FCdefineCOVER_RV64I} ${FCdefineCOVER_RV64M} ${FCdefineCOVER_RV64A} ${FCdefineCOVER_RV64F} ${FCdefineCOVER_RV64D} ${FCdefineCOVER_RV64ZICSR} ${FCdefineCOVER_RV64C} ${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} ${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 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
@ -201,7 +219,7 @@ vopt $accFlag wkdir/${CFG}_${TESTSUITE}.${TESTBENCH} -work ${WKDIR} ${ParamArgs}
#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} -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/work_${1}_${2} testbenchopt -fatal 7 -suppress 3829
# power add generates the logging necessary for said generation.
@ -215,16 +233,30 @@ if { ${GUI} } {
}
}
run -all
# power off -r /dut/core/*
if {$FunctCoverage} {
set UCDB ${WALLY}/sim/questa/fcov_ucdb/${CFG}_${TESTSUITE}.ucdb
coverage save -onexit ${UCDB}
}
if {$coverage || $FunctCoverage} {
set UCDB ${WALLY}/sim/questa/cov/${CFG}_${TESTSUITE}.ucdb
if {$FuncCovRVVI} {
set UCDB ${WALLY}/addins/cvw-arch-verif/work/${CFG}_${TESTSUITE}.ucdb
coverage save -onexit ${UCDB}
}
run -all
if {$ccov} {
set UCDB ${WALLY}/sim/questa/ucdb/${CFG}_${TESTSUITE}.ucdb
echo "Saving coverage to ${UCDB}"
do coverage-exclusions-rv64gc.do # beware: this assumes testing the rv64gc configuration
coverage save -instance /testbench/dut/core ${UCDB}
}
# power off -r /dut/core/*
# These aren't doing anything helpful
#profile report -calltree -file wally-calltree.rpt -cutoff 2
#power report -all -bsaif power.saif

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 /testbench/dut/core/lsu/hptw/hptw/HPTWLoadPageFault
add wave -noupdate /testbench/dut/core/lsu/hptw/hptw/HPTWLoadPageFaultDelay
add wave -noupdate -expand -group rvvi /testbench/rvvi_synth/rvvisynth/clk
add wave -noupdate -expand -group rvvi /testbench/rvvi_synth/rvvisynth/rvvi
add wave -noupdate -expand -group rvvi /testbench/rvvi_synth/rvvisynth/valid
add wave -noupdate -group packetizer -color Gold /testbench/rvvi_synth/packetizer/CurrState
add wave -noupdate -group packetizer -radix unsigned /testbench/rvvi_synth/packetizer/WordCount
add wave -noupdate -group packetizer /testbench/rvvi_synth/packetizer/RVVIStall
add wave -noupdate -group packetizer /testbench/rvvi_synth/packetizer/rvviDelay
add wave -noupdate -group packetizer -expand -group axi-write-interface /testbench/rvvi_synth/packetizer/RvviAxiWdata
add wave -noupdate -group packetizer -expand -group axi-write-interface /testbench/rvvi_synth/packetizer/RvviAxiWlast
add wave -noupdate -group packetizer -expand -group axi-write-interface /testbench/rvvi_synth/packetizer/RvviAxiWstrb
add wave -noupdate -group packetizer -expand -group axi-write-interface /testbench/rvvi_synth/packetizer/RvviAxiWvalid
add wave -noupdate -group packetizer -expand -group axi-write-interface /testbench/rvvi_synth/packetizer/RvviAxiWready
add wave -noupdate -expand -group eth /testbench/rvvi_synth/ethernet/mii_tx_clk
add wave -noupdate -expand -group eth /testbench/rvvi_synth/ethernet/mii_txd
add wave -noupdate -expand -group eth /testbench/rvvi_synth/ethernet/mii_tx_en
add wave -noupdate -expand -group eth /testbench/rvvi_synth/ethernet/mii_tx_er
TreeUpdate [SetDefaultTree]
WaveRestoreCursors {{Cursor 4} {6586 ns} 1} {{Cursor 4} {2112952 ns} 0} {{Cursor 3} {403021 ns} 1}
quietly wave cursor active 2
WaveRestoreCursors {{Cursor 4} {640 ns} 1} {{Cursor 4} {2400 ns} 1} {{Cursor 3} {554 ns} 0} {{Cursor 4} {120089 ns} 0}
quietly wave cursor active 4
configure wave -namecolwidth 250
configure wave -valuecolwidth 194
configure wave -justifyvalue left
@ -674,4 +690,4 @@ configure wave -griddelta 40
configure wave -timeline 0
configure wave -timelineunits ns
update
WaveRestoreZoom {2039338 ns} {2323972 ns}
WaveRestoreZoom {0 ns} {1033211 ns}

View File

@ -25,7 +25,7 @@ TARGET=$(WORKING_DIR)/target
# INCLUDE_PATH are pathes that Verilator should search for files it needs
INCLUDE_PATH="-I${WALLY}/config/shared" "-I${WALLY}/config/$(WALLYCONF)" "-I${WALLY}/config/deriv/$(WALLYCONF)"
# SOURCES are source files
SOURCES=${WALLY}/src/cvw.sv ${WALLY}/testbench/${TESTBENCH}.sv ${WALLY}/testbench/common/*.sv ${WALLY}/src/*/*.sv ${WALLY}/src/*/*/*.sv
SOURCES=${WALLY}/src/cvw.sv ${WALLY}/testbench/${TESTBENCH}.sv ${WALLY}/testbench/common/*.sv ${WALLY}/src/*/*.sv ${WALLY}/src/*/*/*.sv ${WALLY}/addins/verilog-ethernet/*/*.sv ${WALLY}/addins/verilog-ethernet/*/*/*/*.sv
# DEPENDENCIES are configuration files and source files, which leads to recompilation of executables
DEPENDENCIES=${WALLY}/config/shared/*.vh $(SOURCES)

View File

@ -296,7 +296,6 @@ typedef struct packed {
int DIVBLEN ;
// integer division/remainder constants
int INTDIVb ;
} cvw_t;
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 SupportedFmt; // is the format supported
logic SupportedFmt2; // is the source format supported for fp -> fp
logic SupportedRM; // is the rounding mode supported
logic FCvtIntD, FCvtIntM; // convert to integer operation
logic ZfaD; // Zfa variants of instructions
logic ZfaFRoundNXD; // Zfa froundnx instruction
@ -93,14 +94,19 @@ module fctrl import cvw::*; #(parameter cvw_t P) (
(Fmt == 2'b10 & P.ZFH_SUPPORTED) | (Fmt == 2'b11 & P.Q_SUPPORTED));
assign SupportedFmt2 = (Fmt2 == 2'b00 | (Fmt2 == 2'b01 & P.D_SUPPORTED) |
(Fmt2 == 2'b10 & P.ZFH_SUPPORTED) | (Fmt2 == 2'b11 & P.Q_SUPPORTED));
// rounding modes 5 and 6 are reserved. Rounding mode 7 is dynamic, and is reserved if FRM is 5, 6, or 7
assign SupportedRM = ~(Funct3D == 3'b101 | Funct3D == 3'b110 | (Funct3D == 3'b111 & (FRM_REGW == 3'b101 | FRM_REGW == 3'b110 | FRM_REGW == 3'b111))) |
(OpD == 7'b1010011 & Funct3D == 3'b101 & Funct7D[6:2] == 5'b10100 & P.ZFA_SUPPORTED); // Zfa fltq has a funny rounding mode
/*assign SupportedRM = ~(Funct3D == 3'b101 | Funct3D == 3'b110 | (Funct3D == 3'b111 & (FRM_REGW == 3'b101 | FRM_REGW == 3'b110 | FRM_REGW == 3'b111))) |
(OpD == 7'b1010011 & P.ZFA_SUPPORTED);
*/
// decode the instruction
// FRegWrite_FWriteInt_FResSel_PostProcSel_FOpCtrl_FDivStart_IllegalFPUInstr_FCvtInt_Zfa_FroundNX
always_comb
if (STATUS_FS == 2'b00) // FPU instructions are illegal when FPU is disabled
ControlsD = `FCTRLW'b0_0_00_00_000_0_1_0_0_0;
else if (OpD != 7'b0000111 & OpD != 7'b0100111 & ~SupportedFmt)
ControlsD = `FCTRLW'b0_0_00_00_000_0_1_0_0_0; // for anything other than loads and stores, check for supported format
else if (OpD != 7'b0000111 & OpD != 7'b0100111 & (~SupportedFmt | ~SupportedRM))
ControlsD = `FCTRLW'b0_0_00_00_000_0_1_0_0_0; // for anything other than loads and stores, check for supported format and rounding mode
else begin
ControlsD = `FCTRLW'b0_0_00_00_000_0_1_0_0_0; // default: non-implemented instruction
/* verilator lint_off CASEINCOMPLETE */ // default value above has priority so no other default needed

View File

@ -83,11 +83,30 @@ module ram1p1rwbe import cvw::*; #(parameter USE_SRAM=0, DEPTH=64, WIDTH=44, PRE
end else begin: ram
bit [WIDTH-1:0] RAM[DEPTH-1:0];
if (PRELOAD_ENABLED) begin
initial begin
RAM[0] = 64'h00600100d2e3ca40;
// if (PRELOAD_ENABLED) begin
// initial begin
// RAM[0] = 64'h00600100d2e3ca40;
// end
// end
`ifdef VERILATOR
import "DPI-C" function string getenvval(input string env_name);
`endif
initial
if (PRELOAD_ENABLED) begin
if (WIDTH == 64) begin
`ifdef VERILATOR
// because Verilator doesn't automatically accept $WALLY from shell
string WALLY_DIR = getenvval("WALLY");
$readmemh({WALLY_DIR,"/fpga/src/data.mem"}, RAM, 0); // load boot RAM for FPGA
`else
$readmemh({"$WALLY/fpga/src/data.mem"}, RAM, 0); // load boot RAM for FPGA
`endif
end else begin // put something in the RAM so it is not optimized away
RAM[0] = 'h00002197;
end
end
end
// Combinational read: register address and read after clock edge
logic [$clog2(DEPTH)-1:0] addrd;

View File

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

View File

@ -30,7 +30,7 @@
module alu import cvw::*; #(parameter cvw_t P) (
input logic [P.XLEN-1:0] A, B, // Operands
input logic W64, // W64-type instruction
input logic W64, UW64, // W64/.uw-type instruction
input logic SubArith, // Subtraction or arithmetic shift
input logic [2:0] ALUSelect, // ALU mux select signal
input logic [3:0] BSelect, // Binary encoding of if it's a ZBA_ZBB_ZBC_ZBS instruction
@ -77,7 +77,7 @@ module alu import cvw::*; #(parameter cvw_t P) (
end else assign ZeroCondMaskInvB = CondMaskInvB; // no masking if Zicond is not supported
// Shifts (configurable for rotation)
shifter #(P) sh(.A, .Amt(B[P.LOG_XLEN-1:0]), .Right(Funct3[2]), .W64, .SubArith, .Y(Shift), .Rotate(BALUControl[2]));
shifter #(P) sh(.A(CondShiftA), .Amt(B[P.LOG_XLEN-1:0]), .Right(Funct3[2]), .W64, .SubArith, .Y(Shift), .Rotate(BALUControl[2]));
// Condition code flags are based on subtraction output Sum = A-B.
// Overflow occurs when the numbers being subtracted have the opposite sign
@ -113,7 +113,7 @@ module alu import cvw::*; #(parameter cvw_t P) (
P.ZBKB_SUPPORTED | P.ZBKC_SUPPORTED | P.ZBKX_SUPPORTED |
P.ZKND_SUPPORTED | P.ZKNE_SUPPORTED | P.ZKNH_SUPPORTED) begin : bitmanipalu
bitmanipalu #(P) balu(
.A, .B, .W64, .BSelect, .ZBBSelect, .BMUActive,
.A, .B, .W64, .UW64, .BSelect, .ZBBSelect, .BMUActive,
.Funct3, .Funct7, .Rs2E, .LT,.LTU, .BALUControl, .PreALUResult, .FullResult,
.CondMaskB, .CondShiftA, .ALUResult);
end else begin

View File

@ -30,16 +30,16 @@
module bitmanipalu import cvw::*; #(parameter cvw_t P) (
input logic [P.XLEN-1:0] A, B, // Operands
input logic W64, // W64-type instruction
input logic W64, UW64, // W64/.uw-type instruction
input logic [3:0] BSelect, // Binary encoding of if it's a ZBA_ZBB_ZBC_ZBS instruction
input logic [3:0] ZBBSelect, // ZBB mux select signal
input logic [2:0] Funct3, // Funct3 field of opcode indicates operation to perform
input logic [6:0] Funct7, // Funct7 field for ZKND and ZKNE operations
input logic [4:0] Rs2E, // Register source2 for RNUM of ZKNE/ZKND
input logic LT, // less than flag
input logic LTU, // less than unsigned flag
input logic LT, // less than flag
input logic LTU, // less than unsigned flag
input logic [2:0] BALUControl, // ALU Control signals for B instructions in Execute Stage
input logic BMUActive, // Bit manipulation instruction being executed
input logic BMUActive, // Bit manipulation instruction being executed
input logic [P.XLEN-1:0] PreALUResult, // PreALUResult signals
input logic [P.XLEN-1:0] FullResult, // FullResult signals
output logic [P.XLEN-1:0] CondMaskB, // B is conditionally masked for ZBS instructions
@ -76,7 +76,7 @@ module bitmanipalu import cvw::*; #(parameter cvw_t P) (
// 0-3 bit Pre-Shift Mux
if (P.ZBA_SUPPORTED) begin: zbapreshift
if (P.XLEN == 64) begin
mux2 #(64) zextmux(A, {{32{1'b0}}, A[31:0]}, W64, CondZextA);
mux2 #(64) zextmux(A, {{32{1'b0}}, A[31:0]}, UW64, CondZextA);
end else assign CondZextA = A;
assign PreShiftAmt = Funct3[2:1] & {2{PreShift}};
assign CondShiftA = CondZextA << (PreShiftAmt);

View File

@ -36,6 +36,7 @@ module bmuctrl import cvw::*; #(parameter cvw_t P) (
output logic BRegWriteD, // Indicates if it is a R type B instruction in Decode Stage
output logic BALUSrcBD, // Indicates if it is an I/IW (non auipc) type B instruction in Decode Stage
output logic BW64D, // Indiciates if it is a W type B instruction in Decode Stage
output logic BUW64D, // Indiciates if it is a .uw type B instruction in Decode Stage
output logic BSubArithD, // TRUE if ext, clr, andn, orn, xnor instruction in Decode Stage
output logic IllegalBitmanipInstrD, // Indicates if it is unrecognized B instruction in Decode Stage
// Execute stage control signals
@ -60,7 +61,7 @@ module bmuctrl import cvw::*; #(parameter cvw_t P) (
logic [3:0] BSelectD; // Indicates if ZBA_ZBB_ZBC_ZBS instruction in one-hot encoding in Decode stage
logic [3:0] ZBBSelectD; // ZBB mux select signal in Decode stage
`define BMUCTRLW 20
`define BMUCTRLW 21
logic [`BMUCTRLW-1:0] BMUControlsD; // Main B Instructions Decoder control signals
@ -72,209 +73,209 @@ module bmuctrl import cvw::*; #(parameter cvw_t P) (
// Main Instruction Decoder
always_comb begin
// BALUSelect_BSelect_ZBBSelect_BRegWrite_BALUSrcB_BW64_BALUOp_BSubArithD_RotateD_MaskD_PreShiftD_IllegalBitmanipInstrD
// BALUSelect_BSelect_ZBBSelect_BRegWrite_BALUSrcB_BW64_BUW64_BALUOp_BSubArithD_RotateD_MaskD_PreShiftD_IllegalBitmanipInstrD
BMUControlsD = `BMUCTRLW'b000_00_000_0_0_0_0_0_0_0_0_1; // default: Illegal bmu instruction;
if (P.ZBA_SUPPORTED) begin
casez({OpD, Funct7D, Funct3D})
17'b0110011_0010000_010: BMUControlsD = `BMUCTRLW'b000_0001_0000_1_0_0_1_0_0_0_1_0; // sh1add
17'b0110011_0010000_100: BMUControlsD = `BMUCTRLW'b000_0001_0000_1_0_0_1_0_0_0_1_0; // sh2add
17'b0110011_0010000_110: BMUControlsD = `BMUCTRLW'b000_0001_0000_1_0_0_1_0_0_0_1_0; // sh3add
17'b0110011_0010000_010: BMUControlsD = `BMUCTRLW'b000_0001_0000_1_0_0_0_1_0_0_0_1_0; // sh1add
17'b0110011_0010000_100: BMUControlsD = `BMUCTRLW'b000_0001_0000_1_0_0_0_1_0_0_0_1_0; // sh2add
17'b0110011_0010000_110: BMUControlsD = `BMUCTRLW'b000_0001_0000_1_0_0_0_1_0_0_0_1_0; // sh3add
endcase
if (P.XLEN==64)
casez({OpD, Funct7D, Funct3D})
17'b0111011_0010000_010: BMUControlsD = `BMUCTRLW'b000_0001_0000_1_0_1_1_0_0_0_1_0; // sh1add.uw
17'b0111011_0010000_100: BMUControlsD = `BMUCTRLW'b000_0001_0000_1_0_1_1_0_0_0_1_0; // sh2add.uw
17'b0111011_0010000_110: BMUControlsD = `BMUCTRLW'b000_0001_0000_1_0_1_1_0_0_0_1_0; // sh3add.uw
17'b0111011_0000100_000: BMUControlsD = `BMUCTRLW'b000_0001_0000_1_0_1_1_0_0_0_0_0; // add.uw
17'b0011011_000010?_001: BMUControlsD = `BMUCTRLW'b001_0001_0000_1_1_1_1_0_0_0_0_0; // slli.uw
17'b0111011_0010000_010: BMUControlsD = `BMUCTRLW'b000_0001_0000_1_0_0_1_1_0_0_0_1_0; // sh1add.uw
17'b0111011_0010000_100: BMUControlsD = `BMUCTRLW'b000_0001_0000_1_0_0_1_1_0_0_0_1_0; // sh2add.uw
17'b0111011_0010000_110: BMUControlsD = `BMUCTRLW'b000_0001_0000_1_0_0_1_1_0_0_0_1_0; // sh3add.uw
17'b0111011_0000100_000: BMUControlsD = `BMUCTRLW'b000_0001_0000_1_0_0_1_1_0_0_0_0_0; // add.uw
17'b0011011_000010?_001: BMUControlsD = `BMUCTRLW'b001_0001_0000_1_1_0_1_1_0_0_0_0_0; // slli.uw
endcase
end
if (P.ZBB_SUPPORTED) begin
casez({OpD, Funct7D, Funct3D})
17'b0010011_0110000_001: if ((Rs2D[4:1] == 4'b0010))
BMUControlsD = `BMUCTRLW'b000_0010_0001_1_1_0_1_0_0_0_0_0; // sign extend instruction
BMUControlsD = `BMUCTRLW'b000_0010_0001_1_1_0_0_1_0_0_0_0_0; // sign extend instruction
else if ((Rs2D[4:2]==3'b000) & ~(Rs2D[1] & Rs2D[0]))
BMUControlsD = `BMUCTRLW'b000_0010_0000_1_1_0_1_0_0_0_0_0; // count instruction
BMUControlsD = `BMUCTRLW'b000_0010_0000_1_1_0_0_1_0_0_0_0_0; // count instruction
17'b0010011_0010100_101: if (Rs2D[4:0] == 5'b00111)
BMUControlsD = `BMUCTRLW'b000_0010_0010_1_1_0_1_0_0_0_0_0; // orc.b
17'b0110011_0000101_110: BMUControlsD = `BMUCTRLW'b000_0010_0111_1_0_0_1_1_0_0_0_0; // max
17'b0110011_0000101_111: BMUControlsD = `BMUCTRLW'b000_0010_0111_1_0_0_1_1_0_0_0_0; // maxu
17'b0110011_0000101_100: BMUControlsD = `BMUCTRLW'b000_0010_0011_1_0_0_1_1_0_0_0_0; // min
17'b0110011_0000101_101: BMUControlsD = `BMUCTRLW'b000_0010_0011_1_0_0_1_1_0_0_0_0; // minu
BMUControlsD = `BMUCTRLW'b000_0010_0010_1_1_0_0_1_0_0_0_0_0; // orc.b
17'b0110011_0000101_110: BMUControlsD = `BMUCTRLW'b000_0010_0111_1_0_0_0_1_1_0_0_0_0; // max
17'b0110011_0000101_111: BMUControlsD = `BMUCTRLW'b000_0010_0111_1_0_0_0_1_1_0_0_0_0; // maxu
17'b0110011_0000101_100: BMUControlsD = `BMUCTRLW'b000_0010_0011_1_0_0_0_1_1_0_0_0_0; // min
17'b0110011_0000101_101: BMUControlsD = `BMUCTRLW'b000_0010_0011_1_0_0_0_1_1_0_0_0_0; // minu
endcase
if (P.XLEN==32)
casez({OpD, Funct7D, Funct3D})
17'b0110011_0000100_100: BMUControlsD = `BMUCTRLW'b000_0010_0001_1_1_0_1_0_0_0_0_0; // zexth (rv32)
17'b0110011_0000100_100: BMUControlsD = `BMUCTRLW'b000_0010_0001_1_1_0_0_1_0_0_0_0_0; // zexth (rv32)
endcase
else if (P.XLEN==64)
casez({OpD, Funct7D, Funct3D})
17'b0111011_0000100_100: BMUControlsD = `BMUCTRLW'b000_0010_0001_1_0_0_1_0_0_0_0_0; // zexth (rv64)
17'b0111011_0000100_100: BMUControlsD = `BMUCTRLW'b000_0010_0001_1_0_0_0_1_0_0_0_0_0; // zexth (rv64)
17'b0011011_0110000_001: if ((Rs2D[4:2]==3'b000) & ~(Rs2D[1] & Rs2D[0]))
BMUControlsD = `BMUCTRLW'b000_0010_0000_1_1_1_1_0_0_0_0_0; // count word instruction
BMUControlsD = `BMUCTRLW'b000_0010_0000_1_1_1_1_0_0_0_0_0_0; // count word instruction (clzw/ctzw/cpopw)
endcase
end
if (P.ZBC_SUPPORTED)
casez({OpD, Funct7D, Funct3D})
17'b0110011_0000101_010: BMUControlsD = `BMUCTRLW'b000_0011_0001_1_0_0_1_0_0_0_0_0; // clmulr
17'b0110011_0000101_0??: BMUControlsD = `BMUCTRLW'b000_0011_0000_1_0_0_1_0_0_0_0_0; // clmul/clmulh
17'b0110011_0000101_010: BMUControlsD = `BMUCTRLW'b000_0011_0001_1_0_0_0_1_0_0_0_0_0; // clmulr
17'b0110011_0000101_0??: BMUControlsD = `BMUCTRLW'b000_0011_0000_1_0_0_0_1_0_0_0_0_0; // clmul/clmulh
endcase
if (P.ZBKC_SUPPORTED) begin
casez({OpD, Funct7D, Funct3D})
17'b0110011_0000101_0??: BMUControlsD = `BMUCTRLW'b000_0011_0000_1_0_0_1_0_0_0_0_0; // clmul/clmulh
// 17'b0110011_0000101_001: BMUControlsD = `BMUCTRLW'b000_0011_0000_1_0_0_1_0_0_0_0_0; // clmul
// 17'b0110011_0000101_011: BMUControlsD = `BMUCTRLW'b000_0011_0001_1_0_0_1_0_0_0_0_0; // clmulh
17'b0110011_0000101_0??: BMUControlsD = `BMUCTRLW'b000_0011_0000_1_0_0_0_1_0_0_0_0_0; // clmul/clmulh
// 17'b0110011_0000101_001: BMUControlsD = `BMUCTRLW'b000_0011_0000_1_0_0_0_1_0_0_0_0_0; // clmul
// 17'b0110011_0000101_011: BMUControlsD = `BMUCTRLW'b000_0011_0001_1_0_0_0_1_0_0_0_0_0; // clmulh
endcase
end
if (P.ZBS_SUPPORTED) begin // ZBS
casez({OpD, Funct7D, Funct3D})
17'b0110011_0100100_001: BMUControlsD = `BMUCTRLW'b111_0001_0000_1_0_0_1_1_0_1_0_0; // bclr
17'b0110011_0100100_101: BMUControlsD = `BMUCTRLW'b101_0001_0000_1_0_0_1_0_0_1_0_0; // bext
17'b0110011_0110100_001: BMUControlsD = `BMUCTRLW'b100_0001_0000_1_0_0_1_0_0_1_0_0; // binv
17'b0110011_0010100_001: BMUControlsD = `BMUCTRLW'b110_0001_0000_1_0_0_1_0_0_1_0_0; // bset
17'b0110011_0100100_001: BMUControlsD = `BMUCTRLW'b111_0001_0000_1_0_0_0_1_1_0_1_0_0; // bclr
17'b0110011_0100100_101: BMUControlsD = `BMUCTRLW'b101_0001_0000_1_0_0_0_1_0_0_1_0_0; // bext
17'b0110011_0110100_001: BMUControlsD = `BMUCTRLW'b100_0001_0000_1_0_0_0_1_0_0_1_0_0; // binv
17'b0110011_0010100_001: BMUControlsD = `BMUCTRLW'b110_0001_0000_1_0_0_0_1_0_0_1_0_0; // bset
endcase
if (P.XLEN==32) // ZBS 64-bit
casez({OpD, Funct7D, Funct3D})
17'b0010011_0100100_001: BMUControlsD = `BMUCTRLW'b111_0001_0000_1_1_0_1_1_0_1_0_0; // bclri
17'b0010011_0100100_101: BMUControlsD = `BMUCTRLW'b101_0001_0000_1_1_0_1_0_0_1_0_0; // bexti
17'b0010011_0110100_001: BMUControlsD = `BMUCTRLW'b100_0001_0000_1_1_0_1_0_0_1_0_0; // binvi
17'b0010011_0010100_001: BMUControlsD = `BMUCTRLW'b110_0001_0000_1_1_0_1_0_0_1_0_0; // bseti
17'b0010011_0100100_001: BMUControlsD = `BMUCTRLW'b111_0001_0000_1_1_0_0_1_1_0_1_0_0; // bclri
17'b0010011_0100100_101: BMUControlsD = `BMUCTRLW'b101_0001_0000_1_1_0_0_1_0_0_1_0_0; // bexti
17'b0010011_0110100_001: BMUControlsD = `BMUCTRLW'b100_0001_0000_1_1_0_0_1_0_0_1_0_0; // binvi
17'b0010011_0010100_001: BMUControlsD = `BMUCTRLW'b110_0001_0000_1_1_0_0_1_0_0_1_0_0; // bseti
endcase
else if (P.XLEN==64) // ZBS 64-bit
casez({OpD, Funct7D, Funct3D})
17'b0010011_010010?_001: BMUControlsD = `BMUCTRLW'b111_0001_0000_1_1_0_1_1_0_1_0_0; // bclri (rv64)
17'b0010011_010010?_101: BMUControlsD = `BMUCTRLW'b101_0001_0000_1_1_0_1_0_0_1_0_0; // bexti (rv64)
17'b0010011_011010?_001: BMUControlsD = `BMUCTRLW'b100_0001_0000_1_1_0_1_0_0_1_0_0; // binvi (rv64)
17'b0010011_001010?_001: BMUControlsD = `BMUCTRLW'b110_0001_0000_1_1_0_1_0_0_1_0_0; // bseti (rv64)
17'b0010011_010010?_001: BMUControlsD = `BMUCTRLW'b111_0001_0000_1_1_0_0_1_1_0_1_0_0; // bclri (rv64)
17'b0010011_010010?_101: BMUControlsD = `BMUCTRLW'b101_0001_0000_1_1_0_0_1_0_0_1_0_0; // bexti (rv64)
17'b0010011_011010?_001: BMUControlsD = `BMUCTRLW'b100_0001_0000_1_1_0_0_1_0_0_1_0_0; // binvi (rv64)
17'b0010011_001010?_001: BMUControlsD = `BMUCTRLW'b110_0001_0000_1_1_0_0_1_0_0_1_0_0; // bseti (rv64)
endcase
end
if (P.ZBB_SUPPORTED | P.ZBS_SUPPORTED) // rv32i/64i shift instructions need BMU ALUSelect when BMU shifter is used
casez({OpD, Funct7D, Funct3D})
17'b0110011_0?0000?_?01: BMUControlsD = `BMUCTRLW'b001_0000_0000_1_0_0_1_0_0_0_0_0; // sra, srl, sll
17'b0010011_0?0000?_?01: BMUControlsD = `BMUCTRLW'b001_0000_0000_1_1_0_1_0_0_0_0_0; // srai, srli, slli
17'b0111011_0?0000?_?01: BMUControlsD = `BMUCTRLW'b001_0000_0000_1_0_1_1_0_0_0_0_0; // sraw, srlw, sllw
17'b0011011_0?0000?_?01: BMUControlsD = `BMUCTRLW'b001_0000_0000_1_1_1_1_0_0_0_0_0; // sraiw, srliw, slliw
17'b0110011_0?0000?_?01: BMUControlsD = `BMUCTRLW'b001_0000_0000_1_0_0_0_1_0_0_0_0_0; // sra, srl, sll
17'b0010011_0?0000?_?01: BMUControlsD = `BMUCTRLW'b001_0000_0000_1_1_0_0_1_0_0_0_0_0; // srai, srli, slli
17'b0111011_0?0000?_?01: BMUControlsD = `BMUCTRLW'b001_0000_0000_1_0_1_0_1_0_0_0_0_0; // sraw, srlw, sllw
17'b0011011_0?0000?_?01: BMUControlsD = `BMUCTRLW'b001_0000_0000_1_1_1_0_1_0_0_0_0_0; // sraiw, srliw, slliw
endcase
if (P.ZBKB_SUPPORTED) begin // ZBKB Bitmanip
casez({OpD,Funct7D, Funct3D})
17'b0110011_0000100_100: BMUControlsD = `BMUCTRLW'b000_0100_0001_1_0_0_1_0_0_0_0_0; // pack
17'b0110011_0000100_111: BMUControlsD = `BMUCTRLW'b000_0100_0001_1_0_0_1_0_0_0_0_0; // packh
17'b0110011_0000100_100: BMUControlsD = `BMUCTRLW'b000_0100_0001_1_0_0_0_1_0_0_0_0_0; // pack
17'b0110011_0000100_111: BMUControlsD = `BMUCTRLW'b000_0100_0001_1_0_0_0_1_0_0_0_0_0; // packh
17'b0010011_0110100_101: if (Rs2D == 5'b00111)
BMUControlsD = `BMUCTRLW'b000_0100_0000_1_1_0_1_0_0_0_0_0; // brev8
BMUControlsD = `BMUCTRLW'b000_0100_0000_1_1_0_0_1_0_0_0_0_0; // brev8
endcase
if (P.XLEN==32)
casez({OpD, Funct7D, Funct3D})
17'b0010011_0000100_001: if (Rs2D == 5'b01111)
BMUControlsD = `BMUCTRLW'b000_0100_0011_1_1_0_1_0_0_0_0_0; //zip
BMUControlsD = `BMUCTRLW'b000_0100_0011_1_1_0_0_1_0_0_0_0_0; //zip
17'b0010011_0000100_101: if (Rs2D == 5'b01111)
BMUControlsD = `BMUCTRLW'b000_0100_0011_1_1_0_1_0_0_0_0_0; //unzip
BMUControlsD = `BMUCTRLW'b000_0100_0011_1_1_0_0_1_0_0_0_0_0; //unzip
endcase
else if (P.XLEN==64)
casez({OpD,Funct7D, Funct3D})
17'b0111011_0000100_100: BMUControlsD = `BMUCTRLW'b000_0100_0101_1_0_1_1_0_0_0_0_0; //packw
17'b0111011_0000100_100: BMUControlsD = `BMUCTRLW'b000_0100_0101_1_0_1_0_1_0_0_0_0_0; //packw
endcase
end
if (P.ZBB_SUPPORTED | P.ZBKB_SUPPORTED) begin // ZBB and ZBKB shared instructions
casez({OpD, Funct7D, Funct3D})
17'b0110011_0110000_001: BMUControlsD = `BMUCTRLW'b001_0001_0111_1_0_0_1_0_1_0_0_0; // rol
17'b0110011_0110000_101: BMUControlsD = `BMUCTRLW'b001_0001_0111_1_0_0_1_0_1_0_0_0; // ror
17'b0110011_0100000_111: BMUControlsD = `BMUCTRLW'b111_0001_0111_1_0_0_1_1_0_0_0_0; // andn
17'b0110011_0100000_110: BMUControlsD = `BMUCTRLW'b110_0001_0111_1_0_0_1_1_0_0_0_0; // orn
17'b0110011_0100000_100: BMUControlsD = `BMUCTRLW'b100_0001_0111_1_0_0_1_1_0_0_0_0; // xnor
17'b0110011_0110000_001: BMUControlsD = `BMUCTRLW'b001_0001_0111_1_0_0_0_1_0_1_0_0_0; // rol
17'b0110011_0110000_101: BMUControlsD = `BMUCTRLW'b001_0001_0111_1_0_0_0_1_0_1_0_0_0; // ror
17'b0110011_0100000_111: BMUControlsD = `BMUCTRLW'b111_0001_0111_1_0_0_0_1_1_0_0_0_0; // andn
17'b0110011_0100000_110: BMUControlsD = `BMUCTRLW'b110_0001_0111_1_0_0_0_1_1_0_0_0_0; // orn
17'b0110011_0100000_100: BMUControlsD = `BMUCTRLW'b100_0001_0111_1_0_0_0_1_1_0_0_0_0; // xnor
17'b0010011_011010?_101: if ((P.XLEN == 32 ^ Funct7D[0]) & (Rs2D == 5'b11000))
BMUControlsD = `BMUCTRLW'b000_0010_0010_1_1_0_1_0_0_0_0_0; // rev8
BMUControlsD = `BMUCTRLW'b000_0010_0010_1_1_0_0_1_0_0_0_0_0; // rev8
endcase
if (P.XLEN==32)
casez({OpD, Funct7D, Funct3D})
17'b0010011_0110000_101: BMUControlsD = `BMUCTRLW'b001_0000_0111_1_1_0_1_0_1_0_0_0; // rori (rv32)
17'b0010011_0110000_101: BMUControlsD = `BMUCTRLW'b001_0000_0111_1_1_0_0_1_0_1_0_0_0; // rori (rv32)
endcase
else if (P.XLEN==64)
casez({OpD, Funct7D, Funct3D})
17'b0111011_0110000_001: BMUControlsD = `BMUCTRLW'b001_0000_0111_1_0_1_1_0_1_0_0_0; // rolw
17'b0111011_0110000_101: BMUControlsD = `BMUCTRLW'b001_0000_0111_1_0_1_1_0_1_0_0_0; // rorw
17'b0010011_011000?_101: BMUControlsD = `BMUCTRLW'b001_0000_0111_1_1_0_1_0_1_0_0_0; // rori (rv64)
17'b0011011_0110000_101: BMUControlsD = `BMUCTRLW'b001_0000_0111_1_1_1_1_0_1_0_0_0; // roriw
17'b0111011_0110000_001: BMUControlsD = `BMUCTRLW'b001_0000_0111_1_0_1_0_1_0_1_0_0_0; // rolw
17'b0111011_0110000_101: BMUControlsD = `BMUCTRLW'b001_0000_0111_1_0_1_0_1_0_1_0_0_0; // rorw
17'b0010011_011000?_101: BMUControlsD = `BMUCTRLW'b001_0000_0111_1_1_0_0_1_0_1_0_0_0; // rori (rv64)
17'b0011011_0110000_101: BMUControlsD = `BMUCTRLW'b001_0000_0111_1_1_1_0_1_0_1_0_0_0; // roriw
endcase
end
if (P.ZBKX_SUPPORTED) begin //ZBKX
casez({OpD, Funct7D, Funct3D})
17'b0110011_0010100_100: BMUControlsD = `BMUCTRLW'b000_0110_0000_1_0_0_1_0_0_0_0_0; // xperm8
17'b0110011_0010100_010: BMUControlsD = `BMUCTRLW'b000_0110_0001_1_0_0_1_0_0_0_0_0; // xperm4
17'b0110011_0010100_100: BMUControlsD = `BMUCTRLW'b000_0110_0000_1_0_0_0_1_0_0_0_0_0; // xperm8
17'b0110011_0010100_010: BMUControlsD = `BMUCTRLW'b000_0110_0001_1_0_0_0_1_0_0_0_0_0; // xperm4
endcase
end
if (P.ZKND_SUPPORTED) begin //ZKND
if (P.XLEN==32)
casez({OpD, Funct7D, Funct3D})
17'b0110011_??10101_000: BMUControlsD = `BMUCTRLW'b000_0111_0100_1_0_0_1_0_0_0_0_0; // aes32dsi - final round decrypt
17'b0110011_??10111_000: BMUControlsD = `BMUCTRLW'b000_0111_0000_1_0_0_1_0_0_0_0_0; // aes32dsmi - mid round decrypt
17'b0110011_??10101_000: BMUControlsD = `BMUCTRLW'b000_0111_0100_1_0_0_0_1_0_0_0_0_0; // aes32dsi - final round decrypt
17'b0110011_??10111_000: BMUControlsD = `BMUCTRLW'b000_0111_0000_1_0_0_0_1_0_0_0_0_0; // aes32dsmi - mid round decrypt
endcase
else if (P.XLEN==64)
casez({OpD, Funct7D, Funct3D})
17'b0110011_0011101_000: BMUControlsD = `BMUCTRLW'b000_0111_0100_1_0_0_1_0_0_0_0_0; // aes64ds - decrypt final round
17'b0110011_0011111_000: BMUControlsD = `BMUCTRLW'b000_0111_0000_1_0_0_1_0_0_0_0_0; // aes64dsm - decrypt mid round
17'b0110011_0011101_000: BMUControlsD = `BMUCTRLW'b000_0111_0100_1_0_0_0_1_0_0_0_0_0; // aes64ds - decrypt final round
17'b0110011_0011111_000: BMUControlsD = `BMUCTRLW'b000_0111_0000_1_0_0_0_1_0_0_0_0_0; // aes64dsm - decrypt mid round
17'b0010011_0011000_001: if (Rs2D == 5'b00000)
BMUControlsD = `BMUCTRLW'b000_0111_1000_1_1_0_1_0_0_0_0_0; // aes64im - decrypt keyschdule mixcolumns
BMUControlsD = `BMUCTRLW'b000_0111_1000_1_1_0_0_1_0_0_0_0_0; // aes64im - decrypt keyschdule mixcolumns
endcase
end
if (P.ZKNE_SUPPORTED) begin //ZKNE
if (P.XLEN==32)
casez({OpD, Funct7D, Funct3D})
17'b0110011_??10001_000: BMUControlsD = `BMUCTRLW'b000_0111_0101_1_0_0_1_0_0_0_0_0; // aes32esi - final round encrypt
17'b0110011_??10011_000: BMUControlsD = `BMUCTRLW'b000_0111_0001_1_0_0_1_0_0_0_0_0; // aes32esmi - mid round encrypt
17'b0110011_??10001_000: BMUControlsD = `BMUCTRLW'b000_0111_0101_1_0_0_0_1_0_0_0_0_0; // aes32esi - final round encrypt
17'b0110011_??10011_000: BMUControlsD = `BMUCTRLW'b000_0111_0001_1_0_0_0_1_0_0_0_0_0; // aes32esmi - mid round encrypt
endcase
else if (P.XLEN==64)
casez({OpD, Funct7D, Funct3D})
17'b0110011_0011001_000: BMUControlsD = `BMUCTRLW'b000_0111_0101_1_0_0_1_0_0_0_0_0; // aes64es - encrypt final round
17'b0110011_0011011_000: BMUControlsD = `BMUCTRLW'b000_0111_0001_1_0_0_1_0_0_0_0_0; // aes64esm - encrypt mid round
17'b0110011_0011001_000: BMUControlsD = `BMUCTRLW'b000_0111_0101_1_0_0_0_1_0_0_0_0_0; // aes64es - encrypt final round
17'b0110011_0011011_000: BMUControlsD = `BMUCTRLW'b000_0111_0001_1_0_0_0_1_0_0_0_0_0; // aes64esm - encrypt mid round
endcase
end
if ((P.ZKND_SUPPORTED | P.ZKNE_SUPPORTED) & P.XLEN == 64) begin // ZKND and ZKNE shared instructions
casez({OpD, Funct7D, Funct3D})
17'b0010011_0011000_001: if (Rs2D[4] == 1'b1)
BMUControlsD = `BMUCTRLW'b000_0111_0010_1_0_0_1_0_0_0_0_0; // aes64ks1i - key schedule istr1
17'b0110011_0111111_000: BMUControlsD = `BMUCTRLW'b000_0111_0011_1_0_0_1_0_0_0_0_0; // aes64ks2 - key schedule istr2
17'b0010011_0011000_001: if (Rs2D[4] == 1'b1 & $unsigned(Rs2D[3:0]) <= 10)
BMUControlsD = `BMUCTRLW'b000_0111_0010_1_0_0_0_1_0_0_0_0_0; // aes64ks1i - key schedule istr1
17'b0110011_0111111_000: BMUControlsD = `BMUCTRLW'b000_0111_0011_1_0_0_0_1_0_0_0_0_0; // aes64ks2 - key schedule istr2
endcase
end
if (P.ZKNH_SUPPORTED) begin // ZKNH
casez({OpD, Funct7D, Funct3D})
17'b0010011_0001000_001:
if (Rs2D == 5'b00010) BMUControlsD = `BMUCTRLW'b000_1000_0000_1_0_0_1_0_0_0_0_0; // sha256sig0
else if (Rs2D == 5'b00011) BMUControlsD = `BMUCTRLW'b000_1000_0001_1_0_0_1_0_0_0_0_0; // sha256sig1
else if (Rs2D == 5'b00000) BMUControlsD = `BMUCTRLW'b000_1000_0010_1_0_0_1_0_0_0_0_0; // sha256sum0
else if (Rs2D == 5'b00001) BMUControlsD = `BMUCTRLW'b000_1000_0011_1_0_0_1_0_0_0_0_0; // sha256sum1
if (Rs2D == 5'b00010) BMUControlsD = `BMUCTRLW'b000_1000_0000_1_0_0_0_1_0_0_0_0_0; // sha256sig0
else if (Rs2D == 5'b00011) BMUControlsD = `BMUCTRLW'b000_1000_0001_1_0_0_0_1_0_0_0_0_0; // sha256sig1
else if (Rs2D == 5'b00000) BMUControlsD = `BMUCTRLW'b000_1000_0010_1_0_0_0_1_0_0_0_0_0; // sha256sum0
else if (Rs2D == 5'b00001) BMUControlsD = `BMUCTRLW'b000_1000_0011_1_0_0_0_1_0_0_0_0_0; // sha256sum1
endcase
if (P.XLEN==32)
casez({OpD, Funct7D, Funct3D})
17'b0110011_0101110_000: BMUControlsD = `BMUCTRLW'b000_1000_1000_1_0_0_1_0_0_0_0_0; // sha512sig0h
17'b0110011_0101010_000: BMUControlsD = `BMUCTRLW'b000_1000_1001_1_0_0_1_0_0_0_0_0; // sha512sig0l
17'b0110011_0101111_000: BMUControlsD = `BMUCTRLW'b000_1000_1010_1_0_0_1_0_0_0_0_0; // sha512sig1h
17'b0110011_0101011_000: BMUControlsD = `BMUCTRLW'b000_1000_1011_1_0_0_1_0_0_0_0_0; // sha512sig1l
17'b0110011_0101000_000: BMUControlsD = `BMUCTRLW'b000_1000_1100_1_0_0_1_0_0_0_0_0; // sha512sum0r
17'b0110011_0101001_000: BMUControlsD = `BMUCTRLW'b000_1000_1110_1_0_0_1_0_0_0_0_0; // sha512sum1r
17'b0110011_0101110_000: BMUControlsD = `BMUCTRLW'b000_1000_1000_1_0_0_0_1_0_0_0_0_0; // sha512sig0h
17'b0110011_0101010_000: BMUControlsD = `BMUCTRLW'b000_1000_1001_1_0_0_0_1_0_0_0_0_0; // sha512sig0l
17'b0110011_0101111_000: BMUControlsD = `BMUCTRLW'b000_1000_1010_1_0_0_0_1_0_0_0_0_0; // sha512sig1h
17'b0110011_0101011_000: BMUControlsD = `BMUCTRLW'b000_1000_1011_1_0_0_0_1_0_0_0_0_0; // sha512sig1l
17'b0110011_0101000_000: BMUControlsD = `BMUCTRLW'b000_1000_1100_1_0_0_0_1_0_0_0_0_0; // sha512sum0r
17'b0110011_0101001_000: BMUControlsD = `BMUCTRLW'b000_1000_1110_1_0_0_0_1_0_0_0_0_0; // sha512sum1r
endcase
else if (P.XLEN==64)
casez({OpD, Funct7D, Funct3D})
17'b0010011_0001000_001:
if (Rs2D == 5'b00110) BMUControlsD = `BMUCTRLW'b000_1000_1000_1_0_0_1_0_0_0_0_0; // sha512sig0
else if (Rs2D == 5'b00111) BMUControlsD = `BMUCTRLW'b000_1000_1001_1_0_0_1_0_0_0_0_0; // sha512sig1
else if (Rs2D == 5'b00100) BMUControlsD = `BMUCTRLW'b000_1000_1010_1_0_0_1_0_0_0_0_0; // sha512sum0
else if (Rs2D == 5'b00101) BMUControlsD = `BMUCTRLW'b000_1000_1011_1_0_0_1_0_0_0_0_0; // sha512sum1
if (Rs2D == 5'b00110) BMUControlsD = `BMUCTRLW'b000_1000_1000_1_0_0_0_1_0_0_0_0_0; // sha512sig0
else if (Rs2D == 5'b00111) BMUControlsD = `BMUCTRLW'b000_1000_1001_1_0_0_0_1_0_0_0_0_0; // sha512sig1
else if (Rs2D == 5'b00100) BMUControlsD = `BMUCTRLW'b000_1000_1010_1_0_0_0_1_0_0_0_0_0; // sha512sum0
else if (Rs2D == 5'b00101) BMUControlsD = `BMUCTRLW'b000_1000_1011_1_0_0_0_1_0_0_0_0_0; // sha512sum1
endcase
end
end
// Unpack Control Signals
assign {BALUSelectD, BSelectD, ZBBSelectD, BRegWriteD,BALUSrcBD, BW64D, BALUOpD, BSubArithD, RotateD, MaskD, PreShiftD, IllegalBitmanipInstrD} = BMUControlsD;
assign {BALUSelectD, BSelectD, ZBBSelectD, BRegWriteD,BALUSrcBD, BW64D, BUW64D, BALUOpD, BSubArithD, RotateD, MaskD, PreShiftD, IllegalBitmanipInstrD} = BMUControlsD;
// Pack BALUControl Signals
assign BALUControlD = {RotateD, MaskD, PreShiftD};

View File

@ -56,7 +56,7 @@ module controller import cvw::*; #(parameter cvw_t P) (
output logic [2:0] Funct3E, // Instruction's funct3 field
output logic [6:0] Funct7E, // Instruction's funct7 field
output logic IntDivE, // Integer divide
output logic W64E, // RV64 W-type operation
output logic W64E, UW64E, // RV64 W/.uw-type operation
output logic SubArithE, // Subtraction or arithmetic shift
output logic JumpE, // jump instruction
output logic BranchE, // Branch instruction
@ -158,6 +158,7 @@ module controller import cvw::*; #(parameter cvw_t P) (
logic MatchDE; // Match between a source register in Decode stage and destination register in Execute stage
logic FCvtIntStallD, MDUStallD, CSRRdStallD; // Stall due to conversion, load, multiply/divide, CSR read
logic FunctCZeroD; // Funct7 and Funct3 indicate czero.* (not including Op check)
logic BUW64D; // Indiciates if it is a .uw type B instruction in Decode Stage
// Extract fields
assign OpD = InstrD[6:0];
@ -326,7 +327,7 @@ module controller import cvw::*; #(parameter cvw_t P) (
logic BALUSrcBD; // BMU alu src select signal
bmuctrl #(P) bmuctrl(.clk, .reset, .InstrD, .ALUOpD,
.BRegWriteD, .BALUSrcBD, .BW64D, .BSubArithD, .IllegalBitmanipInstrD, .StallE, .FlushE,
.BRegWriteD, .BALUSrcBD, .BW64D, .BUW64D, .BSubArithD, .IllegalBitmanipInstrD, .StallE, .FlushE,
.ALUSelectD(PreALUSelectD), .BSelectE, .ZBBSelectE, .BALUControlE, .BMUActiveE);
if (P.ZBA_SUPPORTED) begin
// ALU Decoding is more comprehensive when ZBA is supported. slt and slti conflicts with sh1add, sh1add.uw
@ -350,6 +351,7 @@ module controller import cvw::*; #(parameter cvw_t P) (
assign W64D = BaseW64D;
assign ALUSrcBD = BaseALUSrcBD;
assign SubArithD = BaseSubArithD; // TRUE If B-type or R-type instruction involves inverted operand
assign BUW64D = 1'b0; // no .uw instructions
// tie off unused bit manipulation signals
assign BSelectE = 4'b0000;
@ -417,9 +419,9 @@ module controller import cvw::*; #(parameter cvw_t P) (
flopenrc #(1) controlregD(clk, reset, FlushD, ~StallD, 1'b1, InstrValidD);
// Execute stage pipeline control register and logic
flopenrc #(44) controlregE(clk, reset, FlushE, ~StallE,
{ALUSelectD, RegWriteD, ResultSrcD, MemRWD, JumpD, BranchD, ALUSrcAD, ALUSrcBD, ALUResultSrcD, CSRReadD, CSRWriteD, PrivilegedD, Funct3D, Funct7D, W64D, SubArithD, MDUD, AtomicD, InvalidateICacheD, FlushDCacheD, FenceD, CMOpD, IFUPrefetchD, LSUPrefetchD, CZeroD, InstrValidD},
{ALUSelectE, IEURegWriteE, ResultSrcE, MemRWE, JumpE, BranchE, ALUSrcAE, ALUSrcBE, ALUResultSrcE, CSRReadE, CSRWriteE, PrivilegedE, Funct3E, Funct7E, W64E, SubArithE, MDUE, AtomicE, InvalidateICacheE, FlushDCacheE, FenceE, CMOpE, IFUPrefetchE, LSUPrefetchE, CZeroE, InstrValidE});
flopenrc #(45) controlregE(clk, reset, FlushE, ~StallE,
{ALUSelectD, RegWriteD, ResultSrcD, MemRWD, JumpD, BranchD, ALUSrcAD, ALUSrcBD, ALUResultSrcD, CSRReadD, CSRWriteD, PrivilegedD, Funct3D, Funct7D, W64D, BUW64D, SubArithD, MDUD, AtomicD, InvalidateICacheD, FlushDCacheD, FenceD, CMOpD, IFUPrefetchD, LSUPrefetchD, CZeroD, InstrValidD},
{ALUSelectE, IEURegWriteE, ResultSrcE, MemRWE, JumpE, BranchE, ALUSrcAE, ALUSrcBE, ALUResultSrcE, CSRReadE, CSRWriteE, PrivilegedE, Funct3E, Funct7E, W64E, UW64E, SubArithE, MDUE, AtomicE, InvalidateICacheE, FlushDCacheE, FenceE, CMOpE, IFUPrefetchE, LSUPrefetchE, CZeroE, InstrValidE});
flopenrc #(5) Rs1EReg(clk, reset, FlushE, ~StallE, Rs1D, Rs1E);
flopenrc #(5) Rs2EReg(clk, reset, FlushE, ~StallE, Rs2D, Rs2E);
flopenrc #(5) RdEReg(clk, reset, FlushE, ~StallE, RdD, RdE);

View File

@ -41,7 +41,7 @@ module datapath import cvw::*; #(parameter cvw_t P) (
input logic [6:0] Funct7E, // Funct7 field of instruction in Execute stage
input logic StallE, FlushE, // Stall, flush Execute stage
input logic [1:0] ForwardAE, ForwardBE, // Forward ALU operands from later stages
input logic W64E, // W64-type instruction
input logic W64E,UW64E, // W64/.uw-type instruction
input logic SubArithE, // Subtraction or arithmetic shift
input logic ALUSrcAE, ALUSrcBE, // ALU operands
input logic ALUResultSrcE, // Selects result to pass on to Memory stage
@ -109,7 +109,7 @@ module datapath import cvw::*; #(parameter cvw_t P) (
comparator #(P.XLEN) comp(ForwardedSrcAE, ForwardedSrcBE, BranchSignedE, FlagsE);
mux2 #(P.XLEN) srcamux(ForwardedSrcAE, PCE, ALUSrcAE, SrcAE);
mux2 #(P.XLEN) srcbmux(ForwardedSrcBE, ImmExtE, ALUSrcBE, SrcBE);
alu #(P) alu(SrcAE, SrcBE, W64E, SubArithE, ALUSelectE, BSelectE, ZBBSelectE, Funct3E, Funct7E, Rs2E, BALUControlE, BMUActiveE, CZeroE, ALUResultE, IEUAdrE);
alu #(P) alu(SrcAE, SrcBE, W64E, UW64E, SubArithE, ALUSelectE, BSelectE, ZBBSelectE, Funct3E, Funct7E, Rs2E, BALUControlE, BMUActiveE, CZeroE, ALUResultE, IEUAdrE);
mux2 #(P.XLEN) altresultmux(ImmExtE, PCLinkE, JumpE, AltResultE);
mux2 #(P.XLEN) ieuresultmux(ALUResultE, AltResultE, ALUResultSrcE, IEUResultE);

View File

@ -93,6 +93,7 @@ module ieu import cvw::*; #(parameter cvw_t P) (
logic [3:0] ZBBSelectE; // ZBB Result Select Signal in Execute Stage
logic [2:0] BALUControlE; // ALU Control signals for B instructions in Execute Stage
logic SubArithE; // Subtraction or arithmetic shift
logic UW64E; // .uw-type instruction
logic [6:0] Funct7E;
@ -111,7 +112,7 @@ module ieu import cvw::*; #(parameter cvw_t P) (
.StructuralStallD, .LoadStallD, .StoreStallD, .Rs1D, .Rs2D, .Rs2E,
.StallE, .FlushE, .FlagsE, .FWriteIntE,
.PCSrcE, .ALUSrcAE, .ALUSrcBE, .ALUResultSrcE, .ALUSelectE,
.Funct3E, .Funct7E, .IntDivE, .W64E, .SubArithE, .BranchD, .BranchE, .JumpD, .JumpE,
.Funct3E, .Funct7E, .IntDivE, .W64E, .UW64E, .SubArithE, .BranchD, .BranchE, .JumpD, .JumpE,
.BranchSignedE, .BSelectE, .ZBBSelectE, .BALUControlE, .BMUActiveE, .CZeroE, .MDUActiveE,
.FCvtIntE, .ForwardAE, .ForwardBE, .CMOpM, .IFUPrefetchE, .LSUPrefetchM,
.StallM, .FlushM, .MemRWE, .MemRWM, .CSRReadM, .CSRWriteM, .PrivilegedM, .AtomicM, .Funct3M,
@ -120,7 +121,7 @@ module ieu import cvw::*; #(parameter cvw_t P) (
.RdW, .RdE, .RdM);
datapath #(P) dp(
.clk, .reset, .ImmSrcD, .InstrD, .Rs1D, .Rs2D, .Rs2E, .StallE, .FlushE, .ForwardAE, .ForwardBE, .W64E, .SubArithE,
.clk, .reset, .ImmSrcD, .InstrD, .Rs1D, .Rs2D, .Rs2E, .StallE, .FlushE, .ForwardAE, .ForwardBE, .W64E, .UW64E, .SubArithE,
.Funct3E, .Funct7E, .ALUSrcAE, .ALUSrcBE, .ALUResultSrcE, .ALUSelectE, .JumpE, .BranchSignedE,
.PCE, .PCLinkE, .FlagsE, .IEUAdrE, .ForwardedSrcAE, .ForwardedSrcBE, .BSelectE, .ZBBSelectE, .BALUControlE, .BMUActiveE, .CZeroE,
.StallM, .FlushM, .FWriteIntM, .FIntResM, .SrcAM, .WriteDataM, .FCvtIntW,

View File

@ -32,13 +32,15 @@ module decompress import cvw::*; #(parameter cvw_t P) (
output logic [31:0] InstrD, // Decompressed instruction
output logic IllegalCompInstrD // Invalid decompressed instruction
);
logic [32:0] LInstrD; // decompressed instruction with illegal flag in [32]
logic [15:0] instr16;
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 [19:0] immCJ, immCILUI;
logic [5:0] immSH;
logic [1:0] op;
logic LegalCompInstrD;
// Extract op and register source/destination fields
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 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 immCILUI = {{15{instr16[12]}}, instr16[6:2]};
assign immCIASP = {{3{instr16[12]}}, instr16[4:3], instr16[5], instr16[2], instr16[6], 4'b0000};
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}; // c.addi16sp
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
// 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
if (op == 2'b11) begin // noncompressed instruction
InstrD = InstrRawD;
IllegalCompInstrD = '0;
LInstrD = {1'b1, InstrRawD};
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]})
5'b00000: if (immCIW != 0) InstrD = {immCIW, 5'b00010, 3'b000, rdp, 7'b0010011}; // c.addi4spn
else begin // illegal instruction
IllegalCompInstrD = 1'b1;
InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap
end
5'b00001: if (P.ZCD_SUPPORTED)
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'b00000: if (immCIW != 0) LInstrD = {1'b1, immCIW, 5'b00010, 3'b000, rdp, 7'b0010011}; // c.addi4spn
5'b00001: if (P.ZCD_SUPPORTED) LInstrD = {1'b1, immCLD, rs1p, 3'b011, rdp, 7'b0000111}; // c.fld
5'b00010: LInstrD = {1'b1, immCL, rs1p, 3'b010, rdp, 7'b0000011}; // c.lw
5'b00011: if (P.XLEN==32) begin
if (P.ZCF_SUPPORTED) LInstrD = {1'b1, immCL, rs1p, 3'b010, rdp, 7'b0000111}; // c.flw
end else LInstrD = {1'b1, immCLD, rs1p, 3'b011, rdp, 7'b0000011}; // c.ld
5'b00100: if (P.ZCB_SUPPORTED)
if (instr16[12:10] == 3'b000)
InstrD = {10'b0, instr16[5], instr16[6], rs1p, 3'b100, rdp, 7'b0000011}; // c.lbu
if (instr16[12:10] == 3'b000) LInstrD = {1'b1, 10'b0, instr16[5], instr16[6], rs1p, 3'b100, rdp, 7'b0000011}; // c.lbu
else if (instr16[12:10] == 3'b001) begin
if (instr16[6])
InstrD = {10'b0, instr16[5], 1'b0, rs1p, 3'b001, rdp, 7'b0000011}; // c.lh
else
InstrD = {10'b0, instr16[5], 1'b0, rs1p, 3'b101, rdp, 7'b0000011}; // c.lhu
if (instr16[6]) LInstrD = {1'b1, 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
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)
InstrD = {7'b0, rs2p, rs1p, 3'b001, 3'b000, instr16[5], 1'b0, 7'b0100011}; // c.sh
else begin
IllegalCompInstrD = 1'b1;
InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap
end
else begin
IllegalCompInstrD = 1'b1;
InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap
end
5'b00101: if (P.ZCD_SUPPORTED)
InstrD = {immCSD[11:5], rs2p, rs1p, 3'b011, immCSD[4:0], 7'b0100111}; // c.fsd
else begin // unsupported instruction
IllegalCompInstrD = 1'b1;
InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap
end
5'b00110: InstrD = {immCS[11:5], rs2p, rs1p, 3'b010, immCS[4:0], 7'b0100011}; // c.sw
5'b00111: if (P.XLEN==32)
if (P.ZCF_SUPPORTED)
InstrD = {immCS[11:5], rs2p, rs1p, 3'b010, immCS[4:0], 7'b0100111}; // c.fsw
else begin
IllegalCompInstrD = 1'b1;
InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap
end
else
InstrD = {immCSD[11:5], rs2p, rs1p, 3'b011, immCSD[4:0], 7'b0100011}; //c.sd
5'b01000: InstrD = {immCI, rds1, 3'b000, rds1, 7'b0010011}; // c.addi
5'b01001: if (P.XLEN==32)
InstrD = {immCJ, 5'b00001, 7'b1101111}; // c.jal
else
InstrD = {immCI, rds1, 3'b000, rds1, 7'b0011011}; // c.addiw
5'b01010: InstrD = {immCI, 5'b00000, 3'b000, rds1, 7'b0010011}; // c.li
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)
LInstrD = {1'b1, 7'b0, rs2p, rs1p, 3'b001, 3'b000, instr16[5], 1'b0, 7'b0100011}; // c.sh
5'b00101: if (P.ZCD_SUPPORTED) LInstrD = {1'b1, immCSD[11:5], rs2p, rs1p, 3'b011, immCSD[4:0], 7'b0100111}; // c.fsd
5'b00110: LInstrD = {1'b1, immCS[11:5], rs2p, rs1p, 3'b010, immCS[4:0], 7'b0100011}; // c.sw
5'b00111: if (P.XLEN==32) begin
if (P.ZCF_SUPPORTED) LInstrD = {1'b1, immCS[11:5], rs2p, rs1p, 3'b010, immCS[4:0], 7'b0100111}; // c.fsw
end else LInstrD = {1'b1, immCSD[11:5], rs2p, rs1p, 3'b011, immCSD[4:0], 7'b0100011}; // c.sd
5'b01000: if (rds1 != 5'b0)
if (immCI[5:0] != 0) LInstrD = {1'b1, immCI, rds1, 3'b000, rds1, 7'b0010011}; // c.addi
else LInstrD = {1'b1, 25'b0, 7'b0010011}; // c.addi with imm = 0 is a HINT, treated as nop
else if (immCI[5:0] == 6'b0) LInstrD = {1'b1, 25'b0, 7'b0010011}; // c.nop = addi x0, x0, 0
else LInstrD = {1'b1, 25'b0, 7'b0010011}; // c.nop with imm != 0 is a HINT, treated as nop
5'b01001: if (P.XLEN==32) LInstrD = {1'b1, immCJ, 5'b00001, 7'b1101111}; // c.jal
else if (rds1 != 5'b0) LInstrD = {1'b1, immCI, rds1, 3'b000, rds1, 7'b0011011}; // c.addiw
5'b01010: if (rds1 != 5'b0) LInstrD = {1'b1, immCI, 5'b00000, 3'b000, rds1, 7'b0010011}; // c.li
else LInstrD = {1'b1, 25'b0, 7'b0010011}; // c.li with rd = 0 is a HINT, treated as nop
5'b01011: if (rds1 == 5'b00010) begin
if (immCIASP[9:4] != 6'b0) LInstrD = {1'b1, immCIASP, rds1, 3'b000, rds1, 7'b0010011}; // c.addi16sp
end else if (immCILUI[5:0] != 0)
if (rds1 != 5'b0) LInstrD = {1'b1, immCILUI, rds1, 7'b0110111}; // c.lui
else LInstrD = {1'b1, 25'b0, 7'b0010011}; // c.lui with rd = 0, imm!=0 is a HINT, treated as nop
5'b01100: if (instr16[11:10] == 2'b00) begin
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 else if (instr16[11:10] == 2'b01) begin
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
end else if (instr16[11:10] == 2'b10) LInstrD = {1'b1, immCI, rds1p, 3'b111, rds1p, 7'b0010011}; // c.andi
else if (instr16[12:10] == 3'b011) begin
if (instr16[6:5] == 2'b00) LInstrD = {1'b1, 7'b0100000, rs2p, rds1p, 3'b000, rds1p, 7'b0110011}; // c.sub
else if (instr16[6:5] == 2'b01) LInstrD = {1'b1, 7'b0000000, rs2p, rds1p, 3'b100, rds1p, 7'b0110011}; // c.xor
else if (instr16[6:5] == 2'b10) LInstrD = {1'b1, 7'b0000000, rs2p, rds1p, 3'b110, rds1p, 7'b0110011}; // c.or
else LInstrD = {1'b1, 7'b0000000, rs2p, rds1p, 3'b111, rds1p, 7'b0110011}; // c.and
end else begin // (instr16[12:10] == 3'b111)
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)
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)
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)
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)
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)
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)
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)
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)
InstrD = {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 else begin // illegal instruction
IllegalCompInstrD = 1'b1;
InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap **/
LInstrD = {1'b1, 7'b0000001, rs2p, rds1p, 3'b000, rds1p, 7'b0110011}; // c.mul
end
5'b01101: InstrD = {immCJ, 5'b00000, 7'b1101111}; // c.j
5'b01110: InstrD = {immCB[11:5], 5'b00000, rs1p, 3'b000, immCB[4:0], 7'b1100011}; // c.beqz
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'b01101: LInstrD = {1'b1, immCJ, 5'b00000, 7'b1101111}; // c.j
5'b01110: LInstrD = {1'b1, immCB[11:5], 5'b00000, rs1p, 3'b000, immCB[4:0], 7'b1100011}; // c.beqz
5'b01111: LInstrD = {1'b1, immCB[11:5], 5'b00000, rs1p, 3'b001, immCB[4:0], 7'b1100011}; // c.bnez
5'b10000: if (rds1 != 5'b0) begin
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
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'b10001: if (P.ZCD_SUPPORTED)
InstrD = {immCILSPD, 5'b00010, 3'b011, rds1, 7'b0000111}; // c.fldsp
else begin // unsupported instruction
IllegalCompInstrD = 1'b1;
InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap
end
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
if (rds1 != 5'b0) LInstrD = {1'b1, immCILSPD, 5'b00010, 3'b011, rds1, 7'b0000111}; // c.fldsp
5'b10010: if (rds1 != 5'b0) LInstrD = {1'b1, immCILSP, 5'b00010, 3'b010, rds1, 7'b0000011}; // c.lwsp
5'b10011: if (P.XLEN == 32) begin
if (P.ZCF_SUPPORTED) LInstrD = {1'b1, immCILSP, 5'b00010, 3'b010, rds1, 7'b0000111}; // c.flwsp
end else if (rds1 != 5'b0) LInstrD = {1'b1, immCILSPD, 5'b00010, 3'b011, rds1, 7'b0000011}; // c.ldsp
5'b10100: if (instr16[12] == 0)
if (instr16[6:2] == 5'b00000)
InstrD = {7'b0000000, 5'b00000, rds1, 3'b000, 5'b00000, 7'b1100111}; // c.jr
else
InstrD = {7'b0000000, rs2, 5'b00000, 3'b000, rds1, 7'b0110011}; // c.mv
if (rs2 == 5'b00000) begin
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
if (rs2 == 5'b00000)
if (rds1 == 5'b00000)
InstrD = {12'b1, 5'b00000, 3'b000, 5'b00000, 7'b1110011}; // c.ebreak
else
InstrD = {12'b0, rds1, 3'b000, 5'b00001, 7'b1100111}; // c.jalr
else
InstrD = {7'b0000000, rs2, rds1, 3'b000, rds1, 7'b0110011}; // c.add
5'b10101: if (P.ZCD_SUPPORTED)
InstrD = {immCSSD[11:5], rs2, 5'b00010, 3'b011, immCSSD[4:0], 7'b0100111}; // c.fsdsp
else begin // unsupported 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
if (rs2 == 5'b00000) begin
if (rds1 == 5'b00000) LInstrD = {1'b1, 12'b1, 5'b00000, 3'b000, 5'b00000, 7'b1110011}; // c.ebreak
else if (rds1 != 5'b0) LInstrD = {1'b1, 12'b0, rds1, 3'b000, 5'b00001, 7'b1100111}; // c.jalr
end else
if (rds1 != 0) LInstrD = {1'b1, 7'b0000000, rs2, rds1, 3'b000, rds1, 7'b0110011}; // c.add
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
5'b10101: if (P.ZCD_SUPPORTED) LInstrD = {1'b1, immCSSD[11:5], rs2, 5'b00010, 3'b011, immCSSD[4:0], 7'b0100111}; // c.fsdsp
5'b10110: LInstrD = {1'b1, immCSS[11:5], rs2, 5'b00010, 3'b010, immCSS[4:0], 7'b0100011}; // c.swsp
5'b10111: if (P.XLEN==32) begin
if (P.ZCF_SUPPORTED) LInstrD = {1'b1, immCSS[11:5], rs2, 5'b00010, 3'b010, immCSS[4:0], 7'b0100111}; // c.fswsp
end else LInstrD = {1'b1, immCSSD[11:5], rs2, 5'b00010, 3'b011, immCSSD[4:0], 7'b0100011}; // c.sdsp
default: ; // illegal instruction
endcase
end
// extract instruction and illegal from LInstrD
assign {LegalCompInstrD, InstrD} = LInstrD;
assign IllegalCompInstrD = ~LegalCompInstrD;
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] MSCRATCH_REGW, MTVAL_REGW, MCAUSE_REGW;
logic [P.XLEN-1:0] MENVCFGH_REGW;
logic [P.XLEN-1:0] TVECWriteValM;
logic WriteMTVECM, WriteMEDELEGM, WriteMIDELEGM;
logic WriteMSCRATCHM, WriteMEPCM, WriteMCAUSEM, WriteMTVALM;
logic WriteMCOUNTERENM, WriteMCOUNTINHIBITM;
@ -105,7 +106,10 @@ module csrm import cvw::*; #(parameter cvw_t P) (
genvar i;
if (P.PMP_ENTRIES > 0) begin:pmp
logic [P.PMP_ENTRIES-1:0] WritePMPCFGM;
logic [P.PMP_ENTRIES-1:0] WritePMPADDRM ;
logic [P.PMP_ENTRIES-1:0] WritePMPADDRM;
logic [7:0] CSRPMPWriteValM[P.PMP_ENTRIES-1:0];
logic [7:0] CSRPMPLegalizedWriteValM[P.PMP_ENTRIES-1:0];
logic [1:0] CSRPMPWRLegalizedWriteValM[P.PMP_ENTRIES-1:0];
logic [P.PMP_ENTRIES-1:0] ADDRLocked, CFGLocked;
for(i=0; i<P.PMP_ENTRIES; i++) begin
// 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]);
if (P.XLEN==64) begin
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
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
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
@ -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);
// 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
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);

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] SENVCFG_WriteValM;
logic [P.XLEN-1:0] TVECWriteValM;
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);
// 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) 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);

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

@ -42,7 +42,8 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
output logic SPIOut,
input logic SPIIn,
output logic [3:0] SPICS,
output logic SPIIntr
output logic SPIIntr,
output logic SPICLK
);
// register map
@ -99,7 +100,7 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
rsrstatetype ReceiveState;
// Transmission signals
logic sck;
// logic sck;
logic [11:0] DivCounter; // Counter for sck
logic SCLKenable; // Flip flop enable high every sclk edge
@ -147,6 +148,7 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
// APB access
assign Entry = {PADDR[7:2],2'b00}; // 32-bit word-aligned accesses
assign Memwrite = PWRITE & PENABLE & PSEL; // Only write in access phase
// JACOB: This shouldn't behave this way
assign PREADY = TransmitInactive; // Tie PREADY to transmission for hardware interlock
// Account for subword read/write circuitry
@ -358,29 +360,32 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
assign DelayMode = SckMode[0] ? (state == DELAY_1) : (state == ACTIVE_1 & ReceiveShiftFull);
assign ChipSelectInternal = (state == CS_INACTIVE | state == INTER_CS | DelayMode & ~|(Delay0[15:8])) ? ChipSelectDef : ~ChipSelectDef;
assign sck = (state == ACTIVE_0) ? ~SckMode[1] : SckMode[1];
assign SPICLK = (state == ACTIVE_0) ? ~SckMode[1] : SckMode[1];
assign Active = (state == ACTIVE_0 | state == ACTIVE_1);
assign SampleEdge = SckMode[0] ? (state == ACTIVE_1) : (state == ACTIVE_0);
assign ZeroDelayHoldMode = ((ChipSelectMode == 2'b10) & (~|(Delay1[7:4])));
assign TransmitInactive = ((state == INTER_CS) | (state == CS_INACTIVE) | (state == INTER_XFR) | (ReceiveShiftFullDelayPCLK & ZeroDelayHoldMode));
assign Active0 = (state == ACTIVE_0);
// Signal tracks which edge of sck to shift data
// Signal tracks which edge of sck to shift data
// Jacob: We need to confirm that this represents the actual polarity and phase options for sampling.
// The first option now samples on the leading edge and shifts on the falling edge like it's supposed to.
// We need to confirm the validity of the other options.
always_comb
case(SckMode[1:0])
2'b00: ShiftEdge = ~sck & SCLKenable;
2'b01: ShiftEdge = (sck & |(FrameCount) & SCLKenable);
2'b10: ShiftEdge = sck & SCLKenable;
2'b11: ShiftEdge = (~sck & |(FrameCount) & SCLKenable);
default: ShiftEdge = sck & SCLKenable;
2'b00: ShiftEdge = SPICLK & SCLKenable;
2'b01: ShiftEdge = (SPICLK & |(FrameCount) & SCLKenable); // Probably wrong
2'b10: ShiftEdge = ~SPICLK & SCLKenable; // Probably wrong
2'b11: ShiftEdge = (~SPICLK & |(FrameCount) & SCLKenable); // Probably wrong
default: ShiftEdge = SPICLK & SCLKenable;
endcase
// Transmit shift register
assign TransmitDataEndian = Format[0] ? {TransmitFIFOReadData[0], TransmitFIFOReadData[1], TransmitFIFOReadData[2], TransmitFIFOReadData[3], TransmitFIFOReadData[4], TransmitFIFOReadData[5], TransmitFIFOReadData[6], TransmitFIFOReadData[7]} : TransmitFIFOReadData[7:0];
always_ff @(posedge PCLK)
if(~PRESETn) TransmitShiftReg <= 8'b0;
if(~PRESETn) TransmitShiftReg <= 8'b0; // Temporarily changing to 1s
else if (TransmitShiftRegLoad) TransmitShiftReg <= TransmitDataEndian;
else if (ShiftEdge & Active) TransmitShiftReg <= {TransmitShiftReg[6:0], 1'b0};
else if (ShiftEdge & Active) TransmitShiftReg <= {TransmitShiftReg[6:0], TransmitShiftReg[0]}; // Temporarily changing to 1s
assign SPIOut = TransmitShiftReg[7];

View File

@ -46,7 +46,6 @@ module uncore import cvw::*; #(parameter cvw_t P)(
output logic [P.AHBW-1:0] HRDATA,
output logic HREADY, HRESP,
output logic HSELEXT,
output logic HSELEXTSDC,
// peripheral pins
output logic MTimerInt, MSwInt, // Timer and software interrupts from CLINT
output logic MExtInt, SExtInt, // External interrupts from PLIC
@ -55,16 +54,20 @@ module uncore import cvw::*; #(parameter cvw_t P)(
output logic [31:0] GPIOOUT, GPIOEN, // GPIO pin output value and enable
input logic UARTSin, // UART serial input
output logic UARTSout, // UART serial output
input logic SDCIntr,
input logic SPIIn,
output logic SPIOut,
output logic [3:0] SPICS
output logic [3:0] SPICS,
output logic SPICLK,
input logic SDCIn,
output logic SDCCmd,
output logic [3:0] SDCCS,
output logic SDCCLK
);
logic [P.XLEN-1:0] HREADRam, HREADSDC;
logic [11:0] HSELRegions;
logic HSELDTIM, HSELIROM, HSELRam, HSELCLINT, HSELPLIC, HSELGPIO, HSELUART, HSELSPI;
logic HSELDTIM, HSELIROM, HSELRam, HSELCLINT, HSELPLIC, HSELGPIO, HSELUART,HSELSDC, HSELSPI;
logic HSELDTIMD, HSELIROMD, HSELEXTD, HSELRamD, HSELCLINTD, HSELPLICD, HSELGPIOD, HSELUARTD, HSELSDCD, HSELSPID;
logic HRESPRam, HRESPSDC;
logic HREADYRam, HRESPSDCD;
@ -75,18 +78,18 @@ module uncore import cvw::*; #(parameter cvw_t P)(
logic SDCIntM;
logic PCLK, PRESETn, PWRITE, PENABLE;
logic [4:0] PSEL;
logic [5:0] PSEL;
logic [31:0] PADDR;
logic [P.XLEN-1:0] PWDATA;
logic [P.XLEN/8-1:0] PSTRB;
/* verilator lint_off UNDRIVEN */ // undriven in rv32e configuration
logic [4:0] PREADY;
logic [4:0][P.XLEN-1:0] PRDATA;
logic [5:0] PREADY;
logic [5:0][P.XLEN-1:0] PRDATA;
/* verilator lint_on UNDRIVEN */
logic [P.XLEN-1:0] HREADBRIDGE;
logic HRESPBRIDGE, HREADYBRIDGE, HSELBRIDGE, HSELBRIDGED;
(* mark_debug = "true" *) logic HSELEXTSDCD;
/* SDC Interrupt (SPI Controller) */
logic SDCIntr;
// Determine which region of physical memory (if any) is being accessed
@ -95,14 +98,14 @@ module uncore import cvw::*; #(parameter cvw_t P)(
adrdecs #(P) adrdecs(HADDR, 1'b1, 1'b1, 1'b1, HSIZE[1:0], HSELRegions);
// unswizzle HSEL signals
assign {HSELSPI, HSELEXTSDC, HSELPLIC, HSELUART, HSELGPIO, HSELCLINT, HSELRam, HSELBootRom, HSELEXT, HSELIROM, HSELDTIM} = HSELRegions[11:1];
assign {HSELSPI, HSELSDC, HSELPLIC, HSELUART, HSELGPIO, HSELCLINT, HSELRam, HSELBootRom, HSELEXT, HSELIROM, HSELDTIM} = HSELRegions[11:1];
// AHB -> APB bridge
ahbapbbridge #(P, 5) ahbapbbridge (
.HCLK, .HRESETn, .HSEL({HSELSPI, HSELUART, HSELPLIC, HSELCLINT, HSELGPIO}), .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HTRANS, .HREADY,
ahbapbbridge #(P, 6) ahbapbbridge (
.HCLK, .HRESETn, .HSEL({HSELSDC, HSELSPI, HSELUART, HSELPLIC, HSELCLINT, HSELGPIO}), .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HTRANS, .HREADY,
.HRDATA(HREADBRIDGE), .HRESP(HRESPBRIDGE), .HREADYOUT(HREADYBRIDGE),
.PCLK, .PRESETn, .PSEL, .PWRITE, .PENABLE, .PADDR, .PWDATA, .PSTRB, .PREADY, .PRDATA);
assign HSELBRIDGE = HSELGPIO | HSELCLINT | HSELPLIC | HSELUART | HSELSPI; // if any of the bridge signals are selected
assign HSELBRIDGE = HSELGPIO | HSELCLINT | HSELPLIC | HSELUART | HSELSPI | HSELSDC; // if any of the bridge signals are selected
// on-chip RAM
if (P.UNCORE_RAM_SUPPORTED) begin : ram
@ -142,6 +145,7 @@ module uncore import cvw::*; #(parameter cvw_t P)(
end else begin : gpio
assign GPIOOUT = '0; assign GPIOEN = '0; assign GPIOIntr = 1'b0;
end
if (P.UART_SUPPORTED == 1) begin : uartgen // Hack to work around Verilator bug https://github.com/verilator/verilator/issues/4769
uart_apb #(P) uart(
.PCLK, .PRESETn, .PSEL(PSEL[3]), .PADDR(PADDR[2:0]), .PWDATA, .PSTRB, .PWRITE, .PENABLE,
@ -152,28 +156,39 @@ module uncore import cvw::*; #(parameter cvw_t P)(
end else begin : uart
assign UARTSout = 1'b0; assign UARTIntr = 1'b0;
end
if (P.SPI_SUPPORTED == 1) begin : spi
spi_apb #(P) spi (
.PCLK, .PRESETn, .PSEL(PSEL[4]), .PADDR(PADDR[7:0]), .PWDATA, .PSTRB, .PWRITE, .PENABLE,
.PREADY(PREADY[4]), .PRDATA(PRDATA[4]),
.SPIOut, .SPIIn, .SPICS, .SPIIntr);
.SPIOut, .SPIIn, .SPICS, .SPICLK, .SPIIntr);
end else begin : spi
assign SPIOut = 1'b0; assign SPICS = '0; assign SPIIntr = 1'b0;
assign SPIOut = 1'b0; assign SPICS = '0; assign SPIIntr = 1'b0; assign SPICLK = 1'b0;
end
if (P.SDC_SUPPORTED == 1) begin : sdc
spi_apb #(P) sdc(
.PCLK, .PRESETn, .PSEL(PSEL[5]), .PADDR(PADDR[7:0]), .PWDATA, .PSTRB, .PWRITE, .PENABLE,
.PREADY(PREADY[5]), .PRDATA(PRDATA[5]),
.SPIOut(SDCCmd), .SPIIn(SDCIn), .SPICS(SDCCS), .SPICLK(SDCCLK), .SPIIntr(SDCIntr));
end else begin : sdc
assign SDCCmd = '0; assign SDCCS = 4'b0; assign SDCIntr = 1'b0; assign SDCCLK = 1'b0;
end
// AHB Read Multiplexer
assign HRDATA = ({P.XLEN{HSELRamD}} & HREADRam) |
({P.XLEN{HSELEXTD | HSELEXTSDCD}} & HRDATAEXT) |
({P.XLEN{HSELEXTD}} & HRDATAEXT) |
({P.XLEN{HSELBRIDGED}} & HREADBRIDGE) |
({P.XLEN{HSELBootRomD}} & HREADBootRom);
assign HRESP = HSELRamD & HRESPRam |
(HSELEXTD | HSELEXTSDCD) & HRESPEXT |
HSELEXTD & HRESPEXT |
HSELBRIDGE & HRESPBRIDGE |
HSELBootRomD & HRESPBootRom;
assign HREADY = HSELRamD & HREADYRam |
(HSELEXTD | HSELEXTSDCD) & HREADYEXT |
HSELEXTD & HREADYEXT |
HSELBRIDGED & HREADYBRIDGE |
HSELBootRomD & HREADYBootRom |
HSELNoneD; // don't lock up the bus if no region is being accessed
@ -184,7 +199,7 @@ module uncore import cvw::*; #(parameter cvw_t P)(
// device is ready. Hense this register must be selectively enabled by HREADY.
// However on reset None must be seleted.
flopenl #(12) hseldelayreg(HCLK, ~HRESETn, HREADY, HSELRegions, 12'b1,
{HSELSPID, HSELEXTSDCD, HSELPLICD, HSELUARTD, HSELGPIOD, HSELCLINTD,
{HSELSPID, HSELSDCD, HSELPLICD, HSELUARTD, HSELGPIOD, HSELCLINTD,
HSELRamD, HSELBootRomD, HSELEXTD, HSELIROMD, HSELDTIMD, HSELNoneD});
flopenr #(1) hselbridgedelayreg(HCLK, ~HRESETn, HREADY, HSELBRIDGE, HSELBRIDGED);
endmodule

View File

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

View File

@ -32,10 +32,11 @@ module wallypipelinedsoc import cvw::*; #(parameter cvw_t P) (
input logic reset_ext, // external asynchronous reset pin
output logic reset, // reset synchronized to clk to prevent races on release
// AHB Interface
input logic [P.AHBW-1:0] HRDATAEXT,
input logic [P.AHBW-1:0] HRDATAEXT,
input logic HREADYEXT, HRESPEXT,
output logic HSELEXT,
output logic HSELEXTSDC,
// fpga debug signals
input logic ExternalStall,
// outputs to external memory, shared with uncore memory
output logic HCLK, HRESETn,
output logic [P.PA_BITS-1:0] HADDR,
@ -55,10 +56,14 @@ module wallypipelinedsoc import cvw::*; #(parameter cvw_t P) (
output logic [31:0] GPIOEN, // output enables for GPIO
input logic UARTSin, // UART serial data input
output logic UARTSout, // UART serial data output
input logic SDCIntr,
input logic SPIIn, // SPI pins in
output logic SPIOut, // SPI pins out
output logic [3:0] SPICS // SPI chip select pins
output logic [3:0] SPICS, // SPI chip select pins
output logic SPICLK, // SPI clock
input logic SDCIn, // SDC DATA[0] to SPI DI
output logic SDCCmd, // SDC CMD from SPI DO
output logic [3:0] SDCCS, // SDC Card Detect from SPI CS
output logic SDCCLK // SDC Clock from SPI Clock
);
// Uncore signals
@ -75,19 +80,20 @@ module wallypipelinedsoc import cvw::*; #(parameter cvw_t P) (
wallypipelinedcore #(P) core(.clk, .reset,
.MTimerInt, .MExtInt, .SExtInt, .MSwInt, .MTIME_CLINT,
.HRDATA, .HREADY, .HRESP, .HCLK, .HRESETn, .HADDR, .HWDATA, .HWSTRB,
.HWRITE, .HSIZE, .HBURST, .HPROT, .HTRANS, .HMASTLOCK
.HWRITE, .HSIZE, .HBURST, .HPROT, .HTRANS, .HMASTLOCK, .ExternalStall
);
// instantiate uncore if a bus interface exists
if (P.BUS_SUPPORTED) begin : uncoregen // Hack to work around Verilator bug https://github.com/verilator/verilator/issues/4769
uncore #(P) uncore(.HCLK, .HRESETn, .TIMECLK,
.HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT, .HTRANS, .HMASTLOCK, .HRDATAEXT,
.HREADYEXT, .HRESPEXT, .HRDATA, .HREADY, .HRESP, .HSELEXT, .HSELEXTSDC,
.HREADYEXT, .HRESPEXT, .HRDATA, .HREADY, .HRESP, .HSELEXT,
.MTimerInt, .MSwInt, .MExtInt, .SExtInt, .GPIOIN, .GPIOOUT, .GPIOEN, .UARTSin,
.UARTSout, .MTIME_CLINT, .SDCIntr, .SPIIn, .SPIOut, .SPICS);
.UARTSout, .MTIME_CLINT, .SPIIn, .SPIOut, .SPICS, .SPICLK, .SDCIn, .SDCCmd, .SDCCS, .SDCCLK);
end else begin
assign {HRDATA, HREADY, HRESP, HSELEXT, HSELEXTSDC, MTimerInt, MSwInt, MExtInt, SExtInt,
MTIME_CLINT, GPIOOUT, GPIOEN, UARTSout, SPIOut, SPICS} = '0;
assign {HRDATA, HREADY, HRESP, HSELEXT, MTimerInt, MSwInt, MExtInt, SExtInt,
MTIME_CLINT, GPIOOUT, GPIOEN, UARTSout, SPIOut, SPICS, SPICLK, SDCCmd, SDCCS, SDCCLK} = '0;
end
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.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.ZICCLSM_SUPPORTED == 0) | (P.DCACHE_SUPPORTED == 1)) else $fatal(1, "ZICCLSM requires DCACHE_SUPPORTED");
end
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
// and gate on ~FlushW.
assign valid = InstrValidW & ~StallW;
assign valid = InstrValidW & ~StallW & ~reset;
assign rvvi.clk = clk;
assign rvvi.valid[0][0] = valid;
assign rvvi.order[0][0] = CSRArray[12'hB02]; // TODO: IMPERAS Should be event order

View File

@ -33,6 +33,11 @@
`include "idv/idv.svh"
`endif
`ifdef RVVI_COVERAGE
`include "RISCV_trace_data.svh"
`include "rvvicov.svh"
`include "wrapper.sv"
`endif
import cvw::*;
@ -44,6 +49,7 @@ module testbench;
parameter BPRED_LOGGER=0;
parameter I_CACHE_ADDR_LOGGER=0;
parameter D_CACHE_ADDR_LOGGER=0;
parameter RVVI_SYNTH_SUPPORTED=0;
`ifdef USE_IMPERAS_DV
import idvPkg::*;
@ -76,8 +82,7 @@ module testbench;
// DUT signals
logic [P.AHBW-1:0] HRDATAEXT;
logic HREADYEXT, HRESPEXT;
logic HSELEXTSDC;
logic HREADYEXT, HRESPEXT;
logic [P.PA_BITS-1:0] HADDR;
logic [P.AHBW-1:0] HWDATA;
logic [P.XLEN/8-1:0] HWSTRB;
@ -93,7 +98,11 @@ module testbench;
logic UARTSin, UARTSout;
logic SPIIn, SPIOut;
logic [3:0] SPICS;
logic SDCIntr;
logic SPICLK;
logic SDCCmd;
logic SDCIn;
logic [3:0] SDCCS;
logic SDCCLK;
logic HREADY;
logic HSELEXT;
@ -114,6 +123,7 @@ module testbench;
logic SelectTest;
logic TestComplete;
logic PrevPCZero;
logic RVVIStall;
initial begin
// look for arguments passed to simulation, or use defaults
@ -371,6 +381,11 @@ module testbench;
uartoutfile = $fopen(uartoutfilename, "w"); // delete UART output file
ProgramAddrMapFile = {RISCV_DIR, "/buildroot/output/images/disassembly/vmlinux.objdump.addr"};
ProgramLabelMapFile = {RISCV_DIR, "/buildroot/output/images/disassembly/vmlinux.objdump.lab"};
end else if(TEST == "fpga") begin
bootmemfilename = {WALLY_DIR, "/fpga/src/boot.mem"};
memfilename = {WALLY_DIR, "/fpga/src/data.mem"};
ProgramAddrMapFile = {WALLY_DIR, "/fpga/zsbl/bin/boot.objdump.addr"};
ProgramLabelMapFile = {WALLY_DIR, "/fpga/zsbl/bin/boot.objdump.lab"};
end else if(ElfFile != "none") begin
elffilename = ElfFile;
memfilename = {ElfFile, ".memfile"};
@ -462,7 +477,7 @@ module testbench;
integer StartIndex;
integer EndIndex;
integer BaseIndex;
integer memFile;
integer memFile, uncoreMemFile;
integer readResult;
if (P.SDC_SUPPORTED) begin
always @(posedge clk) begin
@ -505,8 +520,33 @@ module testbench;
end
readResult = $fread(dut.uncoregen.uncore.ram.ram.memory.ram.RAM, memFile);
$fclose(memFile);
end else
$readmemh(memfilename, dut.uncoregen.uncore.ram.ram.memory.ram.RAM);
end else if (TEST == "fpga") begin
memFile = $fopen(bootmemfilename, "rb");
if (memFile == 0) begin
$display("Error: Could not open file %s", memfilename);
$finish;
end
if (P.BOOTROM_SUPPORTED) begin
readResult = $fread(dut.uncoregen.uncore.bootrom.bootrom.memory.ROM, memFile);
end
$fclose(memFile);
memFile = $fopen(memfilename, "rb");
if (memFile == 0) begin
$display("Error: Could not open file %s", memfilename);
$finish;
end
readResult = $fread(dut.uncoregen.uncore.ram.ram.memory.ram.RAM, memFile);
$fclose(memFile);
end else begin
uncoreMemFile = $fopen(memfilename, "r"); // Is there a better way to test if a file exists?
if (uncoreMemFile == 0) begin
$display("Error: Could not open file %s", memfilename);
$finish;
end else begin
$fclose(uncoreMemFile);
$readmemh(memfilename, dut.uncoregen.uncore.ram.ram.memory.ram.RAM);
end
end
if (TEST == "embench") $display("Read memfile %s", memfilename);
end
if (CopyRAM) begin
@ -576,21 +616,38 @@ module testbench;
assign SDCDat = sd_dat_reg_t ? sd_dat_reg_o : sd_dat_i;
assign SDCDatIn = SDCDat;
-----/\----- EXCLUDED -----/\----- */
assign SDCIntr = 1'b0;
end else begin
assign SDCIntr = 1'b0;
assign SDCIn = 1'b1;
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,
.HCLK, .HRESETn, .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT,
.HTRANS, .HMASTLOCK, .HREADY, .TIMECLK(1'b0), .GPIOIN, .GPIOOUT, .GPIOEN,
.UARTSin, .UARTSout, .SDCIntr, .SPIIn, .SPIOut, .SPICS);
.UARTSin, .UARTSout, .SPIIn, .SPIOut, .SPICS, .SPICLK, .SDCIn, .SDCCmd, .SDCCS, .SDCCLK);
// generate clock to sequence tests
always begin
clk = 1'b1; # 5; clk = 1'b0; # 5;
end
if(RVVI_SYNTH_SUPPORTED) begin : rvvi_synth
localparam MAX_CSRS = 5;
localparam logic [31:0] RVVI_INIT_TIME_OUT = 32'd4;
localparam logic [31:0] RVVI_PACKET_DELAY = 32'd2;
logic [3:0] mii_txd;
logic mii_tx_en, mii_tx_er;
rvvitbwrapper #(P, MAX_CSRS, RVVI_INIT_TIME_OUT, RVVI_PACKET_DELAY)
rvvitbwrapper(.clk, .reset, .RVVIStall, .mii_tx_clk(clk), .mii_txd, .mii_tx_en, .mii_tx_er,
.mii_rx_clk(clk), .mii_rxd('0), .mii_rx_dv('0), .mii_rx_er('0));
end else begin
assign RVVIStall = '0;
end
/*
// Print key info each cycle for debugging
always @(posedge clk) begin
@ -931,6 +988,12 @@ test_pmp_coverage #(P) pmp_inst(clk);
/* verilator lint_on WIDTHTRUNC */
/* verilator lint_on WIDTHEXPAND */
`ifdef RVVI_COVERAGE
rvviTrace #(.XLEN(P.XLEN), .FLEN(P.FLEN)) rvvi();
wallyTracer #(P) wallyTracer(rvvi);
wrapper #(P) wrap(clk);
`endif
endmodule
/* verilator lint_on STMTDLY */

View File

@ -660,7 +660,9 @@ module testbench_fp;
tt0 = $sformatf("%s", Tests[TestNum]);
testname = {pp, tt0};
//$display("Here you are %s", testname);
$display("\n\nRunning %s vectors ", Tests[TestNum]);
// clear the vectors
for(int i=0; i<MAXVECTORS; i++) TestVectors[i] = '1;
$display("\n\nRunning %s vectors ", Tests[TestNum]);
$readmemh(testname, TestVectors);
// set the test index to 0
TestNum = 0;
@ -774,9 +776,9 @@ module testbench_fp;
// Check if the correct answer and result is a NaN
always_comb begin
if (UnitVal === `CVTINTUNIT | UnitVal === `CMPUNIT) begin
// an integer output can't be a NaN
AnsNaN = 1'b0;
ResNaN = 1'b0;
// an integer output can't be a NaN
AnsNaN = 1'b0;
ResNaN = 1'b0;
end
else if (UnitVal === `CVTFPUNIT) begin
case (OpCtrlVal[1:0])
@ -894,11 +896,12 @@ module testbench_fp;
if (reset)
state <= S0;
else
state <= nextstate;
state <= nextstate;
// Increment the vector when Done with each test
if (state == Done)
VectorNum += 1; // increment the vector
if (state == Done) begin
VectorNum += 1; // increment the vector
end
end
@ -982,14 +985,16 @@ module testbench_fp;
$display("TestNum %d VectorNum %d OpCtrl %d", TestNum, VectorNum, OpCtrl[TestNum]);
$display("inputs: %h %h %h\nSrcA: %h\n Res: %h %h\n Expected: %h %h",
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;
end
if (TestVectors[VectorNum][0] === 1'bx & Tests[TestNum] !== "") begin // if reached the eof
if (TestVectors[VectorNum] == '1 & Tests[TestNum] !== "") begin // if reached the eof
// increment the test
TestNum += 1;
// clear the vectors
for(int i=0; i<MAXVECTORS; i++) TestVectors[i] = {P.Q_LEN*4+8{1'bx}};
for(int i=0; i<MAXVECTORS; i++) TestVectors[i] = '1;
// read next files
$readmemh({`PATH, Tests[TestNum]}, TestVectors);
// set the vector index back to 0
@ -999,12 +1004,12 @@ module testbench_fp;
// increment the rounding mode or loop back to rne
if (FrmNum < 4) FrmNum += 1;
else begin
FrmNum = 0;
FrmNum = 0;
// Add some time as a buffer between tests at the end of each test
// (to be removed)
repeat (10)
@(posedge clk);
end
// (to be removed, but as of 7/14/24 breaks Verilator sqrt sim to remove dh)
repeat (10)
@(posedge clk);
end
// if no more Tests - finish
if (Tests[TestNum] === "") begin
$display("\nAll Tests completed with %d errors\n", errors);
@ -1052,9 +1057,9 @@ module readvectors import cvw::*; #(parameter cvw_t P) (
// apply test vectors on rising edge of clk
// Format of vectors Inputs(1/2/3)_AnsFlg
always @(VectorNum) begin
always @(posedge clk) begin
AnsFlg = TestVector[4:0];
//$display("Entering readvectors with VectorNum=%d, TestVector=%x, Unit=%d, Fmt=%d, OpCtrl=%d", VectorNum, TestVector, Unit, Fmt, OpCtrl);
//$display(" Entering readvectors with VectorNum=%d, TestVector=%x, Unit=%d, Fmt=%d, OpCtrl=%d", VectorNum, TestVector, Unit, Fmt, OpCtrl); */
case (Unit)
`FMAUNIT:
case (Fmt)
@ -1076,7 +1081,6 @@ module readvectors import cvw::*; #(parameter cvw_t P) (
X = {{P.Q_LEN-P.D_LEN{1'b1}}, TestVector[8+4*(P.D_LEN)-1:8+3*(P.D_LEN)]};
Y = {{P.Q_LEN-P.D_LEN{1'b1}}, TestVector[8+3*(P.D_LEN)-1:8+2*(P.D_LEN)]};
Z = {{P.Q_LEN-P.D_LEN{1'b1}}, TestVector[8+2*(P.D_LEN)-1:8+P.D_LEN]};
$display("Read %x %x %x", X, Y, Z);
end
else begin
X = {{P.Q_LEN-P.D_LEN{1'b1}}, TestVector[8+3*(P.D_LEN)-1:8+2*(P.D_LEN)]};

View File

@ -32,7 +32,7 @@ module wallywrapper import cvw::*;(
input logic clk,
input logic reset_ext,
input logic SPIIn,
input logic SDCIntr
input logic SDCIn
);
`include "parameter-defs.vh"
@ -56,11 +56,16 @@ module wallywrapper import cvw::*;(
logic UARTSin, UARTSout;
logic SPIOut;
logic [3:0] SPICS;
logic SPICLK;
logic SDCCmd;
logic [3:0] SDCCS;
logic SDCCLK;
logic HREADY;
logic HSELEXT;
logic HSELEXTSDC;
logic ExternalStall;
// instantiate device to be tested
assign GPIOIN = 0;
@ -70,10 +75,11 @@ module wallywrapper import cvw::*;(
assign HRESPEXT = 0;
assign HRDATAEXT = 0;
assign ExternalStall = '0;
wallypipelinedsoc #(P) dut(.clk, .reset_ext, .reset, .HRDATAEXT,.HREADYEXT, .HRESPEXT,.HSELEXT, .HSELEXTSDC,
wallypipelinedsoc #(P) dut(.clk, .reset_ext, .reset, .ExternalStall, .HRDATAEXT,.HREADYEXT, .HRESPEXT,.HSELEXT,
.HCLK, .HRESETn, .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT,
.HTRANS, .HMASTLOCK, .HREADY, .TIMECLK(1'b0), .GPIOIN, .GPIOOUT, .GPIOEN,
.UARTSin, .UARTSout, .SPIIn, .SPIOut, .SPICS, .SDCIntr);
.UARTSin, .UARTSout, .SPIIn, .SPIOut, .SPICS, .SPICLK, .SDCIn, .SDCCmd, .SDCCS, .SDCCLK);
endmodule

View File

@ -4,13 +4,18 @@ work_dir = ./riscof_work
work = ./work
arch_workdir = $(work)/riscv-arch-test
wally_workdir = $(work)/wally-riscv-arch-test
custom_test_dir = ../../addins/cvw-arch-verif/test
submodule_work_dir = ../../addins/cvw-arch-verif/riscof_work
current_dir = $(shell pwd)
#XLEN ?= 64
all: root arch32 wally32 arch32e arch64 wally64
wally-riscv-arch-test: root wally64 wally32
custom: new_test
root:
mkdir -p $(work_dir)
mkdir -p $(work)
@ -47,6 +52,9 @@ wally64:
quad64:
riscof run --work-dir=$(work_dir) --config=config64.ini --suite=$(wally_dir)/riscv-test-suite/rv64i_m/Q/riscv-ctg/tests/ --env=$(wally_dir)/riscv-test-suite/env
new_test:
riscof run --work-dir=$(submodule_work_dir) --config=config64.ini --suite=$(custom_test_dir)/ --env=$(wally_dir)/riscv-test-suite/env --no-browser
#wally32e:
# riscof run --work-dir=$(work_dir) --config=config32e.ini --suite=$(wally_dir)/riscv-test-suite/ --env=$(wally_dir)/riscv-test-suite/env --no-browser --no-dut-run
@ -66,3 +74,4 @@ clean:
rm -rf $(work_dir)
rm -rf $(wally_workdir)
rm -rf $(arch_workdir)
rm -rf $(submodule_wor_dir)

View File

@ -31,55 +31,89 @@ def signedImm12(imm):
imm = imm - 0x1000
return str(imm)
def signedImm20(imm):
def unsignedImm20(imm):
imm = imm % pow(2, 20)
if (imm & 0x80000):
imm = imm - 0x100000
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"
if (rs1val < 0):
rs1val = rs1val + 2**xlen
if (rs2val < 0):
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):
lines = lines + "li x" + str(rs1) + ", " + formatstr.format(rs1val) + " # initialize rs1 to a random value \n"
lines = lines + "li x" + str(rs2) + ", " + formatstr.format(rs2val) + " # initialize rs2 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\n"
lines = lines + test + " x" + str(rd) + ", x" + str(rs1) + ", x" + str(rs2) + " # perform operation\n"
elif (test in shiftitype):
lines = lines + "li x" + str(rs1) + ", " + formatstr.format(rs1val) + " # initialize rs1 to a random value \n"
lines = lines + test + " x" + str(rd) + ", x" + str(rs1) + ", " + shiftImm(immval, xlen) + " # perform operation\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"
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"
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"
lines = lines + "addi x" + str(rs1) + ", x" + str(rs1) + ", " + signedImm12(immval) + " # add immediate to lower part of rs1 \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(rs2) + ", " + signedImm12(immval) + "(x" + str(rs1) + ") # perform operation \n"
#lines = lines + test + " x" + str(rs2) + ", " "0(x" + str(rs1) + ") # perform operation \n"
#print("Error: %s type not implemented yet" % test)
pass
elif (test in btypes):#["beq", "bne", "blt", "bge", "bltu", "bgeu"]
if (randint(1,100) > 50):
rs1val = rs2val
lines = lines + "# same values in both registers\n"
if (rs1 != 0):
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) + ", 0(x" + str(rs1) + ") # perform operation\n"
elif (test in stype):#["sb", "sh", "sw", "sd"]
if (rs1 != 0):
if (rs2 == rs1): # make sure registers are different so they don't conflict
rs2 = (rs1 + 1) % 32
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
lines = lines + "# same values in both registers\n"
lines = lines + "nop\n"
lines = lines + "li x" + str(rs1) + ", " + formatstr.format(rs1val) + " # initialize rs1\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_btype_" + str(immval) + str(same) + " # perform operation \n"
lines = lines + "addi x0, x1, 1\n"
lines = lines + "some_label_for_btype_" + str(immval)+ str(same) + ":\n"
lines = lines + "addi x0, x2, 2\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 + "li x" + str(rs1) + ", " + formatstr.format(rs1val) + " # initialize rs1 to a random value that should get changed\n"
lines = lines + "li x" + str(rs2) + ", " + formatstr.format(rs2val) + " # initialize rs2 to a random value that should get changed\n"
lines = lines + test + " x" + str(rs1) + ", x" + str(rs2) + ", some_label_for_sb_types_" + str(immval) + "+4" + " # perform operation \n"
lines = lines + "addi x0, x1, 1\n"
lines = lines + "some_label_for_sb_types_" + str(immval) + ":\n"
lines = lines + "addi x0, x2, 2\n"
lines = lines + "nop\nnop\nnop\nnop\nnop\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:
pass
#print("Error: %s type not implemented yet" % test)
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():
rs1 = randint(1, 31)
rs2 = randint(1, 31)
@ -94,177 +128,257 @@ def randomize():
rdval = randint(0, 2**xlen-1)
return [rs1, rs2, rd, rs1val, rs2val, immval, rdval]
def make_rd(test, storecmd, xlen):
def make_rd(test, xlen):
for r in range(32):
[rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize()
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):
[rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize()
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):
[rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize()
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):
[rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize()
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):
[rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize()
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):
[rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize()
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):
[rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize()
desc = "cmp_rd_rs1_rs2 (Test rs1 = rs2 = x" + str(r) + ")"
writeCovVector(desc, r, r, rd, rs1val, rs2val, immval, rdval, test, storecmd, xlen)
desc = "cmp_rs1_rs2 (Test rs1 = rs2 = x" + str(r) + ")"
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]:
[rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize()
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]:
[rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize()
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]:
# rs1 = 0, 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, 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()
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()
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()
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):
# pass # *** to be implemented ***
def make_cp_gpr_hazard(test, xlen):
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]:
[rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize()
rs1val = abs(rs1val % 2**(xlen-1)) * v;
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]:
[rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize()
rs2val = abs(rs2val % 2**(xlen-1)) * v;
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 v2 in [1, -1]:
[rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize()
rs1val = abs(rs1val % 2**(xlen-1)) * v1;
rs2val = abs(rs2val % 2**(xlen-1)) * v2;
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:
if (coverpoint == "cp_asm_count"):
pass
elif (coverpoint == "cp_rd"):
make_rd(test, storecmd, xlen)
make_rd(test, xlen)
elif (coverpoint == "cp_rs1"):
make_rs1(test, storecmd, xlen)
make_rs1(test, xlen)
elif (coverpoint == "cp_rs2"):
make_rs2(test, storecmd, xlen)
make_rs2(test, xlen)
elif (coverpoint == "cmp_rd_rs1"):
make_rd_rs1(test, storecmd, xlen)
make_rd_rs1(test, xlen)
elif (coverpoint == "cmp_rd_rs2"):
make_rd_rs2(test, storecmd, xlen)
make_rd_rs2(test, xlen)
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"):
pass # duplicate of cmp_rd_rs1
elif (coverpoint == "cmp_rd_rs2_eq"):
pass # duplicate of cmp_rd_rs2
elif (coverpoint == "cmp_rs1_rs2_eq"):
make_rs1_rs2(test, storecmd, xlen)
make_rs1_rs2(test, xlen)
elif (coverpoint == "cp_rs1_maxvals"):
make_rs1_maxvals(test, storecmd, xlen)
make_rs1_maxvals(test, xlen)
elif (coverpoint == "cp_rs2_maxvals"):
make_rs2_maxvals(test, storecmd, xlen)
make_rs2_maxvals(test, xlen)
elif (coverpoint == "cp_rd_maxvals"):
make_rd_maxvals(test, storecmd, xlen)
make_rd_maxvals(test, xlen)
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"):
make_rd_rs2_eqval(test, storecmd, xlen)
make_rd_rs2_eqval(test, xlen)
elif (coverpoint == "cmp_rs1_rs2_eqval"):
make_rs1_rs2_eqval(test, storecmd, xlen)
make_rs1_rs2_eqval(test, xlen)
elif (coverpoint == "cp_rs1_sign"):
make_rs1_sign(test, storecmd, xlen)
make_rs1_sign(test, xlen)
elif (coverpoint == "cp_rs2_sign"):
make_rs2_sign(test, storecmd, xlen)
make_rs2_sign(test, xlen)
elif (coverpoint == "cp_rd_sign"):
pass #TODO hope already covered by rd_maxvals
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"):
pass #TODO toggle not needed and seems to be covered by other things
elif (coverpoint == "cp_rs2_toggle"):
pass #TODO toggle not needed and seems to be covered by other things
elif (coverpoint == "cp_rd_toggle"):
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"):
pass #TODO
make_imm_zero(test, xlen)
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"):
pass #TODO
if (test in jtype):
make_j_imm_ones_zeros(test, xlen)
elif (coverpoint == "cp_mem_hazard"):
pass #TODO
make_mem_hazard(test, xlen)
elif (coverpoint == "cp_imm_zero"):
pass #TODO
make_imm_zero(test, xlen)
elif (coverpoint == "cp_mem_unaligned"):
pass #TODO
pass # seems this should be part of privileged tests
elif (coverpoint == "cp_offset"):
pass #TODO
make_offset(test, xlen)
elif (coverpoint == "cr_nord_rs1_rs2"):
pass #TODO (not if crosses are not needed)
elif (coverpoint == "cp_imm_shift"):
pass #TODO
make_imm_shift(test, xlen)
elif (coverpoint == "cp_rd_boolean"):
pass #TODO
pass # covered by other generators
else:
print("Warning: " + coverpoint + " not implemented yet for " + test)
@ -302,10 +416,14 @@ rtype = ["add", "sub", "sll", "slt", "sltu", "xor", "srl", "sra", "or", "and",
"mul", "mulh", "mulhsu", "mulhu", "div", "divu", "rem", "remu",
"mulw", "divw", "divuw", "remw", "remuw"]
loaditype = ["lb", "lh", "lw", "ld", "lbu", "lhu", "lwu"]
shiftitype = ["slli", "srli", "srai"]
itype = ["addi", "slti", "sltiu", "xori", "ori", "andi"]
stypes = ["sb", "sh", "sw", "sd"]
btypes = ["beq", "bne", "blt", "bge", "bltu", "bgeu"]
shiftitype = ["slli", "srli", "srai", "slliw", "srliw", "sraiw"]
shiftiwtype = ["slliw", "srliw", "sraiw"]
itype = ["addi", "slti", "sltiu", "xori", "ori", "andi", "addiw"]
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
coverpoints = getcovergroups(coverdefdir, coverfiles)
@ -328,12 +446,11 @@ for xlen in xlens:
else:
storecmd = "sd"
wordsize = 8
WALLY = os.environ.get('WALLY')
pathname = WALLY+"/tests/functcov/rv" + str(xlen) + "/I/"
cmd = "mkdir -p " + pathname + " ; rm -f " + pathname + "/*" # make directory and remove old tests in dir
os.system(cmd)
for test in coverpoints.keys():
# pathname = "../wally-riscv-arch-test/riscv-test-suite/rv" + str(xlen) + "i_m/I/"
WALLY = os.environ.get('WALLY')
pathname = WALLY+"/tests/functcov/rv" + str(xlen) + "/I/"
cmd = "mkdir -p " + pathname
os.system(cmd)
basename = "WALLY-COV-" + test
fname = pathname + "/" + basename + ".S"
@ -341,9 +458,9 @@ for xlen in xlens:
f = open(fname, "w")
line = "///////////////////////////////////////////\n"
f.write(line)
lines="// "+fname+ "\n// " + author + "\n"
f.write(lines)
line ="// Created " + str(datetime.now())
line="// "+fname+ "\n// " + author + "\n"
f.write(line)
line ="// Created " + str(datetime.now()) + "\n"
f.write(line)
# insert generic header
@ -356,8 +473,8 @@ for xlen in xlens:
#if (test not in rtests):
# exit("Error: %s not implemented yet" % test)
#else:
# write_rtype_arith_vectors(test, storecmd, xlen)
write_tests(coverpoints[test], test, storecmd, xlen)
# write_rtype_arith_vectors(test, xlen)
write_tests(coverpoints[test], test, xlen)
# print footer
line = "\n.EQU NUMTESTS," + str(1) + "\n\n"
@ -367,9 +484,6 @@ for xlen in xlens:
f.write(line)
# Finish
# lines = ".fill " + str(testnum) + ", " + str(wordsize) + ", -1\n"
# lines = lines + "\nRV_COMPLIANCE_DATA_END\n"
f.write(lines)
f.close()

View File

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