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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,97 @@
///////////////////////////////////////////
// SRAM2P1R1W
//
// Written: Ross Thomposn
// Email: ross1728@gmail.com
// Created: February 15, 2021
// Modified:
//
// Purpose: BTB model. Outputs type of instruction (currently 1 hot encoded. Probably want
// to encode to reduce storage), valid, target PC.
//
// A component of the Wally configurable RISC-V project.
//
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
// is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
///////////////////////////////////////////
`include "wally-config.vh"
module BTBPredictor
#(parameter int Depth = 10
)
(input logic clk,
input logic reset,
input logic [`XLEN-1:0] LookUpPC,
output logic [`XLEN-1:0] TargetPC,
output logic [3:0] InstrClass,
output logic Valid,
// update
input logic UpdateEN,
input logic [`XLEN-1:0] UpdatePC,
input logic [`XLEN-1:0] UpdateTarget,
input logic [3:0] UpdateInstrClass
);
localparam TotalDepth = 2 ** Depth;
logic [TotalDepth-1:0] ValidBits;
logic [Depth-1:0] LookUpPCIndex, UpdatePCIndex, LookUpPCIndexQ, UpdatePCIndexQ;
// hashing function for indexing the PC
// We have Depth bits to index, but XLEN bits as the input.
// bit 0 is always 0, bit 1 is 0 if using 4 byte instructions, but is not always 0 if
// using compressed instructions. XOR bit 1 with the MSB of index.
assign UpdatePCIndex = {UpdatePC[Depth+1] ^ UpdatePC[1], UpdatePC[Depth:2]};
assign LookUpPCIndex = {LookUpPC[Depth+1] ^ LookUpPC[1], LookUpPC[Depth:2]};
flopenr #(Depth) UpdatePCIndexReg(.clk(clk),
.reset(reset),
.en(1'b1),
.d(UpdatePCIndex),
.q(UpdatePCIndexQ));
// The valid bit must be resetable.
always_ff @ (posedge clk) begin
if (reset) begin
ValidBits <= #1 {TotalDepth{1'b0}};
end else if (UpdateEN) begin
ValidBits[UpdatePCIndexQ] <= #1 1'b1;
end
end
flopenr #(Depth) LookupPCIndexReg(.clk(clk),
.reset(reset),
.en(1'b1),
.d(LookUpPCIndex),
.q(LookUpPCIndexQ));
assign Valid = ValidBits[LookUpPCIndexQ];
// the BTB contains the target address.
// Another optimization may be using a PC relative address.
// *** need to add forwarding.
SRAM2P1R1W #(Depth, `XLEN+4) memory(.clk(clk),
.reset(reset),
.RA1(LookUpPCIndex),
.RD1({{InstrClass, TargetPC}}),
.REN1(1'b1),
.WA1(UpdatePCIndex),
.WD1({UpdateInstrClass, UpdateTarget}),
.WEN1(UpdateEN),
.BitWEN1({`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 (
input logic clk, reset,
input logic StallF, StallD, StallE, StallM, StallW,
input logic FlushD, FlushE, FlushM, FlushW,
input logic FlushF, FlushD, FlushE, FlushM, FlushW,
// Fetch
input logic [`XLEN-1:0] InstrInF,
output logic [`XLEN-1:0] PCF,
@ -37,9 +37,11 @@ module ifu (
output logic InstrReadF,
// Decode
// Execute
output logic [`XLEN-1:0] PCLinkE,
input logic PCSrcE,
input logic [`XLEN-1:0] PCTargetE,
output logic [`XLEN-1:0] PCE,
output logic BPPredWrongE,
// Mem
input logic RetM, TrapM,
input logic [`XLEN-1:0] PrivilegedNextPCM,
@ -60,13 +62,14 @@ module ifu (
output logic ITLBMissF, ITLBHitF,
// bogus
input logic [15:0] rd2
);
logic [`XLEN-1:0] UnalignedPCNextF, PCNextF;
logic misaligned, BranchMisalignedFaultE, BranchMisalignedFaultM, TrapMisalignedFaultM;
logic PrivilegedChangePCM;
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 [31:0] InstrF, InstrRawD, InstrE, InstrW;
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,
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
//assign InstrPAdrF = PCF; // *** no MMU
//assign InstrReadF = ~StallD; // *** & ICacheMissF; add later
@ -89,10 +98,48 @@ module ifu (
assign PrivilegedChangePCM = RetM | TrapM;
mux3 #(`XLEN) pcmux(PCPlus2or4F, PCTargetE, PrivilegedNextPCM, {PrivilegedChangePCM, PCSrcE}, UnalignedPCNextF);
//mux3 #(`XLEN) pcmux(PCPlus2or4F, PCCorrectE, PrivilegedNextPCM, {PrivilegedChangePCM, BPPredWrongE}, UnalignedPCNextF);
mux2 #(`XLEN) pcmux0(.d0(PCPlus2or4F),
.d1(BPPredPCF),
.s(SelBPPredF),
.y(PCNext0F));
mux2 #(`XLEN) pcmux1(.d0(PCNext0F),
.d1(PCCorrectE),
.s(BPPredWrongE),
.y(PCNext1F));
mux2 #(`XLEN) pcmux2(.d0(PCNext1F),
.d1(PrivilegedNextPCM),
.s(PrivilegedChangePCM),
.y(UnalignedPCNextF));
assign PCNextF = {UnalignedPCNextF[`XLEN-1:1], 1'b0}; // hart-SPEC p. 21 about 16-bit alignment
flopenl #(`XLEN) pcreg(clk, reset, ~StallF, PCNextF, `RESET_VECTOR, PCF);
// branch and jump predictor
// I am making the port connection explicit for now as I want to see them and they will be changing.
bpred bpred(.clk(clk),
.reset(reset),
.StallF(StallF),
.StallD(StallD),
.StallE(1'b0), // *** may need this eventually
.FlushF(FlushF),
.FlushD(FlushD),
.FlushE(FlushE),
.PCNextF(PCNextF),
.BPPredPCF(BPPredPCF),
.SelBPPredF(SelBPPredF),
.PCE(PCE),
.PCSrcE(PCSrcE),
.PCTargetE(PCTargetE),
.PCD(PCD),
.PCLinkE(PCLinkE),
.InstrClassE(InstrClassE),
.BPPredWrongE(BPPredWrongE));
// The true correct target is PCTargetE if PCSrcE is 1 else it is the fall through PCLinkE.
assign PCCorrectE = PCSrcE ? PCTargetE : PCLinkE;
// pcadder
// add 2 or 4 to the PC, based on whether the instruction is 16 bits or 32
assign 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
// *** combine these with others in better way, including M, F
// the branch predictor needs a compact decoding of the instruction class.
// *** consider adding in the alternate return address x5 for returns.
assign InstrClassD[3] = InstrD[6:0] == 7'h67 && InstrD[19:15] == 5'h01; // return
assign InstrClassD[2] = InstrD[6:0] == 7'h67 && InstrD[19:15] != 5'h01; // jump register, but not return
assign InstrClassD[1] = InstrD[6:0] == 7'h6F; // jump
assign InstrClassD[0] = InstrD[6:0] == 7'h63; // branch
// Misaligned PC logic
generate
@ -147,6 +202,13 @@ module ifu (
flopenr #(`XLEN) PCMReg(clk, reset, ~StallM, PCE, PCM);
flopenr #(`XLEN) PCWReg(clk, reset, ~StallW, PCM, PCW); // *** probably not needed; delete later
flopenrc #(4) InstrClassRegE(.clk(clk),
.reset(reset),
.en(~StallD),
.clear(FlushD),
.d(InstrClassD),
.q(InstrClassE));
// seems like there should be a lower-cost way of doing this PC+2 or PC+4 for JAL.
// either have ALU compute PC+2/4 and feed into ALUResult input of ResultMux or
// have dedicated adder in Mem stage based on PCM + 2 or 4

View File

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

View File

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

View File

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

View File

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