mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-11 06:05:49 +00:00
Merge remote-tracking branch 'upstream/main' into bit-manip
This commit is contained in:
commit
58ab6ec805
@ -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()
|
||||||
|
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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)
|
@ -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
|
@ -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
|
@ -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;
|
||||||
|
@ -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 = `;
|
||||||
|
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user