forked from Github_Repos/cvw
		
	Merge branch 'main' of https://github.com/mmasserfrye/cvw
This commit is contained in:
		
						commit
						a8ed39ecbe
					
				
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@ -134,3 +134,5 @@ fpga/src/CopiedFiles_do_not_add_to_repo/*
 | 
			
		||||
/fpga/generator/sim/imp-timesim.sdf
 | 
			
		||||
/fpga/generator/sim/imp-timesim.v
 | 
			
		||||
/fpga/generator/sim/syn-funcsim.v
 | 
			
		||||
external
 | 
			
		||||
pipelined/regression/results
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										54
									
								
								bin/imperas-one-time.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										54
									
								
								bin/imperas-one-time.sh
									
									
									
									
									
										Executable file
									
								
							@ -0,0 +1,54 @@
 | 
			
		||||
#!/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: One time setup script for running imperas.
 | 
			
		||||
## 
 | 
			
		||||
## 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.
 | 
			
		||||
################################################################################################
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
IMP_HASH=56b1479
 | 
			
		||||
 | 
			
		||||
# clone the Imperas repo
 | 
			
		||||
cd $WALY
 | 
			
		||||
if [ ! -d external ]; then
 | 
			
		||||
    mkdir -p external
 | 
			
		||||
fi
 | 
			
		||||
pushd external
 | 
			
		||||
    if [ ! -d ImperasDV-HMC ]; then
 | 
			
		||||
	git clone git@github.com:Imperas/ImperasDV-HMC.git
 | 
			
		||||
    fi
 | 
			
		||||
    pushd ImperasDV-HMC
 | 
			
		||||
    git checkout $IMP_HASH
 | 
			
		||||
    popd
 | 
			
		||||
popd
 | 
			
		||||
 | 
			
		||||
# Setup Imperas
 | 
			
		||||
source ${WALLY}/external/ImperasDV-HMC/Imperas/bin/setup.sh
 | 
			
		||||
setupImperas ${WALLY}/external/ImperasDV-HMC/Imperas
 | 
			
		||||
export IMPERAS_PERSONALITY=CPUMAN_DV_ASYNC
 | 
			
		||||
 | 
			
		||||
# setup QUESTA (Imperas only command, YMMV)
 | 
			
		||||
#svsetup -questa
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										26
									
								
								pipelined/regression/imperas.ic
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								pipelined/regression/imperas.ic
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,26 @@
 | 
			
		||||
#--showoverrides
 | 
			
		||||
--override cpu/show_c_prefix=T
 | 
			
		||||
--override cpu/unaligned=F
 | 
			
		||||
--override cpu/mstatus_FS=1
 | 
			
		||||
 | 
			
		||||
# Enable the Imperas instruction coverage
 | 
			
		||||
-extlib    refRoot/cpu/cv=imperas.com/intercept/riscvInstructionCoverage/1.0
 | 
			
		||||
-override  refRoot/cpu/cv/cover=basic
 | 
			
		||||
-override  refRoot/cpu/cv/extensions=RV32I
 | 
			
		||||
 | 
			
		||||
# Add Imperas simulator application instruction tracing
 | 
			
		||||
--trace
 | 
			
		||||
--tracechange
 | 
			
		||||
--traceshowicount
 | 
			
		||||
--tracemode
 | 
			
		||||
--monitornetschange
 | 
			
		||||
 | 
			
		||||
# Turn on verbose output for Imperas simulator
 | 
			
		||||
--verbose
 | 
			
		||||
 | 
			
		||||
# Turn on verbose output for RISCV model
 | 
			
		||||
--override  cpu/verbose=1
 | 
			
		||||
 | 
			
		||||
# Store simulator output to logfile
 | 
			
		||||
--output imperas.log
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										22
									
								
								pipelined/regression/run-imperasdv-tests.bash
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										22
									
								
								pipelined/regression/run-imperasdv-tests.bash
									
									
									
									
									
										Executable file
									
								
							@ -0,0 +1,22 @@
 | 
			
		||||
#!/bin/bash
 | 
			
		||||
 | 
			
		||||
if [ -d results ]; then
 | 
			
		||||
    rm -rf results
 | 
			
		||||
fi
 | 
			
		||||
mkdir -p results
 | 
			
		||||
 | 
			
		||||
ALL=$(find ${WALLY}/external/ImperasDV-HMC/tests/riscof/work/riscv-arch-test/rv64i_m -name "ref" -type d)
 | 
			
		||||
 | 
			
		||||
export IMPERAS_TOOLS=$(pwd)/imperas.ic
 | 
			
		||||
export OTHERFLAGS="+TRACE2LOG_ENABLE=1 VERBOSE=1"
 | 
			
		||||
 | 
			
		||||
for t in $ALL; do
 | 
			
		||||
    export TESTDIR=$(dirname ${t})
 | 
			
		||||
    OUTLOG=$(echo ${TESTDIR} | sed "s|${WALLY}/external/ImperasDV-HMC/tests/riscof/work|results|").log
 | 
			
		||||
    OUTDIR=$(dirname ${OUTLOG})
 | 
			
		||||
    echo "Running test ${TESTDIR} -> ${OUTDIR} :: ${OUTLOG}"
 | 
			
		||||
 | 
			
		||||
    mkdir -p ${OUTDIR}
 | 
			
		||||
    vsim -c -do "do wally-pipelined-imperas.do rv64gc"
 | 
			
		||||
    mv transcript ${OUTLOG}
 | 
			
		||||
done
 | 
			
		||||
							
								
								
									
										32
									
								
								pipelined/regression/sim-imperas
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										32
									
								
								pipelined/regression/sim-imperas
									
									
									
									
									
										Executable file
									
								
							@ -0,0 +1,32 @@
 | 
			
		||||
#!/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.
 | 
			
		||||
## 
 | 
			
		||||
## 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}/external/ImperasDV-HMC/tests/riscof/work/riscv-arch-test/rv64i_m/F/src/fadd_b1-01.S  \
 | 
			
		||||
vsim -c -do "do wally-pipelined-imperas.do rv64gc"
 | 
			
		||||
							
								
								
									
										55
									
								
								pipelined/regression/wally-pipelined-imperas-no-idv.do
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								pipelined/regression/wally-pipelined-imperas-no-idv.do
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,55 @@
 | 
			
		||||
# wally-pipelined.do 
 | 
			
		||||
#
 | 
			
		||||
# 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
 | 
			
		||||
 | 
			
		||||
# run with vsim -do "do wally-pipelined.do rv64ic riscvarchtest-64m"
 | 
			
		||||
 | 
			
		||||
# Use this wally-pipelined.do file to run this example.
 | 
			
		||||
# Either bring up ModelSim and type the following at the "ModelSim>" prompt:
 | 
			
		||||
#     do wally-pipelined.do
 | 
			
		||||
# or, to run from a shell, type the following at the shell prompt:
 | 
			
		||||
#     vsim -do wally-pipelined.do -c
 | 
			
		||||
# (omit the "-c" to see the GUI while running from the shell)
 | 
			
		||||
 | 
			
		||||
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/rvvi-trace.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 
 | 
			
		||||
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
 | 
			
		||||
							
								
								
									
										63
									
								
								pipelined/regression/wally-pipelined-imperas.do
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								pipelined/regression/wally-pipelined-imperas.do
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,63 @@
 | 
			
		||||
# wally-pipelined.do 
 | 
			
		||||
#
 | 
			
		||||
# 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
 | 
			
		||||
 | 
			
		||||
# run with vsim -do "do wally-pipelined.do rv64ic riscvarchtest-64m"
 | 
			
		||||
 | 
			
		||||
# Use this wally-pipelined.do file to run this example.
 | 
			
		||||
# Either bring up ModelSim and type the following at the "ModelSim>" prompt:
 | 
			
		||||
#     do wally-pipelined.do
 | 
			
		||||
# or, to run from a shell, type the following at the shell prompt:
 | 
			
		||||
#     vsim -do wally-pipelined.do -c
 | 
			
		||||
# (omit the "-c" to see the GUI while running from the shell)
 | 
			
		||||
 | 
			
		||||
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/rvvi-api-pkg.sv    \
 | 
			
		||||
     $env(IMPERAS_HOME)/ImpPublic/source/host/rvvi/rvvi-trace.sv      \
 | 
			
		||||
     $env(IMPERAS_HOME)/ImpProprietary/source/host/rvvi/rvvi-pkg.sv   \
 | 
			
		||||
     $env(IMPERAS_HOME)/ImpProprietary/source/host/rvvi/trace2api.sv  \
 | 
			
		||||
     $env(IMPERAS_HOME)/ImpProprietary/source/host/rvvi/trace2log.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 
 | 
			
		||||
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
 | 
			
		||||
@ -6,28 +6,28 @@ add wave -noupdate /testbench/reset
 | 
			
		||||
add wave -noupdate /testbench/reset_ext
 | 
			
		||||
add wave -noupdate /testbench/memfilename
 | 
			
		||||
add wave -noupdate /testbench/dut/core/SATP_REGW
 | 
			
		||||
add wave -noupdate -group HDU -expand -group hazards /testbench/dut/core/hzu/BPPredWrongE
 | 
			
		||||
add wave -noupdate -group HDU -expand -group hazards /testbench/dut/core/hzu/RetM
 | 
			
		||||
add wave -noupdate -group HDU -expand -group hazards -color Pink /testbench/dut/core/hzu/TrapM
 | 
			
		||||
add wave -noupdate -group HDU -expand -group hazards /testbench/dut/core/hzu/LoadStallD
 | 
			
		||||
add wave -noupdate -group HDU -expand -group hazards /testbench/dut/core/ifu/IFUStallF
 | 
			
		||||
add wave -noupdate -group HDU -expand -group hazards /testbench/dut/core/hzu/LSUStallM
 | 
			
		||||
add wave -noupdate -group HDU -expand -group hazards /testbench/dut/core/MDUStallD
 | 
			
		||||
add wave -noupdate -group HDU -expand -group hazards /testbench/dut/core/hzu/DivBusyE
 | 
			
		||||
add wave -noupdate -group HDU -expand -group hazards /testbench/dut/core/hzu/FDivBusyE
 | 
			
		||||
add wave -noupdate -group HDU -expand -group traps /testbench/dut/core/priv/priv/trap/InstrMisalignedFaultM
 | 
			
		||||
add wave -noupdate -group HDU -expand -group traps /testbench/dut/core/priv/priv/trap/InstrAccessFaultM
 | 
			
		||||
add wave -noupdate -group HDU -expand -group traps /testbench/dut/core/priv/priv/trap/IllegalInstrFaultM
 | 
			
		||||
add wave -noupdate -group HDU -expand -group traps /testbench/dut/core/priv/priv/trap/BreakpointFaultM
 | 
			
		||||
add wave -noupdate -group HDU -expand -group traps /testbench/dut/core/priv/priv/trap/LoadMisalignedFaultM
 | 
			
		||||
add wave -noupdate -group HDU -expand -group traps /testbench/dut/core/priv/priv/trap/StoreAmoMisalignedFaultM
 | 
			
		||||
add wave -noupdate -group HDU -expand -group traps /testbench/dut/core/priv/priv/trap/LoadAccessFaultM
 | 
			
		||||
add wave -noupdate -group HDU -expand -group traps /testbench/dut/core/priv/priv/trap/StoreAmoAccessFaultM
 | 
			
		||||
add wave -noupdate -group HDU -expand -group traps /testbench/dut/core/priv/priv/trap/EcallFaultM
 | 
			
		||||
add wave -noupdate -group HDU -expand -group traps /testbench/dut/core/priv/priv/trap/InstrPageFaultM
 | 
			
		||||
add wave -noupdate -group HDU -expand -group traps /testbench/dut/core/priv/priv/trap/LoadPageFaultM
 | 
			
		||||
add wave -noupdate -group HDU -expand -group traps /testbench/dut/core/priv/priv/trap/StoreAmoPageFaultM
 | 
			
		||||
add wave -noupdate -group HDU -expand -group traps /testbench/dut/core/priv/priv/trap/InterruptM
 | 
			
		||||
add wave -noupdate -group HDU -group hazards /testbench/dut/core/hzu/BPPredWrongE
 | 
			
		||||
add wave -noupdate -group HDU -group hazards /testbench/dut/core/hzu/RetM
 | 
			
		||||
add wave -noupdate -group HDU -group hazards -color Pink /testbench/dut/core/hzu/TrapM
 | 
			
		||||
add wave -noupdate -group HDU -group hazards /testbench/dut/core/hzu/LoadStallD
 | 
			
		||||
add wave -noupdate -group HDU -group hazards /testbench/dut/core/ifu/IFUStallF
 | 
			
		||||
add wave -noupdate -group HDU -group hazards /testbench/dut/core/hzu/LSUStallM
 | 
			
		||||
add wave -noupdate -group HDU -group hazards /testbench/dut/core/MDUStallD
 | 
			
		||||
add wave -noupdate -group HDU -group hazards /testbench/dut/core/hzu/DivBusyE
 | 
			
		||||
add wave -noupdate -group HDU -group hazards /testbench/dut/core/hzu/FDivBusyE
 | 
			
		||||
add wave -noupdate -group HDU -group traps /testbench/dut/core/priv/priv/trap/InstrMisalignedFaultM
 | 
			
		||||
add wave -noupdate -group HDU -group traps /testbench/dut/core/priv/priv/trap/InstrAccessFaultM
 | 
			
		||||
add wave -noupdate -group HDU -group traps /testbench/dut/core/priv/priv/trap/IllegalInstrFaultM
 | 
			
		||||
add wave -noupdate -group HDU -group traps /testbench/dut/core/priv/priv/trap/BreakpointFaultM
 | 
			
		||||
add wave -noupdate -group HDU -group traps /testbench/dut/core/priv/priv/trap/LoadMisalignedFaultM
 | 
			
		||||
add wave -noupdate -group HDU -group traps /testbench/dut/core/priv/priv/trap/StoreAmoMisalignedFaultM
 | 
			
		||||
add wave -noupdate -group HDU -group traps /testbench/dut/core/priv/priv/trap/LoadAccessFaultM
 | 
			
		||||
add wave -noupdate -group HDU -group traps /testbench/dut/core/priv/priv/trap/StoreAmoAccessFaultM
 | 
			
		||||
add wave -noupdate -group HDU -group traps /testbench/dut/core/priv/priv/trap/EcallFaultM
 | 
			
		||||
add wave -noupdate -group HDU -group traps /testbench/dut/core/priv/priv/trap/InstrPageFaultM
 | 
			
		||||
add wave -noupdate -group HDU -group traps /testbench/dut/core/priv/priv/trap/LoadPageFaultM
 | 
			
		||||
add wave -noupdate -group HDU -group traps /testbench/dut/core/priv/priv/trap/StoreAmoPageFaultM
 | 
			
		||||
add wave -noupdate -group HDU -group traps /testbench/dut/core/priv/priv/trap/InterruptM
 | 
			
		||||
add wave -noupdate -group HDU -expand -group Flush -color Yellow /testbench/dut/core/FlushD
 | 
			
		||||
add wave -noupdate -group HDU -expand -group Flush -color Yellow /testbench/dut/core/FlushE
 | 
			
		||||
add wave -noupdate -group HDU -expand -group Flush -color Yellow /testbench/dut/core/FlushM
 | 
			
		||||
 | 
			
		||||
@ -42,7 +42,7 @@ module RASPredictor #(parameter int StackSize = 16 )(
 | 
			
		||||
  logic                     CounterEn;
 | 
			
		||||
  localparam Depth = $clog2(StackSize);
 | 
			
		||||
 | 
			
		||||
  logic [Depth-1:0]         PtrD, PtrQ, PtrP1, PtrM1;
 | 
			
		||||
  logic [Depth-1:0]         NextPtr, CurrPtr, PtrP1, PtrM1;
 | 
			
		||||
  logic [StackSize-1:0]     [`XLEN-1:0] memory;
 | 
			
		||||
  integer        index;
 | 
			
		||||
 | 
			
		||||
@ -52,30 +52,31 @@ module RASPredictor #(parameter int StackSize = 16 )(
 | 
			
		||||
  logic 		 IncrRepairD, DecRepairD;
 | 
			
		||||
  
 | 
			
		||||
  logic 		 DecrementPtr;
 | 
			
		||||
  logic 		 FlushedRetDE;
 | 
			
		||||
  logic 		 WrongPredRetD;
 | 
			
		||||
  
 | 
			
		||||
  
 | 
			
		||||
  assign PopF = PredInstrClassF[2] & ~StallD & ~FlushD;
 | 
			
		||||
 | 
			
		||||
  assign RepairD = ((WrongPredInstrClassD[2]) & ~StallE & ~FlushE) |  // Wrong class undo increment or decrement.
 | 
			
		||||
				   (~StallE & FlushE & InstrClassD[2]) | // ret in decode flushed
 | 
			
		||||
				   (~StallM & FlushM & InstrClassE[2]) ; // ret in execution flushed
 | 
			
		||||
  
 | 
			
		||||
  assign IncrRepairD = (~StallE & FlushE & InstrClassD[2]) | // ret in decode flushed
 | 
			
		||||
					   (~StallM & FlushM & InstrClassE[2]) | // ret in execution flushed
 | 
			
		||||
					   (WrongPredInstrClassD[2] & ~InstrClassD[2] & ~StallE & ~FlushE); // Guessed it was a ret, but its not
 | 
			
		||||
 | 
			
		||||
  assign DecRepairD =  (WrongPredInstrClassD[2] & InstrClassD[2] & ~StallE & ~FlushE); // Guessed non ret but is a ret.
 | 
			
		||||
  
 | 
			
		||||
  assign PushE = InstrClassE[3] & ~StallM & ~FlushM;
 | 
			
		||||
 | 
			
		||||
  assign WrongPredRetD = (WrongPredInstrClassD[2]) & ~StallE & ~FlushE;
 | 
			
		||||
  assign FlushedRetDE = (~StallE & FlushE & InstrClassD[2]) | (~StallM & FlushM & InstrClassE[2]); // flushed ret
 | 
			
		||||
 | 
			
		||||
  assign RepairD = WrongPredRetD | FlushedRetDE ;
 | 
			
		||||
 | 
			
		||||
  assign IncrRepairD = FlushedRetDE | (WrongPredRetD & ~InstrClassD[2]); // Guessed it was a ret, but its not
 | 
			
		||||
 | 
			
		||||
  assign DecRepairD =  WrongPredRetD & InstrClassD[2]; // Guessed non ret but is a ret.
 | 
			
		||||
    
 | 
			
		||||
  assign CounterEn = PopF | PushE | RepairD;
 | 
			
		||||
 | 
			
		||||
  assign DecrementPtr = (PopF | DecRepairD) & ~IncrRepairD;
 | 
			
		||||
  mux2 #(Depth) PtrMux(PtrP1, PtrM1, DecrementPtr, PtrD);
 | 
			
		||||
  mux2 #(Depth) PtrMux(PtrP1, PtrM1, DecrementPtr, NextPtr);
 | 
			
		||||
 | 
			
		||||
  assign PtrM1 = PtrQ - 1'b1;
 | 
			
		||||
  assign PtrP1 = PtrQ + 1'b1;
 | 
			
		||||
  assign PtrM1 = CurrPtr - 1'b1;
 | 
			
		||||
  assign PtrP1 = CurrPtr + 1'b1;
 | 
			
		||||
 | 
			
		||||
  flopenr #(Depth) PTR(clk, reset, CounterEn, PtrD, PtrQ);
 | 
			
		||||
  flopenr #(Depth) PTR(clk, reset, CounterEn, NextPtr, CurrPtr);
 | 
			
		||||
 | 
			
		||||
  // RAS must be reset. 
 | 
			
		||||
  always_ff @ (posedge clk) begin
 | 
			
		||||
@ -87,7 +88,7 @@ module RASPredictor #(parameter int StackSize = 16 )(
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  assign RASPCF = memory[PtrQ];
 | 
			
		||||
  assign RASPCF = memory[CurrPtr];
 | 
			
		||||
  
 | 
			
		||||
  
 | 
			
		||||
endmodule
 | 
			
		||||
@ -117,8 +117,7 @@ module bpred (
 | 
			
		||||
  end else if (`BPRED_TYPE == "BPSPECULATIVEGSHARE") begin:Predictor
 | 
			
		||||
    speculativegshare #(`BPRED_SIZE) DirPredictor(.clk, .reset, .StallF, .StallD, .StallE, .StallM, .StallW, .FlushD, .FlushE, .FlushM, .FlushW,
 | 
			
		||||
      .PCNextF, .PCF, .PCD, .PCE, .PCM, .DirPredictionF, .DirPredictionWrongE,
 | 
			
		||||
      .BranchInstrF(PredInstrClassF[0]), .BranchInstrD(InstrClassD[0]), .BranchInstrE(InstrClassE[0]), .BranchInstrM(InstrClassM[0]),
 | 
			
		||||
      .BranchInstrW(InstrClassW[0]), .WrongPredInstrClassD, .PCSrcE);
 | 
			
		||||
      .PredInstrClassF, .InstrClassD, .InstrClassE, .WrongPredInstrClassD, .PCSrcE);
 | 
			
		||||
 | 
			
		||||
  end else if (`BPRED_TYPE == "BPLOCALPAg") begin:Predictor
 | 
			
		||||
    // *** Fix me
 | 
			
		||||
@ -152,15 +151,6 @@ module bpred (
 | 
			
		||||
          .IEUAdrE,
 | 
			
		||||
          .InstrClassE);
 | 
			
		||||
 | 
			
		||||
  // Part 3 RAS
 | 
			
		||||
  // *** need to add the logic to restore RAS on flushes.  We will use incr for this.
 | 
			
		||||
  // *** needs to include flushX
 | 
			
		||||
  RASPredictor RASPredictor(.clk, .reset, .StallF, .StallD, .StallE, .StallM, .FlushD, .FlushE, .FlushM,
 | 
			
		||||
							.PredInstrClassF, .InstrClassD, .InstrClassE,
 | 
			
		||||
							.WrongPredInstrClassD, .RASPCF, .PCLinkE);
 | 
			
		||||
 | 
			
		||||
  assign BPPredPCF = PredInstrClassF[2] ? RASPCF : PredPCF;
 | 
			
		||||
 | 
			
		||||
  // the branch predictor needs a compact decoding of the instruction class.
 | 
			
		||||
  if (`INSTR_CLASS_PRED == 0) begin : DirectClassDecode
 | 
			
		||||
	logic [4:0] CompressedOpcF;
 | 
			
		||||
@ -197,12 +187,19 @@ module bpred (
 | 
			
		||||
						(PredInstrClassF[1] & PredValidF) ;
 | 
			
		||||
  end
 | 
			
		||||
  
 | 
			
		||||
  // Part 3 RAS
 | 
			
		||||
  RASPredictor RASPredictor(.clk, .reset, .StallF, .StallD, .StallE, .StallM, .FlushD, .FlushE, .FlushM,
 | 
			
		||||
							.PredInstrClassF, .InstrClassD, .InstrClassE,
 | 
			
		||||
							.WrongPredInstrClassD, .RASPCF, .PCLinkE);
 | 
			
		||||
 | 
			
		||||
  assign BPPredPCF = PredInstrClassF[2] ? RASPCF : PredPCF;
 | 
			
		||||
 | 
			
		||||
  assign InstrClassD[3] = (InstrD[6:0] & 7'h77) == 7'h67 & (InstrD[11:07] & 5'h1B) == 5'h01; // jal(r) must link to ra or x5
 | 
			
		||||
  assign InstrClassD[2] = InstrD[6:0] == 7'h67 & (InstrD[19:15] & 5'h1B) == 5'h01; // return must return to ra or r5
 | 
			
		||||
  assign InstrClassD[1] = (InstrD[6:0] == 7'h67 & (InstrD[19:15] & 5'h1B) != 5'h01 & (InstrD[11:7] & 5'h1B) != 5'h01) | // jump register, but not return
 | 
			
		||||
						  (InstrD[6:0] == 7'h6F & (InstrD[11:7] & 5'h1B) != 5'h01); // jump, RD != x1 or x5
 | 
			
		||||
  assign InstrClassD[0] = InstrD[6:0] == 7'h63; // branch
 | 
			
		||||
 | 
			
		||||
  flopenrc #(4) InstrClassRegE(clk, reset,  FlushE, ~StallE, InstrClassD, InstrClassE);
 | 
			
		||||
  flopenrc #(4) InstrClassRegM(clk, reset,  FlushM, ~StallM, InstrClassE, InstrClassM);
 | 
			
		||||
  flopenrc #(4) InstrClassRegW(clk, reset,  FlushW, ~StallW, InstrClassM, InstrClassW);
 | 
			
		||||
 | 
			
		||||
@ -37,7 +37,7 @@ module speculativegshare #(parameter int k = 10 ) (
 | 
			
		||||
  output logic 			  DirPredictionWrongE,
 | 
			
		||||
  // update
 | 
			
		||||
  input logic [`XLEN-1:0] PCNextF, PCF, PCD, PCE, PCM,
 | 
			
		||||
  input logic             BranchInstrF, BranchInstrD, BranchInstrE, BranchInstrM, BranchInstrW,
 | 
			
		||||
  input logic [3:0] 	  PredInstrClassF, InstrClassD, InstrClassE,
 | 
			
		||||
  input logic [3:0] 	  WrongPredInstrClassD, 
 | 
			
		||||
  input logic 			  PCSrcE
 | 
			
		||||
);
 | 
			
		||||
@ -46,20 +46,16 @@ module speculativegshare #(parameter int k = 10 ) (
 | 
			
		||||
  logic                    MatchNextX, MatchXF;
 | 
			
		||||
 | 
			
		||||
  logic [1:0]              TableDirPredictionF, DirPredictionD, DirPredictionE;
 | 
			
		||||
  logic [1:0]              NewDirPredictionF, NewDirPredictionD, NewDirPredictionE;
 | 
			
		||||
 | 
			
		||||
  logic [k-1:0]            GHRF;
 | 
			
		||||
  logic 				   GHRExtraF;
 | 
			
		||||
  logic [k-1:0] 		   GHRD, GHRE, GHRM, GHRW;
 | 
			
		||||
  logic [k-1:0] 		   GHRNextF;
 | 
			
		||||
  logic [k-1:0] 		   GHRNextD;
 | 
			
		||||
  logic [k-1:0] 		   GHRNextE, GHRNextM, GHRNextW;
 | 
			
		||||
  logic [k-1:0]            IndexNextF, IndexF;
 | 
			
		||||
  logic [k-1:0]            IndexD, IndexE;
 | 
			
		||||
  
 | 
			
		||||
  logic [1:0]              NewDirPredictionE;
 | 
			
		||||
 | 
			
		||||
  logic [k-1:0] 		   GHRF, GHRD, GHRE;
 | 
			
		||||
  logic 				   GHRLastF;
 | 
			
		||||
  logic [k-1:0] 		   GHRNextF, GHRNextD, GHRNextE;
 | 
			
		||||
  logic [k-1:0]            IndexNextF, IndexF, IndexD, IndexE;
 | 
			
		||||
  logic [1:0]              ForwardNewDirPrediction, ForwardDirPredictionF;
 | 
			
		||||
 | 
			
		||||
  logic 				   FlushDOrDirWrong;
 | 
			
		||||
  
 | 
			
		||||
  assign IndexNextF = GHRNextF ^ {PCNextF[k+1] ^ PCNextF[1], PCNextF[k:2]};
 | 
			
		||||
  assign IndexF = GHRF        ^ {PCF[k+1] ^ PCF[1], PCF[k:2]};
 | 
			
		||||
  assign IndexD = GHRD[k-1:0] ^ {PCD[k+1] ^ PCD[1], PCD[k:2]};
 | 
			
		||||
@ -71,20 +67,20 @@ module speculativegshare #(parameter int k = 10 ) (
 | 
			
		||||
    .rd1(TableDirPredictionF),
 | 
			
		||||
    .wa2(IndexE),
 | 
			
		||||
    .wd2(NewDirPredictionE),
 | 
			
		||||
    .we2(BranchInstrE & ~StallM & ~FlushM),
 | 
			
		||||
    .we2(InstrClassE[0]),
 | 
			
		||||
    .bwe2(1'b1));
 | 
			
		||||
 | 
			
		||||
  // if there are non-flushed branches in the pipeline we need to forward the prediction from that stage to the NextF demi stage
 | 
			
		||||
  // and then register for use in the Fetch stage.
 | 
			
		||||
  assign MatchF = BranchInstrF & ~FlushD & (IndexNextF == IndexF);
 | 
			
		||||
  assign MatchD = BranchInstrD & ~FlushE & (IndexNextF == IndexD);
 | 
			
		||||
  assign MatchE = BranchInstrE & ~FlushM & (IndexNextF == IndexE);
 | 
			
		||||
  assign MatchF = PredInstrClassF[0] & ~FlushD & (IndexNextF == IndexF);
 | 
			
		||||
  assign MatchD = InstrClassD[0] & ~FlushE & (IndexNextF == IndexD);
 | 
			
		||||
  assign MatchE = InstrClassE[0] & ~FlushM & (IndexNextF == IndexE);
 | 
			
		||||
  assign MatchNextX = MatchF | MatchD | MatchE;
 | 
			
		||||
 | 
			
		||||
  flopenr #(1) MatchReg(clk, reset, ~StallF, MatchNextX, MatchXF);
 | 
			
		||||
 | 
			
		||||
  assign ForwardNewDirPrediction = MatchF ? NewDirPredictionF :
 | 
			
		||||
                                   MatchD ? NewDirPredictionD :
 | 
			
		||||
  assign ForwardNewDirPrediction = MatchF ? {2{DirPredictionF[1]}} :
 | 
			
		||||
                                   MatchD ? {2{DirPredictionD[1]}} :
 | 
			
		||||
                                   NewDirPredictionE ;
 | 
			
		||||
  
 | 
			
		||||
  flopenr #(2) ForwardDirPredicitonReg(clk, reset, ~StallF, ForwardNewDirPrediction, ForwardDirPredictionF);
 | 
			
		||||
@ -95,49 +91,37 @@ module speculativegshare #(parameter int k = 10 ) (
 | 
			
		||||
  flopenr #(2) PredictionRegD(clk, reset, ~StallD, DirPredictionF, DirPredictionD);
 | 
			
		||||
  flopenr #(2) PredictionRegE(clk, reset, ~StallE, DirPredictionD, DirPredictionE);
 | 
			
		||||
 | 
			
		||||
  // New prediction pipeline
 | 
			
		||||
  assign NewDirPredictionF = {DirPredictionF[1], DirPredictionF[1]};
 | 
			
		||||
  
 | 
			
		||||
  flopenr #(2) NewPredDReg(clk, reset, ~StallD, NewDirPredictionF, NewDirPredictionD);
 | 
			
		||||
  satCounter2 BPDirUpdateE(.BrDir(PCSrcE), .OldState(DirPredictionE), .NewState(NewDirPredictionE));
 | 
			
		||||
 | 
			
		||||
  // GHR pipeline
 | 
			
		||||
  // this version fails the regression test do to pessimistic x propagation.
 | 
			
		||||
  // assign GHRNextF = FlushD | DirPredictionWrongE ?  GHRNextD[k-1:0] :
 | 
			
		||||
  //                  BranchInstrF ? {DirPredictionF[1], GHRF[k-1:1]} :
 | 
			
		||||
  //                  GHRF;
 | 
			
		||||
 | 
			
		||||
  always_comb begin
 | 
			
		||||
	if(FlushD | DirPredictionWrongE) begin
 | 
			
		||||
	  GHRNextF = GHRNextD[k-1:0];
 | 
			
		||||
	end else if(BranchInstrF) GHRNextF = {DirPredictionF[1], GHRF[k-1:1]};
 | 
			
		||||
	else GHRNextF = GHRF;
 | 
			
		||||
  end
 | 
			
		||||
  // If Fetch has a branch, speculatively insert prediction into the GHR
 | 
			
		||||
  // If the front end is flushed or the direction prediction is wrong, reset to
 | 
			
		||||
  // most recent valid GHR.  For a BP wrong this is GHRD with the correct prediction shifted in.
 | 
			
		||||
  // For FlushE this is GHRE.  GHRNextE is both.
 | 
			
		||||
  assign FlushDOrDirWrong = FlushD | DirPredictionWrongE;
 | 
			
		||||
  mux3 #(k) GHRFMux(GHRF, {DirPredictionF[1], GHRF[k-1:1]}, GHRNextE[k-1:0], 
 | 
			
		||||
					{FlushDOrDirWrong, PredInstrClassF[0]}, GHRNextF);
 | 
			
		||||
 | 
			
		||||
  flopenr  #(k) GHRFReg(clk, reset, (~StallF) | FlushD, GHRNextF, GHRF);	
 | 
			
		||||
  flopenr  #(1) GHRFExtraReg(clk, reset, (~StallF) | FlushD, GHRF[0], GHRExtraF);
 | 
			
		||||
  // Need 1 extra bit to store the shifted out GHRF if repair needs to back shift.
 | 
			
		||||
  flopenr  #(k) GHRFReg(clk, reset, ~StallF | FlushDOrDirWrong, GHRNextF, GHRF);	
 | 
			
		||||
  flopenr  #(1) GHRFLastReg(clk, reset, ~StallF | FlushDOrDirWrong, GHRF[0], GHRLastF);
 | 
			
		||||
 | 
			
		||||
  // use with out instruction class prediction
 | 
			
		||||
  //assign GHRNextD = FlushD ? GHRNextE[k-1:0] : GHRF[k-1:0];
 | 
			
		||||
  // with instruction class prediction
 | 
			
		||||
  assign GHRNextD = (FlushD | DirPredictionWrongE) ? GHRNextE[k-1:0] :
 | 
			
		||||
					WrongPredInstrClassD[0] & BranchInstrD  ? {DirPredictionD[1], GHRF[k-1:1]} : // shift right
 | 
			
		||||
  					WrongPredInstrClassD[0] & ~BranchInstrD ? {GHRF[k-2:0], GHRExtraF}:       // shift left
 | 
			
		||||
					GHRF[k-1:0];
 | 
			
		||||
  // With instruction class prediction, the class could be wrong and is checked in Decode.
 | 
			
		||||
  // If it is wrong and branch does exist then shift right and insert the prediction.
 | 
			
		||||
  // If the branch does not exist then shift left and use GHRLastF to restore the LSB.
 | 
			
		||||
  logic [k-1:0] 		   GHRClassWrong;
 | 
			
		||||
  mux2 #(k) GHRClassWrongMux({DirPredictionD[1], GHRF[k-1:1]}, {GHRF[k-2:0], GHRLastF}, InstrClassD[0], GHRClassWrong);
 | 
			
		||||
  // As with GHRF FlushD and wrong direction prediction flushes the pipeline and restores to GHRNextE.
 | 
			
		||||
  mux3 #(k) GHRDMux(GHRF, GHRClassWrong, GHRNextE, {FlushDOrDirWrong, WrongPredInstrClassD[0]}, GHRNextD);
 | 
			
		||||
 | 
			
		||||
  flopenr  #(k) GHRDReg(clk, reset, (~StallD) | FlushD, GHRNextD, GHRD);
 | 
			
		||||
  flopenr  #(k) GHRDReg(clk, reset, ~StallD | FlushDOrDirWrong, GHRNextD, GHRD);
 | 
			
		||||
 | 
			
		||||
  assign GHRNextE = BranchInstrE & ~FlushM ? {PCSrcE, GHRD[k-2:0]} :   // if the branch is not flushed
 | 
			
		||||
					FlushE ? GHRE :                                // branch is flushed
 | 
			
		||||
					GHRD;
 | 
			
		||||
  flopenr  #(k) GHREReg(clk, reset, (BranchInstrE & ~StallE) | FlushE, GHRNextE, GHRE);
 | 
			
		||||
  mux3 #(k) GHREMux(GHRD, GHRE, {PCSrcE, GHRD[k-2:0]}, {InstrClassE[0] & ~FlushM, FlushE}, GHRNextE);
 | 
			
		||||
 | 
			
		||||
  //assign GHRNextM = FlushM ? GHRM : GHRE;
 | 
			
		||||
  //flopenr  #(k) GHRMReg(clk, reset, (BranchInstrM & ~StallM) | FlushM, GHRNextM, GHRM);
 | 
			
		||||
  flopenr  #(k) GHREReg(clk, reset, ((InstrClassE[0] & ~FlushM) & ~StallE) | FlushE, GHRNextE, GHRE);
 | 
			
		||||
  
 | 
			
		||||
  //assign GHRNextW = FlushW ? GHRW : GHRM;
 | 
			
		||||
  //flopenr  #(k) GHRWReg(clk, reset, (BranchInstrW & ~StallW) | FlushW, GHRNextW, GHRW);
 | 
			
		||||
  
 | 
			
		||||
  assign DirPredictionWrongE = PCSrcE != DirPredictionE[1] & BranchInstrE;
 | 
			
		||||
  assign DirPredictionWrongE = PCSrcE != DirPredictionE[1] & InstrClassE[0];
 | 
			
		||||
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
@ -68,6 +68,7 @@ module csrsr (
 | 
			
		||||
                          STATUS_XS, STATUS_FS, /*STATUS_MPP, 2'b0*/ 4'b0,
 | 
			
		||||
                          STATUS_SPP, /*STATUS_MPIE*/ 1'b0, STATUS_UBE, STATUS_SPIE,
 | 
			
		||||
                          /*1'b0, STATUS_MIE, 1'b0*/ 3'b0, STATUS_SIE, 1'b0};
 | 
			
		||||
	assign MSTATUSH_REGW = '0; // *** does not exist when XLEN=64, but don't want it to have an undefined value.  Spec is not clear what it should be.
 | 
			
		||||
  end else begin: csrsr32 // RV32
 | 
			
		||||
    assign MSTATUS_REGW = {STATUS_SD, 8'b0,
 | 
			
		||||
                          STATUS_TSR, STATUS_TW, STATUS_TVM, STATUS_MXR, STATUS_SUM, STATUS_MPRV,
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										291
									
								
								pipelined/testbench/common/wallyTracer.sv
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										291
									
								
								pipelined/testbench/common/wallyTracer.sv
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,291 @@
 | 
			
		||||
`include "wally-config.vh"
 | 
			
		||||
 | 
			
		||||
`define NUM_REGS 32
 | 
			
		||||
`define NUM_CSRS 4096
 | 
			
		||||
 | 
			
		||||
`define PRINT_PC_INSTR 0
 | 
			
		||||
`define PRINT_MOST 0
 | 
			
		||||
`define PRINT_ALL 0
 | 
			
		||||
`define PRINT_CSRS 0
 | 
			
		||||
 | 
			
		||||
module wallyTracer(rvviTrace rvvi);
 | 
			
		||||
 | 
			
		||||
  localparam NUMREGS = `E_SUPPORTED ? 16 : 32;
 | 
			
		||||
  
 | 
			
		||||
  // wally specific signals
 | 
			
		||||
  logic 						 reset;
 | 
			
		||||
  
 | 
			
		||||
  logic [`XLEN-1:0] 			 PCNextF, PCF, PCD, PCE, PCM, PCW;
 | 
			
		||||
  logic [`XLEN-1:0] 			 InstrRawD, InstrRawE, InstrRawM, InstrRawW;
 | 
			
		||||
  logic 						 InstrValidM, InstrValidW;
 | 
			
		||||
  logic 						 StallE, StallM, StallW;
 | 
			
		||||
  logic 						 FlushD, FlushE, FlushM, FlushW;
 | 
			
		||||
  logic 						 TrapM, TrapW;
 | 
			
		||||
  logic 						 IntrF, IntrD, IntrE, IntrM, IntrW;
 | 
			
		||||
  logic 						 HaltM, HaltW;
 | 
			
		||||
  logic [1:0] 					 PrivilegeModeW;
 | 
			
		||||
  logic [`XLEN-1:0] 			 rf[NUMREGS];
 | 
			
		||||
  logic [NUMREGS-1:0] 			 rf_wb;
 | 
			
		||||
  logic [4:0] 					 rf_a3;
 | 
			
		||||
  logic 						 rf_we3;
 | 
			
		||||
  logic [`XLEN-1:0] 			 frf[32];
 | 
			
		||||
  logic [`NUM_REGS-1:0] 		 frf_wb;
 | 
			
		||||
  logic [4:0] 					 frf_a4;
 | 
			
		||||
  logic 						 frf_we4;
 | 
			
		||||
  logic [`XLEN-1:0]              CSRArray [logic[11:0]];
 | 
			
		||||
  logic [`XLEN-1:0] 			 CSRArrayOld [logic[11:0]];
 | 
			
		||||
  logic [`NUM_CSRS-1:0] 		 CSR_W;
 | 
			
		||||
  logic 						 CSRWriteM, CSRWriteW;
 | 
			
		||||
  logic [11:0] 					 CSRAdrM, CSRAdrW;
 | 
			
		||||
  
 | 
			
		||||
  assign clk = testbench.dut.clk;
 | 
			
		||||
  //  assign InstrValidF = testbench.dut.core.ieu.InstrValidF;  // not needed yet
 | 
			
		||||
  assign InstrValidD    = testbench.dut.core.ieu.c.InstrValidD;
 | 
			
		||||
  assign InstrValidE    = testbench.dut.core.ieu.c.InstrValidE;
 | 
			
		||||
  assign InstrValidM    = testbench.dut.core.ieu.InstrValidM;
 | 
			
		||||
  assign InstrRawD      = testbench.dut.core.ifu.InstrRawD;
 | 
			
		||||
  assign PCNextF        = testbench.dut.core.ifu.PCNextF;
 | 
			
		||||
  assign PCF            = testbench.dut.core.ifu.PCF;
 | 
			
		||||
  assign PCD            = testbench.dut.core.ifu.PCD;
 | 
			
		||||
  assign PCE            = testbench.dut.core.ifu.PCE;
 | 
			
		||||
  assign PCM            = testbench.dut.core.ifu.PCM;
 | 
			
		||||
  assign reset          = testbench.reset;
 | 
			
		||||
  assign StallF         = testbench.dut.core.StallF;
 | 
			
		||||
  assign StallD         = testbench.dut.core.StallD;
 | 
			
		||||
  assign StallE         = testbench.dut.core.StallE;
 | 
			
		||||
  assign StallM         = testbench.dut.core.StallM;
 | 
			
		||||
  assign StallW         = testbench.dut.core.StallW;
 | 
			
		||||
  assign FlushD         = testbench.dut.core.FlushD;
 | 
			
		||||
  assign FlushE         = testbench.dut.core.FlushE;
 | 
			
		||||
  assign FlushM         = testbench.dut.core.FlushM;
 | 
			
		||||
  assign FlushW         = testbench.dut.core.FlushW;
 | 
			
		||||
  assign TrapM          = testbench.dut.core.TrapM;
 | 
			
		||||
  assign HaltM          = testbench.DCacheFlushStart;
 | 
			
		||||
  assign PrivilegeModeW = testbench.dut.core.priv.priv.privmode.PrivilegeModeW;
 | 
			
		||||
  assign STATUS_SXL     = testbench.dut.core.priv.priv.csr.csrsr.STATUS_SXL;
 | 
			
		||||
  assign STATUS_UXL     = testbench.dut.core.priv.priv.csr.csrsr.STATUS_UXL;
 | 
			
		||||
 | 
			
		||||
  logic valid;
 | 
			
		||||
 | 
			
		||||
  always_comb begin
 | 
			
		||||
	// Since we are detected the CSR change by comparing the old value we need to
 | 
			
		||||
	// ensure the CSR is detected when the pipeline's Writeback stage is not
 | 
			
		||||
	// stalled.  If it is stalled we want CSRArray to hold the old value.
 | 
			
		||||
	if(valid) begin 
 | 
			
		||||
	  // machine CSRs
 | 
			
		||||
	  // *** missing PMP and performance counters.
 | 
			
		||||
	  CSRArray[12'h300] = testbench.dut.core.priv.priv.csr.csrm.MSTATUS_REGW;
 | 
			
		||||
	  CSRArray[12'h310] = testbench.dut.core.priv.priv.csr.csrm.MSTATUSH_REGW;
 | 
			
		||||
	  CSRArray[12'h305] = testbench.dut.core.priv.priv.csr.csrm.MTVEC_REGW;
 | 
			
		||||
	  CSRArray[12'h341] = testbench.dut.core.priv.priv.csr.csrm.MEPC_REGW;
 | 
			
		||||
	  CSRArray[12'h306] = testbench.dut.core.priv.priv.csr.csrm.MCOUNTEREN_REGW;
 | 
			
		||||
	  CSRArray[12'h320] = testbench.dut.core.priv.priv.csr.csrm.MCOUNTINHIBIT_REGW;
 | 
			
		||||
	  CSRArray[12'h302] = testbench.dut.core.priv.priv.csr.csrm.MEDELEG_REGW;
 | 
			
		||||
	  CSRArray[12'h303] = testbench.dut.core.priv.priv.csr.csrm.MIDELEG_REGW;
 | 
			
		||||
	  CSRArray[12'h344] = testbench.dut.core.priv.priv.csr.csrm.MIP_REGW;
 | 
			
		||||
	  CSRArray[12'h304] = testbench.dut.core.priv.priv.csr.csrm.MIE_REGW;
 | 
			
		||||
	  CSRArray[12'h301] = testbench.dut.core.priv.priv.csr.csrm.MISA_REGW;
 | 
			
		||||
	  CSRArray[12'hF14] = testbench.dut.core.priv.priv.csr.csrm.MHARTID_REGW;
 | 
			
		||||
	  CSRArray[12'h340] = testbench.dut.core.priv.priv.csr.csrm.MSCRATCH_REGW;
 | 
			
		||||
	  CSRArray[12'h342] = testbench.dut.core.priv.priv.csr.csrm.MCAUSE_REGW;
 | 
			
		||||
	  CSRArray[12'h343] = testbench.dut.core.priv.priv.csr.csrm.MTVAL_REGW;
 | 
			
		||||
	  CSRArray[12'hF11] = 0;
 | 
			
		||||
	  CSRArray[12'hF12] = 0;
 | 
			
		||||
	  CSRArray[12'hF13] = `XLEN'h100;
 | 
			
		||||
	  CSRArray[12'hF15] = 0;
 | 
			
		||||
	  CSRArray[12'h34A] = 0;
 | 
			
		||||
	  // MCYCLE and MINSTRET
 | 
			
		||||
	  CSRArray[12'hB00] = testbench.dut.core.priv.priv.csr.counters.counters.HPMCOUNTER_REGW[0];
 | 
			
		||||
	  CSRArray[12'hB02] = testbench.dut.core.priv.priv.csr.counters.counters.HPMCOUNTER_REGW[2];
 | 
			
		||||
	  // supervisor CSRs
 | 
			
		||||
	  CSRArray[12'h100] = testbench.dut.core.priv.priv.csr.csrs.csrs.SSTATUS_REGW;
 | 
			
		||||
	  CSRArray[12'h104] = testbench.dut.core.priv.priv.csr.csrm.MIE_REGW & 12'h222;
 | 
			
		||||
	  CSRArray[12'h105] = testbench.dut.core.priv.priv.csr.csrs.csrs.STVEC_REGW;
 | 
			
		||||
	  CSRArray[12'h141] = testbench.dut.core.priv.priv.csr.csrs.csrs.SEPC_REGW;
 | 
			
		||||
	  CSRArray[12'h106] = testbench.dut.core.priv.priv.csr.csrs.csrs.SCOUNTEREN_REGW;
 | 
			
		||||
	  CSRArray[12'h180] = testbench.dut.core.priv.priv.csr.csrs.csrs.SATP_REGW;
 | 
			
		||||
	  CSRArray[12'h140] = testbench.dut.core.priv.priv.csr.csrs.csrs.SSCRATCH_REGW;
 | 
			
		||||
	  CSRArray[12'h143] = testbench.dut.core.priv.priv.csr.csrs.csrs.STVAL_REGW;
 | 
			
		||||
	  CSRArray[12'h142] = testbench.dut.core.priv.priv.csr.csrs.csrs.SCAUSE_REGW;
 | 
			
		||||
	  CSRArray[12'h144] = testbench.dut.core.priv.priv.csr.csrm.MIP_REGW & & 12'h222 & testbench.dut.core.priv.priv.csr.csrm.MIDELEG_REGW;
 | 
			
		||||
	  // user CSRs
 | 
			
		||||
	  CSRArray[12'h001] = testbench.dut.core.priv.priv.csr.csru.csru.FFLAGS_REGW;
 | 
			
		||||
	  CSRArray[12'h002] = testbench.dut.core.priv.priv.csr.csru.csru.FRM_REGW;
 | 
			
		||||
	  CSRArray[12'h003] = {testbench.dut.core.priv.priv.csr.csru.csru.FRM_REGW, testbench.dut.core.priv.priv.csr.csru.csru.FFLAGS_REGW};
 | 
			
		||||
	end else begin // hold the old value if the pipeline is stalled.
 | 
			
		||||
	  CSRArray[12'h300] = CSRArrayOld[12'h300];
 | 
			
		||||
	  CSRArray[12'h310] = CSRArrayOld[12'h310];
 | 
			
		||||
	  CSRArray[12'h305] = CSRArrayOld[12'h305];
 | 
			
		||||
	  CSRArray[12'h341] = CSRArrayOld[12'h341];
 | 
			
		||||
	  CSRArray[12'h306] = CSRArrayOld[12'h306];
 | 
			
		||||
	  CSRArray[12'h320] = CSRArrayOld[12'h320];
 | 
			
		||||
	  CSRArray[12'h302] = CSRArrayOld[12'h302];
 | 
			
		||||
	  CSRArray[12'h303] = CSRArrayOld[12'h303];
 | 
			
		||||
	  CSRArray[12'h344] = CSRArrayOld[12'h344];
 | 
			
		||||
	  CSRArray[12'h304] = CSRArrayOld[12'h304];
 | 
			
		||||
	  CSRArray[12'h301] = CSRArrayOld[12'h301];
 | 
			
		||||
	  CSRArray[12'hF14] = CSRArrayOld[12'hF14];
 | 
			
		||||
	  CSRArray[12'h340] = CSRArrayOld[12'h340];
 | 
			
		||||
	  CSRArray[12'h342] = CSRArrayOld[12'h342];
 | 
			
		||||
	  CSRArray[12'h343] = CSRArrayOld[12'h343];
 | 
			
		||||
	  CSRArray[12'hF11] = CSRArrayOld[12'hF11];
 | 
			
		||||
	  CSRArray[12'hF12] = CSRArrayOld[12'hF12];
 | 
			
		||||
	  CSRArray[12'hF13] = CSRArrayOld[12'hF13];
 | 
			
		||||
	  CSRArray[12'hF15] = CSRArrayOld[12'hF15];
 | 
			
		||||
	  CSRArray[12'h34A] = CSRArrayOld[12'h34A];
 | 
			
		||||
	  // MCYCLE and MINSTRET
 | 
			
		||||
	  CSRArray[12'hB00] = CSRArrayOld[12'hB00];
 | 
			
		||||
	  CSRArray[12'hB02] = CSRArrayOld[12'hB02];
 | 
			
		||||
	  // supervisor CSRs
 | 
			
		||||
	  CSRArray[12'h100] = CSRArrayOld[12'h100];
 | 
			
		||||
	  CSRArray[12'h104] = CSRArrayOld[12'h104];
 | 
			
		||||
	  CSRArray[12'h105] = CSRArrayOld[12'h105];
 | 
			
		||||
	  CSRArray[12'h141] = CSRArrayOld[12'h141];
 | 
			
		||||
	  CSRArray[12'h106] = CSRArrayOld[12'h106];
 | 
			
		||||
	  CSRArray[12'h180] = CSRArrayOld[12'h180];
 | 
			
		||||
	  CSRArray[12'h140] = CSRArrayOld[12'h140];
 | 
			
		||||
	  CSRArray[12'h143] = CSRArrayOld[12'h143];
 | 
			
		||||
	  CSRArray[12'h142] = CSRArrayOld[12'h142];
 | 
			
		||||
	  CSRArray[12'h144] = CSRArrayOld[12'h144];
 | 
			
		||||
	  // user CSRs
 | 
			
		||||
	  CSRArray[12'h001] = CSRArrayOld[12'h001];
 | 
			
		||||
	  CSRArray[12'h002] = CSRArrayOld[12'h002];
 | 
			
		||||
	  CSRArray[12'h003] = CSRArrayOld[12'h003];
 | 
			
		||||
	end	  
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  genvar 							index;
 | 
			
		||||
  assign rf[0] = '0;
 | 
			
		||||
  for(index = 1; index < NUMREGS; index += 1) 
 | 
			
		||||
	assign rf[index] = testbench.dut.core.ieu.dp.regf.rf[index];
 | 
			
		||||
 | 
			
		||||
  assign rf_a3  = testbench.dut.core.ieu.dp.regf.a3;
 | 
			
		||||
  assign rf_we3 = testbench.dut.core.ieu.dp.regf.we3;
 | 
			
		||||
  
 | 
			
		||||
  always_comb begin
 | 
			
		||||
	rf_wb <= '0;
 | 
			
		||||
	if(rf_we3)
 | 
			
		||||
	  rf_wb[rf_a3] <= 1'b1;
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  for(index = 0; index < NUMREGS; index += 1) 
 | 
			
		||||
	assign frf[index] = testbench.dut.core.fpu.fpu.fregfile.rf[index];
 | 
			
		||||
  
 | 
			
		||||
  assign frf_a4  = testbench.dut.core.fpu.fpu.fregfile.a4;
 | 
			
		||||
  assign frf_we4 = testbench.dut.core.fpu.fpu.fregfile.we4;
 | 
			
		||||
  
 | 
			
		||||
  always_comb begin
 | 
			
		||||
	frf_wb <= '0;
 | 
			
		||||
	if(frf_we4)
 | 
			
		||||
	  frf_wb[frf_a4] <= 1'b1;
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  assign CSRAdrM  = testbench.dut.core.priv.priv.csr.CSRAdrM;
 | 
			
		||||
  assign CSRWriteM = testbench.dut.core.priv.priv.csr.CSRWriteM;
 | 
			
		||||
  
 | 
			
		||||
  // pipeline to writeback stage
 | 
			
		||||
  flopenrc #(`XLEN) InstrRawEReg (clk, reset, FlushE, ~StallE, InstrRawD, InstrRawE);
 | 
			
		||||
  flopenrc #(`XLEN) InstrRawMReg (clk, reset, FlushM, ~StallM, InstrRawE, InstrRawM);
 | 
			
		||||
  flopenrc #(`XLEN) InstrRawWReg (clk, reset, FlushW, ~StallW, InstrRawM, InstrRawW);
 | 
			
		||||
  flopenrc #(`XLEN) PCWReg (clk, reset, FlushW, ~StallW, PCM, PCW);
 | 
			
		||||
  flopenrc #(1)     InstrValidMReg (clk, reset, FlushW, ~StallW, InstrValidM, InstrValidW);
 | 
			
		||||
  flopenrc #(1)     TrapWReg (clk, reset, 1'b0, ~StallW, TrapM, TrapW);
 | 
			
		||||
  flopenrc #(1)     HaltWReg (clk, reset, 1'b0, ~StallW, HaltM, HaltW);
 | 
			
		||||
 | 
			
		||||
  flopenrc #(1)     IntrFReg (clk, reset, 1'b0, ~StallF, TrapM, IntrF);
 | 
			
		||||
  flopenrc #(1)     IntrDReg (clk, reset, FlushD, ~StallD, IntrF, IntrD);
 | 
			
		||||
  flopenrc #(1)     IntrEReg (clk, reset, FlushE, ~StallE, IntrD, IntrE);
 | 
			
		||||
  flopenrc #(1)     IntrMReg (clk, reset, FlushM, ~StallM, IntrE, IntrM);
 | 
			
		||||
  flopenrc #(1)     IntrWReg (clk, reset, FlushW, ~StallW, IntrM, IntrW);
 | 
			
		||||
 | 
			
		||||
  flopenrc #(12)    CSRAdrWReg (clk, reset, FlushW, ~StallW, CSRAdrM, CSRAdrW);
 | 
			
		||||
  flopenrc #(1)     CSRWriteWReg (clk, reset, FlushW, ~StallW, CSRWriteM, CSRWriteW);
 | 
			
		||||
 | 
			
		||||
  // Initially connecting the writeback stage signals, but may need to use M stage
 | 
			
		||||
  // and gate on ~FlushW.
 | 
			
		||||
 | 
			
		||||
  assign valid  = InstrValidW & ~StallW;
 | 
			
		||||
  assign rvvi.clk = clk;
 | 
			
		||||
  assign #1 rvvi.valid[0][0]    = valid;
 | 
			
		||||
  assign rvvi.order[0][0]    = CSRArray[12'hB02];  // TODO: IMPERAS Should be event order
 | 
			
		||||
  assign rvvi.insn[0][0]     = InstrRawW;
 | 
			
		||||
  assign rvvi.pc_rdata[0][0] = PCW;
 | 
			
		||||
  assign rvvi.trap[0][0]     = 0; // TODO: IMPERAS TrapW;
 | 
			
		||||
  assign rvvi.halt[0][0]     = HaltW;
 | 
			
		||||
  assign rvvi.intr[0][0]     = IntrW;
 | 
			
		||||
  assign rvvi.mode[0][0]     = PrivilegeModeW;
 | 
			
		||||
  assign rvvi.ixl[0][0]      = PrivilegeModeW == 2'b11 ? 2'b10 :
 | 
			
		||||
					           PrivilegeModeW == 2'b01 ? STATUS_SXL : STATUS_UXL;
 | 
			
		||||
  assign rvvi.pc_wdata[0][0] = ~FlushW ? PCM :
 | 
			
		||||
						       ~FlushM ? PCE :
 | 
			
		||||
						       ~FlushE ? PCD :
 | 
			
		||||
						       ~FlushD ? PCF : PCNextF;
 | 
			
		||||
 | 
			
		||||
  for(index = 0; index < `NUM_REGS; index += 1) begin
 | 
			
		||||
	assign rvvi.x_wdata[0][0][index] = rf[index];
 | 
			
		||||
	assign rvvi.x_wb[0][0][index]    = rf_wb[index];
 | 
			
		||||
	assign rvvi.f_wdata[0][0][index] = frf[index];
 | 
			
		||||
	assign rvvi.f_wb[0][0][index]    = frf_wb[index];
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  // record previous csr value.
 | 
			
		||||
  integer index4;
 | 
			
		||||
  always_ff @(posedge clk) begin
 | 
			
		||||
	for (index4 = 0; index4 < `NUM_CSRS; index4 += 1) begin
 | 
			
		||||
// IMPERAS
 | 
			
		||||
	  //CSR_W[index4] = (CSRArrayOld[index4] != CSRArray[index4]) ? 1 : 0;
 | 
			
		||||
	  CSRArrayOld[index4] = CSRArray[index4];
 | 
			
		||||
	end
 | 
			
		||||
  end
 | 
			
		||||
  
 | 
			
		||||
  // check for csr value change.
 | 
			
		||||
  genvar index5;
 | 
			
		||||
  for(index5 = 0; index5 < `NUM_CSRS; index5 += 1) begin
 | 
			
		||||
	// CSR_W should only indicate the change when the Writeback stage is not stalled and valid.
 | 
			
		||||
    assign #2 CSR_W[index5] = (CSRArrayOld[index5] != CSRArray[index5]) ? 1 : 0;
 | 
			
		||||
    assign rvvi.csr_wb[0][0][index5] = CSR_W[index5];
 | 
			
		||||
    assign rvvi.csr[0][0][index5]    = CSRArray[index5];
 | 
			
		||||
  end
 | 
			
		||||
  
 | 
			
		||||
//  always @rvvi.clk $display("%t @rvvi.clk=%X", $time, rvvi.clk);
 | 
			
		||||
//  always @rvvi.csr[0][0]['h300] $display("%t rvvi.csr[0][0]['h300]=%X", $time, rvvi.csr[0][0]['h300]);
 | 
			
		||||
//  always @rvvi.csr_wb[0][0]['h300] $display("%t rvvi.csr_wb[0][0]['h300]=%X", $time, rvvi.csr_wb[0][0]['h300]);
 | 
			
		||||
//  always @rvvi.valid[0][0] $display("%t rvvi.valid[0][0]=%X", $time, rvvi.valid[0][0]);
 | 
			
		||||
  
 | 
			
		||||
  // *** implementation only cancel? so sc does not clear?
 | 
			
		||||
  assign rvvi.lrsc_cancel[0][0] = '0;
 | 
			
		||||
 | 
			
		||||
  integer index2;
 | 
			
		||||
 | 
			
		||||
  always_ff @(posedge clk) begin
 | 
			
		||||
	if(rvvi.valid[0][0]) begin
 | 
			
		||||
	  if(`PRINT_PC_INSTR & !(`PRINT_ALL | `PRINT_MOST))
 | 
			
		||||
		$display("order = %08d, PC = %08x, insn = %08x", rvvi.order[0][0], rvvi.pc_rdata[0][0], rvvi.insn[0][0]);
 | 
			
		||||
	  else if(`PRINT_MOST & !`PRINT_ALL)
 | 
			
		||||
		$display("order = %08d, PC = %010x, insn = %08x, trap = %1d, halt = %1d, intr = %1d, mode = %1x, ixl = %1x, pc_wdata = %010x, x%02d = %016x, f%02d = %016x, csr%03x = %016x", 
 | 
			
		||||
		        rvvi.order[0][0], rvvi.pc_rdata[0][0], rvvi.insn[0][0], rvvi.trap[0][0], rvvi.halt[0][0], rvvi.intr[0][0], rvvi.mode[0][0], rvvi.ixl[0][0], rvvi.pc_wdata[0][0], rf_a3, rvvi.x_wdata[0][0][rf_a3], frf_a4, rvvi.f_wdata[0][0][frf_a4], CSRAdrW, rvvi.csr[0][0][CSRAdrW]);
 | 
			
		||||
	  else if(`PRINT_ALL) begin
 | 
			
		||||
		$display("order = %08d, PC = %08x, insn = %08x, trap = %1d, halt = %1d, intr = %1d, mode = %1x, ixl = %1x, pc_wdata = %08x", 
 | 
			
		||||
				 rvvi.order[0][0], rvvi.pc_rdata[0][0], rvvi.insn[0][0], rvvi.trap[0][0], rvvi.halt[0][0], rvvi.intr[0][0], rvvi.mode[0][0], rvvi.ixl[0][0], rvvi.pc_wdata[0][0]);
 | 
			
		||||
	  	for(index2 = 0; index2 < `NUM_REGS; index2 += 1) begin
 | 
			
		||||
		  $display("x%02d = %08x", index2, rvvi.x_wdata[0][0][index2]);
 | 
			
		||||
		end
 | 
			
		||||
		for(index2 = 0; index2 < `NUM_REGS; index2 += 1) begin
 | 
			
		||||
		  $display("f%02d = %08x", index2, rvvi.f_wdata[0][0][index2]);
 | 
			
		||||
		end
 | 
			
		||||
	  end
 | 
			
		||||
	  if (`PRINT_CSRS) begin
 | 
			
		||||
		for(index2 = 0; index2 < `NUM_CSRS; index2 += 1) begin
 | 
			
		||||
		  if(CSR_W[index2]) begin
 | 
			
		||||
			$display("%t: CSR %03x = %x", $time(), index2, CSRArray[index2]);
 | 
			
		||||
		  end
 | 
			
		||||
		end
 | 
			
		||||
	  end
 | 
			
		||||
	end
 | 
			
		||||
    if(HaltW) $finish;
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
@ -471,15 +471,20 @@ logic [3:0] dummy;
 | 
			
		||||
      genvar adrindex;
 | 
			
		||||
      
 | 
			
		||||
      // Initializing all zeroes into the branch predictor memory.
 | 
			
		||||
      for(adrindex = 0; adrindex < 1024; adrindex++) begin
 | 
			
		||||
      for(adrindex = 0; adrindex < 2**10; adrindex++) begin
 | 
			
		||||
        initial begin 
 | 
			
		||||
        force dut.core.ifu.bpred.bpred.Predictor.DirPredictor.PHT.mem[adrindex] = 0;
 | 
			
		||||
        force dut.core.ifu.bpred.bpred.TargetPredictor.memory.mem[adrindex] = 0;
 | 
			
		||||
        #1;
 | 
			
		||||
        release dut.core.ifu.bpred.bpred.Predictor.DirPredictor.PHT.mem[adrindex];
 | 
			
		||||
        release dut.core.ifu.bpred.bpred.TargetPredictor.memory.mem[adrindex];
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
      for(adrindex = 0; adrindex < 2**`BPRED_SIZE; adrindex++) begin
 | 
			
		||||
        initial begin 
 | 
			
		||||
        force dut.core.ifu.bpred.bpred.Predictor.DirPredictor.PHT.mem[adrindex] = 0;
 | 
			
		||||
        #1;
 | 
			
		||||
        release dut.core.ifu.bpred.bpred.Predictor.DirPredictor.PHT.mem[adrindex];
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      if (`BPRED_LOGGER) begin
 | 
			
		||||
        string direction;
 | 
			
		||||
 | 
			
		||||
@ -31,10 +31,21 @@
 | 
			
		||||
 | 
			
		||||
`include "wally-config.vh"
 | 
			
		||||
 | 
			
		||||
// This is set from the commsnd line script
 | 
			
		||||
// `define USE_IMPERAS_DV
 | 
			
		||||
 | 
			
		||||
`ifdef USE_IMPERAS_DV
 | 
			
		||||
  `include "rvvi/imperasDV.svh"
 | 
			
		||||
`endif
 | 
			
		||||
 | 
			
		||||
module testbench;
 | 
			
		||||
  parameter DEBUG=0;
 | 
			
		||||
 | 
			
		||||
`ifdef USE_IMPERAS_DV
 | 
			
		||||
  import rvviPkg::*;
 | 
			
		||||
  import rvviApiPkg::*;
 | 
			
		||||
`endif
 | 
			
		||||
 | 
			
		||||
  logic        clk;
 | 
			
		||||
  logic        reset_ext, reset;
 | 
			
		||||
 | 
			
		||||
@ -63,7 +74,7 @@ module testbench;
 | 
			
		||||
  integer   	ProgramAddrLabelArray [string] = '{ "begin_signature" : 0, "tohost" : 0 };
 | 
			
		||||
  logic 	    DCacheFlushDone, DCacheFlushStart;
 | 
			
		||||
  string 		testName;
 | 
			
		||||
  string memfilename, pathname, adrstr;
 | 
			
		||||
  string memfilename, testDir, adrstr, elffilename;
 | 
			
		||||
 | 
			
		||||
  logic [31:0] GPIOPinsIn, GPIOPinsOut, GPIOPinsEn;
 | 
			
		||||
  logic        UARTSin, UARTSout;
 | 
			
		||||
@ -92,28 +103,90 @@ module testbench;
 | 
			
		||||
      testadr = 0;
 | 
			
		||||
      testadrNoBase = 0;
 | 
			
		||||
 | 
			
		||||
	  //testName =     "rv64i_m/I/src/add-01.S";
 | 
			
		||||
	  testName =     "rv64i_m/privilege/src/WALLY-mmu-sv48-01.S";
 | 
			
		||||
      if ($value$plusargs("testDir=%s", testDir)) begin
 | 
			
		||||
          memfilename = {testDir, "/ref/ref.elf.memfile"};
 | 
			
		||||
          elffilename = {testDir, "/ref/ref.elf"};
 | 
			
		||||
          $display($sformatf("%m @ t=%0t: loading testDir %0s", $time, testDir));
 | 
			
		||||
      end else begin
 | 
			
		||||
          $error("Must specify test directory using plusarg testDir");
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	  //pathname =     "../../tests/riscof/work/riscv-arch-test/";
 | 
			
		||||
	  pathname = "../../tests/riscof/work/wally-riscv-arch-test/";
 | 
			
		||||
	  
 | 
			
		||||
	  memfilename = {pathname, testName, "/ref/ref.elf.memfile"};
 | 
			
		||||
      if (`BUS_SUPPORTED) $readmemh(memfilename, dut.uncore.uncore.ram.ram.memory.RAM);
 | 
			
		||||
	  else $error("Imperas test bench requires BUS_SUPPORTED.");
 | 
			
		||||
	  else $error("Imperas test bench requires BUS.");
 | 
			
		||||
 | 
			
		||||
      ProgramAddrMapFile = {pathname, testName, "/ref/ref.elf.objdump.addr"};
 | 
			
		||||
      ProgramLabelMapFile = {pathname, testName, "/ref/ref.elf.objdump.lab"};
 | 
			
		||||
      ProgramAddrMapFile = {testDir, "/ref/ref.elf.objdump.addr"};
 | 
			
		||||
      ProgramLabelMapFile = {testDir, "/ref/ref.elf.objdump.lab"};
 | 
			
		||||
      
 | 
			
		||||
      // declare memory labels that interest us, the updateProgramAddrLabelArray task will find the addr of each label and fill the array
 | 
			
		||||
      // to expand, add more elements to this array and initialize them to zero (also initilaize them to zero at the start of the next test)
 | 
			
		||||
      updateProgramAddrLabelArray(ProgramAddrMapFile, ProgramLabelMapFile, ProgramAddrLabelArray);
 | 
			
		||||
      $display("Read memfile %s", memfilename);
 | 
			
		||||
      
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
  rvviTrace rvviTrace();
 | 
			
		||||
  rvviTrace #(.XLEN(`XLEN), .FLEN(`FLEN)) rvvi();
 | 
			
		||||
  wallyTracer wallyTracer(rvvi);
 | 
			
		||||
 | 
			
		||||
`ifdef USE_IMPERAS_DV
 | 
			
		||||
    trace2log idv_trace2log(rvvi);
 | 
			
		||||
 | 
			
		||||
    // enabling of comparison types
 | 
			
		||||
    trace2api #(.CMP_PC      (1),
 | 
			
		||||
                .CMP_INS     (1),
 | 
			
		||||
                .CMP_GPR     (1),
 | 
			
		||||
                .CMP_FPR     (1),
 | 
			
		||||
                .CMP_VR      (0),
 | 
			
		||||
                .CMP_CSR     (1)
 | 
			
		||||
               ) idv_trace2api(rvvi);
 | 
			
		||||
 | 
			
		||||
    initial begin 
 | 
			
		||||
      MAX_ERRS = 3;
 | 
			
		||||
 | 
			
		||||
      // Initialize REF (do this before initializing the DUT)
 | 
			
		||||
      if (!rvviVersionCheck(RVVI_API_VERSION)) begin
 | 
			
		||||
        msgfatal($sformatf("%m @ t=%0t: Expecting RVVI API version %0d.", $time, RVVI_API_VERSION));
 | 
			
		||||
      end
 | 
			
		||||
      void'(rvviRefConfigSetString(IDV_CONFIG_MODEL_VENDOR,  "riscv.ovpworld.org"));
 | 
			
		||||
      void'(rvviRefConfigSetString(IDV_CONFIG_MODEL_NAME,    "riscv"));
 | 
			
		||||
      void'(rvviRefConfigSetString(IDV_CONFIG_MODEL_VARIANT, "RV64GC"));
 | 
			
		||||
      if (!rvviRefInit(elffilename)) begin
 | 
			
		||||
        msgfatal($sformatf("%m @ t=%0t: rvviRefInit failed", $time));
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      // Volatile CSRs
 | 
			
		||||
      void'(rvviRefCsrSetVolatile(0, 32'hC00));   // CYCLE
 | 
			
		||||
      void'(rvviRefCsrSetVolatile(0, 32'hB00));   // MCYCLE
 | 
			
		||||
      void'(rvviRefCsrSetVolatile(0, 32'hC02));   // INSTRET
 | 
			
		||||
      void'(rvviRefCsrSetVolatile(0, 32'hB02));   // MINSTRET
 | 
			
		||||
      void'(rvviRefCsrSetVolatile(0, 32'hC01));   // TIME
 | 
			
		||||
 | 
			
		||||
      if(`XLEN==32) begin
 | 
			
		||||
          void'(rvviRefCsrSetVolatile(0, 32'hC80));   // CYCLEH
 | 
			
		||||
          void'(rvviRefCsrSetVolatile(0, 32'hB80));   // MCYCLEH
 | 
			
		||||
          void'(rvviRefCsrSetVolatile(0, 32'hC82));   // INSTRETH
 | 
			
		||||
          void'(rvviRefCsrSetVolatile(0, 32'hB82));   // MINSTRETH
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
  //    // Temporary fix for inexact difference
 | 
			
		||||
//      void'(rvviRefCsrSetVolatile(0, 32'h001));   // fflags
 | 
			
		||||
//      void'(rvviRefCsrSetVolatile(0, 32'h003));   // fcsr
 | 
			
		||||
      
 | 
			
		||||
      
 | 
			
		||||
      // Enable the trace2log module
 | 
			
		||||
      if ($value$plusargs("TRACE2LOG_ENABLE=%d", TRACE2LOG_ENABLE)) begin
 | 
			
		||||
        msgnote($sformatf("%m @ t=%0t: TRACE2LOG_ENABLE is %0d", $time, TRACE2LOG_ENABLE));
 | 
			
		||||
      end
 | 
			
		||||
      
 | 
			
		||||
      if ($value$plusargs("TRACE2COV_ENABLE=%d", TRACE2COV_ENABLE)) begin
 | 
			
		||||
        msgnote($sformatf("%m @ t=%0t: TRACE2COV_ENABLE is %0d", $time, TRACE2COV_ENABLE));
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    final begin
 | 
			
		||||
      void'(rvviRefShutdown());
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
`endif
 | 
			
		||||
 | 
			
		||||
  flopenr #(`XLEN) PCWReg(clk, reset, ~dut.core.ieu.dp.StallW, dut.core.ifu.PCM, PCW);
 | 
			
		||||
  flopenr  #(32)   InstrWReg(clk, reset, ~dut.core.ieu.dp.StallW,  dut.core.ifu.InstrM, InstrW);
 | 
			
		||||
@ -158,7 +231,7 @@ module testbench;
 | 
			
		||||
 | 
			
		||||
  // Track names of instructions
 | 
			
		||||
  instrTrackerTB it(clk, reset, dut.core.ieu.dp.FlushE,
 | 
			
		||||
                dut.core.ifu.FinalInstrRawF[31:0],
 | 
			
		||||
                dut.core.ifu.InstrRawF[31:0],
 | 
			
		||||
                dut.core.ifu.InstrD, dut.core.ifu.InstrE,
 | 
			
		||||
                dut.core.ifu.InstrM,  InstrW,
 | 
			
		||||
                InstrFName, InstrDName, InstrEName, InstrMName, InstrWName);
 | 
			
		||||
@ -254,7 +327,6 @@ module testbench;
 | 
			
		||||
	end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
module riscvassertions;
 | 
			
		||||
@ -267,17 +339,17 @@ module riscvassertions;
 | 
			
		||||
    assert (`F_SUPPORTED | ~`ZFH_SUPPORTED) else $error("Can't support half-precision fp (ZFH) without supporting float (F)");
 | 
			
		||||
    assert (`DCACHE_SUPPORTED | ~`F_SUPPORTED | `FLEN <= `XLEN) else $error("Data cache required to support FLEN > XLEN because AHB bus width is XLEN");
 | 
			
		||||
    assert (`I_SUPPORTED ^ `E_SUPPORTED) else $error("Exactly one of I and E must be supported");
 | 
			
		||||
    assert (`FLEN<=`XLEN | `DCACHE | `DTIM_SUPPORTED) else $error("Wally does not support FLEN > XLEN unleses data cache or DTIM is supported");
 | 
			
		||||
    assert (`FLEN<=`XLEN | `DCACHE_SUPPORTED | `DTIM_SUPPORTED) else $error("Wally does not support FLEN > XLEN unleses data cache or DTIM is supported");
 | 
			
		||||
    assert (`DCACHE_WAYSIZEINBYTES <= 4096 | (!`DCACHE_SUPPORTED) | `VIRTMEM_SUPPORTED == 0) else $error("DCACHE_WAYSIZEINBYTES cannot exceed 4 KiB when caches and vitual memory is enabled (to prevent aliasing)");
 | 
			
		||||
    assert (`DCACHE_LINELENINBITS >= 128 | (!`DCACH_SUPPORTED)) else $error("DCACHE_LINELENINBITS must be at least 128 when caches are enabled");
 | 
			
		||||
    assert (`DCACHE_LINELENINBITS >= 128 | (!`DCACHE_SUPPORTED)) else $error("DCACHE_LINELENINBITS must be at least 128 when caches are enabled");
 | 
			
		||||
    assert (`DCACHE_LINELENINBITS < `DCACHE_WAYSIZEINBYTES*8) else $error("DCACHE_LINELENINBITS must be smaller than way size");
 | 
			
		||||
    assert (`ICACHE_WAYSIZEINBYTES <= 4096 | (!`ICACHE_SUPPORTED) | `VIRTMEM_SUPPORTED == 0) else $error("ICACHE_WAYSIZEINBYTES cannot exceed 4 KiB when caches and vitual memory is enabled (to prevent aliasing)");
 | 
			
		||||
    assert (`ICACHE_LINELENINBITS >= 32 | (!`ICACHE_SUPPORTED)) else $error("ICACHE_LINELENINBITS must be at least 32 when caches are enabled");
 | 
			
		||||
    assert (`ICACHE_LINELENINBITS < `ICACHE_WAYSIZEINBYTES*8) else $error("ICACHE_LINELENINBITS must be smaller than way size");
 | 
			
		||||
    assert (2**$clog2(`DCACHE_LINELENINBITS) == `DCACHE_LINELENINBITS | (!`DCACHE)) else $error("DCACHE_LINELENINBITS must be a power of 2");
 | 
			
		||||
    assert (2**$clog2(`DCACHE_WAYSIZEINBYTES) == `DCACHE_WAYSIZEINBYTES | (!`DCACHE)) else $error("DCACHE_WAYSIZEINBYTES must be a power of 2");
 | 
			
		||||
    assert (2**$clog2(`ICACHE_LINELENINBITS) == `ICACHE_LINELENINBITS | (!`ICACHE)) else $error("ICACHE_LINELENINBITS must be a power of 2");
 | 
			
		||||
    assert (2**$clog2(`ICACHE_WAYSIZEINBYTES) == `ICACHE_WAYSIZEINBYTES | (!`ICACHE)) else $error("ICACHE_WAYSIZEINBYTES must be a power of 2");
 | 
			
		||||
    assert (2**$clog2(`DCACHE_LINELENINBITS) == `DCACHE_LINELENINBITS | (!`DCACHE_SUPPORTED)) else $error("DCACHE_LINELENINBITS must be a power of 2");
 | 
			
		||||
    assert (2**$clog2(`DCACHE_WAYSIZEINBYTES) == `DCACHE_WAYSIZEINBYTES | (!`DCACHE_SUPPORTED)) else $error("DCACHE_WAYSIZEINBYTES must be a power of 2");
 | 
			
		||||
    assert (2**$clog2(`ICACHE_LINELENINBITS) == `ICACHE_LINELENINBITS | (!`ICACHE_SUPPORTED)) else $error("ICACHE_LINELENINBITS must be a power of 2");
 | 
			
		||||
    assert (2**$clog2(`ICACHE_WAYSIZEINBYTES) == `ICACHE_WAYSIZEINBYTES | (!`ICACHE_SUPPORTED)) else $error("ICACHE_WAYSIZEINBYTES must be a power of 2");
 | 
			
		||||
    assert (2**$clog2(`ITLB_ENTRIES) == `ITLB_ENTRIES | `VIRTMEM_SUPPORTED==0) else $error("ITLB_ENTRIES must be a power of 2");
 | 
			
		||||
    assert (2**$clog2(`DTLB_ENTRIES) == `DTLB_ENTRIES | `VIRTMEM_SUPPORTED==0) else $error("DTLB_ENTRIES must be a power of 2");
 | 
			
		||||
    assert (`UNCORE_RAM_RANGE >= 56'h07FFFFFF) else $warning("Some regression tests will fail if UNCORE_RAM_RANGE is less than 56'h07FFFFFF");
 | 
			
		||||
@ -288,7 +360,7 @@ module riscvassertions;
 | 
			
		||||
    assert (`DCACHE_SUPPORTED | `VIRTMEM_SUPPORTED ==0) else $error("Virtual memory needs dcache");
 | 
			
		||||
    assert (`ICACHE_SUPPORTED | `VIRTMEM_SUPPORTED ==0) else $error("Virtual memory needs icache");
 | 
			
		||||
    assert ((`DCACHE_SUPPORTED == 0 & `ICACHE_SUPPORTED == 0) | `BUS_SUPPORTED) else $error("Dcache and Icache requires DBUS.");
 | 
			
		||||
    assert (`DCACHE_LINELENINBITS <= `XLEN*16 | (!`DCACHE)) else $error("DCACHE_LINELENINBITS must not exceed 16 words because max AHB burst size is 1");
 | 
			
		||||
    assert (`DCACHE_LINELENINBITS <= `XLEN*16 | (!`DCACHE_SUPPORTED)) else $error("DCACHE_LINELENINBITS must not exceed 16 words because max AHB burst size is 1");
 | 
			
		||||
    assert (`DCACHE_LINELENINBITS % 4 == 0) else $error("DCACHE_LINELENINBITS must hold 4, 8, or 16 words");
 | 
			
		||||
    assert (`DCACHE_SUPPORTED | `A_SUPPORTED == 0) else $error("Atomic extension (A) requires cache on Wally.");
 | 
			
		||||
    assert (`IDIV_ON_FPU == 0 | `F_SUPPORTED) else $error("IDIV on FPU needs F_SUPPORTED");
 | 
			
		||||
@ -311,7 +383,7 @@ module DCacheFlushFSM
 | 
			
		||||
 | 
			
		||||
  logic [`XLEN-1:0] ShadowRAM[`UNCORE_RAM_BASE>>(1+`XLEN/32):(`UNCORE_RAM_RANGE+`UNCORE_RAM_BASE)>>1+(`XLEN/32)];
 | 
			
		||||
  
 | 
			
		||||
	if(`DCACHE) begin
 | 
			
		||||
	if(`DCACHE_SUPPORTED) begin
 | 
			
		||||
	  localparam integer numlines = testbench.dut.core.lsu.bus.dcache.dcache.NUMLINES;
 | 
			
		||||
	  localparam integer numways = testbench.dut.core.lsu.bus.dcache.dcache.NUMWAYS;
 | 
			
		||||
	  localparam integer linebytelen = testbench.dut.core.lsu.bus.dcache.dcache.LINEBYTELEN;
 | 
			
		||||
@ -413,6 +485,7 @@ module copyShadow
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
  
 | 
			
		||||
  
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
task automatic updateProgramAddrLabelArray;
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										57
									
								
								setup.imperas.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								setup.imperas.sh
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,57 @@
 | 
			
		||||
#!/bin/bash
 | 
			
		||||
 | 
			
		||||
IMP_HASH=56b1479
 | 
			
		||||
 | 
			
		||||
REPO=davidharrishmc
 | 
			
		||||
REPO=eroom1966
 | 
			
		||||
git clone https://github.com/${REPO}/riscv-wally -b imperas
 | 
			
		||||
 | 
			
		||||
cd riscv-wally
 | 
			
		||||
WALLY=$(dirname ${BASH_SOURCE[0]:-$0})
 | 
			
		||||
export WALLY=$(cd "$WALLY" && pwd)
 | 
			
		||||
 | 
			
		||||
# clone the Imperas repo
 | 
			
		||||
if [ ! -d external ]; then
 | 
			
		||||
    mkdir -p external
 | 
			
		||||
fi
 | 
			
		||||
pushd external
 | 
			
		||||
    if [ ! -f ImperasDV-HMC ]; then
 | 
			
		||||
        git clone git@github.com:Imperas/ImperasDV-HMC.git
 | 
			
		||||
    fi
 | 
			
		||||
    pushd ImperasDV-HMC
 | 
			
		||||
        git checkout $IMP_HASH
 | 
			
		||||
    popd
 | 
			
		||||
popd
 | 
			
		||||
 | 
			
		||||
# Setup Imperas
 | 
			
		||||
source ${WALLY}/external/ImperasDV-HMC/Imperas/bin/setup.sh
 | 
			
		||||
setupImperas ${WALLY}/external/ImperasDV-HMC/Imperas
 | 
			
		||||
export IMPERAS_PERSONALITY=CPUMAN_DV_ASYNC
 | 
			
		||||
 | 
			
		||||
# setup QUESTA (Imperas only command, YMMV)
 | 
			
		||||
svsetup -questa
 | 
			
		||||
 | 
			
		||||
pushd pipelined/regression
 | 
			
		||||
    # With IDV
 | 
			
		||||
    IMPERAS_TOOLS=$(pwd)/imperas.ic \
 | 
			
		||||
        OTHERFLAGS="+TRACE2LOG_ENABLE=1 VERBOSE=1" \
 | 
			
		||||
        TESTDIR=${WALLY}/external/ImperasDV-HMC/tests/riscof/work/riscv-arch-test/rv64i_m/F/src/fadd_b1-01.S  \
 | 
			
		||||
        vsim -c -do "do wally-pipelined-imperas.do rv64gc"
 | 
			
		||||
popd
 | 
			
		||||
 | 
			
		||||
# notes
 | 
			
		||||
# run the pushd external  code
 | 
			
		||||
 | 
			
		||||
#source external/ImperasDV-HMC/Imperas/bin/setup.sh 
 | 
			
		||||
#  setupImperas /home/ross/repos/active-wally/riscv-wally/external/ImperasDV-HMC/Imperas
 | 
			
		||||
#  env | grep IMPERAS
 | 
			
		||||
#  export IMPERAS_PERSONALITY=CPUMAN_DV_ASYNC
 | 
			
		||||
 | 
			
		||||
IMPERAS_TOOLS=$(pwd)/imperas.ic \
 | 
			
		||||
OTHERFLAGS="+TRACE2LOG_ENABLE=1 VERBOSE=1" \
 | 
			
		||||
TESTDIR=../../tests/riscof_lee/work/riscv-arch-test/rv64i_m/F/src/fadd_b1-01.S  \
 | 
			
		||||
vsim -c -do "do wally-pipelined-imperas.do rv64gc"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# getting library issue.
 | 
			
		||||
# try switching to modelsim 2022.01
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user