forked from Github_Repos/cvw
Merge remote-tracking branch 'upstream/main' into main
This commit is contained in:
commit
f91d74896a
@ -110,12 +110,12 @@ Ubuntu users may need to install and update various tools. Beware when cutting
|
||||
|
||||
### Install RISC-V GCC Cross-Compiler
|
||||
|
||||
To install GCC from source can take hours to compile. This configuration enables multilib to target many flavors of RISC-V. This book is tested with GCC 12.2 (tagged 2022.09.21), but will likely work with newer versions as well.
|
||||
To install GCC from source can take hours to compile. This configuration enables multilib to target many flavors of RISC-V. This book is tested with GCC 12.2 (tagged 2023.01.31), but will likely work with newer versions as well.
|
||||
|
||||
$ git clone https://github.com/riscv/riscv-gnu-toolchain
|
||||
$ cd riscv-gnu-toolchain
|
||||
$ git checkout 2022.09.21
|
||||
$ ./configure --prefix=$RISCV --enable-multilib --with-multilib-generator="rv32e-ilp32e--;rv32i-ilp32--;rv32im-ilp32--;rv32iac-ilp32--;rv32imac-ilp32--;rv32imafc-ilp32f--;rv32imafdc-ilp32d--;rv64i-lp64--;rv64ic-lp64--;rv64iac-lp64--;rv64imac-lp64--;rv64imafdc-lp64d--;rv64im-lp64--;"
|
||||
$ git checkout 2023.01.31
|
||||
$ ./configure --prefix=$RISCV --with-multilib-generator="rv32e-ilp32e--;rv32i-ilp32--;rv32im-ilp32--;rv32iac-ilp32--;rv32imac-ilp32--;rv32imafc-ilp32f--;rv32imafdc-ilp32d--;rv64i-lp64--;rv64ic-lp64--;rv64iac-lp64--;rv64imac-lp64--;rv64imafdc-lp64d--;rv64im-lp64--;"
|
||||
$ make --jobs
|
||||
|
||||
Note: make --jobs will reduce compile time by compiling in parallel. However, adding this option could dramatically increase the memory utilization of your local machine.
|
||||
@ -143,7 +143,7 @@ Spike also takes a while to install and compile, but this can be done concurrent
|
||||
$ git clone https://github.com/riscv-software-src/riscv-isa-sim
|
||||
$ mkdir riscv-isa-sim/build
|
||||
$ cd riscv-isa-sim/build
|
||||
$ ../configure --prefix=$RISCV --enable-commitlog
|
||||
$ ../configure --prefix=$RISCV
|
||||
$ make --jobs
|
||||
$ make install
|
||||
$ cd ../arch_test_target/spike/device
|
||||
|
@ -28,6 +28,7 @@
|
||||
import os
|
||||
import sys
|
||||
import matplotlib.pyplot as plt
|
||||
import re
|
||||
|
||||
def ComputeCPI(benchmark):
|
||||
'Computes and inserts CPI into benchmark stats.'
|
||||
@ -145,6 +146,11 @@ def FormatToPlot(currBenchmark):
|
||||
|
||||
if(sys.argv[1] == '-b'):
|
||||
configList = []
|
||||
summery = 0
|
||||
if(sys.argv[2] == '-s'):
|
||||
summery = 1
|
||||
sys.argv = sys.argv[1::]
|
||||
print('summery = %d' % summery)
|
||||
for config in sys.argv[2::]:
|
||||
benchmarks = ProcessFile(config)
|
||||
ComputeAverage(benchmarks)
|
||||
@ -171,18 +177,50 @@ if(sys.argv[1] == '-b'):
|
||||
|
||||
size = len(benchmarkDict)
|
||||
index = 1
|
||||
print('Number of plots', size)
|
||||
for benchmarkName in benchmarkDict:
|
||||
currBenchmark = benchmarkDict[benchmarkName]
|
||||
(names, values) = FormatToPlot(currBenchmark)
|
||||
print(names, values)
|
||||
plt.subplot(6, 7, index)
|
||||
plt.bar(names, values)
|
||||
plt.title(benchmarkName)
|
||||
plt.ylabel('BR Dir Miss Rate (%)')
|
||||
#plt.xlabel('Predictor')
|
||||
index += 1
|
||||
#plt.tight_layout()
|
||||
print('summery = %d' % summery)
|
||||
if(summery == 0):
|
||||
print('Number of plots', size)
|
||||
for benchmarkName in benchmarkDict:
|
||||
currBenchmark = benchmarkDict[benchmarkName]
|
||||
(names, values) = FormatToPlot(currBenchmark)
|
||||
print(names, values)
|
||||
plt.subplot(6, 7, index)
|
||||
plt.bar(names, values)
|
||||
plt.title(benchmarkName)
|
||||
plt.ylabel('BR Dir Miss Rate (%)')
|
||||
#plt.xlabel('Predictor')
|
||||
index += 1
|
||||
else:
|
||||
combined = benchmarkDict['All_']
|
||||
(name, value) = FormatToPlot(combined)
|
||||
lst = []
|
||||
dct = {}
|
||||
category = []
|
||||
length = []
|
||||
accuracy = []
|
||||
for index in range(0, len(name)):
|
||||
match = re.match(r"([a-z]+)([0-9]+)", name[index], re.I)
|
||||
percent = 100 -value[index]
|
||||
if match:
|
||||
(PredType, size) = match.groups()
|
||||
category.append(PredType)
|
||||
length.append(size)
|
||||
accuracy.append(percent)
|
||||
if(PredType not in dct):
|
||||
dct[PredType] = ([size], [percent])
|
||||
else:
|
||||
(currSize, currPercent) = dct[PredType]
|
||||
currSize.append(size)
|
||||
currPercent.append(percent)
|
||||
dct[PredType] = (currSize, currPercent)
|
||||
print(dct)
|
||||
for cat in dct:
|
||||
(x, y) = dct[cat]
|
||||
plt.scatter(x, y, label=cat)
|
||||
plt.plot(x, y)
|
||||
plt.ylabel('Prediction Accuracy')
|
||||
plt.xlabel('Size (b or k)')
|
||||
plt.legend(loc='upper left')
|
||||
plt.show()
|
||||
|
||||
|
||||
|
@ -54,13 +54,15 @@ fi
|
||||
cd $RISCV
|
||||
git clone https://github.com/riscv/riscv-gnu-toolchain
|
||||
cd riscv-gnu-toolchain
|
||||
./configure --prefix=${RISCV} --enable-multilib --with-multilib-generator="rv32e-ilp32e--;rv32i-ilp32--;rv32im-ilp32--;rv32iac-ilp32--;rv32imac-ilp32--;rv32imafc-ilp32f--;rv32imafdc-ilp32d--;rv64i-lp64--;rv64ic-lp64--;rv64iac-lp64--;rv64imac-lp64--;rv64imafdc-lp64d--;rv64im-lp64--;"
|
||||
git checkout 2023.01.31
|
||||
./configure --prefix=${RISCV} --with-multilib-generator="rv32e-ilp32e--;rv32i-ilp32--;rv32im-ilp32--;rv32iac-ilp32--;rv32imac-ilp32--;rv32imafc-ilp32f--;rv32imafdc-ilp32d--;rv64i-lp64--;rv64ic-lp64--;rv64iac-lp64--;rv64imac-lp64--;rv64imafdc-lp64d--;rv64im-lp64--;"
|
||||
make -j ${NUM_THREADS}
|
||||
make install
|
||||
|
||||
# elf2hex
|
||||
cd $RISCV
|
||||
export PATH=$RISCV/riscv-gnu-toolchain/bin:$PATH
|
||||
#export PATH=$RISCV/riscv-gnu-toolchain/bin:$PATH
|
||||
gexport PATH=$RISCV/bin:$PATH
|
||||
git clone https://github.com/sifive/elf2hex.git
|
||||
cd elf2hex
|
||||
autoreconf -i
|
||||
@ -87,7 +89,7 @@ cd $RISCV
|
||||
git clone https://github.com/riscv-software-src/riscv-isa-sim
|
||||
mkdir -p riscv-isa-sim/build
|
||||
cd riscv-isa-sim/build
|
||||
../configure --prefix=$RISCV --enable-commitlog
|
||||
../configure --prefix=$RISCV
|
||||
make -j ${NUM_THREADS}
|
||||
make install
|
||||
cd ../arch_test_target/spike/device
|
||||
|
@ -63,7 +63,8 @@ module controller(
|
||||
output logic [2:0] Funct3M, // Instruction's funct3 field
|
||||
output logic RegWriteM, // Instruction writes a register (needed for Hazard unit)
|
||||
output logic InvalidateICacheM, FlushDCacheM, // Invalidate I$, flush D$
|
||||
output logic InstrValidM, // Instruction is valid
|
||||
output logic InstrValidD, InstrValidE, InstrValidM, // Instruction is valid
|
||||
|
||||
output logic FWriteIntM, // FPU controller writes integer register file
|
||||
// Writeback stage control signals
|
||||
input logic StallW, FlushW, // Stall, flush Writeback stage
|
||||
@ -97,7 +98,6 @@ module controller(
|
||||
logic FenceXD; // Fence instruction
|
||||
logic InvalidateICacheD, FlushDCacheD;// Invalidate I$, flush D$
|
||||
logic CSRWriteD, CSRWriteE; // CSR write
|
||||
logic InstrValidD, InstrValidE; // Instruction is valid
|
||||
logic PrivilegedD, PrivilegedE; // Privileged instruction
|
||||
logic InvalidateICacheE, FlushDCacheE;// Invalidate I$, flush D$
|
||||
logic [`CTRLW-1:0] ControlsD; // Main Instruction Decoder control signals
|
||||
|
@ -54,7 +54,7 @@ module ieu (
|
||||
output logic [4:0] RdM, // Destination register
|
||||
input logic [`XLEN-1:0] FIntResM, // Integer result from FPU (fmv, fclass, fcmp)
|
||||
output logic InvalidateICacheM, FlushDCacheM, // Invalidate I$, flush D$
|
||||
output logic InstrValidM, // Instruction is valid
|
||||
output logic InstrValidD, InstrValidE, InstrValidM,// Instruction is valid
|
||||
// Writeback stage signals
|
||||
input logic [`XLEN-1:0] FIntDivResultW, // Integer divide result from FPU fdivsqrt)
|
||||
input logic [`XLEN-1:0] CSRReadValW, // CSR read value,
|
||||
@ -98,7 +98,7 @@ module ieu (
|
||||
.PCSrcE, .ALUControlE, .ALUSrcAE, .ALUSrcBE, .ALUResultSrcE, .MemReadE, .CSRReadE,
|
||||
.Funct3E, .Funct7E, .IntDivE, .MDUE, .W64E, .JumpE, .SCE, .BranchSignedE, .StallM, .FlushM, .MemRWM,
|
||||
.CSRReadM, .CSRWriteM, .PrivilegedM, .AtomicM, .Funct3M,
|
||||
.RegWriteM, .InvalidateICacheM, .FlushDCacheM, .InstrValidM, .FWriteIntM,
|
||||
.RegWriteM, .InvalidateICacheM, .FlushDCacheM, .InstrValidM, .InstrValidE, .InstrValidD, .FWriteIntM,
|
||||
.StallW, .FlushW, .RegWriteW, .IntDivW, .ResultSrcW, .CSRWriteFenceM, .StoreStallD);
|
||||
|
||||
datapath dp(
|
||||
|
@ -42,7 +42,7 @@ module RASPredictor #(parameter int StackSize = 16 )(
|
||||
logic CounterEn;
|
||||
localparam Depth = $clog2(StackSize);
|
||||
|
||||
logic [Depth-1:0] NextPtr, Ptr, PtrP1, PtrM1;
|
||||
logic [Depth-1:0] NextPtr, Ptr, P1, M1, IncDecPtr;
|
||||
logic [StackSize-1:0] [`XLEN-1:0] memory;
|
||||
integer index;
|
||||
|
||||
@ -71,10 +71,11 @@ module RASPredictor #(parameter int StackSize = 16 )(
|
||||
assign CounterEn = PopF | PushE | RepairD;
|
||||
|
||||
assign DecrementPtr = (PopF | DecRepairD) & ~IncrRepairD;
|
||||
mux2 #(Depth) PtrMux(PtrP1, PtrM1, DecrementPtr, NextPtr);
|
||||
|
||||
assign PtrM1 = Ptr - 1'b1;
|
||||
assign PtrP1 = Ptr + 1'b1;
|
||||
assign P1 = 1;
|
||||
assign M1 = '1; // -1
|
||||
mux2 #(Depth) PtrMux(P1, M1, DecrementPtr, IncDecPtr);
|
||||
assign NextPtr = Ptr + IncDecPtr;
|
||||
|
||||
flopenr #(Depth) PTR(clk, reset, CounterEn, NextPtr, Ptr);
|
||||
|
||||
@ -84,7 +85,7 @@ module RASPredictor #(parameter int StackSize = 16 )(
|
||||
for(index=0; index<StackSize; index++)
|
||||
memory[index] <= {`XLEN{1'b0}};
|
||||
end else if(PushE) begin
|
||||
memory[PtrP1] <= #1 PCLinkE;
|
||||
memory[NextPtr] <= #1 PCLinkE;
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -51,6 +51,7 @@ module bpred (
|
||||
input logic [31:0] PostSpillInstrRawF, // Instruction
|
||||
|
||||
// Branch and jump outcome
|
||||
input logic InstrValidD, InstrValidE,
|
||||
input logic PCSrcE, // Executation stage branch is taken
|
||||
input logic [`XLEN-1:0] IEUAdrE, // The branch/jump target address
|
||||
input logic [`XLEN-1:0] PCLinkE, // The address following the branch instruction. (AKA Fall through address)
|
||||
@ -69,12 +70,12 @@ module bpred (
|
||||
logic PredValidF;
|
||||
logic [1:0] DirPredictionF;
|
||||
|
||||
logic [3:0] BTBPredInstrClassF, PredInstrClassF, PredInstrClassD, PredInstrClassE;
|
||||
logic [3:0] BTBPredInstrClassF, PredInstrClassF, PredInstrClassD;
|
||||
logic [`XLEN-1:0] PredPCF, RASPCF;
|
||||
logic PredictionPCWrongE;
|
||||
logic PredictionInstrClassWrongE;
|
||||
logic AnyWrongPredInstrClassD, AnyWrongPredInstrClassE;
|
||||
logic [3:0] InstrClassF, InstrClassD, InstrClassE, InstrClassW;
|
||||
logic DirPredictionWrongE, BTBPredPCWrongE, RASPredPCWrongE, BPPredClassNonCFIWrongE;
|
||||
logic DirPredictionWrongE, BTBPredPCWrongE, RASPredPCWrongE;
|
||||
|
||||
logic SelBPPredF;
|
||||
logic [`XLEN-1:0] BPPredPCF;
|
||||
@ -82,7 +83,6 @@ module bpred (
|
||||
logic [`XLEN-1:0] PCCorrectE;
|
||||
logic [3:0] WrongPredInstrClassD;
|
||||
|
||||
|
||||
logic BTBTargetWrongE;
|
||||
logic RASTargetWrongE;
|
||||
logic JumpOrTakenBranchE;
|
||||
@ -104,8 +104,7 @@ module bpred (
|
||||
end else if (`BPRED_TYPE == "BPSPECULATIVEGLOBAL") begin:Predictor
|
||||
speculativeglobalhistory #(`BPRED_SIZE) DirPredictor(.clk, .reset, .StallF, .StallD, .StallE, .StallM, .StallW, .FlushD, .FlushE, .FlushM, .FlushW,
|
||||
.DirPredictionF, .DirPredictionWrongE,
|
||||
.BranchInstrF(PredInstrClassF[0]), .BranchInstrD(InstrClassD[0]), .BranchInstrE(InstrClassE[0]), .BranchInstrM(InstrClassM[0]),
|
||||
.BranchInstrW(InstrClassW[0]), .WrongPredInstrClassD, .PCSrcE);
|
||||
.PredInstrClassF, .InstrClassD, .InstrClassE, .WrongPredInstrClassD, .PCSrcE);
|
||||
|
||||
end else if (`BPRED_TYPE == "BPGSHARE") begin:Predictor
|
||||
gshare #(`BPRED_SIZE) DirPredictor(.clk, .reset, .StallF, .StallD, .StallE, .StallM, .FlushD, .FlushE, .FlushM,
|
||||
@ -132,20 +131,15 @@ module bpred (
|
||||
-----/\----- EXCLUDED -----/\----- */
|
||||
end
|
||||
|
||||
// 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 build its next state.
|
||||
// For a 2 bit table this is the prediction count.
|
||||
|
||||
// Part 2 Branch target address prediction
|
||||
// *** For now the BTB will house the direct and indirect targets
|
||||
// BTB contains target address for all CFI
|
||||
|
||||
btb TargetPredictor(.clk, .reset, .StallF, .StallD, .StallM, .FlushD, .FlushM,
|
||||
.PCNextF, .PCF, .PCD, .PCE,
|
||||
.PredPCF,
|
||||
.BTBPredInstrClassF,
|
||||
.PredValidF,
|
||||
.PredictionInstrClassWrongE,
|
||||
.AnyWrongPredInstrClassE,
|
||||
.IEUAdrE,
|
||||
.InstrClassD,
|
||||
.InstrClassE);
|
||||
@ -205,16 +199,15 @@ module bpred (
|
||||
flopenrc #(4) InstrClassRegM(clk, reset, FlushM, ~StallM, InstrClassE, InstrClassM);
|
||||
flopenrc #(4) InstrClassRegW(clk, reset, FlushW, ~StallW, InstrClassM, InstrClassW);
|
||||
flopenrc #(1) BPPredWrongMReg(clk, reset, FlushM, ~StallM, BPPredWrongE, BPPredWrongM);
|
||||
flopenrc #(1) JumpOrTakenBranchMReg(clk, reset, FlushM, ~StallM, JumpOrTakenBranchE, JumpOrTakenBranchM);
|
||||
|
||||
// branch predictor
|
||||
flopenrc #(4) BPPredWrongRegM(clk, reset, FlushM, ~StallM,
|
||||
{DirPredictionWrongE, BTBPredPCWrongE, RASPredPCWrongE, PredictionInstrClassWrongE},
|
||||
{DirPredictionWrongE, BTBPredPCWrongE, RASPredPCWrongE, AnyWrongPredInstrClassE},
|
||||
{DirPredictionWrongM, BTBPredPCWrongM, RASPredPCWrongM, PredictionInstrClassWrongM});
|
||||
|
||||
// pipeline the class
|
||||
flopenrc #(4) PredInstrClassRegD(clk, reset, FlushD, ~StallD, PredInstrClassF, PredInstrClassD);
|
||||
flopenrc #(4) PredInstrClassRegE(clk, reset, FlushE, ~StallE, PredInstrClassD, PredInstrClassE);
|
||||
flopenrc #(1) WrongInstrClassRegE(clk, reset, FlushE, ~StallE, AnyWrongPredInstrClassD, AnyWrongPredInstrClassE);
|
||||
|
||||
// Check the prediction
|
||||
// if it is a CFI then check if the next instruction address (PCD) matches the branch's target or fallthrough address.
|
||||
@ -223,11 +216,13 @@ module bpred (
|
||||
// The next instruction is always valid as no other flush would occur at the same time as the branch and not
|
||||
// also flush the branch. This will change in a superscaler cpu.
|
||||
assign PredictionPCWrongE = PCCorrectE != PCD;
|
||||
assign BPPredWrongE = PredictionPCWrongE & (|InstrClassE | BPPredClassNonCFIWrongE);
|
||||
|
||||
// The branch direction is checked inside each branch predictor, but does not actually matter for
|
||||
// branch miss prediction recovery. If the class or direction is wrong, but the target is correct
|
||||
// we an ignore the branch miss-prediction.
|
||||
// branch class prediction wrong.
|
||||
assign WrongPredInstrClassD = PredInstrClassD ^ InstrClassD;
|
||||
assign AnyWrongPredInstrClassD = |WrongPredInstrClassD;
|
||||
|
||||
// branch is wrong only if the PC does not match and both the Decode and Fetch stages have valid instructions.
|
||||
assign BPPredWrongE = PredictionPCWrongE & InstrValidE & InstrValidD;
|
||||
|
||||
// Output the predicted PC or corrected PC on miss-predict.
|
||||
// Selects the BP or PC+2/4.
|
||||
@ -242,39 +237,23 @@ module bpred (
|
||||
if(`INSTR_CLASS_PRED) mux2 #(`XLEN) pcmuxBPWrongInvalidateFlush(PCE, PCF, BPPredWrongM, NextValidPCE);
|
||||
else assign NextValidPCE = PCE;
|
||||
|
||||
// Finally we need to check if the class is wrong. When the class is wrong the BTB needs to be updated.
|
||||
// Also we want to track this in a performance counter.
|
||||
assign PredictionInstrClassWrongE = InstrClassE != PredInstrClassE;
|
||||
// The remaining checks are used for performance counters.
|
||||
|
||||
|
||||
|
||||
// If we have a jump, jump register or jal or jalr and the PC is wrong we need to increment the performance counter.
|
||||
//assign BTBPredPCWrongE = (InstrClassE[3] | InstrClassE[1] | InstrClassE[0]) & PredictionPCWrongE;
|
||||
//assign BTBPredPCWrongE = TargetWrongE & (InstrClassE[3] | InstrClassE[1] | InstrClassE[0]) & PCSrcE;
|
||||
assign BTBPredPCWrongE = BTBTargetWrongE;
|
||||
|
||||
// similar with RAS. Over counts ras if the class prediction was wrong.
|
||||
//assign RASPredPCWrongE = TargetWrongE & InstrClassE[2] & PCSrcE;
|
||||
assign RASPredPCWrongE = RASTargetWrongE;
|
||||
// Finally if the real instruction class is non CFI but the predictor said it was we need to count.
|
||||
assign BPPredClassNonCFIWrongE = PredictionInstrClassWrongE & ~|InstrClassE;
|
||||
|
||||
// branch class prediction wrong.
|
||||
assign WrongPredInstrClassD = PredInstrClassD ^ InstrClassD;
|
||||
|
||||
|
||||
// performance counters
|
||||
// 1. class (class wrong / minstret) (PredictionInstrClassWrongM / csr) // Correct now
|
||||
// 2. target btb (btb target wrong / class[0,1,3]) (btb target wrong / (br + j + jal)
|
||||
// 3. target ras (ras target wrong / class[2])
|
||||
// 4. direction (br dir wrong / class[0])
|
||||
|
||||
assign BTBTargetWrongE = (PredPCE != IEUAdrE) & (InstrClassE[0] | InstrClassE[1] | InstrClassE[3]) & PCSrcE;
|
||||
assign RASTargetWrongE = (RASPCE != IEUAdrE) & InstrClassE[2] & PCSrcE;
|
||||
// Unforuantely we can't relay on PCD to infer the correctness of the BTB or RAS because the class prediction
|
||||
// could be wrong or the fall through address selected for branch predict not taken.
|
||||
// By pipeline the BTB's PC and RAS address through the pipeline we can measure the accuracy of
|
||||
// both without the above inaccuracies.
|
||||
assign BTBPredPCWrongE = (PredPCE != IEUAdrE) & (InstrClassE[0] | InstrClassE[1] | InstrClassE[3]) & PCSrcE;
|
||||
assign RASPredPCWrongE = (RASPCE != IEUAdrE) & InstrClassE[2] & PCSrcE;
|
||||
|
||||
assign JumpOrTakenBranchE = (InstrClassE[0] & PCSrcE) | InstrClassE[1] | InstrClassE[3];
|
||||
|
||||
flopenrc #(1) JumpOrTakenBranchMReg(clk, reset, FlushM, ~StallM, JumpOrTakenBranchE, JumpOrTakenBranchM);
|
||||
|
||||
flopenrc #(`XLEN) BTBTargetDReg(clk, reset, FlushD, ~StallD, PredPCF, PredPCD);
|
||||
flopenrc #(`XLEN) BTBTargetEReg(clk, reset, FlushE, ~StallE, PredPCD, PredPCE);
|
||||
|
||||
|
@ -39,7 +39,7 @@ module btb #(parameter int Depth = 10 ) (
|
||||
output logic [3:0] BTBPredInstrClassF, // BTB's guess at instruction class
|
||||
output logic PredValidF, // BTB's guess is valid
|
||||
// update
|
||||
input logic PredictionInstrClassWrongE, // BTB's instruction class guess was wrong
|
||||
input logic AnyWrongPredInstrClassE, // BTB's instruction class guess was wrong
|
||||
input logic [`XLEN-1:0] IEUAdrE, // Branch/jump target address to insert into btb
|
||||
input logic [3:0] InstrClassD, // Instruction class to insert into btb
|
||||
input logic [3:0] InstrClassE // Instruction class to insert into btb
|
||||
@ -98,7 +98,7 @@ module btb #(parameter int Depth = 10 ) (
|
||||
|
||||
//assign PredValidF = MatchXF ? 1'b1 : TablePredValidF;
|
||||
|
||||
assign UpdateEn = |InstrClassE | PredictionInstrClassWrongE;
|
||||
assign UpdateEn = |InstrClassE | AnyWrongPredInstrClassE;
|
||||
|
||||
// An optimization may be using a PC relative address.
|
||||
ram2p1r1wbe #(2**Depth, `XLEN+4) memory(
|
||||
|
@ -29,35 +29,31 @@
|
||||
`include "wally-config.vh"
|
||||
|
||||
module speculativeglobalhistory #(parameter int k = 10 ) (
|
||||
input logic clk,
|
||||
input logic reset,
|
||||
input logic StallF, StallD, StallE, StallM, StallW,
|
||||
input logic FlushD, FlushE, FlushM, FlushW,
|
||||
output logic [1:0] DirPredictionF,
|
||||
output logic DirPredictionWrongE,
|
||||
input logic clk,
|
||||
input logic reset,
|
||||
input logic StallF, StallD, StallE, StallM, StallW,
|
||||
input logic FlushD, FlushE, FlushM, FlushW,
|
||||
output logic [1:0] DirPredictionF,
|
||||
output logic DirPredictionWrongE,
|
||||
// update
|
||||
input logic BranchInstrF, BranchInstrD, BranchInstrE, BranchInstrM, BranchInstrW,
|
||||
input logic [3:0] WrongPredInstrClassD,
|
||||
input logic PCSrcE
|
||||
input logic [3:0] PredInstrClassF, InstrClassD, InstrClassE,
|
||||
input logic [3:0] WrongPredInstrClassD,
|
||||
input logic PCSrcE
|
||||
);
|
||||
|
||||
logic MatchF, MatchD, MatchE;
|
||||
logic MatchNextX, MatchXF;
|
||||
|
||||
logic [1:0] TableDirPredictionF, DirPredictionD, DirPredictionE;
|
||||
logic [1:0] NewDirPredictionF, NewDirPredictionD, NewDirPredictionE;
|
||||
|
||||
logic [k-1:0] GHRF;
|
||||
logic GHRExtraF;
|
||||
logic [k-1:0] GHRD, GHRE, GHRM, GHRW;
|
||||
logic [k-1:0] GHRNextF;
|
||||
logic [k-1:0] GHRNextD;
|
||||
logic [k-1:0] GHRNextE, GHRNextM, GHRNextW;
|
||||
logic [k-1:0] IndexNextF, IndexF;
|
||||
logic [k-1:0] IndexD, IndexE;
|
||||
|
||||
logic [1:0] NewDirPredictionE;
|
||||
|
||||
logic [k-1:0] GHRF, GHRD, GHRE;
|
||||
logic GHRLastF;
|
||||
logic [k-1:0] GHRNextF, GHRNextD, GHRNextE;
|
||||
logic [k-1:0] IndexNextF, IndexF, IndexD, IndexE;
|
||||
logic [1:0] ForwardNewDirPrediction, ForwardDirPredictionF;
|
||||
|
||||
logic FlushDOrDirWrong;
|
||||
|
||||
assign IndexNextF = GHRNextF;
|
||||
assign IndexF = GHRF;
|
||||
@ -70,20 +66,20 @@ module speculativeglobalhistory #(parameter int k = 10 ) (
|
||||
.rd1(TableDirPredictionF),
|
||||
.wa2(IndexE),
|
||||
.wd2(NewDirPredictionE),
|
||||
.we2(BranchInstrE & ~StallM & ~FlushM),
|
||||
.we2(InstrClassE[0]),
|
||||
.bwe2(1'b1));
|
||||
|
||||
// if there are non-flushed branches in the pipeline we need to forward the prediction from that stage to the NextF demi stage
|
||||
// and then register for use in the Fetch stage.
|
||||
assign MatchF = BranchInstrF & ~FlushD & (IndexNextF == IndexF);
|
||||
assign MatchD = BranchInstrD & ~FlushE & (IndexNextF == IndexD);
|
||||
assign MatchE = BranchInstrE & ~FlushM & (IndexNextF == IndexE);
|
||||
assign MatchF = PredInstrClassF[0] & ~FlushD & (IndexNextF == IndexF);
|
||||
assign MatchD = InstrClassD[0] & ~FlushE & (IndexNextF == IndexD);
|
||||
assign MatchE = InstrClassE[0] & ~FlushM & (IndexNextF == IndexE);
|
||||
assign MatchNextX = MatchF | MatchD | MatchE;
|
||||
|
||||
flopenr #(1) MatchReg(clk, reset, ~StallF, MatchNextX, MatchXF);
|
||||
|
||||
assign ForwardNewDirPrediction = MatchF ? NewDirPredictionF :
|
||||
MatchD ? NewDirPredictionD :
|
||||
assign ForwardNewDirPrediction = MatchF ? {2{DirPredictionF[1]}} :
|
||||
MatchD ? {2{DirPredictionD[1]}} :
|
||||
NewDirPredictionE ;
|
||||
|
||||
flopenr #(2) ForwardDirPredicitonReg(clk, reset, ~StallF, ForwardNewDirPrediction, ForwardDirPredictionF);
|
||||
@ -94,49 +90,37 @@ module speculativeglobalhistory #(parameter int k = 10 ) (
|
||||
flopenr #(2) PredictionRegD(clk, reset, ~StallD, DirPredictionF, DirPredictionD);
|
||||
flopenr #(2) PredictionRegE(clk, reset, ~StallE, DirPredictionD, DirPredictionE);
|
||||
|
||||
// New prediction pipeline
|
||||
assign NewDirPredictionF = {DirPredictionF[1], DirPredictionF[1]};
|
||||
|
||||
flopenr #(2) NewPredDReg(clk, reset, ~StallD, NewDirPredictionF, NewDirPredictionD);
|
||||
satCounter2 BPDirUpdateE(.BrDir(PCSrcE), .OldState(DirPredictionE), .NewState(NewDirPredictionE));
|
||||
|
||||
// GHR pipeline
|
||||
// this version fails the regression test do to pessimistic x propagation.
|
||||
// assign GHRNextF = FlushD | DirPredictionWrongE ? GHRNextD[k-1:0] :
|
||||
// BranchInstrF ? {DirPredictionF[1], GHRF[k-1:1]} :
|
||||
// GHRF;
|
||||
|
||||
always_comb begin
|
||||
if(FlushD | DirPredictionWrongE) begin
|
||||
GHRNextF = GHRNextD[k-1:0];
|
||||
end else if(BranchInstrF) GHRNextF = {DirPredictionF[1], GHRF[k-1:1]};
|
||||
else GHRNextF = GHRF;
|
||||
end
|
||||
// If Fetch has a branch, speculatively insert prediction into the GHR
|
||||
// If the front end is flushed or the direction prediction is wrong, reset to
|
||||
// most recent valid GHR. For a BP wrong this is GHRD with the correct prediction shifted in.
|
||||
// For FlushE this is GHRE. GHRNextE is both.
|
||||
assign FlushDOrDirWrong = FlushD | DirPredictionWrongE;
|
||||
mux3 #(k) GHRFMux(GHRF, {DirPredictionF[1], GHRF[k-1:1]}, GHRNextE[k-1:0],
|
||||
{FlushDOrDirWrong, PredInstrClassF[0]}, GHRNextF);
|
||||
|
||||
flopenr #(k) GHRFReg(clk, reset, (~StallF) | FlushD, GHRNextF, GHRF);
|
||||
flopenr #(1) GHRFExtraReg(clk, reset, (~StallF) | FlushD, GHRF[0], GHRExtraF);
|
||||
// Need 1 extra bit to store the shifted out GHRF if repair needs to back shift.
|
||||
flopenr #(k) GHRFReg(clk, reset, ~StallF | FlushDOrDirWrong, GHRNextF, GHRF);
|
||||
flopenr #(1) GHRFLastReg(clk, reset, ~StallF | FlushDOrDirWrong, GHRF[0], GHRLastF);
|
||||
|
||||
// use with out instruction class prediction
|
||||
//assign GHRNextD = FlushD ? GHRNextE[k-1:0] : GHRF[k-1:0];
|
||||
// with instruction class prediction
|
||||
assign GHRNextD = (FlushD | DirPredictionWrongE) ? GHRNextE[k-1:0] :
|
||||
WrongPredInstrClassD[0] & BranchInstrD ? {DirPredictionD[1], GHRF[k-1:1]} : // shift right
|
||||
WrongPredInstrClassD[0] & ~BranchInstrD ? {GHRF[k-2:0], GHRExtraF}: // shift left
|
||||
GHRF[k-1:0];
|
||||
// With instruction class prediction, the class could be wrong and is checked in Decode.
|
||||
// If it is wrong and branch does exist then shift right and insert the prediction.
|
||||
// If the branch does not exist then shift left and use GHRLastF to restore the LSB.
|
||||
logic [k-1:0] GHRClassWrong;
|
||||
mux2 #(k) GHRClassWrongMux({DirPredictionD[1], GHRF[k-1:1]}, {GHRF[k-2:0], GHRLastF}, InstrClassD[0], GHRClassWrong);
|
||||
// As with GHRF FlushD and wrong direction prediction flushes the pipeline and restores to GHRNextE.
|
||||
mux3 #(k) GHRDMux(GHRF, GHRClassWrong, GHRNextE, {FlushDOrDirWrong, WrongPredInstrClassD[0]}, GHRNextD);
|
||||
|
||||
flopenr #(k) GHRDReg(clk, reset, (~StallD) | FlushD, GHRNextD, GHRD);
|
||||
flopenr #(k) GHRDReg(clk, reset, ~StallD | FlushDOrDirWrong, GHRNextD, GHRD);
|
||||
|
||||
assign GHRNextE = BranchInstrE & ~FlushM ? {PCSrcE, GHRD[k-2:0]} : // if the branch is not flushed
|
||||
FlushE ? GHRNextM : // branch is flushed
|
||||
GHRD;
|
||||
flopenr #(k) GHREReg(clk, reset, (~StallE) | FlushE, GHRNextE, GHRE);
|
||||
mux3 #(k) GHREMux(GHRD, GHRE, {PCSrcE, GHRD[k-2:0]}, {InstrClassE[0] & ~FlushM, FlushE}, GHRNextE);
|
||||
|
||||
assign GHRNextM = FlushM ? GHRNextW : GHRE;
|
||||
flopenr #(k) GHRMReg(clk, reset, (~StallM) | FlushM, GHRNextM, GHRM);
|
||||
|
||||
assign GHRNextW = FlushW ? GHRW : GHRM;
|
||||
flopenr #(k) GHRWReg(clk, reset, (BranchInstrW & ~StallW) | FlushW, GHRNextW, GHRW);
|
||||
flopenr #(k) GHREReg(clk, reset, ((InstrClassE[0] & ~FlushM) & ~StallE) | FlushE, GHRNextE, GHRE);
|
||||
|
||||
assign DirPredictionWrongE = PCSrcE != DirPredictionE[1] & BranchInstrE;
|
||||
assign DirPredictionWrongE = PCSrcE != DirPredictionE[1] & InstrClassE[0];
|
||||
|
||||
endmodule
|
||||
|
@ -35,6 +35,7 @@ module ifu (
|
||||
// Command from CPU
|
||||
input logic InvalidateICacheM, // Clears all instruction cache valid bits
|
||||
input logic CSRWriteFenceM, // CSR write or fence instruction, PCNextF = the next valid PC (typically PCE)
|
||||
input logic InstrValidD, InstrValidE, InstrValidM,
|
||||
// Bus interface
|
||||
output logic [`PA_BITS-1:0] IFUHADDR, // Bus address from IFU to EBU
|
||||
input logic [`XLEN-1:0] HRDATA, // Bus read data from IFU to EBU
|
||||
@ -322,7 +323,7 @@ module ifu (
|
||||
if (`BPRED_SUPPORTED) begin : bpred
|
||||
bpred bpred(.clk, .reset,
|
||||
.StallF, .StallD, .StallE, .StallM, .StallW,
|
||||
.FlushD, .FlushE, .FlushM, .FlushW,
|
||||
.FlushD, .FlushE, .FlushM, .FlushW, .InstrValidD, .InstrValidE,
|
||||
.InstrD, .PCNextF, .PCPlus2or4F, .PCNext1F, .PCE, .PCM, .PCSrcE, .IEUAdrE, .PCF, .NextValidPCE,
|
||||
.PCD, .PCLinkE, .InstrClassM, .BPPredWrongE, .PostSpillInstrRawF, .JumpOrTakenBranchM, .BPPredWrongM,
|
||||
.DirPredictionWrongM, .BTBPredPCWrongM, .RASPredPCWrongM, .PredictionInstrClassWrongM);
|
||||
|
@ -145,7 +145,7 @@ module csrsr (
|
||||
STATUS_MXR_INT <= #1 0;
|
||||
STATUS_SUM_INT <= #1 0;
|
||||
STATUS_MPRV_INT <= #1 0; // Per Priv 3.3
|
||||
STATUS_FS_INT <= #1 `F_SUPPORTED ? 2'b01 : 2'b00;
|
||||
STATUS_FS_INT <= #1 `F_SUPPORTED ? 2'b00 : 2'b00; // leave floating-point off until activated, even if F_SUPPORTED
|
||||
STATUS_MPP <= #1 0;
|
||||
STATUS_SPP <= #1 0;
|
||||
STATUS_MPIE <= #1 0;
|
||||
@ -156,8 +156,6 @@ module csrsr (
|
||||
STATUS_SBE <= #1 0;
|
||||
STATUS_UBE <= #1 0;
|
||||
end else if (~StallW) begin
|
||||
if (FRegWriteM | WriteFRMM | WriteFFLAGSM) STATUS_FS_INT <= #1 2'b11; // mark Float State dirty *** this should happen in M stage, be part of if/else;
|
||||
|
||||
if (TrapM) begin
|
||||
// Update interrupt enables per Privileged Spec p. 21
|
||||
// y = PrivilegeModeW
|
||||
@ -211,6 +209,6 @@ module csrsr (
|
||||
STATUS_SPIE <= #1 `S_SUPPORTED & CSRWriteValM[5];
|
||||
STATUS_SIE <= #1 `S_SUPPORTED & CSRWriteValM[1];
|
||||
STATUS_UBE <= #1 CSRWriteValM[6] & `U_SUPPORTED & `BIGENDIAN_SUPPORTED;
|
||||
end
|
||||
end else if (FRegWriteM | WriteFRMM | WriteFFLAGSM) STATUS_FS_INT <= #1 2'b11;
|
||||
end
|
||||
endmodule
|
||||
|
@ -68,7 +68,7 @@ module wallypipelinedcore (
|
||||
logic [`XLEN-1:0] CSRReadValW, MDUResultW;
|
||||
logic [`XLEN-1:0] UnalignedPCNextF, PCNext2F;
|
||||
logic [1:0] MemRWM;
|
||||
logic InstrValidM;
|
||||
logic InstrValidD, InstrValidE, InstrValidM;
|
||||
logic InstrMisalignedFaultM;
|
||||
logic IllegalBaseInstrFaultD, IllegalIEUInstrFaultD;
|
||||
logic InstrPageFaultF, LoadPageFaultM, StoreAmoPageFaultM;
|
||||
@ -166,6 +166,7 @@ module wallypipelinedcore (
|
||||
// instruction fetch unit: PC, branch prediction, instruction cache
|
||||
ifu ifu(.clk, .reset,
|
||||
.StallF, .StallD, .StallE, .StallM, .StallW, .FlushD, .FlushE, .FlushM, .FlushW,
|
||||
.InstrValidM, .InstrValidE, .InstrValidD,
|
||||
// Fetch
|
||||
.HRDATA, .PCFSpill, .IFUHADDR, .PCNext2F,
|
||||
.IFUStallF, .IFUHBURST, .IFUHTRANS, .IFUHSIZE, .IFUHREADY, .IFUHWRITE,
|
||||
@ -201,7 +202,7 @@ module wallypipelinedcore (
|
||||
.RdE, .RdM, .FIntResM, .InvalidateICacheM, .FlushDCacheM,
|
||||
// Writeback stage
|
||||
.CSRReadValW, .MDUResultW, .FIntDivResultW, .RdW, .ReadDataW(ReadDataW[`XLEN-1:0]),
|
||||
.InstrValidM, .FCvtIntResW, .FCvtIntW,
|
||||
.InstrValidM, .InstrValidE, .InstrValidD, .FCvtIntResW, .FCvtIntW,
|
||||
// hazards
|
||||
.StallD, .StallE, .StallM, .StallW, .FlushD, .FlushE, .FlushM, .FlushW,
|
||||
.FCvtIntStallD, .LoadStallD, .MDUStallD, .CSRRdStallD, .PCSrcE,
|
||||
|
@ -2,8 +2,15 @@
|
||||
|
||||
TARGET = debug
|
||||
|
||||
$(TARGET).signature.output: $(TARGET).elf.memfile $(TARGET).elf
|
||||
spike --isa=rv64gc +signature=$(TARGET).signature.output +signature-granularity=4 $(TARGET).elf
|
||||
# diff --ignore-case $(TARGET).signature.output $(TARGET).reference_output || exit
|
||||
# echo "Signature matches! Success!"
|
||||
mkdir -p ../work
|
||||
cp -f * ../work
|
||||
|
||||
$(TARGET).elf.memfile:$(TARGET).elf $(TARGET).elf.objdump.addr
|
||||
riscv64-unknown-elf-elf2hex --bit-width $(if $(findstring rv64,$*),64,32) --input $< --output $@
|
||||
riscv64-unknown-elf-elf2hex --bit-width 64 --input $< --output $@
|
||||
|
||||
$(TARGET).elf.objdump.addr: $(TARGET).elf.objdump
|
||||
extractFunctionRadix.sh $<
|
||||
@ -15,13 +22,9 @@ $(TARGET).elf: $(TARGET).S Makefile
|
||||
riscv64-unknown-elf-gcc -g -o $(TARGET).elf -march=rv64gc -mabi=lp64 -mcmodel=medany \
|
||||
-nostartfiles -T$(WALLY)/examples/link/link.ld $(TARGET).S
|
||||
|
||||
sim:
|
||||
spike --isa=rv64gc +signature=$(TARGET).signature.output +signature-granularity=8 $(TARGET).elf
|
||||
diff --ignore-case $(TARGET).signature.output $(TARGET).reference_output || exit
|
||||
echo "Signature matches! Success!"
|
||||
|
||||
clean:
|
||||
rm -f $(TARGET).elf $(TARGET).elf.*
|
||||
rm -f $(TARGET).elf $(TARGET).elf.* *.signature.output
|
||||
|
||||
|
||||
|
||||
|
@ -5,6 +5,8 @@
|
||||
|
||||
.global rvtest_entry_point
|
||||
rvtest_entry_point:
|
||||
lui t0, 0x1e # turn on Floating point and XS
|
||||
csrs mstatus, t0
|
||||
|
||||
# openhwgroup/cvw Issue #55
|
||||
la a6, begin_signature
|
||||
|
@ -1,21 +1,12 @@
|
||||
//
|
||||
// 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.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
|
||||
///////////////////////////////////////////
|
||||
|
||||
#include "model_test.h"
|
||||
#include "arch_test.h"
|
||||
RVTEST_ISA("RV64I")
|
||||
|
||||
.section .text.init
|
||||
.globl rvtest_entry_point
|
||||
@ -23,4 +14,7 @@ rvtest_entry_point:
|
||||
RVMODEL_BOOT
|
||||
RVTEST_CODE_BEGIN
|
||||
|
||||
RVTEST_CASE(0,"//check ISA:=regex(.*64.*);check ISA:=regex(.*I.*);def TEST_CASE_1=True;",temp)
|
||||
|
||||
|
||||
RVTEST_SIGBASE( x6, wally_signature)
|
||||
|
Loading…
Reference in New Issue
Block a user