Merge upstream changes

This commit is contained in:
Jarred Allen 2021-03-09 21:20:34 -05:00
commit c0ee17b6ac
66 changed files with 471755 additions and 3968 deletions

View File

@ -0,0 +1,47 @@
#!/bin/bash
allProgramRadixFile="FunctionRadix"
index=0
for objDumpFile in "$@";
do
# get the lines with named labels from the obj files.
# 64 bit addresses
listOfAddr16=`egrep -i '^[0-9]{16} <[0-9a-zA-Z_]+>' $objDumpFile`
# 32 bit addresses
listOfAddr8=`egrep -i '^[0-9]{8} <[0-9a-zA-Z_]+>' $objDumpFile`
listOfAddr=`echo "$listOfAddr16" "$listOfAddr8"`
# parse out the addresses and the labels
addresses=`echo "$listOfAddr" | awk '{print $1}'`
labels=`echo "$listOfAddr" | awk '{print "\""$2"\"", "-color \"SpringGreen\","}' | tr -d '<>:'`
echo "$addresses" > $objDumpFile.addr
# need to add some formatting to each line
numLines=`echo "$listOfAddr" | wc -l`
prefix=`yes " 16#" | head -n $numLines`
midfix=`yes "# " | head -n $numLines`
# paste echos each of the 4 parts on a per line basis.
#-d'\0' sets no delimiter
temp=`paste -d'\0' <(echo "$prefix") <(echo "$addresses") <(echo "$midfix") <(echo "$labels")`
# remove the last comma
temp2=${temp::-1}
echo "radix define Functions {" > $objDumpFile.do
echo "$temp2" >> $objDumpFile.do
echo " -default hex -color green" >> $objDumpFile.do
echo "}" >> $objDumpFile.do
# now create the all in one version
# put the index at the begining of each line
allAddresses=`paste -d'\0' <(printf "%04x" "$index") <(echo "$addresses")`
printf "%04x%s" "$index" "$addresses" >> $allProgramRadixFile.addr
index=$(($index+1))
done

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
//////////////////////////////////////////
// wally-config.vh
// busybear-config.vh
//
// Written: David_Harris@hmc.edu 4 January 2021
// Modified:
@ -24,6 +24,7 @@
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
///////////////////////////////////////////
`define BUSYBEAR
// RV32 or RV64: XLEN = 32 or 64
`define XLEN 64
@ -61,14 +62,16 @@
// Peripheral memory space extends from BASE to BASE+RANGE
// Range should be a thermometer code with 0's in the upper bits and 1s in the lower bits
`define TIMBASE 64'h0000000080000000
`define TIMRANGE 64'h000000000007FFFF
`define CLINTBASE 64'h0000000002000000
`define CLINTRANGE 64'h000000000000FFFF
`define GPIOBASE 64'h0000000010012000
`define GPIORANGE 64'h00000000000000FF
`define UARTBASE 64'h0000000010000000
`define UARTRANGE 64'h0000000000000007
`define TIMBASE 32'h80000000
`define TIMRANGE 32'h07FFFFFF
`define BOOTTIMBASE 32'h00000000 //only needs to go from 0x1000 to 0x2FFF, extending to a power of 2
`define BOOTTIMRANGE 32'h00003FFF
`define CLINTBASE 32'h02000000
`define CLINTRANGE 32'h0000BFFF
//`define GPIOBASE 32'h10012000 // no GPIO in linux for now
//`define GPIORANGE 32'h000000FF
`define UARTBASE 32'h10000000
`define UARTRANGE 32'h00000007
// Bus Interface width
`define AHBW 64

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -27,8 +27,8 @@
// RV32 or RV64: XLEN = 32 or 64
`define XLEN 64
//`define MISA (32'h00000104)
`define MISA (32'h00000104 | 1<<5 | 1<<18 | 1 << 20 | 1 << 12)
//`define MISA (32'h00000105)
`define MISA (32'h00000104 | 1<<5 | 1<<18 | 1 << 20 | 1 << 12 | 1 << 0)
`define A_SUPPORTED ((`MISA >> 0) % 2 == 1)
`define C_SUPPORTED ((`MISA >> 2) % 2 == 1)
`define D_SUPPORTED ((`MISA >> 3) % 2 == 1)

File diff suppressed because it is too large Load Diff

View File

@ -30,6 +30,7 @@ def test_config(config, print_res=True):
passed = search_log_for_text("no more .* to read", logname)
else:
cmd = "vsim -c >" + logname +" <<!\ndo wally-pipelined-batch-parallel.do ../config/" + config + " " + config + "\n!\n"
print(cmd)
os.system(cmd)
# check for success. grep returns 0 if found, 1 if not found
passed = search_log_for_text("All tests ran without failures", logname)

View File

@ -0,0 +1 @@
vsim -do wally-busybear.do

View File

@ -0,0 +1,3 @@
vsim -c <<!
do wally-busybear-batch.do
!

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,46 @@
# wally-pipelined.do
#
# Modification by Oklahoma State University & Harvey Mudd College
# Use with testbench_busybear
# James Stine, 2008; David Harris 2021
# Go Cowboys!!!!!!
#
# Takes 1:10 to run RV64IC tests using gui
# 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-busybear] {
vdel -all -lib work-busybear
}
vlib work-busybear
# compile source files
# suppress spurious warnngs about
# "Extra checking for conflicts with always_comb done at vopt time"
# because vsim will run vopt
vlog +incdir+../config/busybear ../testbench/*.sv ../src/*/*.sv -suppress 2583
# start and run simulation
# remove +acc flag for faster sim during regressions if there is no need to access internal signals
vopt +acc=+/testbench_busybear/dut/hart/ifu/bpred/DirPredictor/memory/memory +acc=+/testbench_busybear/dut/hart/ifu/bpred/TargetPredictor/memory/memory work.testbench_busybear -o workopt
vsim workopt -suppress 8852,12070
# load the branch predictors with known data. The value of the data is not important for function, but
# is important for perventing pessimistic x propagation.
mem load -infile twoBitPredictor.txt -format bin testbench_busybear/dut/hart/ifu/bpred/DirPredictor/memory/memory
switch $argc {
0 {mem load -infile ../config/rv64ic/BTBPredictor.txt -format bin testbench_busybear/dut/hart/ifu/bpred/TargetPredictor/memory/memory}
1 {mem load -infile ../config/$1/BTBPredictor.txt -format bin testbench_busybear/dut/hart/ifu/bpred/TargetPredictor/memory/memory}
}
run -all
quit

View File

@ -1,136 +1,171 @@
# wally-pipelined.do
#
# Modification by Oklahoma State University & Harvey Mudd College
# Use with testbench_busybear
# James Stine, 2008; David Harris 2021
# Go Cowboys!!!!!!
#
# Takes 1:10 to run RV64IC tests using gui
# 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-busybear] {
vdel -all -lib work-busybear
}
vlib work-busybear
# compile source files
# suppress spurious warnngs about
# "Extra checking for conflicts with always_comb done at vopt time"
# because vsim will run vopt
# wally-pipelined.do
#
# Modification by Oklahoma State University & Harvey Mudd College
# Use with testbench_busybear
# James Stine, 2008; David Harris 2021
# Go Cowboys!!!!!!
#
# Takes 1:10 to run RV64IC tests using gui
# 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-busybear] {
vdel -all -lib work-busybear
}
vlib work-busybear
# compile source files
# suppress spurious warnngs about
# "Extra checking for conflicts with always_comb done at vopt time"
# because vsim will run vopt
vlog +incdir+../config/busybear ../testbench/*.sv ../src/*/*.sv -suppress 2583
# start and run simulation
# remove +acc flag for faster sim during regressions if there is no need to access internal signals
vopt +acc work.testbench_busybear -o workopt
vsim workopt
view wave
-- display input and output signals as hexidecimal values
# Diplays All Signals recursively
add wave /testbench_busybear/clk
add wave /testbench_busybear/reset
add wave -divider
# start and run simulation
# remove +acc flag for faster sim during regressions if there is no need to access internal signals
vopt +acc work.testbench_busybear -o workopt
vsim workopt -suppress 8852,12070
# load the branch predictors with known data. The value of the data is not important for function, but
# is important for perventing pessimistic x propagation.
mem load -infile twoBitPredictor.txt -format bin testbench_busybear/dut/hart/ifu/bpred/DirPredictor/memory/memory
switch $argc {
0 {mem load -infile ../config/rv64ic/BTBPredictor.txt -format bin testbench_busybear/dut/hart/ifu/bpred/TargetPredictor/memory/memory}
1 {mem load -infile ../config/$1/BTBPredictor.txt -format bin testbench_busybear/dut/hart/ifu/bpred/TargetPredictor/memory/memory}
}
view wave
-- display input and output signals as hexidecimal values
# Diplays All Signals recursively
add wave /testbench_busybear/clk
add wave /testbench_busybear/reset
add wave -divider
add wave -hex /testbench_busybear/PCtext
add wave -hex /testbench_busybear/pcExpected
add wave -hex /testbench_busybear/dut/ifu/PCF
add wave -hex /testbench_busybear/dut/ifu/InstrF
add wave /testbench_busybear/lastInstrF
add wave -hex /testbench_busybear/dut/hart/ifu/PCF
add wave -hex /testbench_busybear/dut/hart/ifu/InstrF
add wave -hex /testbench_busybear/dut/hart/ifu/StallD
add wave -hex /testbench_busybear/dut/hart/ifu/FlushD
add wave -hex /testbench_busybear/dut/hart/ifu/InstrRawD
add wave /testbench_busybear/CheckInstrF
add wave /testbench_busybear/lastCheckInstrF
add wave /testbench_busybear/speculative
add wave /testbench_busybear/lastPC2
add wave -divider
# registers!
add wave -divider
add wave -divider
add wave /testbench_busybear/dut/uncore/HSELBootTim
add wave /testbench_busybear/dut/uncore/HSELTim
add wave /testbench_busybear/dut/uncore/HREADTim
add wave /testbench_busybear/dut/uncore/dtim/HREADTim0
add wave /testbench_busybear/dut/uncore/HREADYTim
add wave -divider
add wave /testbench_busybear/dut/uncore/HREADBootTim
add wave /testbench_busybear/dut/uncore/bootdtim/HREADTim0
add wave /testbench_busybear/dut/uncore/HREADYBootTim
add wave /testbench_busybear/dut/uncore/HADDR
add wave /testbench_busybear/dut/uncore/HRESP
add wave /testbench_busybear/dut/uncore/HREADY
add wave /testbench_busybear/dut/uncore/HRDATA
#add wave -hex /testbench_busybear/dut/hart/priv/csr/MTVEC_REG
#add wave -hex /testbench_busybear/dut/hart/priv/csr/MSTATUS_REG
#add wave -hex /testbench_busybear/dut/hart/priv/csr/SCOUNTEREN_REG
#add wave -hex /testbench_busybear/dut/hart/priv/csr/MIE_REG
#add wave -hex /testbench_busybear/dut/hart/priv/csr/MIDELEG_REG
#add wave -hex /testbench_busybear/dut/hart/priv/csr/MEDELEG_REG
add wave -divider
# registers!
add wave -hex /testbench_busybear/regExpected
add wave -hex /testbench_busybear/regNumExpected
add wave -hex /testbench_busybear/HWRITE
add wave -hex /testbench_busybear/dut/MemRWM[1]
add wave -hex /testbench_busybear/dut/hart/MemRWM[1]
add wave -hex /testbench_busybear/HWDATA
add wave -hex /testbench_busybear/HRDATA
add wave -hex /testbench_busybear/HADDR
add wave -hex /testbench_busybear/dut/ieu/dp/regf/rf[1]
add wave -hex /testbench_busybear/dut/ieu/dp/regf/rf[2]
add wave -hex /testbench_busybear/dut/ieu/dp/regf/rf[3]
add wave -hex /testbench_busybear/dut/ieu/dp/regf/rf[4]
add wave -hex /testbench_busybear/dut/ieu/dp/regf/rf[5]
add wave -hex /testbench_busybear/dut/ieu/dp/regf/rf[6]
add wave -hex /testbench_busybear/dut/ieu/dp/regf/rf[7]
add wave -hex /testbench_busybear/dut/ieu/dp/regf/rf[8]
add wave -hex /testbench_busybear/dut/ieu/dp/regf/rf[9]
add wave -hex /testbench_busybear/dut/ieu/dp/regf/rf[10]
add wave -hex /testbench_busybear/dut/ieu/dp/regf/rf[11]
add wave -hex /testbench_busybear/dut/ieu/dp/regf/rf[12]
add wave -hex /testbench_busybear/dut/ieu/dp/regf/rf[13]
add wave -hex /testbench_busybear/dut/ieu/dp/regf/rf[14]
add wave -hex /testbench_busybear/dut/ieu/dp/regf/rf[15]
add wave -hex /testbench_busybear/dut/ieu/dp/regf/rf[16]
add wave -hex /testbench_busybear/dut/ieu/dp/regf/rf[17]
add wave -hex /testbench_busybear/dut/ieu/dp/regf/rf[18]
add wave -hex /testbench_busybear/dut/ieu/dp/regf/rf[19]
add wave -hex /testbench_busybear/dut/ieu/dp/regf/rf[20]
add wave -hex /testbench_busybear/dut/ieu/dp/regf/rf[21]
add wave -hex /testbench_busybear/dut/ieu/dp/regf/rf[22]
add wave -hex /testbench_busybear/dut/ieu/dp/regf/rf[23]
add wave -hex /testbench_busybear/dut/ieu/dp/regf/rf[24]
add wave -hex /testbench_busybear/dut/ieu/dp/regf/rf[25]
add wave -hex /testbench_busybear/dut/ieu/dp/regf/rf[26]
add wave -hex /testbench_busybear/dut/ieu/dp/regf/rf[27]
add wave -hex /testbench_busybear/dut/ieu/dp/regf/rf[28]
add wave -hex /testbench_busybear/dut/ieu/dp/regf/rf[29]
add wave -hex /testbench_busybear/dut/ieu/dp/regf/rf[30]
add wave -hex /testbench_busybear/dut/ieu/dp/regf/rf[31]
add wave /testbench_busybear/InstrFName
add wave -hex /testbench_busybear/dut/ifu/PCD
#add wave -hex /testbench_busybear/dut/ifu/InstrD
add wave /testbench_busybear/InstrDName
#add wave -divider
add wave -hex /testbench_busybear/dut/ifu/PCE
##add wave -hex /testbench_busybear/dut/ifu/InstrE
add wave /testbench_busybear/InstrEName
#add wave -hex /testbench_busybear/dut/ieu/dp/SrcAE
#add wave -hex /testbench_busybear/dut/ieu/dp/SrcBE
add wave -hex /testbench_busybear/dut/ieu/dp/ALUResultE
#add wave /testbench_busybear/dut/ieu/dp/PCSrcE
#add wave -divider
add wave -hex /testbench_busybear/dut/ifu/PCM
##add wave -hex /testbench_busybear/dut/ifu/InstrM
add wave /testbench_busybear/InstrMName
#add wave /testbench_busybear/dut/dmem/dtim/memwrite
#add wave -hex /testbench_busybear/dut/dmem/AdrM
#add wave -hex /testbench_busybear/dut/dmem/WriteDataM
#add wave -divider
add wave -hex /testbench_busybear/dut/ifu/PCW
##add wave -hex /testbench_busybear/dut/ifu/InstrW
add wave /testbench_busybear/InstrWName
#add wave /testbench_busybear/dut/ieu/dp/RegWriteW
#add wave -hex /testbench_busybear/dut/ieu/dp/ResultW
#add wave -hex /testbench_busybear/dut/ieu/dp/RdW
#add wave -divider
##add ww
#add wave -hex -r /testbench_busybear/*
#
#-- Set Wave Output Items
#TreeUpdate [SetDefaultTree]
#WaveRestoreZoom {0 ps} {100 ps}
#configure wave -namecolwidth 250
#configure wave -valuecolwidth 120
#configure wave -justifyvalue left
#configure wave -signalnamewidth 0
#configure wave -snapdistance 10
#configure wave -datasetprefix 0
#configure wave -rowmargin 4
#configure wave -childrowmargin 2
#set DefaultRadix hexadecimal
#
#-- Run the Simulation
run 1483850
#run -all
##quit
add wave -hex /testbench_busybear/readAdrExpected
add wave -hex /testbench_busybear/dut/hart/ieu/dp/regf/rf[1]
add wave -hex /testbench_busybear/dut/hart/ieu/dp/regf/rf[2]
add wave -hex /testbench_busybear/dut/hart/ieu/dp/regf/rf[3]
add wave -hex /testbench_busybear/dut/hart/ieu/dp/regf/rf[4]
add wave -hex /testbench_busybear/dut/hart/ieu/dp/regf/rf[5]
add wave -hex /testbench_busybear/dut/hart/ieu/dp/regf/rf[6]
add wave -hex /testbench_busybear/dut/hart/ieu/dp/regf/rf[7]
add wave -hex /testbench_busybear/dut/hart/ieu/dp/regf/rf[8]
add wave -hex /testbench_busybear/dut/hart/ieu/dp/regf/rf[9]
add wave -hex /testbench_busybear/dut/hart/ieu/dp/regf/rf[10]
add wave -hex /testbench_busybear/dut/hart/ieu/dp/regf/rf[11]
add wave -hex /testbench_busybear/dut/hart/ieu/dp/regf/rf[12]
add wave -hex /testbench_busybear/dut/hart/ieu/dp/regf/rf[13]
add wave -hex /testbench_busybear/dut/hart/ieu/dp/regf/rf[14]
add wave -hex /testbench_busybear/dut/hart/ieu/dp/regf/rf[15]
add wave -hex /testbench_busybear/dut/hart/ieu/dp/regf/rf[16]
add wave -hex /testbench_busybear/dut/hart/ieu/dp/regf/rf[17]
add wave -hex /testbench_busybear/dut/hart/ieu/dp/regf/rf[18]
add wave -hex /testbench_busybear/dut/hart/ieu/dp/regf/rf[19]
add wave -hex /testbench_busybear/dut/hart/ieu/dp/regf/rf[20]
add wave -hex /testbench_busybear/dut/hart/ieu/dp/regf/rf[21]
add wave -hex /testbench_busybear/dut/hart/ieu/dp/regf/rf[22]
add wave -hex /testbench_busybear/dut/hart/ieu/dp/regf/rf[23]
add wave -hex /testbench_busybear/dut/hart/ieu/dp/regf/rf[24]
add wave -hex /testbench_busybear/dut/hart/ieu/dp/regf/rf[25]
add wave -hex /testbench_busybear/dut/hart/ieu/dp/regf/rf[26]
add wave -hex /testbench_busybear/dut/hart/ieu/dp/regf/rf[27]
add wave -hex /testbench_busybear/dut/hart/ieu/dp/regf/rf[28]
add wave -hex /testbench_busybear/dut/hart/ieu/dp/regf/rf[29]
add wave -hex /testbench_busybear/dut/hart/ieu/dp/regf/rf[30]
add wave -hex /testbench_busybear/dut/hart/ieu/dp/regf/rf[31]
add wave /testbench_busybear/InstrFName
add wave -hex /testbench_busybear/dut/hart/ifu/PCD
#add wave -hex /testbench_busybear/dut/hart/ifu/InstrD
add wave /testbench_busybear/InstrDName
#add wave -divider
add wave -hex /testbench_busybear/dut/hart/ifu/PCE
##add wave -hex /testbench_busybear/dut/hart/ifu/InstrE
add wave /testbench_busybear/InstrEName
#add wave -hex /testbench_busybear/dut/hart/ieu/dp/SrcAE
#add wave -hex /testbench_busybear/dut/hart/ieu/dp/SrcBE
add wave -hex /testbench_busybear/dut/hart/ieu/dp/ALUResultE
#add wave /testbench_busybear/dut/hart/ieu/dp/PCSrcE
#add wave -divider
add wave -hex /testbench_busybear/dut/hart/ifu/PCM
##add wave -hex /testbench_busybear/dut/hart/ifu/InstrM
add wave /testbench_busybear/InstrMName
#add wave /testbench_busybear/dut/hart/dmem/dtim/memwrite
#add wave -hex /testbench_busybear/dut/hart/dmem/AdrM
#add wave -hex /testbench_busybear/dut/hart/dmem/WriteDataM
#add wave -divider
add wave -hex /testbench_busybear/dut/hart/ifu/PCW
##add wave -hex /testbench_busybear/dut/hart/ifu/InstrW
add wave /testbench_busybear/InstrWName
#add wave /testbench_busybear/dut/hart/ieu/dp/RegWriteW
#add wave -hex /testbench_busybear/dut/hart/ieu/dp/ResultW
#add wave -hex /testbench_busybear/dut/hart/ieu/dp/RdW
#add wave -divider
##add ww
add wave -hex -r /testbench_busybear/*
#
#-- Set Wave Output Items
#TreeUpdate [SetDefaultTree]
#WaveRestoreZoom {0 ps} {100 ps}
#configure wave -namecolwidth 250
#configure wave -valuecolwidth 120
#configure wave -justifyvalue left
#configure wave -signalnamewidth 0
#configure wave -snapdistance 10
#configure wave -datasetprefix 0
#configure wave -rowmargin 4
#configure wave -childrowmargin 2
#set DefaultRadix hexadecimal
#
#-- Run the Simulation
run -all
##quit

View File

@ -35,6 +35,14 @@ vlog +incdir+../config/coremark ../testbench/testbench-coremark.sv ../src/*/*.sv
vopt +acc work.testbench -o workopt
vsim workopt
# load the branch predictors with known data. The value of the data is not important for function, but
# is important for perventing pessimistic x propagation.
mem load -infile twoBitPredictor.txt -format bin testbench/dut/hart/ifu/bpred/DirPredictor/memory/memory
switch $argc {
0 {mem load -infile ../config/rv64ic/BTBPredictor.txt -format bin testbench/dut/hart/ifu/bpred/TargetPredictor/memory/memory}
1 {mem load -infile ../config/$1/BTBPredictor.txt -format bin testbench/dut/hart/ifu/bpred/TargetPredictor/memory/memory}
}
view wave
-- display input and output signals as hexidecimal values

View File

@ -0,0 +1,80 @@
# wally-peripherals-signals.do
#
# Created by Ben Bracker (bbracker@hmc.edu) on 4 Mar. 2021
#
# I really didn't like having to relaunch and recompile an entire sim
# just because some signal names have changed, so I thought this
# would be good to factor out.
restart -f
delete wave /*
view wave
-- display input and output signals as hexidecimal values
# Diplays All Signals recursively
add wave /testbench/clk
add wave /testbench/reset
add wave -divider
add wave /testbench/dut/hart/DataStall
add wave /testbench/dut/hart/InstrStall
add wave /testbench/dut/hart/StallF
add wave /testbench/dut/hart/StallD
add wave /testbench/dut/hart/FlushD
add wave /testbench/dut/hart/FlushE
add wave /testbench/dut/hart/FlushM
add wave /testbench/dut/hart/FlushW
add wave -divider
add wave -hex /testbench/dut/hart/ifu/PCF
add wave -hex /testbench/dut/hart/ifu/InstrF
add wave /testbench/InstrFName
#add wave -hex /testbench/dut/hart/ifu/PCD
add wave -hex /testbench/dut/hart/ifu/InstrD
add wave /testbench/InstrDName
add wave -divider
add wave -hex /testbench/dut/hart/ifu/PCE
add wave -hex /testbench/dut/hart/ifu/InstrE
add wave /testbench/InstrEName
add wave -hex /testbench/dut/hart/ieu/dp/SrcAE
add wave -hex /testbench/dut/hart/ieu/dp/SrcBE
add wave -hex /testbench/dut/hart/ieu/dp/ALUResultE
add wave -divider
add wave -hex /testbench/dut/hart/ifu/PCM
add wave -hex /testbench/dut/hart/ifu/InstrM
add wave /testbench/InstrMName
add wave /testbench/dut/uncore/dtim/memwrite
add wave -hex /testbench/dut/uncore/HADDR
add wave -hex /testbench/dut/uncore/HWDATA
add wave -divider
add wave -hex /testbench/dut/hart/ifu/PCW
add wave /testbench/InstrWName
add wave /testbench/dut/hart/ieu/dp/RegWriteW
add wave -hex /testbench/dut/hart/ieu/dp/ResultW
add wave -hex /testbench/dut/hart/ieu/dp/RdW
add wave -divider
add wave -hex /testbench/dut/hart/ebu/*
add wave -divider
add wave -hex /testbench/dut/uncore/uart/u/*
add wave -divider
#add ww
add wave -hex -r /testbench/*
-- Set Wave Output Items
TreeUpdate [SetDefaultTree]
WaveRestoreZoom {0 ps} {100 ps}
configure wave -namecolwidth 250
configure wave -valuecolwidth 120
configure wave -justifyvalue left
configure wave -signalnamewidth 0
configure wave -snapdistance 10
configure wave -datasetprefix 0
configure wave -rowmargin 4
configure wave -childrowmargin 2
set DefaultRadix hexadecimal
-- Run the Simulation
#run 5000
run -all
#quit
noview ../testbench/testbench-peripherals.sv
view wave

View File

@ -38,71 +38,13 @@ switch $argc {
vopt +acc work.testbench -o workopt
vsim workopt
# load the branch predictors with known data. The value of the data is not important for function, but
# is important for perventing pessimistic x propagation.
mem load -infile twoBitPredictor.txt -format bin testbench/dut/hart/ifu/bpred/DirPredictor/memory/memory
switch $argc {
0 {mem load -infile ../config/rv64ic/BTBPredictor.txt -format bin testbench/dut/hart/ifu/bpred/TargetPredictor/memory/memory}
1 {mem load -infile ../config/$1/BTBPredictor.txt -format bin testbench/dut/hart/ifu/bpred/TargetPredictor/memory/memory}
}
view wave
-- display input and output signals as hexidecimal values
# Diplays All Signals recursively
add wave /testbench/clk
add wave /testbench/reset
add wave -divider
add wave /testbench/dut/hart/ebu/IReadF
add wave /testbench/dut/hart/DataStall
add wave /testbench/dut/hart/InstrStall
add wave /testbench/dut/hart/StallF
add wave /testbench/dut/hart/StallD
add wave /testbench/dut/hart/FlushD
add wave /testbench/dut/hart/FlushE
add wave /testbench/dut/hart/FlushM
add wave /testbench/dut/hart/FlushW
add wave -divider
add wave -hex /testbench/dut/hart/ifu/PCF
add wave -hex /testbench/dut/hart/ifu/InstrF
add wave /testbench/InstrFName
#add wave -hex /testbench/dut/hart/ifu/PCD
add wave -hex /testbench/dut/hart/ifu/InstrD
add wave /testbench/InstrDName
add wave -divider
#add wave -hex /testbench/dut/hart/ifu/PCE
#add wave -hex /testbench/dut/hart/ifu/InstrE
add wave /testbench/InstrEName
add wave -hex /testbench/dut/hart/ieu/dp/SrcAE
add wave -hex /testbench/dut/hart/ieu/dp/SrcBE
add wave -hex /testbench/dut/hart/ieu/dp/ALUResultE
add wave /testbench/dut/hart/ieu/dp/PCSrcE
add wave -divider
#add wave -hex /testbench/dut/hart/ifu/PCM
#add wave -hex /testbench/dut/hart/ifu/InstrM
add wave /testbench/InstrMName
add wave /testbench/dut/uncore/dtim/memwrite
add wave -hex /testbench/dut/uncore/HADDR
add wave -hex /testbench/dut/uncore/HWDATA
add wave -divider
add wave -hex /testbench/dut/hart/ifu/PCW
add wave /testbench/InstrWName
add wave /testbench/dut/hart/ieu/dp/RegWriteW
add wave -hex /testbench/dut/hart/ieu/dp/ResultW
add wave -hex /testbench/dut/hart/ieu/dp/RdW
add wave -divider
add wave -hex /testbench/dut/uncore/uart/u/*
add wave -divider
#add ww
add wave -hex -r /testbench/*
-- Set Wave Output Items
TreeUpdate [SetDefaultTree]
WaveRestoreZoom {0 ps} {100 ps}
configure wave -namecolwidth 250
configure wave -valuecolwidth 120
configure wave -justifyvalue left
configure wave -signalnamewidth 0
configure wave -snapdistance 10
configure wave -datasetprefix 0
configure wave -rowmargin 4
configure wave -childrowmargin 2
set DefaultRadix hexadecimal
-- Run the Simulation
run 5000
#run -all
#quit
do wally-peripherals-signals.do

View File

@ -34,5 +34,10 @@ vlog +incdir+$1 ../testbench/testbench-imperas.sv ../src/*/*.sv -suppress 2583
vopt work.testbench -o workopt
vsim workopt
# load the branch predictors with known data. The value of the data is not important for function, but
# is important for perventing pessimistic x propagation.
mem load -infile twoBitPredictor.txt -format bin testbench/dut/hart/ifu/bpred/DirPredictor/memory/memory
mem load -infile BTBPredictor.txt -format bin testbench/dut/hart/ifu/bpred/TargetPredictor/memory/memory
run -all
quit

View File

@ -6,13 +6,12 @@
# Go Cowboys!!!!!!
#
# Takes 1:10 to run RV64IC tests using gui
# 11 seconds to run batch mode
# Use this wally-pipelined.do file to run this example.
# Use this wally-pipelined-batch.do file to run this example.
# Either bring up ModelSim and type the following at the "ModelSim>" prompt:
# do wally-pipelined.do ../config/rv64ic
# do wally-pipelined-batch.do
# or, to run from a shell, type the following at the shell prompt:
# vsim -c -do wally-pipelined.do ../config/rv64ic
# vsim -do wally-pipelined-batch.do -c
# (omit the "-c" to see the GUI while running from the shell)
onbreak {resume}
@ -27,12 +26,25 @@ vlib work
# suppress spurious warnngs about
# "Extra checking for conflicts with always_comb done at vopt time"
# because vsim will run vopt
vlog +incdir+$1 ../testbench/testbench-imperas.sv ../src/*/*.sv -suppress 2583
# default to config/rv64ic, but allow this to be overridden at the command line. For example:
# do wally-pipelined-batch.do ../config/rv32ic
switch $argc {
0 {vlog +incdir+../config/rv64ic ../testbench/testbench-imperas.sv ../src/*/*.sv -suppress 2583}
1 {vlog +incdir+$1 ../testbench/testbench-imperas.sv ../src/*/*.sv -suppress 2583}
}
# start and run simulation
# remove +acc flag for faster sim during regressions if there is no need to access internal signals
vopt work.testbench -o workopt
vopt +acc=+/testbench/dut/hart/ifu/bpred/DirPredictor/memory/memory +acc=+/testbench/dut/hart/ifu/bpred/TargetPredictor/memory/memory work.testbench -o workopt
vsim workopt
# load the branch predictors with known data. The value of the data is not important for function, but
# is important for perventing pessimistic x propagation.
mem load -infile twoBitPredictor.txt -format bin testbench/dut/hart/ifu/bpred/DirPredictor/memory/memory
switch $argc {
0 {mem load -infile ../config/rv64ic/BTBPredictor.txt -format bin testbench/dut/hart/ifu/bpred/TargetPredictor/memory/memory}
1 {mem load -infile ../config/$1/BTBPredictor.txt -format bin testbench/dut/hart/ifu/bpred/TargetPredictor/memory/memory}
}
run -all
quit

View 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
# 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
# default to config/rv64ic, but allow this to be overridden at the command line. For example:
# do wally-pipelined.do ../config/rv32ic
switch $argc {
0 {vlog +incdir+../config/rv64ic ../testbench/testbench-imperas.sv ../src/*/*.sv -suppress 2583}
1 {vlog +incdir+$1 ../testbench/testbench-imperas.sv ../src/*/*.sv -suppress 2583}
}
# start and run simulation
# remove +acc flag for faster sim during regressions if there is no need to access internal signals
vopt +acc work.testbench -o workopt
vsim workopt
# load the branch predictors with known data. The value of the data is not important for function, but
# is important for perventing pessimistic x propagation.
mem load -infile twoBitPredictor.txt -format bin testbench/dut/hart/ifu/bpred/DirPredictor/memory/memory
switch $argc {
0 {mem load -infile ../config/rv64ic/BTBPredictor.txt -format bin testbench/dut/hart/ifu/bpred/TargetPredictor/memory/memory}
1 {mem load -infile ../config/$1/BTBPredictor.txt -format bin testbench/dut/hart/ifu/bpred/TargetPredictor/memory/memory}
}
do wave.do
add log -r /*
-- Run the Simulation
#run 1000
run -all
#quit

View File

@ -38,6 +38,14 @@ switch $argc {
vopt +acc work.testbench -o workopt
vsim workopt
# load the branch predictors with known data. The value of the data is not important for function, but
# is important for perventing pessimistic x propagation.
mem load -infile twoBitPredictor.txt -format bin testbench/dut/hart/ifu/bpred/DirPredictor/memory/memory
switch $argc {
0 {mem load -infile ../config/rv64ic/BTBPredictor.txt -format bin testbench/dut/hart/ifu/bpred/TargetPredictor/memory/memory}
1 {mem load -infile ../config/$1/BTBPredictor.txt -format bin testbench/dut/hart/ifu/bpred/TargetPredictor/memory/memory}
}
view wave
-- display input and output signals as hexidecimal values
@ -107,6 +115,6 @@ configure wave -childrowmargin 2
set DefaultRadix hexadecimal
-- Run the Simulation
#run 2000
#run 4100
run -all
#quit

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,134 @@
onerror {resume}
quietly WaveActivateNextPane {} 0
add wave -noupdate /testbench/clk
add wave -noupdate /testbench/reset
add wave -noupdate -radix ascii /testbench/memfilename
add wave -noupdate -expand -group {Execution Stage} /testbench/dut/hart/ifu/PCE
add wave -noupdate -expand -group {Execution Stage} /testbench/InstrEName
add wave -noupdate -expand -group {Execution Stage} /testbench/dut/hart/ifu/InstrE
add wave -noupdate -divider <NULL>
add wave -noupdate /testbench/dut/hart/ebu/IReadF
add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/BPPredWrongE
add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/CSRWritePendingDEM
add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/RetM
add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/TrapM
add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/LoadStallD
add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/InstrStall
add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/DataStall
add wave -noupdate -expand -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/hzu/FlushF
add wave -noupdate -expand -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/FlushD
add wave -noupdate -expand -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/FlushE
add wave -noupdate -expand -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/FlushM
add wave -noupdate -expand -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/FlushW
add wave -noupdate -expand -group HDU -expand -group Stall -color Orange /testbench/dut/hart/StallF
add wave -noupdate -expand -group HDU -expand -group Stall -color Orange /testbench/dut/hart/StallD
add wave -noupdate -group Bpred -expand -group direction -divider Update
add wave -noupdate -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/DirPredictor/UpdatePC
add wave -noupdate -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/DirPredictor/UpdateEN
add wave -noupdate -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/DirPredictor/UpdatePCIndex
add wave -noupdate -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/DirPredictor/UpdatePrediction
add wave -noupdate -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/DirPredictor/memory/memory
add wave -noupdate -group InstrClass /testbench/dut/hart/ifu/bpred/InstrClassF
add wave -noupdate -group InstrClass /testbench/dut/hart/ifu/bpred/InstrClassD
add wave -noupdate -group InstrClass /testbench/dut/hart/ifu/bpred/InstrClassE
add wave -noupdate -group {instruction pipeline} /testbench/dut/hart/ifu/InstrF
add wave -noupdate -group {instruction pipeline} /testbench/dut/hart/ifu/InstrD
add wave -noupdate -group {instruction pipeline} /testbench/dut/hart/ifu/InstrE
add wave -noupdate -group {instruction pipeline} /testbench/dut/hart/ifu/InstrM
add wave -noupdate /testbench/dut/hart/ifu/bpred/BPPredWrongE
add wave -noupdate -group {PCNext Generation} /testbench/dut/hart/ifu/PCNextF
add wave -noupdate -group {PCNext Generation} /testbench/dut/hart/ifu/PCF
add wave -noupdate -group {PCNext Generation} /testbench/dut/hart/ifu/PCPlus2or4F
add wave -noupdate -group {PCNext Generation} /testbench/dut/hart/ifu/BPPredPCF
add wave -noupdate -group {PCNext Generation} /testbench/dut/hart/ifu/PCNext0F
add wave -noupdate -group {PCNext Generation} /testbench/dut/hart/ifu/PCNext1F
add wave -noupdate -group {PCNext Generation} /testbench/dut/hart/ifu/SelBPPredF
add wave -noupdate -group {PCNext Generation} /testbench/dut/hart/ifu/BPPredWrongE
add wave -noupdate -group {PCNext Generation} /testbench/dut/hart/ifu/PrivilegedChangePCM
add wave -noupdate /testbench/dut/hart/ifu/bpred/TargetPredictor/ValidBits
add wave -noupdate /testbench/dut/hart/ifu/bpred/BPPredF
add wave -noupdate /testbench/dut/hart/ifu/bpred/BTBValidF
add wave -noupdate /testbench/dut/hart/ifu/bpred/TargetPredictor/LookUpPCIndexQ
add wave -noupdate /testbench/dut/hart/ifu/bpred/TargetPredictor/UpdatePCIndexQ
add wave -noupdate /testbench/dut/hart/ifu/bpred/TargetPredictor/LookUpPC
add wave -noupdate -group {bp wrong} /testbench/dut/hart/ifu/bpred/TargetWrongE
add wave -noupdate -group {bp wrong} /testbench/dut/hart/ifu/bpred/FallThroughWrongE
add wave -noupdate -group {bp wrong} /testbench/dut/hart/ifu/bpred/PredictionDirWrongE
add wave -noupdate -group {bp wrong} /testbench/dut/hart/ifu/bpred/PredictionPCWrongE
add wave -noupdate -group {bp wrong} /testbench/dut/hart/ifu/bpred/BPPredWrongE
add wave -noupdate -group {bp wrong} /testbench/dut/hart/ifu/bpred/InstrClassE
add wave -noupdate -group BTB -divider Update
add wave -noupdate -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/UpdateEN
add wave -noupdate -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/UpdatePC
add wave -noupdate -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/UpdateTarget
add wave -noupdate -group BTB -divider Lookup
add wave -noupdate -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/TargetPC
add wave -noupdate -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/Valid
add wave -noupdate /testbench/dut/hart/ifu/bpred/BTBPredPCF
add wave -noupdate /testbench/dut/hart/ifu/bpred/TargetPredictor/TargetPC
add wave -noupdate /testbench/dut/hart/ifu/bpred/CorrectPCE
add wave -noupdate /testbench/dut/hart/ifu/bpred/FlushF
add wave -noupdate /testbench/dut/hart/FlushF
add wave -noupdate -expand -group RegFile /testbench/dut/hart/ieu/dp/regf/rf
add wave -noupdate -expand -group RegFile /testbench/dut/hart/ieu/dp/regf/a1
add wave -noupdate -expand -group RegFile /testbench/dut/hart/ieu/dp/regf/a2
add wave -noupdate -expand -group RegFile /testbench/dut/hart/ieu/dp/regf/a3
add wave -noupdate -expand -group RegFile /testbench/dut/hart/ieu/dp/regf/rd1
add wave -noupdate -expand -group RegFile /testbench/dut/hart/ieu/dp/regf/rd2
add wave -noupdate -expand -group RegFile /testbench/dut/hart/ieu/dp/regf/we3
add wave -noupdate -expand -group RegFile /testbench/dut/hart/ieu/dp/regf/wd3
add wave -noupdate -expand -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/ALUResultW
add wave -noupdate -expand -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/ReadDataW
add wave -noupdate -expand -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/PCLinkW
add wave -noupdate -expand -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/CSRReadValW
add wave -noupdate -expand -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/ResultSrcW
add wave -noupdate -expand -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/ResultW
add wave -noupdate /testbench/dut/hart/ieu/c/RegWriteE
add wave -noupdate -group {Decode Stage} /testbench/dut/hart/ifu/InstrD
add wave -noupdate -group {Decode Stage} /testbench/InstrDName
add wave -noupdate -group {Decode Stage} /testbench/dut/hart/ieu/c/RegWriteD
add wave -noupdate -group {Decode Stage} /testbench/dut/hart/ieu/dp/RdD
add wave -noupdate -group {Decode Stage} /testbench/dut/hart/ieu/dp/Rs1D
add wave -noupdate -group {Decode Stage} /testbench/dut/hart/ieu/dp/Rs2D
add wave -noupdate /testbench/InstrFName
add wave -noupdate -expand -group dcache /testbench/dut/hart/MemAdrM
add wave -noupdate -expand -group dcache /testbench/dut/hart/MemPAdrM
add wave -noupdate -expand -group dcache /testbench/dut/hart/WriteDataM
add wave -noupdate -expand -group dcache /testbench/dut/hart/ReadDataM
add wave -noupdate -expand -group dcache /testbench/dut/hart/dmem/MemRWM
add wave -noupdate -group Forward /testbench/dut/hart/ieu/fw/Rs1D
add wave -noupdate -group Forward /testbench/dut/hart/ieu/fw/Rs2D
add wave -noupdate -group Forward /testbench/dut/hart/ieu/fw/Rs1E
add wave -noupdate -group Forward /testbench/dut/hart/ieu/fw/Rs2E
add wave -noupdate -group Forward /testbench/dut/hart/ieu/fw/RdE
add wave -noupdate -group Forward /testbench/dut/hart/ieu/fw/RdM
add wave -noupdate -group Forward /testbench/dut/hart/ieu/fw/RdW
add wave -noupdate -group Forward /testbench/dut/hart/ieu/fw/MemReadE
add wave -noupdate -group Forward /testbench/dut/hart/ieu/fw/RegWriteM
add wave -noupdate -group Forward /testbench/dut/hart/ieu/fw/RegWriteW
add wave -noupdate -group Forward -color Thistle /testbench/dut/hart/ieu/fw/ForwardAE
add wave -noupdate -group Forward -color Thistle /testbench/dut/hart/ieu/fw/ForwardBE
add wave -noupdate -group Forward -color Thistle /testbench/dut/hart/ieu/fw/LoadStallD
add wave -noupdate -expand -group {alu execution stage} /testbench/dut/hart/ieu/dp/WriteDataE
add wave -noupdate -expand -group {alu execution stage} /testbench/dut/hart/ieu/dp/ALUResultE
add wave -noupdate -expand -group {alu execution stage} /testbench/dut/hart/ieu/dp/SrcAE
add wave -noupdate -expand -group {alu execution stage} /testbench/dut/hart/ieu/dp/SrcBE
add wave -noupdate /testbench/dut/hart/ieu/dp/ALUResultM
TreeUpdate [SetDefaultTree]
WaveRestoreCursors {{Cursor 2} {231033 ns} 0} {{Cursor 3} {1276117 ns} 0}
quietly wave cursor active 2
configure wave -namecolwidth 250
configure wave -valuecolwidth 518
configure wave -justifyvalue left
configure wave -signalnamewidth 1
configure wave -snapdistance 10
configure wave -datasetprefix 0
configure wave -rowmargin 4
configure wave -childrowmargin 2
configure wave -gridoffset 0
configure wave -gridperiod 1
configure wave -griddelta 40
configure wave -timeline 0
configure wave -timelineunits ns
update
WaveRestoreZoom {1276094 ns} {1276208 ns}

View File

@ -100,7 +100,7 @@ module dmem (
assign lrM = MemReadM && AtomicM;
assign scM = MemRWM[0] && AtomicM;
assign WriteAdrMatchM = MemRWM[0] && (MemPAdrM == ReservationPAdrW) && ReservationValidW;
assign WriteAdrMatchM = MemRWM[0] && (MemPAdrM[`XLEN-1:2] == ReservationPAdrW) && ReservationValidW;
assign SquashSCM = scM && ~WriteAdrMatchM;
always_comb begin // ReservationValidM (next valiue of valid reservation)
if (lrM) ReservationValidM = 1; // set valid on load reserve

View File

@ -102,7 +102,7 @@ module ahblite (
else NextBusState = IDLE;
INSTRREAD: //if (~HREADY & (MemReadM | MemWriteM)) NextBusState = INSTRREADMEMPENDING; // *** shouldn't happen, delete
if (~HREADY) NextBusState = INSTRREAD;
else NextBusState = IDLE;
else NextBusState = IDLE; // if (InstrReadF still high)
INSTRREADMEMPENDING: if (~HREADY) NextBusState = INSTRREADMEMPENDING; // *** shouldn't happen, delete
else if (MemReadM) NextBusState = MEMREAD;
else NextBusState = MEMWRITE; // must be write if not a read. Don't return to idle.

View File

@ -35,14 +35,14 @@ module add(r[105:0], s[105:0], t[157:0], sum[157:0],
wire [157:0] sum0; // sum of compound adder +0 mode
wire [157:0] sum1; // sum of compound adder +1 mode
// Invert addend if necessary
// Invert addend if z's sign is diffrent from the product's sign
assign t2 = invz ? -t : t;
// Zero out product if Z >> product or product really should be zero
assign r2 = ~proddenorm & killprod ? 106'b0 : r;
assign s2 = ~proddenorm & killprod ? 106'b0 : s;
assign r2 = killprod ? 106'b0 : r;
assign s2 = killprod ? 106'b0 : s;
// Compound adder
// Consists of 3:2 CSA followed by long compound CPA

View File

@ -15,17 +15,17 @@ module align(z[51:0], ae[12:0], aligncnt, xzero, yzero, zzero, zdenorm, proddeno
killprod, bypsel[1], bypplus1, byppostnorm);
/////////////////////////////////////////////////////////////////////////////
input [51:0] z; // Fraction of addend z;
input [51:0] z; // Fraction of addend z;
input [12:0] ae; // sign of exponent of addend z;
input [11:0] aligncnt; // amount to shift
input xzero; // Input X = 0
input yzero; // Input Y = 0
input zzero; // Input Z = 0
input zdenorm; // Input Z = denorm
input proddenorm;
input [11:0] aligncnt; // amount to shift
input xzero; // Input X = 0
input yzero; // Input Y = 0
input zzero; // Input Z = 0
input zdenorm; // Input Z is denormalized
input proddenorm; // product is denormalized
input [1:1] bypsel; // Select bypass to X or Z
input bypplus1; // Add one to bypassed result
input byppostnorm; // Postnormalize bypassed result
input bypplus1; // Add one to bypassed result
input byppostnorm; // Postnormalize bypassed result
output [157:0] t; // aligned addend (54 bits left of bpt)
output bs; // sticky bit of addend
output ps; // sticky bit of product
@ -34,13 +34,13 @@ module align(z[51:0], ae[12:0], aligncnt, xzero, yzero, zzero, zdenorm, proddeno
// Internal nodes
reg [157:0] t; // aligned addend from shifter
reg killprod; // Z >> product
reg killprod; // Z >> product
reg bs; // sticky bit of addend
reg ps; // sticky bit of product
reg [7:0] i; // temp storage for finding sticky bit
wire [52:0] z1; // Z plus 1
wire [51:0] z2; // Z selected after handling rounds
wire [11:0] align104; // alignment count + 104
wire [11:0] align104; // alignment count + 104
// Increment fraction of Z by one if necessary for prerounded bypass
// This incrementor delay is masked by the alignment count computation
@ -56,7 +56,7 @@ module align(z[51:0], ae[12:0], aligncnt, xzero, yzero, zzero, zdenorm, proddeno
// addend on right shifts. Handle special cases of shifting
// by too much.
always @(z2 or aligncnt or align104 or zzero or xzero or yzero or zdenorm)
always @(z2 or aligncnt or align104 or zzero or xzero or yzero or zdenorm or proddenorm)
begin
// Default to clearing sticky bits
@ -66,7 +66,7 @@ module align(z[51:0], ae[12:0], aligncnt, xzero, yzero, zzero, zdenorm, proddeno
// And to using product as primary operand in adder I exponent gen
killprod = 0;
if(zzero) begin
if(zzero) begin // if z = 0
t = 158'b0;
if (xzero || yzero) killprod = 1;
end else if ((aligncnt > 53 && ~aligncnt[11]) || xzero || yzero) begin
@ -75,8 +75,8 @@ module align(z[51:0], ae[12:0], aligncnt, xzero, yzero, zzero, zdenorm, proddeno
t = {53'b0, ~zzero, z2, 52'b0};
killprod = 1;
ps = ~xzero && ~yzero;
end else if ((ae[12] && align104[11])) begin //***fix the if statement
// KEP if the multiplier's exponent overflows
end else if ((ae[12] && align104[11]) && ~proddenorm) begin //***fix the if statement
// KEP if the multiplier's exponent overflows
t = {53'b0, ~zzero, z2, 52'b0};
killprod = 1;
ps = ~xzero && ~yzero;
@ -85,7 +85,7 @@ module align(z[51:0], ae[12:0], aligncnt, xzero, yzero, zzero, zdenorm, proddeno
t = 0;
end else if (~aligncnt[11]) begin // Left shift by reasonable amount
t = {53'b0, ~zzero, z2, 52'b0} << aligncnt;
end else begin // Otherwise right shift
end else begin // Otherwise right shift
t = {53'b0, ~zzero, z2, 52'b0} >> -aligncnt;
// use some behavioral code to find sticky bit. This is really

View File

@ -30,85 +30,85 @@ module array(x, y, xdenorm, ydenorm, r, s, bypsel, bypplus1);
assign xnorm = xdenorm ? {x[50:0], 1'b0} : x; // normalization of denormalized numbers
assign ynorm = ydenorm ? {y[50:0], 1'b0} : y;
assign yExt = {2'b01,ynorm,1'b0}; // y extended and added assumed 1
assign xExt = {2'b01,xnorm}; // x with added assumed 1
//assign yExt = {2'b01,ynorm,1'b0}; // y extended and added assumed 1
//assign xExt = {2'b01,xnorm}; // x with added assumed 1
//booth encoding
generate
for(i=0; i<27; i=i+1) begin
booth booth(.xExt(xExt), .choose(yExt[(i*2)+2:i*2]), .add1(add1[i]), .e(e[i]), .pp(pp[i]));
end
endgenerate
// generate
// for(i=0; i<27; i=i+1) begin
// booth booth(.xExt(xExt), .choose(yExt[(i*2)+2:i*2]), .add1(add1[i]), .e(e[i]), .pp(pp[i]));
// end
// endgenerate
assign acc[0] = {49'b0,~e[0],e[0],e[0],pp[0]};
assign acc[1] = {50'b01,~e[1],pp[1],add1[0]};
assign acc[2] = {48'b01,~e[2],pp[2],add1[1], 2'b0};
assign acc[3] = {46'b01,~e[3],pp[3],add1[2], 4'b0};
assign acc[4] = {44'b01,~e[4],pp[4],add1[3], 6'b0};
assign acc[5] = {42'b01,~e[5],pp[5],add1[4], 8'b0};
assign acc[6] = {40'b01,~e[6],pp[6],add1[5], 10'b0};
assign acc[7] = {38'b01,~e[7],pp[7],add1[6], 12'b0};
assign acc[8] = {36'b01,~e[8],pp[8],add1[7], 14'b0};
assign acc[9] = {34'b01,~e[9],pp[9],add1[8], 16'b0};
assign acc[10] = {32'b01,~e[10],pp[10],add1[9], 18'b0};
assign acc[11] = {30'b01,~e[11],pp[11],add1[10], 20'b0};
assign acc[12] = {28'b01,~e[12],pp[12],add1[11], 22'b0};
assign acc[13] = {26'b01,~e[13],pp[13],add1[12], 24'b0};
assign acc[14] = {24'b01,~e[14],pp[14],add1[13], 26'b0};
assign acc[15] = {22'b01,~e[15],pp[15],add1[14], 28'b0};
assign acc[16] = {20'b01,~e[16],pp[16],add1[15], 30'b0};
assign acc[17] = {18'b01,~e[17],pp[17],add1[16], 32'b0};
assign acc[18] = {16'b01,~e[18],pp[18],add1[17], 34'b0};
assign acc[19] = {14'b01,~e[19],pp[19],add1[18], 36'b0};
assign acc[20] = {12'b01,~e[20],pp[20],add1[19], 38'b0};
assign acc[21] = {10'b01,~e[21],pp[21],add1[20], 40'b0};
assign acc[22] = {8'b01,~e[22],pp[22],add1[21], 42'b0};
assign acc[23] = {6'b01,~e[23],pp[23],add1[22], 44'b0};
assign acc[24] = {4'b01,~e[24],pp[24],add1[23], 46'b0};
assign acc[25] = {~e[25],pp[25],add1[24], 48'b0};
assign acc[26] = {pp[26],add1[25], 50'b0};
// assign acc[0] = {49'b0,~e[0],e[0],e[0],pp[0]};
// assign acc[1] = {50'b01,~e[1],pp[1],add1[0]};
// assign acc[2] = {48'b01,~e[2],pp[2],add1[1], 2'b0};
// assign acc[3] = {46'b01,~e[3],pp[3],add1[2], 4'b0};
// assign acc[4] = {44'b01,~e[4],pp[4],add1[3], 6'b0};
// assign acc[5] = {42'b01,~e[5],pp[5],add1[4], 8'b0};
// assign acc[6] = {40'b01,~e[6],pp[6],add1[5], 10'b0};
// assign acc[7] = {38'b01,~e[7],pp[7],add1[6], 12'b0};
// assign acc[8] = {36'b01,~e[8],pp[8],add1[7], 14'b0};
// assign acc[9] = {34'b01,~e[9],pp[9],add1[8], 16'b0};
// assign acc[10] = {32'b01,~e[10],pp[10],add1[9], 18'b0};
// assign acc[11] = {30'b01,~e[11],pp[11],add1[10], 20'b0};
// assign acc[12] = {28'b01,~e[12],pp[12],add1[11], 22'b0};
// assign acc[13] = {26'b01,~e[13],pp[13],add1[12], 24'b0};
// assign acc[14] = {24'b01,~e[14],pp[14],add1[13], 26'b0};
// assign acc[15] = {22'b01,~e[15],pp[15],add1[14], 28'b0};
// assign acc[16] = {20'b01,~e[16],pp[16],add1[15], 30'b0};
// assign acc[17] = {18'b01,~e[17],pp[17],add1[16], 32'b0};
// assign acc[18] = {16'b01,~e[18],pp[18],add1[17], 34'b0};
// assign acc[19] = {14'b01,~e[19],pp[19],add1[18], 36'b0};
// assign acc[20] = {12'b01,~e[20],pp[20],add1[19], 38'b0};
// assign acc[21] = {10'b01,~e[21],pp[21],add1[20], 40'b0};
// assign acc[22] = {8'b01,~e[22],pp[22],add1[21], 42'b0};
// assign acc[23] = {6'b01,~e[23],pp[23],add1[22], 44'b0};
// assign acc[24] = {4'b01,~e[24],pp[24],add1[23], 46'b0};
// assign acc[25] = {~e[25],pp[25],add1[24], 48'b0};
// assign acc[26] = {pp[26],add1[25], 50'b0};
//*** resize adders
generate
for(i=0; i<9; i=i+1) begin
add3comp2 #(.BITS(106)) add1(.a(acc[i*3]), .b(acc[i*3+1]), .c(acc[i*3+2]),
.carry(carryTmp[i][105:0]), .sum(lv1add[i*2+1]));
assign lv1add[i*2] = {carryTmp[i][104:0], 1'b0};
end
endgenerate
// //*** resize adders
// generate
// for(i=0; i<9; i=i+1) begin
// add3comp2 #(.BITS(106)) add1(.a(acc[i*3]), .b(acc[i*3+1]), .c(acc[i*3+2]),
// .carry(carryTmp[i][105:0]), .sum(lv1add[i*2+1]));
// assign lv1add[i*2] = {carryTmp[i][104:0], 1'b0};
// end
// endgenerate
generate
for(i=0; i<6; i=i+1) begin
add3comp2 #(.BITS(106)) add2(.a(lv1add[i*3]), .b(lv1add[i*3+1]), .c(lv1add[i*3+2]),
.carry(carryTmp[i+9][105:0]), .sum(lv2add[i*2+1]));
assign lv2add[i*2] = {carryTmp[i+9][104:0], 1'b0};
end
endgenerate
// generate
// for(i=0; i<6; i=i+1) begin
// add3comp2 #(.BITS(106)) add2(.a(lv1add[i*3]), .b(lv1add[i*3+1]), .c(lv1add[i*3+2]),
// .carry(carryTmp[i+9][105:0]), .sum(lv2add[i*2+1]));
// assign lv2add[i*2] = {carryTmp[i+9][104:0], 1'b0};
// end
// endgenerate
generate
for(i=0; i<4; i=i+1) begin
add3comp2 #(.BITS(106)) add3(.a(lv2add[i*3]), .b(lv2add[i*3+1]), .c(lv2add[i*3+2]),
.carry(carryTmp[i+15][105:0]), .sum(lv3add[i*2+1]));
assign lv3add[i*2] = {carryTmp[i+15][104:0], 1'b0};
end
endgenerate
// generate
// for(i=0; i<4; i=i+1) begin
// add3comp2 #(.BITS(106)) add3(.a(lv2add[i*3]), .b(lv2add[i*3+1]), .c(lv2add[i*3+2]),
// .carry(carryTmp[i+15][105:0]), .sum(lv3add[i*2+1]));
// assign lv3add[i*2] = {carryTmp[i+15][104:0], 1'b0};
// end
// endgenerate
generate
for(i=0; i<2; i=i+1) begin
add4comp2 #(.BITS(106)) add4(.a(lv3add[i*4]), .b(lv3add[i*4+1]), .c(lv3add[i*4+2]), .d(lv3add[i*4+3]),
.carry(carryTmp[i+19]), .sum(lv4add[i*2+1]));
assign lv4add[i*2] = {carryTmp[i+19][104:0], 1'b0};
end
endgenerate
// generate
// for(i=0; i<2; i=i+1) begin
// add4comp2 #(.BITS(106)) add4(.a(lv3add[i*4]), .b(lv3add[i*4+1]), .c(lv3add[i*4+2]), .d(lv3add[i*4+3]),
// .carry(carryTmp[i+19]), .sum(lv4add[i*2+1]));
// assign lv4add[i*2] = {carryTmp[i+19][104:0], 1'b0};
// end
// endgenerate
add4comp2 #(.BITS(106)) add5(.a(lv4add[0]), .b(lv4add[1]), .c(lv4add[2]), .d(lv4add[3]) ,
.carry(carryTmp[21]), .sum(s));
assign r = {carryTmp[21][104:0], 1'b0};
// add4comp2 #(.BITS(106)) add5(.a(lv4add[0]), .b(lv4add[1]), .c(lv4add[2]), .d(lv4add[3]) ,
// .carry(carryTmp[21]), .sum(s));
// assign r = {carryTmp[21][104:0], 1'b0};
// assign r = 106'b0;
// assign s = ({54'b1,xnorm} + (bypsel && bypplus1)) * {54'b1,ynorm};
assign r = 106'b0;
assign s = ({54'b1,xnorm} + (bypsel && bypplus1)) * {54'b1,ynorm};
endmodule

View File

@ -19,7 +19,7 @@ module expgen(x[62:52], y[62:52], z[62:52],
earlyres[62:52], earlyressel, bypsel[1], byppostnorm,
killprod, sumzero, postnormalize, normcnt, infinity,
invalid, overflow, underflow, inf,
nan, xnan, ynan, znan, zdenorm, specialsel,
nan, xnan, ynan, znan, zdenorm, proddenorm, specialsel,
aligncnt, w[62:52], wbypass[62:52],
prodof, sumof, sumuf, denorm0, ae[12:0]);
/////////////////////////////////////////////////////////////////////////////
@ -28,36 +28,37 @@ module expgen(x[62:52], y[62:52], z[62:52],
input [62:52] y; // Exponent of multiplicand y
input [62:52] z; // Exponent of addend z
input [62:52] earlyres; // Result from other FPU block
input earlyressel; // Select result from other block
input earlyressel; // Select result from other block
input [1:1] bypsel; // Bypass X or Z
input byppostnorm; // Postnormalize bypassed result
input killprod; // Z >> product
input sumzero; // sum exactly equals zero
input postnormalize; // postnormalize rounded result
input byppostnorm; // Postnormalize bypassed result
input killprod; // Z >> product
input sumzero; // sum exactly equals zero
input postnormalize; // postnormalize rounded result
input [8:0] normcnt; // normalization shift count
input infinity; // generate infinity on overflow
input invalid; // Result invalid
input overflow; // Result overflowed
input underflow; // Result underflowed
input inf; // Some input is infinity
input nan; // Some input is NaN
input xnan; // X is NaN
input ynan; // Y is NaN
input znan; // Z is NaN
input zdenorm; // Z is denorm
input specialsel; // Select special result
input infinity; // generate infinity on overflow
input invalid; // Result invalid
input overflow; // Result overflowed
input underflow; // Result underflowed
input inf; // Some input is infinity
input nan; // Some input is NaN
input xnan; // X is NaN
input ynan; // Y is NaN
input znan; // Z is NaN
input zdenorm; // Z is denorm
input proddenorm; // product is denorm
input specialsel; // Select special result
output [11:0] aligncnt; // shift count for alignment shifter
output [62:52] w; // Exponent of result
output [62:52] wbypass; // Prerounded exponent for bypass
output prodof; // X*Y exponent out of bounds
output sumof; // X*Y+Z exponent out of bounds
output sumuf; // X*Y+Z exponent underflows
output denorm0; // exponent = 0 for denorm
output [62:52] w; // Exponent of result
output [62:52] wbypass; // Prerounded exponent for bypass
output prodof; // X*Y exponent out of bounds
output sumof; // X*Y+Z exponent out of bounds
output sumuf; // X*Y+Z exponent underflows
output denorm0; // exponent = 0 for denorm
output [12:0] ae; //exponent of multiply
// Internal nodes
wire [12:0] aetmp; // Exponent of Multiply
wire [12:0] aligncnt0; // Shift count for alignment
wire [12:0] aligncnt1; // Shift count for alignment
wire [12:0] be; // Exponent of multiply
@ -72,9 +73,11 @@ module expgen(x[62:52], y[62:52], z[62:52],
// Note that the exponent does not have to be incremented on a postrounding
// normalization of X because the mantissa was already increased. Report
// if exponent is out of bounds
assign ae = x + y - 1023;
assign prodof = (ae > 2046 && ~ae[12] && ~killprod);
assign ae = x + y - 1023;
assign prodof = (ae > 2046 && ~ae[12]);
// Compute alignment shift count
// Adjust for postrounding normalization of Z.
@ -82,8 +85,10 @@ module expgen(x[62:52], y[62:52], z[62:52],
// check if a round overflows is shorter than the actual round and
// is masked by the bypass mux and two 10 bit adder delays.
assign aligncnt0 = z - ae[10:0] + 13'b0;
assign aligncnt1 = z - ae[10:0] + 13'b1;
assign aligncnt0 = z - ae + 13'b0;// KEP use all of ae
assign aligncnt1 = z - ae + 13'b1;
//assign aligncnt0 = z - ae[10:0] + 13'b0;//original
//assign aligncnt1 = z - ae[10:0] + 13'b1;
assign aligncnt = bypsel[1] && byppostnorm ? aligncnt1 : aligncnt0;
// Select exponent (usually from product except in case of huge addend)
@ -118,13 +123,17 @@ module expgen(x[62:52], y[62:52], z[62:52],
// rounding mode. NaNs are propagated or generated.
assign specialres = earlyressel ? earlyres :
invalid ? nanres :
invalid | nan ? nanres : // KEP added nan
overflow ? infinityres :
inf ? 11'b11111111111 :
underflow ? 11'b0 : 11'bx;
assign infinityres = infinity ? 11'b11111111111 : 11'b11111111110;
// IEEE 754-2008 section 6.2.3 states:
// "If two or more inputs are NaN, then the payload of the resulting NaN should be
// identical to the payload of one of the input NaNs if representable in the destination
// format. This standard does not specify which of the input NaNs will provide the payload."
assign nanres = xnan ? x : (ynan ? y : (znan? z : 11'b11111111111));
// A mux selects the early result from other FPU blocks or the

View File

@ -13,31 +13,31 @@ module flag(xnan, ynan, znan, xinf, yinf, zinf, prodof, sumof, sumuf,
inf, nan, invalid, overflow, underflow, inexact);
/////////////////////////////////////////////////////////////////////////////
input xnan; // X is NaN
input ynan; // Y is NaN
input znan; // Z is NaN
input xinf; // X is Inf
input yinf; // Y is Inf
input zinf; // Z is Inf
input prodof; // X*Y overflows exponent
input sumof; // X*Y + z underflows exponent
input sumuf; // X*Y + z underflows exponent
input psign; // Sign of product
input zsign; // Sign of z
input xzero; // x = 0
input yzero; // y = 0
input [1:0] v; // R and S bits of result
output inf; // Some source is Inf
output nan; // Some source is NaN
output invalid; // Result is invalid
output overflow; // Result overflowed
output underflow; // Result underflowed
output inexact; // Result is not an exact number
input xnan; // X is NaN
input ynan; // Y is NaN
input znan; // Z is NaN
input xinf; // X is Inf
input yinf; // Y is Inf
input zinf; // Z is Inf
input prodof; // X*Y overflows exponent
input sumof; // X*Y + z underflows exponent
input sumuf; // X*Y + z underflows exponent
input psign; // Sign of product
input zsign; // Sign of z
input xzero; // x = 0
input yzero; // y = 0
input [1:0] v; // R and S bits of result
output inf; // Some source is Inf
output nan; // Some source is NaN
output invalid; // Result is invalid
output overflow; // Result overflowed
output underflow; // Result underflowed
output inexact; // Result is not an exact number
// Internal nodes
wire prodinf; // X*Y larger than max possible
wire suminf; // X*Y+Z larger than max possible
wire prodinf; // X*Y larger than max possible
wire suminf; // X*Y+Z larger than max possible
// If any input is NaN, propagate the NaN
@ -46,12 +46,14 @@ module flag(xnan, ynan, znan, xinf, yinf, zinf, prodof, sumof, sumuf,
// Same with infinity (inf - inf and O * inf don't propagate inf
// but it's ok becaue illegal op takes higher precidence)
assign inf= xinf || yinf || zinf;
assign inf= xinf || yinf || zinf || suminf;//KEP added suminf
//assign inf= xinf || yinf || zinf;//original
// Generate infinity checks
assign prodinf = prodof && ~xnan && ~ynan;
assign suminf = sumof && ~xnan && ~ynan && ~znan;
//KEP added if the product is infinity then sum is infinity
assign suminf = prodinf | sumof && ~xnan && ~ynan && ~znan;
// Set invalid flag for following cases:
// 1) Inf - Inf
@ -59,8 +61,7 @@ module flag(xnan, ynan, znan, xinf, yinf, zinf, prodof, sumof, sumuf,
// 3) Output = NaN (this is not part of the IEEE spec, only 486 proj)
assign invalid = (xinf || yinf || prodinf) && zinf && (psign ^ zsign) ||
xzero && yinf || yzero && xinf ||
nan;
xzero && yinf || yzero && xinf;// KEP remove case 3) above
// Set the overflow flag for the following cases:
// 1) Rounded multiply result would be out of bounds

View File

@ -103,7 +103,7 @@ module fmac(xrf, y, zrf, rn, rz, rp, rm,
earlyres[62:52], earlyressel, bypsel[1], byppostnorm,
killprod, sumzero, postnorrnalize, normcnt,
infinity, invalid, overflow, underflow,
inf, nan, xnan, ynan, znan, zdenorm, specialsel,
inf, nan, xnan, ynan, znan, zdenorm, proddenorm, specialsel,
aligncnt, w[62:52], wbypass[62:52],
prodof, sumof, sumuf, denorm0, ae);
// Instantiate special case detection across datapath & exponent path
@ -120,7 +120,7 @@ assign wbypass[63] = w[63];
// Instantiate control logic
sign sign(x[63], y[63], z[63], negsum0, negsum1, bs, ps,
killprod, rm, sumzero, nan, invalid, xinf, yinf, inf,
killprod, rm, overflow, sumzero, nan, invalid, xinf, yinf, zinf, inf,
w[63], invz, negsum, selsum1, psign);
flag flag(xnan, ynan, znan, xinf, yinf, zinf, prodof, sumof, sumuf,
psign, z[63], xzero, yzero, v[1:0],

View File

@ -18,12 +18,12 @@ module normalize(sum[157:0], normcnt, sumzero, bs, ps, denorm0, zdenorm, v[53:0]
/////////////////////////////////////////////////////////////////////////////
input [157:0] sum; // sum
input [8:0] normcnt; // normalization shift count
input sumzero; // sum is zero
input bs; // sticky bit for addend
input ps; // sticky bit for product
input denorm0; // exponent = -1023
input zdenorm; // Input Z is denormalized
output [53:0] v; // normalized sum, R, S bits
input sumzero; // sum is zero
input bs; // sticky bit for addend
input ps; // sticky bit for product
input denorm0; // exponent = -1023
input zdenorm; // Input Z is denormalized
output [53:0] v; // normalized sum, R, S bits
// Internal nodes

View File

@ -19,37 +19,37 @@ module round(v[53:0], earlyres[51:0], earlyressel, rz, rn, rp, rm, wsign,
w[51:0], postnormalize, infinity, specialsel);
/////////////////////////////////////////////////////////////////////////////
input [53:0] v; // normalized sum, R, S bits
input [51:0] earlyres; // result from other FPU blocks
input earlyressel; // use result from other FPU blocks
input rz; // Round toward zero
input rn; // Round toward nearest
input rp; // Round toward plus infinity
input rm; // Round toward minus infinity
input wsign; // Sign of result
input invalid; // Trap on infinity, NaN, denorm
input overflow; // Result overflowed
input underflow; // Result underflowed
input inf; // Some input is infinity
input nan; // Some input is NaN
input xnan; // X is NaN
input ynan; // Y is NaN
input znan; // Z is NaN
input [51:0] x; // Input X
input [51:0] y; // Input Y
input [51:0] z; // Input Z
output [51:0] w; // rounded result of FMAC
output postnormalize; // Right shift 1 for post-rounding norm
output infinity; // Generate infinity on overflow
output specialsel; // Select special result
input [53:0] v; // normalized sum, R, S bits
input [51:0] earlyres; // result from other FPU blocks
input earlyressel; // use result from other FPU blocks
input rz; // Round toward zero
input rn; // Round toward nearest
input rp; // Round toward plus infinity
input rm; // Round toward minus infinity
input wsign; // Sign of result
input invalid; // Trap on infinity, NaN, denorm
input overflow; // Result overflowed
input underflow; // Result underflowed
input inf; // Some input is infinity
input nan; // Some input is NaN
input xnan; // X is NaN
input ynan; // Y is NaN
input znan; // Z is NaN
input [51:0] x; // Input X
input [51:0] y; // Input Y
input [51:0] z; // Input Z
output [51:0] w; // rounded result of FMAC
output postnormalize; // Right shift 1 for post-rounding norm
output infinity; // Generate infinity on overflow
output specialsel; // Select special result
// Internal nodes
wire plus1; // Round by adding one
wire [52:0] v1; // Result + 1 (for rounding)
wire [51:0] specialres; // Result of exceptional case
wire plus1; // Round by adding one
wire [52:0] v1; // Result + 1 (for rounding)
wire [51:0] specialres; // Result of exceptional case
wire [51:0] infinityres; // Infinity or largest real number
wire [51:0] nanres; // Propagated or generated NaN
wire [51:0] nanres; // Propagated or generated NaN
// Compute if round should occur. This equation is derived from
// the rounding tables.
@ -77,7 +77,7 @@ module round(v[53:0], earlyres[51:0], earlyressel, rz, rn, rp, rm, wsign,
assign specialsel = earlyressel || overflow || underflow || invalid ||
nan || inf;
assign specialres = earlyressel ? earlyres :
invalid ? nanres :
invalid | nan ? nanres : //KEP added nan
overflow ? infinityres :
inf ? 52'b0 :
underflow ? 52'b0 : 52'bx; // default to undefined
@ -93,6 +93,11 @@ module round(v[53:0], earlyres[51:0], earlyressel, rz, rn, rp, rm, wsign,
// NaN inputs are already quiet, we don't have to force them quiet.
// assign nanres = xnan ? x: (ynan ? y : (znan ? z : {1'b1, 51'b0})); // original
// IEEE 754-2008 section 6.2.3 states:
// "If two or more inputs are NaN, then the payload of the resulting NaN should be
// identical to the payload of one of the input NaNs if representable in the destination
// format. This standard does not specify which of the input NaNs will provide the payload."
assign nanres = xnan ? {1'b1, x[50:0]}: (ynan ? {1'b1, y[50:0]} : (znan ? {1'b1, z[50:0]} : {1'b1, 51'b0}));// KEP 210112 add the 1 to make NaNs quiet
// Select result with 4:1 mux

View File

@ -10,8 +10,8 @@
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
module sign(xsign, ysign, zsign, negsum0, negsum1, bs, ps, killprod, rm,
sumzero, nan, invalid, xinf, yinf, inf, wsign, invz, negsum, selsum1, psign);
module sign(xsign, ysign, zsign, negsum0, negsum1, bs, ps, killprod, rm, overflow,
sumzero, nan, invalid, xinf, yinf, zinf, inf, wsign, invz, negsum, selsum1, psign);
////////////////////////////////////////////////////////////////////////////I
input xsign; // Sign of X
@ -23,11 +23,13 @@ module sign(xsign, ysign, zsign, negsum0, negsum1, bs, ps, killprod, rm,
input ps; // sticky bit from product
input killprod; // Product forced to zero
input rm; // Round toward minus infinity
input overflow; // Round toward minus infinity
input sumzero; // Sum = O
input nan; // Some input is NaN
input invalid; // Result invalid
input xinf; // X = Inf
input yinf; // Y = Inf
input zinf; // Y = Inf
input inf; // Some input = Inf
output wsign; // Sign of W
output invz; // Invert addend into adder
@ -47,13 +49,13 @@ module sign(xsign, ysign, zsign, negsum0, negsum1, bs, ps, killprod, rm,
assign psign = xsign ^ ysign;
// Invert addend if sign of Z is different from sign of product assign invz = zsign ^ psign;
assign invz = zsign ^ psign;
assign invz = (zsign ^ psign);
// Select +l mode for adder and compute if result must be negated
// This is done according to cases based on the sticky bit.
always @(invz or negsum0 or negsum1 or bs or ps)
begin
if (~invz) begin // both inputs have same sign
if (~invz) begin // both inputs have same sign //KEP if overflow
negsum = 0;
selsum1 = 0;
end else if (bs) begin // sticky bit set on addend
@ -85,9 +87,8 @@ module sign(xsign, ysign, zsign, negsum0, negsum1, bs, ps, killprod, rm,
// sum/difference shall be -0. However, x+x = x-(-X) retains the same sign as x even when x is zero."
assign zerosign = (~invz && killprod) ? zsign : rm;
assign infsign = psign; //KEP 210112 keep the correct sign when result is infinity
// assign infsign = xinf ? (yinf ? psign : xsign) : yinf ? ysign : zsign;//original
assign wsign =invalid? 0 : (inf ? infsign:
(sumzero ? zerosign : psign ^ negsum));
assign infsign = zinf ? zsign : psign; //KEP 210112 keep the correct sign when result is infinity
//assign infsign = xinf ? (yinf ? psign : xsign) : yinf ? ysign : zsign;//original
assign wsign = invalid ? 0 : (inf ? infsign :(sumzero ? zerosign : psign ^ negsum));
endmodule

View File

@ -14,23 +14,23 @@ module special(x[63:0], y[63:0], z[63:0], ae, xzero, yzero, zzero,
xnan, ynan, znan, xdenorm, ydenorm, zdenorm, proddenorm, xinf, yinf, zinf);
/////////////////////////////////////////////////////////////////////////////
input [63:0] x; // Input x
input [63:0] x; // Input x
input [63:0] y; // Input Y
input [63:0] z; // Input z
input [12:0] ae; // exponent of product
output xzero; // Input x = 0
output yzero; // Input y = 0
output zzero; // Input z = 0
output xnan; // x is NaN
output ynan; // y is NaN
output znan; // z is NaN
output xdenorm; // x is denormalized
output ydenorm; // y is denormalized
output zdenorm; // z is denormalized
output proddenorm; // product is denormalized
output xinf; // x is infinity
output yinf; // y is infinity
output zinf; // z is infinity
input [12:0] ae; // exponent of product
output xzero; // Input x = 0
output yzero; // Input y = 0
output zzero; // Input z = 0
output xnan; // x is NaN
output ynan; // y is NaN
output znan; // z is NaN
output xdenorm; // x is denormalized
output ydenorm; // y is denormalized
output zdenorm; // z is denormalized
output proddenorm; // product is denormalized
output xinf; // x is infinity
output yinf; // y is infinity
output zinf; // z is infinity
// In the actual circuit design, the gates looking at bits
// 51:0 and at bits 62:52 should be shared among the various detectors.

View File

@ -1 +1,130 @@
0020000803ffffff bfcb4181a9468e24 000fffffffffffff 7fe2f9c2bca0f33c 00092f9c2bca0f33 Wrong zdenorm 18
0000000000000001 7fdffffeffffffbf 4000000000080004 4007ffffc007fff5 4000000000080005 Wrong xdenorm 85959
0000000000000001 c3ded4d0b02cd6aa 000c158ac12ac439 83eed4d0b02cd6ae 80bed1cb4d7c8bf9 Wrong xdenorm zdenorm 91485
c15000000010001f 434ffffffffffffe 47f55792228596a0 c7e550dbbaf4d2c2 47f557922285969f Wrong 97625
0000000000000001 7fe0000000000001 4340000000000001 4340000000000002 4340000000000001 Wrong xdenorm 99467
0000000000000001 bfdffffffffffffe 801fffffffffbfc0 8021ffffffffdfe0 801fffffffffbfc0 Wrong xdenorm 117273
0000000000000001 ffe0000000000000 40d4000040000000 40d3ffc040000000 40d4000040000000 Wrong xdenorm 133851
000fffffffffffff 3fcffc007fffffff 800fffffffffffff 800800ffe0000000 800c007fefffffff Wrong xdenorm zdenorm 147973
000fffffffffffff 3feffffffffffffe 000ffffffffffffe 001ffffffffffffd 001ffffffffffffc Wrong xdenorm zdenorm 154727
000ffffffffffffe 41dffffffffff900 0000000000000001 02000000000ffc7e 01fffffffffff8fc Wrong xdenorm zdenorm 230863
0010000000000000 bf4fdffffff7fffe 800ffffffffffffe 801003fbfffffeff 801003fbfffffefe Wrong zdenorm 308227
0010000000000000 be6fffffbffffff7 8000000000000000 8000000000000000 800000000fffffe0 Wrong w=-zero unflw 313753
0010000000000001 bcafffffffffffff 801fffffffffffff 8000000000000000 8020000000000000 Wrong w=-zero unflw 392345
0010000000000001 bfe0000000000001 800ffffffffffffe 8018000000000000 8017ffffffffffff Wrong zdenorm 397871
802000003ffffbff c3cfffffffffffd7 0000000000000001 040000003ffffbeb 040000003ffffbea Wrong zdenorm 448219
dc10000000001eff 0000000000000001 802d63f274ada691 9c20000000001f01 98f0000000001eff Wrong ydenorm 489971
001ffffffffffffe 3fddfbffffffffff 000ffffffffffffe 001efdfffffffffe 001efdfffffffffd Wrong zdenorm 551371
3ca0000000000000 0000000000000001 000e8d6ac606e59d 000e8d6ac606e59e 000e8d6ac606e59d Wrong ydenorm zdenorm 559353
3ca0000000000000 434ffffffffffffe c019cab46f8c90a7 c011cab46f8c90a7 c011cab46f8c90a8 Wrong 586983
3ca0000000000001 bfe000000fffdfff 3fee60af9e2e4b00 bfa9f5061d1b5008 3fee60af9e2e4aff Wrong 649611
3ca0000000000001 7fe0000000000000 ffefffffffffffff 7ca8000000000000 ffeffffffffffffe Wrong 657593
44f0000000000dff 000000007fbffffe 801ffffffffffffe 05000000ff800dfb 03bfefffff801bf0 Wrong ydenorm 680311
3ca0000000000001 bfffffffffffffff 3ff0007ffffffc00 bfefff0000000802 3ff0007ffffffbff Wrong 680925
3cafffffffffffff 3caffffffffffffe bcaffffffffffffe 397fffffffffffff bcaffffffffffffc Wrong 707327
3cafffffffffffff c01ffffffffffffe c02cbe486a2b0809 c02cbe486a2b0809 c02cbe486a2b080a Wrong 758289
000667c5d67e1d85 3fdfeffffdffffff 001fffffffffffff 002398247cab1886 002199247ccb1886 Wrong xdenorm 763201
000007fffffffffe 3f6ffffffe01fffe 000ffffffffffffe 00100807ffff7fff 00100007ffffff7e Wrong xdenorm zdenorm 768727
3caffffffffffffe 4060000001000006 4070001fffff7ffe 4070001fffff7ffe 4070001fffff7fff Wrong 771183
3caffffffffffffe 3fdfffffffffffff 3fe0000000000000 3fe0000000000000 3fe0000000000001 Wrong 779165
bfd7ffffffbfffff 4000000000000000 3fffffffffffffff 3ff40000001fffff 3ff4000000200000 Wrong 787147
3caffffffffffffe c00ffffffffffffe c01000000020007f c01000000020007f c010000000200080 Wrong 824601
3caffffffffffffe c00fffffffffff08 4010000000000001 4010000000000001 4010000000000000 Wrong 827671
800000000000007e ffd26a0f710537a9 c01b3b74de550046 c018ee32f034592d c01b3b74de550022 Wrong xdenorm 861441
47f9aa99d39dd7d8 0000000000000001 8000000000000000 0809aa99d39dd7db 04d9aa99d39dd7d8 Wrong ydenorm 908719
bfef000004000000 c000000000000000 c34ff80000000006 42afffffffffebe0 c34ff80000000005 Wrong 1031519
bfe0010000007fff 3ff00003ffffff7f 4340000000000000 4340000000000000 433fffffffffffff Wrong 1039501
3fdffffffffffffe 000ffffffffffffe 8000000000000001 fcdfffffffffffff 0007fffffffffffe Wrong ydenorm zdenorm 1049939
802000007fffffbf 400ffffffffffffe 8000000000000001 804100007fffffbe 804000007fffffbe Wrong zdenorm 1068973
3fdffffffffffffe bfffffffffffffff 3fefffffffffffff 3caffffffffffffe 3cafffffffffffff Wrong 1099673
c7fffffffb7fffff 37efffffffdffbff c34000003ffffffc c34000003ffffffc c34000003ffffffd Wrong 1104585
3fe0000000000001 3ca0000000000000 bcaffffffffffffe bca7fffffffffffd bca7fffffffffffe Wrong 1193615
bfe00000000effff 800fffffffffffff 8010000000000001 8000000000000000 8007fffffff88002 Wrong w=-zero ydenorm unflw 1223701
3feffffffffffffe 3ff0000000000000 bfefffffffffffff bc9ffffffffffffc bca0000000000000 Wrong 1342817
3feffffffffffffe 801fffffffffffff 800007fffffbfffe 802401fffffefffe 802003fffffdfffe Wrong zdenorm 1366149
bfd0002000007fff 0000000000000001 0010000000000001 0000000000000000 0010000000000001 Wrong ydenorm unflw 1466845
0003476357ebf517 7fe000004000003f 8000000000000000 3ff68ec70a130546 3fda3b1b284c141d Wrong xdenorm 1503685
4000002003fffffe bc4fffffbffffffe bfbfffffffffe3ff bfbfffffffffe3ff bfbfffffffffe400 Wrong 1635081
3ca00ffdffffffff 3fdffffffffffffe bfe0000000000001 bfe0000000000001 bfe0000000000000 Wrong 1687885
801fffffbf000000 4012b6da70c3decc 0000000000000006 8041b6da4ac07317 8042b6da4ac07316 Wrong zdenorm 1753583
b7ff7ffffffff000 7fe0000000000000 78b01fffefffffff 78b01f03efffffff 78b01f03f0000000 Wrong 1843841
400fffffffffffff 8000000000000001 801fffffffffffff 8030000000000000 8020000000000001 Wrong ydenorm 1851209
00003fefffffffff ffeffffffffffffe 8000000000000000 c0007fdffffffffd bfaff7ffffffff7e Wrong xdenorm 1881295
800000000003fffe 578284b14dfcc6e4 8000000000000000 979284b14e060938 958284a80ba41fe6 Wrong xdenorm 1989973
bfdeffffff000000 002ffffffffc3ffe 0000002003fffffe 8016ffeffcfc5dff 801effdffafc5e00 Wrong zdenorm 2018831
401fffffffffffff 3fdffffffffffffe c340000000400002 433fffffff800000 c340000000400000 Wrong 2106633
401fffffffffffff 4010000000000001 c050ffffffff0000 c041fffffffdffff c041fffffffe0000 Wrong 2117685
4340000000000000 3fd0000000000000 3fd0000000000001 4320000000000000 4320000000000001 Wrong 2243555
bcb58ba32df145e0 3fbe0000003fffff 3fe0000000000000 3fe0000000000000 3fdfffffffffffff Wrong 2365741
bfed82e3c6c037db 3ff0000000000000 4340000000000000 4340000000000000 433fffffffffffff Wrong 2389687
3fdfffffffff7000 bcaffffffffffffe 3fe0000000000001 3fe0000000000001 3fe0000000000000 Wrong 2417317
8000000002000000 ff100001efffffff 8d261bb2da873976 3f200001f400007b 3d800001efffffff Wrong xdenorm 2422229
bb0fb893e0decb72 c1cffff7ffbfffff c03ffc0000003fff c03ffc0000003fff c03ffc0000003ffe Wrong 2546871
800000000e000000 3fffffffffffffff 034ffff80ffffffe 034ffff80ffffffc 034ffff80ffffffe Wrong xdenorm 2600903
7fe0000000000001 4000000000000000 ffefffffffffffff 7ff0000000000000 7cb8000000000000 Wrong w=+inf 2602745
7fe0000000000001 8000000000000001 c010000000000001 c014000000000002 c010000000000002 Wrong ydenorm 2619323
7fe0000000000001 bcafffffffffffff 7fefffffdffffffc fe70000002800000 7fefffffdffffffb Wrong 2626077
7fefffffffffffff 0000000000000001 37ffffff7ffffeff 4000000000000001 3ccfffffffffffff Wrong ydenorm 2653707
3feffffffffbfffd 3ca0000000000001 bfe0000000000001 3fe0000000000000 bfe0000000000000 Wrong 2660461
000ffffffff00006 bfe0000000000001 0000000000000001 7dfffff400000002 8007fffffff80002 Wrong xdenorm zdenorm 2770981
fd61dd32fb8e3b2c 0000000000000001 801ffffffffffffe bd71dd32fb8e3b2e ba41dd32fb8e3b2c Wrong ydenorm 3003073
000fff000000000f 3ff00800001fffff 8010000000000000 0000000000000000 000006ff801ffe0e Wrong xdenorm unflw 3117277
8000000000000001 400effffff000000 0010000000000000 8000000000000000 000ffffffffffffc Wrong w=-zero xdenorm unflw 3143065
8000000000000001 40211275ffe5ee3c 0000000000000001 802e24ebffcbdc7c 8000000000000008 Wrong xdenorm zdenorm 3148591
8000000000000001 c1c01ffffffffefe 03100007fe000000 0310000900000000 03100007fe000000 Wrong xdenorm 3152889
8000000000000001 3fe0000000000001 800fffffffffffff 8014000000000000 8010000000000000 Wrong xdenorm zdenorm 3155345
8000000000000001 7fef848cc01517b4 c340000000000001 c340000000000002 c340000000000001 Wrong xdenorm 3170695
8000000000000001 7feffffffffffffe 410ffffffc007ffe 410fffeffc007ffe 410ffffffc007ffe Wrong xdenorm 3173151
8000000000000001 bffffffffffffffe 002e000000100000 0033000000080000 002e000000100001 Wrong xdenorm 3195255
8000000000000001 ffe0000000000000 3feffffffffffffe 4000000000000000 3ff0000000000001 Wrong xdenorm 3205079
8000000000000001 ffe0000000000001 c1ffbfffdffffffe c1ffbfffdfeffffe c1ffbfffdffffffe Wrong xdenorm 3206307
800fffffffffffff 3ff0000000000000 001ffffffffffffe 0000000000000000 000fffffffffffff Wrong xdenorm unflw 3227183
3e7ffffffefc0000 bfffffffffffffff 41c0ea1ad0c683e5 c1be2bca5e72f83a 41c0ea1ad0c683e3 Wrong 3264023
3fffa9456a66b8c6 3caffffffffffffe c00ffffffffffffe c00ffffffffffffe c00ffffffffffffd Wrong 3290425
800ffffffffffffe 3fe0000000000001 0010000400000010 0000000000000000 0008000400000011 Wrong xdenorm unflw 3294723
800ffffffffffffe 3fd0000000007ffe 000fffffffffffff 0007ffffffffc001 000bffffffffe000 Wrong xdenorm zdenorm 3308845
800ffffffffffffe c010000000000000 800dfede47fbc1e2 002880486e010f84 00290090dc021f0b Wrong xdenorm zdenorm 3338931
bfdffc90d6e1fc1f 3ca1ffffffffeffe bfe66ad464a87aac bfe66ad464a87aac bfe66ad464a87aad Wrong 3367175
8010000000000000 bfe0000000000000 000fffffffffffff 0018000000000000 0017ffffffffffff Wrong zdenorm 3398489
7fe800000000003e 8004de935d68d1e8 801fffffffffffff c0034ddd0c1d3b0e bfed37743074ebbb Wrong ydenorm 3437785
8010000000000001 bfefffffffffffff 801ffffffffffffe 8000000000000000 800ffffffffffffe Wrong w=-zero unflw 3470327
801fffffffffffff bfdffffffffffffe 0000000000021fff 0018000000010ffe 0010000000021ffe Wrong zdenorm 3537867
0005e0458a43fbdb 7fdfffbfffffffff 0000000000000000 3ffbc0539371cea5 3fe780e726e39d4b Wrong xdenorm 3691981
bca0000000000001 3cafffffffffffff 3cafffffffffffff b970000000000000 3caffffffffffffe Wrong 3707945
bca0000000000001 3fefffffffffffff bff0400000000400 bff0400000000400 bff0400000000401 Wrong 3714699
bca0000000000001 c34ffffffffffffe c000000000000000 0000000000000000 b980000000000000 Wrong 3763205
bcafffffffffffff 3fc200001fffffff 3fdffff00000ffff 3fdffff00000ffff 3fdffff00000fffe Wrong 3788379
bcafffffffffffff 800ffffffffffffe 8000000000000000 0000000000000000 0000000000000001 Wrong ydenorm unflw 3807413
bcaffffffffffffe 3fdffffffffffffe 3ff0000000000000 3ff0000000000000 3fefffffffffffff Wrong 3851621
bcaffffffffffffe 001ffffffffc0000 8000000000000001 8000000000000005 8000000000000003 Wrong zdenorm 3878023
7fec5fed92358a74 400000001bffffff ffefc0003ffffffe 7ff0000000000000 7fe8ffdb47bad466 Wrong w=+inf 3889689
bfdfffffffffffff 000fffffffffffff 0000000000000000 8000000000000000 8007ffffffffffff Wrong w=-zero ydenorm unflw 4050557
bfdfffffffffffff 8000000000000001 8010000000800400 8000000000000000 8010000000800400 Wrong w=-zero ydenorm unflw 4084941
bfdfffffffffffff bff0000000000000 bfe0000000000001 bca7ffffffffffff bca8000000000000 Wrong 4100291
bff400003ffffffe bfeffffffffffffe 434fffffffffffff 434fffffffffffff 4350000000000000 Wrong 4169059
43f00002003ffffe 8000000000000001 0010000000000000 8400000200400000 80cffe04007ffffc Wrong ydenorm 4224319
bfe0000000000000 801fffffffffffff 00000007fff80000 00180003fffc0000 00100007fff80000 Wrong zdenorm 4228617
bfe0000000000000 c000000000000001 c00ffffffffffffe c007fffffffffffd c007fffffffffffe Wrong 4243967
bfcfdffffeffffff 8000000000000001 000fffffffffe080 0011fdffffeff040 000fffffffffe080 Wrong ydenorm zdenorm 4573685
bfffffffffffffff 0000000000000001 8010000000000001 8020000000000001 8010000000000003 Wrong ydenorm 4608683
bfffffffffffffff 3cafffffffffffff 3ff00000040001ff bfeffffff7fffc06 3ff00000040001fd Wrong 4615437
d2b6d8b0e4fde949 0000000000000001 0011fffffffffeff 92c6d8b0e4fde94c 8f96d8b0e4fde949 Wrong ydenorm 4678679
3fd07dfffffffffe 8010000000000001 0000000000000001 7fef040000000006 80041f7fffffffff Wrong zdenorm 4716133
bffffffffffffffe bfffffffffffffff c00ffffffffffffe bcbffffffffffffc bcbffffffffffffe Wrong 4730255
c000000000000001 00000000004fffff 801ffffffffffffe 80280000004fffff 80200000004ffffe Wrong ydenorm 4839547
c00982d68cfe066b 000ffffffffffffe 8000000000000001 802d82d68cfe0668 802982d68cfe0668 Wrong ydenorm zdenorm 4959277
346ffffffffffeef 480ffffeffffffe0 3fdfffffffffffff 3fdfffffffffffff 3fe0000000000000 Wrong 4962961
c01fffffffffffff 0007ffffffff0000 8000000000000000 803ffffffffdffff 802ffffffffbffff Wrong ydenorm 5176633
c01fffffffffffff bfc08000000fffff 434ffffffffffffe 434ffffffffffffe 434fffffffffffff Wrong 5193211
c3a000000fffff7f 80000000000005fe 001000003ffffbff 03b0000010000b7b 0127f80817f81f3f Wrong ydenorm 5450477
0012000000000001 4000000000000001 000909a97b1f06a1 0028426a5ec7c1aa 002684d4bd8f8353 Wrong zdenorm 5535209
ffe0000000000000 8000000000000001 c03000000000003f c02e00000000007e c03000000000003f Wrong ydenorm 5621169
ffe0000000000001 3ca0c6fe6997e5e2 7fefffffffffffff fca8637f34cbf2f2 7feffffffffffffe Wrong 5673973
ffe0000000000001 800fffffffffffff c340000000000001 4340000000000000 c340000000000000 Wrong ydenorm 5691779
43f4595959dece4b 8000000000000001 801fffffffffffff 8404595959dece4e 80d45b5959dece4b Wrong ydenorm 5760547
ffefffffffffffff 3ca14e19e3a06f13 7fe00000000ff7fe ffdfffffffe01006 7fe00000000ff7fd Wrong 5783265
ffeffffffffffffe 8000000000000001 000fffffffffffff 4000000000000001 3ccffffffffffffe Wrong ydenorm zdenorm 5829929
ffeffffffffffffe 800001fffbffffff bac0000ffeffffff 400003fff7fffffd 3f5fffbfffffeffe Wrong ydenorm 5832999
bca0000004000080 bff0000000000009 bff0000000000001 3fefffffffffffff bff0000000000000 Wrong 5841595
3fffffffff9ffffe 800000000f7ffffe 800ffdffbffffffe 801ffefffecffffa 800ffdffdefffffa Wrong ydenorm zdenorm 5887031
41ccc32b421f1ac0 8000000000000001 802ffffc0000001e 81dcc32b461f1a44 802ffffc1cc32b60 Wrong ydenorm 5899925
41ffffffffffff87 8000000000000001 0000000000000000 820fffffffffff8b 8000000200000000 Wrong ydenorm 6039335

Binary file not shown.

View File

@ -14,24 +14,31 @@ void main() {
fp = fopen("testFloat","r");
fq = fopen("tb.v","a");
system("cp tbhead.v tb.v");
int k=0;
for(k=0; k<91 && !feof(fp); k++) {
long k=0L;
for(; !feof(fp); k++) {
//3FDBFFFFFFFFFF7F DE608000000001FF 43CFED83C17EDBD0 DE4CE000000002F9 01
// b68ffff8000000ff_3f9080000007ffff_b6307ffbe0080080_00001
char ch;
int i,j;
char *ln;
char ch;
int i,j,n;
char xrf[17];
char y[17];
char zrf[17];
char ans[81];
char flags[3];
int rn,rz,rm,rp;
{
//my_string = (char *) malloc (nbytes + 1);
//bytes_read = getline (&my_string, &nbytes, stdin);
if(getline(&ln,&nbytes,fp) < 0) break;
//fprintf(stderr,"%s\n", ln);
long stop = 6039335;
int debug = 0;
//my_string = (char *) malloc (nbytes + 1);
//bytes_read = getline (&my_string, &nbytes, stdin);
for(n=0; n < 613; n++) {//613 for 10000
if(getline(&ln,&nbytes,fp) < 0 || feof(fp)) break;
if(k == stop && debug == 1) break;
k++;
}
//fprintf(stderr,"%s\n", ln);
if(!feof(fp)) {
strncpy(xrf, ln, 16); xrf[16]=0;
strncpy(y, &ln[17], 16); y[16]=0;
@ -46,71 +53,80 @@ void main() {
fprintf(fq," zrf = 64'h%s;\n",zrf);
fprintf(fq," ans = 64'h%s;\n", ans);
// fprintf(fq," flags = 5'h%s;\n", flags);
}
{
//rn=1; rz=0; rm=0; rp=0;
fprintf(fq," rn = %d;\n",1);
fprintf(fq," rz = %d;\n", 0);
fprintf(fq," rm = %d;\n", 0);
fprintf(fq," rp = %d;\n", 0);
}
{
fprintf(fq," earlyres = 64'b0;\n");
fprintf(fq," earlyressel = 0;\n");
}
{
{
//rn=1; rz=0; rm=0; rp=0;
fprintf(fq," rn = %d;\n",1);
fprintf(fq," rz = %d;\n", 0);
fprintf(fq," rm = %d;\n", 0);
fprintf(fq," rp = %d;\n", 0);
}
{
fprintf(fq," earlyres = 64'b0;\n");
fprintf(fq," earlyressel = 0;\n");
}
{
fprintf(fq," bypsel= 2'b0;\n"); //, bysel);
fprintf(fq," bypplus1 = 0;\n"); //, byp1);
fprintf(fq," byppostnorm = 0;\n"); //, bypnorm);
}
fprintf(fq,"#10\n");
// IEEE 754-2008 section 6.3 states "When ether an input or result is NaN, this standard does not interpret the sign of a NaN."
//fprintf(fq," $fwrite(fp, \"%%h %%h %%h %%h \",xrf,y,w, ans);\n");
fprintf(fq," // IEEE 754-2008 section 6.3 states: \"When ether an input or result is NaN, this\n");
fprintf(fq," // standard does not interpret the sign of a NaN.\"\n");
fprintf(fq," nan = (w > 64'h7FF0000000000000 && w < 64'h7FF8000000000000) ||\n");
fprintf(fq," (w > 64'hFFF8000000000000 && w < 64'hFFF8000000000000 ) ||\n");
fprintf(fq," (w >= 64'h7FF8000000000000 && w <= 64'h7FFfffffffffffff ) ||\n");
fprintf(fq," (w >= 64'hFFF8000000000000 && w <= 64'hFFFfffffffffffff );\n");
// fprintf(fq," if(!(~(|xrf[62:52]) && |xrf[51:0] || ~(|y[62:52]) && |y[51:0])) begin\n");
// not looknig at negative zero results right now
//fprintf(fq," if( (nan && (w[62:0] != ans[62:0])) || (!nan && (w != ans)) && !(w == 64'h8000000000000000 && ans == 64'b0)) begin\n");
fprintf(fq," if( (nan && (w[62:0] != ans[62:0])) || (!nan && (w != ans)) ) begin\n");
fprintf(fq," $fwrite(fp, \"%%h %%h %%h %%h %%h Wrong \",xrf,y, zrf, w, ans);\n");
fprintf(fq," if(w == 64'h8000000000000000) $fwrite(fp, \"w=-zero \");\n");
fprintf(fq," if(~(|xrf[62:52]) && |xrf[51:0]) $fwrite(fp, \"xdenorm \");\n");
fprintf(fq," if(~(|y[62:52]) && |y[51:0]) $fwrite(fp, \"ydenorm \");\n");
fprintf(fq," if(~(|zrf[62:52]) && |zrf[51:0]) $fwrite(fp, \"zdenorm \");\n");
fprintf(fq," if(invalid != 0) $fwrite(fp, \"invld \");\n");
fprintf(fq," if(overflow != 0) $fwrite(fp, \"ovrflw \");\n");
fprintf(fq," if(underflow != 0) $fwrite(fp, \"unflw \");\n");
fprintf(fq," if(w == 64'hFFF0000000000000) $fwrite(fp, \"w=-inf \");\n");
fprintf(fq," if(w == 64'h7FF0000000000000) $fwrite(fp, \"w=+inf \");\n");
fprintf(fq," if(w > 64'h7FF0000000000000 && w < 64'h7FF8000000000000 ) $fwrite(fp, \"w=sigNaN \");\n");
fprintf(fq," if(w > 64'hFFF8000000000000 && w < 64'hFFF8000000000000 ) $fwrite(fp, \"w=sigNaN \");\n");
fprintf(fq," if(w >= 64'h7FF8000000000000 && w <= 64'h7FFfffffffffffff ) $fwrite(fp, \"w=qutNaN \");\n");
fprintf(fq," if(w >= 64'hFFF8000000000000 && w <= 64'hFFFfffffffffffff ) $fwrite(fp, \"w=qutNaN \");\n");
fprintf(fq," bypsel= 2'b0;\n"); //, bysel);
fprintf(fq," bypplus1 = 0;\n"); //, byp1);
fprintf(fq," byppostnorm = 0;\n"); //, bypnorm);
}
fprintf(fq,"#10\n");
// IEEE 754-2008 section 6.3 states "When ether an input or result is NaN, this standard does not interpret the sign of a NaN."
//fprintf(fq," $fwrite(fp, \"%%h %%h %%h %%h \",xrf,y,w, ans);\n");
fprintf(fq," // IEEE 754-2008 section 6.3 states: \"When ether an input or result is NaN, this\n");
fprintf(fq," // standard does not interpret the sign of a NaN.\"\n");
fprintf(fq," wnan = &w[62:52] && |w[51:0]; \n");
fprintf(fq," xnan = &xrf[62:52] && |xrf[51:0]; \n");
fprintf(fq," ynan = &y[62:52] && |y[51:0]; \n");
fprintf(fq," znan = &zrf[62:52] && |zrf[51:0]; \n");
fprintf(fq," ansnan = &ans[62:52] && |ans[51:0]; \n");
fprintf(fq," xnorm = ~(|xrf[62:52]) && |xrf[51:0] ? {xrf[50:0], 1'b0} : xrf; \n");
fprintf(fq," ynorm = ~(|y[62:52]) && |y[51:0] ? {y[50:0], 1'b0} : y;\n");
fprintf(fq," s = ({54'b1,xnorm} + (bypsel && bypplus1)) * {54'b1,ynorm}; \n");
// fprintf(fq," if(!(~(|xrf[62:52]) && |xrf[51:0] || ~(|y[62:52]) && |y[51:0])) begin\n");
// not looknig at negative zero results right now
//fprintf(fq," if( (nan && (w[62:0] != ans[62:0])) || (!nan && (w != ans)) && !(w == 64'h8000000000000000 && ans == 64'b0)) begin\n");
// fprintf(fq," if( (nan && (w[62:0] != ans[62:0])) || (!nan && (w != ans)) ) begin\n");
fprintf(fq," if((!wnan && (w != ans)) || (wnan && ansnan && ~(((xnan && (w[62:0] == {xrf[62:52],1'b1,xrf[50:0]})) || (ynan && (w[62:0] == {y[62:52],1'b1,y[50:0]})) || (znan && (w[62:0] == {zrf[62:52],1'b1,zrf[50:0]})) || (w[62:0] == ans[62:0])) ))) begin\n");
fprintf(fq," $fwrite(fp, \"%%h %%h %%h %%h %%h Wrong \",xrf,y, zrf, w, ans);\n");
//fprintf(fq," $fwrite(fp, \"%%h \",s);\n");
fprintf(fq," if(w == 64'h8000000000000000) $fwrite(fp, \"w=-zero \");\n");
fprintf(fq," if(~(|xrf[62:52]) && |xrf[51:0]) $fwrite(fp, \"xdenorm \");\n");
fprintf(fq," if(~(|y[62:52]) && |y[51:0]) $fwrite(fp, \"ydenorm \");\n");
fprintf(fq," if(~(|zrf[62:52]) && |zrf[51:0]) $fwrite(fp, \"zdenorm \");\n");
fprintf(fq," if(invalid != 0) $fwrite(fp, \"invld \");\n");
fprintf(fq," if(overflow != 0) $fwrite(fp, \"ovrflw \");\n");
fprintf(fq," if(underflow != 0) $fwrite(fp, \"unflw \");\n");
fprintf(fq," if(w == 64'hFFF0000000000000) $fwrite(fp, \"w=-inf \");\n");
fprintf(fq," if(w == 64'h7FF0000000000000) $fwrite(fp, \"w=+inf \");\n");
fprintf(fq," if(w > 64'h7FF0000000000000 && w < 64'h7FF8000000000000 ) $fwrite(fp, \"w=sigNaN \");\n");
fprintf(fq," if(w > 64'hFFF8000000000000 && w < 64'hFFF8000000000000 ) $fwrite(fp, \"w=sigNaN \");\n");
fprintf(fq," if(w >= 64'h7FF8000000000000 && w <= 64'h7FFfffffffffffff ) $fwrite(fp, \"w=qutNaN \");\n");
fprintf(fq," if(w >= 64'hFFF8000000000000 && w <= 64'hFFFfffffffffffff ) $fwrite(fp, \"w=qutNaN \");\n");
fprintf(fq," if(ans == 64'hFFF0000000000000) $fwrite(fp, \"ans=-inf \");\n");
fprintf(fq," if(ans == 64'h7FF0000000000000) $fwrite(fp, \"ans=+inf \");\n");
fprintf(fq," if(ans > 64'h7FF0000000000000 && ans < 64'h7FF8000000000000 ) $fwrite(fp, \"ans=sigNaN \");\n");
fprintf(fq," if(ans > 64'hFFF8000000000000 && ans < 64'hFFF8000000000000 ) $fwrite(fp, \"ans=sigNaN \");\n");
fprintf(fq," if(ans >= 64'h7FF8000000000000 && ans <= 64'h7FFfffffffffffff ) $fwrite(fp, \"ans=qutNaN \");\n");
fprintf(fq," if(ans >= 64'hFFF8000000000000 && ans <= 64'hFFFfffffffffffff ) $fwrite(fp, \"ans=qutNaN \");\n");
fprintf(fq," $fwrite(fp,\"%d\\n\");\n",cnt);
if(cnt == 358)fprintf(fq," $stop;\n");
// fprintf(fq," end\n");
fprintf(fq," end\n");
cnt++;
fprintf(fq," if(ans == 64'hFFF0000000000000) $fwrite(fp, \"ans=-inf \");\n");
fprintf(fq," if(ans == 64'h7FF0000000000000) $fwrite(fp, \"ans=+inf \");\n");
fprintf(fq," if(ans > 64'h7FF0000000000000 && ans < 64'h7FF8000000000000 ) $fwrite(fp, \"ans=sigNaN \");\n");
fprintf(fq," if(ans > 64'hFFF8000000000000 && ans < 64'hFFF8000000000000 ) $fwrite(fp, \"ans=sigNaN \");\n");
fprintf(fq," if(ans >= 64'h7FF8000000000000 && ans <= 64'h7FFfffffffffffff ) $fwrite(fp, \"ans=qutNaN \");\n");
fprintf(fq," if(ans >= 64'hFFF8000000000000 && ans <= 64'hFFFfffffffffffff ) $fwrite(fp, \"ans=qutNaN \");\n");
fprintf(fq," $fwrite(fp,\"%ld\\n\");\n",k);
//fprintf(fq," $stop;\n");
// fprintf(fq," end\n");
fprintf(fq," end\n");
cnt++;
//if(cnt > 100) break;
fflush(fq);
}
//if(cnt > 100) break;
fflush(fq);
} // if(!feof(fp))
if(k == stop && debug == 1) break;
} // for(k)
fprintf(fq, "\t$stop;\n\tend\nendmodule");
fclose(fq);
fclose(fp);
fprintf(stdout,"cnt = %d\n",cnt);
}

File diff suppressed because it is too large Load Diff

View File

@ -23,7 +23,14 @@ module tb;
wire inexact;
integer fp;
reg nan;
reg wnan;
reg xnan;
reg ynan;
reg znan;
reg ansnan;
reg [105:0] s; // partial product 2
reg [51:0] xnorm;
reg [51:0] ynorm;
localparam period = 20;
fmac UUT(.xrf(xrf), .y(y), .zrf(zrf), .rn(rn), .rz(rz), .rp(rp), .rm(rm),
@ -33,4 +40,4 @@ fmac UUT(.xrf(xrf), .y(y), .zrf(zrf), .rn(rn), .rz(rz), .rp(rp), .rm(rm),
initial
begin
fp = $fopen("/home/kparry/code/FMAC/tbgen/results.dat","w");
fp = $fopen("/home/kparry/riscv-wally/wally-pipelined/src/fpu/FMA/tbgen/results.dat","w");

View File

@ -27,12 +27,12 @@
module hazard(
// Detect hazards
input logic PCSrcE, CSRWritePendingDEM, RetM, TrapM,
input logic BPPredWrongE, CSRWritePendingDEM, RetM, TrapM,
input logic LoadStallD, MulDivStallD, CSRRdStallD,
input logic InstrStall, DataStall, ICacheStallF,
// Stall & flush outputs
output logic StallF, StallD, StallE, StallM, StallW,
output logic FlushD, FlushE, FlushM, FlushW
output logic FlushF, FlushD, FlushE, FlushM, FlushW
);
logic BranchFlushDE;
@ -51,7 +51,7 @@ module hazard(
// A stage must stall if the next stage is stalled
// If any stages are stalled, the first stage that isn't stalled must flush.
assign BranchFlushDE = PCSrcE | RetM | TrapM;
assign BranchFlushDE = BPPredWrongE | RetM | TrapM;
assign StallFCause = CSRWritePendingDEM & ~(BranchFlushDE);
assign StallDCause = (LoadStallD | MulDivStallD | CSRRdStallD) & ~(BranchFlushDE); // stall in decode if instruction is a load/mul/csr dependent on previous
@ -62,6 +62,7 @@ module hazard(
// Each stage stalls if the next stage is stalled or there is a cause to stall this stage.
assign StallF = StallD | StallFCause;
assign StallD = StallE | StallDCause;
assign StallE = StallM | StallECause;
assign StallM = StallW | StallMCause;
@ -73,6 +74,7 @@ module hazard(
assign FirstUnstalledW = (~StallW & StallM);;
// Each stage flushes if the previous stage is the last one stalled (for cause) or the system has reason to flush
assign FlushF = BPPredWrongE;
assign FlushD = FirstUnstalledD || BranchFlushDE; // PCSrcE |InstrStall | CSRWritePendingDEM | RetM | TrapM;
assign FlushE = FirstUnstalledE || BranchFlushDE; //LoadStallD | PCSrcE | RetM | TrapM;
assign FlushM = FirstUnstalledM || RetM || TrapM;

View File

@ -43,6 +43,7 @@ module controller(
output logic MemReadE, CSRReadE, // for Hazard Unit
output logic [2:0] Funct3E,
output logic MulDivE, W64E,
output logic JumpE,
// Memory stage control signals
input logic StallM, FlushM,
output logic [1:0] MemRWM,
@ -68,7 +69,7 @@ module controller(
logic RegWriteD, RegWriteE;
logic [2:0] ResultSrcD, ResultSrcE, ResultSrcM;
logic [1:0] MemRWD, MemRWE;
logic JumpD, JumpE;
logic JumpD;
logic BranchD, BranchE;
logic [1:0] ALUOpD;
logic [4:0] ALUControlD;
@ -115,7 +116,7 @@ module controller(
if (InstrD[31:27] == 5'b00010)
ControlsD = 22'b1_000_00_10_001_0_00_0_0_0_0_0_0_1_0; // lr
else if (InstrD[31:27] == 5'b00011)
ControlsD = 22'b1_101_01_01_110_0_00_0_0_0_0_0_0_1_0; // sc
ControlsD = 22'b1_101_01_01_101_0_00_0_0_0_0_0_0_1_0; // sc
else
ControlsD = 22'b0_000_00_00_000_0_00_0_0_0_0_0_0_1_0; // other atomic; decode later
end else

View File

@ -36,7 +36,9 @@ module datapath (
input logic [4:0] ALUControlE,
input logic ALUSrcAE, ALUSrcBE,
input logic TargetSrcE,
input logic JumpE,
input logic [`XLEN-1:0] PCE,
input logic [`XLEN-1:0] PCLinkE,
output logic [2:0] FlagsE,
output logic [`XLEN-1:0] PCTargetE,
output logic [`XLEN-1:0] SrcAE, SrcBE,
@ -64,7 +66,9 @@ module datapath (
// Execute stage signals
logic [`XLEN-1:0] RD1E, RD2E;
logic [`XLEN-1:0] ExtImmE;
logic [`XLEN-1:0] PreSrcAE;
logic [`XLEN-1:0] PreSrcAE, SrcAE2, SrcBE2;
logic [`XLEN-1:0] ALUResultE;
logic [`XLEN-1:0] WriteDataE;
logic [`XLEN-1:0] TargetBaseE;
@ -93,8 +97,10 @@ module datapath (
mux3 #(`XLEN) faemux(RD1E, ResultW, ALUResultM, ForwardAE, PreSrcAE);
mux3 #(`XLEN) fbemux(RD2E, ResultW, ALUResultM, ForwardBE, WriteDataE);
mux2 #(`XLEN) srcamux(PreSrcAE, PCE, ALUSrcAE, SrcAE);
mux2 #(`XLEN) srcamux2(SrcAE, PCLinkE, JumpE, SrcAE2);
mux2 #(`XLEN) srcbmux(WriteDataE, ExtImmE, ALUSrcBE, SrcBE);
alu #(`XLEN) alu(SrcAE, SrcBE, ALUControlE, ALUResultE, FlagsE);
mux2 #(`XLEN) srcbmux2(SrcBE, {`XLEN{1'b0}}, JumpE, SrcBE2); // *** May be able to remove this mux.
alu #(`XLEN) alu(SrcAE2, SrcBE2, ALUControlE, ALUResultE, FlagsE);
mux2 #(`XLEN) targetsrcmux(PCE, SrcAE, TargetSrcE, TargetBaseE);
assign PCTargetE = ExtImmE + TargetBaseE;
@ -109,6 +115,9 @@ module datapath (
flopenrc #(`XLEN) ALUResultWReg(clk, reset, FlushW, ~StallW, ALUResultM, ALUResultW);
flopenrc #(5) RdWEg(clk, reset, FlushW, ~StallW, RdM, RdW);
// *** something is not right here. Before the merge I found an issue with the jal instruction not writing
// the link address through the alu.
// not sure what changed.
// handle Store Conditional result if atomic extension supported
generate
if (`A_SUPPORTED)
@ -118,4 +127,11 @@ module datapath (
endgenerate
mux6 #(`XLEN) resultmux(ALUResultW, ReadDataW, PCLinkW, CSRReadValW, MulDivResultW, SCResultW, ResultSrcW, ResultW);
/* -----\/----- EXCLUDED -----\/-----
// This mux4:1 no longer needs to include PCLinkW. This is set correctly in the execution stage.
// *** need to look at how the decoder is coded to fix.
mux4 #(`XLEN) resultmux(ALUResultW, ReadDataW, PCLinkW, CSRReadValW, ResultSrcW, ResultW);
>>>>>>> bp
-----/\----- EXCLUDED -----/\----- */
endmodule

View File

@ -33,6 +33,7 @@ module ieu (
output logic IllegalBaseInstrFaultD,
// Execute Stage interface
input logic [`XLEN-1:0] PCE,
input logic [`XLEN-1:0] PCLinkE,
output logic [`XLEN-1:0] PCTargetE,
output logic MulDivE, W64E,
output logic [2:0] Funct3E,
@ -72,6 +73,7 @@ module ieu (
logic [1:0] ForwardAE, ForwardBE;
logic RegWriteM, RegWriteW;
logic MemReadE, CSRReadE;
logic JumpE;
controller c(.*);
datapath dp(.*);

View File

@ -0,0 +1,97 @@
///////////////////////////////////////////
// SRAM2P1R1W
//
// Written: Ross Thomposn
// Email: ross1728@gmail.com
// Created: February 15, 2021
// Modified:
//
// Purpose: BTB model. Outputs type of instruction (currently 1 hot encoded. Probably want
// to encode to reduce storage), valid, target PC.
//
// A component of the Wally configurable RISC-V project.
//
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
// is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
///////////////////////////////////////////
`include "wally-config.vh"
module BTBPredictor
#(parameter int Depth = 10
)
(input logic clk,
input logic reset,
input logic [`XLEN-1:0] LookUpPC,
output logic [`XLEN-1:0] TargetPC,
output logic [3:0] InstrClass,
output logic Valid,
// update
input logic UpdateEN,
input logic [`XLEN-1:0] UpdatePC,
input logic [`XLEN-1:0] UpdateTarget,
input logic [3:0] UpdateInstrClass
);
localparam TotalDepth = 2 ** Depth;
logic [TotalDepth-1:0] ValidBits;
logic [Depth-1:0] LookUpPCIndex, UpdatePCIndex, LookUpPCIndexQ, UpdatePCIndexQ;
// hashing function for indexing the PC
// We have Depth bits to index, but XLEN bits as the input.
// bit 0 is always 0, bit 1 is 0 if using 4 byte instructions, but is not always 0 if
// using compressed instructions. XOR bit 1 with the MSB of index.
assign UpdatePCIndex = {UpdatePC[Depth+1] ^ UpdatePC[1], UpdatePC[Depth:2]};
assign LookUpPCIndex = {LookUpPC[Depth+1] ^ LookUpPC[1], LookUpPC[Depth:2]};
flopenr #(Depth) UpdatePCIndexReg(.clk(clk),
.reset(reset),
.en(1'b1),
.d(UpdatePCIndex),
.q(UpdatePCIndexQ));
// The valid bit must be resetable.
always_ff @ (posedge clk) begin
if (reset) begin
ValidBits <= #1 {TotalDepth{1'b0}};
end else if (UpdateEN) begin
ValidBits[UpdatePCIndexQ] <= #1 1'b1;
end
end
flopenr #(Depth) LookupPCIndexReg(.clk(clk),
.reset(reset),
.en(1'b1),
.d(LookUpPCIndex),
.q(LookUpPCIndexQ));
assign Valid = ValidBits[LookUpPCIndexQ];
// the BTB contains the target address.
// Another optimization may be using a PC relative address.
// *** need to add forwarding.
SRAM2P1R1W #(Depth, `XLEN+4) memory(.clk(clk),
.reset(reset),
.RA1(LookUpPCIndex),
.RD1({{InstrClass, TargetPC}}),
.REN1(1'b1),
.WA1(UpdatePCIndex),
.WD1({UpdateInstrClass, UpdateTarget}),
.WEN1(UpdateEN),
.BitWEN1({4'b0000, {`XLEN{1'b1}}})); // *** definitely not right.
endmodule

View File

@ -0,0 +1,80 @@
///////////////////////////////////////////
// RASPredictor.sv
//
// Written: Ross Thomposn
// Email: ross1728@gmail.com
// Created: February 15, 2021
// Modified:
//
// Purpose: 2 bit saturating counter predictor with parameterized table depth.
//
// A component of the Wally configurable RISC-V project.
//
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
// is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
///////////////////////////////////////////
`include "wally-config.vh"
module RASPredictor
#(parameter int StackSize = 16
)
(input logic clk,
input logic reset,
input logic pop,
output logic [`XLEN-1:0] popPC,
input logic push,
input logic incr,
input logic [`XLEN-1:0] pushPC
);
logic CounterEn;
localparam Depth = $clog2(StackSize);
logic [StackSize-1:0] PtrD, PtrQ, PtrP1, PtrM1;
logic [StackSize-1:0] [`XLEN-1:0] memory;
integer index;
assign CounterEn = pop | push | incr;
assign PtrD = pop ? PtrM1 : PtrP1;
assign PtrM1 = PtrQ - 1'b1;
assign PtrP1 = PtrQ + 1'b1;
// may have to handle a push and an incr at the same time.
// *** what happens if jal is executing and there is a return being flushed in Decode?
flopenr #(StackSize) PTR(.clk(clk),
.reset(reset),
.en(CounterEn),
.d(PtrD),
.q(PtrQ));
// RAS must be reset.
always_ff @ (posedge clk, posedge reset) begin
if(reset) begin
for(index=0; index<StackSize; index++)
memory[index] <= {`XLEN{1'b0}};
end else if(push) begin
memory[PtrP1] <= #1 pushPC;
end
end
assign popPC = memory[PtrQ];
endmodule

View File

@ -0,0 +1,111 @@
///////////////////////////////////////////
// SRAM2P1R1W
//
// Written: Ross Thomposn
// Email: ross1728@gmail.com
// Created: February 14, 2021
// Modified:
//
// Purpose: Behavioral model of two port SRAM. While this is synthesizable it will produce a flip flop based memory whi
// behaves with the timing of an SRAM typical of GF 14nm, 32nm, and 45nm.
//
//
// to preload this memory we can use the following command
// in modelsim's do file.
// mem load -infile <relative path to the text file > -format <bin|hex> <hierarchy to the memory.>
// example
// mem laod -infile twoBitPredictor.txt -format bin testbench/dut/hart/ifu/bpred/DirPredictor/memory/memory
//
// A component of the Wally configurable RISC-V project.
//
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
// is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
///////////////////////////////////////////
`include "wally-config.vh"
module SRAM2P1R1W
#(parameter int Depth = 10,
parameter int Width = 2
)
(input logic clk,
// *** have to remove reset eventually
input logic reset,
// port 1 is read only
input logic [Depth-1:0] RA1,
output logic [Width-1:0] RD1,
input logic REN1,
// port 2 is write only
input logic [Depth-1:0] WA1,
input logic [Width-1:0] WD1,
input logic WEN1,
input logic [Width-1:0] BitWEN1
);
logic [Depth-1:0] RA1Q, WA1Q;
logic WEN1Q;
logic [Width-1:0] WD1Q;
logic [Width-1:0] memory [2**Depth-1:0];
// SRAMs address busses are always registered first.
flopenr #(Depth) RA1Reg(.clk(clk),
.reset(reset),
.en(REN1),
.d(RA1),
.q(RA1Q));
flopenr #(Depth) WA1Reg(.clk(clk),
.reset(reset),
.en(REN1),
.d(WA1),
.q(WA1Q));
flopenr #(1) WEN1Reg(.clk(clk),
.reset(reset),
.en(1'b1),
.d(WEN1),
.q(WEN1Q));
flopenr #(Width) WD1Reg(.clk(clk),
.reset(reset),
.en(REN1),
.d(WD1),
.q(WD1Q));
// read port
assign RD1 = memory[RA1Q];
genvar index;
// write port
generate
for (index = 0; index < Width; index = index + 1) begin
always_ff @ (posedge clk) begin
if (WEN1Q & BitWEN1[index]) begin
memory[WA1Q][index] <= WD1Q[index];
end
end
end
endgenerate
endmodule

View File

@ -0,0 +1,169 @@
///////////////////////////////////////////
// bpred.sv
//
// Written: Ross Thomposn
// Email: ross1728@gmail.com
// Created: February 12, 2021
// Modified:
//
// Purpose: Branch prediction unit
// Produces a branch prediction based on branch history.
//
// A component of the Wally configurable RISC-V project.
//
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
// is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
///////////////////////////////////////////
`include "wally-config.vh"
module bpred
(input logic clk, reset,
input logic StallF, StallD, StallE, FlushF, FlushD, FlushE,
// Fetch stage
// the prediction
input logic [`XLEN-1:0] PCNextF, // *** forgot to include this one on the I/O list
output logic [`XLEN-1:0] BPPredPCF,
output logic SelBPPredF,
// Update Predictor
input logic [`XLEN-1:0] PCE, // The address of the currently executing instruction
// 1 hot encoding
// return, jump register, jump, branch
// *** after reviewing the compressed instruction set I am leaning towards having the btb predict the instruction class.
// *** the specifics of how this is encode is subject to change.
input logic PCSrcE, // AKA Branch Taken
// Signals required to check the branch prediction accuracy.
input logic [`XLEN-1:0] PCTargetE, // The branch destination if the branch is taken.
input logic [`XLEN-1:0] PCD, // The address the branch predictor took.
input logic [`XLEN-1:0] PCLinkE, // The address following the branch instruction. (AKA Fall through address)
input logic [3:0] InstrClassE,
// Report branch prediction status
output logic BPPredWrongE
);
logic BTBValidF;
logic [1:0] BPPredF, BPPredD, BPPredE, UpdateBPPredE;
logic [3:0] BPInstrClassF, BPInstrClassD, BPInstrClassE;
logic [`XLEN-1:0] BTBPredPCF, RASPCF;
logic TargetWrongE;
logic FallThroughWrongE;
logic PredictionDirWrongE;
logic PredictionPCWrongE;
logic [`XLEN-1:0] CorrectPCE;
// Part 1 branch direction prediction
twoBitPredictor DirPredictor(.clk(clk),
.reset(reset),
.LookUpPC(PCNextF),
.Prediction(BPPredF),
// update
.UpdatePC(PCE),
.UpdateEN(InstrClassE[0]),
.UpdatePrediction(UpdateBPPredE));
// this predictor will have two pieces of data,
// 1) A direction (1 = Taken, 0 = Not Taken)
// 2) Any information which is necessary for the predictor to built it's next state.
// For a 2 bit table this is the prediction count.
assign SelBPPredF = ((BPInstrClassF[0] & BPPredF[1] & BTBValidF) |
BPInstrClassF[3] |
(BPInstrClassF[2] & BTBValidF) |
BPInstrClassF[1] & BTBValidF) ;
// Part 2 Branch target address prediction
// *** For now the BTB will house the direct and indirect targets
BTBPredictor TargetPredictor(.clk(clk),
.reset(reset),
.LookUpPC(PCNextF),
.TargetPC(BTBPredPCF),
.InstrClass(BPInstrClassF),
.Valid(BTBValidF),
// update
.UpdateEN(InstrClassE[2] | InstrClassE[1] | InstrClassE[0]),
.UpdatePC(PCE),
.UpdateTarget(PCTargetE),
.UpdateInstrClass(InstrClassE));
// need to forward when updating to the same address as reading.
//assign CorrectPCE = PCSrcE ? PCTargetE : PCLinkE;
//assign TargetPC = (PCE == PCNextF) ? CorrectPCE : BTBPredPCF;
// Part 3 RAS
// *** need to add the logic to restore RAS on flushes. We will use incr for this.
RASPredictor RASPredictor(.clk(clk),
.reset(reset),
.pop(BPInstrClassF[3]),
.popPC(RASPCF),
.push(InstrClassE[3]),
.incr(1'b0),
.pushPC(PCLinkE));
assign BPPredPCF = BPInstrClassF[3] ? RASPCF : BTBPredPCF;
// The prediction and its results need to be passed through the pipeline
// *** for other predictors will will be different.
flopenrc #(2) BPPredRegD(.clk(clk),
.reset(reset),
.en(~StallF),
.clear(FlushF),
.d(BPPredF),
.q(BPPredD));
flopenrc #(2) BPPredRegE(.clk(clk),
.reset(reset),
.en(~StallD),
.clear(FlushD),
.d(BPPredD),
.q(BPPredE));
// pipeline the class
flopenrc #(4) InstrClassRegD(.clk(clk),
.reset(reset),
.en(~StallF),
.clear(FlushF),
.d(BPInstrClassF),
.q(BPInstrClassD));
flopenrc #(4) InstrClassRegE(.clk(clk),
.reset(reset),
.en(~StallD),
.clear(FlushD),
.d(BPInstrClassD),
.q(BPInstrClassE));
// Check the prediction makes execution.
assign TargetWrongE = PCTargetE != PCD;
assign FallThroughWrongE = PCLinkE != PCD;
assign PredictionDirWrongE = (BPPredE[1] ^ PCSrcE) & InstrClassE[0];
assign PredictionPCWrongE = PCSrcE ? TargetWrongE : FallThroughWrongE;
assign BPPredWrongE = (PredictionPCWrongE | PredictionDirWrongE) & (|InstrClassE);
// Update predictors
satCounter2 BPDirUpdate(.BrDir(PCSrcE),
.OldState(BPPredE),
.NewState(UpdateBPPredE));
endmodule

View File

@ -29,7 +29,7 @@
module ifu (
input logic clk, reset,
input logic StallF, StallD, StallE, StallM, StallW,
input logic FlushD, FlushE, FlushM, FlushW,
input logic FlushF, FlushD, FlushE, FlushM, FlushW,
// Fetch
input logic [`XLEN-1:0] InstrInF,
output logic [`XLEN-1:0] PCF,
@ -38,13 +38,15 @@ module ifu (
output logic ICacheStallF,
// Decode
// Execute
input logic PCSrcE,
input logic [`XLEN-1:0] PCTargetE,
output logic [`XLEN-1:0] PCE,
output logic [`XLEN-1:0] PCLinkE,
input logic PCSrcE,
input logic [`XLEN-1:0] PCTargetE,
output logic [`XLEN-1:0] PCE,
output logic BPPredWrongE,
// Mem
input logic RetM, TrapM,
input logic [`XLEN-1:0] PrivilegedNextPCM,
output logic [31:0] InstrD, InstrM,
input logic RetM, TrapM,
input logic [`XLEN-1:0] PrivilegedNextPCM,
output logic [31:0] InstrD, InstrM,
output logic [`XLEN-1:0] PCM,
// Writeback
output logic [`XLEN-1:0] PCLinkW,
@ -65,7 +67,7 @@ module ifu (
logic misaligned, BranchMisalignedFaultE, BranchMisalignedFaultM, TrapMisalignedFaultM;
logic PrivilegedChangePCM;
logic IllegalCompInstrD;
logic [`XLEN-1:0] PCPlusUpperF, PCPlus2or4F, PCD, PCW, PCLinkD, PCLinkE, PCLinkM, PCPF;
logic [`XLEN-1:0] PCPlusUpperF, PCPlus2or4F, PCD, PCW, PCLinkD, PCLinkM, PCPF;
logic CompressedF;
logic [31:0] InstrRawD, InstrE, InstrW;
logic [31:0] nop = 32'h00000013; // instruction for NOP
@ -81,6 +83,12 @@ module ifu (
tlb #(3) itlb(clk, reset, SATP, PCF, PageTableEntryF, ITLBWriteF, ITLBFlushF,
ITLBInstrPAdrF, ITLBMissF, ITLBHitF);
// branch predictor signals
logic SelBPPredF;
logic [`XLEN-1:0] BPPredPCF, PCCorrectE, PCNext0F, PCNext1F;
logic [3:0] InstrClassD, InstrClassE;
// *** put memory interface on here, InstrF becomes output
//assign InstrPAdrF = PCF; // *** no MMU
//assign InstrReadF = ~StallD; // *** & ICacheMissF; add later
@ -94,10 +102,48 @@ module ifu (
assign PrivilegedChangePCM = RetM | TrapM;
mux3 #(`XLEN) pcmux(PCPlus2or4F, PCTargetE, PrivilegedNextPCM, {PrivilegedChangePCM, PCSrcE}, UnalignedPCNextF);
//mux3 #(`XLEN) pcmux(PCPlus2or4F, PCCorrectE, PrivilegedNextPCM, {PrivilegedChangePCM, BPPredWrongE}, UnalignedPCNextF);
mux2 #(`XLEN) pcmux0(.d0(PCPlus2or4F),
.d1(BPPredPCF),
.s(SelBPPredF),
.y(PCNext0F));
mux2 #(`XLEN) pcmux1(.d0(PCNext0F),
.d1(PCCorrectE),
.s(BPPredWrongE),
.y(PCNext1F));
mux2 #(`XLEN) pcmux2(.d0(PCNext1F),
.d1(PrivilegedNextPCM),
.s(PrivilegedChangePCM),
.y(UnalignedPCNextF));
assign PCNextF = {UnalignedPCNextF[`XLEN-1:1], 1'b0}; // hart-SPEC p. 21 about 16-bit alignment
flopenl #(`XLEN) pcreg(clk, reset, ~StallF & ~ICacheStallF, PCNextF, `RESET_VECTOR, PCF);
// branch and jump predictor
// I am making the port connection explicit for now as I want to see them and they will be changing.
bpred bpred(.clk(clk),
.reset(reset),
.StallF(StallF),
.StallD(StallD),
.StallE(1'b0), // *** may need this eventually
.FlushF(FlushF),
.FlushD(FlushD),
.FlushE(FlushE),
.PCNextF(PCNextF),
.BPPredPCF(BPPredPCF),
.SelBPPredF(SelBPPredF),
.PCE(PCE),
.PCSrcE(PCSrcE),
.PCTargetE(PCTargetE),
.PCD(PCD),
.PCLinkE(PCLinkE),
.InstrClassE(InstrClassE),
.BPPredWrongE(BPPredWrongE));
// The true correct target is PCTargetE if PCSrcE is 1 else it is the fall through PCLinkE.
assign PCCorrectE = PCSrcE ? PCTargetE : PCLinkE;
// pcadder
// add 2 or 4 to the PC, based on whether the instruction is 16 bits or 32
assign PCPlusUpperF = PCF[`XLEN-1:2] + 1; // add 4 to PC
@ -116,6 +162,14 @@ module ifu (
assign IllegalIEUInstrFaultD = IllegalBaseInstrFaultD | IllegalCompInstrD; // illegal if bad 32 or 16-bit instr
// *** combine these with others in better way, including M, F
// the branch predictor needs a compact decoding of the instruction class.
// *** consider adding in the alternate return address x5 for returns.
assign InstrClassD[3] = InstrD[6:0] == 7'h67 && InstrD[19:15] == 5'h01; // return
assign InstrClassD[2] = InstrD[6:0] == 7'h67 && InstrD[19:15] != 5'h01; // jump register, but not return
assign InstrClassD[1] = InstrD[6:0] == 7'h6F; // jump
assign InstrClassD[0] = InstrD[6:0] == 7'h63; // branch
// Misaligned PC logic
generate
@ -139,6 +193,13 @@ module ifu (
flopenr #(`XLEN) PCMReg(clk, reset, ~StallM, PCE, PCM);
flopenr #(`XLEN) PCWReg(clk, reset, ~StallW, PCM, PCW); // *** probably not needed; delete later
flopenrc #(4) InstrClassRegE(.clk(clk),
.reset(reset),
.en(~StallD),
.clear(FlushD),
.d(InstrClassD),
.q(InstrClassE));
// seems like there should be a lower-cost way of doing this PC+2 or PC+4 for JAL.
// either have ALU compute PC+2/4 and feed into ALUResult input of ResultMux or
// have dedicated adder in Mem stage based on PCM + 2 or 4

View File

@ -0,0 +1,57 @@
///////////////////////////////////////////
// satCounter2.sv
//
// Written: Ross Thomposn
// Email: ross1728@gmail.com
// Created: February 13, 2021
// Modified:
//
// Purpose: 2 bit starting counter
//
// A component of the Wally configurable RISC-V project.
//
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
// is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
///////////////////////////////////////////
`include "wally-config.vh"
module satCounter2
(input logic BrDir,
input logic [1:0] OldState,
output logic [1:0] NewState
);
always_comb begin
case(OldState)
2'b00: begin
if(BrDir) NewState = 2'b01;
else NewState = 2'b00;
end
2'b01: begin
if(BrDir) NewState = 2'b10;
else NewState = 2'b00;
end
2'b10: begin
if(BrDir) NewState = 2'b11;
else NewState = 2'b01;
end
2'b11: begin
if(BrDir) NewState = 2'b11;
else NewState = 2'b10;
end
endcase
end
endmodule

View File

@ -0,0 +1,84 @@
///////////////////////////////////////////
// twoBitPredictor.sv
//
// Written: Ross Thomposn
// Email: ross1728@gmail.com
// Created: February 14, 2021
// Modified:
//
// Purpose: 2 bit saturating counter predictor with parameterized table depth.
//
// A component of the Wally configurable RISC-V project.
//
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
// is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
///////////////////////////////////////////
`include "wally-config.vh"
module twoBitPredictor
#(parameter int Depth = 10
)
(input logic clk,
input logic reset,
input logic [`XLEN-1:0] LookUpPC,
output logic [1:0] Prediction,
// update
input logic [`XLEN-1:0] UpdatePC,
input logic UpdateEN,
input logic [1:0] UpdatePrediction
);
logic [Depth-1:0] LookUpPCIndex, UpdatePCIndex;
logic [1:0] PredictionMemory;
logic DoForwarding, DoForwardingF;
logic [1:0] UpdatePredictionF;
// hashing function for indexing the PC
// We have Depth bits to index, but XLEN bits as the input.
// bit 0 is always 0, bit 1 is 0 if using 4 byte instructions, but is not always 0 if
// using compressed instructions. XOR bit 1 with the MSB of index.
assign UpdatePCIndex = {UpdatePC[Depth+1] ^ UpdatePC[1], UpdatePC[Depth:2]};
assign LookUpPCIndex = {LookUpPC[Depth+1] ^ LookUpPC[1], LookUpPC[Depth:2]};
SRAM2P1R1W #(Depth, 2) memory(.clk(clk),
.reset(reset),
.RA1(LookUpPCIndex),
.RD1(PredictionMemory),
.REN1(1'b1),
.WA1(UpdatePCIndex),
.WD1(UpdatePrediction),
.WEN1(UpdateEN),
.BitWEN1(2'b11));
// need to forward when updating to the same address as reading.
// first we compare to see if the update and lookup addreses are the same
assign DoForwarding = UpdatePCIndex == LookUpPCIndex;
// register the update value and the forwarding signal into the Fetch stage
flopr #(1) DoForwardingReg(.clk(clk),
.reset(reset),
.d(DoForwarding),
.q(DoForwardingF));
flopr #(2) UpdatePredictionReg(.clk(clk),
.reset(reset),
.d(UpdatePrediction),
.q(UpdatePredictionF));
assign Prediction = DoForwardingF ? UpdatePredictionF : PredictionMemory;
endmodule

View File

@ -108,7 +108,7 @@ module csrm #(parameter
assign WriteMCOUNTINHIBITM = CSRMWriteM && (CSRAdrM == MCOUNTINHIBIT);
// CSRs
flopenl #(`XLEN) MTVECreg(clk, reset, WriteMTVECM, CSRWriteValM, `RESET_VECTOR, MTVEC_REGW);
flopenl #(`XLEN) MTVECreg(clk, reset, WriteMTVECM, CSRWriteValM, `XLEN'b0, MTVEC_REGW); //busybear: changed reset value to 0
generate
if (`S_SUPPORTED | (`U_SUPPORTED & `N_SUPPORTED)) begin // DELEG registers should exist
flopenl #(`XLEN) MEDELEGreg(clk, reset, WriteMEDELEGM, CSRWriteValM & MEDELEG_MASK, zero, MEDELEG_REGW);
@ -125,7 +125,11 @@ module csrm #(parameter
flopenr #(`XLEN) MEPCreg(clk, reset, WriteMEPCM, NextEPCM, MEPC_REGW);
flopenr #(`XLEN) MCAUSEreg(clk, reset, WriteMCAUSEM, NextCauseM, MCAUSE_REGW);
flopenr #(`XLEN) MTVALreg(clk, reset, WriteMTVALM, NextMtvalM, MTVAL_REGW);
`ifndef BUSYBEAR
flopenl #(32) MCOUNTERENreg(clk, reset, WriteMCOUNTERENM, CSRWriteValM[31:0], allones, MCOUNTEREN_REGW);
`else
flopenl #(32) MCOUNTERENreg(clk, reset, WriteMCOUNTERENM, {CSRWriteValM[31:2],1'b0,CSRWriteValM[0]}, 32'b0, MCOUNTEREN_REGW);
`endif
flopenl #(32) MCOUNTINHIBITreg(clk, reset, WriteMCOUNTINHIBITM, CSRWriteValM[31:0], allones, MCOUNTINHIBIT_REGW);
flopenr #(`XLEN) PMPADDR0reg(clk, reset, WritePMPADDR0M, CSRWriteValM, PMPADDR0_REGW);
// PMPCFG registers are a pair of 64-bit in RV64 and four 32-bit in RV32

View File

@ -75,13 +75,17 @@ module csrs #(parameter
assign WriteSCOUNTERENM = CSRSWriteM && (CSRAdrM == SCOUNTEREN);
// CSRs
flopenl #(`XLEN) STVECreg(clk, reset, WriteSTVECM, CSRWriteValM, `RESET_VECTOR, STVEC_REGW);
flopenl #(`XLEN) STVECreg(clk, reset, WriteSTVECM, CSRWriteValM, zero, STVEC_REGW); //busybear: change reset to 0
flopenr #(`XLEN) SSCRATCHreg(clk, reset, WriteSSCRATCHM, CSRWriteValM, SSCRATCH_REGW);
flopenr #(`XLEN) SEPCreg(clk, reset, WriteSEPCM, NextEPCM, SEPC_REGW);
flopenl #(`XLEN) SCAUSEreg(clk, reset, WriteSCAUSEM, NextCauseM, zero, SCAUSE_REGW);
flopenr #(`XLEN) STVALreg(clk, reset, WriteSTVALM, NextMtvalM, STVAL_REGW);
flopenr #(`XLEN) SATPreg(clk, reset, WriteSATPM, CSRWriteValM, SATP_REGW);
`ifndef BUSYBEAR
flopenl #(32) SCOUNTERENreg(clk, reset, WriteSCOUNTERENM, CSRWriteValM[31:0], allones, SCOUNTEREN_REGW);
`else
flopenl #(32) SCOUNTERENreg(clk, reset, WriteSCOUNTERENM, {CSRWriteValM[31:2],1'b0,CSRWriteValM[0]}, 32'b0, SCOUNTEREN_REGW);
`endif
if (`N_SUPPORTED) begin
logic WriteSEDELEGM, WriteSIDELEGM;
assign WriteSEDELEGM = CSRSWriteM && (CSRAdrM == SEDELEG);

View File

@ -109,15 +109,15 @@ module csrsr (
if (reset) begin
STATUS_SUM_INT <= 0;
STATUS_MPRV_INT <= 0; // Per Priv 3.3
STATUS_FS_INT <= 2'b01; // initial
STATUS_MPP <= `M_MODE;
STATUS_SPP <= 1'b1;
STATUS_MPIE <= 1;
STATUS_SPIE <= `S_SUPPORTED;
STATUS_UPIE <= `U_SUPPORTED;
STATUS_FS_INT <= 0; //2'b01; // busybear: change all these reset values to 0
STATUS_MPP <= 0; //`M_MODE;
STATUS_SPP <= 0; //1'b1;
STATUS_MPIE <= 0; //1;
STATUS_SPIE <= 0; //`S_SUPPORTED;
STATUS_UPIE <= 0; // `U_SUPPORTED;
STATUS_MIE <= 0; // Per Priv 3.3
STATUS_SIE <= `S_SUPPORTED;
STATUS_UIE <= `U_SUPPORTED;
STATUS_SIE <= 0; //`S_SUPPORTED;
STATUS_UIE <= 0; //`U_SUPPORTED;
end else if (~StallW) begin
if (WriteMSTATUSM) begin
STATUS_SUM_INT <= CSRWriteValM[18];
@ -179,4 +179,4 @@ module csrsr (
// *** add code to track STATUS_FS_INT for dirty floating point registers
end
end
endmodule
endmodule

View File

@ -28,8 +28,9 @@
module clint (
input logic HCLK, HRESETn,
input logic [1:0] MemRWclint,
input logic [15:0] HADDR,
input logic HSELCLINT,
input logic [15:0] HADDR,
input logic HWRITE,
input logic [`XLEN-1:0] HWDATA,
output logic [`XLEN-1:0] HREADCLINT,
output logic HRESPCLINT, HREADYCLINT,
@ -41,8 +42,8 @@ module clint (
logic [15:0] entry;
logic memread, memwrite;
assign memread = MemRWclint[1];
assign memwrite = MemRWclint[0];
assign memread = HSELCLINT & ~HWRITE;
assign memwrite = HSELCLINT & HWRITE;
assign HRESPCLINT = 0; // OK
// assign HREADYCLINT = 1; // Respond immediately
always_ff @(posedge HCLK) // delay response

View File

@ -25,24 +25,30 @@
`include "wally-config.vh"
module dtim (
module dtim #(parameter BASE=0, RANGE = 65535) (
input logic HCLK, HRESETn,
input logic [1:0] MemRWtim,
input logic [18:0] HADDR,
input logic [`XLEN-1:0] HWDATA,
input logic HSELTim,
input logic [31:0] HADDR,
input logic HWRITE,
input logic [`XLEN-1:0] HWDATA,
output logic [`XLEN-1:0] HREADTim,
output logic HRESPTim, HREADYTim
);
logic [`XLEN-1:0] RAM[0:65535];
logic [18:0] HWADDR;
logic [`XLEN-1:0] RAM[BASE>>(1+`XLEN/32):(RANGE+BASE)>>1+(`XLEN/32)];
logic [31:0] HWADDR, A;
logic [`XLEN-1:0] HREADTim0;
// logic [`XLEN-1:0] write;
logic [15:0] entry;
logic memread, memwrite;
logic [3:0] busycount;
logic memread, memwrite;
logic [3:0] busycount;
always_ff @(posedge HCLK) begin
memread <= HSELTim & ~ HWRITE;
memwrite <= HSELTim & HWRITE;
A <= HADDR;
end
// busy FSM to extend READY signal
always_ff @(posedge HCLK, negedge HRESETn)
@ -61,42 +67,21 @@ module dtim (
end
end
/* always_ff @(posedge HCLK, negedge HRESETn)
if (~HRESETn) begin
HREADYTim <= 0;
end else begin
HREADYTim <= HSELTim; // always respond one cycle later
end */
assign memread = MemRWtim[1];
assign memwrite = MemRWtim[0];
// always_ff @(posedge HCLK)
// memwrite <= MemRWtim[0]; // delay memwrite to write phase
assign HRESPTim = 0; // OK
// assign HREADYTim = 1; // Respond immediately; *** extend this
// Model memory read and write
generate
if (`XLEN == 64) begin
// always_ff @(negedge HCLK)
// if (memwrite) RAM[HWADDR[17:3]] <= HWDATA;
always_ff @(posedge HCLK) begin
//if (memwrite) RAM[HADDR[17:3]] <= HWDATA;
HWADDR <= HADDR;
HREADTim0 <= RAM[HADDR[17:3]];
if (memwrite && HREADYTim) RAM[HWADDR[17:3]] <= HWDATA;
HWADDR <= A;
HREADTim0 <= RAM[A[31:3]];
if (memwrite && HREADYTim) RAM[HWADDR[31:3]] <= HWDATA;
end
end else begin
// always_ff @(negedge HCLK)
// if (memwrite) RAM[HWADDR[17:2]] <= HWDATA;
always_ff @(posedge HCLK) begin
//if (memwrite) RAM[HADDR[17:2]] <= HWDATA;
HWADDR <= HADDR;
HREADTim0 <= RAM[HADDR[17:2]];
if (memwrite && HREADYTim) RAM[HWADDR[17:2]] <= HWDATA;
HWADDR <= A;
HREADTim0 <= RAM[A[31:2]];
if (memwrite && HREADYTim) RAM[HWADDR[31:2]] <= HWDATA;
end
end
endgenerate

View File

@ -29,9 +29,10 @@
module gpio (
input logic HCLK, HRESETn,
input logic [1:0] MemRWgpio,
input logic HSELGPIO,
input logic [7:0] HADDR,
input logic [`XLEN-1:0] HWDATA,
input logic HWRITE,
output logic [`XLEN-1:0] HREADGPIO,
output logic HRESPGPIO, HREADYGPIO,
input logic [31:0] GPIOPinsIn,
@ -42,8 +43,8 @@ module gpio (
logic [7:0] entry;
logic memread, memwrite;
assign memread = MemRWgpio[1];
assign memwrite = MemRWgpio[0];
assign memread = HSELGPIO & ~HWRITE;
assign memwrite = HSELGPIO & HWRITE;
assign HRESPGPIO = 0; // OK
always_ff @(posedge HCLK) // delay response to data cycle
HREADYGPIO <= memread | memwrite;

View File

@ -32,24 +32,35 @@ module imem (
output logic InstrAccessFaultF);
/* verilator lint_off UNDRIVEN */
logic [`XLEN-1:0] RAM[0:65535];
logic [`XLEN-1:0] RAM[`TIMBASE>>(1+`XLEN/32):(`TIMRANGE+`TIMBASE)>>(1+`XLEN/32)];
`ifdef BOOTTIMBASE
logic [`XLEN-1:0] bootram[`BOOTTIMBASE>>(1+`XLEN/32):(`BOOTTIMRANGE+`BOOTTIMBASE)>>(1+`XLEN/32)];
`endif
/* verilator lint_on UNDRIVEN */
logic [15:0] adrbits;
logic [28:0] adrbits;
logic [`XLEN-1:0] rd;
// logic [15:0] rd2;
generate
if (`XLEN==32) assign adrbits = AdrF[17:2];
else assign adrbits = AdrF[18:3];
if (`XLEN==32) assign adrbits = AdrF[30:2];
else assign adrbits = AdrF[31:3];
endgenerate
`ifndef BOOTTIMBASE
assign #2 rd = RAM[adrbits]; // word aligned
`else
assign #2 rd = (AdrF < (`TIMBASE >> 1)) ? bootram[adrbits] : RAM[adrbits]; // busybear: 2 memory options
`endif
// hack right now for unaligned 32-bit instructions
// eventually this will need to cause a stall like a cache miss
// when the instruction wraps around a cache line
// could be optimized to only stall when the instruction wrapping is 32 bits
`ifndef BOOTTIMBASE
assign #2 rd2 = RAM[adrbits+1][15:0];
`else
assign #2 rd2 = (AdrF < (`TIMBASE >> 1)) ? bootram[adrbits+1][15:0] : RAM[adrbits+1][15:0]; //busybear: 2 memory options
`endif
generate
if (`XLEN==32) begin
assign InstrF = AdrF[1] ? {rd2[15:0], rd[31:16]} : rd;
@ -57,7 +68,11 @@ module imem (
end else begin
assign InstrF = AdrF[2] ? (AdrF[1] ? {rd2[15:0], rd[63:48]} : rd[63:32])
: (AdrF[1] ? rd[47:16] : rd[31:0]);
`ifndef BOOTTIMBASE
assign InstrAccessFaultF = |AdrF[`XLEN-1:32] | ~&({AdrF[31:1],1'b0} ~^ `TIMBASE | `TIMRANGE);
`else
assign InstrAccessFaultF = 0; //busybear: for now, i know we're not doing this
`endif
end
endgenerate
endmodule

View File

@ -29,8 +29,9 @@
module uart (
input logic HCLK, HRESETn,
input logic [1:0] MemRWuart,
input logic [2:0] HADDR,
input logic HSELUART,
input logic [2:0] HADDR,
input logic HWRITE,
input logic [`XLEN-1:0] HWDATA,
output logic [`XLEN-1:0] HREADUART,
output logic HRESPUART, HREADYUART,
@ -44,37 +45,37 @@ module uart (
logic [7:0] Din, Dout;
// rename processor interface signals to match PC16550D and provide one-byte interface
assign MEMRb = ~MemRWuart[1];
assign MEMWb = ~MemRWuart[0];
assign A = HADDR[2:0];
always_ff @(posedge HCLK) begin
MEMRb <= ~(HSELUART & ~HWRITE);
MEMWb <= ~(HSELUART & HWRITE);
A <= HADDR[2:0];
end
assign HRESPUART = 0; // OK
//assign HREADYUART = 1; // Respond immediately
always_ff @(posedge HCLK) // delay response to data cycle
HREADYUART <= ~MEMRb | ~MEMWb;
assign HREADYUART = 1; // should idle high during address phase and respond high when done; will need to be modified if UART ever needs more than 1 cycle to do something
generate
if (`XLEN == 64) begin
always @(posedge HCLK) begin
always_comb begin
HREADUART = {Dout, Dout, Dout, Dout, Dout, Dout, Dout, Dout};
case (HADDR)
3'b000: Din <= HWDATA[7:0];
3'b001: Din <= HWDATA[15:8];
3'b010: Din <= HWDATA[23:16];
3'b011: Din <= HWDATA[31:24];
3'b100: Din <= HWDATA[39:32];
3'b101: Din <= HWDATA[47:40];
3'b110: Din <= HWDATA[55:48];
3'b111: Din <= HWDATA[63:56];
case (A)
3'b000: Din = HWDATA[7:0];
3'b001: Din = HWDATA[15:8];
3'b010: Din = HWDATA[23:16];
3'b011: Din = HWDATA[31:24];
3'b100: Din = HWDATA[39:32];
3'b101: Din = HWDATA[47:40];
3'b110: Din = HWDATA[55:48];
3'b111: Din = HWDATA[63:56];
endcase
end
end else begin // 32-bit
always @(posedge HCLK) begin
always_comb begin
HREADUART = {Dout, Dout, Dout, Dout};
case (HADDR[1:0])
2'b00: Din <= HWDATA[7:0];
2'b01: Din <= HWDATA[15:8];
2'b10: Din <= HWDATA[23:16];
2'b11: Din <= HWDATA[31:24];
case (A[1:0])
2'b00: Din = HWDATA[7:0];
2'b01: Din = HWDATA[15:8];
2'b10: Din = HWDATA[23:16];
2'b11: Din = HWDATA[31:24];
endcase
end
end

View File

@ -376,7 +376,7 @@ module uartPC16550D(
TXHR <= Din;
txhrfull <= 1;
end
$display("UART transmits: %c",Din); // for testbench
$write("%c",Din); // for testbench
end
if (txstate == UART_IDLE) begin // move data into tx shift register if available
if (fifoenabled) begin

View File

@ -2,7 +2,7 @@
// uncore.sv
//
// Written: David_Harris@hmc.edu 9 January 2021
// Modified:
// Modified: Ben Bracker 6 Mar 2021 to better fit AMBA 3 AHB-Lite spec
//
// Purpose: System-on-Chip components outside the core (hart)
// Memories, peripherals, external bus control
@ -59,58 +59,96 @@ module uncore (
logic [`XLEN-1:0] HWDATA;
logic [`XLEN-1:0] HREADTim, HREADCLINT, HREADGPIO, HREADUART;
logic HSELTim, HSELCLINT, HSELGPIO, PreHSELUART, HSELUART;
logic HSELTimD, HSELCLINTD, HSELGPIOD, HSELUARTD;
logic HRESPTim, HRESPCLINT, HRESPGPIO, HRESPUART;
logic HREADYTim, HREADYCLINT, HREADYGPIO, HREADYUART;
logic [1:0] MemRW;
logic [1:0] MemRWtim, MemRWclint, MemRWgpio, MemRWuart;
`ifdef BOOTTIMBASE
logic [`XLEN-1:0] HREADBootTim;
logic HSELBootTim, HSELBootTimD, HRESPBootTim, HREADYBootTim;
logic [1:0] MemRWboottim;
`endif
logic UARTIntr;// *** will need to tie INTR to an interrupt handler
// AHB Address decoder
adrdec timdec(HADDR, `TIMBASE, `TIMRANGE, HSELTim);
`ifdef BOOTTIMBASE
adrdec boottimdec(HADDR, `BOOTTIMBASE, `BOOTTIMRANGE, HSELBootTim);
`endif
adrdec clintdec(HADDR, `CLINTBASE, `CLINTRANGE, HSELCLINT);
adrdec gpiodec(HADDR, `GPIOBASE, `GPIORANGE, HSELGPIO);
`ifdef GPIOBASE
adrdec gpiodec(HADDR, `GPIOBASE, `GPIORANGE, HSELGPIO);
`endif
adrdec uartdec(HADDR, `UARTBASE, `UARTRANGE, PreHSELUART);
assign HSELUART = PreHSELUART && (HSIZE == 3'b000); // only byte writes to UART are supported
// Enable read or write based on decoded address
assign MemRW = {~HWRITE, HWRITED};
assign MemRWtim = MemRW & {2{HSELTim}};
assign MemRWclint = MemRW & {2{HSELCLINT}};
assign MemRWgpio = MemRW & {2{HSELGPIO}};
assign MemRWuart = MemRW & {2{HSELUART}};
/* always_ff @(posedge HCLK) begin
HADDRD <= HADDR;
MemRWtim <= MemRW & {2{HSELTim}};
MemRWclint <= MemRW & {2{HSELCLINT}};
MemRWgpio <= MemRW & {2{HSELGPIO}};
MemRWuart <= MemRW & {2{HSELUART}};
end */
// subword accesses: converts HWDATAIN to HWDATA
subwordwrite sww(.*);
// tightly integrated memory
dtim dtim(.HADDR(HADDR[18:0]), .*);
dtim #(.BASE(`TIMBASE), .RANGE(`TIMRANGE)) dtim (.*);
`ifdef BOOTTIMBASE
dtim #(.BASE(`BOOTTIMBASE), .RANGE(`BOOTTIMRANGE)) bootdtim(.HSELTim(HSELBootTim), .HREADTim(HREADBootTim), .HRESPTim(HRESPBootTim), .HREADYTim(HREADYBootTim), .*);
`endif
// memory-mapped I/O peripherals
clint clint(.HADDR(HADDR[15:0]), .*);
`ifdef GPIOBASE
gpio gpio(.HADDR(HADDR[7:0]), .*); // *** may want to add GPIO interrupts
`endif
uart uart(.HADDR(HADDR[2:0]), .TXRDYb(), .RXRDYb(), .INTR(UARTIntr), .SIN(UARTSin), .SOUT(UARTSout),
.DSRb(1'b1), .DCDb(1'b1), .CTSb(1'b0), .RIb(1'b1),
.RTSb(), .DTRb(), .OUT1b(), .OUT2b(), .*);
.RTSb(), .DTRb(), .OUT1b(), .OUT2b(), .*);
// mux could also include external memory
// AHB Read Multiplexer
assign HRDATA = ({`XLEN{HSELTim}} & HREADTim) | ({`XLEN{HSELCLINT}} & HREADCLINT) |
({`XLEN{HSELGPIO}} & HREADGPIO) | ({`XLEN{HSELUART}} & HREADUART);
assign HRESP = HSELTim & HRESPTim | HSELCLINT & HRESPCLINT | HSELGPIO & HRESPGPIO | HSELUART & HRESPUART;
assign HREADY = HSELTim & HREADYTim | HSELCLINT & HREADYCLINT | HSELGPIO & HREADYGPIO | HSELUART & HREADYUART;
assign HRDATA = ({`XLEN{HSELTimD}} & HREADTim) | ({`XLEN{HSELCLINTD}} & HREADCLINT) |
`ifdef GPIOBASE
({`XLEN{HSELGPIOD}} & HREADGPIO) |
`endif
`ifdef BOOTTIMBASE
({`XLEN{HSELBootTimD}} & HREADBootTim) |
`endif
({`XLEN{HSELUARTD}} & HREADUART);
assign HRESP = HSELTimD & HRESPTim | HSELCLINTD & HRESPCLINT |
`ifdef GPIOBASE
HSELGPIOD & HRESPGPIO |
`endif
`ifdef BOOTTIMBASE
HSELBootTimD & HRESPBootTim |
`endif
HSELUARTD & HRESPUART;
assign HREADY = HSELTimD & HREADYTim | HSELCLINTD & HREADYCLINT |
`ifdef GPIOBASE
HSELGPIOD & HREADYGPIO |
`endif
`ifdef BOOTTIMBASE
HSELBootTimD & HREADYBootTim |
`endif
HSELUARTD & HREADYUART;
// Faults
assign DataAccessFaultM = ~(HSELTim | HSELCLINT | HSELGPIO | HSELUART);
assign DataAccessFaultM = ~(HSELTimD | HSELCLINTD |
`ifdef GPIOBASE
HSELGPIOD |
`endif
`ifdef BOOTTIMBASE
HSELBootTimD |
`endif
HSELUARTD);
// Address Decoder Delay (figure 4-2 in spec)
flopr #(1) hseltimreg(HCLK, ~HRESETn, HSELTim, HSELTimD);
flopr #(1) hselclintreg(HCLK, ~HRESETn, HSELCLINT, HSELCLINTD);
`ifdef GPIOBASE
flopr #(1) hselgpioreg(HCLK, ~HRESETn, HSELGPIO, HSELGPIOD);
`endif
flopr #(1) hseluartreg(HCLK, ~HRESETn, HSELUART, HSELUARTD);
`ifdef BOOTTIMBASE
flopr #(1) hselboottimreg(HCLK, ~HRESETn, HSELBootTim, HSELBootTimD);
`endif
endmodule

View File

@ -55,7 +55,7 @@ module wallypipelinedhart (
// logic [1:0] ForwardAE, ForwardBE;
logic StallF, StallD, StallE, StallM, StallW;
logic FlushD, FlushE, FlushM, FlushW;
logic FlushF, FlushD, FlushE, FlushM, FlushW;
logic RetM, TrapM;
// new signals that must connect through DP
@ -66,7 +66,7 @@ module wallypipelinedhart (
logic [2:0] Funct3E;
// logic [31:0] InstrF;
logic [31:0] InstrD, InstrM;
logic [`XLEN-1:0] PCE, PCM, PCLinkW;
logic [`XLEN-1:0] PCE, PCM, PCLinkE, PCLinkW;
logic [`XLEN-1:0] PCTargetE;
logic [`XLEN-1:0] CSRReadValW, MulDivResultW;
logic [`XLEN-1:0] PrivilegedNextPCM;
@ -104,13 +104,14 @@ module wallypipelinedhart (
logic InstrReadF;
logic DataStall, InstrStall;
logic InstrAckD, MemAckW;
logic BPPredWrongE;
ifu ifu(.InstrInF(InstrRData), .*); // instruction fetch unit: PC, branch prediction, instruction cache
ieu ieu(.*); // inteber execution unit: integer register file, datapath and controller
ieu ieu(.*); // integer execution unit: integer register file, datapath and controller
dmem dmem(.*); // data cache unit
ahblite ebu(
//.InstrReadF(1'b0),
//.InstrRData(InstrF), // hook up InstrF later

View File

@ -0,0 +1,108 @@
///////////////////////////////////////////
// datapath.sv
//
// Written: Ross Thompson
// email: ross1728@gmail.com
// Created: November 9, 2019
//
// Purpose: Finds the current function or global assembly label based on PCE.
//
// A component of the Wally configurable RISC-V project.
//
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
// is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
///////////////////////////////////////////
`include "wally-config.vh"
module function_radix();
parameter PRELOAD_FILE = "funct_addr.txt";
integer memory_bank [];
integer index;
logic [`XLEN-1:0] pc;
initial begin
$init_signal_spy("/riscv_mram_tb/dut/pc", "/riscv_mram_tb/function_radix/pc");
end
task automatic bin_search_min;
input integer pc;
input integer length;
ref integer array [];
output integer minval;
integer left, right;
integer mid;
begin
left = 0;
right = length;
while (left <= right) begin
mid = left + ((right - left) / 2);
if (array[mid] == pc) begin
minval = array[mid];
return;
end
if (array[mid] < pc) begin
left = mid + 1;
end else begin
right = mid -1;
end
end // while (left <= right)
// if the element pc is now found, right and left will be equal at this point.
// we need to check if pc is less than the array at left or greather.
// if it is less than pc, then we select left as the index.
// if it is greather we want 1 less than left.
if (array[left] < pc) begin
minval = array[left];
return;
end else begin
minval = array[left-1];
return;
end
end
endtask
// preload
initial $readmemh(PRELOAD_FILE, memory_bank);
// we need to count the number of lines in the file so we can set line_count.
integer fp;
integer line_count = 0;
logic [31:0] line;
initial begin
fp = $fopen(PRELOAD_FILE, "r");
// read line by line to count lines
if (fp) begin
while (! $feof(fp)) begin
$fscanf(fp, "%h\n", line);
line_count = line_count + 1;
end
end else begin
$display("Cannot open file %s for reading.", PRELOAD_FILE);
$stop;
end
end
always @(pc) begin
bin_search_min(pc, line_count, memory_bank, index);
end
endmodule // function_radix

View File

@ -7,14 +7,9 @@ module testbench_busybear();
logic [31:0] GPIOPinsOut, GPIOPinsEn;
// instantiate device to be tested
logic [`XLEN-1:0] PCF;
logic [31:0] InstrF;
logic InstrAccessFaultF, DataAccessFaultM;
logic TimerIntM = 0, SwIntM = 0; // from CLINT
logic ExtIntM = 0; // not yet connected
logic [31:0] CheckInstrF;
logic [`AHBW-1:0] HRDATA;
logic HREADY, HRESP;
logic [31:0] HADDR;
logic [`AHBW-1:0] HWDATA;
logic HWRITE;
@ -24,85 +19,124 @@ module testbench_busybear();
logic [1:0] HTRANS;
logic HMASTLOCK;
logic HCLK, HRESETn;
logic [`AHBW-1:0] HRDATAEXT;
logic HREADYEXT, HRESPEXT;
logic UARTSout;
assign GPIOPinsIn = 0;
assign UARTSin = 1;
assign HREADY = 1;
assign HRESP = 0;
assign HRDATA = 0;
// for now, seem to need these to be zero until we get a better idea
assign InstrAccessFaultF = 0;
assign DataAccessFaultM = 0;
// instantiate processor and memories
wallypipelinedhart dut(.*);
wallypipelinedsoc dut(.*);
// initialize test
initial
begin
reset <= 1; # 22; reset <= 0;
end
// read pc trace file
integer data_file_PC, scan_file_PC;
initial begin
data_file_PC = $fopen("../busybear-testgen/parsedPC.txt", "r");
data_file_PC = $fopen("/courses/e190ax/busybear_boot/parsedPC.txt", "r");
if (data_file_PC == 0) begin
$display("file couldn't be opened");
$stop;
end
end
end
integer data_file_PCW, scan_file_PCW;
initial begin
data_file_PCW = $fopen("../busybear-testgen/parsedPC.txt", "r");
data_file_PCW = $fopen("/courses/e190ax/busybear_boot/parsedPC.txt", "r");
if (data_file_PCW == 0) begin
$display("file couldn't be opened");
$stop;
end
end
end
// read register trace file
integer data_file_rf, scan_file_rf;
initial begin
data_file_rf = $fopen("../busybear-testgen/parsedRegs.txt", "r");
data_file_rf = $fopen("/courses/e190ax/busybear_boot/parsedRegs.txt", "r");
if (data_file_rf == 0) begin
$display("file couldn't be opened");
$stop;
end
end
end
// read CSR trace file
integer data_file_csr, scan_file_csr;
initial begin
data_file_csr = $fopen("../busybear-testgen/parsedCSRs.txt", "r");
data_file_csr = $fopen("/courses/e190ax/busybear_boot/parsedCSRs.txt", "r");
if (data_file_csr == 0) begin
$display("file couldn't be opened");
$stop;
end
end
end
// read memreads trace file
integer data_file_memR, scan_file_memR;
initial begin
data_file_memR = $fopen("../busybear-testgen/parsedMemRead.txt", "r");
data_file_memR = $fopen("/courses/e190ax/busybear_boot/parsedMemRead.txt", "r");
if (data_file_memR == 0) begin
$display("file couldn't be opened");
$stop;
end
end
end
// read memwrite trace file
integer data_file_memW, scan_file_memW;
initial begin
data_file_memW = $fopen("../busybear-testgen/parsedMemWrite.txt", "r");
data_file_memW = $fopen("/courses/e190ax/busybear_boot/parsedMemWrite.txt", "r");
if (data_file_memW == 0) begin
$display("file couldn't be opened");
$stop;
end
end
end
// initial loading of memories
initial begin
$readmemh("/courses/e190ax/busybear_boot/bootmem.txt", dut.uncore.bootdtim.RAM, 'h1000 >> 3);
$readmemh("/courses/e190ax/busybear_boot/ram.txt", dut.uncore.dtim.RAM);
$readmemh("/courses/e190ax/busybear_boot/bootmem.txt", dut.imem.bootram, 'h1000 >> 3);
$readmemh("/courses/e190ax/busybear_boot/ram.txt", dut.imem.RAM);
end
integer warningCount = 0;
//logic[63:0] adrTranslation[4:0];
//string translationType[4:0] = {"rf", "writeAdr", "PCW", "PC", "readAdr"};
//initial begin
// for(int i=0; i<5; i++) begin
// adrTranslation[i] = 64'b0;
// end
//end
//function logic equal(logic[63:0] adr, logic[63:0] adrExpected, integer func);
// if (adr[11:0] !== adrExpected[11:0]) begin
// equal = 1'b0;
// end else begin
// equal = 1'b1;
// if ((adr+adrTranslation[func]) !== adrExpected) begin
// adrTranslation[func] = adrExpected - adr;
// $display("warning: probably new address translation %x for %s at instr %0d", adrTranslation[func], translationType[func], instrs);
// warningCount += 1;
// end
// end
//endfunction
// pretty sure this isn't necessary anymore, but keeping this for now since its easier
function logic equal(logic[63:0] adr, logic[63:0] adrExpected, integer func);
equal = adr === adrExpected;
endfunction
`define ERROR \
#10; \
$display("processed %0d instructions with %0d warnings", instrs, warningCount); \
$stop;
logic [63:0] pcExpected;
logic [63:0] regExpected;
integer regNumExpected;
@ -110,115 +144,195 @@ module testbench_busybear();
genvar i;
generate
for(i=1; i<32; i++) begin
always @(dut.ieu.dp.regf.rf[i]) begin
if ($time != 0) begin
always @(dut.hart.ieu.dp.regf.rf[i]) begin
if ($time == 0) begin
scan_file_rf = $fscanf(data_file_rf, "%x\n", regExpected);
if (dut.hart.ieu.dp.regf.rf[i] != regExpected) begin
$display("%0t ps, instr %0d: rf[%0d] does not equal rf expected: %x, %x", $time, instrs, i, dut.hart.ieu.dp.regf.rf[i], regExpected);
`ERROR
end
end else begin
scan_file_rf = $fscanf(data_file_rf, "%d\n", regNumExpected);
scan_file_rf = $fscanf(data_file_rf, "%x\n", regExpected);
if (i != regNumExpected) begin
$display("%t ps, instr %0d: wrong register changed: %0d, %0d expected", $time, instrs, i, regNumExpected);
$display("%0t ps, instr %0d: wrong register changed: %0d, %0d expected", $time, instrs, i, regNumExpected);
`ERROR
end
if (dut.ieu.dp.regf.rf[i] != regExpected) begin
$display("%t ps, instr %0d: rf[%0d] does not equal rf expected: %x, %x", $time, instrs, i, dut.ieu.dp.regf.rf[i], regExpected);
if (~equal(dut.hart.ieu.dp.regf.rf[i],regExpected, 0)) begin
$display("%0t ps, instr %0d: rf[%0d] does not equal rf expected: %x, %x", $time, instrs, i, dut.hart.ieu.dp.regf.rf[i], regExpected);
`ERROR
end
//if (dut.hart.ieu.dp.regf.rf[i] !== regExpected) begin
// force dut.hart.ieu.dp.regf.rf[i] = regExpected;
// release dut.hart.ieu.dp.regf.rf[i];
//end
end
end
end
endgenerate
// RAM and bootram are addressed in 64-bit blocks - this logic handles R/W
// including subwords. Brief explanation on signals:
//
// readMask: bitmask of bits to read / write, left-shifted to align with
// nearest 64-bit boundary - examples
// HSIZE = 0 -> readMask = 11111111
// HSIZE = 1 -> readMask = 1111111111111111
//
// In the linux boot, the processor spends the first ~5 instructions in
// bootram, before jr jumps to main RAM
logic [63:0] readMask;
assign readMask = ((1 << (8*(1 << HSIZE))) - 1) << 8 * HADDR[2:0];
logic [`XLEN-1:0] readAdrExpected;
// this might need to change
always @(dut.MemRWM[1] or HADDR) begin
if (dut.MemRWM[1]) begin
always @(dut.hart.MemRWM[1] or HADDR or dut.HRDATA) begin
if (dut.hart.MemRWM[1] && HADDR != dut.PCF && dut.HRDATA != {64{1'bx}}) begin
if($feof(data_file_memR)) begin
$display("no more memR data to read");
$stop;
`ERROR
end
scan_file_memR = $fscanf(data_file_memR, "%x\n", readAdrExpected);
scan_file_memR = $fscanf(data_file_memR, "%x\n", HRDATA);
#1;
if (HADDR != readAdrExpected) begin
$display("%t ps, instr %0d: HADDR does not equal readAdrExpected: %x, %x", $time, instrs, HADDR, readAdrExpected);
#2;
if (~equal(HADDR,readAdrExpected,4)) begin
$display("%0t ps, instr %0d: HADDR does not equal readAdrExpected: %x, %x", $time, instrs, HADDR, readAdrExpected);
`ERROR
end
if (((readMask & HRDATA) !== (readMask & dut.HRDATA)) && (HADDR >= 'h80000000 && HADDR <= 'h87FFFFFF)) begin
$display("warning %0t ps, instr %0d: ExpectedHRDATA does not equal dut.HRDATA: %x, %x from address %x, %x", $time, instrs, HRDATA, dut.HRDATA, HADDR, HSIZE);
warningCount += 1;
`ERROR
end
end
end
logic [`XLEN-1:0] writeDataExpected, writeAdrExpected;
// this might need to change
always @(HWDATA or HADDR or HSIZE) begin
#1;
if (HWRITE) begin
//always @(HWDATA or HADDR or HSIZE or HWRITE) begin
always @(negedge HWRITE) begin
//#1;
if ($time != 0) begin
if($feof(data_file_memW)) begin
$display("no more memW data to read");
$stop;
`ERROR
end
scan_file_memW = $fscanf(data_file_memW, "%x\n", writeDataExpected);
scan_file_memW = $fscanf(data_file_memW, "%x\n", writeAdrExpected);
if (writeDataExpected != HWDATA) begin
$display("%t ps, instr %0d: HWDATA does not equal writeDataExpected: %x, %x", $time, instrs, HWDATA, writeDataExpected);
$display("%0t ps, instr %0d: HWDATA does not equal writeDataExpected: %x, %x", $time, instrs, HWDATA, writeDataExpected);
`ERROR
end
if (writeAdrExpected != HADDR) begin
$display("%t ps, instr %0d: HADDR does not equal writeAdrExpected: %x, %x", $time, instrs, HADDR, writeAdrExpected);
if (~equal(writeAdrExpected,HADDR,1)) begin
$display("%0t ps, instr %0d: HADDR does not equal writeAdrExpected: %x, %x", $time, instrs, HADDR, writeAdrExpected);
`ERROR
end
end
end
`define CHECK_CSR(CSR) \
integer totalCSR = 0;
logic [99:0] StartCSRexpected[63:0];
string StartCSRname[99:0];
initial begin
while(1) begin
scan_file_csr = $fscanf(data_file_csr, "%s\n", StartCSRname[totalCSR]);
if(StartCSRname[totalCSR] == "---") begin
break;
end
scan_file_csr = $fscanf(data_file_csr, "%x\n", StartCSRexpected[totalCSR]);
totalCSR = totalCSR + 1;
end
end
`define CHECK_CSR2(CSR, PATH) \
string CSR; \
logic [63:0] expected``CSR``; \
//CSR checking \
always @(dut.priv.csr.``CSR``_REGW) begin \
always @(``PATH``.``CSR``_REGW) begin \
if ($time > 1) begin \
scan_file_csr = $fscanf(data_file_csr, "%s\n", CSR); \
scan_file_csr = $fscanf(data_file_csr, "%x\n", expected``CSR``); \
if(CSR.icompare(`"CSR`")) begin \
$display("%t ps, instr %0d: %s changed, expected %s", $time, instrs, `"CSR`", CSR); \
$display("%0t ps, instr %0d: %s changed, expected %s", $time, instrs, `"CSR`", CSR); \
end \
if(dut.priv.csr.``CSR``_REGW != ``expected``CSR) begin \
$display("%t ps, instr %0d: %s does not equal %s expected: %x, %x", $time, instrs, CSR, CSR, dut.priv.csr.``CSR``_REGW, ``expected``CSR); \
if(``PATH``.``CSR``_REGW != ``expected``CSR) begin \
$display("%0t ps, instr %0d: %s does not equal %s expected: %x, %x", $time, instrs, `"CSR`", CSR, ``PATH``.``CSR``_REGW, ``expected``CSR); \
`ERROR \
end \
end else begin \
for(integer j=0; j<totalCSR; j++) begin \
if(!StartCSRname[j].icompare(`"CSR`")) begin \
if(``PATH``.``CSR``_REGW != StartCSRexpected[j]) begin \
$display("%0t ps, instr %0d: %s does not equal %s expected: %x, %x", $time, instrs, `"CSR`", StartCSRname[j], ``PATH``.``CSR``_REGW, StartCSRexpected[j]); \
`ERROR \
end \
end \
end \
end \
end
`define CHECK_CSR(CSR) \
`CHECK_CSR2(CSR, dut.hart.priv.csr)
`define CSRM dut.hart.priv.csr.genblk1.csrm
`define CSRS dut.hart.priv.csr.genblk1.csrs.genblk1
//`CHECK_CSR(FCSR)
`CHECK_CSR2(MCAUSE, `CSRM)
`CHECK_CSR(MCOUNTEREN)
`CHECK_CSR(MEDELEG)
`CHECK_CSR(MEPC)
//`CHECK_CSR(MHARTID)
`CHECK_CSR(MIDELEG)
`CHECK_CSR(MIE)
//`CHECK_CSR(MSCRATCH)
//`CHECK_CSR(MIP)
`CHECK_CSR2(MISA, `CSRM)
`CHECK_CSR2(MSCRATCH, `CSRM)
`CHECK_CSR(MSTATUS)
`CHECK_CSR2(MTVAL, `CSRM)
`CHECK_CSR(MTVEC)
//`CHECK_CSR(SATP)
//`CHECK_CSR2(PMPADDR0, `CSRM)
//`CHECK_CSR2(PMdut.PCFG0, `CSRM)
`CHECK_CSR2(SATP, `CSRS)
`CHECK_CSR2(SCAUSE, `CSRS)
`CHECK_CSR(SCOUNTEREN)
`CHECK_CSR(SEPC)
`CHECK_CSR(SIE)
`CHECK_CSR2(SSCRATCH, `CSRS)
`CHECK_CSR(SSTATUS)
`CHECK_CSR2(STVAL, `CSRS)
`CHECK_CSR(STVEC)
logic speculative;
initial begin
speculative = 0;
speculative = 0;
end
logic [63:0] lastInstrF, lastPC, lastPC2;
logic [63:0] lastCheckInstrF, lastPC, lastPC2;
string PCtextW, PCtext2W;
logic [31:0] InstrWExpected;
logic [63:0] PCWExpected;
always @(dut.ifu.PCW or dut.ieu.InstrValidW) begin
if(dut.ieu.InstrValidW && dut.ifu.PCW != 0) begin
always @(dut.hart.ifu.PCW or dut.hart.ieu.InstrValidW) begin
if(dut.hart.ieu.InstrValidW && dut.hart.ifu.PCW != 0) begin
if($feof(data_file_PCW)) begin
$display("no more PC data to read");
$stop;
`ERROR
end
scan_file_PCW = $fscanf(data_file_PCW, "%s\n", PCtextW);
if (PCtextW != "ret") begin
if (PCtextW != "ret" && PCtextW != "fence" && PCtextW != "nop" && PCtextW != "mret" && PCtextW != "sfence.vma" && PCtextW != "unimp") begin
scan_file_PC = $fscanf(data_file_PCW, "%s\n", PCtext2W);
PCtextW = {PCtextW, " ", PCtext2W};
end
scan_file_PCW = $fscanf(data_file_PCW, "%x\n", InstrWExpected);
// then expected PC value
scan_file_PCW = $fscanf(data_file_PCW, "%x\n", PCWExpected);
if(dut.ifu.PCW != PCWExpected) begin
$display("%t ps, instr %0d: PCW does not equal PCW expected: %x, %x", $time, instrs, dut.ifu.PCW, PCWExpected);
if(~equal(dut.hart.ifu.PCW,PCWExpected,2)) begin
$display("%0t ps, instr %0d: PCW does not equal PCW expected: %x, %x", $time, instrs, dut.hart.ifu.PCW, PCWExpected);
`ERROR
end
//if(it.InstrW != InstrWExpected) begin
// $display("%t ps, instr %0d: InstrW does not equal InstrW expected: %x, %x", $time, instrs, it.InstrW, InstrWExpected);
// $display("%0t ps, instr %0d: InstrW does not equal InstrW expected: %x, %x", $time, instrs, it.InstrW, InstrWExpected);
//end
end
end
@ -227,72 +341,139 @@ module testbench_busybear();
integer instrs;
initial begin
instrs = 0;
end
always @(PCF) begin
lastInstrF = InstrF;
lastPC <= PCF;
lastPC2 <= lastPC;
if (speculative && lastPC != pcExpected) begin
speculative = (PCF != pcExpected);
end
else begin
//if (~speculative) begin
if($feof(data_file_PC)) begin
$display("no more PC data to read");
$stop;
end
// first read instruction
scan_file_PC = $fscanf(data_file_PC, "%s\n", PCtext);
if (PCtext != "ret") begin
scan_file_PC = $fscanf(data_file_PC, "%s\n", PCtext2);
PCtext = {PCtext, " ", PCtext2};
end
scan_file_PC = $fscanf(data_file_PC, "%x\n", InstrF);
if(InstrF[6:0] == 7'b1010011) begin // for now, NOP out any float instrs
InstrF = 32'b0010011;
$display("warning: NOPing out %s at PC=%0x", PCtext, PCF);
end
// then expected PC value
scan_file_PC = $fscanf(data_file_PC, "%x\n", pcExpected);
if (instrs <= 10 || (instrs <= 100 && instrs % 10 == 0) ||
(instrs <= 1000 && instrs % 100 == 0) || (instrs <= 10000 && instrs % 1000 == 0) ||
(instrs <= 100000 && instrs % 10000 == 0)) begin
$display("loaded %0d instructions", instrs);
end
instrs += 1;
// are we at a branch/jump?
casex (lastInstrF[15:0])
16'bXXXXXXXXX1101111, // JAL
16'bXXXXXXXXX1100111, // JALR
16'bXXXXXXXXX1100011, // B
16'b110XXXXXXXXXXX01, // C.BEQZ
16'b111XXXXXXXXXXX01, // C.BNEZ
16'b101XXXXXXXXXXX01: // C.J
speculative = 1;
16'b1001000000000010: // C.EBREAK:
speculative = 0; // tbh don't really know what should happen here
16'b1000XXXXX0000010, // C.JR
16'b1001XXXXX0000010: // C.JALR //this is RV64 only so no C.JAL
speculative = 1;
default:
speculative = 0;
endcase
end
logic [31:0] InstrMask;
logic forcedInstr;
logic [63:0] lastPCF;
always @(dut.PCF or dut.hart.ifu.InstrF or reset) begin
if(~HWRITE) begin
#3;
if (~reset && dut.hart.ifu.InstrF[15:0] !== {16{1'bx}} && ~dut.hart.StallD) begin
if (dut.PCF !== lastPCF) begin
lastCheckInstrF = CheckInstrF;
lastPC <= dut.PCF;
lastPC2 <= lastPC;
if (speculative && (lastPC != pcExpected)) begin
speculative = ~equal(dut.PCF,pcExpected,3);
if(dut.PCF===pcExpected) begin
if(dut.hart.ifu.InstrF[6:0] == 7'b1010011) begin // for now, NOP out any float instrs
force CheckInstrF = 32'b0010011;
release CheckInstrF;
force dut.hart.ifu.InstrF = 32'b0010011;
#7;
release dut.hart.ifu.InstrF;
$display("warning: NOPing out %s at PC=%0x, instr %0d, time %0t", PCtext, dut.PCF, instrs, $time);
warningCount += 1;
forcedInstr = 1;
end
else begin
if(dut.hart.ifu.InstrF[28:27] != 2'b11 && dut.hart.ifu.InstrF[6:0] == 7'b0101111) begin //for now, replace non-SC A instrs with LD
force CheckInstrF = {12'b0, CheckInstrF[19:7], 7'b0000011};
release CheckInstrF;
force dut.hart.ifu.InstrF = {12'b0, dut.hart.ifu.InstrF[19:7], 7'b0000011};
#7;
release dut.hart.ifu.InstrF;
$display("warning: replacing AMO instr %s at PC=%0x with ld", PCtext, dut.PCF);
warningCount += 1;
forcedInstr = 1;
end
else begin
forcedInstr = 0;
end
end
end
end
else begin
if($feof(data_file_PC)) begin
$display("no more PC data to read");
`ERROR
end
scan_file_PC = $fscanf(data_file_PC, "%s\n", PCtext);
if (PCtext != "ret" && PCtext != "fence" && PCtext != "nop" && PCtext != "mret" && PCtext != "sfence.vma" && PCtext != "unimp") begin
scan_file_PC = $fscanf(data_file_PC, "%s\n", PCtext2);
PCtext = {PCtext, " ", PCtext2};
end
scan_file_PC = $fscanf(data_file_PC, "%x\n", CheckInstrF);
if(dut.PCF === pcExpected) begin
if(dut.hart.ifu.InstrF[6:0] == 7'b1010011) begin // for now, NOP out any float instrs
force CheckInstrF = 32'b0010011;
release CheckInstrF;
force dut.hart.ifu.InstrF = 32'b0010011;
#7;
release dut.hart.ifu.InstrF;
$display("warning: NOPing out %s at PC=%0x, instr %0d, time %0t", PCtext, dut.PCF, instrs, $time);
warningCount += 1;
forcedInstr = 1;
end
else begin
if(dut.hart.ifu.InstrF[28:27] != 2'b11 && dut.hart.ifu.InstrF[6:0] == 7'b0101111) begin //for now, replace non-SC A instrs with LD
force CheckInstrF = {12'b0, CheckInstrF[19:7], 7'b0000011};
release CheckInstrF;
force dut.hart.ifu.InstrF = {12'b0, dut.hart.ifu.InstrF[19:7], 7'b0000011};
#7;
release dut.hart.ifu.InstrF;
$display("warning: replacing AMO instr %s at PC=%0x with ld", PCtext, dut.PCF);
warningCount += 1;
forcedInstr = 1;
end
else begin
forcedInstr = 0;
end
end
end
// then expected PC value
scan_file_PC = $fscanf(data_file_PC, "%x\n", pcExpected);
if (instrs <= 10 || (instrs <= 100 && instrs % 10 == 0) ||
(instrs <= 1000 && instrs % 100 == 0) || (instrs <= 10000 && instrs % 1000 == 0) ||
(instrs <= 100000 && instrs % 10000 == 0) || (instrs <= 1000000 && instrs % 100000 == 0)) begin
$display("loaded %0d instructions", instrs);
end
instrs += 1;
// are we at a branch/jump?
casex (lastCheckInstrF[31:0])
32'b00000000001000000000000001110011, // URET
32'b00010000001000000000000001110011, // SRET
32'b00110000001000000000000001110011, // MRET
32'bXXXXXXXXXXXXXXXXXXXXXXXXX1101111, // JAL
32'bXXXXXXXXXXXXXXXXXXXXXXXXX1100111, // JALR
32'bXXXXXXXXXXXXXXXXXXXXXXXXX1100011, // B
32'bXXXXXXXXXXXXXXXX110XXXXXXXXXXX01, // C.BEQZ
32'bXXXXXXXXXXXXXXXX111XXXXXXXXXXX01, // C.BNEZ
32'bXXXXXXXXXXXXXXXX101XXXXXXXXXXX01: // C.J
speculative = 1;
32'bXXXXXXXXXXXXXXXX1001000000000010: // C.EBREAK:
speculative = 0; // tbh don't really know what should happen here
32'bXXXXXXXXXXXXXXXX1000XXXXX0000010, // C.JR
32'bXXXXXXXXXXXXXXXX1001XXXXX0000010: // C.JALR //this is RV64 only so no C.JAL
speculative = 1;
default:
speculative = 0;
endcase
//check things!
if ((~speculative) && (PCF !== pcExpected)) begin
$display("%t ps, instr %0d: PC does not equal PC expected: %x, %x", $time, instrs, PCF, pcExpected);
// $stop;
//check things!
if ((~speculative) && (~equal(dut.PCF,pcExpected,3))) begin
$display("%0t ps, instr %0d: PC does not equal PC expected: %x, %x", $time, instrs, dut.PCF, pcExpected);
`ERROR
end
InstrMask = CheckInstrF[1:0] == 2'b11 ? 32'hFFFFFFFF : 32'h0000FFFF;
if ((~forcedInstr) && (~speculative) && ((InstrMask & dut.hart.ifu.InstrF) !== (InstrMask & CheckInstrF))) begin
$display("%0t ps, instr %0d: InstrF does not equal CheckInstrF: %x, %x, PC: %x", $time, instrs, dut.hart.ifu.InstrF, CheckInstrF, dut.PCF);
`ERROR
end
end
end
lastPCF = dut.PCF;
end
end
end
// Track names of instructions
string InstrFName, InstrDName, InstrEName, InstrMName, InstrWName;
logic [31:0] InstrW;
instrNameDecTB dec(InstrF, InstrFName);
instrTrackerTB it(clk, reset, dut.ieu.dp.FlushE,
dut.ifu.InstrD, dut.ifu.InstrE,
dut.ifu.InstrM, InstrW,
instrNameDecTB dec(dut.hart.ifu.InstrF, InstrFName);
instrTrackerTB it(clk, reset, dut.hart.ieu.dp.FlushE,
dut.hart.ifu.InstrD, dut.hart.ifu.InstrE,
dut.hart.ifu.InstrM, InstrW,
InstrDName, InstrEName, InstrMName, InstrWName);
// generate clock to sequence tests
@ -301,17 +482,4 @@ module testbench_busybear();
clk <= 1; # 5; clk <= 0; # 5;
end
//// check results
//always @(negedge clk)
// begin
// if(MemWrite) begin
// if(DataAdr === 84 & WriteData === 71) begin
// $display("Simulation succeeded");
// $stop;
// end else if (DataAdr !== 80) begin
// $display("Simulation failed");
// $stop;
// end
// end
// end
endmodule

View File

@ -37,6 +37,9 @@ module testbench();
string InstrFName, InstrDName, InstrEName, InstrMName, InstrWName;
//logic [31:0] InstrW;
logic [`XLEN-1:0] meminit;
string tests64a[] = '{
"rv64a/WALLY-LRSC", "2110"
};
string tests64m[] = '{
"rv64m/I-MUL-01", "3000",
"rv64m/I-MULH-01", "3000",
@ -321,9 +324,11 @@ string tests32i[] = {
initial
if (`XLEN == 64) begin // RV64
tests = {tests64i};
if (`C_SUPPORTED % 2 == 1) tests = {tests64ic, tests};
else tests = {tests, tests64iNOc};
if (`M_SUPPORTED % 2 == 1) tests = {tests, tests64m};
if (`C_SUPPORTED) tests = {tests64ic, tests};
else tests = {tests, tests64iNOc};
if (`M_SUPPORTED) tests = {tests, tests64m};
if (`A_SUPPORTED) tests = {tests64a, tests};
// tests = {tests64a, tests};
end else begin // RV32
tests = {tests32i};
if (`C_SUPPORTED % 2 == 1) tests = {tests, tests32ic};
@ -367,7 +372,8 @@ string tests32i[] = {
memfilename = {"../../imperas-riscv-tests/work/", tests[test], ".elf.memfile"};
$readmemh(memfilename, dut.imem.RAM);
$readmemh(memfilename, dut.uncore.dtim.RAM);
reset = 1; # 22; reset = 0;
$display("Read memfile %s", memfilename);
reset = 1; # 42; reset = 0;
end
// generate clock to sequence tests
@ -406,9 +412,9 @@ string tests32i[] = {
i = 0;
errors = 0;
if (`XLEN == 32)
testadr = tests[test+1].atohex()/4;
testadr = (`TIMBASE+tests[test+1].atohex())/4;
else
testadr = tests[test+1].atohex()/8;
testadr = (`TIMBASE+tests[test+1].atohex())/8;
/* verilator lint_off INFINITELOOP */
while (signature[i] !== 'bx) begin
//$display("signature[%h] = %h", i, signature[i]);
@ -443,7 +449,11 @@ string tests32i[] = {
reset = 1; # 17; reset = 0;
end
end
end
end // always @ (negedge clk)
// track the current function or label
//function_rfunction_radix function_radix();
endmodule
/* verilator lint_on STMTDLY */
@ -579,6 +589,30 @@ module instrNameDecTB(
10'b1110011_101: name = "CSRRWI";
10'b1110011_110: name = "CSRRSI";
10'b1110011_111: name = "CSRRCI";
10'b0101111_010: if (funct7[6:2] == 5'b00010) name = "LR.W";
else if (funct7[6:2] == 5'b00011) name = "SC.W";
else if (funct7[6:2] == 5'b00001) name = "AMOSWAP.W";
else if (funct7[6:2] == 5'b00000) name = "AMOADD.W";
else if (funct7[6:2] == 5'b00100) name = "AMOAXOR.W";
else if (funct7[6:2] == 5'b01100) name = "AMOAND.W";
else if (funct7[6:2] == 5'b01000) name = "AMOOR.W";
else if (funct7[6:2] == 5'b10000) name = "AMOMIN.W";
else if (funct7[6:2] == 5'b10100) name = "AMOMAX.W";
else if (funct7[6:2] == 5'b11000) name = "AMOMINU.W";
else if (funct7[6:2] == 5'b11100) name = "AMOMAXU.W";
else name = "ILLEGAL";
10'b0101111_011: if (funct7[6:2] == 5'b00010) name = "LR.D";
else if (funct7[6:2] == 5'b00011) name = "SC.D";
else if (funct7[6:2] == 5'b00001) name = "AMOSWAP.D";
else if (funct7[6:2] == 5'b00000) name = "AMOADD.D";
else if (funct7[6:2] == 5'b00100) name = "AMOAXOR.D";
else if (funct7[6:2] == 5'b01100) name = "AMOAND.D";
else if (funct7[6:2] == 5'b01000) name = "AMOOR.D";
else if (funct7[6:2] == 5'b10000) name = "AMOMIN.D";
else if (funct7[6:2] == 5'b10100) name = "AMOMAX.D";
else if (funct7[6:2] == 5'b11000) name = "AMOMINU.D";
else if (funct7[6:2] == 5'b11100) name = "AMOMAXU.D";
else name = "ILLEGAL";
10'b0001111_???: name = "FENCE";
default: name = "ILLEGAL";
endcase

View File

@ -136,9 +136,9 @@ module testbench();
i = 0;
errors = 0;
if (`XLEN == 32)
testadr = tests[test+1].atohex()/4;
testadr = (`TIMBASE+tests[test+1].atohex())/4;
else
testadr = tests[test+1].atohex()/8;
testadr = (`TIMBASE+tests[test+1].atohex())/8;
/* verilator lint_off INFINITELOOP */
while (signature[i] !== 'bx) begin
//$display("signature[%h] = %h", i, signature[i]);