This commit is contained in:
Ross Thompson 2021-03-05 15:27:22 -06:00
commit d6bc34121f
20 changed files with 615 additions and 387 deletions

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

View File

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

View File

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

View File

@ -27,12 +27,13 @@ vlib work-busybear
# "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
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/dut/hart/ifu/bpred/DirPredictor/memory/memory
@ -41,6 +42,15 @@ switch $argc {
1 {mem load -infile ../config/$1/BTBPredictor.txt -format bin testbench/dut/hart/ifu/bpred/TargetPredictor/memory/memory}
}
mem load -startaddress 0 -endaddress 2047 -filltype value -fillradix hex -filldata 0 /testbench_busybear/dut/uncore/bootdtim/RAM
mem load -startaddress 512 -i "/courses/e190ax/busybear_boot/bootmem.txt" -format hex /testbench_busybear/dut/uncore/bootdtim/RAM
mem load -startaddress 0 -endaddress 2047 -filltype value -fillradix hex -filldata 0 /testbench_busybear/dut/imem/bootram
mem load -startaddress 512 -i "/courses/e190ax/busybear_boot/bootmem.txt" -format hex /testbench_busybear/dut/imem/bootram
mem load -startaddress 268435456 -endaddress 285212671 -filltype value -fillradix hex -filldata 0 /testbench_busybear/dut/uncore/dtim/RAM
mem load -startaddress 268435456 -i "/courses/e190ax/busybear_boot/ram.txt" -format hex /testbench_busybear/dut/uncore/dtim/RAM
mem load -startaddress 268435456 -endaddress 285212671 -filltype value -fillradix hex -filldata 0 /testbench_busybear/dut/imem/RAM
mem load -startaddress 268435456 -i "/courses/e190ax/busybear_boot/ram.txt" -format hex /testbench_busybear/dut/imem/RAM
view wave
@ -51,80 +61,104 @@ 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/InstrF
add wave /testbench_busybear/CheckInstrF
add wave /testbench_busybear/lastCheckInstrF
add wave /testbench_busybear/speculative
add wave /testbench_busybear/lastPC2
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 -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/ifu/PCD
#add wave -hex /testbench_busybear/dut/ifu/InstrD
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/ifu/PCE
##add wave -hex /testbench_busybear/dut/ifu/InstrE
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/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 -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/ifu/PCM
##add wave -hex /testbench_busybear/dut/ifu/InstrM
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/dmem/dtim/memwrite
#add wave -hex /testbench_busybear/dut/dmem/AdrM
#add wave -hex /testbench_busybear/dut/dmem/WriteDataM
#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/ifu/PCW
##add wave -hex /testbench_busybear/dut/ifu/InstrW
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/ieu/dp/RegWriteW
#add wave -hex /testbench_busybear/dut/ieu/dp/ResultW
#add wave -hex /testbench_busybear/dut/ieu/dp/RdW
#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/*
add wave -hex -r /testbench_busybear/*
#
#-- Set Wave Output Items
#TreeUpdate [SetDefaultTree]
@ -140,6 +174,5 @@ add wave /testbench_busybear/InstrWName
#set DefaultRadix hexadecimal
#
#-- Run the Simulation
run 1483850
#run -all
run -all
##quit

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

@ -47,70 +47,4 @@ switch $argc {
}
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

@ -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,8 +26,13 @@ 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 +acc=+/testbench/dut/hart/ifu/bpred/DirPredictor/memory/memory +acc=+/testbench/dut/hart/ifu/bpred/TargetPredictor/memory/memory work.testbench -o workopt
@ -40,8 +44,6 @@ mem load -infile twoBitPredictor.txt -format bin testbench/dut/hart/ifu/bpred/Di
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

@ -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

@ -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,116 @@ 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
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 +136,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) begin
if (dut.hart.MemRWM[1] && HADDR != dut.PCF) 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: HRDATA 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 +333,102 @@ 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}}) begin
if (dut.PCF !== lastPCF) begin
lastCheckInstrF = CheckInstrF;
lastPC <= dut.PCF;
lastPC2 <= lastPC;
if (speculative && (lastPC != pcExpected)) begin
speculative = ~equal(dut.PCF,pcExpected,3);
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(CheckInstrF[6:0] == 7'b1010011) begin // for now, NOP out any float instrs
CheckInstrF = 32'b0010011;
$display("warning: NOPing out %s at PC=%0x", PCtext, dut.PCF);
warningCount += 1;
forcedInstr = 1;
end
else begin
if(CheckInstrF[28:27] != 2'b11 && CheckInstrF[6:0] == 7'b0101111) begin //for now, replace non-SC A instrs with LD
CheckInstrF = {12'b0, CheckInstrF[19:7], 7'b0000011};
$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
// 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 +437,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

@ -407,9 +407,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]);

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]);