Merge branch 'bp' into main

Concerns:
1. I don't think the correct data buses are going to the multiplier.
2. I'm not sure the FlushF signal is correct.
This commit is contained in:
Ross Thompson 2021-03-04 13:35:46 -06:00
commit 66e84f3a2c
21 changed files with 4699 additions and 21 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

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,52 @@
# 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
mem load -infile 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,11 @@ switch $argc {
vopt +acc work.testbench -o workopt vopt +acc work.testbench -o workopt
vsim 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
view wave view wave
-- display input and output signals as hexidecimal values -- display input and output signals as hexidecimal values

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

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

View File

@ -43,6 +43,7 @@ module controller(
output logic MemReadE, CSRReadE, // for Hazard Unit output logic MemReadE, CSRReadE, // for Hazard Unit
output logic [2:0] Funct3E, output logic [2:0] Funct3E,
output logic MulDivE, W64E, output logic MulDivE, W64E,
output logic JumpE,
// Memory stage control signals // Memory stage control signals
input logic StallM, FlushM, input logic StallM, FlushM,
output logic [1:0] MemRWM, output logic [1:0] MemRWM,
@ -68,7 +69,7 @@ module controller(
logic RegWriteD, RegWriteE; logic RegWriteD, RegWriteE;
logic [2:0] ResultSrcD, ResultSrcE, ResultSrcM; logic [2:0] ResultSrcD, ResultSrcE, ResultSrcM;
logic [1:0] MemRWD, MemRWE; logic [1:0] MemRWD, MemRWE;
logic JumpD, JumpE; logic JumpD;
logic BranchD, BranchE; logic BranchD, BranchE;
logic [1:0] ALUOpD; logic [1:0] ALUOpD;
logic [4:0] ALUControlD; logic [4:0] ALUControlD;

View File

@ -36,7 +36,9 @@ module datapath (
input logic [4:0] ALUControlE, input logic [4:0] ALUControlE,
input logic ALUSrcAE, ALUSrcBE, input logic ALUSrcAE, ALUSrcBE,
input logic TargetSrcE, input logic TargetSrcE,
input logic JumpE,
input logic [`XLEN-1:0] PCE, input logic [`XLEN-1:0] PCE,
input logic [`XLEN-1:0] PCLinkE,
output logic [2:0] FlagsE, output logic [2:0] FlagsE,
output logic [`XLEN-1:0] PCTargetE, output logic [`XLEN-1:0] PCTargetE,
output logic [`XLEN-1:0] SrcAE, SrcBE, output logic [`XLEN-1:0] SrcAE, SrcBE,
@ -64,7 +66,9 @@ module datapath (
// Execute stage signals // Execute stage signals
logic [`XLEN-1:0] RD1E, RD2E; logic [`XLEN-1:0] RD1E, RD2E;
logic [`XLEN-1:0] ExtImmE; 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] ALUResultE;
logic [`XLEN-1:0] WriteDataE; logic [`XLEN-1:0] WriteDataE;
logic [`XLEN-1:0] TargetBaseE; logic [`XLEN-1:0] TargetBaseE;
@ -93,8 +97,10 @@ module datapath (
mux3 #(`XLEN) faemux(RD1E, ResultW, ALUResultM, ForwardAE, PreSrcAE); mux3 #(`XLEN) faemux(RD1E, ResultW, ALUResultM, ForwardAE, PreSrcAE);
mux3 #(`XLEN) fbemux(RD2E, ResultW, ALUResultM, ForwardBE, WriteDataE); mux3 #(`XLEN) fbemux(RD2E, ResultW, ALUResultM, ForwardBE, WriteDataE);
mux2 #(`XLEN) srcamux(PreSrcAE, PCE, ALUSrcAE, SrcAE); mux2 #(`XLEN) srcamux(PreSrcAE, PCE, ALUSrcAE, SrcAE);
mux2 #(`XLEN) srcamux2(SrcAE, PCLinkE, JumpE, SrcAE2);
mux2 #(`XLEN) srcbmux(WriteDataE, ExtImmE, ALUSrcBE, SrcBE); 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); mux2 #(`XLEN) targetsrcmux(PCE, SrcAE, TargetSrcE, TargetBaseE);
assign PCTargetE = ExtImmE + TargetBaseE; assign PCTargetE = ExtImmE + TargetBaseE;
@ -109,6 +115,9 @@ module datapath (
flopenrc #(`XLEN) ALUResultWReg(clk, reset, FlushW, ~StallW, ALUResultM, ALUResultW); flopenrc #(`XLEN) ALUResultWReg(clk, reset, FlushW, ~StallW, ALUResultM, ALUResultW);
flopenrc #(5) RdWEg(clk, reset, FlushW, ~StallW, RdM, RdW); 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 // handle Store Conditional result if atomic extension supported
generate generate
if (`A_SUPPORTED) if (`A_SUPPORTED)
@ -118,4 +127,11 @@ module datapath (
endgenerate endgenerate
mux6 #(`XLEN) resultmux(ALUResultW, ReadDataW, PCLinkW, CSRReadValW, MulDivResultW, SCResultW, ResultSrcW, ResultW); 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 endmodule

View File

@ -33,6 +33,7 @@ module ieu (
output logic IllegalBaseInstrFaultD, output logic IllegalBaseInstrFaultD,
// Execute Stage interface // Execute Stage interface
input logic [`XLEN-1:0] PCE, input logic [`XLEN-1:0] PCE,
input logic [`XLEN-1:0] PCLinkE,
output logic [`XLEN-1:0] PCTargetE, output logic [`XLEN-1:0] PCTargetE,
output logic MulDivE, W64E, output logic MulDivE, W64E,
output logic [2:0] Funct3E, output logic [2:0] Funct3E,
@ -72,6 +73,7 @@ module ieu (
logic [1:0] ForwardAE, ForwardBE; logic [1:0] ForwardAE, ForwardBE;
logic RegWriteM, RegWriteW; logic RegWriteM, RegWriteW;
logic MemReadE, CSRReadE; logic MemReadE, CSRReadE;
logic JumpE;
controller c(.*); controller c(.*);
datapath dp(.*); 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({`XLEN{1'b1}}));
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 ( module ifu (
input logic clk, reset, input logic clk, reset,
input logic StallF, StallD, StallE, StallM, StallW, input logic StallF, StallD, StallE, StallM, StallW,
input logic FlushD, FlushE, FlushM, FlushW, input logic FlushF, FlushD, FlushE, FlushM, FlushW,
// Fetch // Fetch
input logic [`XLEN-1:0] InstrInF, input logic [`XLEN-1:0] InstrInF,
output logic [`XLEN-1:0] PCF, output logic [`XLEN-1:0] PCF,
@ -37,13 +37,15 @@ module ifu (
output logic InstrReadF, output logic InstrReadF,
// Decode // Decode
// Execute // Execute
input logic PCSrcE, output logic [`XLEN-1:0] PCLinkE,
input logic [`XLEN-1:0] PCTargetE, input logic PCSrcE,
output logic [`XLEN-1:0] PCE, input logic [`XLEN-1:0] PCTargetE,
output logic [`XLEN-1:0] PCE,
output logic BPPredWrongE,
// Mem // Mem
input logic RetM, TrapM, input logic RetM, TrapM,
input logic [`XLEN-1:0] PrivilegedNextPCM, input logic [`XLEN-1:0] PrivilegedNextPCM,
output logic [31:0] InstrD, InstrM, output logic [31:0] InstrD, InstrM,
output logic [`XLEN-1:0] PCM, output logic [`XLEN-1:0] PCM,
// Writeback // Writeback
output logic [`XLEN-1:0] PCLinkW, output logic [`XLEN-1:0] PCLinkW,
@ -60,13 +62,14 @@ module ifu (
output logic ITLBMissF, ITLBHitF, output logic ITLBMissF, ITLBHitF,
// bogus // bogus
input logic [15:0] rd2 input logic [15:0] rd2
); );
logic [`XLEN-1:0] UnalignedPCNextF, PCNextF; logic [`XLEN-1:0] UnalignedPCNextF, PCNextF;
logic misaligned, BranchMisalignedFaultE, BranchMisalignedFaultM, TrapMisalignedFaultM; logic misaligned, BranchMisalignedFaultE, BranchMisalignedFaultM, TrapMisalignedFaultM;
logic PrivilegedChangePCM; logic PrivilegedChangePCM;
logic IllegalCompInstrD; logic IllegalCompInstrD;
logic [`XLEN-1:0] PCPlusUpperF, PCPlus2or4F, PCD, PCW, PCLinkD, PCLinkE, PCLinkM; logic [`XLEN-1:0] PCPlusUpperF, PCPlus2or4F, PCD, PCW, PCLinkD, PCLinkM;
logic CompressedF; logic CompressedF;
logic [31:0] InstrF, InstrRawD, InstrE, InstrW; logic [31:0] InstrF, InstrRawD, InstrE, InstrW;
logic [31:0] nop = 32'h00000013; // instruction for NOP logic [31:0] nop = 32'h00000013; // instruction for NOP
@ -81,6 +84,12 @@ module ifu (
tlb #(3) itlb(clk, reset, SATP, PCF, PageTableEntryF, ITLBWriteF, ITLBFlushF, tlb #(3) itlb(clk, reset, SATP, PCF, PageTableEntryF, ITLBWriteF, ITLBFlushF,
InstrPAdrF, ITLBMissF, ITLBHitF); InstrPAdrF, 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 // *** put memory interface on here, InstrF becomes output
//assign InstrPAdrF = PCF; // *** no MMU //assign InstrPAdrF = PCF; // *** no MMU
//assign InstrReadF = ~StallD; // *** & ICacheMissF; add later //assign InstrReadF = ~StallD; // *** & ICacheMissF; add later
@ -89,10 +98,48 @@ module ifu (
assign PrivilegedChangePCM = RetM | TrapM; 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 assign PCNextF = {UnalignedPCNextF[`XLEN-1:1], 1'b0}; // hart-SPEC p. 21 about 16-bit alignment
flopenl #(`XLEN) pcreg(clk, reset, ~StallF, PCNextF, `RESET_VECTOR, PCF); flopenl #(`XLEN) pcreg(clk, reset, ~StallF, 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 // pcadder
// add 2 or 4 to the PC, based on whether the instruction is 16 bits or 32 // add 2 or 4 to the PC, based on whether the instruction is 16 bits or 32
assign CompressedF = (InstrF[1:0] != 2'b11); // is it a 16-bit compressed instruction? assign CompressedF = (InstrF[1:0] != 2'b11); // is it a 16-bit compressed instruction?
@ -124,6 +171,14 @@ module ifu (
assign IllegalIEUInstrFaultD = IllegalBaseInstrFaultD | IllegalCompInstrD; // illegal if bad 32 or 16-bit instr assign IllegalIEUInstrFaultD = IllegalBaseInstrFaultD | IllegalCompInstrD; // illegal if bad 32 or 16-bit instr
// *** combine these with others in better way, including M, F // *** 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 // Misaligned PC logic
generate generate
@ -147,6 +202,13 @@ module ifu (
flopenr #(`XLEN) PCMReg(clk, reset, ~StallM, PCE, PCM); flopenr #(`XLEN) PCMReg(clk, reset, ~StallM, PCE, PCM);
flopenr #(`XLEN) PCWReg(clk, reset, ~StallW, PCM, PCW); // *** probably not needed; delete later 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. // 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 // 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 // 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

@ -55,7 +55,7 @@ module wallypipelinedhart (
// logic [1:0] ForwardAE, ForwardBE; // logic [1:0] ForwardAE, ForwardBE;
logic StallF, StallD, StallE, StallM, StallW; logic StallF, StallD, StallE, StallM, StallW;
logic FlushD, FlushE, FlushM, FlushW; logic FlushF, FlushD, FlushE, FlushM, FlushW;
logic RetM, TrapM; logic RetM, TrapM;
// new signals that must connect through DP // new signals that must connect through DP
@ -66,7 +66,7 @@ module wallypipelinedhart (
logic [2:0] Funct3E; logic [2:0] Funct3E;
// logic [31:0] InstrF; // logic [31:0] InstrF;
logic [31:0] InstrD, InstrM; 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] PCTargetE;
logic [`XLEN-1:0] CSRReadValW, MulDivResultW; logic [`XLEN-1:0] CSRReadValW, MulDivResultW;
logic [`XLEN-1:0] PrivilegedNextPCM; logic [`XLEN-1:0] PrivilegedNextPCM;
@ -101,13 +101,14 @@ module wallypipelinedhart (
logic InstrReadF; logic InstrReadF;
logic DataStall, InstrStall; logic DataStall, InstrStall;
logic InstrAckD, MemAckW; logic InstrAckD, MemAckW;
logic BPPredWrongE;
ifu ifu(.InstrInF(InstrRData), .*); // instruction fetch unit: PC, branch prediction, instruction cache 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 dmem dmem(.*); // data cache unit
ahblite ebu( ahblite ebu(
//.InstrReadF(1'b0), //.InstrReadF(1'b0),
//.InstrRData(InstrF), // hook up InstrF later //.InstrRData(InstrF), // hook up InstrF later

View File

@ -0,0 +1,84 @@
// Ross Thompson
// November 05, 2019
// Oklahoma State University
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

@ -368,7 +368,7 @@ string tests32i[] = {
memfilename = {"../../imperas-riscv-tests/work/", tests[test], ".elf.memfile"}; memfilename = {"../../imperas-riscv-tests/work/", tests[test], ".elf.memfile"};
$readmemh(memfilename, dut.imem.RAM); $readmemh(memfilename, dut.imem.RAM);
$readmemh(memfilename, dut.uncore.dtim.RAM); $readmemh(memfilename, dut.uncore.dtim.RAM);
reset = 1; # 22; reset = 0; reset = 1; # 42; reset = 0;
end end
// generate clock to sequence tests // generate clock to sequence tests
@ -444,7 +444,11 @@ string tests32i[] = {
reset = 1; # 17; reset = 0; reset = 1; # 17; reset = 0;
end end
end end
end end // always @ (negedge clk)
// track the current function or label
//function_rfunction_radix function_radix();
endmodule endmodule
/* verilator lint_on STMTDLY */ /* verilator lint_on STMTDLY */