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

This commit is contained in:
Kip Macsai-Goren 2023-03-03 09:48:13 -08:00
commit 48b10f96e9
51 changed files with 696 additions and 494 deletions

@ -1 +1 @@
Subproject commit ee028eb325525148a34420a4ca7959b24220a91e Subproject commit a3b7f0c2cf89652b8a0cba3146890c512ff8ba44

View File

@ -156,7 +156,7 @@ def GeometricAverage(benchmarks, field):
return Product ** (1.0/index) return Product ** (1.0/index)
def ComputeGeometricAverage(benchmarks): def ComputeGeometricAverage(benchmarks):
fields = ['BDMR', 'BTMR', 'RASMPR', 'ClassMPR', 'ICacheMR', 'DCacheMR'] fields = ['BDMR', 'BTMR', 'RASMPR', 'ClassMPR', 'ICacheMR', 'DCacheMR', 'CPI']
AllAve = {} AllAve = {}
for field in fields: for field in fields:
Product = 1 Product = 1
@ -247,20 +247,34 @@ 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', 'btb': 'x'}
colors={'twobit' : 'black', 'gshare' : 'blue', 'global' : 'dodgerblue', 'gshareBasic' : 'turquoise', 'globalBasic' : 'lightsteelblue', 'btb' : 'blue'}
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)) 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('Entries')
axes.set_xticks([64, 256, 1024, 4096, 16384, 65536])
axes.set_xticklabels([64, 256, 1024, 4096, 16384, 65536])
axes.grid(color='b', alpha=0.5, linestyle='dashed', linewidth=0.5)
plt.show() plt.show()
else: else:
# steps 1 and 2 # steps 1 and 2
benchmarks = ProcessFile(sys.argv[1]) benchmarks = ProcessFile(sys.argv[1])
ComputeAverage(benchmarks) print(benchmarks[0])
ComputeAll(benchmarks)
ComputeGeometricAverage(benchmarks)
# 3 process into useful data # 3 process into useful data
# cache hit rates # cache hit rates
# cache fill time # cache fill time
@ -268,7 +282,6 @@ else:
# hazard counts # hazard counts
# CPI # CPI
# instruction distribution # instruction distribution
ComputeAll(benchmarks)
for benchmark in benchmarks: for benchmark in benchmarks:
printStats(benchmark) printStats(benchmark)

View File

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

View File

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

View File

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

View File

@ -134,10 +134,11 @@
`define BPRED_SUPPORTED 1 `define BPRED_SUPPORTED 1
`define BPRED_TYPE "BP_GSHARE" // BP_GSHARE_BASIC, BP_GLOBAL, BP_GLOBAL_BASIC, BP_TWOBIT `define BPRED_TYPE "BP_GSHARE" // BP_GSHARE_BASIC, BP_GLOBAL, BP_GLOBAL_BASIC, BP_TWOBIT
`define BPRED_SIZE 10 `define BPRED_SIZE 16
`define BTB_SIZE 10 `define BTB_SIZE 10
`define HPTW_WRITES_SUPPORTED 0 `define SVADU_SUPPORTED 0
`define ZMMUL_SUPPORTED 0
// FPU division architecture // FPU division architecture
`define RADIX 32'h4 `define RADIX 32'h4

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,6 +1,11 @@
#--showoverrides
#--help --helpall
--traceregs
--override cpu/show_c_prefix=T --override cpu/show_c_prefix=T
--override cpu/unaligned=F --override cpu/unaligned=F
--override cpu/ignore_non_leaf_DAU=1 --override cpu/ignore_non_leaf_DAU=1
--override cpu/wfi_is_nop=T
# Enable the Imperas instruction coverage # Enable the Imperas instruction coverage
#-extlib refRoot/cpu/cv=imperas.com/intercept/riscvInstructionCoverage/1.0 #-extlib refRoot/cpu/cv=imperas.com/intercept/riscvInstructionCoverage/1.0
@ -33,3 +38,6 @@
# ignore settings of bits DAU for non leaf page table walks # ignore settings of bits DAU for non leaf page table walks
--override cpu/ignore_non_leaf_DAU=1 --override cpu/ignore_non_leaf_DAU=1
# mimpid = 0x100
--override cpu/mimpid=0x100

View File

@ -29,4 +29,4 @@
IMPERAS_TOOLS=$(pwd)/imperas.ic \ IMPERAS_TOOLS=$(pwd)/imperas.ic \
OTHERFLAGS="+TRACE2LOG_ENABLE=1 VERBOSE=1" \ OTHERFLAGS="+TRACE2LOG_ENABLE=1 VERBOSE=1" \
TESTDIR=${WALLY}/tests/riscof/work/wally-riscv-arch-test/rv64i_m/privilege/src/Lee.S/ \ TESTDIR=${WALLY}/tests/riscof/work/wally-riscv-arch-test/rv64i_m/privilege/src/Lee.S/ \
vsim -do "do wally-pipelined-imperas.do rv64gc" vsim -do "do wally-imperas.do rv64gc"

View File

@ -30,7 +30,7 @@
module hazard ( module hazard (
// Detect hazards // Detect hazards
input logic BPPredWrongE, CSRWriteFenceM, RetM, TrapM, input logic BPWrongE, CSRWriteFenceM, RetM, TrapM,
input logic LoadStallD, StoreStallD, MDUStallD, CSRRdStallD, input logic LoadStallD, StoreStallD, MDUStallD, CSRRdStallD,
input logic LSUStallM, IFUStallF, input logic LSUStallM, IFUStallF,
input logic FCvtIntStallD, FPUStallD, input logic FCvtIntStallD, FPUStallD,
@ -65,8 +65,8 @@ module hazard (
// Similarly, CSR writes and fences flush all subsequent instructions and refetch them in light of the new operating modes and cache/TLB contents // Similarly, CSR writes and fences flush all subsequent instructions and refetch them in light of the new operating modes and cache/TLB contents
// Branch misprediction is found in the Execute stage and must flush the next two instructions. // Branch misprediction is found in the Execute stage and must flush the next two instructions.
// However, an active division operation resides in the Execute stage, and when the BP incorrectly mispredicts the divide as a taken branch, the divde must still complete // However, an active division operation resides in the Execute stage, and when the BP incorrectly mispredicts the divide as a taken branch, the divde must still complete
assign FlushDCause = TrapM | RetM | CSRWriteFenceM | BPPredWrongE; assign FlushDCause = TrapM | RetM | CSRWriteFenceM | BPWrongE;
assign FlushECause = TrapM | RetM | CSRWriteFenceM |(BPPredWrongE & ~(DivBusyE | FDivBusyE)); assign FlushECause = TrapM | RetM | CSRWriteFenceM |(BPWrongE & ~(DivBusyE | FDivBusyE));
assign FlushMCause = TrapM | RetM | CSRWriteFenceM; assign FlushMCause = TrapM | RetM | CSRWriteFenceM;
assign FlushWCause = TrapM; assign FlushWCause = TrapM;

View File

@ -38,7 +38,9 @@ module controller(
output logic [2:0] ImmSrcD, // Type of immediate extension output logic [2:0] ImmSrcD, // Type of immediate extension
input logic IllegalIEUFPUInstrD, // Illegal IEU and FPU instruction input logic IllegalIEUFPUInstrD, // Illegal IEU and FPU instruction
output logic IllegalBaseInstrD, // Illegal I-type instruction, or illegal RV32 access to upper 16 registers output logic IllegalBaseInstrD, // Illegal I-type instruction, or illegal RV32 access to upper 16 registers
// Execute stage control signals output logic JumpD, // Jump instruction
output logic BranchD, // Branch instruction
// Execute stage control signals
input logic StallE, FlushE, // Stall, flush Execute stage input logic StallE, FlushE, // Stall, flush Execute stage
input logic [1:0] FlagsE, // Comparison flags ({eq, lt}) input logic [1:0] FlagsE, // Comparison flags ({eq, lt})
input logic FWriteIntE, // Write integer register, coming from FPU controller input logic FWriteIntE, // Write integer register, coming from FPU controller
@ -52,7 +54,8 @@ module controller(
output logic IntDivE, // Integer divide output logic IntDivE, // Integer divide
output logic MDUE, // MDU (multiply/divide) operatio output logic MDUE, // MDU (multiply/divide) operatio
output logic W64E, // RV64 W-type operation output logic W64E, // RV64 W-type operation
output logic JumpE, // jump instruction output logic JumpE, // jump instruction
output logic BranchE, // Branch instruction
output logic SCE, // Store Conditional instruction output logic SCE, // Store Conditional instruction
output logic BranchSignedE, // Branch comparison operands are signed (if it's a branch) output logic BranchSignedE, // Branch comparison operands are signed (if it's a branch)
output logic [3:0] BSelectE, // One-Hot encoding of if it's ZBA_ZBB_ZBC_ZBS instruction output logic [3:0] BSelectE, // One-Hot encoding of if it's ZBA_ZBB_ZBC_ZBS instruction
@ -66,9 +69,7 @@ module controller(
output logic RegWriteM, // Instruction writes a register (needed for Hazard unit) output logic RegWriteM, // Instruction writes a register (needed for Hazard unit)
output logic InvalidateICacheM, FlushDCacheM, // Invalidate I$, flush D$ output logic InvalidateICacheM, FlushDCacheM, // Invalidate I$, flush D$
output logic InstrValidD, InstrValidE, InstrValidM, // Instruction is valid output logic InstrValidD, InstrValidE, InstrValidM, // Instruction is valid
output logic BranchD, BranchE, output logic FenceM, // Fence instruction
output logic JumpD,
output logic FWriteIntM, // FPU controller writes integer register file output logic FWriteIntM, // FPU controller writes integer register file
// Writeback stage control signals // Writeback stage control signals
input logic StallW, FlushW, // Stall, flush Writeback stage input logic StallW, FlushW, // Stall, flush Writeback stage
@ -116,7 +117,7 @@ module controller(
logic IEURegWriteE; // Register write logic IEURegWriteE; // Register write
logic IllegalERegAdrD; // RV32E attempts to write upper 16 registers logic IllegalERegAdrD; // RV32E attempts to write upper 16 registers
logic [1:0] AtomicE; // Atomic instruction logic [1:0] AtomicE; // Atomic instruction
logic FenceD, FenceE, FenceM; // Fence instruction logic FenceD, FenceE; // Fence instruction
logic SFenceVmaD; // sfence.vma instruction logic SFenceVmaD; // sfence.vma instruction
logic IntDivM; // Integer divide instruction logic IntDivM; // Integer divide instruction
logic [3:0] BSelectD; // One-Hot encoding if it's ZBA_ZBB_ZBC_ZBS instruction in decode stage logic [3:0] BSelectD; // One-Hot encoding if it's ZBA_ZBB_ZBC_ZBS instruction in decode stage
@ -162,14 +163,14 @@ module controller(
ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // Non-implemented instruction ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // Non-implemented instruction
7'b0110011: if (Funct7D == 7'b0000000 | Funct7D == 7'b0100000 | ((`ZBB_SUPPORTED & BSelectD[2]) | (`ZBC_SUPPORTED & BSelectD[1]) | (`ZBS_SUPPORTED & BSelectD[0]) | (`ZBA_SUPPORTED & BSelectD[3]))) 7'b0110011: if (Funct7D == 7'b0000000 | Funct7D == 7'b0100000 | ((`ZBB_SUPPORTED & BSelectD[2]) | (`ZBC_SUPPORTED & BSelectD[1]) | (`ZBS_SUPPORTED & BSelectD[0]) | (`ZBA_SUPPORTED & BSelectD[3])))
ControlsD = `CTRLW'b1_000_00_00_000_0_1_0_0_0_0_0_0_0_00_0; // R-type ControlsD = `CTRLW'b1_000_00_00_000_0_1_0_0_0_0_0_0_0_00_0; // R-type
else if (Funct7D == 7'b0000001 & `M_SUPPORTED) else if (Funct7D == 7'b0000001 & (`M_SUPPORTED | (`ZMMUL_SUPPORTED & ~Funct3D[2])))
ControlsD = `CTRLW'b1_000_00_00_011_0_0_0_0_0_0_0_0_1_00_0; // Multiply/divide ControlsD = `CTRLW'b1_000_00_00_011_0_0_0_0_0_0_0_0_1_00_0; // Multiply/divide
else else
ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // Non-implemented instruction ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // Non-implemented instruction
7'b0110111: ControlsD = `CTRLW'b1_100_01_00_000_0_0_0_1_0_0_0_0_0_00_0; // lui 7'b0110111: ControlsD = `CTRLW'b1_100_01_00_000_0_0_0_1_0_0_0_0_0_00_0; // lui
7'b0111011: if ((Funct7D == 7'b0000000 | Funct7D == 7'b0100000 | (`ZBA_SUPPORTED & BSelectD[3]) | (`ZBB_SUPPORTED & BSelectD[2])) & `XLEN == 64) 7'b0111011: if ((Funct7D == 7'b0000000 | Funct7D == 7'b0100000 | (`ZBA_SUPPORTED & BSelectD[3]) | (`ZBB_SUPPORTED & BSelectD[2])) & `XLEN == 64)
ControlsD = `CTRLW'b1_000_00_00_000_0_1_0_0_1_0_0_0_0_00_0; // R-type W instructions for RV64i ControlsD = `CTRLW'b1_000_00_00_000_0_1_0_0_1_0_0_0_0_00_0; // R-type W instructions for RV64i
else if (Funct7D == 7'b0000001 & `M_SUPPORTED & `XLEN == 64) else if (Funct7D == 7'b0000001 & (`M_SUPPORTED | (`ZMMUL_SUPPORTED & ~Funct3D[2])) & `XLEN == 64)
ControlsD = `CTRLW'b1_000_00_00_011_0_0_0_0_1_0_0_0_1_00_0; // W-type Multiply/Divide ControlsD = `CTRLW'b1_000_00_00_011_0_0_0_0_1_0_0_0_1_00_0; // W-type Multiply/Divide
else else
ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // Non-implemented instruction ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // Non-implemented instruction

View File

@ -71,7 +71,8 @@ module ieu (
output logic FCvtIntStallD, LoadStallD, // Stall causes from IEU to hazard unit output logic FCvtIntStallD, LoadStallD, // Stall causes from IEU to hazard unit
output logic MDUStallD, CSRRdStallD, StoreStallD, output logic MDUStallD, CSRRdStallD, StoreStallD,
output logic CSRReadM, CSRWriteM, PrivilegedM,// CSR read, CSR write, is privileged instruction output logic CSRReadM, CSRWriteM, PrivilegedM,// CSR read, CSR write, is privileged instruction
output logic CSRWriteFenceM // CSR write or fence instruction needs to flush subsequent instructions output logic CSRWriteFenceM, // CSR write or fence instruction needs to flush subsequent instructions
output logic FenceM
); );
logic [2:0] ImmSrcD; // Select type of immediate extension logic [2:0] ImmSrcD; // Select type of immediate extension
@ -102,7 +103,7 @@ controller c(
.Funct3E, .IntDivE, .MDUE, .W64E, .BranchD, .BranchE, .JumpD, .JumpE, .SCE, .BranchSignedE, .BSelectE, .ZBBSelectE, .StallM, .FlushM, .MemRWM, .Funct3E, .IntDivE, .MDUE, .W64E, .BranchD, .BranchE, .JumpD, .JumpE, .SCE, .BranchSignedE, .BSelectE, .ZBBSelectE, .StallM, .FlushM, .MemRWM,
.CSRReadM, .CSRWriteM, .PrivilegedM, .AtomicM, .Funct3M, .CSRReadM, .CSRWriteM, .PrivilegedM, .AtomicM, .Funct3M,
.RegWriteM, .InvalidateICacheM, .FlushDCacheM, .InstrValidM, .InstrValidE, .InstrValidD, .FWriteIntM, .RegWriteM, .InvalidateICacheM, .FlushDCacheM, .InstrValidM, .InstrValidE, .InstrValidD, .FWriteIntM,
.StallW, .FlushW, .RegWriteW, .IntDivW, .ResultSrcW, .CSRWriteFenceM, .StoreStallD); .StallW, .FlushW, .RegWriteW, .IntDivW, .ResultSrcW, .CSRWriteFenceM, .FenceM, .StoreStallD);
datapath dp( datapath dp(
.clk, .reset, .ImmSrcD, .InstrD, .StallE, .FlushE, .ForwardAE, .ForwardBE, .clk, .reset, .ImmSrcD, .InstrD, .StallE, .FlushE, .ForwardAE, .ForwardBE,

View File

@ -33,11 +33,11 @@ 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 BPReturnWrongD, // Prediction class is wrong
input logic [3:0] InstrClassD, input logic ReturnD,
input logic [3:0] InstrClassE, // Instr class input logic ReturnE, CallE, // Instr class
input logic [3:0] PredInstrClassF, input logic BPReturnF,
input logic [`XLEN-1:0] PCLinkE, // PC of instruction after a jal input logic [`XLEN-1:0] PCLinkE, // PC of instruction after a call
output logic [`XLEN-1:0] RASPCF // Top of the stack output logic [`XLEN-1:0] RASPCF // Top of the stack
); );
@ -54,21 +54,21 @@ module RASPredictor #(parameter int StackSize = 16 )(
logic IncrRepairD, DecRepairD; logic IncrRepairD, DecRepairD;
logic DecrementPtr; logic DecrementPtr;
logic FlushedRetDE; logic FlushedReturnDE;
logic WrongPredRetD; logic WrongPredReturnD;
assign PopF = PredInstrClassF[2] & ~StallD & ~FlushD; assign PopF = BPReturnF & ~StallD & ~FlushD;
assign PushE = InstrClassE[3] & ~StallM & ~FlushM; assign PushE = CallE & ~StallM & ~FlushM;
assign WrongPredRetD = (WrongPredInstrClassD[2]) & ~StallE & ~FlushE; assign WrongPredReturnD = (BPReturnWrongD) & ~StallE & ~FlushE;
assign FlushedRetDE = (~StallE & FlushE & InstrClassD[2]) | (~StallM & FlushM & InstrClassE[2]); // flushed ret assign FlushedReturnDE = (~StallE & FlushE & ReturnD) | (~StallM & FlushM & ReturnE); // flushed return
assign RepairD = WrongPredRetD | FlushedRetDE ; assign RepairD = WrongPredReturnD | FlushedReturnDE ;
assign IncrRepairD = FlushedRetDE | (WrongPredRetD & ~InstrClassD[2]); // Guessed it was a ret, but its not assign IncrRepairD = FlushedReturnDE | (WrongPredReturnD & ~ReturnD); // Guessed it was a return, but its not
assign DecRepairD = WrongPredRetD & InstrClassD[2]; // Guessed non ret but is a ret. assign DecRepairD = WrongPredReturnD & ReturnD; // Guessed non return but is a return.
assign CounterEn = PopF | PushE | RepairD; assign CounterEn = PopF | PushE | RepairD;

View File

@ -39,7 +39,7 @@ module bpred (
input logic [31:0] InstrD, // Decompressed decode stage instruction. Used to decode instruction class input logic [31:0] InstrD, // Decompressed decode stage instruction. Used to decode instruction class
input logic [`XLEN-1:0] PCNextF, // Next Fetch Address input logic [`XLEN-1:0] PCNextF, // Next Fetch Address
input logic [`XLEN-1:0] PCPlus2or4F, // PCF+2/4 input logic [`XLEN-1:0] PCPlus2or4F, // PCF+2/4
output logic [`XLEN-1:0] PCNext1F, // Branch Predictor predicted or corrected fetch address on miss prediction output logic [`XLEN-1:0] PC1NextF, // Branch Predictor predicted or corrected fetch address on miss prediction
output logic [`XLEN-1:0] NextValidPCE, // Address of next valid instruction after the instruction in the Memory stage output logic [`XLEN-1:0] NextValidPCE, // Address of next valid instruction after the instruction in the Memory stage
// Update Predictor // Update Predictor
@ -58,67 +58,76 @@ module bpred (
input logic [`XLEN-1:0] IEUAdrE, // The branch/jump target address input logic [`XLEN-1:0] IEUAdrE, // The branch/jump target address
input logic [`XLEN-1:0] IEUAdrM, // The branch/jump target address input logic [`XLEN-1:0] IEUAdrM, // The branch/jump target address
input logic [`XLEN-1:0] PCLinkE, // The address following the branch instruction. (AKA Fall through address) input logic [`XLEN-1:0] PCLinkE, // The address following the branch instruction. (AKA Fall through address)
output logic [3:0] InstrClassM, // The valid instruction class. 1-hot encoded as jalr, ret, jr (not ret), j, br output logic [3:0] InstrClassM, // The valid instruction class. 1-hot encoded as call, return, jr (not return), j, br
output logic JumpOrTakenBranchM, // The valid instruction class. 1-hot encoded as jalr, ret, jr (not ret), j, br
// Report branch prediction status // Report branch prediction status
output logic BPPredWrongE, // Prediction is wrong output logic BPWrongE, // Prediction is wrong
output logic BPPredWrongM, // Prediction is wrong output logic BPWrongM, // Prediction is wrong
output logic DirPredictionWrongM, // Prediction direction is wrong output logic BPDirPredWrongM, // Prediction direction is wrong
output logic BTBPredPCWrongM, // Prediction target wrong output logic BTAWrongM, // Prediction target wrong
output logic RASPredPCWrongM, // RAS prediction is wrong output logic RASPredPCWrongM, // RAS prediction is wrong
output logic PredictionInstrClassWrongM // Class prediction is wrong output logic IClassWrongM // Class prediction is wrong
); );
logic [1:0] DirPredictionF; logic [1:0] BPDirPredF;
logic [3:0] BTBPredInstrClassF, PredInstrClassF, PredInstrClassD; logic [`XLEN-1:0] BTAF, RASPCF;
logic [`XLEN-1:0] BTAF, RASPCF; logic BPPCWrongE;
logic PredictionPCWrongE; logic IClassWrongE;
logic AnyWrongPredInstrClassD, AnyWrongPredInstrClassE; logic BPDirPredWrongE;
logic [3:0] InstrClassD;
logic [3:0] InstrClassE;
logic DirPredictionWrongE;
logic SelBPPredF; logic BPPCSrcF;
logic [`XLEN-1:0] BPPredPCF; logic [`XLEN-1:0] BPPCF;
logic [`XLEN-1:0] PCNext0F; logic [`XLEN-1:0] PC0NextF;
logic [`XLEN-1:0] PCCorrectE; logic [`XLEN-1:0] PCCorrectE;
logic [3:0] WrongPredInstrClassD; logic [3:0] WrongPredInstrClassD;
logic BTBTargetWrongE; logic BTBTargetWrongE;
logic RASTargetWrongE; logic RASTargetWrongE;
logic [`XLEN-1:0] BTAD; logic [`XLEN-1:0] BTAD;
logic BTBCallF, BTBReturnF, BTBJumpF, BTBBranchF;
logic BPBranchF, BPJumpF, BPReturnF, BPCallF;
logic BPBranchD, BPJumpD, BPReturnD, BPCallD;
logic ReturnD, CallD;
logic ReturnE, CallE;
logic BranchM, JumpM, ReturnM, CallM;
logic BranchW, JumpW, ReturnW, CallW;
logic BPReturnWrongD;
logic [`XLEN-1:0] BTAE;
// 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,
.PCNextF, .PCM, .DirPredictionF, .DirPredictionWrongE, .FlushD, .FlushE, .FlushM, .FlushW,
.BranchInstrE(InstrClassE[0]), .BranchInstrM(InstrClassM[0]), .PCSrcE); .PCNextF, .PCM, .BPDirPredF, .BPDirPredWrongE,
.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, .BPDirPredF, .BPDirPredWrongE,
.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, .BPDirPredF, .BPDirPredWrongE,
.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, .BPDirPredF, .BPDirPredWrongE,
.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, .BPDirPredF, .BPDirPredWrongE,
.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
@ -126,7 +135,7 @@ module bpred (
localHistoryPredictor DirPredictor(.clk, localHistoryPredictor DirPredictor(.clk,
.reset, .StallF, .StallE, .reset, .StallF, .StallE,
.LookUpPC(PCNextF), .LookUpPC(PCNextF),
.Prediction(DirPredictionF), .Prediction(BPDirPredF),
// update // update
.UpdatePC(PCE), .UpdatePC(PCE),
.UpdateEN(InstrClassE[0] & ~StallE), .UpdateEN(InstrClassE[0] & ~StallE),
@ -141,139 +150,78 @@ 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,
.BTAF, .BTAD, .BTAF, .BTAD, .BTAE,
.BTBPredInstrClassF, .BTBIClassF({BTBCallF, BTBReturnF, BTBJumpF, BTBBranchF}),
.PredictionInstrClassWrongM, .IClassWrongM, .IClassWrongE,
.IEUAdrE, .IEUAdrM, .IEUAdrE, .IEUAdrM,
.InstrClassD, .InstrClassE, .InstrClassM); .InstrClassD({CallD, ReturnD, JumpD, BranchD}),
.InstrClassE({CallE, ReturnE, JumpE, BranchE}),
.InstrClassM({CallM, ReturnM, JumpM, BranchM}),
.InstrClassW({CallW, ReturnW, JumpW, BranchW}));
// the branch predictor needs a compact decoding of the instruction class. icpred #(`INSTR_CLASS_PRED) icpred(.clk, .reset, .StallF, .StallD, .StallE, .StallM, .StallW, .FlushD, .FlushE, .FlushM, .FlushW,
if (`INSTR_CLASS_PRED == 0) begin : DirectClassDecode .PostSpillInstrRawF, .InstrD, .BranchD, .BranchE, .JumpD, .JumpE, .BranchM, .BranchW, .JumpM, .JumpW,
logic [3:0] InstrClassF; .CallD, .CallE, .CallM, .CallW, .ReturnD, .ReturnE, .ReturnM, .ReturnW, .BTBCallF, .BTBReturnF, .BTBJumpF,
logic cjal, cj, cjr, cjalr, CJumpF, CBranchF; .BTBBranchF, .BPCallF, .BPReturnF, .BPJumpF, .BPBranchF, .IClassWrongM, .IClassWrongE, .BPReturnWrongD);
logic JumpF, BranchF;
if(`C_SUPPORTED) begin
logic [4:0] CompressedOpcF;
assign CompressedOpcF = {PostSpillInstrRawF[1:0], PostSpillInstrRawF[15:13]};
assign cjal = CompressedOpcF == 5'h09 & `XLEN == 32;
assign cj = CompressedOpcF == 5'h0d;
assign cjr = CompressedOpcF == 5'h14 & ~PostSpillInstrRawF[12] & PostSpillInstrRawF[6:2] == 5'b0 & PostSpillInstrRawF[11:7] != 5'b0;
assign cjalr = CompressedOpcF == 5'h14 & PostSpillInstrRawF[12] & PostSpillInstrRawF[6:2] == 5'b0 & PostSpillInstrRawF[11:7] != 5'b0;
assign CJumpF = cjal | cj | cjr | cjalr;
assign CBranchF = CompressedOpcF[4:1] == 4'h7;
end else begin
assign {cjal, cj, cjr, cjalr, CJumpF, CBranchF} = '0;
end
assign JumpF = PostSpillInstrRawF[6:0] == 7'h67 | PostSpillInstrRawF[6:0] == 7'h6F;
assign BranchF = PostSpillInstrRawF[6:0] == 7'h63;
assign InstrClassF[0] = BranchF | (`C_SUPPORTED & CBranchF);
assign InstrClassF[1] = JumpF | (`C_SUPPORTED & (CJumpF));
assign InstrClassF[2] = (JumpF & (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));
assign InstrClassF[3] = (JumpF & (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)));
assign PredInstrClassF = InstrClassF;
assign SelBPPredF = (PredInstrClassF[0] & DirPredictionF[1]) |
PredInstrClassF[1];
end else begin
assign PredInstrClassF = BTBPredInstrClassF;
assign SelBPPredF = (PredInstrClassF[0] & DirPredictionF[1]) |
PredInstrClassF[1];
end
// 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, .BPReturnF, .ReturnD, .ReturnE, .CallE,
.WrongPredInstrClassD, .RASPCF, .PCLinkE); .BPReturnWrongD, .RASPCF, .PCLinkE);
assign BPPredPCF = PredInstrClassF[2] ? RASPCF : BTAF;
assign InstrClassD[0] = BranchD;
assign InstrClassD[1] = JumpD ;
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 #(4) InstrClassRegM(clk, reset, FlushM, ~StallM, InstrClassE, InstrClassM);
flopenrc #(1) BPPredWrongMReg(clk, reset, FlushM, ~StallM, BPPredWrongE, BPPredWrongM);
// branch predictor
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);
// 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.
// if the class prediction is wrong a regular instruction may have been predicted as a taken branch // if the class prediction is wrong a regular instruction may have been predicted as a taken branch
// this will result in PCD not being equal to the fall through address PCLinkE (PCE+4). // this will result in PCD not being equal to the fall through address PCLinkE (PCE+4).
// The next instruction is always valid as no other flush would occur at the same time as the branch and not // The next instruction is always valid as no other flush would occur at the same time as the branch and not
// also flush the branch. This will change in a superscaler cpu. // also flush the branch. This will change in a superscaler cpu.
assign PredictionPCWrongE = PCCorrectE != PCD;
// branch class prediction wrong.
assign WrongPredInstrClassD = PredInstrClassD ^ InstrClassD[3:0];
assign AnyWrongPredInstrClassD = |WrongPredInstrClassD;
// 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 BPWrongE = (PCCorrectE != PCD) & InstrValidE & InstrValidD;
assign BPPredWrongE = PredictionPCWrongE & InstrValidE & InstrValidD; flopenrc #(1) BPWrongMReg(clk, reset, FlushM, ~StallM, BPWrongE, BPWrongM);
logic BPPredWrongEAlt;
logic NotMatch;
assign BPPredWrongEAlt = PredictionPCWrongE & InstrValidE & InstrValidD; // this does not work for cubic benchmark
assign NotMatch = BPPredWrongE != BPPredWrongEAlt;
// Output the predicted PC or corrected PC on miss-predict. // Output the predicted PC or corrected PC on miss-predict.
assign BPPCSrcF = (BPBranchF & BPDirPredF[1]) | BPJumpF;
mux2 #(`XLEN) pcmuxbp(BTAF, RASPCF, BPReturnF, BPPCF);
// 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, BPPCF, BPPCSrcF, PC0NextF);
// 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(PC0NextF, PCCorrectE, BPWrongE, PC1NextF);
// Correct branch/jump target. // Correct branch/jump target.
mux2 #(`XLEN) pccorrectemux(PCLinkE, IEUAdrE, PCSrcE, PCCorrectE); mux2 #(`XLEN) pccorrectemux(PCLinkE, IEUAdrE, PCSrcE, PCCorrectE);
// If the fence/csrw was predicted as a taken branch then we select PCF, rather PCE. // If the fence/csrw was predicted as a taken branch then we select PCF, rather PCE.
// Effectively this is PCM+4 or the non-existant PCLinkM // Effectively this is PCM+4 or the non-existant PCLinkM
if(`INSTR_CLASS_PRED) mux2 #(`XLEN) pcmuxBPWrongInvalidateFlush(PCE, PCF, BPPredWrongM, NextValidPCE); if(`INSTR_CLASS_PRED) mux2 #(`XLEN) pcmuxBPWrongInvalidateFlush(PCE, PCF, BPWrongM, NextValidPCE);
else assign NextValidPCE = PCE; else assign NextValidPCE = PCE;
if(`ZICOUNTERS_SUPPORTED) begin if(`ZICOUNTERS_SUPPORTED) begin
logic JumpOrTakenBranchE; logic [`XLEN-1:0] RASPCD, RASPCE;
logic [`XLEN-1:0] BTAE, RASPCD, RASPCE; logic BTBPredPCWrongE, RASPredPCWrongE;
logic BTBPredPCWrongE, RASPredPCWrongE; // performance counters
// performance counters // 1. class (class wrong / minstret) (IClassWrongM / csr) // Correct now
// 1. class (class wrong / minstret) (PredictionInstrClassWrongM / csr) // Correct now // 2. target btb (btb target wrong / class[0,1,3]) (btb target wrong / (br + j + jal)
// 2. target btb (btb target wrong / class[0,1,3]) (btb target wrong / (br + j + jal) // 3. target ras (ras target wrong / class[2])
// 3. target ras (ras target wrong / class[2]) // 4. direction (br dir wrong / class[0])
// 4. direction (br dir wrong / class[0])
// Unforuantely we can't use PCD to infer the correctness of the BTB or RAS because the class prediction // Unforuantely we can't use PCD to infer the correctness of the BTB or RAS because the class prediction
// could be wrong or the fall through address selected for branch predict not taken. // 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; // **** use BTAWrongM from BTB.
assign RASPredPCWrongE = (RASPCE != IEUAdrE) & InstrClassE[2] & PCSrcE; assign BTBPredPCWrongE = (BTAE != IEUAdrE) & (BranchE | JumpE & ~ReturnE) & PCSrcE;
assign RASPredPCWrongE = (RASPCE != IEUAdrE) & ReturnE & PCSrcE;
assign JumpOrTakenBranchE = (InstrClassE[0] & PCSrcE) | InstrClassE[1]; flopenrc #(`XLEN) RASTargetDReg(clk, reset, FlushD, ~StallD, RASPCF, RASPCD);
flopenrc #(`XLEN) RASTargetEReg(clk, reset, FlushE, ~StallE, RASPCD, RASPCE);
flopenrc #(1) JumpOrTakenBranchMReg(clk, reset, FlushM, ~StallM, JumpOrTakenBranchE, JumpOrTakenBranchM); flopenrc #(3) BPPredWrongRegM(clk, reset, FlushM, ~StallM,
{BPDirPredWrongE, BTBPredPCWrongE, RASPredPCWrongE},
flopenrc #(`XLEN) BTBTargetEReg(clk, reset, FlushE, ~StallE, BTAD, BTAE); {BPDirPredWrongM, BTAWrongM, RASPredPCWrongM});
flopenrc #(`XLEN) RASTargetDReg(clk, reset, FlushD, ~StallD, RASPCF, RASPCD);
flopenrc #(`XLEN) RASTargetEReg(clk, reset, FlushE, ~StallE, RASPCD, RASPCE);
flopenrc #(3) BPPredWrongRegM(clk, reset, FlushM, ~StallM,
{DirPredictionWrongE, BTBPredPCWrongE, RASPredPCWrongE},
{DirPredictionWrongM, BTBPredPCWrongM, RASPredPCWrongM});
end else begin end else begin
assign {BTBPredPCWrongM, RASPredPCWrongM, JumpOrTakenBranchM} = '0; assign {BTAWrongM, RASPredPCWrongM} = '0;
end end
// **** Fix me
assign InstrClassM = {CallM, ReturnM, JumpM, BranchM};
endmodule endmodule

View File

@ -34,26 +34,33 @@ 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,// 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 [`XLEN-1:0] BTAE,
output logic [3:0] BTBIClassF, // BTB's guess at instruction class
// update // update
input logic PredictionInstrClassWrongM, // BTB's instruction class guess was wrong input logic IClassWrongM, // BTB's instruction class guess was wrong
input logic IClassWrongE,
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 [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] TableBTBPredF;
logic UpdateEn; logic [`XLEN-1:0] IEUAdrW;
logic [`XLEN-1:0] PCW;
logic BTBWrongE, BTAWrongE;
logic BTBWrongM, BTAWrongM;
// hashing function for indexing the PC // hashing function for indexing the PC
// We have Depth bits to index, but XLEN bits as the input. // We have Depth bits to index, but XLEN bits as the input.
// bit 0 is always 0, bit 1 is 0 if using 4 byte instructions, but is not always 0 if // bit 0 is always 0, bit 1 is 0 if using 4 byte instructions, but is not always 0 if
@ -62,6 +69,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,31 +78,38 @@ 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 {BTBIClassF, BTAF} = MatchX ? ForwardBTBPredictionF : {TableBTBPredF};
assign {BTBPredInstrClassF, BTAF} = MatchXF ? ForwardBTBPredictionF : {TableBTBPredictionF};
assign UpdateEn = |InstrClassM | PredictionInstrClassWrongM;
// An optimization may be using a PC relative address. // An optimization may be using a PC relative address.
ram2p1r1wbe #(2**Depth, `XLEN+4) memory( ram2p1r1wbe #(2**Depth, `XLEN+4) memory(
.clk, .ce1(~StallF | reset), .ra1(PCNextFIndex), .rd1(TableBTBPredictionF), .clk, .ce1(~StallF | reset), .ra1(PCNextFIndex), .rd1(TableBTBPredF),
.ce2(~StallW & ~FlushW), .wa2(PCMIndex), .wd2({InstrClassM, IEUAdrM}), .we2(UpdateEn), .bwe2('1)); .ce2(~StallW & ~FlushW), .wa2(PCMIndex), .wd2({InstrClassM, IEUAdrM}), .we2(BTBWrongM), .bwe2('1));
flopenrc #(`XLEN) BTBD(clk, reset, FlushD, ~StallD, BTAF, BTAD); flopenrc #(`XLEN) BTBD(clk, reset, FlushD, ~StallD, BTAF, BTAD);
// BTAE is not strickly necessary. However it is used by two parts of wally.
// 1. It gates updates to the BTB when the prediction does not change. This save power.
// 2. BTAWrongE is used by the performance counters to track when the BTB's BTA or instruction class is wrong.
flopenrc #(`XLEN) BTBTargetEReg(clk, reset, FlushE, ~StallE, BTAD, BTAE);
assign BTAWrongE = (BTAE != IEUAdrE) & (InstrClassE[0] | InstrClassE[1] & ~InstrClassE[2]);
flopenrc #(1) BTAWrongMReg(clk, reset, FlushM, ~StallM, BTAWrongE, BTAWrongM);
assign BTBWrongM = BTAWrongM | IClassWrongM;
flopenr #(`XLEN) PCWReg(clk, reset, ~StallW, PCM, PCW);
flopenr #(`XLEN) IEUAdrWReg(clk, reset, ~StallW, IEUAdrM, IEUAdrW);
endmodule endmodule

View File

@ -35,20 +35,20 @@ module gshare #(parameter k = 10,
input logic reset, input logic reset,
input logic StallF, StallD, StallE, StallM, StallW, input logic StallF, StallD, StallE, StallM, StallW,
input logic FlushD, FlushE, FlushM, FlushW, input logic FlushD, FlushE, FlushM, FlushW,
output logic [1:0] DirPredictionF, output logic [1:0] BPDirPredF,
output logic DirPredictionWrongE, output logic BPDirPredWrongE,
// update // update
input logic [`XLEN-1:0] PCNextF, PCF, PCD, PCE, PCM, input logic [`XLEN-1:0] PCNextF, PCF, PCD, PCE, PCM,
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] TableBPDirPredF, BPDirPredD, BPDirPredE, FwdNewDirPredF;
logic [1:0] NewDirPredictionE, NewDirPredictionM; logic [1:0] NewBPDirPredE, NewBPDirPredM, NewBPDirPredW;
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,48 +68,47 @@ 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 FwdNewDirPredF = MatchD ? {2{BPDirPredD[1]}} :
MatchD ? {2{DirPredictionD[1]}} : MatchE ? {NewBPDirPredE} :
MatchE ? {NewDirPredictionE} : MatchM ? {NewBPDirPredM} :
NewDirPredictionM ; NewBPDirPredW ;
flopenr #(2) ForwardDirPredicitonReg(clk, reset, ~StallF, ForwardNewDirPrediction, ForwardDirPredictionF); assign BPDirPredF = MatchX ? FwdNewDirPredF : TableBPDirPredF;
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(~StallW & ~FlushW),
.ra1(IndexNextF), .ra1(IndexNextF),
.rd1(TableDirPredictionF), .rd1(TableBPDirPredF),
.wa2(IndexM), .wa2(IndexM),
.wd2(NewDirPredictionM), .wd2(NewBPDirPredM),
.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, BPDirPredF, BPDirPredD);
flopenrc #(2) PredictionRegE(clk, reset, FlushE, ~StallE, DirPredictionD, DirPredictionE); flopenrc #(2) PredictionRegE(clk, reset, FlushE, ~StallE, BPDirPredD, BPDirPredE);
satCounter2 BPDirUpdateE(.BrDir(PCSrcE), .OldState(DirPredictionE), .NewState(NewDirPredictionE)); satCounter2 BPDirUpdateE(.BrDir(PCSrcE), .OldState(BPDirPredE), .NewState(NewBPDirPredE));
flopenrc #(2) NewPredictionRegM(clk, reset, FlushM, ~StallM, NewDirPredictionE, NewDirPredictionM); flopenrc #(2) NewPredictionRegM(clk, reset, FlushM, ~StallM, NewBPDirPredE, NewBPDirPredM);
flopenrc #(2) NewPredictionRegW(clk, reset, FlushW, ~StallW, NewBPDirPredM, NewBPDirPredW);
assign DirPredictionWrongE = PCSrcE != DirPredictionE[1] & BranchInstrE; assign BPDirPredWrongE = PCSrcE != BPDirPredE[1] & BranchE;
assign GHRNextF = BranchInstrF ? {DirPredictionF[1], GHRF[k-1:1]} : GHRF; assign GHRNextF = BPBranchF ? {BPDirPredF[1], GHRF[k-1:1]} : GHRF;
assign GHRF = BranchInstrD ? {DirPredictionD[1], GHRD[k-1:1]} : GHRD; assign GHRF = BranchD ? {BPDirPredD[1], GHRD[k-1:1]} : GHRD;
assign GHRD = BranchInstrE ? {PCSrcE, GHRE[k-1:1]} : GHRE; assign GHRD = BranchE ? {PCSrcE, GHRE[k-1:1]} : GHRE;
assign GHRE = BranchInstrM ? {PCSrcM, GHRM[k-1:1]} : GHRM; assign GHRE = BranchM ? {PCSrcM, GHRM[k-1:1]} : GHRM;
assign GHRNextM = {PCSrcM, GHRM[k-1:1]}; assign GHRNextM = {PCSrcM, GHRM[k-1:1]};
flopenr #(k) GHRReg(clk, reset, ~StallW & ~FlushW & BranchInstrM, GHRNextM, GHRM); flopenr #(k) GHRReg(clk, reset, ~StallW & ~FlushW & BranchM, GHRNextM, GHRM);
flopenrc #(1) PCSrcMReg(clk, reset, FlushM, ~StallM, PCSrcE, PCSrcM); flopenrc #(1) PCSrcMReg(clk, reset, FlushM, ~StallM, PCSrcE, PCSrcM);
endmodule endmodule

View File

@ -35,16 +35,16 @@ module gsharebasic #(parameter k = 10,
input logic reset, input logic reset,
input logic StallF, StallD, StallE, StallM, StallW, input logic StallF, StallD, StallE, StallM, StallW,
input logic FlushD, FlushE, FlushM, FlushW, input logic FlushD, FlushE, FlushM, FlushW,
output logic [1:0] DirPredictionF, output logic [1:0] BPDirPredF,
output logic DirPredictionWrongE, output logic BPDirPredWrongE,
// 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;
logic [1:0] DirPredictionD, DirPredictionE; logic [1:0] BPDirPredD, BPDirPredE;
logic [1:0] NewDirPredictionE, NewDirPredictionM; logic [1:0] NewBPDirPredE, NewBPDirPredM;
logic [k-1:0] GHRF, GHRD, GHRE, GHRM, GHR; logic [k-1:0] GHRF, GHRD, GHRE, GHRM, GHR;
logic [k-1:0] GHRNext; logic [k-1:0] GHRNext;
@ -61,22 +61,22 @@ module gsharebasic #(parameter k = 10,
ram2p1r1wbe #(2**k, 2) PHT(.clk(clk), ram2p1r1wbe #(2**k, 2) PHT(.clk(clk),
.ce1(~StallF), .ce2(~StallW & ~FlushW), .ce1(~StallF), .ce2(~StallW & ~FlushW),
.ra1(IndexNextF), .ra1(IndexNextF),
.rd1(DirPredictionF), .rd1(BPDirPredF),
.wa2(IndexM), .wa2(IndexM),
.wd2(NewDirPredictionM), .wd2(NewBPDirPredM),
.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, BPDirPredF, BPDirPredD);
flopenrc #(2) PredictionRegE(clk, reset, FlushE, ~StallE, DirPredictionD, DirPredictionE); flopenrc #(2) PredictionRegE(clk, reset, FlushE, ~StallE, BPDirPredD, BPDirPredE);
satCounter2 BPDirUpdateE(.BrDir(PCSrcE), .OldState(DirPredictionE), .NewState(NewDirPredictionE)); satCounter2 BPDirUpdateE(.BrDir(PCSrcE), .OldState(BPDirPredE), .NewState(NewBPDirPredE));
flopenrc #(2) NewPredictionRegM(clk, reset, FlushM, ~StallM, NewDirPredictionE, NewDirPredictionM); flopenrc #(2) NewPredictionRegM(clk, reset, FlushM, ~StallM, NewBPDirPredE, NewBPDirPredM);
assign DirPredictionWrongE = PCSrcE != DirPredictionE[1] & BranchInstrE; assign BPDirPredWrongE = PCSrcE != BPDirPredE[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);

106
src/ifu/bpred/icpred.sv Normal file
View File

@ -0,0 +1,106 @@
///////////////////////////////////////////
// icpred.sv
//
// Written: Ross Thomposn ross1728@gmail.com
// Created: February 26, 2023
// Modified: February 26, 2023
//
// Purpose: Partial decode of instructions into control flow instructions (cfi)P
// Call, Return, Jump, and Branch
//
// A component of the CORE-V-WALLY configurable RISC-V project.
//
// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University
//
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
//
// Licensed under the Solderpad Hardware License v 2.1 (the “License”); you may not use this file
// except in compliance with the License, or, at your option, the Apache License version 2.0. You
// may obtain a copy of the License at
//
// https://solderpad.org/licenses/SHL-2.1/
//
// Unless required by applicable law or agreed to in writing, any work distributed under the
// License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
// either express or implied. See the License for the specific language governing permissions
// and limitations under the License.
////////////////////////////////////////////////////////////////////////////////////////////////
`include "wally-config.vh"
module icpred #(parameter INSTR_CLASS_PRED = 1)(
input logic clk, reset,
input logic StallF, StallD, StallE, StallM, StallW,
input logic FlushD, FlushE, FlushM, FlushW,
input logic [31:0] PostSpillInstrRawF, InstrD, // Instruction
input logic BranchD, BranchE,
input logic JumpD, JumpE,
output logic BranchM, BranchW,
output logic JumpM, JumpW,
output logic CallD, CallE, CallM, CallW,
output logic ReturnD, ReturnE, ReturnM, ReturnW,
input logic BTBCallF, BTBReturnF, BTBJumpF, BTBBranchF,
output logic BPCallF, BPReturnF, BPJumpF, BPBranchF,
output logic IClassWrongM, BPReturnWrongD, IClassWrongE
);
logic IClassWrongD;
logic BPBranchD, BPJumpD, BPReturnD, BPCallD;
if (!INSTR_CLASS_PRED) begin : DirectClassDecode
// This section is mainly for testing, verification, and PPA comparison.
// An alternative to using the BTB to store the instruction class is to partially decode
// the instructions in the Fetch stage into, Call, Return, Jump, and Branch instructions.
// This logic is not described in the text book as of 23 February 2023.
logic ccall, cj, cjr, ccallr, CJumpF, CBranchF;
logic NCJumpF, NCBranchF;
if(`C_SUPPORTED) begin
logic [4:0] CompressedOpcF;
assign CompressedOpcF = {PostSpillInstrRawF[1:0], PostSpillInstrRawF[15:13]};
assign ccall = CompressedOpcF == 5'h09 & `XLEN == 32;
assign cj = CompressedOpcF == 5'h0d;
assign cjr = CompressedOpcF == 5'h14 & ~PostSpillInstrRawF[12] & PostSpillInstrRawF[6:2] == 5'b0 & PostSpillInstrRawF[11:7] != 5'b0;
assign ccallr = CompressedOpcF == 5'h14 & PostSpillInstrRawF[12] & PostSpillInstrRawF[6:2] == 5'b0 & PostSpillInstrRawF[11:7] != 5'b0;
assign CJumpF = ccall | cj | cjr | ccallr;
assign CBranchF = CompressedOpcF[4:1] == 4'h7;
end else begin
assign {ccall, cj, cjr, ccallr, CJumpF, CBranchF} = '0;
end
assign NCJumpF = PostSpillInstrRawF[6:0] == 7'h67 | PostSpillInstrRawF[6:0] == 7'h6F;
assign NCBranchF = PostSpillInstrRawF[6:0] == 7'h63;
assign BPBranchF = NCBranchF | (`C_SUPPORTED & CBranchF);
assign BPJumpF = NCJumpF | (`C_SUPPORTED & (CJumpF));
assign BPReturnF = (NCJumpF & (PostSpillInstrRawF[19:15] & 5'h1B) == 5'h01) | // returnurn must returnurn to ra or r5
(`C_SUPPORTED & (ccallr | cjr) & ((PostSpillInstrRawF[11:7] & 5'h1B) == 5'h01));
assign BPCallF = (NCJumpF & (PostSpillInstrRawF[11:07] & 5'h1B) == 5'h01) | // call(r) must link to ra or x5
(`C_SUPPORTED & (ccall | (ccallr & (PostSpillInstrRawF[11:7] & 5'h1b) == 5'h01)));
end else begin
// This section connects the BTB's instruction class prediction.
assign {BPCallF, BPReturnF, BPJumpF, BPBranchF} = {BTBCallF, BTBReturnF, BTBJumpF, BTBBranchF};
end
assign ReturnD = JumpD & (InstrD[19:15] & 5'h1B) == 5'h01; // returnurn must returnurn to ra or x5
assign CallD = JumpD & (InstrD[11:7] & 5'h1B) == 5'h01; // call(r) must link to ra or x5
flopenrc #(2) InstrClassRegE(clk, reset, FlushE, ~StallE, {CallD, ReturnD}, {CallE, ReturnE});
flopenrc #(4) InstrClassRegM(clk, reset, FlushM, ~StallM, {CallE, ReturnE, JumpE, BranchE}, {CallM, ReturnM, JumpM, BranchM});
flopenrc #(4) InstrClassRegW(clk, reset, FlushM, ~StallW, {CallM, ReturnM, JumpM, BranchM}, {CallW, ReturnW, JumpW, BranchW});
// branch predictor
flopenrc #(1) BPClassWrongRegM(clk, reset, FlushM, ~StallM, IClassWrongE, IClassWrongM);
flopenrc #(1) WrongInstrClassRegE(clk, reset, FlushE, ~StallE, IClassWrongD, IClassWrongE);
// pipeline the predicted class
flopenrc #(4) PredInstrClassRegD(clk, reset, FlushD, ~StallD, {BPCallF, BPReturnF, BPJumpF, BPBranchF}, {BPCallD, BPReturnD, BPJumpD, BPBranchD});
// branch class prediction wrong.
assign IClassWrongD = |({BPCallD, BPReturnD, BPJumpD, BPBranchD} ^ {CallD, ReturnD, JumpD, BranchD});
assign BPReturnWrongD = BPReturnD ^ ReturnD;
endmodule

View File

@ -31,20 +31,20 @@
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] BPDirPredF,
output logic DirPredictionWrongE, output logic BPDirPredWrongE,
input logic BranchInstrE, BranchInstrM, input logic BranchE, BranchM,
input logic PCSrcE input logic PCSrcE
); );
logic [k-1:0] IndexNextF, IndexM; logic [k-1:0] IndexNextF, IndexM;
logic [1:0] PredictionMemory; logic [1:0] PredictionMemory;
logic DoForwarding, DoForwardingF; logic DoForwarding, DoForwardingF;
logic [1:0] DirPredictionD, DirPredictionE; logic [1:0] BPDirPredD, BPDirPredE;
logic [1:0] NewDirPredictionE, NewDirPredictionM; logic [1:0] NewBPDirPredE, NewBPDirPredM;
// hashing function for indexing the PC // hashing function for indexing the PC
// We have k bits to index, but XLEN bits as the input. // We have k bits to index, but XLEN bits as the input.
@ -55,21 +55,21 @@ 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(BPDirPredF),
.wa2(IndexM), .wa2(IndexM),
.wd2(NewDirPredictionM), .wd2(NewBPDirPredM),
.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, BPDirPredF, BPDirPredD);
flopenrc #(2) PredictionRegE(clk, reset, FlushE, ~StallE, DirPredictionD, DirPredictionE); flopenrc #(2) PredictionRegE(clk, reset, FlushE, ~StallE, BPDirPredD, BPDirPredE);
assign DirPredictionWrongE = PCSrcE != DirPredictionE[1] & BranchInstrE; assign BPDirPredWrongE = PCSrcE != BPDirPredE[1] & BranchE;
satCounter2 BPDirUpdateE(.BrDir(PCSrcE), .OldState(DirPredictionE), .NewState(NewDirPredictionE)); satCounter2 BPDirUpdateE(.BrDir(PCSrcE), .OldState(BPDirPredE), .NewState(NewBPDirPredE));
flopenrc #(2) NewPredictionRegM(clk, reset, FlushM, ~StallM, NewDirPredictionE, NewDirPredictionM); flopenrc #(2) NewPredictionRegM(clk, reset, FlushM, ~StallM, NewBPDirPredE, NewBPDirPredM);
endmodule endmodule

View File

@ -54,22 +54,22 @@ module ifu (
input logic [`XLEN-1:0] IEUAdrE, // The branch/jump target address input logic [`XLEN-1:0] IEUAdrE, // The branch/jump target address
input logic [`XLEN-1:0] IEUAdrM, // The branch/jump target address input logic [`XLEN-1:0] IEUAdrM, // The branch/jump target address
output logic [`XLEN-1:0] PCE, // Execution stage instruction address output logic [`XLEN-1:0] PCE, // Execution stage instruction address
output logic BPPredWrongE, // Prediction is wrong output logic BPWrongE, // Prediction is wrong
output logic BPPredWrongM, // Prediction is wrong output logic BPWrongM, // Prediction is wrong
// Mem // Mem
output logic CommittedF, // I$ or bus memory operation started, delay interrupts output logic CommittedF, // I$ or bus memory operation started, delay interrupts
input logic [`XLEN-1:0] UnalignedPCNextF, // The next PCF, but not aligned to 2 bytes. input logic [`XLEN-1:0] UnalignedPCNextF, // The next PCF, but not aligned to 2 bytes.
output logic [`XLEN-1:0] PCNext2F, // Selected PC between branch prediction and next valid PC if CSRWriteFence output logic [`XLEN-1:0] PC2NextF, // Selected PC between branch prediction and next valid PC if CSRWriteFence
output logic [31:0] InstrD, // The decoded instruction in Decode stage output logic [31:0] InstrD, // The decoded instruction in Decode stage
output logic [31:0] InstrM, // The decoded instruction in Memory stage output logic [31:0] InstrM, // The decoded instruction in Memory stage
output logic [`XLEN-1:0] PCM, // Memory stage instruction address output logic [`XLEN-1:0] PCM, // Memory stage instruction address
// branch predictor // branch predictor
output logic [3:0] InstrClassM, // The valid instruction class. 1-hot encoded as jalr, ret, jr (not ret), j, br output logic [3:0] InstrClassM, // The valid instruction class. 1-hot encoded as jalr, ret, jr (not ret), j, br
output logic JumpOrTakenBranchM, output logic BPDirPredWrongM, // Prediction direction is wrong
output logic DirPredictionWrongM, // Prediction direction is wrong output logic BTAWrongM, // Prediction target wrong
output logic BTBPredPCWrongM, // Prediction target wrong
output logic RASPredPCWrongM, // RAS prediction is wrong output logic RASPredPCWrongM, // RAS prediction is wrong
output logic PredictionInstrClassWrongM, // Class prediction is wrong output logic IClassWrongM, // Class prediction is wrong
output logic ICacheStallF, // I$ busy with multicycle operation
// Faults // Faults
input logic IllegalBaseInstrD, // Illegal non-compressed instruction input logic IllegalBaseInstrD, // Illegal non-compressed instruction
input logic IllegalFPUInstrD, // Illegal FP instruction input logic IllegalFPUInstrD, // Illegal FP instruction
@ -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
@ -128,11 +128,10 @@ module ifu (
logic CacheableF; // PMA indicates instruction address is cacheable logic CacheableF; // PMA indicates instruction address is cacheable
logic SelNextSpillF; // In a spill, stall pipeline and gate local stallF logic SelNextSpillF; // In a spill, stall pipeline and gate local stallF
logic BusStall; // Bus interface busy with multicycle operation logic BusStall; // Bus interface busy with multicycle operation
logic ICacheStallF; // I$ busy with multicycle operation
logic IFUCacheBusStallD; // EIther I$ or bus busy with multicycle operation logic IFUCacheBusStallD; // EIther I$ or bus busy with multicycle operation
logic GatedStallD; // StallD gated by selected next spill logic GatedStallD; // StallD gated by selected next spill
// branch predictor signal // branch predictor signal
logic [`XLEN-1:0] PCNext1F; // Branch predictor next PCF logic [`XLEN-1:0] PC1NextF; // Branch predictor next PCF
logic BusCommittedF; // Bus memory operation in flight, delay interrupts logic BusCommittedF; // Bus memory operation in flight, delay interrupts
logic CacheCommittedF; // I$ memory operation started, delay interrupts logic CacheCommittedF; // I$ memory operation started, delay interrupts
logic SelIROM; // PMA indicates instruction address is in the IROM logic SelIROM; // PMA indicates instruction address is in the IROM
@ -145,7 +144,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 +184,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;
@ -297,8 +296,8 @@ module ifu (
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
if(`ZICSR_SUPPORTED | `ZIFENCEI_SUPPORTED) if(`ZICSR_SUPPORTED | `ZIFENCEI_SUPPORTED)
mux2 #(`XLEN) pcmux2(.d0(PCNext1F), .d1(NextValidPCE), .s(CSRWriteFenceM),.y(PCNext2F)); mux2 #(`XLEN) pcmux2(.d0(PC1NextF), .d1(NextValidPCE), .s(CSRWriteFenceM),.y(PC2NextF));
else assign PCNext2F = PCNext1F; else assign PC2NextF = PC1NextF;
assign PCNextF = {UnalignedPCNextF[`XLEN-1:1], 1'b0}; // hart-SPEC p. 21 about 16-bit alignment assign PCNextF = {UnalignedPCNextF[`XLEN-1:1], 1'b0}; // hart-SPEC p. 21 about 16-bit alignment
flopenl #(`XLEN) pcreg(clk, reset, ~StallF, PCNextF, `RESET_VECTOR, PCF); flopenl #(`XLEN) pcreg(clk, reset, ~StallF, PCNextF, `RESET_VECTOR, PCF);
@ -330,14 +329,14 @@ module ifu (
.StallF, .StallD, .StallE, .StallM, .StallW, .StallF, .StallD, .StallE, .StallM, .StallW,
.FlushD, .FlushE, .FlushM, .FlushW, .InstrValidD, .InstrValidE, .FlushD, .FlushE, .FlushM, .FlushW, .InstrValidD, .InstrValidE,
.BranchD, .BranchE, .JumpD, .JumpE, .BranchD, .BranchE, .JumpD, .JumpE,
.InstrD, .PCNextF, .PCPlus2or4F, .PCNext1F, .PCE, .PCM, .PCSrcE, .IEUAdrE, .IEUAdrM, .PCF, .NextValidPCE, .InstrD, .PCNextF, .PCPlus2or4F, .PC1NextF, .PCE, .PCM, .PCSrcE, .IEUAdrE, .IEUAdrM, .PCF, .NextValidPCE,
.PCD, .PCLinkE, .InstrClassM, .BPPredWrongE, .PostSpillInstrRawF, .JumpOrTakenBranchM, .BPPredWrongM, .PCD, .PCLinkE, .InstrClassM, .BPWrongE, .PostSpillInstrRawF, .BPWrongM,
.DirPredictionWrongM, .BTBPredPCWrongM, .RASPredPCWrongM, .PredictionInstrClassWrongM); .BPDirPredWrongM, .BTAWrongM, .RASPredPCWrongM, .IClassWrongM);
end else begin : bpred end else begin : bpred
mux2 #(`XLEN) pcmux1(.d0(PCPlus2or4F), .d1(IEUAdrE), .s(PCSrcE), .y(PCNext1F)); mux2 #(`XLEN) pcmux1(.d0(PCPlus2or4F), .d1(IEUAdrE), .s(PCSrcE), .y(PC1NextF));
assign BPPredWrongE = PCSrcE; assign BPWrongE = PCSrcE;
assign {InstrClassM, DirPredictionWrongM, BTBPredPCWrongM, RASPredPCWrongM, PredictionInstrClassWrongM} = '0; assign {InstrClassM, BPDirPredWrongM, BTAWrongM, RASPredPCWrongM, IClassWrongM} = '0;
assign NextValidPCE = PCE; assign NextValidPCE = PCE;
end end

View File

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

View File

@ -54,6 +54,7 @@ module lsu (
input logic [1:0] PrivilegeModeW, // Current privilege mode input logic [1:0] PrivilegeModeW, // Current privilege mode
input logic BigEndianM, // Swap byte order to big endian input logic BigEndianM, // Swap byte order to big endian
input logic sfencevmaM, // Virtual memory address fence, invalidate TLB entries input logic sfencevmaM, // Virtual memory address fence, invalidate TLB entries
output logic DCacheStallM, // D$ busy with multicycle operation
// fpu // fpu
input logic [`FLEN-1:0] FWriteDataM, // Write data from FPU input logic [`FLEN-1:0] FWriteDataM, // Write data from FPU
input logic FpLoadStoreM, // Selects FPU as store for write data input logic FpLoadStoreM, // Selects FPU as store for write data
@ -81,7 +82,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
@ -103,7 +104,6 @@ module lsu (
logic GatedStallW; // Hazard unit StallW gated when SelHPTW = 1 logic GatedStallW; // Hazard unit StallW gated when SelHPTW = 1
logic DCacheStallM; // D$ busy with multicycle operation
logic BusStall; // Bus interface busy with multicycle operation logic BusStall; // Bus interface busy with multicycle operation
logic HPTWStall; // HPTW busy with multicycle operation logic HPTWStall; // HPTW busy with multicycle operation
@ -127,7 +127,7 @@ module lsu (
logic DTLBMissM; // DTLB miss causes HPTW walk logic DTLBMissM; // DTLB miss causes HPTW walk
logic DTLBWriteM; // Writes PTE and PageType to DTLB logic DTLBWriteM; // Writes PTE and PageType to DTLB
logic DataDAPageFaultM; // DTLB hit needs to update dirty or access bits logic DataUpdateDAM; // DTLB hit needs to update dirty or access bits
logic LSULoadAccessFaultM; // Load acces fault logic LSULoadAccessFaultM; // Load acces fault
logic LSUStoreAmoAccessFaultM; // Store access fault logic LSUStoreAmoAccessFaultM; // Store access fault
logic IgnoreRequestTLB; // On either ITLB or DTLB miss, ignore miss so HPTW can handle logic IgnoreRequestTLB; // On either ITLB or DTLB miss, ignore miss so HPTW can handle
@ -151,7 +151,7 @@ module lsu (
if(`VIRTMEM_SUPPORTED) begin : VIRTMEM_SUPPORTED if(`VIRTMEM_SUPPORTED) begin : VIRTMEM_SUPPORTED
hptw hptw(.clk, .reset, .MemRWM, .AtomicM, .ITLBMissF, .ITLBWriteF, hptw hptw(.clk, .reset, .MemRWM, .AtomicM, .ITLBMissF, .ITLBWriteF,
.DTLBMissM, .DTLBWriteM, .InstrDAPageFaultF, .DataDAPageFaultM, .DTLBMissM, .DTLBWriteM, .InstrUpdateDAF, .DataUpdateDAM,
.FlushW, .DCacheStallM, .SATP_REGW, .PCFSpill, .FlushW, .DCacheStallM, .SATP_REGW, .PCFSpill,
.STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, .PrivilegeModeW, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, .PrivilegeModeW,
.ReadDataM(ReadDataM[`XLEN-1:0]), // ReadDataM is LLEN, but HPTW only needs XLEN .ReadDataM(ReadDataM[`XLEN-1:0]), // ReadDataM is LLEN, but HPTW only needs XLEN
@ -196,7 +196,7 @@ module lsu (
.StoreAmoAccessFaultM(LSUStoreAmoAccessFaultM), .InstrPageFaultF(), .LoadPageFaultM, .StoreAmoAccessFaultM(LSUStoreAmoAccessFaultM), .InstrPageFaultF(), .LoadPageFaultM,
.StoreAmoPageFaultM, .StoreAmoPageFaultM,
.LoadMisalignedFaultM, .StoreAmoMisalignedFaultM, // *** these faults need to be supressed during hptw. .LoadMisalignedFaultM, .StoreAmoMisalignedFaultM, // *** these faults need to be supressed during hptw.
.DAPageFault(DataDAPageFaultM), .UpdateDA(DataUpdateDAM),
.AtomicAccessM(|LSUAtomicM), .ExecuteAccessF(1'b0), .AtomicAccessM(|LSUAtomicM), .ExecuteAccessF(1'b0),
.WriteAccessM(PreLSURWM[0]), .ReadAccessM(PreLSURWM[1]), .WriteAccessM(PreLSURWM[0]), .ReadAccessM(PreLSURWM[1]),
.PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW); .PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW);

View File

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

View File

@ -38,8 +38,8 @@ module adrdecs (
localparam logic [3:0] SUPPORTED_SIZE = (`LLEN == 32 ? 4'b0111 : 4'b1111); localparam logic [3:0] SUPPORTED_SIZE = (`LLEN == 32 ? 4'b0111 : 4'b1111);
// Determine which region of physical memory (if any) is being accessed // Determine which region of physical memory (if any) is being accessed
adrdec dtimdec(PhysicalAddress, `DTIM_BASE, `DTIM_RANGE, `DTIM_SUPPORTED, AccessRWX, Size, SUPPORTED_SIZE, SelRegions[10]); adrdec dtimdec(PhysicalAddress, `DTIM_BASE, `DTIM_RANGE, `DTIM_SUPPORTED, AccessRW, Size, SUPPORTED_SIZE, SelRegions[10]);
adrdec iromdec(PhysicalAddress, `IROM_BASE, `IROM_RANGE, `IROM_SUPPORTED, AccessRWX, Size, SUPPORTED_SIZE, SelRegions[9]); adrdec iromdec(PhysicalAddress, `IROM_BASE, `IROM_RANGE, `IROM_SUPPORTED, AccessRX, Size, SUPPORTED_SIZE, SelRegions[9]);
adrdec ddr4dec(PhysicalAddress, `EXT_MEM_BASE, `EXT_MEM_RANGE, `EXT_MEM_SUPPORTED, AccessRWX, Size, SUPPORTED_SIZE, SelRegions[8]); adrdec ddr4dec(PhysicalAddress, `EXT_MEM_BASE, `EXT_MEM_RANGE, `EXT_MEM_SUPPORTED, AccessRWX, Size, SUPPORTED_SIZE, SelRegions[8]);
adrdec bootromdec(PhysicalAddress, `BOOTROM_BASE, `BOOTROM_RANGE, `BOOTROM_SUPPORTED, AccessRX, Size, SUPPORTED_SIZE, SelRegions[7]); adrdec bootromdec(PhysicalAddress, `BOOTROM_BASE, `BOOTROM_RANGE, `BOOTROM_SUPPORTED, AccessRX, Size, SUPPORTED_SIZE, SelRegions[7]);
adrdec uncoreramdec(PhysicalAddress, `UNCORE_RAM_BASE, `UNCORE_RAM_RANGE, `UNCORE_RAM_SUPPORTED, AccessRWX, Size, SUPPORTED_SIZE, SelRegions[6]); adrdec uncoreramdec(PhysicalAddress, `UNCORE_RAM_BASE, `UNCORE_RAM_RANGE, `UNCORE_RAM_SUPPORTED, AccessRWX, Size, SUPPORTED_SIZE, SelRegions[6]);

View File

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

View File

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

View File

@ -58,8 +58,12 @@ module pmachecker (
// Only non-core RAM/ROM memory regions are cacheable // Only non-core RAM/ROM memory regions are cacheable
assign Cacheable = SelRegions[8] | SelRegions[7] | SelRegions[6]; assign Cacheable = SelRegions[8] | SelRegions[7] | SelRegions[6];
assign Idempotent = SelRegions[10] | SelRegions[9] | SelRegions[8] | SelRegions[6]; // Nonidemdempotent means access could have side effect and must not be done speculatively or redundantly
assign AtomicAllowed = SelRegions[10] | SelRegions[9] | SelRegions[8] | SelRegions[6]; // I/O is nonidempotent.
assign Idempotent = SelRegions[10] | SelRegions[9] | SelRegions[8] | SelRegions[7] | SelRegions[6];
// Atomic operations are only allowed on RAM
assign AtomicAllowed = SelRegions[10] | SelRegions[8] | SelRegions[6];
// Check if tightly integrated memories are selected
assign SelTIM = SelRegions[10] | SelRegions[9]; assign SelTIM = SelRegions[10] | SelRegions[9];
// Detect access faults // Detect access faults

View File

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

View File

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

View File

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

View File

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

View File

@ -37,13 +37,14 @@ module csr #(parameter
input logic FlushM, FlushW, input logic FlushM, FlushW,
input logic StallE, StallM, StallW, input logic StallE, StallM, StallW,
input logic [31:0] InstrM, // current instruction input logic [31:0] InstrM, // current instruction
input logic [`XLEN-1:0] PCM, PCNext2F, // program counter, next PC going to trap/return logic input logic [`XLEN-1:0] PCM, PC2NextF, // program counter, next PC going to trap/return logic
input logic [`XLEN-1:0] SrcAM, IEUAdrM, // SrcA and memory address from IEU input logic [`XLEN-1:0] SrcAM, IEUAdrM, // SrcA and memory address from IEU
input logic CSRReadM, CSRWriteM, // read or write CSR input logic CSRReadM, CSRWriteM, // read or write CSR
input logic TrapM, // trap is occurring input logic TrapM, // trap is occurring
input logic mretM, sretM, wfiM, // return or WFI instruction input logic mretM, sretM, wfiM, // return or WFI instruction
input logic IntPendingM, // at least one interrupt is pending and could occur if enabled input logic IntPendingM, // at least one interrupt is pending and could occur if enabled
input logic InterruptM, // interrupt is occurring input logic InterruptM, // interrupt is occurring
input logic ExceptionM, // interrupt is occurring
input logic MTimerInt, // timer interrupt input logic MTimerInt, // timer interrupt
input logic MExtInt, SExtInt, // external interrupt (from PLIC) input logic MExtInt, SExtInt, // external interrupt (from PLIC)
input logic MSwInt, // software interrupt input logic MSwInt, // software interrupt
@ -57,17 +58,23 @@ module csr #(parameter
input logic SelHPTW, // hardware page table walker active, so base endianness on supervisor mode input logic SelHPTW, // hardware page table walker active, so base endianness on supervisor mode
// inputs for performance counters // inputs for performance counters
input logic LoadStallD, input logic LoadStallD,
input logic DirPredictionWrongM, input logic StoreStallD,
input logic BTBPredPCWrongM, input logic ICacheStallF,
input logic DCacheStallM,
input logic BPDirPredWrongM,
input logic BTAWrongM,
input logic RASPredPCWrongM, input logic RASPredPCWrongM,
input logic PredictionInstrClassWrongM, input logic IClassWrongM,
input logic BPPredWrongM, // branch predictor is wrong input logic BPWrongM, // branch predictor is wrong
input logic [3:0] InstrClassM, input logic [3:0] InstrClassM,
input logic JumpOrTakenBranchM, // actual instruction class
input logic DCacheMiss, input logic DCacheMiss,
input logic DCacheAccess, input logic DCacheAccess,
input logic ICacheMiss, input logic ICacheMiss,
input logic ICacheAccess, input logic ICacheAccess,
input logic sfencevmaM,
input logic FenceM,
input logic DivBusyE, // integer divide busy
input logic FDivBusyE, // floating point divide busy
// outputs from CSRs // outputs from CSRs
output logic [1:0] STATUS_MPP, output logic [1:0] STATUS_MPP,
output logic STATUS_SPP, STATUS_TSR, STATUS_TVM, output logic STATUS_SPP, STATUS_TSR, STATUS_TVM,
@ -155,7 +162,7 @@ module csr #(parameter
// A return sets the PC to MEPC or SEPC // A return sets the PC to MEPC or SEPC
assign RetM = mretM | sretM; assign RetM = mretM | sretM;
mux2 #(`XLEN) epcmux(SEPC_REGW, MEPC_REGW, mretM, EPC); mux2 #(`XLEN) epcmux(SEPC_REGW, MEPC_REGW, mretM, EPC);
mux3 #(`XLEN) pcmux3(PCNext2F, EPC, TrapVectorM, {TrapM, RetM}, UnalignedPCNextF); mux3 #(`XLEN) pcmux3(PC2NextF, EPC, TrapVectorM, {TrapM, RetM}, UnalignedPCNextF);
/////////////////////////////////////////// ///////////////////////////////////////////
// CSRWriteValM // CSRWriteValM
@ -258,9 +265,10 @@ module csr #(parameter
if (`ZICOUNTERS_SUPPORTED) begin:counters if (`ZICOUNTERS_SUPPORTED) begin:counters
csrc counters(.clk, .reset, .StallE, .StallM, .FlushM, csrc counters(.clk, .reset, .StallE, .StallM, .FlushM,
.InstrValidNotFlushedM, .LoadStallD, .CSRMWriteM, .InstrValidNotFlushedM, .LoadStallD, .StoreStallD, .CSRWriteM, .CSRMWriteM,
.DirPredictionWrongM, .BTBPredPCWrongM, .RASPredPCWrongM, .PredictionInstrClassWrongM, .JumpOrTakenBranchM, .BPPredWrongM, .BPDirPredWrongM, .BTAWrongM, .RASPredPCWrongM, .IClassWrongM, .BPWrongM,
.InstrClassM, .DCacheMiss, .DCacheAccess, .ICacheMiss, .ICacheAccess, .InstrClassM, .DCacheMiss, .DCacheAccess, .ICacheMiss, .ICacheAccess, .sfencevmaM,
.InterruptM, .ExceptionM, .FenceM, .ICacheStallF, .DCacheStallM, .DivBusyE, .FDivBusyE,
.CSRAdrM, .PrivilegeModeW, .CSRWriteValM, .CSRAdrM, .PrivilegeModeW, .CSRWriteValM,
.MCOUNTINHIBIT_REGW, .MCOUNTEREN_REGW, .SCOUNTEREN_REGW, .MCOUNTINHIBIT_REGW, .MCOUNTEREN_REGW, .SCOUNTEREN_REGW,
.MTIME_CLINT, .CSRCReadValM, .IllegalCSRCAccessM); .MTIME_CLINT, .CSRCReadValM, .IllegalCSRCAccessM);

View File

@ -43,20 +43,28 @@ module csrc #(parameter
input logic clk, reset, input logic clk, reset,
input logic StallE, StallM, input logic StallE, StallM,
input logic FlushM, input logic FlushM,
input logic InstrValidNotFlushedM, LoadStallD, CSRMWriteM, input logic InstrValidNotFlushedM, LoadStallD, StoreStallD,
input logic DirPredictionWrongM, input logic CSRMWriteM, CSRWriteM,
input logic BTBPredPCWrongM, input logic BPDirPredWrongM,
input logic BTAWrongM,
input logic RASPredPCWrongM, input logic RASPredPCWrongM,
input logic PredictionInstrClassWrongM, input logic IClassWrongM,
input logic BPPredWrongM, // branch predictor is wrong input logic BPWrongM, // branch predictor is wrong
input logic [3:0] InstrClassM, input logic [3:0] InstrClassM,
input logic JumpOrTakenBranchM, // actual instruction class
input logic DCacheMiss, input logic DCacheMiss,
input logic DCacheAccess, input logic DCacheAccess,
input logic ICacheMiss, input logic ICacheMiss,
input logic ICacheAccess, input logic ICacheAccess,
input logic ICacheStallF,
input logic DCacheStallM,
input logic sfencevmaM,
input logic InterruptM,
input logic ExceptionM,
input logic FenceM,
input logic DivBusyE, // integer divide busy
input logic FDivBusyE, // floating point divide busy
input logic [11:0] CSRAdrM, input logic [11:0] CSRAdrM,
input logic [1:0] PrivilegeModeW, input logic [1:0] PrivilegeModeW,
input logic [`XLEN-1:0] CSRWriteValM, input logic [`XLEN-1:0] CSRWriteValM,
input logic [31:0] MCOUNTINHIBIT_REGW, MCOUNTEREN_REGW, SCOUNTEREN_REGW, input logic [31:0] MCOUNTINHIBIT_REGW, MCOUNTEREN_REGW, SCOUNTEREN_REGW,
input logic [63:0] MTIME_CLINT, input logic [63:0] MTIME_CLINT,
@ -68,6 +76,7 @@ module csrc #(parameter
logic [`XLEN-1:0] HPMCOUNTER_REGW[`COUNTERS-1:0]; logic [`XLEN-1:0] HPMCOUNTER_REGW[`COUNTERS-1:0];
logic [`XLEN-1:0] HPMCOUNTERH_REGW[`COUNTERS-1:0]; logic [`XLEN-1:0] HPMCOUNTERH_REGW[`COUNTERS-1:0];
logic LoadStallE, LoadStallM; logic LoadStallE, LoadStallM;
logic StoreStallE, StoreStallM;
logic [`COUNTERS-1:0] WriteHPMCOUNTERM; logic [`COUNTERS-1:0] WriteHPMCOUNTERM;
logic [`COUNTERS-1:0] CounterEvent; logic [`COUNTERS-1:0] CounterEvent;
logic [63:0] HPMCOUNTERPlusM[`COUNTERS-1:0]; logic [63:0] HPMCOUNTERPlusM[`COUNTERS-1:0];
@ -75,8 +84,8 @@ module csrc #(parameter
genvar i; genvar i;
// Interface signals // Interface signals
flopenrc #(1) LoadStallEReg(.clk, .reset, .clear(1'b0), .en(~StallE), .d(LoadStallD), .q(LoadStallE)); // don't flush the load stall during a load stall. flopenrc #(2) LoadStallEReg(.clk, .reset, .clear(1'b0), .en(~StallE), .d({StoreStallD, LoadStallD}), .q({StoreStallE, LoadStallE})); // don't flush the load stall during a load stall.
flopenrc #(1) LoadStallMReg(.clk, .reset, .clear(FlushM), .en(~StallM), .d(LoadStallE), .q(LoadStallM)); flopenrc #(2) LoadStallMReg(.clk, .reset, .clear(FlushM), .en(~StallM), .d({StoreStallE, LoadStallE}), .q({StoreStallM, LoadStallM}));
// Determine when to increment each counter // Determine when to increment each counter
assign CounterEvent[0] = 1'b1; // MCYCLE always increments assign CounterEvent[0] = 1'b1; // MCYCLE always increments
@ -85,20 +94,29 @@ module csrc #(parameter
if(`QEMU) begin: cevent // No other performance counters in QEMU if(`QEMU) begin: cevent // No other performance counters in QEMU
assign CounterEvent[`COUNTERS-1:3] = 0; assign CounterEvent[`COUNTERS-1:3] = 0;
end else begin: cevent // User-defined counters end else begin: cevent // User-defined counters
assign CounterEvent[3] = LoadStallM & InstrValidNotFlushedM; // Load Stalls. don't want to suppress on flush as this only happens if flushed. assign CounterEvent[3] = InstrClassM[0] & InstrValidNotFlushedM; // branch instruction
assign CounterEvent[4] = DirPredictionWrongM & InstrValidNotFlushedM; // Branch predictor wrong direction assign CounterEvent[4] = InstrClassM[1] & ~InstrClassM[2] & InstrValidNotFlushedM; // jump and not return instructions
assign CounterEvent[5] = InstrClassM[0] & InstrValidNotFlushedM; // branch instruction assign CounterEvent[5] = InstrClassM[2] & InstrValidNotFlushedM; // return instructions
assign CounterEvent[6] = BTBPredPCWrongM & InstrValidNotFlushedM; // branch predictor wrong target assign CounterEvent[6] = BPWrongM & InstrValidNotFlushedM; // branch predictor wrong
assign CounterEvent[7] = JumpOrTakenBranchM & InstrValidNotFlushedM; // jump or taken branch instructions assign CounterEvent[7] = BPDirPredWrongM & InstrValidNotFlushedM; // Branch predictor wrong direction
assign CounterEvent[8] = RASPredPCWrongM & InstrValidNotFlushedM; // return address stack wrong address assign CounterEvent[8] = BTAWrongM & InstrValidNotFlushedM; // branch predictor wrong target
assign CounterEvent[9] = InstrClassM[2] & InstrValidNotFlushedM; // return instructions assign CounterEvent[9] = RASPredPCWrongM & InstrValidNotFlushedM; // return address stack wrong address
assign CounterEvent[10] = PredictionInstrClassWrongM & InstrValidNotFlushedM; // instruction class predictor wrong assign CounterEvent[10] = IClassWrongM & InstrValidNotFlushedM; // instruction class predictor wrong
assign CounterEvent[11] = DCacheAccess & InstrValidNotFlushedM; // data cache access assign CounterEvent[11] = LoadStallM & InstrValidNotFlushedM; // Load Stalls. don't want to suppress on flush as this only happens if flushed.
assign CounterEvent[12] = DCacheMiss; // data cache miss. Miss asserted 1 cycle at start of cache miss assign CounterEvent[12] = StoreStallM & InstrValidNotFlushedM; // Store Stall
assign CounterEvent[13] = ICacheAccess & InstrValidNotFlushedM; // instruction cache access assign CounterEvent[13] = DCacheAccess & InstrValidNotFlushedM; // data cache access
assign CounterEvent[14] = ICacheMiss; // instruction cache miss. Miss asserted 1 cycle at start of cache miss assign CounterEvent[14] = DCacheMiss; // data cache miss. Miss asserted 1 cycle at start of cache miss
assign CounterEvent[15] = BPPredWrongM & InstrValidNotFlushedM; // branch predictor wrong assign CounterEvent[15] = DCacheStallM; // d cache miss cycles
assign CounterEvent[`COUNTERS-1:16] = 0; // eventually give these sources, including FP instructions, I$/D$ misses, branches and mispredictions assign CounterEvent[16] = ICacheAccess & InstrValidNotFlushedM; // instruction cache access
assign CounterEvent[17] = ICacheMiss; // instruction cache miss. Miss asserted 1 cycle at start of cache miss
assign CounterEvent[18] = ICacheStallF; // i cache miss cycles
assign CounterEvent[19] = CSRWriteM & InstrValidNotFlushedM; // CSR writes
assign CounterEvent[20] = FenceM & InstrValidNotFlushedM; // fence.i
assign CounterEvent[21] = sfencevmaM & InstrValidNotFlushedM; // sfence.vma
assign CounterEvent[22] = InterruptM; // interrupt, InstrValidNotFlushedM will be low
assign CounterEvent[23] = ExceptionM; // exceptions, InstrValidNotFlushedM will be low
assign CounterEvent[24] = DivBusyE | FDivBusyE; // division cycles *** RT: might need to be delay until the next cycle
assign CounterEvent[`COUNTERS-1:25] = 0; // eventually give these sources, including FP instructions, I$/D$ misses, branches and mispredictions
end end
// Counter update and write logic // Counter update and write logic

View File

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

View File

@ -38,7 +38,7 @@ module privileged (
input logic [`XLEN-1:0] SrcAM, // GPR register to write input logic [`XLEN-1:0] SrcAM, // GPR register to write
input logic [31:0] InstrM, // Instruction input logic [31:0] InstrM, // Instruction
input logic [`XLEN-1:0] IEUAdrM, // address from IEU input logic [`XLEN-1:0] IEUAdrM, // address from IEU
input logic [`XLEN-1:0] PCM, PCNext2F, // program counter, next PC going to trap/return PC logic input logic [`XLEN-1:0] PCM, PC2NextF, // program counter, next PC going to trap/return PC logic
// control signals // control signals
input logic InstrValidM, // Current instruction is valid (not flushed) input logic InstrValidM, // Current instruction is valid (not flushed)
input logic CommittedM, CommittedF, // current instruction is using bus; don't interrupt input logic CommittedM, CommittedF, // current instruction is using bus; don't interrupt
@ -46,17 +46,21 @@ module privileged (
// processor events for performance counter logging // processor events for performance counter logging
input logic FRegWriteM, // instruction will write floating-point registers input logic FRegWriteM, // instruction will write floating-point registers
input logic LoadStallD, // load instruction is stalling input logic LoadStallD, // load instruction is stalling
input logic DirPredictionWrongM, // branch predictor guessed wrong directoin input logic StoreStallD, // store instruction is stalling
input logic BTBPredPCWrongM, // branch predictor guessed wrong target input logic ICacheStallF, // I cache stalled
input logic RASPredPCWrongM, // return adddress stack guessed wrong target input logic DCacheStallM, // D cache stalled
input logic PredictionInstrClassWrongM, // branch predictor guessed wrong instruction class input logic BPDirPredWrongM, // branch predictor guessed wrong direction
input logic BPPredWrongM, // branch predictor is wrong input logic BTAWrongM, // branch predictor guessed wrong target
input logic RASPredPCWrongM, // return adddress stack guessed wrong target
input logic IClassWrongM, // branch predictor guessed wrong instruction class
input logic BPWrongM, // branch predictor is wrong
input logic [3:0] InstrClassM, // actual instruction class input logic [3:0] InstrClassM, // actual instruction class
input logic JumpOrTakenBranchM, // actual instruction class
input logic DCacheMiss, // data cache miss input logic DCacheMiss, // data cache miss
input logic DCacheAccess, // data cache accessed (hit or miss) input logic DCacheAccess, // data cache accessed (hit or miss)
input logic ICacheMiss, // instruction cache miss input logic ICacheMiss, // instruction cache miss
input logic ICacheAccess, // instruction cache access input logic ICacheAccess, // instruction cache access
input logic DivBusyE, // integer divide busy
input logic FDivBusyE, // floating point divide busy
// fault sources // fault sources
input logic InstrAccessFaultF, // instruction access fault input logic InstrAccessFaultF, // instruction access fault
input logic LoadAccessFaultM, StoreAmoAccessFaultM, // load or store access fault input logic LoadAccessFaultM, StoreAmoAccessFaultM, // load or store access fault
@ -84,6 +88,7 @@ module privileged (
// control outputs // control outputs
output logic RetM, TrapM, // return instruction, or trap output logic RetM, TrapM, // return instruction, or trap
output logic sfencevmaM, // sfence.vma instruction output logic sfencevmaM, // sfence.vma instruction
input logic FenceM, // fence instruction
output logic BigEndianM, // Use big endian in current privilege mode output logic BigEndianM, // Use big endian in current privilege mode
// Fault outputs // Fault outputs
output logic BreakpointFaultM, EcallFaultM, // breakpoint and Ecall traps should retire output logic BreakpointFaultM, EcallFaultM, // breakpoint and Ecall traps should retire
@ -106,9 +111,9 @@ module privileged (
logic DelegateM; // trap should be delegated logic DelegateM; // trap should be delegated
logic wfiM; // wait for interrupt instruction logic wfiM; // wait for interrupt instruction
logic IntPendingM; // interrupt is pending, even if not enabled. ends wfi logic IntPendingM; // interrupt is pending, even if not enabled. ends wfi
logic InterruptM; // interrupt occuring logic InterruptM; // interrupt occuring
logic ExceptionM; // Memory stage instruction caused a fault
// track the current privilege level // track the current privilege level
privmode privmode(.clk, .reset, .StallW, .TrapM, .mretM, .sretM, .DelegateM, privmode privmode(.clk, .reset, .StallW, .TrapM, .mretM, .sretM, .DelegateM,
.STATUS_MPP, .STATUS_SPP, .NextPrivilegeModeM, .PrivilegeModeW); .STATUS_MPP, .STATUS_SPP, .NextPrivilegeModeM, .PrivilegeModeW);
@ -121,12 +126,13 @@ module privileged (
// Control and Status Registers // Control and Status Registers
csr csr(.clk, .reset, .FlushM, .FlushW, .StallE, .StallM, .StallW, csr csr(.clk, .reset, .FlushM, .FlushW, .StallE, .StallM, .StallW,
.InstrM, .PCM, .SrcAM, .IEUAdrM, .PCNext2F, .InstrM, .PCM, .SrcAM, .IEUAdrM, .PC2NextF,
.CSRReadM, .CSRWriteM, .TrapM, .mretM, .sretM, .wfiM, .IntPendingM, .InterruptM, .CSRReadM, .CSRWriteM, .TrapM, .mretM, .sretM, .wfiM, .IntPendingM, .InterruptM,
.MTimerInt, .MExtInt, .SExtInt, .MSwInt, .MTimerInt, .MExtInt, .SExtInt, .MSwInt,
.MTIME_CLINT, .InstrValidM, .FRegWriteM, .LoadStallD, .MTIME_CLINT, .InstrValidM, .FRegWriteM, .LoadStallD, .StoreStallD,
.DirPredictionWrongM, .BTBPredPCWrongM, .RASPredPCWrongM, .BPPredWrongM, .BPDirPredWrongM, .BTAWrongM, .RASPredPCWrongM, .BPWrongM,
.PredictionInstrClassWrongM, .InstrClassM, .DCacheMiss, .DCacheAccess, .ICacheMiss, .ICacheAccess, .JumpOrTakenBranchM, .sfencevmaM, .ExceptionM, .FenceM, .ICacheStallF, .DCacheStallM, .DivBusyE, .FDivBusyE,
.IClassWrongM, .InstrClassM, .DCacheMiss, .DCacheAccess, .ICacheMiss, .ICacheAccess,
.NextPrivilegeModeM, .PrivilegeModeW, .CauseM, .SelHPTW, .NextPrivilegeModeM, .PrivilegeModeW, .CauseM, .SelHPTW,
.STATUS_MPP, .STATUS_SPP, .STATUS_TSR, .STATUS_TVM, .STATUS_MPP, .STATUS_SPP, .STATUS_TSR, .STATUS_TVM,
.STATUS_MIE, .STATUS_SIE, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_TW, .STATUS_FS, .STATUS_MIE, .STATUS_SIE, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_TW, .STATUS_FS,
@ -149,7 +155,7 @@ module privileged (
.mretM, .sretM, .PrivilegeModeW, .mretM, .sretM, .PrivilegeModeW,
.MIP_REGW, .MIE_REGW, .MIDELEG_REGW, .MEDELEG_REGW, .STATUS_MIE, .STATUS_SIE, .MIP_REGW, .MIE_REGW, .MIDELEG_REGW, .MEDELEG_REGW, .STATUS_MIE, .STATUS_SIE,
.InstrValidM, .CommittedM, .CommittedF, .InstrValidM, .CommittedM, .CommittedF,
.TrapM, .RetM, .wfiM, .InterruptM, .IntPendingM, .DelegateM, .WFIStallM, .CauseM); .TrapM, .RetM, .wfiM, .InterruptM, .ExceptionM, .IntPendingM, .DelegateM, .WFIStallM, .CauseM);
endmodule endmodule

View File

@ -45,6 +45,7 @@ module trap (
output logic TrapM, // Trap is occurring output logic TrapM, // Trap is occurring
output logic RetM, // Return instruction being executed output logic RetM, // Return instruction being executed
output logic InterruptM, // Interrupt is occurring output logic InterruptM, // Interrupt is occurring
output logic ExceptionM, // exception is occurring
output logic IntPendingM, // Interrupt is pending, might occur if enabled output logic IntPendingM, // Interrupt is pending, might occur if enabled
output logic DelegateM, // Delegate trap to supervisor handler output logic DelegateM, // Delegate trap to supervisor handler
output logic WFIStallM, // Stall due to WFI instruction output logic WFIStallM, // Stall due to WFI instruction
@ -52,7 +53,6 @@ module trap (
); );
logic MIntGlobalEnM, SIntGlobalEnM; // Global interupt enables logic MIntGlobalEnM, SIntGlobalEnM; // Global interupt enables
logic ExceptionM; // exception is occurring
logic Committed; // LSU or IFU has committed to a bus operation that can't be interrupted logic Committed; // LSU or IFU has committed to a bus operation that can't be interrupted
logic BothInstrAccessFaultM; // instruction or HPTW ITLB fill caused an Instruction Access Fault logic BothInstrAccessFaultM; // instruction or HPTW ITLB fill caused an Instruction Access Fault
logic [11:0] PendingIntsM, ValidIntsM, EnabledIntsM; // interrupts are pending, valid, or enabled logic [11:0] PendingIntsM, ValidIntsM, EnabledIntsM; // interrupts are pending, valid, or enabled

View File

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

View File

@ -66,7 +66,7 @@ module wallypipelinedcore (
logic [`XLEN-1:0] PCFSpill, PCE, PCLinkE; logic [`XLEN-1:0] PCFSpill, PCE, PCLinkE;
logic [`XLEN-1:0] PCM; logic [`XLEN-1:0] PCM;
logic [`XLEN-1:0] CSRReadValW, MDUResultW; logic [`XLEN-1:0] CSRReadValW, MDUResultW;
logic [`XLEN-1:0] UnalignedPCNextF, PCNext2F; logic [`XLEN-1:0] UnalignedPCNextF, PC2NextF;
logic [1:0] MemRWM; logic [1:0] MemRWM;
logic InstrValidD, InstrValidE, InstrValidM; logic InstrValidD, InstrValidE, InstrValidM;
logic InstrMisalignedFaultM; logic InstrMisalignedFaultM;
@ -140,11 +140,11 @@ module wallypipelinedcore (
logic LSUHWRITE; logic LSUHWRITE;
logic LSUHREADY; logic LSUHREADY;
logic BPPredWrongE, BPPredWrongM; logic BPWrongE, BPWrongM;
logic DirPredictionWrongM; logic BPDirPredWrongM;
logic BTBPredPCWrongM; logic BTAWrongM;
logic RASPredPCWrongM; logic RASPredPCWrongM;
logic PredictionInstrClassWrongM; logic IClassWrongM;
logic [3:0] InstrClassM; logic [3:0] InstrClassM;
logic InstrAccessFaultF, HPTWInstrAccessFaultM; logic InstrAccessFaultF, HPTWInstrAccessFaultM;
logic [2:0] LSUHSIZE; logic [2:0] LSUHSIZE;
@ -156,35 +156,36 @@ 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;
logic JumpOrTakenBranchM;
logic BranchD, BranchE, JumpD, JumpE; logic BranchD, BranchE, JumpD, JumpE;
logic FenceM;
logic DCacheStallM, ICacheStallF;
// instruction fetch unit: PC, branch prediction, instruction cache // instruction fetch unit: PC, branch prediction, instruction cache
ifu ifu(.clk, .reset, ifu ifu(.clk, .reset,
.StallF, .StallD, .StallE, .StallM, .StallW, .FlushD, .FlushE, .FlushM, .FlushW, .StallF, .StallD, .StallE, .StallM, .StallW, .FlushD, .FlushE, .FlushM, .FlushW,
.InstrValidM, .InstrValidE, .InstrValidD, .InstrValidM, .InstrValidE, .InstrValidD,
.BranchD, .BranchE, .JumpD, .JumpE, .BranchD, .BranchE, .JumpD, .JumpE, .ICacheStallF,
// Fetch // Fetch
.HRDATA, .PCFSpill, .IFUHADDR, .PCNext2F, .HRDATA, .PCFSpill, .IFUHADDR, .PC2NextF,
.IFUStallF, .IFUHBURST, .IFUHTRANS, .IFUHSIZE, .IFUHREADY, .IFUHWRITE, .IFUStallF, .IFUHBURST, .IFUHTRANS, .IFUHSIZE, .IFUHREADY, .IFUHWRITE,
.ICacheAccess, .ICacheMiss, .ICacheAccess, .ICacheMiss,
// Execute // Execute
.PCLinkE, .PCSrcE, .IEUAdrE, .IEUAdrM, .PCE, .BPPredWrongE, .BPPredWrongM, .PCLinkE, .PCSrcE, .IEUAdrE, .IEUAdrM, .PCE, .BPWrongE, .BPWrongM,
// Mem // Mem
.CommittedF, .UnalignedPCNextF, .InvalidateICacheM, .CSRWriteFenceM, .CommittedF, .UnalignedPCNextF, .InvalidateICacheM, .CSRWriteFenceM,
.InstrD, .InstrM, .PCM, .InstrClassM, .DirPredictionWrongM, .JumpOrTakenBranchM, .InstrD, .InstrM, .PCM, .InstrClassM, .BPDirPredWrongM,
.BTBPredPCWrongM, .RASPredPCWrongM, .PredictionInstrClassWrongM, .BTAWrongM, .RASPredPCWrongM, .IClassWrongM,
// Faults out // Faults out
.IllegalBaseInstrD, .IllegalFPUInstrD, .InstrPageFaultF, .IllegalIEUFPUInstrD, .InstrMisalignedFaultM, .IllegalBaseInstrD, .IllegalFPUInstrD, .InstrPageFaultF, .IllegalIEUFPUInstrD, .InstrMisalignedFaultM,
// mmu management // mmu management
.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,
@ -208,7 +209,7 @@ module wallypipelinedcore (
// hazards // hazards
.StallD, .StallE, .StallM, .StallW, .FlushD, .FlushE, .FlushM, .FlushW, .StallD, .StallE, .StallM, .StallW, .FlushD, .FlushE, .FlushM, .FlushW,
.FCvtIntStallD, .LoadStallD, .MDUStallD, .CSRRdStallD, .PCSrcE, .FCvtIntStallD, .LoadStallD, .MDUStallD, .CSRRdStallD, .PCSrcE,
.CSRReadM, .CSRWriteM, .PrivilegedM, .CSRWriteFenceM, .StoreStallD); .CSRReadM, .CSRWriteM, .PrivilegedM, .CSRWriteFenceM, .FenceM, .StoreStallD);
lsu lsu( lsu lsu(
.clk, .reset, .StallM, .FlushM, .StallW, .FlushW, .clk, .reset, .StallM, .FlushM, .StallW, .FlushW,
@ -231,6 +232,7 @@ module wallypipelinedcore (
.STATUS_MPRV, // from csr .STATUS_MPRV, // from csr
.STATUS_MPP, // from csr .STATUS_MPP, // from csr
.sfencevmaM, // connects to privilege .sfencevmaM, // connects to privilege
.DCacheStallM, // connects to privilege
.LoadPageFaultM, // connects to privilege .LoadPageFaultM, // connects to privilege
.StoreAmoPageFaultM, // connects to privilege .StoreAmoPageFaultM, // connects to privilege
.LoadMisalignedFaultM, // connects to privilege .LoadMisalignedFaultM, // connects to privilege
@ -238,7 +240,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);
@ -268,7 +270,7 @@ module wallypipelinedcore (
// global stall and flush control // global stall and flush control
hazard hzu( hazard hzu(
.BPPredWrongE, .CSRWriteFenceM, .RetM, .TrapM, .BPWrongE, .CSRWriteFenceM, .RetM, .TrapM,
.LoadStallD, .StoreStallD, .MDUStallD, .CSRRdStallD, .LoadStallD, .StoreStallD, .MDUStallD, .CSRRdStallD,
.LSUStallM, .IFUStallF, .LSUStallM, .IFUStallF,
.FCvtIntStallD, .FPUStallD, .FCvtIntStallD, .FPUStallD,
@ -284,14 +286,14 @@ module wallypipelinedcore (
privileged priv( privileged priv(
.clk, .reset, .clk, .reset,
.FlushD, .FlushE, .FlushM, .FlushW, .StallD, .StallE, .StallM, .StallW, .FlushD, .FlushE, .FlushM, .FlushW, .StallD, .StallE, .StallM, .StallW,
.CSRReadM, .CSRWriteM, .SrcAM, .PCM, .PCNext2F, .CSRReadM, .CSRWriteM, .SrcAM, .PCM, .PC2NextF,
.InstrM, .CSRReadValW, .UnalignedPCNextF, .InstrM, .CSRReadValW, .UnalignedPCNextF,
.RetM, .TrapM, .sfencevmaM, .RetM, .TrapM, .sfencevmaM, .FenceM, .DCacheStallM, .ICacheStallF,
.InstrValidM, .CommittedM, .CommittedF, .InstrValidM, .CommittedM, .CommittedF,
.FRegWriteM, .LoadStallD, .FRegWriteM, .LoadStallD, .StoreStallD,
.DirPredictionWrongM, .BTBPredPCWrongM, .BPPredWrongM, .BPDirPredWrongM, .BTAWrongM, .BPWrongM,
.RASPredPCWrongM, .PredictionInstrClassWrongM, .RASPredPCWrongM, .IClassWrongM, .DivBusyE, .FDivBusyE,
.InstrClassM, .JumpOrTakenBranchM, .DCacheMiss, .DCacheAccess, .ICacheMiss, .ICacheAccess, .PrivilegedM, .InstrClassM, .DCacheMiss, .DCacheAccess, .ICacheMiss, .ICacheAccess, .PrivilegedM,
.InstrPageFaultF, .LoadPageFaultM, .StoreAmoPageFaultM, .InstrPageFaultF, .LoadPageFaultM, .StoreAmoPageFaultM,
.InstrMisalignedFaultM, .IllegalIEUFPUInstrD, .InstrMisalignedFaultM, .IllegalIEUFPUInstrD,
.LoadMisalignedFaultM, .StoreAmoMisalignedFaultM, .LoadMisalignedFaultM, .StoreAmoMisalignedFaultM,
@ -304,7 +306,7 @@ module wallypipelinedcore (
.FRM_REGW,.BreakpointFaultM, .EcallFaultM, .WFIStallM, .BigEndianM); .FRM_REGW,.BreakpointFaultM, .EcallFaultM, .WFIStallM, .BigEndianM);
end else begin end else begin
assign CSRReadValW = 0; assign CSRReadValW = 0;
assign UnalignedPCNextF = PCNext2F; assign UnalignedPCNextF = PC2NextF;
assign RetM = 0; assign RetM = 0;
assign TrapM = 0; assign TrapM = 0;
assign WFIStallM = 0; assign WFIStallM = 0;
@ -313,7 +315,7 @@ module wallypipelinedcore (
end end
// multiply/divide unit // multiply/divide unit
if (`M_SUPPORTED) begin:mdu if (`M_SUPPORTED | `ZMMUL_SUPPORTED) begin:mdu
mdu mdu(.clk, .reset, .StallM, .StallW, .FlushE, .FlushM, .FlushW, mdu mdu(.clk, .reset, .StallM, .StallW, .FlushE, .FlushM, .FlushW,
.ForwardedSrcAE, .ForwardedSrcBE, .ForwardedSrcAE, .ForwardedSrcBE,
.Funct3E, .Funct3M, .IntDivE, .W64E, .Funct3E, .Funct3M, .IntDivE, .W64E,

View File

@ -12,7 +12,7 @@ export MOD ?= orig
# title to add a note in the synth's directory name # title to add a note in the synth's directory name
TITLE = TITLE =
# tsmc28, sky130, and sky90 presently supported # tsmc28, sky130, and sky90 presently supported
export TECH ?= tsmc28 export TECH ?= sky90
# MAXCORES allows parallel compilation, which is faster but less CPU-efficient # MAXCORES allows parallel compilation, which is faster but less CPU-efficient
# Avoid when doing sweeps of many optimization points in parallel # Avoid when doing sweeps of many optimization points in parallel
export MAXCORES ?= 1 export MAXCORES ?= 1

View File

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

View File

@ -137,17 +137,24 @@ module testbench;
.CMP_CSR (1) .CMP_CSR (1)
) idv_trace2api(rvvi); ) idv_trace2api(rvvi);
int PRIV_RWX = RVVI_MEMORY_PRIVILEGE_READ | RVVI_MEMORY_PRIVILEGE_WRITE | RVVI_MEMORY_PRIVILEGE_EXEC;
int PRIV_RW = RVVI_MEMORY_PRIVILEGE_READ | RVVI_MEMORY_PRIVILEGE_WRITE;
int PRIV_X = RVVI_MEMORY_PRIVILEGE_EXEC;
initial begin initial begin
MAX_ERRS = 3; MAX_ERRS = 3;
// Initialize REF (do this before initializing the DUT) // Initialize REF (do this before initializing the DUT)
if (!rvviVersionCheck(RVVI_API_VERSION)) begin if (!rvviVersionCheck(RVVI_API_VERSION)) begin
msgfatal($sformatf("%m @ t=%0t: Expecting RVVI API version %0d.", $time, RVVI_API_VERSION)); msgfatal($sformatf("%m @ t=%0t: Expecting RVVI API version %0d.", $time, RVVI_API_VERSION));
end end
void'(rvviRefConfigSetString(IDV_CONFIG_MODEL_VENDOR, "riscv.ovpworld.org")); void'(rvviRefConfigSetString(IDV_CONFIG_MODEL_VENDOR, "riscv.ovpworld.org"));
void'(rvviRefConfigSetString(IDV_CONFIG_MODEL_NAME, "riscv")); void'(rvviRefConfigSetString(IDV_CONFIG_MODEL_NAME, "riscv"));
void'(rvviRefConfigSetString(IDV_CONFIG_MODEL_VARIANT, "RV64GC")); void'(rvviRefConfigSetString(IDV_CONFIG_MODEL_VARIANT, "RV64GC"));
void'(rvviRefConfigSetInt(IDV_CONFIG_MODEL_ADDRESS_BUS_WIDTH, 39)); void'(rvviRefConfigSetInt(IDV_CONFIG_MODEL_ADDRESS_BUS_WIDTH, 39));
void'(rvviRefConfigSetInt(IDV_CONFIG_MAX_NET_LATENCY_RETIREMENTS, 6));
if (!rvviRefInit(elffilename)) begin if (!rvviRefInit(elffilename)) begin
msgfatal($sformatf("%m @ t=%0t: rvviRefInit failed", $time)); msgfatal($sformatf("%m @ t=%0t: rvviRefInit failed", $time));
end end
@ -158,6 +165,41 @@ module testbench;
void'(rvviRefCsrSetVolatile(0, 32'hC02)); // INSTRET void'(rvviRefCsrSetVolatile(0, 32'hC02)); // INSTRET
void'(rvviRefCsrSetVolatile(0, 32'hB02)); // MINSTRET void'(rvviRefCsrSetVolatile(0, 32'hB02)); // MINSTRET
void'(rvviRefCsrSetVolatile(0, 32'hC01)); // TIME void'(rvviRefCsrSetVolatile(0, 32'hC01)); // TIME
// cannot predict this register due to latency between
// pending and taken
void'(rvviRefCsrSetVolatile(0, 32'h344)); // MIP
void'(rvviRefCsrSetVolatile(0, 32'h144)); // SIP
// Memory lo, hi, priv (RVVI_MEMORY_PRIVILEGE_{READ,WRITE,EXEC})
void'(rvviRefMemorySetPrivilege(56'h0, 56'h7fffffffff, 0));
if (`BOOTROM_SUPPORTED)
void'(rvviRefMemorySetPrivilege(`BOOTROM_BASE, (`BOOTROM_BASE + `BOOTROM_RANGE), PRIV_X));
if (`UNCORE_RAM_SUPPORTED)
void'(rvviRefMemorySetPrivilege(`UNCORE_RAM_BASE, (`UNCORE_RAM_BASE + `UNCORE_RAM_RANGE), PRIV_RWX));
if (`EXT_MEM_SUPPORTED)
void'(rvviRefMemorySetPrivilege(`EXT_MEM_BASE, (`EXT_MEM_BASE + `EXT_MEM_RANGE), PRIV_RWX));
if (`CLINT_SUPPORTED) begin
void'(rvviRefMemorySetPrivilege(`CLINT_BASE, (`CLINT_BASE + `CLINT_RANGE), PRIV_RW));
void'(rvviRefMemorySetVolatile(`CLINT_BASE, (`CLINT_BASE + `CLINT_RANGE)));
end
if (`GPIO_SUPPORTED) begin
void'(rvviRefMemorySetPrivilege(`GPIO_BASE, (`GPIO_BASE + `GPIO_RANGE), PRIV_RW));
void'(rvviRefMemorySetVolatile(`GPIO_BASE, (`GPIO_BASE + `GPIO_RANGE)));
end
if (`UART_SUPPORTED) begin
void'(rvviRefMemorySetPrivilege(`UART_BASE, (`UART_BASE + `UART_RANGE), PRIV_RW));
void'(rvviRefMemorySetVolatile(`UART_BASE, (`UART_BASE + `UART_RANGE)));
end
if (`PLIC_SUPPORTED) begin
void'(rvviRefMemorySetPrivilege(`PLIC_BASE, (`PLIC_BASE + `PLIC_RANGE), PRIV_RW));
void'(rvviRefMemorySetVolatile(`PLIC_BASE, (`PLIC_BASE + `PLIC_RANGE)));
end
if (`SDC_SUPPORTED) begin
void'(rvviRefMemorySetPrivilege(`SDC_BASE, (`SDC_BASE + `SDC_RANGE), PRIV_RW));
void'(rvviRefMemorySetVolatile(`SDC_BASE, (`SDC_BASE + `SDC_RANGE)));
end
if(`XLEN==32) begin if(`XLEN==32) begin
void'(rvviRefCsrSetVolatile(0, 32'hC80)); // CYCLEH void'(rvviRefCsrSetVolatile(0, 32'hC80)); // CYCLEH
@ -166,16 +208,24 @@ module testbench;
void'(rvviRefCsrSetVolatile(0, 32'hB82)); // MINSTRETH void'(rvviRefCsrSetVolatile(0, 32'hB82)); // MINSTRETH
end end
// Enable the trace2log module void'(rvviRefCsrSetVolatile(0, 32'h104)); // SIE - Temporary!!!!
if ($value$plusargs("TRACE2LOG_ENABLE=%d", TRACE2LOG_ENABLE)) begin
msgnote($sformatf("%m @ t=%0t: TRACE2LOG_ENABLE is %0d", $time, TRACE2LOG_ENABLE));
end
if ($value$plusargs("TRACE2COV_ENABLE=%d", TRACE2COV_ENABLE)) begin // These should be done in the attached client
msgnote($sformatf("%m @ t=%0t: TRACE2COV_ENABLE is %0d", $time, TRACE2COV_ENABLE)); // // Enable the trace2log module
end // if ($value$plusargs("TRACE2LOG_ENABLE=%d", TRACE2LOG_ENABLE)) begin
// msgnote($sformatf("%m @ t=%0t: TRACE2LOG_ENABLE is %0d", $time, TRACE2LOG_ENABLE));
// end
//
// if ($value$plusargs("TRACE2COV_ENABLE=%d", TRACE2COV_ENABLE)) begin
// msgnote($sformatf("%m @ t=%0t: TRACE2COV_ENABLE is %0d", $time, TRACE2COV_ENABLE));
// end
end end
always @(dut.core.MTimerInt) void'(rvvi.net_push("MTimerInterrupt", dut.core.MTimerInt));
always @(dut.core.MExtInt) void'(rvvi.net_push("MExternalInterrupt", dut.core.MExtInt));
always @(dut.core.SExtInt) void'(rvvi.net_push("SExternalInterrupt", dut.core.SExtInt));
always @(dut.core.MSwInt) void'(rvvi.net_push("MSWInterrupt", dut.core.MSwInt));
final begin final begin
void'(rvviRefShutdown()); void'(rvviRefShutdown());
end end