Merge remote-tracking branch 'upstream/main' into bit-manip

This commit is contained in:
Kip Macsai-Goren 2023-02-28 14:41:51 -08:00
commit 58ab6ec805
37 changed files with 285 additions and 240 deletions

View File

@ -247,13 +247,25 @@ if(sys.argv[1] == '-b'):
currPercent.append(percent) currPercent.append(percent)
dct[PredType] = (currSize, currPercent) dct[PredType] = (currSize, currPercent)
print(dct) print(dct)
fig, axes = plt.subplots()
marker={'twobit' : '^', 'gshare' : 'o', 'global' : 's', 'gshareBasic' : '*', 'globalBasic' : 'x'}
colors={'twobit' : 'black', 'gshare' : 'blue', 'global' : 'dodgerblue', 'gshareBasic' : 'turquoise', 'globalBasic' : 'lightsteelblue'}
for cat in dct: for cat in dct:
(x, y) = dct[cat] (x, y) = dct[cat]
plt.scatter(x, y, label='k') x=[int(2**int(v)/4) for v in x]
plt.plot(x, y) print(x, y)
plt.ylabel('Prediction Accuracy') axes.plot(x,y, color=colors[cat])
plt.xlabel('Size (b or k)') axes.scatter(x,y, label=cat, marker=marker[cat], color=colors[cat])
plt.legend(loc='upper left') #plt.scatter(x, y, label=cat)
#plt.plot(x, y)
#axes.set_xticks([4, 6, 8, 10, 12, 14])
axes.legend(loc='upper left')
axes.set_xscale("log")
axes.set_ylabel('Prediction Accuracy')
axes.set_xlabel('Size (bytes)')
axes.set_xticks([16, 64, 256, 1024, 4096, 16384])
axes.set_xticklabels([16, 64, 256, 1024, 4096, 16384])
axes.grid(color='b', alpha=0.5, linestyle='dashed', linewidth=0.5)
plt.show() plt.show()

View File

@ -135,7 +135,8 @@
`define BTB_SIZE 10 `define BTB_SIZE 10
`define HPTW_WRITES_SUPPORTED 1 `define SVADU_SUPPORTED 1
`define ZMMUL_SUPPORTED 0
// FPU division architecture // FPU division architecture
`define RADIX 32'h4 `define RADIX 32'h4

View File

@ -144,7 +144,8 @@
`define BTB_SIZE 10 `define BTB_SIZE 10
`define HPTW_WRITES_SUPPORTED 1 `define SVADU_SUPPORTED 1
`define ZMMUL_SUPPORTED 0
// FPU division architecture // FPU division architecture
`define RADIX 32'h4 `define RADIX 32'h4

View File

@ -138,7 +138,8 @@
`define BPRED_SIZE 10 `define BPRED_SIZE 10
`define BTB_SIZE 10 `define BTB_SIZE 10
`define HPTW_WRITES_SUPPORTED 0 `define SVADU_SUPPORTED 0
`define ZMMUL_SUPPORTED 0
// FPU division architecture // FPU division architecture
`define RADIX 32'h4 `define RADIX 32'h4

View File

@ -137,7 +137,8 @@
`define BPRED_SIZE 10 `define BPRED_SIZE 10
`define BTB_SIZE 10 `define BTB_SIZE 10
`define HPTW_WRITES_SUPPORTED 0 `define SVADU_SUPPORTED 0
`define ZMMUL_SUPPORTED 0
// FPU division architecture // FPU division architecture
`define RADIX 32'h4 `define RADIX 32'h4

View File

@ -138,7 +138,8 @@
`define BPRED_SIZE 10 `define BPRED_SIZE 10
`define BTB_SIZE 10 `define BTB_SIZE 10
`define HPTW_WRITES_SUPPORTED 0 `define SVADU_SUPPORTED 0
`define ZMMUL_SUPPORTED 0
// FPU division architecture // FPU division architecture
`define RADIX 32'h4 `define RADIX 32'h4

View File

@ -137,7 +137,8 @@
`define BPRED_SIZE 10 `define BPRED_SIZE 10
`define BTB_SIZE 10 `define BTB_SIZE 10
`define HPTW_WRITES_SUPPORTED 0 `define SVADU_SUPPORTED 0
`define ZMMUL_SUPPORTED 0
// FPU division architecture // FPU division architecture
`define RADIX 32'h4 `define RADIX 32'h4

View File

@ -140,7 +140,8 @@
`define BPRED_SIZE 10 `define BPRED_SIZE 10
`define BTB_SIZE 10 `define BTB_SIZE 10
`define HPTW_WRITES_SUPPORTED 0 `define SVADU_SUPPORTED 0
`define ZMMUL_SUPPORTED 0
// FPU division architecture // FPU division architecture
`define RADIX 32'h4 `define RADIX 32'h4

View File

@ -140,7 +140,8 @@
`define BPRED_SIZE 10 `define BPRED_SIZE 10
`define BTB_SIZE 10 `define BTB_SIZE 10
`define HPTW_WRITES_SUPPORTED 0 `define SVADU_SUPPORTED 0
`define ZMMUL_SUPPORTED 0
// FPU division architecture // FPU division architecture
`define RADIX 32'h4 `define RADIX 32'h4

View File

@ -140,7 +140,8 @@
`define BPRED_SIZE 10 `define BPRED_SIZE 10
`define BTB_SIZE 10 `define BTB_SIZE 10
`define HPTW_WRITES_SUPPORTED 0 `define SVADU_SUPPORTED 0
`define ZMMUL_SUPPORTED 0
// FPU division architecture // FPU division architecture
`define RADIX 32'h4 `define RADIX 32'h4

View File

@ -162,14 +162,14 @@ module controller(
ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // Non-implemented instruction ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // Non-implemented instruction
7'b0110011: if (Funct7D == 7'b0000000 | Funct7D == 7'b0100000 | ((`ZBB_SUPPORTED & BSelectD[2]) | (`ZBC_SUPPORTED & BSelectD[1]) | (`ZBS_SUPPORTED & BSelectD[0]) | (`ZBA_SUPPORTED & BSelectD[3]))) 7'b0110011: if (Funct7D == 7'b0000000 | Funct7D == 7'b0100000 | ((`ZBB_SUPPORTED & BSelectD[2]) | (`ZBC_SUPPORTED & BSelectD[1]) | (`ZBS_SUPPORTED & BSelectD[0]) | (`ZBA_SUPPORTED & BSelectD[3])))
ControlsD = `CTRLW'b1_000_00_00_000_0_1_0_0_0_0_0_0_0_00_0; // R-type ControlsD = `CTRLW'b1_000_00_00_000_0_1_0_0_0_0_0_0_0_00_0; // R-type
else if (Funct7D == 7'b0000001 & `M_SUPPORTED) else if (Funct7D == 7'b0000001 & (`M_SUPPORTED | (`ZMMUL_SUPPORTED & ~Funct3D[2])))
ControlsD = `CTRLW'b1_000_00_00_011_0_0_0_0_0_0_0_0_1_00_0; // Multiply/divide ControlsD = `CTRLW'b1_000_00_00_011_0_0_0_0_0_0_0_0_1_00_0; // Multiply/divide
else else
ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // Non-implemented instruction ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // Non-implemented instruction
7'b0110111: ControlsD = `CTRLW'b1_100_01_00_000_0_0_0_1_0_0_0_0_0_00_0; // lui 7'b0110111: ControlsD = `CTRLW'b1_100_01_00_000_0_0_0_1_0_0_0_0_0_00_0; // lui
7'b0111011: if ((Funct7D == 7'b0000000 | Funct7D == 7'b0100000 | (`ZBA_SUPPORTED & BSelectD[3]) | (`ZBB_SUPPORTED & BSelectD[2])) & `XLEN == 64) 7'b0111011: if ((Funct7D == 7'b0000000 | Funct7D == 7'b0100000 | (`ZBA_SUPPORTED & BSelectD[3]) | (`ZBB_SUPPORTED & BSelectD[2])) & `XLEN == 64)
ControlsD = `CTRLW'b1_000_00_00_000_0_1_0_0_1_0_0_0_0_00_0; // R-type W instructions for RV64i ControlsD = `CTRLW'b1_000_00_00_000_0_1_0_0_1_0_0_0_0_00_0; // R-type W instructions for RV64i
else if (Funct7D == 7'b0000001 & `M_SUPPORTED & `XLEN == 64) else if (Funct7D == 7'b0000001 & (`M_SUPPORTED | (`ZMMUL_SUPPORTED & ~Funct3D[2])) & `XLEN == 64)
ControlsD = `CTRLW'b1_000_00_00_011_0_0_0_0_1_0_0_0_1_00_0; // W-type Multiply/Divide ControlsD = `CTRLW'b1_000_00_00_011_0_0_0_0_1_0_0_0_1_00_0; // W-type Multiply/Divide
else else
ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // Non-implemented instruction ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // Non-implemented instruction

View File

@ -33,10 +33,10 @@ module RASPredictor #(parameter int StackSize = 16 )(
input logic clk, input logic clk,
input logic reset, input logic reset,
input logic StallF, StallD, StallE, StallM, FlushD, FlushE, FlushM, input logic StallF, StallD, StallE, StallM, FlushD, FlushE, FlushM,
input logic [3:0] WrongPredInstrClassD, // Prediction class is wrong input logic WrongBPRetD, // Prediction class is wrong
input logic [3:0] InstrClassD, input logic RetD,
input logic [3:0] InstrClassE, // Instr class input logic RetE, JalE, // Instr class
input logic [3:0] PredInstrClassF, input logic BPRetF,
input logic [`XLEN-1:0] PCLinkE, // PC of instruction after a jal input logic [`XLEN-1:0] PCLinkE, // PC of instruction after a jal
output logic [`XLEN-1:0] RASPCF // Top of the stack output logic [`XLEN-1:0] RASPCF // Top of the stack
); );
@ -58,17 +58,17 @@ module RASPredictor #(parameter int StackSize = 16 )(
logic WrongPredRetD; logic WrongPredRetD;
assign PopF = PredInstrClassF[2] & ~StallD & ~FlushD; assign PopF = BPRetF & ~StallD & ~FlushD;
assign PushE = InstrClassE[3] & ~StallM & ~FlushM; assign PushE = JalE & ~StallM & ~FlushM;
assign WrongPredRetD = (WrongPredInstrClassD[2]) & ~StallE & ~FlushE; assign WrongPredRetD = (WrongBPRetD) & ~StallE & ~FlushE;
assign FlushedRetDE = (~StallE & FlushE & InstrClassD[2]) | (~StallM & FlushM & InstrClassE[2]); // flushed ret assign FlushedRetDE = (~StallE & FlushE & RetD) | (~StallM & FlushM & RetE); // flushed ret
assign RepairD = WrongPredRetD | FlushedRetDE ; assign RepairD = WrongPredRetD | FlushedRetDE ;
assign IncrRepairD = FlushedRetDE | (WrongPredRetD & ~InstrClassD[2]); // Guessed it was a ret, but its not assign IncrRepairD = FlushedRetDE | (WrongPredRetD & ~RetD); // Guessed it was a ret, but its not
assign DecRepairD = WrongPredRetD & InstrClassD[2]; // Guessed non ret but is a ret. assign DecRepairD = WrongPredRetD & RetD; // Guessed non ret but is a ret.
assign CounterEn = PopF | PushE | RepairD; assign CounterEn = PopF | PushE | RepairD;

View File

@ -72,15 +72,12 @@ module bpred (
logic [1:0] DirPredictionF; logic [1:0] DirPredictionF;
logic [3:0] BTBPredInstrClassF, PredInstrClassF, PredInstrClassD;
logic [`XLEN-1:0] BTAF, RASPCF; logic [`XLEN-1:0] BTAF, RASPCF;
logic PredictionPCWrongE; logic PredictionPCWrongE;
logic AnyWrongPredInstrClassD, AnyWrongPredInstrClassE; logic AnyWrongPredInstrClassD, AnyWrongPredInstrClassE;
logic [3:0] InstrClassD;
logic [3:0] InstrClassE;
logic DirPredictionWrongE; logic DirPredictionWrongE;
logic SelBPPredF; logic BPPCSrcF;
logic [`XLEN-1:0] BPPredPCF; logic [`XLEN-1:0] BPPredPCF;
logic [`XLEN-1:0] PCNext0F; logic [`XLEN-1:0] PCNext0F;
logic [`XLEN-1:0] PCCorrectE; logic [`XLEN-1:0] PCCorrectE;
@ -91,34 +88,45 @@ module bpred (
logic [`XLEN-1:0] BTAD; logic [`XLEN-1:0] BTAD;
logic BTBJalF, BTBRetF, BTBJumpF, BTBBranchF;
logic BPBranchF, BPJumpF, BPRetF, BPJalF;
logic BPBranchD, BPJumpD, BPRetD, BPJalD;
logic RetD, JalD;
logic RetE, JalE;
logic BranchM, JumpM, RetM, JalM;
logic BranchW, JumpW, RetW, JalW;
logic WrongBPRetD;
logic [`XLEN-1:0] PCW, IEUAdrW;
// Part 1 branch direction prediction // Part 1 branch direction prediction
// look into the 2 port Sram model. something is wrong. // look into the 2 port Sram model. something is wrong.
if (`BPRED_TYPE == "BP_TWOBIT") begin:Predictor if (`BPRED_TYPE == "BP_TWOBIT") begin:Predictor
twoBitPredictor #(`BPRED_SIZE) DirPredictor(.clk, .reset, .StallF, .StallD, .StallE, .StallM, .FlushD, .FlushE, .FlushM, twoBitPredictor #(`BPRED_SIZE) DirPredictor(.clk, .reset, .StallF, .StallD, .StallE, .StallM, .StallW,
.FlushD, .FlushE, .FlushM, .FlushW,
.PCNextF, .PCM, .DirPredictionF, .DirPredictionWrongE, .PCNextF, .PCM, .DirPredictionF, .DirPredictionWrongE,
.BranchInstrE(InstrClassE[0]), .BranchInstrM(InstrClassM[0]), .PCSrcE); .BranchE, .BranchM, .PCSrcE);
end else if (`BPRED_TYPE == "BP_GSHARE") begin:Predictor end else if (`BPRED_TYPE == "BP_GSHARE") begin:Predictor
gshare #(`BPRED_SIZE) DirPredictor(.clk, .reset, .StallF, .StallD, .StallE, .StallM, .StallW, .FlushD, .FlushE, .FlushM, .FlushW, gshare #(`BPRED_SIZE) DirPredictor(.clk, .reset, .StallF, .StallD, .StallE, .StallM, .StallW, .FlushD, .FlushE, .FlushM, .FlushW,
.PCNextF, .PCF, .PCD, .PCE, .PCM, .DirPredictionF, .DirPredictionWrongE, .PCNextF, .PCF, .PCD, .PCE, .PCM, .PCW, .DirPredictionF, .DirPredictionWrongE,
.BranchInstrF(PredInstrClassF[0]), .BranchInstrD(InstrClassD[0]), .BranchInstrE(InstrClassE[0]), .BranchInstrM(InstrClassM[0]), .BPBranchF, .BranchD, .BranchE, .BranchM, .BranchW,
.PCSrcE); .PCSrcE);
end else if (`BPRED_TYPE == "BP_GLOBAL") begin:Predictor end else if (`BPRED_TYPE == "BP_GLOBAL") begin:Predictor
gshare #(`BPRED_SIZE, 0) DirPredictor(.clk, .reset, .StallF, .StallD, .StallE, .StallM, .StallW, .FlushD, .FlushE, .FlushM, .FlushW, gshare #(`BPRED_SIZE, 0) DirPredictor(.clk, .reset, .StallF, .StallD, .StallE, .StallM, .StallW, .FlushD, .FlushE, .FlushM, .FlushW,
.PCNextF, .PCF, .PCD, .PCE, .PCM, .DirPredictionF, .DirPredictionWrongE, .PCNextF, .PCF, .PCD, .PCE, .PCM, .PCW, .DirPredictionF, .DirPredictionWrongE,
.BranchInstrF(PredInstrClassF[0]), .BranchInstrD(InstrClassD[0]), .BranchInstrE(InstrClassE[0]), .BranchInstrM(InstrClassM[0]), .BPBranchF, .BranchD, .BranchE, .BranchM, .BranchW,
.PCSrcE); .PCSrcE);
end else if (`BPRED_TYPE == "BP_GSHARE_BASIC") begin:Predictor end else if (`BPRED_TYPE == "BP_GSHARE_BASIC") begin:Predictor
gsharebasic #(`BPRED_SIZE) DirPredictor(.clk, .reset, .StallF, .StallD, .StallE, .StallM, .StallW, .FlushD, .FlushE, .FlushM, .FlushW, gsharebasic #(`BPRED_SIZE) DirPredictor(.clk, .reset, .StallF, .StallD, .StallE, .StallM, .StallW, .FlushD, .FlushE, .FlushM, .FlushW,
.PCNextF, .PCM, .DirPredictionF, .DirPredictionWrongE, .PCNextF, .PCM, .DirPredictionF, .DirPredictionWrongE,
.BranchInstrE(InstrClassE[0]), .BranchInstrM(InstrClassM[0]), .PCSrcE); .BranchE, .BranchM, .PCSrcE);
end else if (`BPRED_TYPE == "BP_GLOBAL_BASIC") begin:Predictor end else if (`BPRED_TYPE == "BP_GLOBAL_BASIC") begin:Predictor
gsharebasic #(`BPRED_SIZE, 0) DirPredictor(.clk, .reset, .StallF, .StallD, .StallE, .StallM, .StallW, .FlushD, .FlushE, .FlushM, .FlushW, gsharebasic #(`BPRED_SIZE, 0) DirPredictor(.clk, .reset, .StallF, .StallD, .StallE, .StallM, .StallW, .FlushD, .FlushE, .FlushM, .FlushW,
.PCNextF, .PCM, .DirPredictionF, .DirPredictionWrongE, .PCNextF, .PCM, .DirPredictionF, .DirPredictionWrongE,
.BranchInstrE(InstrClassE[0]), .BranchInstrM(InstrClassM[0]), .PCSrcE); .BranchE, .BranchM, .PCSrcE);
end else if (`BPRED_TYPE == "BPLOCALPAg") begin:Predictor end else if (`BPRED_TYPE == "BPLOCALPAg") begin:Predictor
// *** Fix me // *** Fix me
@ -140,18 +148,21 @@ module bpred (
btb #(`BTB_SIZE) btb #(`BTB_SIZE)
TargetPredictor(.clk, .reset, .StallF, .StallD, .StallE, .StallM, .StallW, .FlushD, .FlushE, .FlushM, .FlushW, TargetPredictor(.clk, .reset, .StallF, .StallD, .StallE, .StallM, .StallW, .FlushD, .FlushE, .FlushM, .FlushW,
.PCNextF, .PCF, .PCD, .PCE, .PCM, .PCNextF, .PCF, .PCD, .PCE, .PCM, .PCW,
.BTAF, .BTAD, .BTAF, .BTAD,
.BTBPredInstrClassF, .BTBPredInstrClassF({BTBJalF, BTBRetF, BTBJumpF, BTBBranchF}),
.PredictionInstrClassWrongM, .PredictionInstrClassWrongM,
.IEUAdrE, .IEUAdrM, .IEUAdrE, .IEUAdrM, .IEUAdrW,
.InstrClassD, .InstrClassE, .InstrClassM); .InstrClassD({JalD, RetD, JumpD, BranchD}), .InstrClassE({JalE, RetE, JumpE, BranchE}), .InstrClassM({JalM, RetM, JumpM, BranchM}),
.InstrClassW({JalW, RetW, JumpW, BranchW}));
// the branch predictor needs a compact decoding of the instruction class. if (!`INSTR_CLASS_PRED) begin : DirectClassDecode
if (`INSTR_CLASS_PRED == 0) begin : DirectClassDecode // This section is mainly for testing, verification, and PPA comparison.
logic [3:0] InstrClassF; // An alternative to using the BTB to store the instruction class is to partially decode
// the instructions in the Fetch stage into, Jal, Ret, Jump, and Branch instructions.
// This logic is not described in the text book as of 23 February 2023.
logic cjal, cj, cjr, cjalr, CJumpF, CBranchF; logic cjal, cj, cjr, cjalr, CJumpF, CBranchF;
logic JumpF, BranchF; logic NCJumpF, NCBranchF;
if(`C_SUPPORTED) begin if(`C_SUPPORTED) begin
logic [4:0] CompressedOpcF; logic [4:0] CompressedOpcF;
@ -166,48 +177,44 @@ module bpred (
assign {cjal, cj, cjr, cjalr, CJumpF, CBranchF} = '0; assign {cjal, cj, cjr, cjalr, CJumpF, CBranchF} = '0;
end end
assign JumpF = PostSpillInstrRawF[6:0] == 7'h67 | PostSpillInstrRawF[6:0] == 7'h6F; assign NCJumpF = PostSpillInstrRawF[6:0] == 7'h67 | PostSpillInstrRawF[6:0] == 7'h6F;
assign BranchF = PostSpillInstrRawF[6:0] == 7'h63; assign NCBranchF = PostSpillInstrRawF[6:0] == 7'h63;
assign InstrClassF[0] = BranchF | (`C_SUPPORTED & CBranchF); assign BPBranchF = NCBranchF | (`C_SUPPORTED & CBranchF);
assign InstrClassF[1] = JumpF | (`C_SUPPORTED & (CJumpF)); assign BPJumpF = NCJumpF | (`C_SUPPORTED & (CJumpF));
assign InstrClassF[2] = (JumpF & (PostSpillInstrRawF[19:15] & 5'h1B) == 5'h01) | // return must return to ra or r5 assign BPRetF = (NCJumpF & (PostSpillInstrRawF[19:15] & 5'h1B) == 5'h01) | // return must return to ra or r5
(`C_SUPPORTED & (cjalr | cjr) & ((PostSpillInstrRawF[11:7] & 5'h1B) == 5'h01)); (`C_SUPPORTED & (cjalr | cjr) & ((PostSpillInstrRawF[11:7] & 5'h1B) == 5'h01));
assign InstrClassF[3] = (JumpF & (PostSpillInstrRawF[11:07] & 5'h1B) == 5'h01) | // jal(r) must link to ra or x5 assign BPJalF = (NCJumpF & (PostSpillInstrRawF[11:07] & 5'h1B) == 5'h01) | // jal(r) must link to ra or x5
(`C_SUPPORTED & (cjal | (cjalr & (PostSpillInstrRawF[11:7] & 5'h1b) == 5'h01))); (`C_SUPPORTED & (cjal | (cjalr & (PostSpillInstrRawF[11:7] & 5'h1b) == 5'h01)));
assign PredInstrClassF = InstrClassF;
assign SelBPPredF = (PredInstrClassF[0] & DirPredictionF[1]) |
PredInstrClassF[1];
end else begin end else begin
assign PredInstrClassF = BTBPredInstrClassF; // This section connects the BTB's instruction class prediction.
assign SelBPPredF = (PredInstrClassF[0] & DirPredictionF[1]) | assign {BPJalF, BPRetF, BPJumpF, BPBranchF} = {BTBJalF, BTBRetF, BTBJumpF, BTBBranchF};
PredInstrClassF[1];
end end
assign BPPCSrcF = (BPBranchF & DirPredictionF[1]) | BPJumpF;
// Part 3 RAS // Part 3 RAS
RASPredictor RASPredictor(.clk, .reset, .StallF, .StallD, .StallE, .StallM, .FlushD, .FlushE, .FlushM, RASPredictor RASPredictor(.clk, .reset, .StallF, .StallD, .StallE, .StallM, .FlushD, .FlushE, .FlushM,
.PredInstrClassF, .InstrClassD, .InstrClassE, .BPRetF, .RetD, .RetE, .JalE,
.WrongPredInstrClassD, .RASPCF, .PCLinkE); .WrongBPRetD, .RASPCF, .PCLinkE);
assign BPPredPCF = PredInstrClassF[2] ? RASPCF : BTAF; assign BPPredPCF = BPRetF ? RASPCF : BTAF;
assign InstrClassD[0] = BranchD; assign RetD = JumpD & (InstrD[19:15] & 5'h1B) == 5'h01; // return must return to ra or x5
assign InstrClassD[1] = JumpD ; assign JalD = JumpD & (InstrD[11:7] & 5'h1B) == 5'h01; // jal(r) must link to ra or x5
assign InstrClassD[2] = JumpD & (InstrD[19:15] & 5'h1B) == 5'h01; // return must return to ra or x5
assign InstrClassD[3] = JumpD & (InstrD[11:7] & 5'h1B) == 5'h01; // jal(r) must link to ra or x5
flopenrc #(4) InstrClassRegE(clk, reset, FlushE, ~StallE, InstrClassD, InstrClassE); flopenrc #(2) InstrClassRegE(clk, reset, FlushE, ~StallE, {JalD, RetD}, {JalE, RetE});
flopenrc #(4) InstrClassRegM(clk, reset, FlushM, ~StallM, InstrClassE, InstrClassM); flopenrc #(4) InstrClassRegM(clk, reset, FlushM, ~StallM, {JalE, RetE, JumpE, BranchE}, {JalM, RetM, JumpM, BranchM});
flopenrc #(4) InstrClassRegW(clk, reset, FlushM, ~StallW, {JalM, RetM, JumpM, BranchM}, {JalW, RetW, JumpW, BranchW});
flopenrc #(1) BPPredWrongMReg(clk, reset, FlushM, ~StallM, BPPredWrongE, BPPredWrongM); flopenrc #(1) BPPredWrongMReg(clk, reset, FlushM, ~StallM, BPPredWrongE, BPPredWrongM);
// branch predictor // branch predictor
flopenrc #(1) BPClassWrongRegM(clk, reset, FlushM, ~StallM, AnyWrongPredInstrClassE, PredictionInstrClassWrongM); flopenrc #(1) BPClassWrongRegM(clk, reset, FlushM, ~StallM, AnyWrongPredInstrClassE, PredictionInstrClassWrongM);
// pipeline the class
flopenrc #(4) PredInstrClassRegD(clk, reset, FlushD, ~StallD, PredInstrClassF, PredInstrClassD);
flopenrc #(1) WrongInstrClassRegE(clk, reset, FlushE, ~StallE, AnyWrongPredInstrClassD, AnyWrongPredInstrClassE); flopenrc #(1) WrongInstrClassRegE(clk, reset, FlushE, ~StallE, AnyWrongPredInstrClassD, AnyWrongPredInstrClassE);
// pipeline the predicted class
flopenrc #(4) PredInstrClassRegD(clk, reset, FlushD, ~StallD, {BPJalF, BPRetF, BPJumpF, BPBranchF}, {BPJalD, BPRetD, BPJumpD, BPBranchD});
// Check the prediction // Check the prediction
// if it is a CFI then check if the next instruction address (PCD) matches the branch's target or fallthrough address. // if it is a CFI then check if the next instruction address (PCD) matches the branch's target or fallthrough address.
@ -218,11 +225,10 @@ module bpred (
assign PredictionPCWrongE = PCCorrectE != PCD; assign PredictionPCWrongE = PCCorrectE != PCD;
// branch class prediction wrong. // branch class prediction wrong.
assign WrongPredInstrClassD = PredInstrClassD ^ InstrClassD[3:0]; assign AnyWrongPredInstrClassD = |({BPJalD, BPRetD, BPJumpD, BPBranchD} ^ {JalD, RetD, JumpD, BranchD});
assign AnyWrongPredInstrClassD = |WrongPredInstrClassD; assign WrongBPRetD = BPRetD ^ RetD;
// branch is wrong only if the PC does not match and both the Decode and Fetch stages have valid instructions. // branch is wrong only if the PC does not match and both the Decode and Fetch stages have valid instructions.
//assign BPPredWrongE = (PredictionPCWrongE & |InstrClassE | (AnyWrongPredInstrClassE & ~|InstrClassE));
assign BPPredWrongE = PredictionPCWrongE & InstrValidE & InstrValidD; assign BPPredWrongE = PredictionPCWrongE & InstrValidE & InstrValidD;
logic BPPredWrongEAlt; logic BPPredWrongEAlt;
@ -232,7 +238,7 @@ module bpred (
// Output the predicted PC or corrected PC on miss-predict. // Output the predicted PC or corrected PC on miss-predict.
// Selects the BP or PC+2/4. // Selects the BP or PC+2/4.
mux2 #(`XLEN) pcmux0(PCPlus2or4F, BPPredPCF, SelBPPredF, PCNext0F); mux2 #(`XLEN) pcmux0(PCPlus2or4F, BPPredPCF, BPPCSrcF, PCNext0F);
// If the prediction is wrong select the correct address. // If the prediction is wrong select the correct address.
mux2 #(`XLEN) pcmux1(PCNext0F, PCCorrectE, BPPredWrongE, PCNext1F); mux2 #(`XLEN) pcmux1(PCNext0F, PCCorrectE, BPPredWrongE, PCNext1F);
// Correct branch/jump target. // Correct branch/jump target.
@ -257,10 +263,10 @@ module bpred (
// could be wrong or the fall through address selected for branch predict not taken. // 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 // By pipeline the BTB's PC and RAS address through the pipeline we can measure the accuracy of
// both without the above inaccuracies. // both without the above inaccuracies.
assign BTBPredPCWrongE = (BTAE != IEUAdrE) & (InstrClassE[0] | InstrClassE[1] & ~InstrClassE[2]) & PCSrcE; assign BTBPredPCWrongE = (BTAE != IEUAdrE) & (BranchE | JumpE & ~RetE) & PCSrcE;
assign RASPredPCWrongE = (RASPCE != IEUAdrE) & InstrClassE[2] & PCSrcE; assign RASPredPCWrongE = (RASPCE != IEUAdrE) & RetE & PCSrcE;
assign JumpOrTakenBranchE = (InstrClassE[0] & PCSrcE) | InstrClassE[1]; assign JumpOrTakenBranchE = (BranchE & PCSrcE) | JumpE;
flopenrc #(1) JumpOrTakenBranchMReg(clk, reset, FlushM, ~StallM, JumpOrTakenBranchE, JumpOrTakenBranchM); flopenrc #(1) JumpOrTakenBranchMReg(clk, reset, FlushM, ~StallM, JumpOrTakenBranchE, JumpOrTakenBranchM);
@ -275,5 +281,11 @@ module bpred (
end else begin end else begin
assign {BTBPredPCWrongM, RASPredPCWrongM, JumpOrTakenBranchM} = '0; assign {BTBPredPCWrongM, RASPredPCWrongM, JumpOrTakenBranchM} = '0;
end end
// **** Fix me
assign InstrClassM = {JalM, RetM, JumpM, BranchM};
flopenr #(`XLEN) PCWReg(clk, reset, ~StallW, PCM, PCW);
flopenr #(`XLEN) IEUAdrWReg(clk, reset, ~StallW, IEUAdrM, IEUAdrW);
endmodule endmodule

View File

@ -34,7 +34,7 @@ module btb #(parameter Depth = 10 ) (
input logic clk, input logic clk,
input logic reset, input logic reset,
input logic StallF, StallD, StallE, StallM, StallW, FlushD, FlushE, FlushM, FlushW, input logic StallF, StallD, StallE, StallM, StallW, FlushD, FlushE, FlushM, FlushW,
input logic [`XLEN-1:0] PCNextF, PCF, PCD, PCE, PCM, // PC at various stages input logic [`XLEN-1:0] PCNextF, PCF, PCD, PCE, PCM, PCW,// PC at various stages
output logic [`XLEN-1:0] BTAF, // BTB's guess at PC output logic [`XLEN-1:0] BTAF, // BTB's guess at PC
output logic [`XLEN-1:0] BTAD, output logic [`XLEN-1:0] BTAD,
output logic [3:0] BTBPredInstrClassF, // BTB's guess at instruction class output logic [3:0] BTBPredInstrClassF, // BTB's guess at instruction class
@ -42,14 +42,16 @@ module btb #(parameter Depth = 10 ) (
input logic PredictionInstrClassWrongM, // BTB's instruction class guess was wrong input logic PredictionInstrClassWrongM, // BTB's instruction class guess was wrong
input logic [`XLEN-1:0] IEUAdrE, // Branch/jump target address to insert into btb input logic [`XLEN-1:0] IEUAdrE, // Branch/jump target address to insert into btb
input logic [`XLEN-1:0] IEUAdrM, // Branch/jump target address to insert into btb input logic [`XLEN-1:0] IEUAdrM, // Branch/jump target address to insert into btb
input logic [`XLEN-1:0] IEUAdrW,
input logic [3:0] InstrClassD, // Instruction class 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 input logic [3:0] InstrClassE, // Instruction class to insert into btb
input logic [3:0] InstrClassM // Instruction class to insert into btb input logic [3:0] InstrClassM, // Instruction class to insert into btb
input logic [3:0] InstrClassW
); );
logic [Depth-1:0] PCNextFIndex, PCFIndex, PCDIndex, PCEIndex, PCMIndex; logic [Depth-1:0] PCNextFIndex, PCFIndex, PCDIndex, PCEIndex, PCMIndex, PCWIndex;
logic [`XLEN-1:0] ResetPC; logic [`XLEN-1:0] ResetPC;
logic MatchF, MatchD, MatchE, MatchM, MatchNextX, MatchXF; logic MatchD, MatchE, MatchM, MatchW, MatchX;
logic [`XLEN+3:0] ForwardBTBPrediction, ForwardBTBPredictionF; logic [`XLEN+3:0] ForwardBTBPrediction, ForwardBTBPredictionF;
logic [`XLEN+3:0] TableBTBPredictionF; logic [`XLEN+3:0] TableBTBPredictionF;
logic UpdateEn; logic UpdateEn;
@ -62,6 +64,7 @@ module btb #(parameter Depth = 10 ) (
assign PCDIndex = {PCD[Depth+1] ^ PCD[1], PCD[Depth:2]}; assign PCDIndex = {PCD[Depth+1] ^ PCD[1], PCD[Depth:2]};
assign PCEIndex = {PCE[Depth+1] ^ PCE[1], PCE[Depth:2]}; assign PCEIndex = {PCE[Depth+1] ^ PCE[1], PCE[Depth:2]};
assign PCMIndex = {PCM[Depth+1] ^ PCM[1], PCM[Depth:2]}; assign PCMIndex = {PCM[Depth+1] ^ PCM[1], PCM[Depth:2]};
assign PCWIndex = {PCW[Depth+1] ^ PCW[1], PCW[Depth:2]};
// must output a valid PC and valid bit during reset. Because only PCF, not PCNextF is reset, PCNextF is invalid // must output a valid PC and valid bit during reset. Because only PCF, not PCNextF is reset, PCNextF is invalid
// during reset. The BTB must produce a non X PC1NextF to allow the simulation to run. // during reset. The BTB must produce a non X PC1NextF to allow the simulation to run.
@ -70,23 +73,18 @@ module btb #(parameter Depth = 10 ) (
assign ResetPC = `RESET_VECTOR; assign ResetPC = `RESET_VECTOR;
assign PCNextFIndex = reset ? ResetPC[Depth+1:2] : {PCNextF[Depth+1] ^ PCNextF[1], PCNextF[Depth:2]}; assign PCNextFIndex = reset ? ResetPC[Depth+1:2] : {PCNextF[Depth+1] ^ PCNextF[1], PCNextF[Depth:2]};
assign MatchF = PCNextFIndex == PCFIndex; assign MatchD = PCFIndex == PCDIndex;
assign MatchD = PCNextFIndex == PCDIndex; assign MatchE = PCFIndex == PCEIndex;
assign MatchE = PCNextFIndex == PCEIndex; assign MatchM = PCFIndex == PCMIndex;
assign MatchM = PCNextFIndex == PCMIndex; assign MatchW = PCFIndex == PCWIndex;
assign MatchNextX = MatchF | MatchD | MatchE | MatchM; assign MatchX = MatchD | MatchE | MatchM | MatchW;
flopenr #(1) MatchReg(clk, reset, ~StallF, MatchNextX, MatchXF);
assign ForwardBTBPrediction = MatchF ? {BTBPredInstrClassF, BTAF} : assign ForwardBTBPredictionF = MatchD ? {InstrClassD, BTAD} :
MatchD ? {InstrClassD, BTAD} : MatchE ? {InstrClassE, IEUAdrE} :
MatchE ? {InstrClassE, IEUAdrE} : MatchM ? {InstrClassM, IEUAdrM} :
{InstrClassM, IEUAdrM} ; {InstrClassW, IEUAdrW} ;
flopenr #(`XLEN+4) ForwardBTBPredicitonReg(clk, reset, ~StallF, ForwardBTBPrediction, ForwardBTBPredictionF);
assign {BTBPredInstrClassF, BTAF} = MatchXF ? ForwardBTBPredictionF : {TableBTBPredictionF};
assign {BTBPredInstrClassF, BTAF} = MatchX ? ForwardBTBPredictionF : {TableBTBPredictionF};
assign UpdateEn = |InstrClassM | PredictionInstrClassWrongM; assign UpdateEn = |InstrClassM | PredictionInstrClassWrongM;

View File

@ -38,17 +38,17 @@ module gshare #(parameter k = 10,
output logic [1:0] DirPredictionF, output logic [1:0] DirPredictionF,
output logic DirPredictionWrongE, output logic DirPredictionWrongE,
// update // update
input logic [`XLEN-1:0] PCNextF, PCF, PCD, PCE, PCM, input logic [`XLEN-1:0] PCNextF, PCF, PCD, PCE, PCM, PCW,
input logic BranchInstrF, BranchInstrD, BranchInstrE, BranchInstrM, PCSrcE input logic BPBranchF, BranchD, BranchE, BranchM, BranchW, PCSrcE
); );
logic MatchF, MatchD, MatchE, MatchM; logic MatchF, MatchD, MatchE, MatchM, MatchW;
logic MatchNextX, MatchXF; logic MatchX;
logic [1:0] TableDirPredictionF, DirPredictionD, DirPredictionE, ForwardNewDirPrediction, ForwardDirPredictionF; logic [1:0] TableDirPredictionF, DirPredictionD, DirPredictionE, ForwardNewDirPredictionF;
logic [1:0] NewDirPredictionE, NewDirPredictionM; logic [1:0] NewDirPredictionE, NewDirPredictionM, NewDirPredictionW;
logic [k-1:0] IndexNextF, IndexF, IndexD, IndexE, IndexM; logic [k-1:0] IndexNextF, IndexF, IndexD, IndexE, IndexM, IndexW;
logic [k-1:0] GHRF, GHRD, GHRE, GHRM; logic [k-1:0] GHRF, GHRD, GHRE, GHRM;
logic [k-1:0] GHRNextM, GHRNextF; logic [k-1:0] GHRNextM, GHRNextF;
@ -68,22 +68,20 @@ module gshare #(parameter k = 10,
assign IndexM = GHRM; assign IndexM = GHRM;
end end
assign MatchF = BranchInstrF & ~FlushD & (IndexNextF == IndexF); flopenrc #(k) IndexWReg(clk, reset, FlushW, ~StallW, IndexM, IndexW);
assign MatchD = BranchInstrD & ~FlushE & (IndexNextF == IndexD);
assign MatchE = BranchInstrE & ~FlushM & (IndexNextF == IndexE);
assign MatchM = BranchInstrM & ~FlushW & (IndexNextF == IndexM);
assign MatchNextX = MatchF | MatchD | MatchE | MatchM;
flopenr #(1) MatchReg(clk, reset, ~StallF, MatchNextX, MatchXF); assign MatchD = BranchD & ~FlushE & (IndexF == IndexD);
assign MatchE = BranchE & ~FlushM & (IndexF == IndexE);
assign MatchM = BranchM & ~FlushW & (IndexF == IndexM);
assign MatchW = BranchW & ~FlushW & (IndexF == IndexW);
assign MatchX = MatchD | MatchE | MatchM | MatchW;
assign ForwardNewDirPrediction = MatchF ? {2{DirPredictionF[1]}} : assign ForwardNewDirPredictionF = MatchD ? {2{DirPredictionD[1]}} :
MatchD ? {2{DirPredictionD[1]}} :
MatchE ? {NewDirPredictionE} : MatchE ? {NewDirPredictionE} :
NewDirPredictionM ; MatchM ? {NewDirPredictionM} :
NewDirPredictionW ;
flopenr #(2) ForwardDirPredicitonReg(clk, reset, ~StallF, ForwardNewDirPrediction, ForwardDirPredictionF); assign DirPredictionF = MatchX ? ForwardNewDirPredictionF : TableDirPredictionF;
assign DirPredictionF = MatchXF ? ForwardDirPredictionF : TableDirPredictionF;
ram2p1r1wbe #(2**k, 2) PHT(.clk(clk), ram2p1r1wbe #(2**k, 2) PHT(.clk(clk),
.ce1(~StallF), .ce2(~StallM & ~FlushM), .ce1(~StallF), .ce2(~StallM & ~FlushM),
@ -91,7 +89,7 @@ module gshare #(parameter k = 10,
.rd1(TableDirPredictionF), .rd1(TableDirPredictionF),
.wa2(IndexM), .wa2(IndexM),
.wd2(NewDirPredictionM), .wd2(NewDirPredictionM),
.we2(BranchInstrM), .we2(BranchM),
.bwe2(1'b1)); .bwe2(1'b1));
flopenrc #(2) PredictionRegD(clk, reset, FlushD, ~StallD, DirPredictionF, DirPredictionD); flopenrc #(2) PredictionRegD(clk, reset, FlushD, ~StallD, DirPredictionF, DirPredictionD);
@ -99,17 +97,18 @@ module gshare #(parameter k = 10,
satCounter2 BPDirUpdateE(.BrDir(PCSrcE), .OldState(DirPredictionE), .NewState(NewDirPredictionE)); satCounter2 BPDirUpdateE(.BrDir(PCSrcE), .OldState(DirPredictionE), .NewState(NewDirPredictionE));
flopenrc #(2) NewPredictionRegM(clk, reset, FlushM, ~StallM, NewDirPredictionE, NewDirPredictionM); flopenrc #(2) NewPredictionRegM(clk, reset, FlushM, ~StallM, NewDirPredictionE, NewDirPredictionM);
flopenrc #(2) NewPredictionRegW(clk, reset, FlushW, ~StallW, NewDirPredictionM, NewDirPredictionW);
assign DirPredictionWrongE = PCSrcE != DirPredictionE[1] & BranchInstrE; assign DirPredictionWrongE = PCSrcE != DirPredictionE[1] & BranchE;
assign GHRNextF = BranchInstrF ? {DirPredictionF[1], GHRF[k-1:1]} : GHRF; assign GHRNextF = BPBranchF ? {DirPredictionF[1], GHRF[k-1:1]} : GHRF;
assign GHRF = BranchInstrD ? {DirPredictionD[1], GHRD[k-1:1]} : GHRD; assign GHRF = BranchD ? {DirPredictionD[1], GHRD[k-1:1]} : GHRD;
assign GHRD = BranchInstrE ? {PCSrcE, GHRE[k-1:1]} : GHRE; assign GHRD = BranchE ? {PCSrcE, GHRE[k-1:1]} : GHRE;
assign GHRE = BranchInstrM ? {PCSrcM, GHRM[k-1:1]} : GHRM; assign GHRE = BranchM ? {PCSrcM, GHRM[k-1:1]} : GHRM;
assign GHRNextM = {PCSrcM, GHRM[k-1:1]}; assign GHRNextM = {PCSrcM, GHRM[k-1:1]};
flopenr #(k) GHRReg(clk, reset, ~StallW & ~FlushW & BranchInstrM, GHRNextM, GHRM); flopenr #(k) GHRReg(clk, reset, ~StallW & ~FlushW & BranchM, GHRNextM, GHRM);
flopenrc #(1) PCSrcMReg(clk, reset, FlushM, ~StallM, PCSrcE, PCSrcM); flopenrc #(1) PCSrcMReg(clk, reset, FlushM, ~StallM, PCSrcE, PCSrcM);
endmodule endmodule

View File

@ -39,7 +39,7 @@ module gsharebasic #(parameter k = 10,
output logic DirPredictionWrongE, output logic DirPredictionWrongE,
// update // update
input logic [`XLEN-1:0] PCNextF, PCM, input logic [`XLEN-1:0] PCNextF, PCM,
input logic BranchInstrE, BranchInstrM, PCSrcE input logic BranchE, BranchM, PCSrcE
); );
logic [k-1:0] IndexNextF, IndexM; logic [k-1:0] IndexNextF, IndexM;
@ -64,7 +64,7 @@ module gsharebasic #(parameter k = 10,
.rd1(DirPredictionF), .rd1(DirPredictionF),
.wa2(IndexM), .wa2(IndexM),
.wd2(NewDirPredictionM), .wd2(NewDirPredictionM),
.we2(BranchInstrM), .we2(BranchM),
.bwe2(1'b1)); .bwe2(1'b1));
flopenrc #(2) PredictionRegD(clk, reset, FlushD, ~StallD, DirPredictionF, DirPredictionD); flopenrc #(2) PredictionRegD(clk, reset, FlushD, ~StallD, DirPredictionF, DirPredictionD);
@ -73,10 +73,10 @@ module gsharebasic #(parameter k = 10,
satCounter2 BPDirUpdateE(.BrDir(PCSrcE), .OldState(DirPredictionE), .NewState(NewDirPredictionE)); satCounter2 BPDirUpdateE(.BrDir(PCSrcE), .OldState(DirPredictionE), .NewState(NewDirPredictionE));
flopenrc #(2) NewPredictionRegM(clk, reset, FlushM, ~StallM, NewDirPredictionE, NewDirPredictionM); flopenrc #(2) NewPredictionRegM(clk, reset, FlushM, ~StallM, NewDirPredictionE, NewDirPredictionM);
assign DirPredictionWrongE = PCSrcE != DirPredictionE[1] & BranchInstrE; assign DirPredictionWrongE = PCSrcE != DirPredictionE[1] & BranchE;
assign GHRNext = BranchInstrM ? {PCSrcM, GHR[k-1:1]} : GHR; assign GHRNext = BranchM ? {PCSrcM, GHR[k-1:1]} : GHR;
flopenr #(k) GHRReg(clk, reset, ~StallM & ~FlushM & BranchInstrM, GHRNext, GHR); flopenr #(k) GHRReg(clk, reset, ~StallM & ~FlushM & BranchM, GHRNext, GHR);
flopenrc #(1) PCSrcMReg(clk, reset, FlushM, ~StallM, PCSrcE, PCSrcM); flopenrc #(1) PCSrcMReg(clk, reset, FlushM, ~StallM, PCSrcE, PCSrcM);
flopenrc #(k) GHRFReg(clk, reset, FlushD, ~StallF, GHR, GHRF); flopenrc #(k) GHRFReg(clk, reset, FlushD, ~StallF, GHR, GHRF);

View File

@ -31,12 +31,12 @@
module twoBitPredictor #(parameter k = 10) ( module twoBitPredictor #(parameter k = 10) (
input logic clk, input logic clk,
input logic reset, input logic reset,
input logic StallF, StallD, StallE, StallM, input logic StallF, StallD, StallE, StallM, StallW,
input logic FlushD, FlushE, FlushM, input logic FlushD, FlushE, FlushM, FlushW,
input logic [`XLEN-1:0] PCNextF, PCM, input logic [`XLEN-1:0] PCNextF, PCM,
output logic [1:0] DirPredictionF, output logic [1:0] DirPredictionF,
output logic DirPredictionWrongE, output logic DirPredictionWrongE,
input logic BranchInstrE, BranchInstrM, input logic BranchE, BranchM,
input logic PCSrcE input logic PCSrcE
); );
@ -55,18 +55,18 @@ module twoBitPredictor #(parameter k = 10) (
ram2p1r1wbe #(2**k, 2) PHT(.clk(clk), ram2p1r1wbe #(2**k, 2) PHT(.clk(clk),
.ce1(~StallF), .ce2(~StallM & ~FlushM), .ce1(~StallF), .ce2(~StallW & ~FlushW),
.ra1(IndexNextF), .ra1(IndexNextF),
.rd1(DirPredictionF), .rd1(DirPredictionF),
.wa2(IndexM), .wa2(IndexM),
.wd2(NewDirPredictionM), .wd2(NewDirPredictionM),
.we2(BranchInstrM & ~StallM & ~FlushM), .we2(BranchM),
.bwe2(1'b1)); .bwe2(1'b1));
flopenrc #(2) PredictionRegD(clk, reset, FlushD, ~StallD, DirPredictionF, DirPredictionD); flopenrc #(2) PredictionRegD(clk, reset, FlushD, ~StallD, DirPredictionF, DirPredictionD);
flopenrc #(2) PredictionRegE(clk, reset, FlushE, ~StallE, DirPredictionD, DirPredictionE); flopenrc #(2) PredictionRegE(clk, reset, FlushE, ~StallE, DirPredictionD, DirPredictionE);
assign DirPredictionWrongE = PCSrcE != DirPredictionE[1] & BranchInstrE; assign DirPredictionWrongE = PCSrcE != DirPredictionE[1] & BranchE;
satCounter2 BPDirUpdateE(.BrDir(PCSrcE), .OldState(DirPredictionE), .NewState(NewDirPredictionE)); satCounter2 BPDirUpdateE(.BrDir(PCSrcE), .OldState(DirPredictionE), .NewState(NewDirPredictionE));
flopenrc #(2) NewPredictionRegM(clk, reset, FlushM, ~StallM, NewDirPredictionE, NewDirPredictionM); flopenrc #(2) NewPredictionRegM(clk, reset, FlushM, ~StallM, NewDirPredictionE, NewDirPredictionM);

View File

@ -88,7 +88,7 @@ module ifu (
input logic [1:0] STATUS_MPP, // Status CSR: previous machine privilege level input logic [1:0] STATUS_MPP, // Status CSR: previous machine privilege level
input logic sfencevmaM, // Virtual memory address fence, invalidate TLB entries input logic sfencevmaM, // Virtual memory address fence, invalidate TLB entries
output logic ITLBMissF, // ITLB miss causes HPTW (hardware pagetable walker) walk output logic ITLBMissF, // ITLB miss causes HPTW (hardware pagetable walker) walk
output logic InstrDAPageFaultF, // ITLB hit needs to update dirty or access bits output logic InstrUpdateDAF, // ITLB hit needs to update dirty or access bits
input var logic [7:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES-1:0], // PMP configuration from privileged unit input var logic [7:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES-1:0], // PMP configuration from privileged unit
input var logic [`XLEN-1:0] PMPADDR_ARRAY_REGW[`PMP_ENTRIES-1:0], // PMP address from privileged unit input var logic [`XLEN-1:0] PMPADDR_ARRAY_REGW[`PMP_ENTRIES-1:0], // PMP address from privileged unit
output logic InstrAccessFaultF, // Instruction access fault output logic InstrAccessFaultF, // Instruction access fault
@ -145,7 +145,7 @@ module ifu (
if(`C_SUPPORTED) begin : Spill if(`C_SUPPORTED) begin : Spill
spill #(`ICACHE_SUPPORTED) spill(.clk, .reset, .StallD, .FlushD, .PCF, .PCPlus4F, .PCNextF, .InstrRawF, spill #(`ICACHE_SUPPORTED) spill(.clk, .reset, .StallD, .FlushD, .PCF, .PCPlus4F, .PCNextF, .InstrRawF,
.InstrDAPageFaultF, .IFUCacheBusStallD, .ITLBMissF, .PCNextFSpill, .PCFSpill, .SelNextSpillF, .PostSpillInstrRawF, .CompressedF); .InstrUpdateDAF, .IFUCacheBusStallD, .ITLBMissF, .PCNextFSpill, .PCFSpill, .SelNextSpillF, .PostSpillInstrRawF, .CompressedF);
end else begin : NoSpill end else begin : NoSpill
assign PCNextFSpill = PCNextF; assign PCNextFSpill = PCNextF;
assign PCFSpill = PCF; assign PCFSpill = PCF;
@ -185,12 +185,12 @@ module ifu (
.InstrAccessFaultF, .LoadAccessFaultM(), .StoreAmoAccessFaultM(), .InstrAccessFaultF, .LoadAccessFaultM(), .StoreAmoAccessFaultM(),
.InstrPageFaultF, .LoadPageFaultM(), .StoreAmoPageFaultM(), .InstrPageFaultF, .LoadPageFaultM(), .StoreAmoPageFaultM(),
.LoadMisalignedFaultM(), .StoreAmoMisalignedFaultM(), .LoadMisalignedFaultM(), .StoreAmoMisalignedFaultM(),
.DAPageFault(InstrDAPageFaultF), .UpdateDA(InstrUpdateDAF),
.AtomicAccessM(1'b0),.ExecuteAccessF(1'b1), .WriteAccessM(1'b0), .ReadAccessM(1'b0), .AtomicAccessM(1'b0),.ExecuteAccessF(1'b1), .WriteAccessM(1'b0), .ReadAccessM(1'b0),
.PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW); .PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW);
end else begin end else begin
assign {ITLBMissF, InstrAccessFaultF, InstrPageFaultF, InstrDAPageFaultF} = '0; assign {ITLBMissF, InstrAccessFaultF, InstrPageFaultF, InstrUpdateDAF} = '0;
assign PCPF = PCFExt[`PA_BITS-1:0]; assign PCPF = PCFExt[`PA_BITS-1:0];
assign CacheableF = '1; assign CacheableF = '1;
assign SelIROM = '0; assign SelIROM = '0;

View File

@ -42,7 +42,7 @@ module spill #(
input logic [31:0] InstrRawF, // Instruction from the IROM, I$, or bus. Used to check if the instruction if compressed input logic [31:0] InstrRawF, // Instruction from the IROM, I$, or bus. Used to check if the instruction if compressed
input logic IFUCacheBusStallD, // I$ or bus are stalled. Transition to second fetch of spill after the first is fetched input logic IFUCacheBusStallD, // I$ or bus are stalled. Transition to second fetch of spill after the first is fetched
input logic ITLBMissF, // ITLB miss, ignore memory request input logic ITLBMissF, // ITLB miss, ignore memory request
input logic InstrDAPageFaultF, // Ignore memory request if the hptw support write and a DA page fault occurs (hptw is still active) input logic InstrUpdateDAF, // Ignore memory request if the hptw support write and a DA page fault occurs (hptw is still active)
output logic [`XLEN-1:0] PCNextFSpill, // The next PCF for one of the two memory addresses of the spill output logic [`XLEN-1:0] PCNextFSpill, // The next PCF for one of the two memory addresses of the spill
output logic [`XLEN-1:0] PCFSpill, // PCF for one of the two memory addresses of the spill output logic [`XLEN-1:0] PCFSpill, // PCF for one of the two memory addresses of the spill
output logic SelNextSpillF, // During the transition between the two spill operations, the IFU should stall the pipeline output logic SelNextSpillF, // During the transition between the two spill operations, the IFU should stall the pipeline
@ -77,7 +77,7 @@ module spill #(
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
assign SpillF = &PCF[$clog2(SPILLTHRESHOLD)+1:1]; assign SpillF = &PCF[$clog2(SPILLTHRESHOLD)+1:1];
assign TakeSpillF = SpillF & ~IFUCacheBusStallD & ~(ITLBMissF | (`HPTW_WRITES_SUPPORTED & InstrDAPageFaultF)); assign TakeSpillF = SpillF & ~IFUCacheBusStallD & ~(ITLBMissF | (`SVADU_SUPPORTED & InstrUpdateDAF));
always_ff @(posedge clk) always_ff @(posedge clk)
if (reset | FlushD) CurrState <= #1 STATE_READY; if (reset | FlushD) CurrState <= #1 STATE_READY;

View File

@ -81,7 +81,7 @@ module lsu (
input logic [1:0] STATUS_MPP, // Machine previous privilege mode input logic [1:0] STATUS_MPP, // Machine previous privilege mode
input logic [`XLEN-1:0] PCFSpill, // Fetch PC input logic [`XLEN-1:0] PCFSpill, // Fetch PC
input logic ITLBMissF, // ITLB miss causes HPTW (hardware pagetable walker) walk input logic ITLBMissF, // ITLB miss causes HPTW (hardware pagetable walker) walk
input logic InstrDAPageFaultF, // ITLB hit needs to update dirty or access bits input logic InstrUpdateDAF, // ITLB hit needs to update dirty or access bits
output logic [`XLEN-1:0] PTE, // Page table entry write to ITLB output logic [`XLEN-1:0] PTE, // Page table entry write to ITLB
output logic [1:0] PageType, // Type of page table entry to write to ITLB output logic [1:0] PageType, // Type of page table entry to write to ITLB
output logic ITLBWriteF, // Write PTE to ITLB output logic ITLBWriteF, // Write PTE to ITLB
@ -127,7 +127,7 @@ module lsu (
logic DTLBMissM; // DTLB miss causes HPTW walk logic DTLBMissM; // DTLB miss causes HPTW walk
logic DTLBWriteM; // Writes PTE and PageType to DTLB logic DTLBWriteM; // Writes PTE and PageType to DTLB
logic DataDAPageFaultM; // DTLB hit needs to update dirty or access bits logic DataUpdateDAM; // DTLB hit needs to update dirty or access bits
logic LSULoadAccessFaultM; // Load acces fault logic LSULoadAccessFaultM; // Load acces fault
logic LSUStoreAmoAccessFaultM; // Store access fault logic LSUStoreAmoAccessFaultM; // Store access fault
logic IgnoreRequestTLB; // On either ITLB or DTLB miss, ignore miss so HPTW can handle logic IgnoreRequestTLB; // On either ITLB or DTLB miss, ignore miss so HPTW can handle
@ -151,7 +151,7 @@ module lsu (
if(`VIRTMEM_SUPPORTED) begin : VIRTMEM_SUPPORTED if(`VIRTMEM_SUPPORTED) begin : VIRTMEM_SUPPORTED
hptw hptw(.clk, .reset, .MemRWM, .AtomicM, .ITLBMissF, .ITLBWriteF, hptw hptw(.clk, .reset, .MemRWM, .AtomicM, .ITLBMissF, .ITLBWriteF,
.DTLBMissM, .DTLBWriteM, .InstrDAPageFaultF, .DataDAPageFaultM, .DTLBMissM, .DTLBWriteM, .InstrUpdateDAF, .DataUpdateDAM,
.FlushW, .DCacheStallM, .SATP_REGW, .PCFSpill, .FlushW, .DCacheStallM, .SATP_REGW, .PCFSpill,
.STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, .PrivilegeModeW, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, .PrivilegeModeW,
.ReadDataM(ReadDataM[`XLEN-1:0]), // ReadDataM is LLEN, but HPTW only needs XLEN .ReadDataM(ReadDataM[`XLEN-1:0]), // ReadDataM is LLEN, but HPTW only needs XLEN
@ -196,7 +196,7 @@ module lsu (
.StoreAmoAccessFaultM(LSUStoreAmoAccessFaultM), .InstrPageFaultF(), .LoadPageFaultM, .StoreAmoAccessFaultM(LSUStoreAmoAccessFaultM), .InstrPageFaultF(), .LoadPageFaultM,
.StoreAmoPageFaultM, .StoreAmoPageFaultM,
.LoadMisalignedFaultM, .StoreAmoMisalignedFaultM, // *** these faults need to be supressed during hptw. .LoadMisalignedFaultM, .StoreAmoMisalignedFaultM, // *** these faults need to be supressed during hptw.
.DAPageFault(DataDAPageFaultM), .UpdateDA(DataUpdateDAM),
.AtomicAccessM(|LSUAtomicM), .ExecuteAccessF(1'b0), .AtomicAccessM(|LSUAtomicM), .ExecuteAccessF(1'b0),
.WriteAccessM(PreLSURWM[0]), .ReadAccessM(PreLSURWM[1]), .WriteAccessM(PreLSURWM[0]), .ReadAccessM(PreLSURWM[1]),
.PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW); .PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW);

View File

@ -51,16 +51,18 @@ module mdu(
// Divider // Divider
// Start a divide when a new division instruction is received and the divider isn't already busy or finishing // Start a divide when a new division instruction is received and the divider isn't already busy or finishing
// When IDIV_ON_FPU is set, use the FPU divider instead // When IDIV_ON_FPU is set, use the FPU divider instead
if (`IDIV_ON_FPU) begin // In ZMMUL, with M_SUPPORTED = 0, omit the divider
if ((`IDIV_ON_FPU) || (!`M_SUPPORTED)) begin:nodiv
assign QuotM = 0; assign QuotM = 0;
assign RemM = 0; assign RemM = 0;
assign DivBusyE = 0; assign DivBusyE = 0;
end else begin end else begin:div
intdivrestoring div(.clk, .reset, .StallM, .FlushE, .DivSignedE(~Funct3E[0]), .W64E, .IntDivE, intdivrestoring div(.clk, .reset, .StallM, .FlushE, .DivSignedE(~Funct3E[0]), .W64E, .IntDivE,
.ForwardedSrcAE, .ForwardedSrcBE, .DivBusyE, .QuotM, .RemM); .ForwardedSrcAE, .ForwardedSrcBE, .DivBusyE, .QuotM, .RemM);
end end
// Result multiplexer // Result multiplexer
// For ZMMUL, QuotM and RemM are tied to 0, so the mux automatically simplifies
always_comb always_comb
case (Funct3M) case (Funct3M)
3'b000: PrelimResultM = ProdM[`XLEN-1:0]; // mul 3'b000: PrelimResultM = ProdM[`XLEN-1:0]; // mul

View File

@ -49,8 +49,8 @@ module hptw (
input logic ITLBMissF, input logic ITLBMissF,
input logic DTLBMissM, input logic DTLBMissM,
input logic FlushW, input logic FlushW,
input logic InstrDAPageFaultF, input logic InstrUpdateDAF,
input logic DataDAPageFaultM, input logic DataUpdateDAM,
output logic [`XLEN-1:0] PTE, // page table entry to TLBs output logic [`XLEN-1:0] PTE, // page table entry to TLBs
output logic [1:0] PageType, // page type to TLBs output logic [1:0] PageType, // page type to TLBs
output logic ITLBWriteF, DTLBWriteM, // write TLB with new entry output logic ITLBWriteF, DTLBWriteM, // write TLB with new entry
@ -87,21 +87,23 @@ module hptw (
logic [`XLEN-1:0] TranslationVAdr; logic [`XLEN-1:0] TranslationVAdr;
logic [`XLEN-1:0] NextPTE; logic [`XLEN-1:0] NextPTE;
logic UpdatePTE; logic UpdatePTE;
logic DAPageFault; logic HPTWUpdateDA;
logic [`PA_BITS-1:0] HPTWReadAdr; logic [`PA_BITS-1:0] HPTWReadAdr;
logic SelHPTWAdr; logic SelHPTWAdr;
logic [`XLEN+1:0] HPTWAdrExt; logic [`XLEN+1:0] HPTWAdrExt;
logic ITLBMissOrDAFaultF; logic ITLBMissOrDAFaultF;
logic DTLBMissOrDAFaultM; logic DTLBMissOrDAFaultM;
logic LSUAccessFaultM;
logic [`PA_BITS-1:0] HPTWAdr; logic [`PA_BITS-1:0] HPTWAdr;
logic [1:0] HPTWRW; logic [1:0] HPTWRW;
logic [2:0] HPTWSize; // 32 or 64 bit access logic [2:0] HPTWSize; // 32 or 64 bit access
statetype WalkerState, NextWalkerState, InitialWalkerState; statetype WalkerState, NextWalkerState, InitialWalkerState;
// map hptw access faults onto either the original LSU load/store fault or instruction access fault // map hptw access faults onto either the original LSU load/store fault or instruction access fault
assign LoadAccessFaultM = WalkerState == IDLE ? LSULoadAccessFaultM : (LSULoadAccessFaultM | LSUStoreAmoAccessFaultM) & DTLBWalk & MemRWM[1] & ~MemRWM[0]; assign LSUAccessFaultM = LSULoadAccessFaultM | LSUStoreAmoAccessFaultM;
assign StoreAmoAccessFaultM = WalkerState == IDLE ? LSUStoreAmoAccessFaultM : (LSULoadAccessFaultM | LSUStoreAmoAccessFaultM) & DTLBWalk & MemRWM[0]; assign LoadAccessFaultM = WalkerState == IDLE ? LSULoadAccessFaultM : LSUAccessFaultM & DTLBWalk & MemRWM[1] & ~MemRWM[0];
assign HPTWInstrAccessFaultM = WalkerState == IDLE ? 1'b0: (LSUStoreAmoAccessFaultM | LSULoadAccessFaultM) & ~DTLBWalk; assign StoreAmoAccessFaultM = WalkerState == IDLE ? LSUStoreAmoAccessFaultM : LSUAccessFaultM & DTLBWalk & MemRWM[0];
assign HPTWInstrAccessFaultM = WalkerState == IDLE ? 1'b0: LSUAccessFaultM & ~DTLBWalk;
// Extract bits from CSRs and inputs // Extract bits from CSRs and inputs
assign SvMode = SATP_REGW[`XLEN-1:`XLEN-`SVMODE_BITS]; assign SvMode = SATP_REGW[`XLEN-1:`XLEN-`SVMODE_BITS];
@ -125,10 +127,10 @@ module hptw (
assign ValidLeafPTE = ValidPTE & LeafPTE; assign ValidLeafPTE = ValidPTE & LeafPTE;
assign ValidNonLeafPTE = ValidPTE & ~LeafPTE; assign ValidNonLeafPTE = ValidPTE & ~LeafPTE;
if(`HPTW_WRITES_SUPPORTED) begin : hptwwrites if(`SVADU_SUPPORTED) begin : hptwwrites
logic ReadAccess, WriteAccess; logic ReadAccess, WriteAccess;
logic InvalidRead, InvalidWrite; logic InvalidRead, InvalidWrite, InvalidOp;
logic UpperBitsUnequalPageFault; logic UpperBitsUnequal;
logic OtherPageFault; logic OtherPageFault;
logic [1:0] EffectivePrivilegeMode; logic [1:0] EffectivePrivilegeMode;
logic ImproperPrivilege; logic ImproperPrivilege;
@ -147,7 +149,7 @@ module hptw (
mux2 #(`PA_BITS) HPTWWriteAdrMux(HPTWReadAdr, HPTWWriteAdr, SelHPTWWriteAdr, HPTWAdr); mux2 #(`PA_BITS) HPTWWriteAdrMux(HPTWReadAdr, HPTWWriteAdr, SelHPTWWriteAdr, HPTWAdr);
assign {Dirty, Accessed} = PTE[7:6]; assign {Dirty, Accessed} = PTE[7:6];
assign WriteAccess = MemRWM[0] | (|AtomicM); assign WriteAccess = MemRWM[0]; // implies | (|AtomicM);
assign SetDirty = ~Dirty & DTLBWalk & WriteAccess; assign SetDirty = ~Dirty & DTLBWalk & WriteAccess;
assign ReadAccess = MemRWM[1]; assign ReadAccess = MemRWM[1];
@ -157,24 +159,24 @@ module hptw (
// Check for page faults // Check for page faults
vm64check vm64check(.SATP_MODE(SATP_REGW[`XLEN-1:`XLEN-`SVMODE_BITS]), .VAdr(TranslationVAdr), vm64check vm64check(.SATP_MODE(SATP_REGW[`XLEN-1:`XLEN-`SVMODE_BITS]), .VAdr(TranslationVAdr),
.SV39Mode(), .UpperBitsUnequalPageFault); .SV39Mode(), .UpperBitsUnequal);
assign InvalidRead = ReadAccess & ~Readable & (~STATUS_MXR | ~Executable); assign InvalidRead = ReadAccess & ~Readable & (~STATUS_MXR | ~Executable);
assign InvalidWrite = WriteAccess & ~Writable; assign InvalidWrite = WriteAccess & ~Writable;
assign OtherPageFault = DTLBWalk? ImproperPrivilege | InvalidRead | InvalidWrite | UpperBitsUnequalPageFault | Misaligned | ~Valid : assign InvalidOp = DTLBWalk ? (InvalidRead | InvalidWrite) : ~Executable;
ImproperPrivilege | ~Executable | UpperBitsUnequalPageFault | Misaligned | ~Valid; assign OtherPageFault = ImproperPrivilege | InvalidOp | UpperBitsUnequal | Misaligned | ~Valid;
// hptw needs to know if there is a Dirty or Access fault occuring on this // hptw needs to know if there is a Dirty or Access fault occuring on this
// memory access. If there is the PTE needs to be updated seting Access // memory access. If there is the PTE needs to be updated seting Access
// and possibly also Dirty. Dirty is set if the operation is a store/amo. // and possibly also Dirty. Dirty is set if the operation is a store/amo.
// However any other fault should not cause the update. // However any other fault should not cause the update.
assign DAPageFault = ValidLeafPTE & (~Accessed | SetDirty) & ~OtherPageFault; assign HPTWUpdateDA = ValidLeafPTE & (~Accessed | SetDirty) & ~OtherPageFault;
assign HPTWRW[0] = (WalkerState == UPDATE_PTE); assign HPTWRW[0] = (WalkerState == UPDATE_PTE);
assign UpdatePTE = (WalkerState == LEAF) & DAPageFault; assign UpdatePTE = (WalkerState == LEAF) & HPTWUpdateDA;
end else begin // block: hptwwrites end else begin // block: hptwwrites
assign NextPTE = ReadDataM; assign NextPTE = ReadDataM;
assign HPTWAdr = HPTWReadAdr; assign HPTWAdr = HPTWReadAdr;
assign DAPageFault = '0; assign HPTWUpdateDA = '0;
assign UpdatePTE = '0; assign UpdatePTE = '0;
assign HPTWRW[0] = '0; assign HPTWRW[0] = '0;
end end
@ -182,8 +184,8 @@ module hptw (
// Enable and select signals based on states // Enable and select signals based on states
assign StartWalk = (WalkerState == IDLE) & TLBMiss; assign StartWalk = (WalkerState == IDLE) & TLBMiss;
assign HPTWRW[1] = (WalkerState == L3_RD) | (WalkerState == L2_RD) | (WalkerState == L1_RD) | (WalkerState == L0_RD); assign HPTWRW[1] = (WalkerState == L3_RD) | (WalkerState == L2_RD) | (WalkerState == L1_RD) | (WalkerState == L0_RD);
assign DTLBWriteM = (WalkerState == LEAF & ~DAPageFault) & DTLBWalk; assign DTLBWriteM = (WalkerState == LEAF & ~HPTWUpdateDA) & DTLBWalk;
assign ITLBWriteF = (WalkerState == LEAF & ~DAPageFault) & ~DTLBWalk; assign ITLBWriteF = (WalkerState == LEAF & ~HPTWUpdateDA) & ~DTLBWalk;
// FSM to track PageType based on the levels of the page table traversed // FSM to track PageType based on the levels of the page table traversed
flopr #(2) PageTypeReg(clk, reset, NextPageType, PageType); flopr #(2) PageTypeReg(clk, reset, NextPageType, PageType);
@ -262,7 +264,7 @@ module hptw (
else NextWalkerState = LEAF; else NextWalkerState = LEAF;
L0_RD: if (DCacheStallM) NextWalkerState = L0_RD; L0_RD: if (DCacheStallM) NextWalkerState = L0_RD;
else NextWalkerState = LEAF; else NextWalkerState = LEAF;
LEAF: if (`HPTW_WRITES_SUPPORTED & DAPageFault) NextWalkerState = UPDATE_PTE; LEAF: if (`SVADU_SUPPORTED & HPTWUpdateDA) NextWalkerState = UPDATE_PTE;
else NextWalkerState = IDLE; else NextWalkerState = IDLE;
UPDATE_PTE: if(DCacheStallM) NextWalkerState = UPDATE_PTE; UPDATE_PTE: if(DCacheStallM) NextWalkerState = UPDATE_PTE;
else NextWalkerState = LEAF; else NextWalkerState = LEAF;
@ -273,8 +275,8 @@ module hptw (
assign SelHPTW = WalkerState != IDLE; assign SelHPTW = WalkerState != IDLE;
assign HPTWStall = (WalkerState != IDLE) | (WalkerState == IDLE & TLBMiss); assign HPTWStall = (WalkerState != IDLE) | (WalkerState == IDLE & TLBMiss);
assign ITLBMissOrDAFaultF = ITLBMissF | (`HPTW_WRITES_SUPPORTED & InstrDAPageFaultF); assign ITLBMissOrDAFaultF = ITLBMissF | (`SVADU_SUPPORTED & InstrUpdateDAF);
assign DTLBMissOrDAFaultM = DTLBMissM | (`HPTW_WRITES_SUPPORTED & DataDAPageFaultM); assign DTLBMissOrDAFaultM = DTLBMissM | (`SVADU_SUPPORTED & DataUpdateDAM);
// HTPW address/data/control muxing // HTPW address/data/control muxing
@ -291,7 +293,7 @@ module hptw (
mux2 #(7) funct7mux(Funct7M, 7'b0, SelHPTW, LSUFunct7M); mux2 #(7) funct7mux(Funct7M, 7'b0, SelHPTW, LSUFunct7M);
mux2 #(2) atomicmux(AtomicM, 2'b00, SelHPTW, LSUAtomicM); mux2 #(2) atomicmux(AtomicM, 2'b00, SelHPTW, LSUAtomicM);
mux2 #(`XLEN+2) lsupadrmux(IEUAdrExtM, HPTWAdrExt, SelHPTWAdr, IHAdrM); mux2 #(`XLEN+2) lsupadrmux(IEUAdrExtM, HPTWAdrExt, SelHPTWAdr, IHAdrM);
if(`HPTW_WRITES_SUPPORTED) if(`SVADU_SUPPORTED)
mux2 #(`XLEN) lsuwritedatamux(WriteDataM, PTE, SelHPTW, IHWriteDataM); mux2 #(`XLEN) lsuwritedatamux(WriteDataM, PTE, SelHPTW, IHWriteDataM);
else assign IHWriteDataM = WriteDataM; else assign IHWriteDataM = WriteDataM;

View File

@ -51,7 +51,7 @@ module mmu #(parameter TLB_ENTRIES = 8, IMMU = 0) (
// Faults // Faults
output logic InstrAccessFaultF, LoadAccessFaultM, StoreAmoAccessFaultM, // access fault sources output logic InstrAccessFaultF, LoadAccessFaultM, StoreAmoAccessFaultM, // access fault sources
output logic InstrPageFaultF, LoadPageFaultM, StoreAmoPageFaultM, // page fault sources output logic InstrPageFaultF, LoadPageFaultM, StoreAmoPageFaultM, // page fault sources
output logic DAPageFault, // page fault due to setting dirty or access bit output logic UpdateDA, // page fault due to setting dirty or access bit
output logic LoadMisalignedFaultM, StoreAmoMisalignedFaultM, // misaligned fault sources output logic LoadMisalignedFaultM, StoreAmoMisalignedFaultM, // misaligned fault sources
// PMA checker signals // PMA checker signals
input logic AtomicAccessM, ExecuteAccessF, WriteAccessM, ReadAccessM, // access type input logic AtomicAccessM, ExecuteAccessF, WriteAccessM, ReadAccessM, // access type
@ -70,6 +70,7 @@ module mmu #(parameter TLB_ENTRIES = 8, IMMU = 0) (
logic Translate; // Translation occurs when virtual memory is active and DisableTranslation is off logic Translate; // Translation occurs when virtual memory is active and DisableTranslation is off
logic TLBHit; // Hit in TLB logic TLBHit; // Hit in TLB
logic TLBPageFault; // Page fault from TLB logic TLBPageFault; // Page fault from TLB
logic ReadNoAmoAccessM; // Read that is not part of atomic operation causes Load faults. Otherwise StoreAmo faults
// only instantiate TLB if Virtual Memory is supported // only instantiate TLB if Virtual Memory is supported
if (`VIRTMEM_SUPPORTED) begin:tlb if (`VIRTMEM_SUPPORTED) begin:tlb
@ -84,7 +85,7 @@ module mmu #(parameter TLB_ENTRIES = 8, IMMU = 0) (
.PrivilegeModeW, .ReadAccess, .WriteAccess, .PrivilegeModeW, .ReadAccess, .WriteAccess,
.DisableTranslation, .PTE, .PageTypeWriteVal, .DisableTranslation, .PTE, .PageTypeWriteVal,
.TLBWrite, .TLBFlush, .TLBPAdr, .TLBMiss, .TLBHit, .TLBWrite, .TLBFlush, .TLBPAdr, .TLBMiss, .TLBHit,
.Translate, .TLBPageFault, .DAPageFault); .Translate, .TLBPageFault, .UpdateDA);
end else begin:tlb// just pass address through as physical end else begin:tlb// just pass address through as physical
assign Translate = 0; assign Translate = 0;
assign TLBMiss = 0; assign TLBMiss = 0;
@ -118,11 +119,13 @@ module mmu #(parameter TLB_ENTRIES = 8, IMMU = 0) (
assign PMPLoadAccessFaultM = 0; assign PMPLoadAccessFaultM = 0;
end end
assign ReadNoAmoAccessM = ReadAccessM & ~WriteAccessM;// AMO causes StoreAmo rather than Load fault
// Access faults // Access faults
// If TLB miss and translating we want to not have faults from the PMA and PMP checkers. // If TLB miss and translating we want to not have faults from the PMA and PMP checkers.
assign InstrAccessFaultF = (PMAInstrAccessFaultF | PMPInstrAccessFaultF) & ~(Translate & ~TLBHit); assign InstrAccessFaultF = (PMAInstrAccessFaultF | PMPInstrAccessFaultF) & ~TLBMiss;
assign LoadAccessFaultM = (PMALoadAccessFaultM | PMPLoadAccessFaultM) & ~(Translate & ~TLBHit); assign LoadAccessFaultM = (PMALoadAccessFaultM | PMPLoadAccessFaultM) & ~TLBMiss;
assign StoreAmoAccessFaultM = (PMAStoreAmoAccessFaultM | PMPStoreAmoAccessFaultM) & ~(Translate & ~TLBHit); assign StoreAmoAccessFaultM = (PMAStoreAmoAccessFaultM | PMPStoreAmoAccessFaultM) & ~TLBMiss;
// Misaligned faults // Misaligned faults
always_comb always_comb
@ -132,11 +135,11 @@ module mmu #(parameter TLB_ENTRIES = 8, IMMU = 0) (
2'b10: DataMisalignedM = VAdr[1] | VAdr[0]; // lw, sw, flw, fsw, lwu 2'b10: DataMisalignedM = VAdr[1] | VAdr[0]; // lw, sw, flw, fsw, lwu
2'b11: DataMisalignedM = |VAdr[2:0]; // ld, sd, fld, fsd 2'b11: DataMisalignedM = |VAdr[2:0]; // ld, sd, fld, fsd
endcase endcase
assign LoadMisalignedFaultM = DataMisalignedM & ReadAccessM; assign LoadMisalignedFaultM = DataMisalignedM & ReadNoAmoAccessM;
assign StoreAmoMisalignedFaultM = DataMisalignedM & (WriteAccessM | AtomicAccessM); assign StoreAmoMisalignedFaultM = DataMisalignedM & WriteAccessM;
// Specify which type of page fault is occurring // Specify which type of page fault is occurring
assign InstrPageFaultF = TLBPageFault & ExecuteAccessF; assign InstrPageFaultF = TLBPageFault & ExecuteAccessF;
assign LoadPageFaultM = TLBPageFault & ReadAccessM; assign LoadPageFaultM = TLBPageFault & ReadNoAmoAccessM;
assign StoreAmoPageFaultM = TLBPageFault & (WriteAccessM | AtomicAccessM); assign StoreAmoPageFaultM = TLBPageFault & WriteAccessM;
endmodule endmodule

View File

@ -85,5 +85,9 @@ module pmpadrdec (
assign W = PMPCfg[1]; assign W = PMPCfg[1];
assign R = PMPCfg[0]; assign R = PMPCfg[0];
assign Active = |PMPCfg[4:3]; assign Active = |PMPCfg[4:3];
// known bug: The size of the access is not yet checked. For example, if an NA4 entry matches 0xC-0xF and the system
// attempts an 8-byte access to 0x8, the access should fail (see page 60 of privileged specification 20211203). This
// implementation will not detect the failure.
endmodule endmodule

View File

@ -72,7 +72,7 @@ module tlb #(parameter TLB_ENTRIES = 8, ITLB = 0) (
output logic TLBHit, output logic TLBHit,
output logic Translate, output logic Translate,
output logic TLBPageFault, output logic TLBPageFault,
output logic DAPageFault output logic UpdateDA
); );
logic [TLB_ENTRIES-1:0] Matches, WriteEnables, PTE_Gs; // used as the one-hot encoding of WriteIndex logic [TLB_ENTRIES-1:0] Matches, WriteEnables, PTE_Gs; // used as the one-hot encoding of WriteIndex
@ -105,7 +105,7 @@ module tlb #(parameter TLB_ENTRIES = 8, ITLB = 0) (
tlbcontrol #(ITLB) tlbcontrol(.SATP_MODE, .VAdr, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, tlbcontrol #(ITLB) tlbcontrol(.SATP_MODE, .VAdr, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP,
.PrivilegeModeW, .ReadAccess, .WriteAccess, .DisableTranslation, .TLBFlush, .PrivilegeModeW, .ReadAccess, .WriteAccess, .DisableTranslation, .TLBFlush,
.PTEAccessBits, .CAMHit, .Misaligned, .TLBMiss, .TLBHit, .TLBPageFault, .PTEAccessBits, .CAMHit, .Misaligned, .TLBMiss, .TLBHit, .TLBPageFault,
.DAPageFault, .SV39Mode, .Translate); .UpdateDA, .SV39Mode, .Translate);
tlblru #(TLB_ENTRIES) lru(.clk, .reset, .TLBWrite, .TLBFlush, .Matches, .CAMHit, .WriteEnables); tlblru #(TLB_ENTRIES) lru(.clk, .reset, .TLBWrite, .TLBFlush, .Matches, .CAMHit, .WriteEnables);
tlbcam #(TLB_ENTRIES, `VPN_BITS + `ASID_BITS, `VPN_SEGMENT_BITS) tlbcam #(TLB_ENTRIES, `VPN_BITS + `ASID_BITS, `VPN_SEGMENT_BITS)

View File

@ -43,7 +43,7 @@ module tlbcontrol #(parameter ITLB = 0) (
output logic TLBMiss, output logic TLBMiss,
output logic TLBHit, output logic TLBHit,
output logic TLBPageFault, output logic TLBPageFault,
output logic DAPageFault, output logic UpdateDA,
output logic SV39Mode, output logic SV39Mode,
output logic Translate output logic Translate
); );
@ -52,7 +52,7 @@ module tlbcontrol #(parameter ITLB = 0) (
logic [1:0] EffectivePrivilegeMode; logic [1:0] EffectivePrivilegeMode;
logic PTE_D, PTE_A, PTE_U, PTE_X, PTE_W, PTE_R, PTE_V; // Useful PTE Control Bits logic PTE_D, PTE_A, PTE_U, PTE_X, PTE_W, PTE_R, PTE_V; // Useful PTE Control Bits
logic UpperBitsUnequalPageFault; logic UpperBitsUnequal;
logic TLBAccess; logic TLBAccess;
logic ImproperPrivilege; logic ImproperPrivilege;
@ -64,7 +64,7 @@ module tlbcontrol #(parameter ITLB = 0) (
assign TLBAccess = ReadAccess | WriteAccess; assign TLBAccess = ReadAccess | WriteAccess;
// Check that upper bits are legal (all 0s or all 1s) // Check that upper bits are legal (all 0s or all 1s)
vm64check vm64check(.SATP_MODE, .VAdr, .SV39Mode, .UpperBitsUnequalPageFault); vm64check vm64check(.SATP_MODE, .VAdr, .SV39Mode, .UpperBitsUnequal);
// unswizzle useful PTE bits // unswizzle useful PTE bits
assign {PTE_D, PTE_A} = PTEAccessBits[7:6]; assign {PTE_D, PTE_A} = PTEAccessBits[7:6];
@ -76,13 +76,13 @@ module tlbcontrol #(parameter ITLB = 0) (
// only execute non-user mode pages. // only execute non-user mode pages.
assign ImproperPrivilege = ((EffectivePrivilegeMode == `U_MODE) & ~PTE_U) | assign ImproperPrivilege = ((EffectivePrivilegeMode == `U_MODE) & ~PTE_U) |
((EffectivePrivilegeMode == `S_MODE) & PTE_U); ((EffectivePrivilegeMode == `S_MODE) & PTE_U);
if(`HPTW_WRITES_SUPPORTED) begin : hptwwrites if(`SVADU_SUPPORTED) begin : hptwwrites
assign DAPageFault = Translate & TLBHit & ~PTE_A & ~TLBPageFault; assign UpdateDA = Translate & TLBHit & ~PTE_A & ~TLBPageFault;
assign TLBPageFault = (Translate & TLBHit & (ImproperPrivilege | ~PTE_X | UpperBitsUnequalPageFault | Misaligned | ~PTE_V)); assign TLBPageFault = Translate & TLBHit & (ImproperPrivilege | ~PTE_X | UpperBitsUnequal | Misaligned | ~PTE_V);
end else begin end else begin
// fault for software handling if access bit is off // fault for software handling if access bit is off
assign DAPageFault = ~PTE_A; assign UpdateDA = ~PTE_A;
assign TLBPageFault = (Translate & TLBHit & (ImproperPrivilege | ~PTE_X | DAPageFault | UpperBitsUnequalPageFault | Misaligned | ~PTE_V)); assign TLBPageFault = Translate & TLBHit & (ImproperPrivilege | ~PTE_X | UpdateDA | UpperBitsUnequal | Misaligned | ~PTE_V);
end end
end else begin:dtlb // Data TLB fault checking end else begin:dtlb // Data TLB fault checking
logic InvalidRead, InvalidWrite; logic InvalidRead, InvalidWrite;
@ -98,16 +98,16 @@ module tlbcontrol #(parameter ITLB = 0) (
// Check for write error. Writes are invalid when the page's write bit is // Check for write error. Writes are invalid when the page's write bit is
// low. // low.
assign InvalidWrite = WriteAccess & ~PTE_W; assign InvalidWrite = WriteAccess & ~PTE_W;
if(`HPTW_WRITES_SUPPORTED) begin : hptwwrites if(`SVADU_SUPPORTED) begin : hptwwrites
assign DAPageFault = Translate & TLBHit & (~PTE_A | WriteAccess & ~PTE_D) & ~TLBPageFault; assign UpdateDA = Translate & TLBHit & (~PTE_A | WriteAccess & ~PTE_D) & ~TLBPageFault;
assign TLBPageFault = (Translate & TLBHit & (ImproperPrivilege | InvalidRead | InvalidWrite | UpperBitsUnequalPageFault | Misaligned | ~PTE_V)); assign TLBPageFault = (Translate & TLBHit & (ImproperPrivilege | InvalidRead | InvalidWrite | UpperBitsUnequal | Misaligned | ~PTE_V));
end else begin end else begin
// Fault for software handling if access bit is off or writing a page with dirty bit off // Fault for software handling if access bit is off or writing a page with dirty bit off
assign DAPageFault = ~PTE_A | WriteAccess & ~PTE_D; assign UpdateDA = ~PTE_A | WriteAccess & ~PTE_D;
assign TLBPageFault = (Translate & TLBHit & (ImproperPrivilege | InvalidRead | InvalidWrite | DAPageFault | UpperBitsUnequalPageFault | Misaligned | ~PTE_V)); assign TLBPageFault = (Translate & TLBHit & (ImproperPrivilege | InvalidRead | InvalidWrite | UpdateDA | UpperBitsUnequal | Misaligned | ~PTE_V));
end end
end end
assign TLBHit = CAMHit & TLBAccess; assign TLBHit = CAMHit & TLBAccess;
assign TLBMiss = (~CAMHit | TLBFlush) & Translate & TLBAccess; assign TLBMiss = ~CAMHit & TLBAccess & Translate ;
endmodule endmodule

View File

@ -32,7 +32,7 @@ module vm64check (
input logic [`SVMODE_BITS-1:0] SATP_MODE, input logic [`SVMODE_BITS-1:0] SATP_MODE,
input logic [`XLEN-1:0] VAdr, input logic [`XLEN-1:0] VAdr,
output logic SV39Mode, output logic SV39Mode,
output logic UpperBitsUnequalPageFault output logic UpperBitsUnequal
); );
if (`XLEN == 64) begin if (`XLEN == 64) begin
@ -42,9 +42,9 @@ module vm64check (
logic eq_63_47, eq_46_38; logic eq_63_47, eq_46_38;
assign eq_46_38 = &(VAdr[46:38]) | ~|(VAdr[46:38]); assign eq_46_38 = &(VAdr[46:38]) | ~|(VAdr[46:38]);
assign eq_63_47 = &(VAdr[63:47]) | ~|(VAdr[63:47]); assign eq_63_47 = &(VAdr[63:47]) | ~|(VAdr[63:47]);
assign UpperBitsUnequalPageFault = SV39Mode ? ~(eq_63_47 & eq_46_38) : ~eq_63_47; assign UpperBitsUnequal = SV39Mode ? ~(eq_63_47 & eq_46_38) : ~eq_63_47;
end else begin end else begin
assign SV39Mode = 0; assign SV39Mode = 0;
assign UpperBitsUnequalPageFault = 0; assign UpperBitsUnequal = 0;
end end
endmodule endmodule

View File

@ -86,8 +86,8 @@ module csrs #(parameter
assign WriteSTVALM = STrapM | (CSRSWriteM & (CSRAdrM == STVAL)) & InstrValidNotFlushedM; assign WriteSTVALM = STrapM | (CSRSWriteM & (CSRAdrM == STVAL)) & InstrValidNotFlushedM;
assign WriteSATPM = CSRSWriteM & (CSRAdrM == SATP) & (PrivilegeModeW == `M_MODE | ~STATUS_TVM) & InstrValidNotFlushedM; assign WriteSATPM = CSRSWriteM & (CSRAdrM == SATP) & (PrivilegeModeW == `M_MODE | ~STATUS_TVM) & InstrValidNotFlushedM;
assign WriteSCOUNTERENM = CSRSWriteM & (CSRAdrM == SCOUNTEREN) & InstrValidNotFlushedM; assign WriteSCOUNTERENM = CSRSWriteM & (CSRAdrM == SCOUNTEREN) & InstrValidNotFlushedM;
assign WriteSTIMECMPM = CSRSWriteM & (CSRAdrM == STIMECMP) & MCOUNTEREN_TM & InstrValidNotFlushedM; assign WriteSTIMECMPM = CSRSWriteM & (CSRAdrM == STIMECMP) & (PrivilegeModeW == `M_MODE | MCOUNTEREN_TM) & InstrValidNotFlushedM;
assign WriteSTIMECMPHM = CSRSWriteM & (CSRAdrM == STIMECMPH) & MCOUNTEREN_TM & (`XLEN == 32) & InstrValidNotFlushedM; assign WriteSTIMECMPHM = CSRSWriteM & (CSRAdrM == STIMECMPH) & (PrivilegeModeW == `M_MODE | MCOUNTEREN_TM) & (`XLEN == 32) & InstrValidNotFlushedM;
// CSRs // CSRs
flopenr #(`XLEN) STVECreg(clk, reset, WriteSTVECM, {CSRWriteValM[`XLEN-1:2], 1'b0, CSRWriteValM[0]}, STVEC_REGW); flopenr #(`XLEN) STVECreg(clk, reset, WriteSTVECM, {CSRWriteValM[`XLEN-1:2], 1'b0, CSRWriteValM[0]}, STVEC_REGW);
@ -100,12 +100,14 @@ module csrs #(parameter
else else
assign SATP_REGW = 0; // hardwire to zero if virtual memory not supported assign SATP_REGW = 0; // hardwire to zero if virtual memory not supported
flopens #(32) SCOUNTERENreg(clk, reset, WriteSCOUNTERENM, CSRWriteValM[31:0], SCOUNTEREN_REGW); flopens #(32) SCOUNTERENreg(clk, reset, WriteSCOUNTERENM, CSRWriteValM[31:0], SCOUNTEREN_REGW);
if (`XLEN == 64) if (`SSTC_SUPPORTED) begin
flopenr #(`XLEN) STIMECMPreg(clk, reset, WriteSTIMECMPM, CSRWriteValM, STIMECMP_REGW); if (`XLEN == 64)
else begin flopenr #(`XLEN) STIMECMPreg(clk, reset, WriteSTIMECMPM, CSRWriteValM, STIMECMP_REGW);
flopenr #(`XLEN) STIMECMPreg(clk, reset, WriteSTIMECMPM, CSRWriteValM, STIMECMP_REGW[31:0]); else begin
flopenr #(`XLEN) STIMECMPHreg(clk, reset, WriteSTIMECMPHM, CSRWriteValM, STIMECMP_REGW[63:32]); flopenr #(`XLEN) STIMECMPreg(clk, reset, WriteSTIMECMPM, CSRWriteValM, STIMECMP_REGW[31:0]);
end flopenr #(`XLEN) STIMECMPHreg(clk, reset, WriteSTIMECMPHM, CSRWriteValM, STIMECMP_REGW[63:32]);
end
end else assign STIMECMP_REGW = 0;
// Supervisor timer interrupt logic // Supervisor timer interrupt logic
// Spec is a bit peculiar - Machine timer interrupts are produced in CLINT, while Supervisor timer interrupts are in CSRs // Spec is a bit peculiar - Machine timer interrupts are produced in CLINT, while Supervisor timer interrupts are in CSRs
@ -132,12 +134,12 @@ module csrs #(parameter
if (PrivilegeModeW == `S_MODE & STATUS_TVM) IllegalCSRSAccessM = 1; if (PrivilegeModeW == `S_MODE & STATUS_TVM) IllegalCSRSAccessM = 1;
end end
SCOUNTEREN:CSRSReadValM = {{(`XLEN-32){1'b0}}, SCOUNTEREN_REGW}; SCOUNTEREN:CSRSReadValM = {{(`XLEN-32){1'b0}}, SCOUNTEREN_REGW};
STIMECMP: if (MCOUNTEREN_TM) CSRSReadValM = STIMECMP_REGW[`XLEN-1:0]; STIMECMP: if (`SSTC_SUPPORTED & (PrivilegeModeW == `M_MODE | MCOUNTEREN_TM)) CSRSReadValM = STIMECMP_REGW[`XLEN-1:0];
else begin else begin
CSRSReadValM = 0; CSRSReadValM = 0;
IllegalCSRSAccessM = 1; IllegalCSRSAccessM = 1;
end end
STIMECMPH: if (MCOUNTEREN_TM & (`XLEN == 32)) CSRSReadValM[31:0] = STIMECMP_REGW[63:32]; STIMECMPH: if (`SSTC_SUPPORTED & (`XLEN == 32) & (PrivilegeModeW == `M_MODE | MCOUNTEREN_TM)) CSRSReadValM[31:0] = STIMECMP_REGW[63:32];
else begin // not supported for RV64 else begin // not supported for RV64
CSRSReadValM = 0; CSRSReadValM = 0;
IllegalCSRSAccessM = 1; IllegalCSRSAccessM = 1;

View File

@ -101,7 +101,7 @@ package cvw;
parameter BPRED_SUPPORTED = `BPRED_SUPPORTED; parameter BPRED_SUPPORTED = `BPRED_SUPPORTED;
parameter BPRED_TYPE = `BPRED_TYPE; parameter BPRED_TYPE = `BPRED_TYPE;
parameter BPRED_SIZE = `BPRED_SIZE; parameter BPRED_SIZE = `BPRED_SIZE;
parameter HPTW_WRITES_SUPPORTED = `HPTW_WRITES_SUPPORTED; parameter SVADU_SUPPORTED = `SVADU_SUPPORTED;
// parameter = `; // parameter = `;

View File

@ -156,7 +156,7 @@ module wallypipelinedcore (
logic ICacheMiss; logic ICacheMiss;
logic ICacheAccess; logic ICacheAccess;
logic BreakpointFaultM, EcallFaultM; logic BreakpointFaultM, EcallFaultM;
logic InstrDAPageFaultF; logic InstrUpdateDAF;
logic BigEndianM; logic BigEndianM;
logic FCvtIntE; logic FCvtIntE;
logic CommittedF; logic CommittedF;
@ -184,7 +184,7 @@ module wallypipelinedcore (
.PrivilegeModeW, .PTE, .PageType, .SATP_REGW, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .PrivilegeModeW, .PTE, .PageType, .SATP_REGW, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV,
.STATUS_MPP, .ITLBWriteF, .sfencevmaM, .ITLBMissF, .STATUS_MPP, .ITLBWriteF, .sfencevmaM, .ITLBMissF,
// pmp/pma (inside mmu) signals. // pmp/pma (inside mmu) signals.
.PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW, .InstrAccessFaultF, .InstrDAPageFaultF); .PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW, .InstrAccessFaultF, .InstrUpdateDAF);
// integer execution unit: integer register file, datapath and controller // integer execution unit: integer register file, datapath and controller
ieu ieu(.clk, .reset, ieu ieu(.clk, .reset,
@ -238,7 +238,7 @@ module wallypipelinedcore (
.HPTWInstrAccessFaultM, // connects to privilege .HPTWInstrAccessFaultM, // connects to privilege
.StoreAmoMisalignedFaultM, // connects to privilege .StoreAmoMisalignedFaultM, // connects to privilege
.StoreAmoAccessFaultM, // connects to privilege .StoreAmoAccessFaultM, // connects to privilege
.InstrDAPageFaultF, .InstrUpdateDAF,
.PCFSpill, .ITLBMissF, .PTE, .PageType, .ITLBWriteF, .SelHPTW, .PCFSpill, .ITLBMissF, .PTE, .PageType, .ITLBWriteF, .SelHPTW,
.LSUStallM); .LSUStallM);
@ -313,7 +313,7 @@ module wallypipelinedcore (
end end
// multiply/divide unit // multiply/divide unit
if (`M_SUPPORTED) begin:mdu if (`M_SUPPORTED | `ZMMUL_SUPPORTED) begin:mdu
mdu mdu(.clk, .reset, .StallM, .StallW, .FlushE, .FlushM, .FlushW, mdu mdu(.clk, .reset, .StallM, .StallW, .FlushE, .FlushM, .FlushW,
.ForwardedSrcAE, .ForwardedSrcBE, .ForwardedSrcAE, .ForwardedSrcBE,
.Funct3E, .Funct3M, .IntDivE, .W64E, .Funct3E, .Funct3M, .IntDivE, .W64E,

View File

@ -23,40 +23,42 @@
module riscvassertions; module riscvassertions;
initial begin initial begin
assert (`PMP_ENTRIES == 0 | `PMP_ENTRIES==16 | `PMP_ENTRIES==64) else $error("Illegal number of PMP entries: PMP_ENTRIES must be 0, 16, or 64"); $display("IDIV_ON_FPU = %b M_SUPPORTED %b comb %b\n", `IDIV_ON_FPU, `M_SUPPORTED, ((`IDIV_ON_FPU) || (!`M_SUPPORTED)));
assert (`S_SUPPORTED | `VIRTMEM_SUPPORTED == 0) else $error("Virtual memory requires S mode support"); assert (`PMP_ENTRIES == 0 || `PMP_ENTRIES==16 || `PMP_ENTRIES==64) else $error("Illegal number of PMP entries: PMP_ENTRIES must be 0, 16, or 64");
assert (`IDIV_BITSPERCYCLE == 1 | `IDIV_BITSPERCYCLE==2 | `IDIV_BITSPERCYCLE==4) else $error("Illegal number of divider bits/cycle: IDIV_BITSPERCYCLE must be 1, 2, or 4"); assert (`S_SUPPORTED || `VIRTMEM_SUPPORTED == 0) else $error("Virtual memory requires S mode support");
assert (`F_SUPPORTED | ~`D_SUPPORTED) else $error("Can't support double fp (D) without supporting float (F)"); assert (`IDIV_BITSPERCYCLE == 1 || `IDIV_BITSPERCYCLE==2 || `IDIV_BITSPERCYCLE==4) else $error("Illegal number of divider bits/cycle: IDIV_BITSPERCYCLE must be 1, 2, or 4");
assert (`D_SUPPORTED | ~`Q_SUPPORTED) else $error("Can't support quad fp (Q) without supporting double (D)"); assert (`F_SUPPORTED || ~`D_SUPPORTED) else $error("Can't support double fp (D) without supporting float (F)");
assert (`F_SUPPORTED | ~`ZFH_SUPPORTED) else $error("Can't support half-precision fp (ZFH) without supporting float (F)"); assert (`D_SUPPORTED || ~`Q_SUPPORTED) else $error("Can't support quad fp (Q) without supporting double (D)");
assert (`DCACHE_SUPPORTED | ~`F_SUPPORTED | `FLEN <= `XLEN) else $error("Data cache required to support FLEN > XLEN because AHB bus width is XLEN"); assert (`F_SUPPORTED || ~`ZFH_SUPPORTED) else $error("Can't support half-precision fp (ZFH) without supporting float (F)");
assert (`DCACHE_SUPPORTED || ~`F_SUPPORTED || `FLEN <= `XLEN) else $error("Data cache required to support FLEN > XLEN because AHB bus width is XLEN");
assert (`I_SUPPORTED ^ `E_SUPPORTED) else $error("Exactly one of I and E must be supported"); assert (`I_SUPPORTED ^ `E_SUPPORTED) else $error("Exactly one of I and E must be supported");
assert (`FLEN<=`XLEN | `DCACHE_SUPPORTED | `DTIM_SUPPORTED) else $error("Wally does not support FLEN > XLEN unleses data cache or DTIM is supported"); assert (`FLEN<=`XLEN || `DCACHE_SUPPORTED || `DTIM_SUPPORTED) else $error("Wally does not support FLEN > XLEN unleses data cache or DTIM is supported");
assert (`DCACHE_WAYSIZEINBYTES <= 4096 | (!`DCACHE_SUPPORTED) | `VIRTMEM_SUPPORTED == 0) else $error("DCACHE_WAYSIZEINBYTES cannot exceed 4 KiB when caches and vitual memory is enabled (to prevent aliasing)"); assert (`DCACHE_WAYSIZEINBYTES <= 4096 || (!`DCACHE_SUPPORTED) || `VIRTMEM_SUPPORTED == 0) else $error("DCACHE_WAYSIZEINBYTES cannot exceed 4 KiB when caches and vitual memory is enabled (to prevent aliasing)");
assert (`DCACHE_LINELENINBITS >= 128 | (!`DCACHE_SUPPORTED)) else $error("DCACHE_LINELENINBITS must be at least 128 when caches are enabled"); assert (`DCACHE_LINELENINBITS >= 128 || (!`DCACHE_SUPPORTED)) else $error("DCACHE_LINELENINBITS must be at least 128 when caches are enabled");
assert (`DCACHE_LINELENINBITS < `DCACHE_WAYSIZEINBYTES*8) else $error("DCACHE_LINELENINBITS must be smaller than way size"); assert (`DCACHE_LINELENINBITS < `DCACHE_WAYSIZEINBYTES*8) else $error("DCACHE_LINELENINBITS must be smaller than way size");
assert (`ICACHE_WAYSIZEINBYTES <= 4096 | (!`ICACHE_SUPPORTED) | `VIRTMEM_SUPPORTED == 0) else $error("ICACHE_WAYSIZEINBYTES cannot exceed 4 KiB when caches and vitual memory is enabled (to prevent aliasing)"); assert (`ICACHE_WAYSIZEINBYTES <= 4096 || (!`ICACHE_SUPPORTED) || `VIRTMEM_SUPPORTED == 0) else $error("ICACHE_WAYSIZEINBYTES cannot exceed 4 KiB when caches and vitual memory is enabled (to prevent aliasing)");
assert (`ICACHE_LINELENINBITS >= 32 | (!`ICACHE_SUPPORTED)) else $error("ICACHE_LINELENINBITS must be at least 32 when caches are enabled"); assert (`ICACHE_LINELENINBITS >= 32 || (!`ICACHE_SUPPORTED)) else $error("ICACHE_LINELENINBITS must be at least 32 when caches are enabled");
assert (`ICACHE_LINELENINBITS < `ICACHE_WAYSIZEINBYTES*8) else $error("ICACHE_LINELENINBITS must be smaller than way size"); assert (`ICACHE_LINELENINBITS < `ICACHE_WAYSIZEINBYTES*8) else $error("ICACHE_LINELENINBITS must be smaller than way size");
assert (2**$clog2(`DCACHE_LINELENINBITS) == `DCACHE_LINELENINBITS | (!`DCACHE_SUPPORTED)) else $error("DCACHE_LINELENINBITS must be a power of 2"); assert (2**$clog2(`DCACHE_LINELENINBITS) == `DCACHE_LINELENINBITS || (!`DCACHE_SUPPORTED)) else $error("DCACHE_LINELENINBITS must be a power of 2");
assert (2**$clog2(`DCACHE_WAYSIZEINBYTES) == `DCACHE_WAYSIZEINBYTES | (!`DCACHE_SUPPORTED)) else $error("DCACHE_WAYSIZEINBYTES must be a power of 2"); assert (2**$clog2(`DCACHE_WAYSIZEINBYTES) == `DCACHE_WAYSIZEINBYTES || (!`DCACHE_SUPPORTED)) else $error("DCACHE_WAYSIZEINBYTES must be a power of 2");
assert (2**$clog2(`ICACHE_LINELENINBITS) == `ICACHE_LINELENINBITS | (!`ICACHE_SUPPORTED)) else $error("ICACHE_LINELENINBITS must be a power of 2"); assert (2**$clog2(`ICACHE_LINELENINBITS) == `ICACHE_LINELENINBITS || (!`ICACHE_SUPPORTED)) else $error("ICACHE_LINELENINBITS must be a power of 2");
assert (2**$clog2(`ICACHE_WAYSIZEINBYTES) == `ICACHE_WAYSIZEINBYTES | (!`ICACHE_SUPPORTED)) else $error("ICACHE_WAYSIZEINBYTES must be a power of 2"); assert (2**$clog2(`ICACHE_WAYSIZEINBYTES) == `ICACHE_WAYSIZEINBYTES || (!`ICACHE_SUPPORTED)) else $error("ICACHE_WAYSIZEINBYTES must be a power of 2");
assert (2**$clog2(`ITLB_ENTRIES) == `ITLB_ENTRIES | `VIRTMEM_SUPPORTED==0) else $error("ITLB_ENTRIES must be a power of 2"); assert (2**$clog2(`ITLB_ENTRIES) == `ITLB_ENTRIES || `VIRTMEM_SUPPORTED==0) else $error("ITLB_ENTRIES must be a power of 2");
assert (2**$clog2(`DTLB_ENTRIES) == `DTLB_ENTRIES | `VIRTMEM_SUPPORTED==0) else $error("DTLB_ENTRIES must be a power of 2"); assert (2**$clog2(`DTLB_ENTRIES) == `DTLB_ENTRIES || `VIRTMEM_SUPPORTED==0) else $error("DTLB_ENTRIES must be a power of 2");
assert (`UNCORE_RAM_RANGE >= 56'h07FFFFFF) else $warning("Some regression tests will fail if UNCORE_RAM_RANGE is less than 56'h07FFFFFF"); assert (`UNCORE_RAM_RANGE >= 56'h07FFFFFF) else $warning("Some regression tests will fail if UNCORE_RAM_RANGE is less than 56'h07FFFFFF");
assert (`ZICSR_SUPPORTED == 1 | (`PMP_ENTRIES == 0 & `VIRTMEM_SUPPORTED == 0)) else $error("PMP_ENTRIES and VIRTMEM_SUPPORTED must be zero if ZICSR not supported."); assert (`ZICSR_SUPPORTED == 1 || (`PMP_ENTRIES == 0 && `VIRTMEM_SUPPORTED == 0)) else $error("PMP_ENTRIES and VIRTMEM_SUPPORTED must be zero if ZICSR not supported.");
assert (`ZICSR_SUPPORTED == 1 | (`S_SUPPORTED == 0 & `U_SUPPORTED == 0)) else $error("S and U modes not supported if ZICSR not supported"); assert (`ZICSR_SUPPORTED == 1 || (`S_SUPPORTED == 0 && `U_SUPPORTED == 0)) else $error("S and U modes not supported if ZICSR not supported");
assert (`U_SUPPORTED | (`S_SUPPORTED == 0)) else $error ("S mode only supported if U also is supported"); assert (`U_SUPPORTED || (`S_SUPPORTED == 0)) else $error ("S mode only supported if U also is supported");
assert (`VIRTMEM_SUPPORTED == 0 | (`DTIM_SUPPORTED == 0 & `IROM_SUPPORTED == 0)) else $error("Can't simultaneously have virtual memory and DTIM_SUPPORTED/IROM_SUPPORTED because local memories don't translate addresses"); assert (`VIRTMEM_SUPPORTED == 0 || (`DTIM_SUPPORTED == 0 && `IROM_SUPPORTED == 0)) else $error("Can't simultaneously have virtual memory and DTIM_SUPPORTED/IROM_SUPPORTED because local memories don't translate addresses");
assert (`DCACHE_SUPPORTED | `VIRTMEM_SUPPORTED ==0) else $error("Virtual memory needs dcache"); assert (`DCACHE_SUPPORTED || `VIRTMEM_SUPPORTED ==0) else $error("Virtual memory needs dcache");
assert (`ICACHE_SUPPORTED | `VIRTMEM_SUPPORTED ==0) else $error("Virtual memory needs icache"); assert (`ICACHE_SUPPORTED || `VIRTMEM_SUPPORTED ==0) else $error("Virtual memory needs icache");
assert ((`DCACHE_SUPPORTED == 0 & `ICACHE_SUPPORTED == 0) | `BUS_SUPPORTED) else $error("Dcache and Icache requires DBUS_SUPPORTED."); assert ((`DCACHE_SUPPORTED == 0 && `ICACHE_SUPPORTED == 0) || `BUS_SUPPORTED) else $error("Dcache and Icache requires DBUS_SUPPORTED.");
assert (`DCACHE_LINELENINBITS <= `XLEN*16 | (!`DCACHE_SUPPORTED)) else $error("DCACHE_LINELENINBITS must not exceed 16 words because max AHB burst size is 1"); assert (`DCACHE_LINELENINBITS <= `XLEN*16 || (!`DCACHE_SUPPORTED)) else $error("DCACHE_LINELENINBITS must not exceed 16 words because max AHB burst size is 1");
assert (`DCACHE_LINELENINBITS % 4 == 0) else $error("DCACHE_LINELENINBITS must hold 4, 8, or 16 words"); assert (`DCACHE_LINELENINBITS % 4 == 0) else $error("DCACHE_LINELENINBITS must hold 4, 8, or 16 words");
assert (`DCACHE_SUPPORTED | `A_SUPPORTED == 0) else $error("Atomic extension (A) requires cache on Wally."); assert (`DCACHE_SUPPORTED || (`A_SUPPORTED == 0)) else $error("Atomic extension (A) requires cache on Wally.");
assert (`IDIV_ON_FPU == 0 | `F_SUPPORTED) else $error("IDIV on FPU needs F_SUPPORTED"); assert (`IDIV_ON_FPU == 0 || `F_SUPPORTED) else $error("IDIV on FPU needs F_SUPPORTED");
assert (`SSTC_SUPPORTED == 0 | (`S_SUPPORTED)) else $error("SSTC requires S_SUPPORTED"); assert (`SSTC_SUPPORTED == 0 || (`S_SUPPORTED)) else $error("SSTC requires S_SUPPORTED");
assert ((`ZMMUL_SUPPORTED == 0) || (`M_SUPPORTED ==0)) else $error("At most one of ZMMUL_SUPPORTED and M_SUPPORTED can be enabled");
end end
endmodule endmodule