mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-11 06:05:49 +00:00
Merge branch 'main' of https://github.com/openhwgroup/cvw into dev
This commit is contained in:
commit
325a670435
@ -28,55 +28,55 @@
|
|||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
module datapath import cvw::*; #(parameter cvw_t P) (
|
module datapath import cvw::*; #(parameter cvw_t P) (
|
||||||
input logic clk, reset,
|
input logic clk, reset,
|
||||||
// Decode stage signals
|
// Decode stage signals
|
||||||
input logic [2:0] ImmSrcD, // Selects type of immediate extension
|
input logic [2:0] ImmSrcD, // Selects type of immediate extension
|
||||||
input logic [31:0] InstrD, // Instruction in Decode stage
|
input logic [31:0] InstrD, // Instruction in Decode stage
|
||||||
// Execute stage signals
|
// Execute stage signals
|
||||||
input logic [P.XLEN-1:0] PCE, // PC in Execute stage
|
input logic [P.XLEN-1:0] PCE, // PC in Execute stage
|
||||||
input logic [P.XLEN-1:0] PCLinkE, // PC + 4 (of instruction in Execute stage)
|
input logic [P.XLEN-1:0] PCLinkE, // PC + 4 (of instruction in Execute stage)
|
||||||
input logic [2:0] Funct3E, // Funct3 field of instruction in Execute stage
|
input logic [2:0] Funct3E, // Funct3 field of instruction in Execute stage
|
||||||
input logic StallE, FlushE, // Stall, flush Execute stage
|
input logic StallE, FlushE, // Stall, flush Execute stage
|
||||||
input logic [1:0] ForwardAE, ForwardBE, // Forward ALU operands from later stages
|
input logic [1:0] ForwardAE, ForwardBE, // Forward ALU operands from later stages
|
||||||
input logic W64E, // W64-type instruction
|
input logic W64E, // W64-type instruction
|
||||||
input logic SubArithE, // Subtraction or arithmetic shift
|
input logic SubArithE, // Subtraction or arithmetic shift
|
||||||
input logic ALUSrcAE, ALUSrcBE, // ALU operands
|
input logic ALUSrcAE, ALUSrcBE, // ALU operands
|
||||||
input logic ALUResultSrcE, // Selects result to pass on to Memory stage
|
input logic ALUResultSrcE, // Selects result to pass on to Memory stage
|
||||||
input logic [2:0] ALUSelectE, // ALU mux select signal
|
input logic [2:0] ALUSelectE, // ALU mux select signal
|
||||||
input logic JumpE, // Is a jump (j) instruction
|
input logic JumpE, // Is a jump (j) instruction
|
||||||
input logic BranchSignedE, // Branch comparison operands are signed (if it's a branch)
|
input logic BranchSignedE, // Branch comparison operands are signed (if it's a branch)
|
||||||
input logic [1:0] BSelectE, // One hot encoding of ZBA_ZBB_ZBC_ZBS instruction
|
input logic [1:0] BSelectE, // One hot encoding of ZBA_ZBB_ZBC_ZBS instruction
|
||||||
input logic [2:0] ZBBSelectE, // ZBB mux select signal
|
input logic [2:0] ZBBSelectE, // ZBB mux select signal
|
||||||
input logic [2:0] BALUControlE, // ALU Control signals for B instructions in Execute Stage
|
input logic [2:0] BALUControlE, // ALU Control signals for B instructions in Execute Stage
|
||||||
output logic [1:0] FlagsE, // Comparison flags ({eq, lt})
|
output logic [1:0] FlagsE, // Comparison flags ({eq, lt})
|
||||||
output logic [P.XLEN-1:0] IEUAdrE, // Address computed by ALU
|
output logic [P.XLEN-1:0] IEUAdrE, // Address computed by ALU
|
||||||
output logic [P.XLEN-1:0] ForwardedSrcAE, ForwardedSrcBE, // ALU sources before the mux chooses between them and PCE to put in srcA/B
|
output logic [P.XLEN-1:0] ForwardedSrcAE, ForwardedSrcBE, // ALU sources before the mux chooses between them and PCE to put in srcA/B
|
||||||
// Memory stage signals
|
// Memory stage signals
|
||||||
input logic StallM, FlushM, // Stall, flush Memory stage
|
input logic StallM, FlushM, // Stall, flush Memory stage
|
||||||
input logic FWriteIntM, FCvtIntW, // FPU writes integer register file, FPU converts float to int
|
input logic FWriteIntM, FCvtIntW, // FPU writes integer register file, FPU converts float to int
|
||||||
input logic [P.XLEN-1:0] FIntResM, // FPU integer result
|
input logic [P.XLEN-1:0] FIntResM, // FPU integer result
|
||||||
output logic [P.XLEN-1:0] SrcAM, // ALU's Source A in Memory stage to privilege unit for CSR writes
|
output logic [P.XLEN-1:0] SrcAM, // ALU's Source A in Memory stage to privilege unit for CSR writes
|
||||||
output logic [P.XLEN-1:0] WriteDataM, // Write data in Memory stage
|
output logic [P.XLEN-1:0] WriteDataM, // Write data in Memory stage
|
||||||
// Writeback stage signals
|
// Writeback stage signals
|
||||||
input logic StallW, FlushW, // Stall, flush Writeback stage
|
input logic StallW, FlushW, // Stall, flush Writeback stage
|
||||||
input logic RegWriteW, IntDivW, // Write register file, integer divide instruction
|
input logic RegWriteW, IntDivW, // Write register file, integer divide instruction
|
||||||
input logic SquashSCW, // Squash a store conditional when a conflict arose
|
input logic SquashSCW, // Squash a store conditional when a conflict arose
|
||||||
input logic [2:0] ResultSrcW, // Select source of result to write back to register file
|
input logic [2:0] ResultSrcW, // Select source of result to write back to register file
|
||||||
input logic [P.XLEN-1:0] FCvtIntResW, // FPU convert fp to integer result
|
input logic [P.XLEN-1:0] FCvtIntResW, // FPU convert fp to integer result
|
||||||
input logic [P.XLEN-1:0] ReadDataW, // Read data from LSU
|
input logic [P.XLEN-1:0] ReadDataW, // Read data from LSU
|
||||||
input logic [P.XLEN-1:0] CSRReadValW, // CSR read result
|
input logic [P.XLEN-1:0] CSRReadValW, // CSR read result
|
||||||
input logic [P.XLEN-1:0] MDUResultW, // MDU (Multiply/divide unit) result
|
input logic [P.XLEN-1:0] MDUResultW, // MDU (Multiply/divide unit) result
|
||||||
input logic [P.XLEN-1:0] FIntDivResultW, // FPU's integer divide result
|
input logic [P.XLEN-1:0] FIntDivResultW, // FPU's integer divide result
|
||||||
// Hazard Unit signals
|
// Hazard Unit signals
|
||||||
output logic [4:0] Rs1D, Rs2D, Rs1E, Rs2E, // Register sources to read in Decode or Execute stage
|
output logic [4:0] Rs1D, Rs2D, Rs1E, Rs2E, // Register sources to read in Decode or Execute stage
|
||||||
output logic [4:0] RdE, RdM, RdW // Register destinations in Execute, Memory, or Writeback stage
|
output logic [4:0] RdE, RdM, RdW // Register destinations in Execute, Memory, or Writeback stage
|
||||||
);
|
);
|
||||||
|
|
||||||
// Fetch stage signals
|
// Fetch stage signals
|
||||||
// Decode stage signals
|
// Decode stage signals
|
||||||
logic [P.XLEN-1:0] R1D, R2D; // Read data from Rs1 (RD1), Rs2 (RD2)
|
logic [P.XLEN-1:0] R1D, R2D; // Read data from Rs1 (RD1), Rs2 (RD2)
|
||||||
logic [P.XLEN-1:0] ImmExtD; // Extended immediate in Decode stage
|
logic [P.XLEN-1:0] ImmExtD; // Extended immediate in Decode stage
|
||||||
logic [4:0] RdD; // Destination register in Decode stage
|
logic [4:0] RdD; // Destination register in Decode stage
|
||||||
// Execute stage signals
|
// Execute stage signals
|
||||||
logic [P.XLEN-1:0] R1E, R2E; // Source operands read from register file
|
logic [P.XLEN-1:0] R1E, R2E; // Source operands read from register file
|
||||||
logic [P.XLEN-1:0] ImmExtE; // Extended immediate in Execute stage
|
logic [P.XLEN-1:0] ImmExtE; // Extended immediate in Execute stage
|
||||||
@ -103,9 +103,9 @@ module datapath import cvw::*; #(parameter cvw_t P) (
|
|||||||
flopenrc #(P.XLEN) RD1EReg(clk, reset, FlushE, ~StallE, R1D, R1E);
|
flopenrc #(P.XLEN) RD1EReg(clk, reset, FlushE, ~StallE, R1D, R1E);
|
||||||
flopenrc #(P.XLEN) RD2EReg(clk, reset, FlushE, ~StallE, R2D, R2E);
|
flopenrc #(P.XLEN) RD2EReg(clk, reset, FlushE, ~StallE, R2D, R2E);
|
||||||
flopenrc #(P.XLEN) ImmExtEReg(clk, reset, FlushE, ~StallE, ImmExtD, ImmExtE);
|
flopenrc #(P.XLEN) ImmExtEReg(clk, reset, FlushE, ~StallE, ImmExtD, ImmExtE);
|
||||||
flopenrc #(5) Rs1EReg(clk, reset, FlushE, ~StallE, Rs1D, Rs1E);
|
flopenrc #(5) Rs1EReg(clk, reset, FlushE, ~StallE, Rs1D, Rs1E);
|
||||||
flopenrc #(5) Rs2EReg(clk, reset, FlushE, ~StallE, Rs2D, Rs2E);
|
flopenrc #(5) Rs2EReg(clk, reset, FlushE, ~StallE, Rs2D, Rs2E);
|
||||||
flopenrc #(5) RdEReg(clk, reset, FlushE, ~StallE, RdD, RdE);
|
flopenrc #(5) RdEReg(clk, reset, FlushE, ~StallE, RdD, RdE);
|
||||||
|
|
||||||
mux3 #(P.XLEN) faemux(R1E, ResultW, IFResultM, ForwardAE, ForwardedSrcAE);
|
mux3 #(P.XLEN) faemux(R1E, ResultW, IFResultM, ForwardAE, ForwardedSrcAE);
|
||||||
mux3 #(P.XLEN) fbemux(R2E, ResultW, IFResultM, ForwardBE, ForwardedSrcBE);
|
mux3 #(P.XLEN) fbemux(R2E, ResultW, IFResultM, ForwardBE, ForwardedSrcBE);
|
||||||
@ -144,5 +144,5 @@ module datapath import cvw::*; #(parameter cvw_t P) (
|
|||||||
|
|
||||||
// handle Store Conditional result if atomic extension supported
|
// handle Store Conditional result if atomic extension supported
|
||||||
if (P.A_SUPPORTED) assign SCResultW = {{(P.XLEN-1){1'b0}}, SquashSCW};
|
if (P.A_SUPPORTED) assign SCResultW = {{(P.XLEN-1){1'b0}}, SquashSCW};
|
||||||
else assign SCResultW = 0;
|
else assign SCResultW = 0;
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
module extend #(parameter XLEN, A_SUPPORTED) (
|
module extend #(parameter XLEN, A_SUPPORTED) (
|
||||||
input logic [31:7] InstrD, // All instruction bits except opcode (lower 7 bits)
|
input logic [31:7] InstrD, // All instruction bits except opcode (lower 7 bits)
|
||||||
input logic [2:0] ImmSrcD, // Select what kind of extension to perform
|
input logic [2:0] ImmSrcD, // Select what kind of extension to perform
|
||||||
output logic [XLEN-1:0 ] ImmExtD); // Extended immediate
|
output logic [XLEN-1:0] ImmExtD); // Extended immediate
|
||||||
|
|
||||||
localparam [XLEN-1:0] undefined = {(XLEN){1'bx}}; // could change to 0 after debug
|
localparam [XLEN-1:0] undefined = {(XLEN){1'bx}}; // could change to 0 after debug
|
||||||
|
|
||||||
@ -45,10 +45,10 @@ module extend #(parameter XLEN, A_SUPPORTED) (
|
|||||||
// J-type (jal)
|
// J-type (jal)
|
||||||
3'b011: ImmExtD = {{(XLEN-20){InstrD[31]}}, InstrD[19:12], InstrD[20], InstrD[30:21], 1'b0};
|
3'b011: ImmExtD = {{(XLEN-20){InstrD[31]}}, InstrD[19:12], InstrD[20], InstrD[30:21], 1'b0};
|
||||||
// U-type (lui, auipc)
|
// U-type (lui, auipc)
|
||||||
3'b100: ImmExtD = {{(XLEN-31){InstrD[31]}}, InstrD[30:12], 12'b0};
|
3'b100: ImmExtD = {{(XLEN-31){InstrD[31]}}, InstrD[30:12], 12'b0};
|
||||||
// Store Conditional: zero offset
|
// Store Conditional: zero offset
|
||||||
3'b101: if (A_SUPPORTED) ImmExtD = 0;
|
3'b101: if (A_SUPPORTED) ImmExtD = 0;
|
||||||
else ImmExtD = undefined;
|
else ImmExtD = undefined;
|
||||||
default: ImmExtD = undefined; // undefined
|
default: ImmExtD = undefined; // undefined
|
||||||
endcase
|
endcase
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -26,7 +26,6 @@
|
|||||||
// and limitations under the License.
|
// and limitations under the License.
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
module ieu import cvw::*; #(parameter cvw_t P) (
|
module ieu import cvw::*; #(parameter cvw_t P) (
|
||||||
input logic clk, reset,
|
input logic clk, reset,
|
||||||
// Decode stage signals
|
// Decode stage signals
|
||||||
@ -34,36 +33,36 @@ module ieu import cvw::*; #(parameter cvw_t P) (
|
|||||||
input logic IllegalIEUFPUInstrD, // Illegal instruction
|
input logic IllegalIEUFPUInstrD, // Illegal 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 signals
|
// Execute stage signals
|
||||||
input logic [P.XLEN-1:0] PCE, // PC
|
input logic [P.XLEN-1:0] PCE, // PC
|
||||||
input logic [P.XLEN-1:0] PCLinkE, // PC + 4
|
input logic [P.XLEN-1:0] PCLinkE, // PC + 4
|
||||||
output logic PCSrcE, // Select next PC (between PC+4 and IEUAdrE)
|
output logic PCSrcE, // Select next PC (between PC+4 and IEUAdrE)
|
||||||
input logic FWriteIntE, FCvtIntE, // FPU writes to integer register file, FPU converts float to int
|
input logic FWriteIntE, FCvtIntE, // FPU writes to integer register file, FPU converts float to int
|
||||||
output logic [P.XLEN-1:0] IEUAdrE, // Memory address
|
output logic [P.XLEN-1:0] IEUAdrE, // Memory address
|
||||||
output logic IntDivE, W64E, // Integer divide, RV64 W-type instruction
|
output logic IntDivE, W64E, // Integer divide, RV64 W-type instruction
|
||||||
output logic [2:0] Funct3E, // Funct3 instruction field
|
output logic [2:0] Funct3E, // Funct3 instruction field
|
||||||
output logic [P.XLEN-1:0] ForwardedSrcAE, ForwardedSrcBE, // ALU src inputs before the mux choosing between them and PCE to put in srcA/B
|
output logic [P.XLEN-1:0] ForwardedSrcAE, ForwardedSrcBE, // ALU src inputs before the mux choosing between them and PCE to put in srcA/B
|
||||||
output logic [4:0] RdE, // Destination register
|
output logic [4:0] RdE, // Destination register
|
||||||
// Memory stage signals
|
// Memory stage signals
|
||||||
input logic SquashSCW, // Squash store conditional, from LSU
|
input logic SquashSCW, // Squash store conditional, from LSU
|
||||||
output logic [1:0] MemRWM, // Read/write control goes to LSU
|
output logic [1:0] MemRWM, // Read/write control goes to LSU
|
||||||
output logic [1:0] AtomicM, // Atomic control goes to LSU
|
output logic [1:0] AtomicM, // Atomic control goes to LSU
|
||||||
output logic [P.XLEN-1:0] WriteDataM, // Write data to LSU
|
output logic [P.XLEN-1:0] WriteDataM, // Write data to LSU
|
||||||
output logic [2:0] Funct3M, // Funct3 (size and signedness) to LSU
|
output logic [2:0] Funct3M, // Funct3 (size and signedness) to LSU
|
||||||
output logic [P.XLEN-1:0] SrcAM, // ALU SrcA to Privileged unit and FPU
|
output logic [P.XLEN-1:0] SrcAM, // ALU SrcA to Privileged unit and FPU
|
||||||
output logic [4:0] RdM, // Destination register
|
output logic [4:0] RdM, // Destination register
|
||||||
input logic [P.XLEN-1:0] FIntResM, // Integer result from FPU (fmv, fclass, fcmp)
|
input logic [P.XLEN-1:0] FIntResM, // Integer result from FPU (fmv, fclass, fcmp)
|
||||||
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 BranchD, BranchE,
|
||||||
output logic JumpD, JumpE,
|
output logic JumpD, JumpE,
|
||||||
// Writeback stage signals
|
// Writeback stage signals
|
||||||
input logic [P.XLEN-1:0] FIntDivResultW, // Integer divide result from FPU fdivsqrt)
|
input logic [P.XLEN-1:0] FIntDivResultW, // Integer divide result from FPU fdivsqrt)
|
||||||
input logic [P.XLEN-1:0] CSRReadValW, // CSR read value,
|
input logic [P.XLEN-1:0] CSRReadValW, // CSR read value,
|
||||||
input logic [P.XLEN-1:0] MDUResultW, // multiply/divide unit result
|
input logic [P.XLEN-1:0] MDUResultW, // multiply/divide unit result
|
||||||
input logic [P.XLEN-1:0] FCvtIntResW, // FPU's float to int conversion result
|
input logic [P.XLEN-1:0] FCvtIntResW, // FPU's float to int conversion result
|
||||||
input logic FCvtIntW, // FPU converts float to int
|
input logic FCvtIntW, // FPU converts float to int
|
||||||
output logic [4:0] RdW, // Destination register
|
output logic [4:0] RdW, // Destination register
|
||||||
input logic [P.XLEN-1:0] ReadDataW, // LSU's read data
|
input logic [P.XLEN-1:0] ReadDataW, // LSU's read data
|
||||||
// Hazard unit signals
|
// Hazard unit signals
|
||||||
input logic StallD, StallE, StallM, StallW, // Stall signals from hazard unit
|
input logic StallD, StallE, StallM, StallW, // Stall signals from hazard unit
|
||||||
input logic FlushD, FlushE, FlushM, FlushW, // Flush signals
|
input logic FlushD, FlushE, FlushM, FlushW, // Flush signals
|
||||||
@ -118,4 +117,3 @@ module ieu import cvw::*; #(parameter cvw_t P) (
|
|||||||
.FCvtIntE, .SCE, .ForwardAE, .ForwardBE,
|
.FCvtIntE, .SCE, .ForwardAE, .ForwardBE,
|
||||||
.FCvtIntStallD, .LoadStallD, .MDUStallD, .CSRRdStallD);
|
.FCvtIntStallD, .LoadStallD, .MDUStallD, .CSRRdStallD);
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
@ -31,10 +31,10 @@ module regfile #(parameter XLEN, E_SUPPORTED) (
|
|||||||
input logic clk, reset,
|
input logic clk, reset,
|
||||||
input logic we3, // Write enable
|
input logic we3, // Write enable
|
||||||
input logic [4:0] a1, a2, a3, // Source registers to read (a1, a2), destination register to write (a3)
|
input logic [4:0] a1, a2, a3, // Source registers to read (a1, a2), destination register to write (a3)
|
||||||
input logic [XLEN-1:0] wd3, // Write data for port 3
|
input logic [XLEN-1:0] wd3, // Write data for port 3
|
||||||
output logic [XLEN-1:0] rd1, rd2); // Read data for ports 1, 2
|
output logic [XLEN-1:0] rd1, rd2); // Read data for ports 1, 2
|
||||||
|
|
||||||
localparam NUMREGS = E_SUPPORTED ? 16 : 32; // only 16 registers in E mode
|
localparam NUMREGS = E_SUPPORTED ? 16 : 32; // only 16 registers in E mode
|
||||||
|
|
||||||
logic [XLEN-1:0] rf[NUMREGS-1:1];
|
logic [XLEN-1:0] rf[NUMREGS-1:1];
|
||||||
integer i;
|
integer i;
|
||||||
@ -50,7 +50,7 @@ module regfile #(parameter XLEN, E_SUPPORTED) (
|
|||||||
|
|
||||||
always_ff @(negedge clk)
|
always_ff @(negedge clk)
|
||||||
if (reset) for(i=1; i<NUMREGS; i++) rf[i] <= 0;
|
if (reset) for(i=1; i<NUMREGS; i++) rf[i] <= 0;
|
||||||
else if (we3) rf[a3] <= wd3;
|
else if (we3) rf[a3] <= wd3;
|
||||||
|
|
||||||
assign #2 rd1 = (a1 != 0) ? rf[a1] : 0;
|
assign #2 rd1 = (a1 != 0) ? rf[a1] : 0;
|
||||||
assign #2 rd2 = (a2 != 0) ? rf[a2] : 0;
|
assign #2 rd2 = (a2 != 0) ? rf[a2] : 0;
|
||||||
|
@ -41,7 +41,7 @@ module shifter (
|
|||||||
|
|
||||||
assign Sign = A[`XLEN-1] & SubArith; // sign bit for sign extension
|
assign Sign = A[`XLEN-1] & SubArith; // sign bit for sign extension
|
||||||
if (`XLEN==32) begin // rv32
|
if (`XLEN==32) begin // rv32
|
||||||
if (`ZBB_SUPPORTED) begin: rotfunnel32 //rv32 shifter with rotates
|
if (`ZBB_SUPPORTED) begin: rotfunnel32 // rv32 shifter with rotates
|
||||||
always_comb // funnel mux
|
always_comb // funnel mux
|
||||||
case({Right, Rotate})
|
case({Right, Rotate})
|
||||||
2'b00: Z = {A[31:0], 31'b0};
|
2'b00: Z = {A[31:0], 31'b0};
|
||||||
@ -84,5 +84,3 @@ module shifter (
|
|||||||
assign ZShift = Z >> Offset;
|
assign ZShift = Z >> Offset;
|
||||||
assign Y = ZShift[`XLEN-1:0];
|
assign Y = ZShift[`XLEN-1:0];
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,112 +0,0 @@
|
|||||||
import os
|
|
||||||
|
|
||||||
# Kevin Wan kewan@hmc.edu 10/27/2021
|
|
||||||
def read_input(filename): #1
|
|
||||||
"""Takes in a string filename and outputs the parsed verilog code by line into a list
|
|
||||||
such that each element of the list is one line of verilog code as a string."""
|
|
||||||
lineOfCode = []
|
|
||||||
input_file = open(filename, 'r')
|
|
||||||
for line in input_file:
|
|
||||||
lineOfCode.append(line)
|
|
||||||
return lineOfCode
|
|
||||||
###################################################################################
|
|
||||||
def ID_start(GiantString):#2
|
|
||||||
"""takes in the list of sv file lines, outputs the location that variable names should start"""
|
|
||||||
VarLoc = 0
|
|
||||||
VarLineNum = None
|
|
||||||
for lines in GiantString:
|
|
||||||
if ' logic ' in lines and (lines.find("//") == -1 or lines.find("//") > lines.find(' logic ')): # // logic does not proceed. logic proceeds. logic // proceeds.
|
|
||||||
if "[" in lines and "]" in lines:# need to account for these space
|
|
||||||
NowLoc = lines.find(']') + 3# column number in sv code when 1st char of the var name should appear.
|
|
||||||
if NowLoc>VarLoc:
|
|
||||||
VarLoc = NowLoc
|
|
||||||
VarLineNum = GiantString.index(lines) # Update this number if new record is made.
|
|
||||||
else:
|
|
||||||
NowLoc = lines.find('logic') + 7 # same as before.
|
|
||||||
if NowLoc>VarLoc:
|
|
||||||
VarLoc = NowLoc
|
|
||||||
VarLineNum = GiantString.index(lines)
|
|
||||||
#print("Furthest variable appears on line", VarLineNum + 1,VarLoc) # Disable this line after debugging.
|
|
||||||
return VarLoc
|
|
||||||
##################################################################################
|
|
||||||
def modified_logNew(GS,SOV): #3
|
|
||||||
Ind = SOV - 1 # SOV is for human readability, Ind is the character's index in computer, since computers count from 0's we need to correct it.
|
|
||||||
Out = []
|
|
||||||
for l in GS:
|
|
||||||
lines = l.replace('\t',' ')
|
|
||||||
|
|
||||||
if ' logic ' in lines and (lines.find("//") == -1 or lines.find("//") > lines.find(' logic ')): # // logic does not proceed. logic proceeds. logic // proceeds.
|
|
||||||
if "[" in lines and "]" in lines: # the line is an extended declaration.
|
|
||||||
EditLoc = lines.find("]") # Re-finds the string index number of ].
|
|
||||||
VarLoc = FindCharRel(lines[EditLoc+1::]) + EditLoc + 1 # Checks where variable declaration currently is at.
|
|
||||||
#print(VarLoc,lines[VarLoc])# VERIFIED
|
|
||||||
NewLine = Mod_Space_at(lines,VarLoc,VarLoc-Ind)
|
|
||||||
Out.append(NewLine)# Verified0957 10272021
|
|
||||||
else:
|
|
||||||
EditLoc1 = lines.find('c') # Hopefully sees the c in 'logic'
|
|
||||||
|
|
||||||
VarLoc1 = FindCharRel(lines[EditLoc1+1::]) + EditLoc1 + 1
|
|
||||||
NewLine1 = Mod_Space_at(lines,VarLoc1,VarLoc1-Ind)
|
|
||||||
|
|
||||||
Out.append(NewLine1)# Verified 1005 10272021
|
|
||||||
else:
|
|
||||||
Out.append(lines)
|
|
||||||
return Out
|
|
||||||
################################################################################
|
|
||||||
def write_to_output(filename,GiantString,OW=True,Lines_editted=None): #4
|
|
||||||
"""Filename is preferrably passed from the early function calls"""
|
|
||||||
"""GiantString has all the corrected features in the code, each line is a good verilog code line"""
|
|
||||||
newname = filename
|
|
||||||
if not OW or OW =='f': #which means no overwrite (create a new file)
|
|
||||||
Decomposed=filename.split('.')
|
|
||||||
newname = Decomposed[0] + "_AL." + Decomposed[1] # AL for aligned.
|
|
||||||
|
|
||||||
OutFile = open(newname,'w') # This step should create a new file.
|
|
||||||
OutFile.writelines(GiantString)
|
|
||||||
OutFile.close()
|
|
||||||
print("Success! " + newname + " Now contains an aligned file!")
|
|
||||||
return newname
|
|
||||||
#################################################################################
|
|
||||||
|
|
||||||
def FindCharRel(Ln):
|
|
||||||
#returns the computer location of a character's first occurence
|
|
||||||
for num in range(len(Ln)):
|
|
||||||
if Ln[num] != " ":
|
|
||||||
return num
|
|
||||||
|
|
||||||
|
|
||||||
def Mod_Space_at(Ln,loc,diff):
|
|
||||||
#loc is the varLoc from mln, diff is varLoc - Ind
|
|
||||||
if diff > 0: # to delete
|
|
||||||
NewString = Ln[:(loc-diff)] + Ln[loc:]
|
|
||||||
|
|
||||||
if diff < 0: # to add
|
|
||||||
NewString = Ln[:loc] + (-diff)*" " + Ln[loc:]
|
|
||||||
if diff == 0:
|
|
||||||
NewString = Ln
|
|
||||||
|
|
||||||
return NewString
|
|
||||||
|
|
||||||
'''def main_filehandler(overwrite=False):
|
|
||||||
for filename in os.listdir():
|
|
||||||
if ".sv" in filename:
|
|
||||||
GiantString = read_input(filename)
|
|
||||||
SOV = ID_start(GiantString)
|
|
||||||
ModifiedGS = modified_logNew(GiantString,SOV)
|
|
||||||
Newname = write_to_output(filename,ModifiedGS,overwrite)'''
|
|
||||||
def root_filehandler(path,overwrite=False):
|
|
||||||
for f in os.listdir(path):
|
|
||||||
if os.path.isdir(f):
|
|
||||||
root_filehandler(path+"/"+f)
|
|
||||||
else:
|
|
||||||
if ".sv" in f:
|
|
||||||
GiantString = read_input(f)
|
|
||||||
SOV = ID_start(GiantString)
|
|
||||||
ModifiedGS = modified_logNew(GiantString,SOV)
|
|
||||||
Newname = write_to_output(f,ModifiedGS,overwrite)
|
|
||||||
|
|
||||||
|
|
||||||
def driver(overwrite=False):
|
|
||||||
root_filehandler(os.getcwd())
|
|
||||||
|
|
||||||
driver(True)
|
|
@ -181,4 +181,3 @@ module decompress #(parameter XLEN)(
|
|||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
191
src/ifu/ifu.sv
191
src/ifu/ifu.sv
@ -26,116 +26,115 @@
|
|||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
module ifu import cvw::*; #(parameter cvw_t P) (
|
module ifu import cvw::*; #(parameter cvw_t P) (
|
||||||
input logic clk, reset,
|
input logic clk, 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 IFUStallF, // IFU stalsl pipeline during a multicycle operation
|
output logic IFUStallF, // IFU stalsl pipeline during a multicycle operation
|
||||||
// Command from CPU
|
// Command from CPU
|
||||||
input logic InvalidateICacheM, // Clears all instruction cache valid bits
|
input logic InvalidateICacheM, // Clears all instruction cache valid bits
|
||||||
input logic CSRWriteFenceM, // CSR write or fence instruction, PCNextF = the next valid PC (typically PCE)
|
input logic CSRWriteFenceM, // CSR write or fence instruction, PCNextF = the next valid PC (typically PCE)
|
||||||
input logic InstrValidD, InstrValidE, InstrValidM,
|
input logic InstrValidD, InstrValidE, InstrValidM,
|
||||||
input logic BranchD, BranchE,
|
input logic BranchD, BranchE,
|
||||||
input logic JumpD, JumpE,
|
input logic JumpD, JumpE,
|
||||||
// Bus interface
|
// Bus interface
|
||||||
output logic [P.PA_BITS-1:0] IFUHADDR, // Bus address from IFU to EBU
|
output logic [P.PA_BITS-1:0] IFUHADDR, // Bus address from IFU to EBU
|
||||||
input logic [P.XLEN-1:0] HRDATA, // Bus read data from IFU to EBU
|
input logic [P.XLEN-1:0] HRDATA, // Bus read data from IFU to EBU
|
||||||
input logic IFUHREADY, // Bus ready from IFU to EBU
|
input logic IFUHREADY, // Bus ready from IFU to EBU
|
||||||
output logic IFUHWRITE, // Bus write operation from IFU to EBU
|
output logic IFUHWRITE, // Bus write operation from IFU to EBU
|
||||||
output logic [2:0] IFUHSIZE, // Bus operation size from IFU to EBU
|
output logic [2:0] IFUHSIZE, // Bus operation size from IFU to EBU
|
||||||
output logic [2:0] IFUHBURST, // Bus burst from IFU to EBU
|
output logic [2:0] IFUHBURST, // Bus burst from IFU to EBU
|
||||||
output logic [1:0] IFUHTRANS, // Bus transaction type from IFU to EBU
|
output logic [1:0] IFUHTRANS, // Bus transaction type from IFU to EBU
|
||||||
|
|
||||||
output logic [P.XLEN-1:0] PCSpillF, // PCF with possible + 2 to handle spill to HPTW
|
output logic [P.XLEN-1:0] PCSpillF, // PCF with possible + 2 to handle spill to HPTW
|
||||||
// Execute
|
// Execute
|
||||||
output logic [P.XLEN-1:0] PCLinkE, // The address following the branch instruction. (AKA Fall through address)
|
output logic [P.XLEN-1:0] PCLinkE, // The address following the branch instruction. (AKA Fall through address)
|
||||||
input logic PCSrcE, // Executation stage branch is taken
|
input logic PCSrcE, // Executation stage branch is taken
|
||||||
input logic [P.XLEN-1:0] IEUAdrE, // The branch/jump target address
|
input logic [P.XLEN-1:0] IEUAdrE, // The branch/jump target address
|
||||||
input logic [P.XLEN-1:0] IEUAdrM, // The branch/jump target address
|
input logic [P.XLEN-1:0] IEUAdrM, // The branch/jump target address
|
||||||
output logic [P.XLEN-1:0] PCE, // Execution stage instruction address
|
output logic [P.XLEN-1:0] PCE, // Execution stage instruction address
|
||||||
output logic BPWrongE, // Prediction is wrong
|
output logic BPWrongE, // Prediction is wrong
|
||||||
output logic BPWrongM, // 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 [P.XLEN-1:0] UnalignedPCNextF, // The next PCF, but not aligned to 2 bytes.
|
input logic [P.XLEN-1:0] UnalignedPCNextF, // The next PCF, but not aligned to 2 bytes.
|
||||||
output logic [P.XLEN-1:0] PC2NextF, // Selected PC between branch prediction and next valid PC if CSRWriteFence
|
output logic [P.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 [31:0] InstrOrigM, // Original compressed or uncompressed instruction in Memory stage for Illegal Instruction MTVAL
|
output logic [31:0] InstrOrigM, // Original compressed or uncompressed instruction in Memory stage for Illegal Instruction MTVAL
|
||||||
output logic [P.XLEN-1:0] PCM, // Memory stage instruction address
|
output logic [P.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 BPDirPredWrongM, // Prediction direction is wrong
|
output logic BPDirPredWrongM, // Prediction direction is wrong
|
||||||
output logic BTAWrongM, // 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 IClassWrongM, // Class prediction is wrong
|
output logic IClassWrongM, // Class prediction is wrong
|
||||||
output logic ICacheStallF, // I$ busy with multicycle operation
|
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
|
||||||
output logic InstrPageFaultF, // Instruction page fault
|
output logic InstrPageFaultF, // Instruction page fault
|
||||||
output logic IllegalIEUFPUInstrD, // Illegal instruction including compressed & FP
|
output logic IllegalIEUFPUInstrD, // Illegal instruction including compressed & FP
|
||||||
output logic InstrMisalignedFaultM, // Branch target not aligned to 4 bytes if no compressed allowed (2 bytes if allowed)
|
output logic InstrMisalignedFaultM, // Branch target not aligned to 4 bytes if no compressed allowed (2 bytes if allowed)
|
||||||
// mmu management
|
// mmu management
|
||||||
input logic [1:0] PrivilegeModeW, // Priviledge mode in Writeback stage
|
input logic [1:0] PrivilegeModeW, // Priviledge mode in Writeback stage
|
||||||
input logic [P.XLEN-1:0] PTE, // Hardware page table walker (HPTW) writes Page table entry (PTE) to ITLB
|
input logic [P.XLEN-1:0] PTE, // Hardware page table walker (HPTW) writes Page table entry (PTE) to ITLB
|
||||||
input logic [1:0] PageType, // Hardware page table walker (HPTW) writes PageType to ITLB
|
input logic [1:0] PageType, // Hardware page table walker (HPTW) writes PageType to ITLB
|
||||||
input logic ITLBWriteF, // Writes PTE and PageType to ITLB
|
input logic ITLBWriteF, // Writes PTE and PageType to ITLB
|
||||||
input logic [P.XLEN-1:0] SATP_REGW, // Location of the root page table and page table configuration
|
input logic [P.XLEN-1:0] SATP_REGW, // Location of the root page table and page table configuration
|
||||||
input logic STATUS_MXR, // Status CSR: make executable page readable
|
input logic STATUS_MXR, // Status CSR: make executable page readable
|
||||||
input logic STATUS_SUM, // Status CSR: Supervisor access to user memory
|
input logic STATUS_SUM, // Status CSR: Supervisor access to user memory
|
||||||
input logic STATUS_MPRV, // Status CSR: modify machine privilege
|
input logic STATUS_MPRV, // Status CSR: modify machine privilege
|
||||||
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 InstrUpdateDAF, // 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[P.PMP_ENTRIES-1:0], // PMP configuration from privileged unit
|
input var logic [7:0] PMPCFG_ARRAY_REGW[P.PMP_ENTRIES-1:0], // PMP configuration from privileged unit
|
||||||
input var logic [P.PA_BITS-3:0] PMPADDR_ARRAY_REGW[P.PMP_ENTRIES-1:0], // PMP address from privileged unit
|
input var logic [P.PA_BITS-3:0] PMPADDR_ARRAY_REGW[P.PMP_ENTRIES-1:0],// PMP address from privileged unit
|
||||||
output logic InstrAccessFaultF, // Instruction access fault
|
output logic InstrAccessFaultF, // Instruction access fault
|
||||||
output logic ICacheAccess, // Report I$ read to performance counters
|
output logic ICacheAccess, // Report I$ read to performance counters
|
||||||
output logic ICacheMiss // Report I$ miss to performance counters
|
output logic ICacheMiss // Report I$ miss to performance counters
|
||||||
);
|
);
|
||||||
|
|
||||||
localparam [31:0] nop = 32'h00000013; // instruction for NOP
|
localparam [31:0] nop = 32'h00000013; // instruction for NOP
|
||||||
|
|
||||||
logic [P.XLEN-1:0] PCNextF; // Next PCF, selected from Branch predictor, Privilege, or PC+2/4
|
logic [P.XLEN-1:0] PCNextF; // Next PCF, selected from Branch predictor, Privilege, or PC+2/4
|
||||||
logic BranchMisalignedFaultE; // Branch target not aligned to 4 bytes if no compressed allowed (2 bytes if allowed)
|
logic BranchMisalignedFaultE; // Branch target not aligned to 4 bytes if no compressed allowed (2 bytes if allowed)
|
||||||
logic [P.XLEN-1:0] PCPlus2or4F; // PCF + 2 (CompressedF) or PCF + 4 (Non-compressed)
|
logic [P.XLEN-1:0] PCPlus2or4F; // PCF + 2 (CompressedF) or PCF + 4 (Non-compressed)
|
||||||
logic [P.XLEN-1:0] PCSpillNextF; // Next PCF after possible + 2 to handle spill
|
logic [P.XLEN-1:0] PCSpillNextF; // Next PCF after possible + 2 to handle spill
|
||||||
logic [P.XLEN-1:0] PCLinkD; // PCF2or4F delayed 1 cycle. This is next PC after a control flow instruction (br or j)
|
logic [P.XLEN-1:0] PCLinkD; // PCF2or4F delayed 1 cycle. This is next PC after a control flow instruction (br or j)
|
||||||
logic [P.XLEN-1:2] PCPlus4F; // PCPlus4F is always PCF + 4. Fancy way to compute PCPlus2or4F
|
logic [P.XLEN-1:2] PCPlus4F; // PCPlus4F is always PCF + 4. Fancy way to compute PCPlus2or4F
|
||||||
logic [P.XLEN-1:0] PCD; // Decode stage instruction address
|
logic [P.XLEN-1:0] PCD; // Decode stage instruction address
|
||||||
logic [P.XLEN-1:0] NextValidPCE; // The PC of the next valid instruction in the pipeline after csr write or fence
|
logic [P.XLEN-1:0] NextValidPCE; // The PC of the next valid instruction in the pipeline after csr write or fence
|
||||||
logic [P.XLEN-1:0] PCF; // Fetch stage instruction address
|
logic [P.XLEN-1:0] PCF; // Fetch stage instruction address
|
||||||
logic [P.PA_BITS-1:0] PCPF; // Physical address after address translation
|
logic [P.PA_BITS-1:0] PCPF; // Physical address after address translation
|
||||||
logic [P.XLEN+1:0] PCFExt; //
|
logic [P.XLEN+1:0] PCFExt;
|
||||||
|
|
||||||
logic [31:0] IROMInstrF; // Instruction from the IROM
|
logic [31:0] IROMInstrF; // Instruction from the IROM
|
||||||
logic [31:0] ICacheInstrF; // Instruction from the I$
|
logic [31:0] ICacheInstrF; // Instruction from the I$
|
||||||
logic [31:0] InstrRawF; // Instruction from the IROM, I$, or bus
|
logic [31:0] InstrRawF; // Instruction from the IROM, I$, or bus
|
||||||
logic CompressedF; // The fetched instruction is compressed
|
logic CompressedF; // The fetched instruction is compressed
|
||||||
logic CompressedD; // The decoded instruction is compressed
|
logic CompressedD; // The decoded instruction is compressed
|
||||||
logic CompressedE; // The execution instruction is compressed
|
logic CompressedE; // The execution instruction is compressed
|
||||||
logic CompressedM; // The execution instruction is compressed
|
logic CompressedM; // The execution instruction is compressed
|
||||||
logic [31:0] PostSpillInstrRawF; // Fetch instruction after merge two halves of spill
|
logic [31:0] PostSpillInstrRawF; // Fetch instruction after merge two halves of spill
|
||||||
logic [31:0] InstrRawD; // Non-decompressed instruction in the Decode stage
|
logic [31:0] InstrRawD; // Non-decompressed instruction in the Decode stage
|
||||||
logic IllegalIEUInstrD; // IEU Instruction (regular or compressed) is not good
|
logic IllegalIEUInstrD; // IEU Instruction (regular or compressed) is not good
|
||||||
|
|
||||||
logic [1:0] IFURWF; // IFU alreays read IFURWF = 10
|
logic [1:0] IFURWF; // IFU alreays read IFURWF = 10
|
||||||
logic [31:0] InstrE; // Instruction in the Execution stage
|
logic [31:0] InstrE; // Instruction in the Execution stage
|
||||||
logic [31:0] NextInstrD, NextInstrE; // Instruction into the next stage after possible stage flush
|
logic [31:0] NextInstrD, NextInstrE; // Instruction into the next stage after possible stage flush
|
||||||
|
|
||||||
|
logic CacheableF; // PMA indicates instruction address is cacheable
|
||||||
logic CacheableF; // PMA indicates instruction address is cacheable
|
logic SelSpillNextF; // In a spill, stall pipeline and gate local stallF
|
||||||
logic SelSpillNextF; // 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 IFUCacheBusStallF; // EIther I$ or bus busy with multicycle operation
|
||||||
logic IFUCacheBusStallF; // 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 [P.XLEN-1:0] PC1NextF; // Branch predictor next PCF
|
logic [P.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
|
||||||
logic [15:0] InstrRawE, InstrRawM;
|
logic [15:0] InstrRawE, InstrRawM;
|
||||||
|
|
||||||
assign PCFExt = {2'b00, PCSpillF};
|
assign PCFExt = {2'b00, PCSpillF};
|
||||||
|
|
||||||
@ -199,6 +198,7 @@ module ifu import cvw::*; #(parameter cvw_t P) (
|
|||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Memory
|
// Memory
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// CommittedM tells the CPU's privileged unit the current instruction
|
// CommittedM tells the CPU's privileged unit the current instruction
|
||||||
// in the memory stage is a memory operaton and that memory operation is either completed
|
// in the memory stage is a memory operaton and that memory operation is either completed
|
||||||
// or is partially executed. Partially completed memory operations need to prevent an interrupts.
|
// or is partially executed. Partially completed memory operations need to prevent an interrupts.
|
||||||
@ -206,7 +206,7 @@ module ifu import cvw::*; #(parameter cvw_t P) (
|
|||||||
// delay the interrupt until the LSU is in a clean state.
|
// delay the interrupt until the LSU is in a clean state.
|
||||||
assign CommittedF = CacheCommittedF | BusCommittedF;
|
assign CommittedF = CacheCommittedF | BusCommittedF;
|
||||||
|
|
||||||
logic IgnoreRequest;
|
logic IgnoreRequest;
|
||||||
assign IgnoreRequest = ITLBMissF | FlushD;
|
assign IgnoreRequest = ITLBMissF | FlushD;
|
||||||
|
|
||||||
// The IROM uses untranslated addresses, so it is not compatible with virtual memory.
|
// The IROM uses untranslated addresses, so it is not compatible with virtual memory.
|
||||||
@ -223,12 +223,12 @@ module ifu import cvw::*; #(parameter cvw_t P) (
|
|||||||
localparam WORDSPERLINE = P.ICACHE_SUPPORTED ? P.ICACHE_LINELENINBITS/P.XLEN : 1;
|
localparam WORDSPERLINE = P.ICACHE_SUPPORTED ? P.ICACHE_LINELENINBITS/P.XLEN : 1;
|
||||||
localparam LOGBWPL = P.ICACHE_SUPPORTED ? $clog2(WORDSPERLINE) : 1;
|
localparam LOGBWPL = P.ICACHE_SUPPORTED ? $clog2(WORDSPERLINE) : 1;
|
||||||
if(P.ICACHE_SUPPORTED) begin : icache
|
if(P.ICACHE_SUPPORTED) begin : icache
|
||||||
localparam LINELEN = P.ICACHE_SUPPORTED ? P.ICACHE_LINELENINBITS : P.XLEN;
|
localparam LINELEN = P.ICACHE_SUPPORTED ? P.ICACHE_LINELENINBITS : P.XLEN;
|
||||||
localparam LLENPOVERAHBW = P.LLEN / P.AHBW; // Number of AHB beats in a LLEN word. AHBW cannot be larger than LLEN. (implementation limitation)
|
localparam LLENPOVERAHBW = P.LLEN / P.AHBW; // Number of AHB beats in a LLEN word. AHBW cannot be larger than LLEN. (implementation limitation)
|
||||||
logic [LINELEN-1:0] FetchBuffer;
|
logic [LINELEN-1:0] FetchBuffer;
|
||||||
logic [P.PA_BITS-1:0] ICacheBusAdr;
|
logic [P.PA_BITS-1:0] ICacheBusAdr;
|
||||||
logic ICacheBusAck;
|
logic ICacheBusAck;
|
||||||
logic [1:0] CacheBusRW, BusRW, CacheRWF;
|
logic [1:0] CacheBusRW, BusRW, CacheRWF;
|
||||||
|
|
||||||
assign BusRW = ~ITLBMissF & ~CacheableF & ~SelIROM ? IFURWF : '0;
|
assign BusRW = ~ITLBMissF & ~CacheableF & ~SelIROM ? IFURWF : '0;
|
||||||
assign CacheRWF = ~ITLBMissF & CacheableF & ~SelIROM ? IFURWF : '0;
|
assign CacheRWF = ~ITLBMissF & CacheableF & ~SelIROM ? IFURWF : '0;
|
||||||
@ -255,7 +255,7 @@ module ifu import cvw::*; #(parameter cvw_t P) (
|
|||||||
.Flush(FlushD), .CacheBusRW, .HSIZE(IFUHSIZE), .HBURST(IFUHBURST), .HTRANS(IFUHTRANS), .HWSTRB(),
|
.Flush(FlushD), .CacheBusRW, .HSIZE(IFUHSIZE), .HBURST(IFUHBURST), .HTRANS(IFUHTRANS), .HWSTRB(),
|
||||||
.Funct3(3'b010), .HADDR(IFUHADDR), .HREADY(IFUHREADY), .HWRITE(IFUHWRITE), .CacheBusAdr(ICacheBusAdr),
|
.Funct3(3'b010), .HADDR(IFUHADDR), .HREADY(IFUHREADY), .HWRITE(IFUHWRITE), .CacheBusAdr(ICacheBusAdr),
|
||||||
.BeatCount(), .Cacheable(CacheableF), .SelBusBeat(), .WriteDataM('0),
|
.BeatCount(), .Cacheable(CacheableF), .SelBusBeat(), .WriteDataM('0),
|
||||||
.CacheBusAck(ICacheBusAck), .HWDATA(), .CacheableOrFlushCacheM(1'b0), .CacheReadDataWordM('0),
|
.CacheBusAck(ICacheBusAck), .HWDATA(), .CacheableOrFlushCacheM(1'b0), .CacheReadDataWordM('0),
|
||||||
.FetchBuffer, .PAdr(PCPF),
|
.FetchBuffer, .PAdr(PCPF),
|
||||||
.BusRW, .Stall(GatedStallD),
|
.BusRW, .Stall(GatedStallD),
|
||||||
.BusStall, .BusCommitted(BusCommittedF));
|
.BusStall, .BusCommitted(BusCommittedF));
|
||||||
@ -321,7 +321,6 @@ module ifu import cvw::*; #(parameter cvw_t P) (
|
|||||||
else PCPlus2or4F = {PCF[P.XLEN-1:2], 2'b10};
|
else PCPlus2or4F = {PCF[P.XLEN-1:2], 2'b10};
|
||||||
else PCPlus2or4F = {PCPlus4F, PCF[1:0]}; // add 4
|
else PCPlus2or4F = {PCPlus4F, PCF[1:0]}; // add 4
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Branch and Jump Predictor
|
// Branch and Jump Predictor
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
@ -341,10 +340,10 @@ module ifu import cvw::*; #(parameter cvw_t P) (
|
|||||||
assign NextValidPCE = PCE;
|
assign NextValidPCE = PCE;
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Decode stage pipeline register and compressed instruction decoding.
|
// Decode stage pipeline register and compressed instruction decoding.
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// Decode stage pipeline register and logic
|
// Decode stage pipeline register and logic
|
||||||
flopenrc #(P.XLEN) PCDReg(clk, reset, FlushD, ~StallD, PCF, PCD);
|
flopenrc #(P.XLEN) PCDReg(clk, reset, FlushD, ~StallD, PCF, PCD);
|
||||||
|
|
||||||
@ -374,10 +373,10 @@ module ifu import cvw::*; #(parameter cvw_t P) (
|
|||||||
|
|
||||||
// Instruction and PC/PCLink pipeline registers
|
// Instruction and PC/PCLink pipeline registers
|
||||||
// Cannot use flopenrc for Instr(E/M) as it resets to NOP not 0.
|
// Cannot use flopenrc for Instr(E/M) as it resets to NOP not 0.
|
||||||
mux2 #(32) FlushInstrEMux(InstrD, nop, FlushE, NextInstrD);
|
mux2 #(32) FlushInstrEMux(InstrD, nop, FlushE, NextInstrD);
|
||||||
mux2 #(32) FlushInstrMMux(InstrE, nop, FlushM, NextInstrE);
|
mux2 #(32) FlushInstrMMux(InstrE, nop, FlushM, NextInstrE);
|
||||||
flopenr #(32) InstrEReg(clk, reset, ~StallE, NextInstrD, InstrE);
|
flopenr #(32) InstrEReg(clk, reset, ~StallE, NextInstrD, InstrE);
|
||||||
flopenr #(32) InstrMReg(clk, reset, ~StallM, NextInstrE, InstrM);
|
flopenr #(32) InstrMReg(clk, reset, ~StallM, NextInstrE, InstrM);
|
||||||
flopenr #(P.XLEN) PCEReg(clk, reset, ~StallE, PCD, PCE);
|
flopenr #(P.XLEN) PCEReg(clk, reset, ~StallE, PCD, PCE);
|
||||||
flopenr #(P.XLEN) PCMReg(clk, reset, ~StallM, PCE, PCM);
|
flopenr #(P.XLEN) PCMReg(clk, reset, ~StallM, PCE, PCM);
|
||||||
//flopenr #(P.XLEN) PCPDReg(clk, reset, ~StallD, PCPlus2or4F, PCLinkD);
|
//flopenr #(P.XLEN) PCPDReg(clk, reset, ~StallD, PCPlus2or4F, PCLinkD);
|
||||||
|
@ -25,10 +25,10 @@
|
|||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
module irom import cvw::*; #(parameter cvw_t P) (
|
module irom import cvw::*; #(parameter cvw_t P) (
|
||||||
input logic clk,
|
input logic clk,
|
||||||
input logic ce, // Chip Enable. 0: Holds IROMInstrF constant
|
input logic ce, // Chip Enable. 0: Holds IROMInstrF constant
|
||||||
input logic [P.XLEN-1:0] Adr, // PCNextFSpill
|
input logic [P.XLEN-1:0] Adr, // PCNextFSpill
|
||||||
output logic [31:0] IROMInstrF // Instruction read data
|
output logic [31:0] IROMInstrF // Instruction read data
|
||||||
);
|
);
|
||||||
|
|
||||||
localparam XLENBYTES = {{P.PA_BITS-32{1'b0}}, P.XLEN/8}; // XLEN/8, adjusted for width
|
localparam XLENBYTES = {{P.PA_BITS-32{1'b0}}, P.XLEN/8}; // XLEN/8, adjusted for width
|
||||||
@ -36,14 +36,13 @@ module irom import cvw::*; #(parameter cvw_t P) (
|
|||||||
localparam OFFSET = $clog2(XLENBYTES);
|
localparam OFFSET = $clog2(XLENBYTES);
|
||||||
|
|
||||||
logic [P.XLEN-1:0] IROMInstrFFull;
|
logic [P.XLEN-1:0] IROMInstrFFull;
|
||||||
logic [31:0] RawIROMInstrF;
|
logic [31:0] RawIROMInstrF;
|
||||||
|
logic [1:0] AdrD;
|
||||||
logic [1:0] AdrD;
|
|
||||||
flopen #(2) AdrReg(clk, ce, Adr[2:1], AdrD);
|
flopen #(2) AdrReg(clk, ce, Adr[2:1], AdrD);
|
||||||
|
|
||||||
rom1p1r #(ADDR_WDITH, P.XLEN) rom(.clk, .ce, .addr(Adr[ADDR_WDITH+OFFSET-1:OFFSET]), .dout(IROMInstrFFull));
|
rom1p1r #(ADDR_WDITH, P.XLEN) rom(.clk, .ce, .addr(Adr[ADDR_WDITH+OFFSET-1:OFFSET]), .dout(IROMInstrFFull));
|
||||||
if (P.XLEN == 32) assign RawIROMInstrF = IROMInstrFFull;
|
if (P.XLEN == 32) assign RawIROMInstrF = IROMInstrFFull;
|
||||||
else begin
|
else begin
|
||||||
// IROM is aligned to XLEN words, but instructions are 32 bits. Select between the two
|
// IROM is aligned to XLEN words, but instructions are 32 bits. Select between the two
|
||||||
// haves. Adr is the Next PCF not PCF so we delay 1 cycle.
|
// haves. Adr is the Next PCF not PCF so we delay 1 cycle.
|
||||||
assign RawIROMInstrF = AdrD[1] ? IROMInstrFFull[63:32] : IROMInstrFFull[31:0];
|
assign RawIROMInstrF = AdrD[1] ? IROMInstrFFull[63:32] : IROMInstrFFull[31:0];
|
||||||
@ -52,4 +51,3 @@ module irom import cvw::*; #(parameter cvw_t P) (
|
|||||||
// The spill logic will handle merging the two together.
|
// The spill logic will handle merging the two together.
|
||||||
assign IROMInstrF = AdrD[0] ? {16'b0, RawIROMInstrF[31:16]} : RawIROMInstrF;
|
assign IROMInstrF = AdrD[0] ? {16'b0, RawIROMInstrF[31:16]} : RawIROMInstrF;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
@ -32,33 +32,33 @@
|
|||||||
`include "wally-config.vh"
|
`include "wally-config.vh"
|
||||||
|
|
||||||
module spill import cvw::*; #(parameter cvw_t P) (
|
module spill import cvw::*; #(parameter cvw_t P) (
|
||||||
input logic clk,
|
input logic clk,
|
||||||
input logic reset,
|
input logic reset,
|
||||||
input logic StallD, FlushD,
|
input logic StallD, FlushD,
|
||||||
input logic [P.XLEN-1:0] PCF, // 2 byte aligned PC in Fetch stage
|
input logic [P.XLEN-1:0] PCF, // 2 byte aligned PC in Fetch stage
|
||||||
input logic [P.XLEN-1:2] PCPlus4F, // PCF + 4
|
input logic [P.XLEN-1:2] PCPlus4F, // PCF + 4
|
||||||
input logic [P.XLEN-1:0] PCNextF, // The next PCF
|
input logic [P.XLEN-1:0] PCNextF, // The next PCF
|
||||||
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 IFUCacheBusStallF, // I$ or bus are stalled. Transition to second fetch of spill after the first is fetched
|
input logic IFUCacheBusStallF, // 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 InstrUpdateDAF, // 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 [P.XLEN-1:0] PCSpillNextF, // The next PCF for one of the two memory addresses of the spill
|
output logic [P.XLEN-1:0] PCSpillNextF, // The next PCF for one of the two memory addresses of the spill
|
||||||
output logic [P.XLEN-1:0] PCSpillF, // PCF for one of the two memory addresses of the spill
|
output logic [P.XLEN-1:0] PCSpillF, // PCF for one of the two memory addresses of the spill
|
||||||
output logic SelSpillNextF, // During the transition between the two spill operations, the IFU should stall the pipeline
|
output logic SelSpillNextF, // During the transition between the two spill operations, the IFU should stall the pipeline
|
||||||
output logic [31:0] PostSpillInstrRawF,// The final 32 bit instruction after merging the two spilled fetches into 1 instruction
|
output logic [31:0] PostSpillInstrRawF,// The final 32 bit instruction after merging the two spilled fetches into 1 instruction
|
||||||
output logic CompressedF); // The fetched instruction is compressed
|
output logic CompressedF); // The fetched instruction is compressed
|
||||||
|
|
||||||
// Spill threshold occurs when all the cache offset PC bits are 1 (except [0]). Without a cache this is just PCF[1]
|
// Spill threshold occurs when all the cache offset PC bits are 1 (except [0]). Without a cache this is just PCF[1]
|
||||||
typedef enum logic [1:0] {STATE_READY, STATE_SPILL} statetype;
|
typedef enum logic [1:0] {STATE_READY, STATE_SPILL} statetype;
|
||||||
localparam SPILLTHRESHOLD = P.ICACHE_SUPPORTED ? P.ICACHE_LINELENINBITS/32 : 1;
|
localparam SPILLTHRESHOLD = P.ICACHE_SUPPORTED ? P.ICACHE_LINELENINBITS/32 : 1;
|
||||||
|
|
||||||
statetype CurrState, NextState;
|
statetype CurrState, NextState;
|
||||||
logic [P.XLEN-1:0] PCPlus2F;
|
logic [P.XLEN-1:0] PCPlus2F;
|
||||||
logic TakeSpillF;
|
logic TakeSpillF;
|
||||||
logic SpillF;
|
logic SpillF;
|
||||||
logic SelSpillF;
|
logic SelSpillF;
|
||||||
logic SpillSaveF;
|
logic SpillSaveF;
|
||||||
logic [15:0] InstrFirstHalfF;
|
logic [15:0] InstrFirstHalfF;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// PC logic
|
// PC logic
|
||||||
@ -71,7 +71,6 @@ module spill import cvw::*; #(parameter cvw_t P) (
|
|||||||
// select between PCF and PCF+2
|
// select between PCF and PCF+2
|
||||||
mux2 #(P.XLEN) pcspillmux(.d0(PCF), .d1(PCPlus2F), .s(SelSpillF), .y(PCSpillF));
|
mux2 #(P.XLEN) pcspillmux(.d0(PCF), .d1(PCPlus2F), .s(SelSpillF), .y(PCSpillF));
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Detect spill
|
// Detect spill
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -30,8 +30,8 @@
|
|||||||
module amoalu import cvw::*; #(parameter cvw_t P) (
|
module amoalu import cvw::*; #(parameter cvw_t P) (
|
||||||
input logic [P.XLEN-1:0] ReadDataM, // LSU's ReadData
|
input logic [P.XLEN-1:0] ReadDataM, // LSU's ReadData
|
||||||
input logic [P.XLEN-1:0] IHWriteDataM, // LSU's WriteData
|
input logic [P.XLEN-1:0] IHWriteDataM, // LSU's WriteData
|
||||||
input logic [6:0] LSUFunct7M, // ALU Operation
|
input logic [6:0] LSUFunct7M, // ALU Operation
|
||||||
input logic [2:0] LSUFunct3M, // Memoy access width
|
input logic [2:0] LSUFunct3M, // Memoy access width
|
||||||
output logic [P.XLEN-1:0] AMOResultM // ALU output
|
output logic [P.XLEN-1:0] AMOResultM // ALU output
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -72,4 +72,3 @@ module amoalu import cvw::*; #(parameter cvw_t P) (
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
@ -28,24 +28,24 @@
|
|||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
module atomic import cvw::*; #(parameter cvw_t P) (
|
module atomic import cvw::*; #(parameter cvw_t P) (
|
||||||
input logic clk,
|
input logic clk,
|
||||||
input logic reset,
|
input logic reset,
|
||||||
input logic StallW,
|
input logic StallW,
|
||||||
input logic [P.XLEN-1:0] ReadDataM, // LSU ReadData XLEN because FPU does not issue atomic memory operation from FPU registers
|
input logic [P.XLEN-1:0] ReadDataM, // LSU ReadData XLEN because FPU does not issue atomic memory operation from FPU registers
|
||||||
input logic [P.XLEN-1:0] IHWriteDataM, // LSU WriteData XLEN because FPU does not issue atomic memory operation from FPU registers
|
input logic [P.XLEN-1:0] IHWriteDataM, // LSU WriteData XLEN because FPU does not issue atomic memory operation from FPU registers
|
||||||
input logic [P.PA_BITS-1:0] PAdrM, // Physical memory address
|
input logic [P.PA_BITS-1:0] PAdrM, // Physical memory address
|
||||||
input logic [6:0] LSUFunct7M, // AMO alu operation gated by HPTW
|
input logic [6:0] LSUFunct7M, // AMO alu operation gated by HPTW
|
||||||
input logic [2:0] LSUFunct3M, // IEU or HPTW memory operation size
|
input logic [2:0] LSUFunct3M, // IEU or HPTW memory operation size
|
||||||
input logic [1:0] LSUAtomicM, // 10: AMO operation, select AMOResultM as the writedata output, 01: LR/SC operation
|
input logic [1:0] LSUAtomicM, // 10: AMO operation, select AMOResultM as the writedata output, 01: LR/SC operation
|
||||||
input logic [1:0] PreLSURWM, // IEU or HPTW Read/Write signal
|
input logic [1:0] PreLSURWM, // IEU or HPTW Read/Write signal
|
||||||
input logic IgnoreRequest, // On FlushM or TLB miss ignore memory operation
|
input logic IgnoreRequest, // On FlushM or TLB miss ignore memory operation
|
||||||
output logic [P.XLEN-1:0] IMAWriteDataM, // IEU, HPTW, or AMO write data
|
output logic [P.XLEN-1:0] IMAWriteDataM, // IEU, HPTW, or AMO write data
|
||||||
output logic SquashSCW, // Store conditional failed disable write to GPR
|
output logic SquashSCW, // Store conditional failed disable write to GPR
|
||||||
output logic [1:0] LSURWM // IEU or HPTW Read/Write signal gated by LR/SC
|
output logic [1:0] LSURWM // IEU or HPTW Read/Write signal gated by LR/SC
|
||||||
);
|
);
|
||||||
|
|
||||||
logic [P.XLEN-1:0] AMOResultM;
|
logic [P.XLEN-1:0] AMOResultM;
|
||||||
logic MemReadM;
|
logic MemReadM;
|
||||||
|
|
||||||
amoalu #(P) amoalu(.ReadDataM, .IHWriteDataM, .LSUFunct7M, .LSUFunct3M, .AMOResultM);
|
amoalu #(P) amoalu(.ReadDataM, .IHWriteDataM, .LSUFunct7M, .LSUFunct3M, .AMOResultM);
|
||||||
|
|
||||||
|
@ -28,17 +28,17 @@
|
|||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
module dtim import cvw::*; #(parameter cvw_t P) (
|
module dtim import cvw::*; #(parameter cvw_t P) (
|
||||||
input logic clk,
|
input logic clk,
|
||||||
input logic FlushW,
|
input logic FlushW,
|
||||||
input logic ce, // Chip Enable. 0: Holds ReadDataWordM
|
input logic ce, // Chip Enable. 0: Holds ReadDataWordM
|
||||||
input logic [1:0] MemRWM, // Read/Write control
|
input logic [1:0] MemRWM, // Read/Write control
|
||||||
input logic [P.PA_BITS-1:0] DTIMAdr, // No stall: Execution stage memory address. Stall: Memory stage memory address
|
input logic [P.PA_BITS-1:0] DTIMAdr, // No stall: Execution stage memory address. Stall: Memory stage memory address
|
||||||
input logic [P.LLEN-1:0] WriteDataM, // Write data from IEU
|
input logic [P.LLEN-1:0] WriteDataM, // Write data from IEU
|
||||||
input logic [P.LLEN/8-1:0] ByteMaskM, // Selects which bytes within a word to write
|
input logic [P.LLEN/8-1:0] ByteMaskM, // Selects which bytes within a word to write
|
||||||
output logic [P.LLEN-1:0] ReadDataWordM // Read data before subword selection
|
output logic [P.LLEN-1:0] ReadDataWordM // Read data before subword selection
|
||||||
);
|
);
|
||||||
|
|
||||||
logic we;
|
logic we;
|
||||||
|
|
||||||
localparam LLENBYTES = P.LLEN/8;
|
localparam LLENBYTES = P.LLEN/8;
|
||||||
// verilator lint_off WIDTH
|
// verilator lint_off WIDTH
|
||||||
@ -52,4 +52,3 @@ module dtim import cvw::*; #(parameter cvw_t P) (
|
|||||||
ram1p1rwbe #(.DEPTH(DEPTH), .WIDTH(P.LLEN))
|
ram1p1rwbe #(.DEPTH(DEPTH), .WIDTH(P.LLEN))
|
||||||
ram(.clk, .ce, .we, .bwe(ByteMaskM), .addr(DTIMAdr[ADDR_WDITH+OFFSET-1:OFFSET]), .dout(ReadDataWordM), .din(WriteDataM));
|
ram(.clk, .ce, .we, .bwe(ByteMaskM), .addr(DTIMAdr[ADDR_WDITH+OFFSET-1:OFFSET]), .dout(ReadDataWordM), .din(WriteDataM));
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
@ -29,23 +29,23 @@
|
|||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
module lrsc import cvw::*; #(parameter cvw_t P) (
|
module lrsc import cvw::*; #(parameter cvw_t P) (
|
||||||
input logic clk,
|
input logic clk,
|
||||||
input logic reset,
|
input logic reset,
|
||||||
input logic StallW,
|
input logic StallW,
|
||||||
input logic MemReadM, // Memory read
|
input logic MemReadM, // Memory read
|
||||||
input logic [1:0] PreLSURWM, // Memory operation from the HPTW or IEU [1]: read, [0]: write
|
input logic [1:0] PreLSURWM, // Memory operation from the HPTW or IEU [1]: read, [0]: write
|
||||||
output logic [1:0] LSURWM, // Memory operation after potential squash of SC
|
output logic [1:0] LSURWM, // Memory operation after potential squash of SC
|
||||||
input logic [1:0] LSUAtomicM, // Atomic memory operaiton
|
input logic [1:0] LSUAtomicM, // Atomic memory operaiton
|
||||||
input logic [P.PA_BITS-1:0] PAdrM, // Physical memory address
|
input logic [P.PA_BITS-1:0] PAdrM, // Physical memory address
|
||||||
output logic SquashSCW // Squash the store conditional by not allowing rf write
|
output logic SquashSCW // Squash the store conditional by not allowing rf write
|
||||||
);
|
);
|
||||||
|
|
||||||
// possible bug: *** double check if PreLSURWM needs to be flushed by ignorerequest.
|
// possible bug: *** double check if PreLSURWM needs to be flushed by ignorerequest.
|
||||||
// Handle atomic load reserved / store conditional
|
// Handle atomic load reserved / store conditional
|
||||||
logic [P.PA_BITS-1:2] ReservationPAdrW;
|
logic [P.PA_BITS-1:2] ReservationPAdrW;
|
||||||
logic ReservationValidM, ReservationValidW;
|
logic ReservationValidM, ReservationValidW;
|
||||||
logic lrM, scM, WriteAdrMatchM;
|
logic lrM, scM, WriteAdrMatchM;
|
||||||
logic SquashSCM;
|
logic SquashSCM;
|
||||||
|
|
||||||
assign lrM = MemReadM & LSUAtomicM[0];
|
assign lrM = MemReadM & LSUAtomicM[0];
|
||||||
assign scM = PreLSURWM[0] & LSUAtomicM[0];
|
assign scM = PreLSURWM[0] & LSUAtomicM[0];
|
||||||
|
170
src/lsu/lsu.sv
170
src/lsu/lsu.sv
@ -30,63 +30,63 @@
|
|||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
module lsu import cvw::*; #(parameter cvw_t P) (
|
module lsu import cvw::*; #(parameter cvw_t P) (
|
||||||
input logic clk, reset,
|
input logic clk, reset,
|
||||||
input logic StallM, FlushM, StallW, FlushW,
|
input logic StallM, FlushM, StallW, FlushW,
|
||||||
output logic LSUStallM, // LSU stalls pipeline during a multicycle operation
|
output logic LSUStallM, // LSU stalls pipeline during a multicycle operation
|
||||||
// connected to cpu (controls)
|
// connected to cpu (controls)
|
||||||
input logic [1:0] MemRWM, // Read/Write control
|
input logic [1:0] MemRWM, // Read/Write control
|
||||||
input logic [2:0] Funct3M, // Size of memory operation
|
input logic [2:0] Funct3M, // Size of memory operation
|
||||||
input logic [6:0] Funct7M, // Atomic memory operation function
|
input logic [6:0] Funct7M, // Atomic memory operation function
|
||||||
input logic [1:0] AtomicM, // Atomic memory operation
|
input logic [1:0] AtomicM, // Atomic memory operation
|
||||||
input logic FlushDCacheM, // Flush D cache to next level of memory
|
input logic FlushDCacheM, // Flush D cache to next level of memory
|
||||||
output logic CommittedM, // Delay interrupts while memory operation in flight
|
output logic CommittedM, // Delay interrupts while memory operation in flight
|
||||||
output logic SquashSCW, // Store conditional failed disable write to GPR
|
output logic SquashSCW, // Store conditional failed disable write to GPR
|
||||||
output logic DCacheMiss, // D cache miss for performance counters
|
output logic DCacheMiss, // D cache miss for performance counters
|
||||||
output logic DCacheAccess, // D cache memory access for performance counters
|
output logic DCacheAccess, // D cache memory access for performance counters
|
||||||
// address and write data
|
// address and write data
|
||||||
input logic [P.XLEN-1:0] IEUAdrE, // Execution stage memory address
|
input logic [P.XLEN-1:0] IEUAdrE, // Execution stage memory address
|
||||||
output logic [P.XLEN-1:0] IEUAdrM, // Memory stage memory address
|
output logic [P.XLEN-1:0] IEUAdrM, // Memory stage memory address
|
||||||
input logic [P.XLEN-1:0] WriteDataM, // Write data from IEU
|
input logic [P.XLEN-1:0] WriteDataM, // Write data from IEU
|
||||||
output logic [P.LLEN-1:0] ReadDataW, // Read data to IEU or FPU
|
output logic [P.LLEN-1:0] ReadDataW, // Read data to IEU or FPU
|
||||||
// cpu privilege
|
// cpu privilege
|
||||||
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
|
output logic DCacheStallM, // D$ busy with multicycle operation
|
||||||
// fpu
|
// fpu
|
||||||
input logic [P.FLEN-1:0] FWriteDataM, // Write data from FPU
|
input logic [P.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
|
||||||
// faults
|
// faults
|
||||||
output logic LoadPageFaultM, StoreAmoPageFaultM, // Page fault exceptions
|
output logic LoadPageFaultM, StoreAmoPageFaultM, // Page fault exceptions
|
||||||
output logic LoadMisalignedFaultM, // Load address misaligned fault
|
output logic LoadMisalignedFaultM, // Load address misaligned fault
|
||||||
output logic LoadAccessFaultM, // Load access fault (PMA)
|
output logic LoadAccessFaultM, // Load access fault (PMA)
|
||||||
output logic HPTWInstrAccessFaultF, // HPTW generated access fault during instruction fetch
|
output logic HPTWInstrAccessFaultF, // HPTW generated access fault during instruction fetch
|
||||||
// cpu hazard unit (trap)
|
// cpu hazard unit (trap)
|
||||||
output logic StoreAmoMisalignedFaultM, // Store or AMO address misaligned fault
|
output logic StoreAmoMisalignedFaultM, // Store or AMO address misaligned fault
|
||||||
output logic StoreAmoAccessFaultM, // Store or AMO access fault
|
output logic StoreAmoAccessFaultM, // Store or AMO access fault
|
||||||
// connect to ahb
|
// connect to ahb
|
||||||
output logic [P.PA_BITS-1:0] LSUHADDR, // Bus address from LSU to EBU
|
output logic [P.PA_BITS-1:0] LSUHADDR, // Bus address from LSU to EBU
|
||||||
input logic [P.XLEN-1:0] HRDATA, // Bus read data from LSU to EBU
|
input logic [P.XLEN-1:0] HRDATA, // Bus read data from LSU to EBU
|
||||||
output logic [P.XLEN-1:0] LSUHWDATA, // Bus write data from LSU to EBU
|
output logic [P.XLEN-1:0] LSUHWDATA, // Bus write data from LSU to EBU
|
||||||
input logic LSUHREADY, // Bus ready from LSU to EBU
|
input logic LSUHREADY, // Bus ready from LSU to EBU
|
||||||
output logic LSUHWRITE, // Bus write operation from LSU to EBU
|
output logic LSUHWRITE, // Bus write operation from LSU to EBU
|
||||||
output logic [2:0] LSUHSIZE, // Bus operation size from LSU to EBU
|
output logic [2:0] LSUHSIZE, // Bus operation size from LSU to EBU
|
||||||
output logic [2:0] LSUHBURST, // Bus burst from LSU to EBU
|
output logic [2:0] LSUHBURST, // Bus burst from LSU to EBU
|
||||||
output logic [1:0] LSUHTRANS, // Bus transaction type from LSU to EBU
|
output logic [1:0] LSUHTRANS, // Bus transaction type from LSU to EBU
|
||||||
output logic [P.XLEN/8-1:0] LSUHWSTRB, // Bus byte write enables from LSU to EBU
|
output logic [P.XLEN/8-1:0] LSUHWSTRB, // Bus byte write enables from LSU to EBU
|
||||||
// page table walker
|
// page table walker
|
||||||
input logic [P.XLEN-1:0] SATP_REGW, // SATP (supervisor address translation and protection) CSR
|
input logic [P.XLEN-1:0] SATP_REGW, // SATP (supervisor address translation and protection) CSR
|
||||||
input logic STATUS_MXR, STATUS_SUM, STATUS_MPRV, // STATUS CSR bits: make executable readable, supervisor user memory, machine privilege
|
input logic STATUS_MXR, STATUS_SUM, STATUS_MPRV, // STATUS CSR bits: make executable readable, supervisor user memory, machine privilege
|
||||||
input logic [1:0] STATUS_MPP, // Machine previous privilege mode
|
input logic [1:0] STATUS_MPP, // Machine previous privilege mode
|
||||||
input logic [P.XLEN-1:0] PCSpillF, // Fetch PC
|
input logic [P.XLEN-1:0] PCSpillF, // 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 InstrUpdateDAF, // ITLB hit needs to update dirty or access bits
|
input logic InstrUpdateDAF, // ITLB hit needs to update dirty or access bits
|
||||||
output logic [P.XLEN-1:0] PTE, // Page table entry write to ITLB
|
output logic [P.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
|
||||||
output logic SelHPTW, // During a HPTW walk the effective privilege mode becomes S_MODE
|
output logic SelHPTW, // During a HPTW walk the effective privilege mode becomes S_MODE
|
||||||
input var logic [7:0] PMPCFG_ARRAY_REGW[P.PMP_ENTRIES-1:0], // PMP configuration from privileged unit
|
input var logic [7:0] PMPCFG_ARRAY_REGW[P.PMP_ENTRIES-1:0], // PMP configuration from privileged unit
|
||||||
input var logic [P.PA_BITS-3:0] PMPADDR_ARRAY_REGW[P.PMP_ENTRIES-1:0] // PMP address from privileged unit
|
input var logic [P.PA_BITS-3:0] PMPADDR_ARRAY_REGW[P.PMP_ENTRIES-1:0] // PMP address from privileged unit
|
||||||
);
|
);
|
||||||
|
|
||||||
logic [P.XLEN+1:0] IEUAdrExtM; // Memory stage address zero-extended to PA_BITS or XLEN whichever is longer
|
logic [P.XLEN+1:0] IEUAdrExtM; // Memory stage address zero-extended to PA_BITS or XLEN whichever is longer
|
||||||
@ -94,20 +94,20 @@ module lsu import cvw::*; #(parameter cvw_t P) (
|
|||||||
logic [P.PA_BITS-1:0] PAdrM; // Physical memory address
|
logic [P.PA_BITS-1:0] PAdrM; // Physical memory address
|
||||||
logic [P.XLEN+1:0] IHAdrM; // Either IEU or HPTW memory address
|
logic [P.XLEN+1:0] IHAdrM; // Either IEU or HPTW memory address
|
||||||
|
|
||||||
logic [1:0] PreLSURWM; // IEU or HPTW Read/Write signal
|
logic [1:0] PreLSURWM; // IEU or HPTW Read/Write signal
|
||||||
logic [1:0] LSURWM; // IEU or HPTW Read/Write signal gated by LR/SC
|
logic [1:0] LSURWM; // IEU or HPTW Read/Write signal gated by LR/SC
|
||||||
logic [2:0] LSUFunct3M; // IEU or HPTW memory operation size
|
logic [2:0] LSUFunct3M; // IEU or HPTW memory operation size
|
||||||
logic [6:0] LSUFunct7M; // AMO function gated by HPTW
|
logic [6:0] LSUFunct7M; // AMO function gated by HPTW
|
||||||
logic [1:0] LSUAtomicM; // AMO signal gated by HPTW
|
logic [1:0] LSUAtomicM; // AMO signal gated by HPTW
|
||||||
|
|
||||||
logic GatedStallW; // Hazard unit StallW gated when SelHPTW = 1
|
logic GatedStallW; // Hazard unit StallW gated when SelHPTW = 1
|
||||||
|
|
||||||
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
|
||||||
|
|
||||||
logic CacheableM; // PMA indicates memory address is cacheable
|
logic CacheableM; // PMA indicates memory address is cacheable
|
||||||
logic BusCommittedM; // Bus memory operation in flight, delay interrupts
|
logic BusCommittedM; // Bus memory operation in flight, delay interrupts
|
||||||
logic DCacheCommittedM; // D$ memory operation started, delay interrupts
|
logic DCacheCommittedM; // D$ memory operation started, delay interrupts
|
||||||
|
|
||||||
logic [P.LLEN-1:0] DTIMReadDataWordM; // DTIM read data
|
logic [P.LLEN-1:0] DTIMReadDataWordM; // DTIM read data
|
||||||
logic [P.LLEN-1:0] DCacheReadDataWordM; // D$ read data
|
logic [P.LLEN-1:0] DCacheReadDataWordM; // D$ read data
|
||||||
@ -123,16 +123,15 @@ module lsu import cvw::*; #(parameter cvw_t P) (
|
|||||||
logic [P.LLEN-1:0] LSUWriteDataM; // Final write data
|
logic [P.LLEN-1:0] LSUWriteDataM; // Final write data
|
||||||
logic [(P.LLEN-1)/8:0] ByteMaskM; // Selects which bytes within a word to write
|
logic [(P.LLEN-1)/8:0] ByteMaskM; // Selects which bytes within a word to write
|
||||||
|
|
||||||
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 DataUpdateDAM; // 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
|
||||||
logic IgnoreRequest; // On FlushM or TLB miss ignore memory operation
|
logic IgnoreRequest; // On FlushM or TLB miss ignore memory operation
|
||||||
logic SelDTIM; // Select DTIM rather than bus or D$
|
logic SelDTIM; // Select DTIM rather than bus or D$
|
||||||
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Pipeline for IEUAdr E to M
|
// Pipeline for IEUAdr E to M
|
||||||
// Zero-extend address to 34 bits for XLEN=32
|
// Zero-extend address to 34 bits for XLEN=32
|
||||||
@ -222,7 +221,7 @@ module lsu import cvw::*; #(parameter cvw_t P) (
|
|||||||
|
|
||||||
if (P.DTIM_SUPPORTED) begin : dtim
|
if (P.DTIM_SUPPORTED) begin : dtim
|
||||||
logic [P.PA_BITS-1:0] DTIMAdr;
|
logic [P.PA_BITS-1:0] DTIMAdr;
|
||||||
logic [1:0] DTIMMemRWM;
|
logic [1:0] DTIMMemRWM;
|
||||||
|
|
||||||
// The DTIM uses untranslated addresses, so it is not compatible with virtual memory.
|
// The DTIM uses untranslated addresses, so it is not compatible with virtual memory.
|
||||||
mux2 #(P.PA_BITS) DTIMAdrMux(IEUAdrExtE[P.PA_BITS-1:0], IEUAdrExtM[P.PA_BITS-1:0], MemRWM[0], DTIMAdr);
|
mux2 #(P.PA_BITS) DTIMAdrMux(IEUAdrExtE[P.PA_BITS-1:0], IEUAdrExtM[P.PA_BITS-1:0], MemRWM[0], DTIMAdr);
|
||||||
@ -237,23 +236,23 @@ module lsu import cvw::*; #(parameter cvw_t P) (
|
|||||||
if (P.BUS_SUPPORTED) begin : bus
|
if (P.BUS_SUPPORTED) begin : bus
|
||||||
if(P.DCACHE_SUPPORTED) begin : dcache
|
if(P.DCACHE_SUPPORTED) begin : dcache
|
||||||
localparam LLENWORDSPERLINE = P.DCACHE_LINELENINBITS/P.LLEN; // Number of LLEN words in cacheline
|
localparam LLENWORDSPERLINE = P.DCACHE_LINELENINBITS/P.LLEN; // Number of LLEN words in cacheline
|
||||||
localparam LLENLOGBWPL = $clog2(LLENWORDSPERLINE); // Log2 of ^
|
localparam LLENLOGBWPL = $clog2(LLENWORDSPERLINE); // Log2 of ^
|
||||||
localparam BEATSPERLINE = P.DCACHE_LINELENINBITS/P.AHBW; // Number of AHBW words (beats) in cacheline
|
localparam BEATSPERLINE = P.DCACHE_LINELENINBITS/P.AHBW; // Number of AHBW words (beats) in cacheline
|
||||||
localparam AHBWLOGBWPL = $clog2(BEATSPERLINE); // Log2 of ^
|
localparam AHBWLOGBWPL = $clog2(BEATSPERLINE); // Log2 of ^
|
||||||
localparam LINELEN = P.DCACHE_LINELENINBITS; // Number of bits in cacheline
|
localparam LINELEN = P.DCACHE_LINELENINBITS; // Number of bits in cacheline
|
||||||
localparam LLENPOVERAHBW = P.LLEN / P.AHBW; // Number of AHB beats in a LLEN word. AHBW cannot be larger than LLEN. (implementation limitation)
|
localparam LLENPOVERAHBW = P.LLEN / P.AHBW; // Number of AHB beats in a LLEN word. AHBW cannot be larger than LLEN. (implementation limitation)
|
||||||
|
|
||||||
logic [LINELEN-1:0] FetchBuffer; // Temporary buffer to hold partially fetched cacheline
|
logic [LINELEN-1:0] FetchBuffer; // Temporary buffer to hold partially fetched cacheline
|
||||||
logic [P.PA_BITS-1:0] DCacheBusAdr; // Cacheline address to fetch or writeback.
|
logic [P.PA_BITS-1:0] DCacheBusAdr; // Cacheline address to fetch or writeback.
|
||||||
logic [AHBWLOGBWPL-1:0] BeatCount; // Position within a cacheline. ahbcacheinterface to cache
|
logic [AHBWLOGBWPL-1:0] BeatCount; // Position within a cacheline. ahbcacheinterface to cache
|
||||||
logic DCacheBusAck; // ahbcacheinterface completed fetch or writeback
|
logic DCacheBusAck; // ahbcacheinterface completed fetch or writeback
|
||||||
logic SelBusBeat; // ahbcacheinterface selects postion in cacheline with BeatCount
|
logic SelBusBeat; // ahbcacheinterface selects postion in cacheline with BeatCount
|
||||||
logic [1:0] CacheBusRW; // Cache sends request to ahbcacheinterface
|
logic [1:0] CacheBusRW; // Cache sends request to ahbcacheinterface
|
||||||
logic [1:0] BusRW; // Uncached bus memory access
|
logic [1:0] BusRW; // Uncached bus memory access
|
||||||
logic CacheableOrFlushCacheM; // Memory address is cacheable or operation is a cache flush
|
logic CacheableOrFlushCacheM; // Memory address is cacheable or operation is a cache flush
|
||||||
logic [1:0] CacheRWM; // Cache read (10), write (01), AMO (11)
|
logic [1:0] CacheRWM; // Cache read (10), write (01), AMO (11)
|
||||||
logic [1:0] CacheAtomicM; // Cache AMO
|
logic [1:0] CacheAtomicM; // Cache AMO
|
||||||
logic FlushDCache; // Suppress d cache flush if there is an ITLB miss.
|
logic FlushDCache; // Suppress d cache flush if there is an ITLB miss.
|
||||||
|
|
||||||
assign BusRW = ~CacheableM & ~IgnoreRequestTLB & ~SelDTIM ? LSURWM : '0;
|
assign BusRW = ~CacheableM & ~IgnoreRequestTLB & ~SelDTIM ? LSURWM : '0;
|
||||||
assign CacheableOrFlushCacheM = CacheableM | FlushDCacheM;
|
assign CacheableOrFlushCacheM = CacheableM | FlushDCacheM;
|
||||||
@ -320,6 +319,7 @@ module lsu import cvw::*; #(parameter cvw_t P) (
|
|||||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Atomic operations
|
// Atomic operations
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
if (P.A_SUPPORTED) begin:atomic
|
if (P.A_SUPPORTED) begin:atomic
|
||||||
atomic #(P) atomic(.clk, .reset, .StallW, .ReadDataM(ReadDataM[P.XLEN-1:0]), .IHWriteDataM, .PAdrM,
|
atomic #(P) atomic(.clk, .reset, .StallW, .ReadDataM(ReadDataM[P.XLEN-1:0]), .IHWriteDataM, .PAdrM,
|
||||||
.LSUFunct7M, .LSUFunct3M, .LSUAtomicM, .PreLSURWM, .IgnoreRequest,
|
.LSUFunct7M, .LSUFunct3M, .LSUAtomicM, .PreLSURWM, .IgnoreRequest,
|
||||||
@ -335,6 +335,7 @@ module lsu import cvw::*; #(parameter cvw_t P) (
|
|||||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Subword Accesses
|
// Subword Accesses
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
subwordread #(P.LLEN) subwordread(.ReadDataWordMuxM(LittleEndianReadDataWordM), .PAdrM(PAdrM[2:0]), .BigEndianM,
|
subwordread #(P.LLEN) subwordread(.ReadDataWordMuxM(LittleEndianReadDataWordM), .PAdrM(PAdrM[2:0]), .BigEndianM,
|
||||||
.FpLoadStoreM, .Funct3M(LSUFunct3M), .ReadDataM);
|
.FpLoadStoreM, .Funct3M(LSUFunct3M), .ReadDataM);
|
||||||
subwordwrite #(P.LLEN) subwordwrite(.LSUFunct3M, .IMAFWriteDataM, .LittleEndianWriteDataM);
|
subwordwrite #(P.LLEN) subwordwrite(.LSUFunct3M, .IMAFWriteDataM, .LittleEndianWriteDataM);
|
||||||
@ -361,5 +362,4 @@ module lsu import cvw::*; #(parameter cvw_t P) (
|
|||||||
assign LSUWriteDataM = LittleEndianWriteDataM;
|
assign LSUWriteDataM = LittleEndianWriteDataM;
|
||||||
assign LittleEndianReadDataWordM = ReadDataWordMuxM;
|
assign LittleEndianReadDataWordM = ReadDataWordMuxM;
|
||||||
end
|
end
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -29,12 +29,12 @@
|
|||||||
|
|
||||||
module subwordread #(parameter LLEN)
|
module subwordread #(parameter LLEN)
|
||||||
(
|
(
|
||||||
input logic [LLEN-1:0] ReadDataWordMuxM,
|
input logic [LLEN-1:0] ReadDataWordMuxM,
|
||||||
input logic [2:0] PAdrM,
|
input logic [2:0] PAdrM,
|
||||||
input logic [2:0] Funct3M,
|
input logic [2:0] Funct3M,
|
||||||
input logic FpLoadStoreM,
|
input logic FpLoadStoreM,
|
||||||
input logic BigEndianM,
|
input logic BigEndianM,
|
||||||
output logic [LLEN-1:0] ReadDataM
|
output logic [LLEN-1:0] ReadDataM
|
||||||
);
|
);
|
||||||
|
|
||||||
logic [7:0] ByteM;
|
logic [7:0] ByteM;
|
||||||
@ -89,7 +89,7 @@ module subwordread #(parameter LLEN)
|
|||||||
//3'b100: ReadDataM = FpLoadStoreM ? ReadDataWordMuxM : {{LLEN-8{1'b0}}, ByteM[7:0]}; // lbu/flq - only needed when LLEN=128
|
//3'b100: ReadDataM = FpLoadStoreM ? ReadDataWordMuxM : {{LLEN-8{1'b0}}, ByteM[7:0]}; // lbu/flq - only needed when LLEN=128
|
||||||
3'b101: ReadDataM = {{LLEN-16{1'b0}}, HalfwordM[15:0]}; // lhu
|
3'b101: ReadDataM = {{LLEN-16{1'b0}}, HalfwordM[15:0]}; // lhu
|
||||||
3'b110: ReadDataM = {{LLEN-32{1'b0}}, WordM[31:0]}; // lwu
|
3'b110: ReadDataM = {{LLEN-32{1'b0}}, WordM[31:0]}; // lwu
|
||||||
default: ReadDataM = ReadDataWordMuxM; // Shouldn't happen
|
default: ReadDataM = ReadDataWordMuxM; // Shouldn't happen
|
||||||
endcase
|
endcase
|
||||||
|
|
||||||
end else begin:swrmux // 32-bit
|
end else begin:swrmux // 32-bit
|
||||||
|
@ -28,8 +28,8 @@
|
|||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
module subwordwrite #(parameter LLEN) (
|
module subwordwrite #(parameter LLEN) (
|
||||||
input logic [2:0] LSUFunct3M,
|
input logic [2:0] LSUFunct3M,
|
||||||
input logic [LLEN-1:0] IMAFWriteDataM,
|
input logic [LLEN-1:0] IMAFWriteDataM,
|
||||||
output logic [LLEN-1:0] LittleEndianWriteDataM
|
output logic [LLEN-1:0] LittleEndianWriteDataM
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -46,18 +46,18 @@ module subwordwrite #(parameter LLEN) (
|
|||||||
end else if (LLEN == 64) begin:sww
|
end else if (LLEN == 64) begin:sww
|
||||||
always_comb
|
always_comb
|
||||||
case(LSUFunct3M[1:0])
|
case(LSUFunct3M[1:0])
|
||||||
2'b00: LittleEndianWriteDataM = {8{IMAFWriteDataM[7:0]}}; // sb
|
2'b00: LittleEndianWriteDataM = {8{IMAFWriteDataM[7:0]}}; // sb
|
||||||
2'b01: LittleEndianWriteDataM = {4{IMAFWriteDataM[15:0]}}; // sh
|
2'b01: LittleEndianWriteDataM = {4{IMAFWriteDataM[15:0]}}; // sh
|
||||||
2'b10: LittleEndianWriteDataM = {2{IMAFWriteDataM[31:0]}}; // sw
|
2'b10: LittleEndianWriteDataM = {2{IMAFWriteDataM[31:0]}}; // sw
|
||||||
2'b11: LittleEndianWriteDataM = IMAFWriteDataM; // sd
|
2'b11: LittleEndianWriteDataM = IMAFWriteDataM; // sd
|
||||||
endcase
|
endcase
|
||||||
end else begin:sww // 32-bit
|
end else begin:sww // 32-bit
|
||||||
always_comb
|
always_comb
|
||||||
case(LSUFunct3M[1:0])
|
case(LSUFunct3M[1:0])
|
||||||
2'b00: LittleEndianWriteDataM = {4{IMAFWriteDataM[7:0]}}; // sb
|
2'b00: LittleEndianWriteDataM = {4{IMAFWriteDataM[7:0]}}; // sb
|
||||||
2'b01: LittleEndianWriteDataM = {2{IMAFWriteDataM[15:0]}}; // sh
|
2'b01: LittleEndianWriteDataM = {2{IMAFWriteDataM[15:0]}}; // sh
|
||||||
2'b10: LittleEndianWriteDataM = IMAFWriteDataM; // sw
|
2'b10: LittleEndianWriteDataM = IMAFWriteDataM; // sw
|
||||||
default: LittleEndianWriteDataM = IMAFWriteDataM; // shouldn't happen
|
default: LittleEndianWriteDataM = IMAFWriteDataM; // shouldn't happen
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -28,9 +28,9 @@
|
|||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
module swbytemask #(parameter WORDLEN)(
|
module swbytemask #(parameter WORDLEN)(
|
||||||
input logic [2:0] Size,
|
input logic [2:0] Size,
|
||||||
input logic [$clog2(WORDLEN/8)-1:0] Adr,
|
input logic [$clog2(WORDLEN/8)-1:0] Adr,
|
||||||
output logic [WORDLEN/8-1:0] ByteMask
|
output logic [WORDLEN/8-1:0] ByteMask
|
||||||
);
|
);
|
||||||
|
|
||||||
assign ByteMask = ((2**(2**Size))-1) << Adr;
|
assign ByteMask = ((2**(2**Size))-1) << Adr;
|
||||||
|
@ -27,38 +27,38 @@
|
|||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
module div import cvw::*; #(parameter cvw_t P) (
|
module div import cvw::*; #(parameter cvw_t P) (
|
||||||
input logic clk,
|
input logic clk,
|
||||||
input logic reset,
|
input logic reset,
|
||||||
input logic StallM,
|
input logic StallM,
|
||||||
input logic FlushE,
|
input logic FlushE,
|
||||||
input logic IntDivE, // integer division/remainder instruction of any type
|
input logic IntDivE, // integer division/remainder instruction of any type
|
||||||
input logic DivSignedE, // signed division
|
input logic DivSignedE, // signed division
|
||||||
input logic W64E, // W-type instructions (divw, divuw, remw, remuw)
|
input logic W64E, // W-type instructions (divw, divuw, remw, remuw)
|
||||||
input logic [P.XLEN-1:0] ForwardedSrcAE, ForwardedSrcBE,// Forwarding mux outputs for Source A and B
|
input logic [P.XLEN-1:0] ForwardedSrcAE, ForwardedSrcBE, // Forwarding mux outputs for Source A and B
|
||||||
output logic DivBusyE, // Divide is busy - stall pipeline
|
output logic DivBusyE, // Divide is busy - stall pipeline
|
||||||
output logic [P.XLEN-1:0] QuotM, RemM // Quotient and remainder outputs
|
output logic [P.XLEN-1:0] QuotM, RemM // Quotient and remainder outputs
|
||||||
);
|
);
|
||||||
|
|
||||||
localparam STEPBITS = $clog2(P.XLEN/P.IDIV_BITSPERCYCLE); // Number of steps
|
localparam STEPBITS = $clog2(P.XLEN/P.IDIV_BITSPERCYCLE); // Number of steps
|
||||||
|
|
||||||
typedef enum logic [1:0] {IDLE, BUSY, DONE} statetype; // division FSM state
|
typedef enum logic [1:0] {IDLE, BUSY, DONE} statetype; // division FSM state
|
||||||
statetype state;
|
statetype state;
|
||||||
|
|
||||||
logic [P.XLEN-1:0] W[P.IDIV_BITSPERCYCLE:0]; // Residual for each of k steps
|
logic [P.XLEN-1:0] W[P.IDIV_BITSPERCYCLE:0]; // Residual for each of k steps
|
||||||
logic [P.XLEN-1:0] XQ[P.IDIV_BITSPERCYCLE:0]; // dividend/quotient for each of k steps
|
logic [P.XLEN-1:0] XQ[P.IDIV_BITSPERCYCLE:0]; // dividend/quotient for each of k steps
|
||||||
logic [P.XLEN-1:0] WNext, XQNext; // initialized W and XQ going into registers
|
logic [P.XLEN-1:0] WNext, XQNext; // initialized W and XQ going into registers
|
||||||
logic [P.XLEN-1:0] DinE, XinE; // divisor & dividend, possibly truncated to 32 bits
|
logic [P.XLEN-1:0] DinE, XinE; // divisor & dividend, possibly truncated to 32 bits
|
||||||
logic [P.XLEN-1:0] DnE; // DnE = ~DinE
|
logic [P.XLEN-1:0] DnE; // DnE = ~DinE
|
||||||
logic [P.XLEN-1:0] DAbsBE; // absolute value of D
|
logic [P.XLEN-1:0] DAbsBE; // absolute value of D
|
||||||
logic [P.XLEN-1:0] DAbsB; // registered absolute value of D, constant during division
|
logic [P.XLEN-1:0] DAbsB; // registered absolute value of D, constant during division
|
||||||
logic [P.XLEN-1:0] XnE; // DXnE = ~XinE
|
logic [P.XLEN-1:0] XnE; // DXnE = ~XinE
|
||||||
logic [P.XLEN-1:0] XInitE; // |X|, or original X for divide by 0
|
logic [P.XLEN-1:0] XInitE; // |X|, or original X for divide by 0
|
||||||
logic [P.XLEN-1:0] WnM, XQnM; // negated residual W and quotient XQ for postprocessing sign correction
|
logic [P.XLEN-1:0] WnM, XQnM; // negated residual W and quotient XQ for postprocessing sign correction
|
||||||
logic [STEPBITS:0] step; // division step
|
logic [STEPBITS:0] step; // division step
|
||||||
logic Div0E, Div0M; // divide by 0
|
logic Div0E, Div0M; // divide by 0
|
||||||
logic DivStartE; // start integer division
|
logic DivStartE; // start integer division
|
||||||
logic SignXE, SignDE; // sign of dividend and divisor
|
logic SignXE, SignDE; // sign of dividend and divisor
|
||||||
logic NegQE, NegWM, NegQM; // negate quotient or residual during postprocessing
|
logic NegQE, NegWM, NegQM; // negate quotient or residual during postprocessing
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
// Execute Stage: prepare for division calculation with control logic, W logic and absolute values, initialize W and XQ
|
// Execute Stage: prepare for division calculation with control logic, W logic and absolute values, initialize W and XQ
|
||||||
@ -131,7 +131,7 @@ module div import cvw::*; #(parameter cvw_t P) (
|
|||||||
step <= 1;
|
step <= 1;
|
||||||
if (Div0E) state <= DONE;
|
if (Div0E) state <= DONE;
|
||||||
else state <= BUSY;
|
else state <= BUSY;
|
||||||
end else if (state == BUSY) begin // pause one cycle at beginning of signed operations for absolute value
|
end else if (state == BUSY) begin // pause one cycle at beginning of signed operations for absolute value
|
||||||
if (step[STEPBITS] | (P.XLEN==64) & W64E & step[STEPBITS-1]) begin // complete in half the time for W-type instructions
|
if (step[STEPBITS] | (P.XLEN==64) & W64E & step[STEPBITS-1]) begin // complete in half the time for W-type instructions
|
||||||
state <= DONE;
|
state <= DONE;
|
||||||
end
|
end
|
||||||
|
@ -27,21 +27,21 @@
|
|||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
module mdu import cvw::*; #(parameter cvw_t P) (
|
module mdu import cvw::*; #(parameter cvw_t P) (
|
||||||
input logic clk, reset,
|
input logic clk, reset,
|
||||||
input logic StallM, StallW,
|
input logic StallM, StallW,
|
||||||
input logic FlushE, FlushM, FlushW,
|
input logic FlushE, FlushM, FlushW,
|
||||||
input logic [P.XLEN-1:0] ForwardedSrcAE, ForwardedSrcBE, // inputs A and B from IEU forwarding mux output
|
input logic [P.XLEN-1:0] ForwardedSrcAE, ForwardedSrcBE, // inputs A and B from IEU forwarding mux output
|
||||||
input logic [2:0] Funct3E, Funct3M, // type of MDU operation
|
input logic [2:0] Funct3E, Funct3M, // type of MDU operation
|
||||||
input logic IntDivE, W64E, // Integer division/remainder, and W-type instrutions
|
input logic IntDivE, W64E, // Integer division/remainder, and W-type instrutions
|
||||||
output logic [P.XLEN-1:0] MDUResultW, // multiply/divide result
|
output logic [P.XLEN-1:0] MDUResultW, // multiply/divide result
|
||||||
output logic DivBusyE // busy signal to stall pipeline in Execute stage
|
output logic DivBusyE // busy signal to stall pipeline in Execute stage
|
||||||
);
|
);
|
||||||
|
|
||||||
logic [P.XLEN*2-1:0] ProdM; // double-width product from mul
|
logic [P.XLEN*2-1:0] ProdM; // double-width product from mul
|
||||||
logic [P.XLEN-1:0] QuotM, RemM; // quotient and remainder from intdivrestoring
|
logic [P.XLEN-1:0] QuotM, RemM; // quotient and remainder from intdivrestoring
|
||||||
logic [P.XLEN-1:0] PrelimResultM; // selected result before W truncation
|
logic [P.XLEN-1:0] PrelimResultM; // selected result before W truncation
|
||||||
logic [P.XLEN-1:0] MDUResultM; // result after W truncation
|
logic [P.XLEN-1:0] MDUResultM; // result after W truncation
|
||||||
logic W64M; // W-type instruction
|
logic W64M; // W-type instruction
|
||||||
|
|
||||||
// Multiplier
|
// Multiplier
|
||||||
mul #(P.XLEN) mul(.clk, .reset, .StallM, .FlushM, .ForwardedSrcAE, .ForwardedSrcBE, .Funct3E, .ProdM);
|
mul #(P.XLEN) mul(.clk, .reset, .StallM, .FlushM, .ForwardedSrcAE, .ForwardedSrcBE, .Funct3E, .ProdM);
|
||||||
@ -64,13 +64,13 @@ module mdu import cvw::*; #(parameter cvw_t P) (
|
|||||||
always_comb
|
always_comb
|
||||||
case (Funct3M)
|
case (Funct3M)
|
||||||
3'b000: PrelimResultM = ProdM[P.XLEN-1:0]; // mul
|
3'b000: PrelimResultM = ProdM[P.XLEN-1:0]; // mul
|
||||||
3'b001: PrelimResultM = ProdM[P.XLEN*2-1:P.XLEN]; // mulh
|
3'b001: PrelimResultM = ProdM[P.XLEN*2-1:P.XLEN]; // mulh
|
||||||
3'b010: PrelimResultM = ProdM[P.XLEN*2-1:P.XLEN]; // mulhsu
|
3'b010: PrelimResultM = ProdM[P.XLEN*2-1:P.XLEN]; // mulhsu
|
||||||
3'b011: PrelimResultM = ProdM[P.XLEN*2-1:P.XLEN]; // mulhu
|
3'b011: PrelimResultM = ProdM[P.XLEN*2-1:P.XLEN]; // mulhu
|
||||||
3'b100: PrelimResultM = QuotM; // div
|
3'b100: PrelimResultM = QuotM; // div
|
||||||
3'b101: PrelimResultM = QuotM; // divu
|
3'b101: PrelimResultM = QuotM; // divu
|
||||||
3'b110: PrelimResultM = RemM; // rem
|
3'b110: PrelimResultM = RemM; // rem
|
||||||
3'b111: PrelimResultM = RemM; // remu
|
3'b111: PrelimResultM = RemM; // remu
|
||||||
endcase
|
endcase
|
||||||
|
|
||||||
// Handle sign extension for W-type instructions
|
// Handle sign extension for W-type instructions
|
||||||
@ -84,5 +84,3 @@ module mdu import cvw::*; #(parameter cvw_t P) (
|
|||||||
// Writeback stage pipeline register
|
// Writeback stage pipeline register
|
||||||
flopenrc #(P.XLEN) MDUResultWReg(clk, reset, FlushW, ~StallW, MDUResultM, MDUResultW);
|
flopenrc #(P.XLEN) MDUResultWReg(clk, reset, FlushW, ~StallW, MDUResultM, MDUResultW);
|
||||||
endmodule // mdu
|
endmodule // mdu
|
||||||
|
|
||||||
|
|
||||||
|
@ -29,9 +29,9 @@
|
|||||||
module mul #(parameter XLEN) (
|
module mul #(parameter XLEN) (
|
||||||
input logic clk, reset,
|
input logic clk, reset,
|
||||||
input logic StallM, FlushM,
|
input logic StallM, FlushM,
|
||||||
input logic [XLEN-1:0] ForwardedSrcAE, ForwardedSrcBE, // source A and B from after Forwarding mux
|
input logic [XLEN-1:0] ForwardedSrcAE, ForwardedSrcBE, // source A and B from after Forwarding mux
|
||||||
input logic [2:0] Funct3E, // type of multiply
|
input logic [2:0] Funct3E, // type of multiply
|
||||||
output logic [XLEN*2-1:0] ProdM // double-widthproduct
|
output logic [XLEN*2-1:0] ProdM // double-widthproduct
|
||||||
);
|
);
|
||||||
|
|
||||||
// Number systems
|
// Number systems
|
||||||
@ -48,12 +48,12 @@ module mul #(parameter XLEN) (
|
|||||||
// Signed * Unsigned = P' + ( PA - PB)*2^(XLEN-1) - PP*2^(2XLEN-2)
|
// Signed * Unsigned = P' + ( PA - PB)*2^(XLEN-1) - PP*2^(2XLEN-2)
|
||||||
// Unsigned * Unsigned = P' + ( PA + PB)*2^(XLEN-1) + PP*2^(2XLEN-2)
|
// Unsigned * Unsigned = P' + ( PA + PB)*2^(XLEN-1) + PP*2^(2XLEN-2)
|
||||||
|
|
||||||
logic [XLEN-1:0] Aprime, Bprime; // lower bits of source A and B
|
logic [XLEN-1:0] Aprime, Bprime; // lower bits of source A and B
|
||||||
logic MULH, MULHSU; // type of multiply
|
logic MULH, MULHSU; // type of multiply
|
||||||
logic [XLEN-2:0] PA, PB; // product of msb and lsbs
|
logic [XLEN-2:0] PA, PB; // product of msb and lsbs
|
||||||
logic PP; // product of msbs
|
logic PP; // product of msbs
|
||||||
logic [XLEN*2-1:0] PP1E, PP2E, PP3E, PP4E; // partial products
|
logic [XLEN*2-1:0] PP1E, PP2E, PP3E, PP4E; // partial products
|
||||||
logic [XLEN*2-1:0] PP1M, PP2M, PP3M, PP4M; // registered partial proudcts
|
logic [XLEN*2-1:0] PP1M, PP2M, PP3M, PP4M; // registered partial proudcts
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
// Execute Stage: Compute partial products
|
// Execute Stage: Compute partial products
|
||||||
@ -90,4 +90,3 @@ module mul #(parameter XLEN) (
|
|||||||
// add up partial products; this multi-input add implies CSAs and a final CPA
|
// add up partial products; this multi-input add implies CSAs and a final CPA
|
||||||
assign ProdM = PP1M + PP2M + PP3M + PP4M; //ForwardedSrcAE * ForwardedSrcBE;
|
assign ProdM = PP1M + PP2M + PP3M + PP4M; //ForwardedSrcAE * ForwardedSrcBE;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
@ -27,8 +27,8 @@
|
|||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
module adrdec #(parameter PA_BITS) (
|
module adrdec #(parameter PA_BITS) (
|
||||||
input logic [PA_BITS-1:0] PhysicalAddress, // Physical address to decode
|
input logic [PA_BITS-1:0] PhysicalAddress, // Physical address to decode
|
||||||
input logic [PA_BITS-1:0] Base, Range, // Base and range of peripheral addresses
|
input logic [PA_BITS-1:0] Base, Range, // Base and range of peripheral addresses
|
||||||
input logic Supported, // Is this peripheral supported?
|
input logic Supported, // Is this peripheral supported?
|
||||||
input logic AccessValid, // Is the access type valid?
|
input logic AccessValid, // Is the access type valid?
|
||||||
input logic [1:0] Size, // Size of access
|
input logic [1:0] Size, // Size of access
|
||||||
@ -50,4 +50,3 @@ module adrdec #(parameter PA_BITS) (
|
|||||||
// Select this peripheral if the address matches, the peripheral is supported, and the type and size of access is ok
|
// Select this peripheral if the address matches, the peripheral is supported, and the type and size of access is ok
|
||||||
assign Sel = Match & Supported & AccessValid & SizeValid;
|
assign Sel = Match & Supported & AccessValid & SizeValid;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
@ -30,12 +30,12 @@
|
|||||||
|
|
||||||
module adrdecs import cvw::*; #(parameter cvw_t P) (
|
module adrdecs import cvw::*; #(parameter cvw_t P) (
|
||||||
input logic [P.PA_BITS-1:0] PhysicalAddress,
|
input logic [P.PA_BITS-1:0] PhysicalAddress,
|
||||||
input logic AccessRW, AccessRX, AccessRWX,
|
input logic AccessRW, AccessRX, AccessRWX,
|
||||||
input logic [1:0] Size,
|
input logic [1:0] Size,
|
||||||
output logic [10:0] SelRegions
|
output logic [10:0] SelRegions
|
||||||
);
|
);
|
||||||
|
|
||||||
localparam logic [3:0] SUPPORTED_SIZE = (P.LLEN == 32 ? 4'b0111 : 4'b1111);
|
localparam logic [3:0] SUPPORTED_SIZE = (P.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 #(P.PA_BITS) dtimdec(PhysicalAddress, P.DTIM_BASE[P.PA_BITS-1:0], P.DTIM_RANGE[P.PA_BITS-1:0], P.DTIM_SUPPORTED, AccessRW, Size, SUPPORTED_SIZE, SelRegions[10]);
|
adrdec #(P.PA_BITS) dtimdec(PhysicalAddress, P.DTIM_BASE[P.PA_BITS-1:0], P.DTIM_RANGE[P.PA_BITS-1:0], P.DTIM_SUPPORTED, AccessRW, Size, SUPPORTED_SIZE, SelRegions[10]);
|
||||||
adrdec #(P.PA_BITS) iromdec(PhysicalAddress, P.IROM_BASE[P.PA_BITS-1:0], P.IROM_RANGE[P.PA_BITS-1:0], P.IROM_SUPPORTED, AccessRX, Size, SUPPORTED_SIZE, SelRegions[9]);
|
adrdec #(P.PA_BITS) iromdec(PhysicalAddress, P.IROM_BASE[P.PA_BITS-1:0], P.IROM_RANGE[P.PA_BITS-1:0], P.IROM_SUPPORTED, AccessRX, Size, SUPPORTED_SIZE, SelRegions[9]);
|
||||||
|
118
src/mmu/hptw.sv
118
src/mmu/hptw.sv
@ -30,39 +30,39 @@
|
|||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
|
|
||||||
module hptw import cvw::*; #(parameter cvw_t P) (
|
module hptw import cvw::*; #(parameter cvw_t P) (
|
||||||
input logic clk, reset,
|
input logic clk, reset,
|
||||||
input logic [P.XLEN-1:0] SATP_REGW, // includes SATP.MODE to determine number of levels in page table
|
input logic [P.XLEN-1:0] SATP_REGW, // includes SATP.MODE to determine number of levels in page table
|
||||||
input logic [P.XLEN-1:0] PCSpillF, // addresses to translate
|
input logic [P.XLEN-1:0] PCSpillF, // addresses to translate
|
||||||
input logic [P.XLEN+1:0] IEUAdrExtM, // addresses to translate
|
input logic [P.XLEN+1:0] IEUAdrExtM, // addresses to translate
|
||||||
input logic [1:0] MemRWM, AtomicM,
|
input logic [1:0] MemRWM, AtomicM,
|
||||||
// system status
|
// system status
|
||||||
input logic STATUS_MXR, STATUS_SUM, STATUS_MPRV,
|
input logic STATUS_MXR, STATUS_SUM, STATUS_MPRV,
|
||||||
input logic [1:0] STATUS_MPP,
|
input logic [1:0] STATUS_MPP,
|
||||||
input logic [1:0] PrivilegeModeW,
|
input logic [1:0] PrivilegeModeW,
|
||||||
input logic [P.XLEN-1:0] ReadDataM, // page table entry from LSU
|
input logic [P.XLEN-1:0] ReadDataM, // page table entry from LSU
|
||||||
input logic [P.XLEN-1:0] WriteDataM,
|
input logic [P.XLEN-1:0] WriteDataM,
|
||||||
input logic DCacheStallM, // stall from LSU
|
input logic DCacheStallM, // stall from LSU
|
||||||
input logic [2:0] Funct3M,
|
input logic [2:0] Funct3M,
|
||||||
input logic [6:0] Funct7M,
|
input logic [6:0] Funct7M,
|
||||||
input logic ITLBMissF,
|
input logic ITLBMissF,
|
||||||
input logic DTLBMissM,
|
input logic DTLBMissM,
|
||||||
input logic FlushW,
|
input logic FlushW,
|
||||||
input logic InstrUpdateDAF,
|
input logic InstrUpdateDAF,
|
||||||
input logic DataUpdateDAM,
|
input logic DataUpdateDAM,
|
||||||
output logic [P.XLEN-1:0] PTE, // page table entry to TLBs
|
output logic [P.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
|
||||||
output logic [1:0] PreLSURWM,
|
output logic [1:0] PreLSURWM,
|
||||||
output logic [P.XLEN+1:0] IHAdrM,
|
output logic [P.XLEN+1:0] IHAdrM,
|
||||||
output logic [P.XLEN-1:0] IHWriteDataM,
|
output logic [P.XLEN-1:0] IHWriteDataM,
|
||||||
output logic [1:0] LSUAtomicM,
|
output logic [1:0] LSUAtomicM,
|
||||||
output logic [2:0] LSUFunct3M,
|
output logic [2:0] LSUFunct3M,
|
||||||
output logic [6:0] LSUFunct7M,
|
output logic [6:0] LSUFunct7M,
|
||||||
output logic IgnoreRequestTLB,
|
output logic IgnoreRequestTLB,
|
||||||
output logic SelHPTW,
|
output logic SelHPTW,
|
||||||
output logic HPTWStall,
|
output logic HPTWStall,
|
||||||
input logic LSULoadAccessFaultM, LSUStoreAmoAccessFaultM,
|
input logic LSULoadAccessFaultM, LSUStoreAmoAccessFaultM,
|
||||||
output logic LoadAccessFaultM, StoreAmoAccessFaultM, HPTWInstrAccessFaultF
|
output logic LoadAccessFaultM, StoreAmoAccessFaultM, HPTWInstrAccessFaultF
|
||||||
);
|
);
|
||||||
|
|
||||||
typedef enum logic [3:0] {L0_ADR, L0_RD,
|
typedef enum logic [3:0] {L0_ADR, L0_RD,
|
||||||
@ -72,39 +72,39 @@ module hptw import cvw::*; #(parameter cvw_t P) (
|
|||||||
LEAF, IDLE, UPDATE_PTE,
|
LEAF, IDLE, UPDATE_PTE,
|
||||||
FAULT} statetype;
|
FAULT} statetype;
|
||||||
|
|
||||||
logic DTLBWalk; // register TLBs translation miss requests
|
logic DTLBWalk; // register TLBs translation miss requests
|
||||||
logic [P.PPN_BITS-1:0] BasePageTablePPN;
|
logic [P.PPN_BITS-1:0] BasePageTablePPN;
|
||||||
logic [P.PPN_BITS-1:0] CurrentPPN;
|
logic [P.PPN_BITS-1:0] CurrentPPN;
|
||||||
logic Executable, Writable, Readable, Valid, PTE_U;
|
logic Executable, Writable, Readable, Valid, PTE_U;
|
||||||
logic Misaligned, MegapageMisaligned;
|
logic Misaligned, MegapageMisaligned;
|
||||||
logic ValidPTE, LeafPTE, ValidLeafPTE, ValidNonLeafPTE;
|
logic ValidPTE, LeafPTE, ValidLeafPTE, ValidNonLeafPTE;
|
||||||
logic StartWalk;
|
logic StartWalk;
|
||||||
logic TLBMiss;
|
logic TLBMiss;
|
||||||
logic PRegEn;
|
logic PRegEn;
|
||||||
logic [1:0] NextPageType;
|
logic [1:0] NextPageType;
|
||||||
logic [P.SVMODE_BITS-1:0] SvMode;
|
logic [P.SVMODE_BITS-1:0] SvMode;
|
||||||
logic [P.XLEN-1:0] TranslationVAdr;
|
logic [P.XLEN-1:0] TranslationVAdr;
|
||||||
logic [P.XLEN-1:0] NextPTE;
|
logic [P.XLEN-1:0] NextPTE;
|
||||||
logic UpdatePTE;
|
logic UpdatePTE;
|
||||||
logic HPTWUpdateDA;
|
logic HPTWUpdateDA;
|
||||||
logic [P.PA_BITS-1:0] HPTWReadAdr;
|
logic [P.PA_BITS-1:0] HPTWReadAdr;
|
||||||
logic SelHPTWAdr;
|
logic SelHPTWAdr;
|
||||||
logic [P.XLEN+1:0] HPTWAdrExt;
|
logic [P.XLEN+1:0] HPTWAdrExt;
|
||||||
logic ITLBMissOrUpdateDAF;
|
logic ITLBMissOrUpdateDAF;
|
||||||
logic DTLBMissOrUpdateDAM;
|
logic DTLBMissOrUpdateDAM;
|
||||||
logic LSUAccessFaultM;
|
logic LSUAccessFaultM;
|
||||||
logic [P.PA_BITS-1:0] HPTWAdr;
|
logic [P.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;
|
||||||
logic HPTWLoadAccessFault, HPTWStoreAmoAccessFault, HPTWInstrAccessFault;
|
logic HPTWLoadAccessFault, HPTWStoreAmoAccessFault, HPTWInstrAccessFault;
|
||||||
logic HPTWLoadAccessFaultDelay, HPTWStoreAmoAccessFaultDelay, HPTWInstrAccessFaultDelay;
|
logic HPTWLoadAccessFaultDelay, HPTWStoreAmoAccessFaultDelay, HPTWInstrAccessFaultDelay;
|
||||||
logic HPTWAccessFaultDelay;
|
logic HPTWAccessFaultDelay;
|
||||||
logic TakeHPTWFault, TakeHPTWFaultDelay;
|
logic TakeHPTWFault, TakeHPTWFaultDelay;
|
||||||
|
|
||||||
// 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 LSUAccessFaultM = LSULoadAccessFaultM | LSUStoreAmoAccessFaultM;
|
assign LSUAccessFaultM = LSULoadAccessFaultM | LSUStoreAmoAccessFaultM;
|
||||||
assign HPTWLoadAccessFault = LSUAccessFaultM & DTLBWalk & MemRWM[1] & ~MemRWM[0];
|
assign HPTWLoadAccessFault = LSUAccessFaultM & DTLBWalk & MemRWM[1] & ~MemRWM[0];
|
||||||
assign HPTWStoreAmoAccessFault = LSUAccessFaultM & DTLBWalk & MemRWM[0];
|
assign HPTWStoreAmoAccessFault = LSUAccessFaultM & DTLBWalk & MemRWM[0];
|
||||||
assign HPTWInstrAccessFault = LSUAccessFaultM & ~DTLBWalk;
|
assign HPTWInstrAccessFault = LSUAccessFaultM & ~DTLBWalk;
|
||||||
|
|
||||||
@ -140,16 +140,16 @@ module hptw import cvw::*; #(parameter cvw_t P) (
|
|||||||
assign ValidNonLeafPTE = ValidPTE & ~LeafPTE;
|
assign ValidNonLeafPTE = ValidPTE & ~LeafPTE;
|
||||||
|
|
||||||
if(P.SVADU_SUPPORTED) begin : hptwwrites
|
if(P.SVADU_SUPPORTED) begin : hptwwrites
|
||||||
logic ReadAccess, WriteAccess;
|
logic ReadAccess, WriteAccess;
|
||||||
logic InvalidRead, InvalidWrite, InvalidOp;
|
logic InvalidRead, InvalidWrite, InvalidOp;
|
||||||
logic UpperBitsUnequal;
|
logic UpperBitsUnequal;
|
||||||
logic OtherPageFault;
|
logic OtherPageFault;
|
||||||
logic [1:0] EffectivePrivilegeMode;
|
logic [1:0] EffectivePrivilegeMode;
|
||||||
logic ImproperPrivilege;
|
logic ImproperPrivilege;
|
||||||
logic SaveHPTWAdr, SelHPTWWriteAdr;
|
logic SaveHPTWAdr, SelHPTWWriteAdr;
|
||||||
logic [P.PA_BITS-1:0] HPTWWriteAdr;
|
logic [P.PA_BITS-1:0] HPTWWriteAdr;
|
||||||
logic SetDirty;
|
logic SetDirty;
|
||||||
logic Dirty, Accessed;
|
logic Dirty, Accessed;
|
||||||
logic [P.XLEN-1:0] AccessedPTE;
|
logic [P.XLEN-1:0] AccessedPTE;
|
||||||
|
|
||||||
assign AccessedPTE = {PTE[P.XLEN-1:8], (SetDirty | PTE[7]), 1'b1, PTE[5:0]}; // set accessed bit, conditionally set dirty bit
|
assign AccessedPTE = {PTE[P.XLEN-1:8], (SetDirty | PTE[7]), 1'b1, PTE[5:0]}; // set accessed bit, conditionally set dirty bit
|
||||||
@ -194,8 +194,8 @@ module hptw import cvw::*; #(parameter cvw_t P) (
|
|||||||
end
|
end
|
||||||
|
|
||||||
// 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 & ~HPTWUpdateDA) & DTLBWalk;
|
assign DTLBWriteM = (WalkerState == LEAF & ~HPTWUpdateDA) & DTLBWalk;
|
||||||
assign ITLBWriteF = (WalkerState == LEAF & ~HPTWUpdateDA) & ~DTLBWalk;
|
assign ITLBWriteF = (WalkerState == LEAF & ~HPTWUpdateDA) & ~DTLBWalk;
|
||||||
|
|
||||||
@ -310,7 +310,7 @@ module hptw import cvw::*; #(parameter cvw_t P) (
|
|||||||
|
|
||||||
// multiplex the outputs to LSU
|
// multiplex the outputs to LSU
|
||||||
if(P.XLEN == 64) assign HPTWAdrExt = {{(P.XLEN+2-P.PA_BITS){1'b0}}, HPTWAdr}; // extend to 66 bits
|
if(P.XLEN == 64) assign HPTWAdrExt = {{(P.XLEN+2-P.PA_BITS){1'b0}}, HPTWAdr}; // extend to 66 bits
|
||||||
else assign HPTWAdrExt = HPTWAdr;
|
else assign HPTWAdrExt = HPTWAdr;
|
||||||
mux2 #(2) rwmux(MemRWM, HPTWRW, SelHPTW, PreLSURWM);
|
mux2 #(2) rwmux(MemRWM, HPTWRW, SelHPTW, PreLSURWM);
|
||||||
mux2 #(3) sizemux(Funct3M, HPTWSize, SelHPTW, LSUFunct3M);
|
mux2 #(3) sizemux(Funct3M, HPTWSize, SelHPTW, LSUFunct3M);
|
||||||
mux2 #(7) funct7mux(Funct7M, 7'b0, SelHPTW, LSUFunct7M);
|
mux2 #(7) funct7mux(Funct7M, 7'b0, SelHPTW, LSUFunct7M);
|
||||||
|
@ -28,48 +28,48 @@
|
|||||||
|
|
||||||
module mmu import cvw::*; #(parameter cvw_t P,
|
module mmu import cvw::*; #(parameter cvw_t P,
|
||||||
parameter TLB_ENTRIES = 8, IMMU = 0) (
|
parameter TLB_ENTRIES = 8, IMMU = 0) (
|
||||||
input logic clk, reset,
|
input logic clk, reset,
|
||||||
input logic [P.XLEN-1:0] SATP_REGW, // Current value of satp CSR (from privileged unit)
|
input logic [P.XLEN-1:0] SATP_REGW, // Current value of satp CSR (from privileged unit)
|
||||||
input logic STATUS_MXR, // Status CSR: make executable page readable
|
input logic STATUS_MXR, // Status CSR: make executable page readable
|
||||||
input logic STATUS_SUM, // Status CSR: Supervisor access to user memory
|
input logic STATUS_SUM, // Status CSR: Supervisor access to user memory
|
||||||
input logic STATUS_MPRV, // Status CSR: modify machine privilege
|
input logic STATUS_MPRV, // Status CSR: modify machine privilege
|
||||||
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 [1:0] PrivilegeModeW, // Current privilege level of the processeor
|
input logic [1:0] PrivilegeModeW, // Current privilege level of the processeor
|
||||||
input logic DisableTranslation, // virtual address translation disabled during D$ flush and HPTW walk that use physical addresses
|
input logic DisableTranslation, // virtual address translation disabled during D$ flush and HPTW walk that use physical addresses
|
||||||
input logic [P.XLEN+1:0] VAdr, // virtual/physical address from IEU or physical address from HPTW
|
input logic [P.XLEN+1:0] VAdr, // virtual/physical address from IEU or physical address from HPTW
|
||||||
input logic [1:0] Size, // access size: 00 = 8 bits, 01 = 16 bits, 10 = 32 bits , 11 = 64 bits
|
input logic [1:0] Size, // access size: 00 = 8 bits, 01 = 16 bits, 10 = 32 bits , 11 = 64 bits
|
||||||
input logic [P.XLEN-1:0] PTE, // page table entry
|
input logic [P.XLEN-1:0] PTE, // page table entry
|
||||||
input logic [1:0] PageTypeWriteVal, // page type
|
input logic [1:0] PageTypeWriteVal, // page type
|
||||||
input logic TLBWrite, // write TLB entry
|
input logic TLBWrite, // write TLB entry
|
||||||
input logic TLBFlush, // Invalidate all TLB entries
|
input logic TLBFlush, // Invalidate all TLB entries
|
||||||
output logic [P.PA_BITS-1:0] PhysicalAddress, // PAdr when no translation, or translated VAdr (TLBPAdr) when there is translation
|
output logic [P.PA_BITS-1:0] PhysicalAddress, // PAdr when no translation, or translated VAdr (TLBPAdr) when there is translation
|
||||||
output logic TLBMiss, // Miss TLB
|
output logic TLBMiss, // Miss TLB
|
||||||
output logic Cacheable, // PMA indicates memory address is cachable
|
output logic Cacheable, // PMA indicates memory address is cachable
|
||||||
output logic Idempotent, // PMA indicates memory address is idempotent
|
output logic Idempotent, // PMA indicates memory address is idempotent
|
||||||
output logic SelTIM, // Select a tightly integrated memory
|
output logic SelTIM, // Select a tightly integrated memory
|
||||||
// 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 UpdateDA, // 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
|
||||||
input var logic [7:0] PMPCFG_ARRAY_REGW[P.PMP_ENTRIES-1:0], // PMP configuration
|
input var logic [7:0] PMPCFG_ARRAY_REGW[P.PMP_ENTRIES-1:0], // PMP configuration
|
||||||
input var logic [P.PA_BITS-3:0] PMPADDR_ARRAY_REGW[P.PMP_ENTRIES-1:0] // PMP addresses
|
input var logic [P.PA_BITS-3:0] PMPADDR_ARRAY_REGW[P.PMP_ENTRIES-1:0] // PMP addresses
|
||||||
);
|
);
|
||||||
|
|
||||||
logic [P.PA_BITS-1:0] TLBPAdr; // physical address for TLB
|
logic [P.PA_BITS-1:0] TLBPAdr; // physical address for TLB
|
||||||
logic PMAInstrAccessFaultF; // Instruction access fault from PMA
|
logic PMAInstrAccessFaultF; // Instruction access fault from PMA
|
||||||
logic PMPInstrAccessFaultF; // Instruction access fault from PMP
|
logic PMPInstrAccessFaultF; // Instruction access fault from PMP
|
||||||
logic PMALoadAccessFaultM; // Load access fault from PMA
|
logic PMALoadAccessFaultM; // Load access fault from PMA
|
||||||
logic PMPLoadAccessFaultM; // Load access fault from PMP
|
logic PMPLoadAccessFaultM; // Load access fault from PMP
|
||||||
logic PMAStoreAmoAccessFaultM; // Store or AMO access fault from PMA
|
logic PMAStoreAmoAccessFaultM; // Store or AMO access fault from PMA
|
||||||
logic PMPStoreAmoAccessFaultM; // Store or AMO access fault from PMP
|
logic PMPStoreAmoAccessFaultM; // Store or AMO access fault from PMP
|
||||||
logic DataMisalignedM; // load or store misaligned
|
logic DataMisalignedM; // load or store misaligned
|
||||||
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
|
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 (P.VIRTMEM_SUPPORTED) begin:tlb
|
if (P.VIRTMEM_SUPPORTED) begin:tlb
|
||||||
@ -86,9 +86,9 @@ module mmu import cvw::*; #(parameter cvw_t P,
|
|||||||
.TLBWrite, .TLBFlush, .TLBPAdr, .TLBMiss, .TLBHit,
|
.TLBWrite, .TLBFlush, .TLBPAdr, .TLBMiss, .TLBHit,
|
||||||
.Translate, .TLBPageFault, .UpdateDA);
|
.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;
|
||||||
assign TLBHit = 1; // *** is this necessary
|
assign TLBHit = 1; // *** is this necessary
|
||||||
assign TLBPageFault = 0;
|
assign TLBPageFault = 0;
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -30,26 +30,26 @@
|
|||||||
|
|
||||||
module pmachecker import cvw::*; #(parameter cvw_t P) (
|
module pmachecker import cvw::*; #(parameter cvw_t P) (
|
||||||
input logic [P.PA_BITS-1:0] PhysicalAddress,
|
input logic [P.PA_BITS-1:0] PhysicalAddress,
|
||||||
input logic [1:0] Size,
|
input logic [1:0] Size,
|
||||||
input logic AtomicAccessM, // Atomic access
|
input logic AtomicAccessM, // Atomic access
|
||||||
input logic ExecuteAccessF, // Execute access
|
input logic ExecuteAccessF, // Execute access
|
||||||
input logic WriteAccessM, // Write access
|
input logic WriteAccessM, // Write access
|
||||||
input logic ReadAccessM, // Read access
|
input logic ReadAccessM, // Read access
|
||||||
output logic Cacheable, Idempotent, SelTIM,
|
output logic Cacheable, Idempotent, SelTIM,
|
||||||
output logic PMAInstrAccessFaultF,
|
output logic PMAInstrAccessFaultF,
|
||||||
output logic PMALoadAccessFaultM,
|
output logic PMALoadAccessFaultM,
|
||||||
output logic PMAStoreAmoAccessFaultM
|
output logic PMAStoreAmoAccessFaultM
|
||||||
);
|
);
|
||||||
|
|
||||||
logic PMAAccessFault;
|
logic PMAAccessFault;
|
||||||
logic AccessRW, AccessRWX, AccessRX;
|
logic AccessRW, AccessRWX, AccessRX;
|
||||||
logic [10:0] SelRegions;
|
logic [10:0] SelRegions;
|
||||||
logic AtomicAllowed;
|
logic AtomicAllowed;
|
||||||
|
|
||||||
// Determine what type of access is being made
|
// Determine what type of access is being made
|
||||||
assign AccessRW = ReadAccessM | WriteAccessM;
|
assign AccessRW = ReadAccessM | WriteAccessM;
|
||||||
assign AccessRWX = ReadAccessM | WriteAccessM | ExecuteAccessF;
|
assign AccessRWX = ReadAccessM | WriteAccessM | ExecuteAccessF;
|
||||||
assign AccessRX = ReadAccessM | ExecuteAccessF;
|
assign AccessRX = ReadAccessM | ExecuteAccessF;
|
||||||
|
|
||||||
// Determine which region of physical memory (if any) is being accessed
|
// Determine which region of physical memory (if any) is being accessed
|
||||||
adrdecs #(P) adrdecs(PhysicalAddress, AccessRW, AccessRX, AccessRWX, Size, SelRegions);
|
adrdecs #(P) adrdecs(PhysicalAddress, AccessRW, AccessRX, AccessRWX, Size, SelRegions);
|
||||||
@ -65,9 +65,8 @@ module pmachecker import cvw::*; #(parameter cvw_t P) (
|
|||||||
assign SelTIM = SelRegions[10] | SelRegions[9]; // exclusion-tag: unused-tim
|
assign SelTIM = SelRegions[10] | SelRegions[9]; // exclusion-tag: unused-tim
|
||||||
|
|
||||||
// Detect access faults
|
// Detect access faults
|
||||||
assign PMAAccessFault = (SelRegions[0]) & AccessRWX | AtomicAccessM & ~AtomicAllowed;
|
assign PMAAccessFault = (SelRegions[0]) & AccessRWX | AtomicAccessM & ~AtomicAllowed;
|
||||||
assign PMAInstrAccessFaultF = ExecuteAccessF & PMAAccessFault;
|
assign PMAInstrAccessFaultF = ExecuteAccessF & PMAAccessFault;
|
||||||
assign PMALoadAccessFaultM = ReadAccessM & PMAAccessFault;
|
assign PMALoadAccessFaultM = ReadAccessM & PMAAccessFault;
|
||||||
assign PMAStoreAmoAccessFaultM = WriteAccessM & PMAAccessFault;
|
assign PMAStoreAmoAccessFaultM = WriteAccessM & PMAAccessFault;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
@ -87,4 +87,3 @@ module pmpadrdec import cvw::*; #(parameter cvw_t P) (
|
|||||||
// attempts an 8-byte access to 0x8, the access should fail (see page 60 of privileged specification 20211203). This
|
// 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.
|
// implementation will not detect the failure.
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ module pmpchecker import cvw::*; #(parameter cvw_t P) (
|
|||||||
// keyword, the compiler warns us that it's interpreting the signal as a var,
|
// keyword, the compiler warns us that it's interpreting the signal as a var,
|
||||||
// which we might not intend.
|
// which we might not intend.
|
||||||
input var logic [7:0] PMPCFG_ARRAY_REGW[P.PMP_ENTRIES-1:0],
|
input var logic [7:0] PMPCFG_ARRAY_REGW[P.PMP_ENTRIES-1:0],
|
||||||
input var logic [P.PA_BITS-3:0] PMPADDR_ARRAY_REGW [P.PMP_ENTRIES-1:0],
|
input var logic [P.PA_BITS-3:0] PMPADDR_ARRAY_REGW [P.PMP_ENTRIES-1:0],
|
||||||
input logic ExecuteAccessF, WriteAccessM, ReadAccessM,
|
input logic ExecuteAccessF, WriteAccessM, ReadAccessM,
|
||||||
output logic PMPInstrAccessFaultF,
|
output logic PMPInstrAccessFaultF,
|
||||||
output logic PMPLoadAccessFaultM,
|
output logic PMPLoadAccessFaultM,
|
||||||
@ -48,11 +48,11 @@ module pmpchecker import cvw::*; #(parameter cvw_t P) (
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Bit i is high when the address falls in PMP region i
|
// Bit i is high when the address falls in PMP region i
|
||||||
logic EnforcePMP; // should PMP be checked in this privilege level
|
logic EnforcePMP; // should PMP be checked in this privilege level
|
||||||
logic [P.PMP_ENTRIES-1:0] Match; // physical address matches one of the pmp ranges
|
logic [P.PMP_ENTRIES-1:0] Match; // physical address matches one of the pmp ranges
|
||||||
logic [P.PMP_ENTRIES-1:0] FirstMatch; // onehot encoding for the first pmpaddr to match the current address.
|
logic [P.PMP_ENTRIES-1:0] FirstMatch; // onehot encoding for the first pmpaddr to match the current address.
|
||||||
logic [P.PMP_ENTRIES-1:0] L, X, W, R; // PMP matches and has flag set
|
logic [P.PMP_ENTRIES-1:0] L, X, W, R; // PMP matches and has flag set
|
||||||
logic [P.PMP_ENTRIES-1:0] PAgePMPAdr; // for TOR PMP matching, PhysicalAddress > PMPAdr[i]
|
logic [P.PMP_ENTRIES-1:0] PAgePMPAdr; // for TOR PMP matching, PhysicalAddress > PMPAdr[i]
|
||||||
|
|
||||||
if (P.PMP_ENTRIES > 0) begin: pmp // prevent complaints about array of no elements when PMP_ENTRIES = 0
|
if (P.PMP_ENTRIES > 0) begin: pmp // prevent complaints about array of no elements when PMP_ENTRIES = 0
|
||||||
pmpadrdec #(P) pmpadrdecs[P.PMP_ENTRIES-1:0](
|
pmpadrdec #(P) pmpadrdecs[P.PMP_ENTRIES-1:0](
|
||||||
|
@ -29,66 +29,66 @@
|
|||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
module csr import cvw::*; #(parameter cvw_t P) (
|
module csr import cvw::*; #(parameter cvw_t P) (
|
||||||
input logic clk, reset,
|
input logic clk, reset,
|
||||||
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 [31:0] InstrOrigM, // Original compressed or uncompressed instruction in Memory stage for Illegal Instruction MTVAL
|
input logic [31:0] InstrOrigM, // Original compressed or uncompressed instruction in Memory stage for Illegal Instruction MTVAL
|
||||||
input logic [P.XLEN-1:0] PCM, PC2NextF, // program counter, next PC going to trap/return logic
|
input logic [P.XLEN-1:0] PCM, PC2NextF, // program counter, next PC going to trap/return logic
|
||||||
input logic [P.XLEN-1:0] SrcAM, IEUAdrM, // SrcA and memory address from IEU
|
input logic [P.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 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
|
||||||
input logic [63:0] MTIME_CLINT, // TIME value from CLINT
|
input logic [63:0] MTIME_CLINT, // TIME value from CLINT
|
||||||
input logic InstrValidM, // current instruction is valid
|
input logic InstrValidM, // current instruction is valid
|
||||||
input logic FRegWriteM, // writes to floating point registers change STATUS.FS
|
input logic FRegWriteM, // writes to floating point registers change STATUS.FS
|
||||||
input logic [4:0] SetFflagsM, // Set floating point flag bits in FCSR
|
input logic [4:0] SetFflagsM, // Set floating point flag bits in FCSR
|
||||||
input logic [1:0] NextPrivilegeModeM, // STATUS bits updated based on next privilege mode
|
input logic [1:0] NextPrivilegeModeM, // STATUS bits updated based on next privilege mode
|
||||||
input logic [1:0] PrivilegeModeW, // current privilege mode
|
input logic [1:0] PrivilegeModeW, // current privilege mode
|
||||||
input logic [3:0] CauseM, // Trap cause
|
input logic [3:0] CauseM, // Trap cause
|
||||||
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 StoreStallD,
|
input logic StoreStallD,
|
||||||
input logic ICacheStallF,
|
input logic ICacheStallF,
|
||||||
input logic DCacheStallM,
|
input logic DCacheStallM,
|
||||||
input logic BPDirPredWrongM,
|
input logic BPDirPredWrongM,
|
||||||
input logic BTAWrongM,
|
input logic BTAWrongM,
|
||||||
input logic RASPredPCWrongM,
|
input logic RASPredPCWrongM,
|
||||||
input logic IClassWrongM,
|
input logic IClassWrongM,
|
||||||
input logic BPWrongM, // branch predictor is wrong
|
input logic BPWrongM, // branch predictor is wrong
|
||||||
input logic [3:0] InstrClassM,
|
input logic [3:0] InstrClassM,
|
||||||
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 sfencevmaM,
|
||||||
input logic InvalidateICacheM,
|
input logic InvalidateICacheM,
|
||||||
input logic DivBusyE, // integer divide busy
|
input logic DivBusyE, // integer divide busy
|
||||||
input logic FDivBusyE, // floating point 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,
|
||||||
output logic [15:0] MEDELEG_REGW,
|
output logic [15:0] MEDELEG_REGW,
|
||||||
output logic [P.XLEN-1:0] SATP_REGW,
|
output logic [P.XLEN-1:0] SATP_REGW,
|
||||||
output logic [11:0] MIP_REGW, MIE_REGW, MIDELEG_REGW,
|
output logic [11:0] MIP_REGW, MIE_REGW, MIDELEG_REGW,
|
||||||
output logic STATUS_MIE, STATUS_SIE,
|
output logic STATUS_MIE, STATUS_SIE,
|
||||||
output logic STATUS_MXR, STATUS_SUM, STATUS_MPRV, STATUS_TW,
|
output logic STATUS_MXR, STATUS_SUM, STATUS_MPRV, STATUS_TW,
|
||||||
output logic [1:0] STATUS_FS,
|
output logic [1:0] STATUS_FS,
|
||||||
output var logic [7:0] PMPCFG_ARRAY_REGW[P.PMP_ENTRIES-1:0],
|
output var logic [7:0] PMPCFG_ARRAY_REGW[P.PMP_ENTRIES-1:0],
|
||||||
output var logic [P.PA_BITS-3:0] PMPADDR_ARRAY_REGW[P.PMP_ENTRIES-1:0],
|
output var logic [P.PA_BITS-3:0] PMPADDR_ARRAY_REGW[P.PMP_ENTRIES-1:0],
|
||||||
output logic [2:0] FRM_REGW,
|
output logic [2:0] FRM_REGW,
|
||||||
//
|
//
|
||||||
output logic [P.XLEN-1:0] CSRReadValW, // value read from CSR
|
output logic [P.XLEN-1:0] CSRReadValW, // value read from CSR
|
||||||
output logic [P.XLEN-1:0] UnalignedPCNextF, // Next PC, accounting for traps and returns
|
output logic [P.XLEN-1:0] UnalignedPCNextF, // Next PC, accounting for traps and returns
|
||||||
output logic IllegalCSRAccessM, // Illegal CSR access: CSR doesn't exist or is inaccessible at this privilege level
|
output logic IllegalCSRAccessM, // Illegal CSR access: CSR doesn't exist or is inaccessible at this privilege level
|
||||||
output logic BigEndianM // memory access is big-endian based on privilege mode and STATUS register endian fields
|
output logic BigEndianM // memory access is big-endian based on privilege mode and STATUS register endian fields
|
||||||
);
|
);
|
||||||
|
|
||||||
localparam MIP = 12'h344;
|
localparam MIP = 12'h344;
|
||||||
@ -180,13 +180,13 @@ module csr import cvw::*; #(parameter cvw_t P) (
|
|||||||
else CSRReadVal2M = CSRReadValM;
|
else CSRReadVal2M = CSRReadValM;
|
||||||
|
|
||||||
// Compute AND/OR modification
|
// Compute AND/OR modification
|
||||||
CSRRWM = CSRSrcM;
|
CSRRWM = CSRSrcM;
|
||||||
CSRRSM = CSRReadVal2M | CSRSrcM;
|
CSRRSM = CSRReadVal2M | CSRSrcM;
|
||||||
CSRRCM = CSRReadVal2M & ~CSRSrcM;
|
CSRRCM = CSRReadVal2M & ~CSRSrcM;
|
||||||
case (InstrM[13:12])
|
case (InstrM[13:12])
|
||||||
2'b01: CSRWriteValM = CSRRWM;
|
2'b01: CSRWriteValM = CSRRWM;
|
||||||
2'b10: CSRWriteValM = CSRRSM;
|
2'b10: CSRWriteValM = CSRRSM;
|
||||||
2'b11: CSRWriteValM = CSRRCM;
|
2'b11: CSRWriteValM = CSRRCM;
|
||||||
default: CSRWriteValM = CSRReadValM;
|
default: CSRWriteValM = CSRReadValM;
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
// csrc.sv
|
// csrc.sv
|
||||||
//
|
//
|
||||||
@ -31,57 +29,57 @@
|
|||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
module csrc import cvw::*; #(parameter cvw_t P) (
|
module csrc import cvw::*; #(parameter cvw_t P) (
|
||||||
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, StoreStallD,
|
input logic InstrValidNotFlushedM, LoadStallD, StoreStallD,
|
||||||
input logic CSRMWriteM, CSRWriteM,
|
input logic CSRMWriteM, CSRWriteM,
|
||||||
input logic BPDirPredWrongM,
|
input logic BPDirPredWrongM,
|
||||||
input logic BTAWrongM,
|
input logic BTAWrongM,
|
||||||
input logic RASPredPCWrongM,
|
input logic RASPredPCWrongM,
|
||||||
input logic IClassWrongM,
|
input logic IClassWrongM,
|
||||||
input logic BPWrongM, // branch predictor is wrong
|
input logic BPWrongM, // branch predictor is wrong
|
||||||
input logic [3:0] InstrClassM,
|
input logic [3:0] InstrClassM,
|
||||||
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 ICacheStallF,
|
||||||
input logic DCacheStallM,
|
input logic DCacheStallM,
|
||||||
input logic sfencevmaM,
|
input logic sfencevmaM,
|
||||||
input logic InterruptM,
|
input logic InterruptM,
|
||||||
input logic ExceptionM,
|
input logic ExceptionM,
|
||||||
input logic InvalidateICacheM,
|
input logic InvalidateICacheM,
|
||||||
input logic DivBusyE, // integer divide busy
|
input logic DivBusyE, // integer divide busy
|
||||||
input logic FDivBusyE, // floating point 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 [P.XLEN-1:0] CSRWriteValM,
|
input logic [P.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,
|
||||||
output logic [P.XLEN-1:0] CSRCReadValM,
|
output logic [P.XLEN-1:0] CSRCReadValM,
|
||||||
output logic IllegalCSRCAccessM
|
output logic IllegalCSRCAccessM
|
||||||
);
|
);
|
||||||
|
|
||||||
localparam MHPMCOUNTERBASE = 12'hB00;
|
localparam MHPMCOUNTERBASE = 12'hB00;
|
||||||
localparam MTIME = 12'hB01; // this is a memory-mapped register; no such CSR exists, and access should faul;
|
localparam MTIME = 12'hB01; // this is a memory-mapped register; no such CSR exists, and access should faul;
|
||||||
localparam MHPMCOUNTERHBASE = 12'hB80;
|
localparam MHPMCOUNTERHBASE = 12'hB80;
|
||||||
localparam MTIMEH = 12'hB81; // this is a memory-mapped register; no such CSR exists, and access should fault
|
localparam MTIMEH = 12'hB81; // this is a memory-mapped register; no such CSR exists, and access should fault
|
||||||
localparam MHPMEVENTBASE = 12'h320;
|
localparam MHPMEVENTBASE = 12'h320;
|
||||||
localparam HPMCOUNTERBASE = 12'hC00;
|
localparam HPMCOUNTERBASE = 12'hC00;
|
||||||
localparam HPMCOUNTERHBASE = 12'hC80;
|
localparam HPMCOUNTERHBASE = 12'hC80;
|
||||||
localparam TIME = 12'hC01;
|
localparam TIME = 12'hC01;
|
||||||
localparam TIMEH = 12'hC81;
|
localparam TIMEH = 12'hC81;
|
||||||
|
|
||||||
logic [4:0] CounterNumM;
|
logic [4:0] CounterNumM;
|
||||||
logic [P.XLEN-1:0] HPMCOUNTER_REGW[P.COUNTERS-1:0];
|
logic [P.XLEN-1:0] HPMCOUNTER_REGW[P.COUNTERS-1:0];
|
||||||
logic [P.XLEN-1:0] HPMCOUNTERH_REGW[P.COUNTERS-1:0];
|
logic [P.XLEN-1:0] HPMCOUNTERH_REGW[P.COUNTERS-1:0];
|
||||||
logic LoadStallE, LoadStallM;
|
logic LoadStallE, LoadStallM;
|
||||||
logic StoreStallE, StoreStallM;
|
logic StoreStallE, StoreStallM;
|
||||||
logic [P.COUNTERS-1:0] WriteHPMCOUNTERM;
|
logic [P.COUNTERS-1:0] WriteHPMCOUNTERM;
|
||||||
logic [P.COUNTERS-1:0] CounterEvent;
|
logic [P.COUNTERS-1:0] CounterEvent;
|
||||||
logic [63:0] HPMCOUNTERPlusM[P.COUNTERS-1:0];
|
logic [63:0] HPMCOUNTERPlusM[P.COUNTERS-1:0];
|
||||||
logic [P.XLEN-1:0] NextHPMCOUNTERM[P.COUNTERS-1:0];
|
logic [P.XLEN-1:0] NextHPMCOUNTERM[P.COUNTERS-1:0];
|
||||||
genvar i;
|
genvar i;
|
||||||
|
|
||||||
// Interface signals
|
// Interface signals
|
||||||
@ -89,34 +87,34 @@ module csrc import cvw::*; #(parameter cvw_t P) (
|
|||||||
flopenrc #(2) LoadStallMReg(.clk, .reset, .clear(FlushM), .en(~StallM), .d({StoreStallE, LoadStallE}), .q({StoreStallM, 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
|
||||||
assign CounterEvent[1] = 1'b0; // Counter 1 doesn't exist
|
assign CounterEvent[1] = 1'b0; // Counter 1 doesn't exist
|
||||||
assign CounterEvent[2] = InstrValidNotFlushedM; // MINSTRET instructions retired
|
assign CounterEvent[2] = InstrValidNotFlushedM; // MINSTRET instructions retired
|
||||||
if (P.ZIHPM_SUPPORTED) begin: cevent // User-defined counters
|
if (P.ZIHPM_SUPPORTED) begin: cevent // User-defined counters
|
||||||
assign CounterEvent[3] = InstrClassM[0] & InstrValidNotFlushedM; // branch instruction
|
assign CounterEvent[3] = InstrClassM[0] & InstrValidNotFlushedM; // branch instruction
|
||||||
assign CounterEvent[4] = InstrClassM[1] & ~InstrClassM[2] & InstrValidNotFlushedM; // jump and not return instructions
|
assign CounterEvent[4] = InstrClassM[1] & ~InstrClassM[2] & InstrValidNotFlushedM; // jump and not return instructions
|
||||||
assign CounterEvent[5] = InstrClassM[2] & InstrValidNotFlushedM; // return instructions
|
assign CounterEvent[5] = InstrClassM[2] & InstrValidNotFlushedM; // return instructions
|
||||||
assign CounterEvent[6] = BPWrongM & InstrValidNotFlushedM; // branch predictor wrong
|
assign CounterEvent[6] = BPWrongM & InstrValidNotFlushedM; // branch predictor wrong
|
||||||
assign CounterEvent[7] = BPDirPredWrongM & InstrValidNotFlushedM; // Branch predictor wrong direction
|
assign CounterEvent[7] = BPDirPredWrongM & InstrValidNotFlushedM; // Branch predictor wrong direction
|
||||||
assign CounterEvent[8] = BTAWrongM & InstrValidNotFlushedM; // branch predictor wrong target
|
assign CounterEvent[8] = BTAWrongM & InstrValidNotFlushedM; // branch predictor wrong target
|
||||||
assign CounterEvent[9] = RASPredPCWrongM & InstrValidNotFlushedM; // return address stack wrong address
|
assign CounterEvent[9] = RASPredPCWrongM & InstrValidNotFlushedM; // return address stack wrong address
|
||||||
assign CounterEvent[10] = IClassWrongM & InstrValidNotFlushedM; // instruction class predictor wrong
|
assign CounterEvent[10] = IClassWrongM & InstrValidNotFlushedM; // instruction class predictor wrong
|
||||||
assign CounterEvent[11] = LoadStallM; // Load Stalls. don't want to suppress on flush as this only happens if flushed.
|
assign CounterEvent[11] = LoadStallM; // Load Stalls. don't want to suppress on flush as this only happens if flushed.
|
||||||
assign CounterEvent[12] = StoreStallM; // Store Stall
|
assign CounterEvent[12] = StoreStallM; // Store Stall
|
||||||
assign CounterEvent[13] = DCacheAccess & InstrValidNotFlushedM; // data cache access
|
assign CounterEvent[13] = DCacheAccess & InstrValidNotFlushedM; // data cache access
|
||||||
assign CounterEvent[14] = DCacheMiss; // data 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] = DCacheStallM; // d cache miss cycles
|
assign CounterEvent[15] = DCacheStallM; // d cache miss cycles
|
||||||
assign CounterEvent[16] = ICacheAccess & InstrValidNotFlushedM; // instruction cache access
|
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[17] = ICacheMiss; // instruction cache miss. Miss asserted 1 cycle at start of cache miss
|
||||||
assign CounterEvent[18] = ICacheStallF; // i cache miss cycles
|
assign CounterEvent[18] = ICacheStallF; // i cache miss cycles
|
||||||
assign CounterEvent[19] = CSRWriteM & InstrValidNotFlushedM; // CSR writes
|
assign CounterEvent[19] = CSRWriteM & InstrValidNotFlushedM; // CSR writes
|
||||||
assign CounterEvent[20] = InvalidateICacheM & InstrValidNotFlushedM; // fence.i
|
assign CounterEvent[20] = InvalidateICacheM & InstrValidNotFlushedM; // fence.i
|
||||||
assign CounterEvent[21] = sfencevmaM & InstrValidNotFlushedM; // sfence.vma
|
assign CounterEvent[21] = sfencevmaM & InstrValidNotFlushedM; // sfence.vma
|
||||||
assign CounterEvent[22] = InterruptM; // interrupt, InstrValidNotFlushedM will be low
|
assign CounterEvent[22] = InterruptM; // interrupt, InstrValidNotFlushedM will be low
|
||||||
assign CounterEvent[23] = ExceptionM; // exceptions, InstrValidNotFlushedM will be low
|
assign CounterEvent[23] = ExceptionM; // exceptions, InstrValidNotFlushedM will be low
|
||||||
// coverage off
|
// coverage off
|
||||||
// DivBusyE will never be assert high since this configuration uses the FPU to do integer division
|
// DivBusyE will never be assert high since this configuration uses the FPU to do integer division
|
||||||
assign CounterEvent[24] = DivBusyE | FDivBusyE; // division cycles *** RT: might need to be delay until the next cycle
|
assign CounterEvent[24] = DivBusyE | FDivBusyE; // division cycles *** RT: might need to be delay until the next cycle
|
||||||
// coverage on
|
// coverage on
|
||||||
assign CounterEvent[P.COUNTERS-1:25] = 0; // eventually give these sources, including FP instructions, I$/D$ misses, branches and mispredictions
|
assign CounterEvent[P.COUNTERS-1:25] = 0; // eventually give these sources, including FP instructions, I$/D$ misses, branches and mispredictions
|
||||||
end else begin: cevent
|
end else begin: cevent
|
||||||
@ -158,7 +156,7 @@ module csrc import cvw::*; #(parameter cvw_t P) (
|
|||||||
/* verilator lint_on WIDTH */
|
/* verilator lint_on WIDTH */
|
||||||
else if (CSRAdrM >= MHPMCOUNTERBASE & CSRAdrM < MHPMCOUNTERBASE+P.COUNTERS & CSRAdrM != MTIME)
|
else if (CSRAdrM >= MHPMCOUNTERBASE & CSRAdrM < MHPMCOUNTERBASE+P.COUNTERS & CSRAdrM != MTIME)
|
||||||
CSRCReadValM = HPMCOUNTER_REGW[CounterNumM];
|
CSRCReadValM = HPMCOUNTER_REGW[CounterNumM];
|
||||||
else if (CSRAdrM >= HPMCOUNTERBASE & CSRAdrM < HPMCOUNTERBASE+P.COUNTERS)
|
else if (CSRAdrM >= HPMCOUNTERBASE & CSRAdrM < HPMCOUNTERBASE+P.COUNTERS)
|
||||||
CSRCReadValM = HPMCOUNTER_REGW[CounterNumM];
|
CSRCReadValM = HPMCOUNTER_REGW[CounterNumM];
|
||||||
else begin
|
else begin
|
||||||
CSRCReadValM = 0;
|
CSRCReadValM = 0;
|
||||||
@ -189,4 +187,4 @@ module csrc import cvw::*; #(parameter cvw_t P) (
|
|||||||
end
|
end
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
// mounteren should only exist if u-mode exists
|
// mounteren should only exist if u-mode exists
|
@ -82,7 +82,6 @@ module csri import cvw::*; #(parameter cvw_t P) (
|
|||||||
else if (WriteMIEM) MIE_REGW <= (CSRWriteValM[11:0] & MIE_WRITE_MASK); // MIE controls M and S fields
|
else if (WriteMIEM) MIE_REGW <= (CSRWriteValM[11:0] & MIE_WRITE_MASK); // MIE controls M and S fields
|
||||||
else if (WriteSIEM) MIE_REGW <= (CSRWriteValM[11:0] & 12'h222 & MIDELEG_REGW) | (MIE_REGW & 12'h888); // only S fields
|
else if (WriteSIEM) MIE_REGW <= (CSRWriteValM[11:0] & 12'h222 & MIDELEG_REGW) | (MIE_REGW & 12'h888); // only S fields
|
||||||
|
|
||||||
|
|
||||||
assign MIP_REGW = {MExtInt, 1'b0, SExtInt|MIP_REGW_writeable[9], 1'b0,
|
assign MIP_REGW = {MExtInt, 1'b0, SExtInt|MIP_REGW_writeable[9], 1'b0,
|
||||||
MTimerInt, 1'b0, STIP, 1'b0,
|
MTimerInt, 1'b0, STIP, 1'b0,
|
||||||
MSwInt, 1'b0, MIP_REGW_writeable[1], 1'b0};
|
MSwInt, 1'b0, MIP_REGW_writeable[1], 1'b0};
|
||||||
|
@ -62,44 +62,44 @@ module csrm import cvw::*; #(parameter cvw_t P) (
|
|||||||
logic WriteMENVCFGM;
|
logic WriteMENVCFGM;
|
||||||
|
|
||||||
// Machine CSRs
|
// Machine CSRs
|
||||||
localparam MVENDORID = 12'hF11;
|
localparam MVENDORID = 12'hF11;
|
||||||
localparam MARCHID = 12'hF12;
|
localparam MARCHID = 12'hF12;
|
||||||
localparam MIMPID = 12'hF13;
|
localparam MIMPID = 12'hF13;
|
||||||
localparam MHARTID = 12'hF14;
|
localparam MHARTID = 12'hF14;
|
||||||
localparam MCONFIGPTR = 12'hF15;
|
localparam MCONFIGPTR = 12'hF15;
|
||||||
localparam MSTATUS = 12'h300;
|
localparam MSTATUS = 12'h300;
|
||||||
localparam MISA_ADR = 12'h301;
|
localparam MISA_ADR = 12'h301;
|
||||||
localparam MEDELEG = 12'h302;
|
localparam MEDELEG = 12'h302;
|
||||||
localparam MIDELEG = 12'h303;
|
localparam MIDELEG = 12'h303;
|
||||||
localparam MIE = 12'h304;
|
localparam MIE = 12'h304;
|
||||||
localparam MTVEC = 12'h305;
|
localparam MTVEC = 12'h305;
|
||||||
localparam MCOUNTEREN = 12'h306;
|
localparam MCOUNTEREN = 12'h306;
|
||||||
localparam MENVCFG = 12'h30A;
|
localparam MENVCFG = 12'h30A;
|
||||||
localparam MSTATUSH = 12'h310;
|
localparam MSTATUSH = 12'h310;
|
||||||
localparam MENVCFGH = 12'h31A;
|
localparam MENVCFGH = 12'h31A;
|
||||||
localparam MCOUNTINHIBIT = 12'h320;
|
localparam MCOUNTINHIBIT = 12'h320;
|
||||||
localparam MSCRATCH = 12'h340;
|
localparam MSCRATCH = 12'h340;
|
||||||
localparam MEPC = 12'h341;
|
localparam MEPC = 12'h341;
|
||||||
localparam MCAUSE = 12'h342;
|
localparam MCAUSE = 12'h342;
|
||||||
localparam MTVAL = 12'h343;
|
localparam MTVAL = 12'h343;
|
||||||
localparam MIP = 12'h344;
|
localparam MIP = 12'h344;
|
||||||
localparam MTINST = 12'h34A;
|
localparam MTINST = 12'h34A;
|
||||||
localparam PMPCFG0 = 12'h3A0;
|
localparam PMPCFG0 = 12'h3A0;
|
||||||
// .. up to 15 more at consecutive addresses
|
// .. up to 15 more at consecutive addresses
|
||||||
localparam PMPADDR0 = 12'h3B0;
|
localparam PMPADDR0 = 12'h3B0;
|
||||||
// ... up to 63 more at consecutive addresses
|
// ... up to 63 more at consecutive addresses
|
||||||
localparam TSELECT = 12'h7A0;
|
localparam TSELECT = 12'h7A0;
|
||||||
localparam TDATA1 = 12'h7A1;
|
localparam TDATA1 = 12'h7A1;
|
||||||
localparam TDATA2 = 12'h7A2;
|
localparam TDATA2 = 12'h7A2;
|
||||||
localparam TDATA3 = 12'h7A3;
|
localparam TDATA3 = 12'h7A3;
|
||||||
localparam DCSR = 12'h7B0;
|
localparam DCSR = 12'h7B0;
|
||||||
localparam DPC = 12'h7B1;
|
localparam DPC = 12'h7B1;
|
||||||
localparam DSCRATCH0 = 12'h7B2;
|
localparam DSCRATCH0 = 12'h7B2;
|
||||||
localparam DSCRATCH1 = 12'h7B3;
|
localparam DSCRATCH1 = 12'h7B3;
|
||||||
// Constants
|
// Constants
|
||||||
localparam ZERO = {(P.XLEN){1'b0}};
|
localparam ZERO = {(P.XLEN){1'b0}};
|
||||||
localparam MEDELEG_MASK = 16'hB3FF;
|
localparam MEDELEG_MASK = 16'hB3FF;
|
||||||
localparam MIDELEG_MASK = 12'h222; // we choose to not make machine interrupts delegable
|
localparam MIDELEG_MASK = 12'h222; // we choose to not make machine interrupts delegable
|
||||||
|
|
||||||
// There are PMP_ENTRIES = 0, 16, or 64 PMPADDR registers, each of which has its own flop
|
// There are PMP_ENTRIES = 0, 16, or 64 PMPADDR registers, each of which has its own flop
|
||||||
genvar i;
|
genvar i;
|
||||||
@ -137,17 +137,17 @@ module csrm import cvw::*; #(parameter cvw_t P) (
|
|||||||
assign MHARTID_REGW = 0;
|
assign MHARTID_REGW = 0;
|
||||||
|
|
||||||
// Write machine Mode CSRs
|
// Write machine Mode CSRs
|
||||||
assign WriteMSTATUSM = CSRMWriteM & (CSRAdrM == MSTATUS);
|
assign WriteMSTATUSM = CSRMWriteM & (CSRAdrM == MSTATUS);
|
||||||
assign WriteMSTATUSHM = CSRMWriteM & (CSRAdrM == MSTATUSH) & (P.XLEN==32);
|
assign WriteMSTATUSHM = CSRMWriteM & (CSRAdrM == MSTATUSH) & (P.XLEN==32);
|
||||||
assign WriteMTVECM = CSRMWriteM & (CSRAdrM == MTVEC);
|
assign WriteMTVECM = CSRMWriteM & (CSRAdrM == MTVEC);
|
||||||
assign WriteMEDELEGM = CSRMWriteM & (CSRAdrM == MEDELEG);
|
assign WriteMEDELEGM = CSRMWriteM & (CSRAdrM == MEDELEG);
|
||||||
assign WriteMIDELEGM = CSRMWriteM & (CSRAdrM == MIDELEG);
|
assign WriteMIDELEGM = CSRMWriteM & (CSRAdrM == MIDELEG);
|
||||||
assign WriteMSCRATCHM = CSRMWriteM & (CSRAdrM == MSCRATCH);
|
assign WriteMSCRATCHM = CSRMWriteM & (CSRAdrM == MSCRATCH);
|
||||||
assign WriteMEPCM = MTrapM | (CSRMWriteM & (CSRAdrM == MEPC));
|
assign WriteMEPCM = MTrapM | (CSRMWriteM & (CSRAdrM == MEPC));
|
||||||
assign WriteMCAUSEM = MTrapM | (CSRMWriteM & (CSRAdrM == MCAUSE));
|
assign WriteMCAUSEM = MTrapM | (CSRMWriteM & (CSRAdrM == MCAUSE));
|
||||||
assign WriteMTVALM = MTrapM | (CSRMWriteM & (CSRAdrM == MTVAL));
|
assign WriteMTVALM = MTrapM | (CSRMWriteM & (CSRAdrM == MTVAL));
|
||||||
assign WriteMCOUNTERENM = CSRMWriteM & (CSRAdrM == MCOUNTEREN);
|
assign WriteMCOUNTERENM = CSRMWriteM & (CSRAdrM == MCOUNTEREN);
|
||||||
assign WriteMENVCFGM = CSRMWriteM & (CSRAdrM == MENVCFG);
|
assign WriteMENVCFGM = CSRMWriteM & (CSRAdrM == MENVCFG);
|
||||||
assign WriteMCOUNTINHIBITM = CSRMWriteM & (CSRAdrM == MCOUNTINHIBIT);
|
assign WriteMCOUNTINHIBITM = CSRMWriteM & (CSRAdrM == MCOUNTINHIBIT);
|
||||||
|
|
||||||
assign IllegalCSRMWriteReadonlyM = UngatedCSRMWriteM & (CSRAdrM == MVENDORID | CSRAdrM == MARCHID | CSRAdrM == MIMPID | CSRAdrM == MHARTID);
|
assign IllegalCSRMWriteReadonlyM = UngatedCSRMWriteM & (CSRAdrM == MVENDORID | CSRAdrM == MARCHID | CSRAdrM == MIMPID | CSRAdrM == MHARTID);
|
||||||
@ -197,10 +197,10 @@ module csrm import cvw::*; #(parameter cvw_t P) (
|
|||||||
assign MENVCFG_STCE = MENVCFG_REGW[63];
|
assign MENVCFG_STCE = MENVCFG_REGW[63];
|
||||||
// Uncomment these other fields when they are defined
|
// Uncomment these other fields when they are defined
|
||||||
// assign MENVCFG_PBMTE = MENVCFG_REGW[62];
|
// assign MENVCFG_PBMTE = MENVCFG_REGW[62];
|
||||||
// assign MENVCFG_CBZE = MENVCFG_REGW[7];
|
// assign MENVCFG_CBZE = MENVCFG_REGW[7];
|
||||||
// assign MENVCFG_CBCFE = MENVCFG_REGW[6];
|
// assign MENVCFG_CBCFE = MENVCFG_REGW[6];
|
||||||
// assign MENVCFG_CBIE = MENVCFG_REGW[5:4];
|
// assign MENVCFG_CBIE = MENVCFG_REGW[5:4];
|
||||||
// assign MENVCFG_FIOM = MENVCFG_REGW[0];
|
// assign MENVCFG_FIOM = MENVCFG_REGW[0];
|
||||||
|
|
||||||
// Read machine mode CSRs
|
// Read machine mode CSRs
|
||||||
// verilator lint_off WIDTH
|
// verilator lint_off WIDTH
|
||||||
@ -222,28 +222,28 @@ module csrm import cvw::*; #(parameter cvw_t P) (
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
else case (CSRAdrM)
|
else case (CSRAdrM)
|
||||||
MISA_ADR: CSRMReadValM = MISA_REGW;
|
MISA_ADR: CSRMReadValM = MISA_REGW;
|
||||||
MVENDORID: CSRMReadValM = 0;
|
MVENDORID: CSRMReadValM = 0;
|
||||||
MARCHID: CSRMReadValM = 0;
|
MARCHID: CSRMReadValM = 0;
|
||||||
MIMPID: CSRMReadValM = {{P.XLEN-12{1'b0}}, 12'h100}; // pipelined implementation
|
MIMPID: CSRMReadValM = {{P.XLEN-12{1'b0}}, 12'h100}; // pipelined implementation
|
||||||
MHARTID: CSRMReadValM = MHARTID_REGW; // hardwired to 0
|
MHARTID: CSRMReadValM = MHARTID_REGW; // hardwired to 0
|
||||||
MCONFIGPTR: CSRMReadValM = 0; // hardwired to 0
|
MCONFIGPTR: CSRMReadValM = 0; // hardwired to 0
|
||||||
MSTATUS: CSRMReadValM = MSTATUS_REGW;
|
MSTATUS: CSRMReadValM = MSTATUS_REGW;
|
||||||
MSTATUSH: CSRMReadValM = MSTATUSH_REGW;
|
MSTATUSH: CSRMReadValM = MSTATUSH_REGW;
|
||||||
MTVEC: CSRMReadValM = MTVEC_REGW;
|
MTVEC: CSRMReadValM = MTVEC_REGW;
|
||||||
MEDELEG: CSRMReadValM = {{(P.XLEN-16){1'b0}}, MEDELEG_REGW};
|
MEDELEG: CSRMReadValM = {{(P.XLEN-16){1'b0}}, MEDELEG_REGW};
|
||||||
MIDELEG: CSRMReadValM = {{(P.XLEN-12){1'b0}}, MIDELEG_REGW};
|
MIDELEG: CSRMReadValM = {{(P.XLEN-12){1'b0}}, MIDELEG_REGW};
|
||||||
MIP: CSRMReadValM = {{(P.XLEN-12){1'b0}}, MIP_REGW};
|
MIP: CSRMReadValM = {{(P.XLEN-12){1'b0}}, MIP_REGW};
|
||||||
MIE: CSRMReadValM = {{(P.XLEN-12){1'b0}}, MIE_REGW};
|
MIE: CSRMReadValM = {{(P.XLEN-12){1'b0}}, MIE_REGW};
|
||||||
MSCRATCH: CSRMReadValM = MSCRATCH_REGW;
|
MSCRATCH: CSRMReadValM = MSCRATCH_REGW;
|
||||||
MEPC: CSRMReadValM = MEPC_REGW;
|
MEPC: CSRMReadValM = MEPC_REGW;
|
||||||
MCAUSE: CSRMReadValM = MCAUSE_REGW;
|
MCAUSE: CSRMReadValM = MCAUSE_REGW;
|
||||||
MTVAL: CSRMReadValM = MTVAL_REGW;
|
MTVAL: CSRMReadValM = MTVAL_REGW;
|
||||||
MTINST: CSRMReadValM = 0; // implemented as trivial zero
|
MTINST: CSRMReadValM = 0; // implemented as trivial zero
|
||||||
MCOUNTEREN:CSRMReadValM = {{(P.XLEN-32){1'b0}}, MCOUNTEREN_REGW};
|
MCOUNTEREN: CSRMReadValM = {{(P.XLEN-32){1'b0}}, MCOUNTEREN_REGW};
|
||||||
MENVCFG: CSRMReadValM = MENVCFG_REGW[P.XLEN-1:0];
|
MENVCFG: CSRMReadValM = MENVCFG_REGW[P.XLEN-1:0];
|
||||||
MENVCFGH: CSRMReadValM = MENVCFGH_REGW;
|
MENVCFGH: CSRMReadValM = MENVCFGH_REGW;
|
||||||
MCOUNTINHIBIT:CSRMReadValM = {{(P.XLEN-32){1'b0}}, MCOUNTINHIBIT_REGW};
|
MCOUNTINHIBIT: CSRMReadValM = {{(P.XLEN-32){1'b0}}, MCOUNTINHIBIT_REGW};
|
||||||
|
|
||||||
default: begin
|
default: begin
|
||||||
CSRMReadValM = 0;
|
CSRMReadValM = 0;
|
||||||
@ -252,4 +252,4 @@ module csrm import cvw::*; #(parameter cvw_t P) (
|
|||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
// verilator lint_on WIDTH
|
// verilator lint_on WIDTH
|
||||||
endmodule
|
endmodule
|
@ -51,21 +51,21 @@ module csrs import cvw::*; #(parameter cvw_t P) (
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Supervisor CSRs
|
// Supervisor CSRs
|
||||||
localparam SSTATUS = 12'h100;
|
localparam SSTATUS = 12'h100;
|
||||||
localparam SIE = 12'h104;
|
localparam SIE = 12'h104;
|
||||||
localparam STVEC = 12'h105;
|
localparam STVEC = 12'h105;
|
||||||
localparam SCOUNTEREN = 12'h106;
|
localparam SCOUNTEREN = 12'h106;
|
||||||
localparam SENVCFG = 12'h10A;
|
localparam SENVCFG = 12'h10A;
|
||||||
localparam SSCRATCH = 12'h140;
|
localparam SSCRATCH = 12'h140;
|
||||||
localparam SEPC = 12'h141;
|
localparam SEPC = 12'h141;
|
||||||
localparam SCAUSE = 12'h142;
|
localparam SCAUSE = 12'h142;
|
||||||
localparam STVAL = 12'h143;
|
localparam STVAL = 12'h143;
|
||||||
localparam SIP= 12'h144;
|
localparam SIP = 12'h144;
|
||||||
localparam STIMECMP = 12'h14D;
|
localparam STIMECMP = 12'h14D;
|
||||||
localparam STIMECMPH = 12'h15D;
|
localparam STIMECMPH = 12'h15D;
|
||||||
localparam SATP = 12'h180;
|
localparam SATP = 12'h180;
|
||||||
// Constants
|
// Constants
|
||||||
localparam ZERO = {(P.XLEN){1'b0}};
|
localparam ZERO = {(P.XLEN){1'b0}};
|
||||||
localparam SEDELEG_MASK = ~(ZERO | {{P.XLEN-3{1'b0}}, 3'b111} << 9);
|
localparam SEDELEG_MASK = ~(ZERO | {{P.XLEN-3{1'b0}}, 3'b111} << 9);
|
||||||
|
|
||||||
logic WriteSTVECM;
|
logic WriteSTVECM;
|
||||||
@ -81,17 +81,17 @@ module csrs import cvw::*; #(parameter cvw_t P) (
|
|||||||
logic [63:0] STIMECMP_REGW;
|
logic [63:0] STIMECMP_REGW;
|
||||||
|
|
||||||
// write enables
|
// write enables
|
||||||
assign WriteSSTATUSM = CSRSWriteM & (CSRAdrM == SSTATUS);
|
assign WriteSSTATUSM = CSRSWriteM & (CSRAdrM == SSTATUS);
|
||||||
assign WriteSTVECM = CSRSWriteM & (CSRAdrM == STVEC);
|
assign WriteSTVECM = CSRSWriteM & (CSRAdrM == STVEC);
|
||||||
assign WriteSSCRATCHM = CSRSWriteM & (CSRAdrM == SSCRATCH);
|
assign WriteSSCRATCHM = CSRSWriteM & (CSRAdrM == SSCRATCH);
|
||||||
assign WriteSEPCM = STrapM | (CSRSWriteM & (CSRAdrM == SEPC));
|
assign WriteSEPCM = STrapM | (CSRSWriteM & (CSRAdrM == SEPC));
|
||||||
assign WriteSCAUSEM = STrapM | (CSRSWriteM & (CSRAdrM == SCAUSE));
|
assign WriteSCAUSEM = STrapM | (CSRSWriteM & (CSRAdrM == SCAUSE));
|
||||||
assign WriteSTVALM = STrapM | (CSRSWriteM & (CSRAdrM == STVAL));
|
assign WriteSTVALM = STrapM | (CSRSWriteM & (CSRAdrM == STVAL));
|
||||||
assign WriteSATPM = CSRSWriteM & (CSRAdrM == SATP) & (PrivilegeModeW == P.M_MODE | ~STATUS_TVM);
|
assign WriteSATPM = CSRSWriteM & (CSRAdrM == SATP) & (PrivilegeModeW == P.M_MODE | ~STATUS_TVM);
|
||||||
assign WriteSCOUNTERENM = CSRSWriteM & (CSRAdrM == SCOUNTEREN);
|
assign WriteSCOUNTERENM = CSRSWriteM & (CSRAdrM == SCOUNTEREN);
|
||||||
assign WriteSENVCFGM = CSRSWriteM & (CSRAdrM == SENVCFG);
|
assign WriteSENVCFGM = CSRSWriteM & (CSRAdrM == SENVCFG);
|
||||||
assign WriteSTIMECMPM = CSRSWriteM & (CSRAdrM == STIMECMP) & (PrivilegeModeW == P.M_MODE | (MCOUNTEREN_TM & MENVCFG_STCE));
|
assign WriteSTIMECMPM = CSRSWriteM & (CSRAdrM == STIMECMP) & (PrivilegeModeW == P.M_MODE | (MCOUNTEREN_TM & MENVCFG_STCE));
|
||||||
assign WriteSTIMECMPHM = CSRSWriteM & (CSRAdrM == STIMECMPH) & (PrivilegeModeW == P.M_MODE | (MCOUNTEREN_TM & MENVCFG_STCE)) & (P.XLEN == 32);
|
assign WriteSTIMECMPHM = CSRSWriteM & (CSRAdrM == STIMECMPH) & (PrivilegeModeW == P.M_MODE | (MCOUNTEREN_TM & MENVCFG_STCE)) & (P.XLEN == 32);
|
||||||
|
|
||||||
// CSRs
|
// CSRs
|
||||||
flopenr #(P.XLEN) STVECreg(clk, reset, WriteSTVECM, {CSRWriteValM[P.XLEN-1:2], 1'b0, CSRWriteValM[0]}, STVEC_REGW);
|
flopenr #(P.XLEN) STVECreg(clk, reset, WriteSTVECM, {CSRWriteValM[P.XLEN-1:2], 1'b0, CSRWriteValM[0]}, STVEC_REGW);
|
||||||
@ -116,7 +116,7 @@ module csrs import cvw::*; #(parameter cvw_t P) (
|
|||||||
// 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
|
||||||
if (P.SSTC_SUPPORTED)
|
if (P.SSTC_SUPPORTED)
|
||||||
assign STimerInt = ({1'b0, MTIME_CLINT} >= {1'b0, STIMECMP_REGW}); // unsigned comparison
|
assign STimerInt = ({1'b0, MTIME_CLINT} >= {1'b0, STIMECMP_REGW}); // unsigned comparison
|
||||||
else
|
else
|
||||||
assign STimerInt = 0;
|
assign STimerInt = 0;
|
||||||
|
|
||||||
@ -133,10 +133,10 @@ module csrs import cvw::*; #(parameter cvw_t P) (
|
|||||||
// Extract bit fields
|
// Extract bit fields
|
||||||
// Uncomment these other fields when they are defined
|
// Uncomment these other fields when they are defined
|
||||||
// assign SENVCFG_PBMTE = SENVCFG_REGW[62];
|
// assign SENVCFG_PBMTE = SENVCFG_REGW[62];
|
||||||
// assign SENVCFG_CBZE = SENVCFG_REGW[7];
|
// assign SENVCFG_CBZE = SENVCFG_REGW[7];
|
||||||
// assign SENVCFG_CBCFE = SENVCFG_REGW[6];
|
// assign SENVCFG_CBCFE = SENVCFG_REGW[6];
|
||||||
// assign SENVCFG_CBIE = SENVCFG_REGW[5:4];
|
// assign SENVCFG_CBIE = SENVCFG_REGW[5:4];
|
||||||
// assign SENVCFG_FIOM = SENVCFG_REGW[0];
|
// assign SENVCFG_FIOM = SENVCFG_REGW[0];
|
||||||
|
|
||||||
// CSR Reads
|
// CSR Reads
|
||||||
always_comb begin:csrr
|
always_comb begin:csrr
|
||||||
@ -175,4 +175,4 @@ module csrs import cvw::*; #(parameter cvw_t P) (
|
|||||||
end
|
end
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
endmodule
|
endmodule
|
@ -28,22 +28,22 @@
|
|||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
module csrsr import cvw::*; #(parameter cvw_t P) (
|
module csrsr import cvw::*; #(parameter cvw_t P) (
|
||||||
input logic clk, reset, StallW,
|
input logic clk, reset, StallW,
|
||||||
input logic WriteMSTATUSM, WriteMSTATUSHM, WriteSSTATUSM,
|
input logic WriteMSTATUSM, WriteMSTATUSHM, WriteSSTATUSM,
|
||||||
input logic TrapM, FRegWriteM,
|
input logic TrapM, FRegWriteM,
|
||||||
input logic [1:0] NextPrivilegeModeM, PrivilegeModeW,
|
input logic [1:0] NextPrivilegeModeM, PrivilegeModeW,
|
||||||
input logic mretM, sretM,
|
input logic mretM, sretM,
|
||||||
input logic WriteFRMM, WriteFFLAGSM,
|
input logic WriteFRMM, WriteFFLAGSM,
|
||||||
input logic [P.XLEN-1:0] CSRWriteValM,
|
input logic [P.XLEN-1:0] CSRWriteValM,
|
||||||
input logic SelHPTW,
|
input logic SelHPTW,
|
||||||
output logic [P.XLEN-1:0] MSTATUS_REGW, SSTATUS_REGW, MSTATUSH_REGW,
|
output logic [P.XLEN-1:0] MSTATUS_REGW, SSTATUS_REGW, MSTATUSH_REGW,
|
||||||
output logic [1:0] STATUS_MPP,
|
output logic [1:0] STATUS_MPP,
|
||||||
output logic STATUS_SPP, STATUS_TSR, STATUS_TW,
|
output logic STATUS_SPP, STATUS_TSR, STATUS_TW,
|
||||||
output logic STATUS_MIE, STATUS_SIE,
|
output logic STATUS_MIE, STATUS_SIE,
|
||||||
output logic STATUS_MXR, STATUS_SUM,
|
output logic STATUS_MXR, STATUS_SUM,
|
||||||
output logic STATUS_MPRV, STATUS_TVM,
|
output logic STATUS_MPRV, STATUS_TVM,
|
||||||
output logic [1:0] STATUS_FS,
|
output logic [1:0] STATUS_FS,
|
||||||
output logic BigEndianM
|
output logic BigEndianM
|
||||||
);
|
);
|
||||||
|
|
||||||
logic STATUS_SD, STATUS_TW_INT, STATUS_TSR_INT, STATUS_TVM_INT, STATUS_MXR_INT, STATUS_SUM_INT, STATUS_MPRV_INT;
|
logic STATUS_SD, STATUS_TW_INT, STATUS_TSR_INT, STATUS_TVM_INT, STATUS_MXR_INT, STATUS_SUM_INT, STATUS_MPRV_INT;
|
||||||
@ -56,27 +56,27 @@ module csrsr import cvw::*; #(parameter cvw_t P) (
|
|||||||
// Lower privilege status registers are a subset of the full status register
|
// Lower privilege status registers are a subset of the full status register
|
||||||
// *** consider adding MBE, SBE, UBE fields, parameterized to be fixed or adjustable
|
// *** consider adding MBE, SBE, UBE fields, parameterized to be fixed or adjustable
|
||||||
if (P.XLEN==64) begin: csrsr64 // RV64
|
if (P.XLEN==64) begin: csrsr64 // RV64
|
||||||
assign MSTATUS_REGW = {STATUS_SD, 25'b0, STATUS_MBE, STATUS_SBE, STATUS_SXL, STATUS_UXL, 9'b0,
|
assign MSTATUS_REGW = {STATUS_SD, 25'b0, STATUS_MBE, STATUS_SBE, STATUS_SXL, STATUS_UXL, 9'b0,
|
||||||
STATUS_TSR, STATUS_TW, STATUS_TVM, STATUS_MXR, STATUS_SUM, STATUS_MPRV,
|
STATUS_TSR, STATUS_TW, STATUS_TVM, STATUS_MXR, STATUS_SUM, STATUS_MPRV,
|
||||||
STATUS_XS, STATUS_FS, STATUS_MPP, 2'b0,
|
STATUS_XS, STATUS_FS, STATUS_MPP, 2'b0,
|
||||||
STATUS_SPP, STATUS_MPIE, STATUS_UBE, STATUS_SPIE, 1'b0,
|
STATUS_SPP, STATUS_MPIE, STATUS_UBE, STATUS_SPIE, 1'b0,
|
||||||
STATUS_MIE, 1'b0, STATUS_SIE, 1'b0};
|
STATUS_MIE, 1'b0, STATUS_SIE, 1'b0};
|
||||||
assign SSTATUS_REGW = {STATUS_SD, /*27'b0, */ 29'b0, /*STATUS_SXL, */ {P.QEMU ? 2'b0 : STATUS_UXL}, /*9'b0, */ 12'b0,
|
assign SSTATUS_REGW = {STATUS_SD, /*27'b0, */ 29'b0, /*STATUS_SXL, */ {P.QEMU ? 2'b0 : STATUS_UXL}, /*9'b0, */ 12'b0,
|
||||||
/*STATUS_TSR, STATUS_TW, STATUS_TVM, */STATUS_MXR, STATUS_SUM, /* STATUS_MPRV, */ 1'b0,
|
/*STATUS_TSR, STATUS_TW, STATUS_TVM, */STATUS_MXR, STATUS_SUM, /* STATUS_MPRV, */ 1'b0,
|
||||||
STATUS_XS, STATUS_FS, /*STATUS_MPP, 2'b0*/ 4'b0,
|
STATUS_XS, STATUS_FS, /*STATUS_MPP, 2'b0*/ 4'b0,
|
||||||
STATUS_SPP, /*STATUS_MPIE*/ 1'b0, STATUS_UBE, STATUS_SPIE,
|
STATUS_SPP, /*STATUS_MPIE*/ 1'b0, STATUS_UBE, STATUS_SPIE,
|
||||||
/*1'b0, STATUS_MIE, 1'b0*/ 3'b0, STATUS_SIE, 1'b0};
|
/*1'b0, STATUS_MIE, 1'b0*/ 3'b0, STATUS_SIE, 1'b0};
|
||||||
assign MSTATUSH_REGW = '0; // *** does not exist when XLEN=64, but don't want it to have an undefined value. Spec is not clear what it should be.
|
assign MSTATUSH_REGW = '0; // *** does not exist when XLEN=64, but don't want it to have an undefined value. Spec is not clear what it should be.
|
||||||
end else begin: csrsr32 // RV32
|
end else begin: csrsr32 // RV32
|
||||||
assign MSTATUS_REGW = {STATUS_SD, 8'b0,
|
assign MSTATUS_REGW = {STATUS_SD, 8'b0,
|
||||||
STATUS_TSR, STATUS_TW, STATUS_TVM, STATUS_MXR, STATUS_SUM, STATUS_MPRV,
|
STATUS_TSR, STATUS_TW, STATUS_TVM, STATUS_MXR, STATUS_SUM, STATUS_MPRV,
|
||||||
STATUS_XS, STATUS_FS, STATUS_MPP, 2'b0,
|
STATUS_XS, STATUS_FS, STATUS_MPP, 2'b0,
|
||||||
STATUS_SPP, STATUS_MPIE, STATUS_UBE, STATUS_SPIE, 1'b0, STATUS_MIE, 1'b0, STATUS_SIE, 1'b0};
|
STATUS_SPP, STATUS_MPIE, STATUS_UBE, STATUS_SPIE, 1'b0, STATUS_MIE, 1'b0, STATUS_SIE, 1'b0};
|
||||||
assign MSTATUSH_REGW = {26'b0, STATUS_MBE, STATUS_SBE, 4'b0};
|
assign MSTATUSH_REGW = {26'b0, STATUS_MBE, STATUS_SBE, 4'b0};
|
||||||
assign SSTATUS_REGW = {STATUS_SD, 11'b0,
|
assign SSTATUS_REGW = {STATUS_SD, 11'b0,
|
||||||
/*STATUS_TSR, STATUS_TW, STATUS_TVM, */STATUS_MXR, STATUS_SUM, /* STATUS_MPRV, */ 1'b0,
|
/*STATUS_TSR, STATUS_TW, STATUS_TVM, */STATUS_MXR, STATUS_SUM, /* STATUS_MPRV, */ 1'b0,
|
||||||
STATUS_XS, STATUS_FS, /*STATUS_MPP, 2'b0*/ 4'b0,
|
STATUS_XS, STATUS_FS, /*STATUS_MPP, 2'b0*/ 4'b0,
|
||||||
STATUS_SPP, /*STATUS_MPIE*/ 1'b0, STATUS_UBE, STATUS_SPIE,
|
STATUS_SPP, /*STATUS_MPIE*/ 1'b0, STATUS_UBE, STATUS_SPIE,
|
||||||
/*1'b0, STATUS_MIE, 1'b0*/ 3'b0, STATUS_SIE, 1'b0};
|
/*1'b0, STATUS_MIE, 1'b0*/ 3'b0, STATUS_SIE, 1'b0};
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -90,21 +90,21 @@ module csrsr import cvw::*; #(parameter cvw_t P) (
|
|||||||
end
|
end
|
||||||
|
|
||||||
// harwired STATUS bits
|
// harwired STATUS bits
|
||||||
assign STATUS_TSR = P.S_SUPPORTED & STATUS_TSR_INT; // override reigster with 0 if supervisor mode not supported
|
assign STATUS_TSR = P.S_SUPPORTED & STATUS_TSR_INT; // override reigster with 0 if supervisor mode not supported
|
||||||
assign STATUS_TW = (P.S_SUPPORTED | P.U_SUPPORTED) & STATUS_TW_INT; // override register with 0 if only machine mode supported
|
assign STATUS_TW = (P.S_SUPPORTED | P.U_SUPPORTED) & STATUS_TW_INT; // override register with 0 if only machine mode supported
|
||||||
assign STATUS_TVM = P.S_SUPPORTED & STATUS_TVM_INT; // override reigster with 0 if supervisor mode not supported
|
assign STATUS_TVM = P.S_SUPPORTED & STATUS_TVM_INT; // override reigster with 0 if supervisor mode not supported
|
||||||
assign STATUS_MXR = P.S_SUPPORTED & STATUS_MXR_INT; // override reigster with 0 if supervisor mode not supported
|
assign STATUS_MXR = P.S_SUPPORTED & STATUS_MXR_INT; // override reigster with 0 if supervisor mode not supported
|
||||||
/* assign STATUS_UBE = 0; // little-endian
|
/* assign STATUS_UBE = 0; // little-endian
|
||||||
assign STATUS_SBE = 0; // little-endian
|
assign STATUS_SBE = 0; // little-endian
|
||||||
assign STATUS_MBE = 0; // little-endian */
|
assign STATUS_MBE = 0; // little-endian */
|
||||||
// SXL and UXL bits only matter for RV64. Set to 10 for RV64 if mode is supported, or 0 if not
|
// SXL and UXL bits only matter for RV64. Set to 10 for RV64 if mode is supported, or 0 if not
|
||||||
assign STATUS_SXL = P.S_SUPPORTED ? 2'b10 : 2'b00; // 10 if supervisor mode supported
|
assign STATUS_SXL = P.S_SUPPORTED ? 2'b10 : 2'b00; // 10 if supervisor mode supported
|
||||||
assign STATUS_UXL = P.U_SUPPORTED ? 2'b10 : 2'b00; // 10 if user mode supported
|
assign STATUS_UXL = P.U_SUPPORTED ? 2'b10 : 2'b00; // 10 if user mode supported
|
||||||
assign STATUS_SUM = P.S_SUPPORTED & P.VIRTMEM_SUPPORTED & STATUS_SUM_INT; // override reigster with 0 if supervisor mode not supported
|
assign STATUS_SUM = P.S_SUPPORTED & P.VIRTMEM_SUPPORTED & STATUS_SUM_INT; // override reigster with 0 if supervisor mode not supported
|
||||||
assign STATUS_MPRV = P.U_SUPPORTED & STATUS_MPRV_INT; // override with 0 if user mode not supported
|
assign STATUS_MPRV = P.U_SUPPORTED & STATUS_MPRV_INT; // override with 0 if user mode not supported
|
||||||
assign STATUS_FS = (P.S_SUPPORTED & (P.F_SUPPORTED | P.D_SUPPORTED)) ? STATUS_FS_INT : 2'b00; // off if no FP
|
assign STATUS_FS = (P.S_SUPPORTED & (P.F_SUPPORTED | P.D_SUPPORTED)) ? STATUS_FS_INT : 2'b00; // off if no FP
|
||||||
assign STATUS_SD = (STATUS_FS == 2'b11) | (STATUS_XS == 2'b11); // dirty state logic
|
assign STATUS_SD = (STATUS_FS == 2'b11) | (STATUS_XS == 2'b11); // dirty state logic
|
||||||
assign STATUS_XS = 2'b00; // No additional user-mode state to be dirty
|
assign STATUS_XS = 2'b00; // No additional user-mode state to be dirty
|
||||||
|
|
||||||
always_comb
|
always_comb
|
||||||
if (CSRWriteValM[12:11] == P.U_MODE & P.U_SUPPORTED) STATUS_MPP_NEXT = P.U_MODE;
|
if (CSRWriteValM[12:11] == P.U_MODE & P.U_SUPPORTED) STATUS_MPP_NEXT = P.U_MODE;
|
||||||
@ -122,14 +122,14 @@ module csrsr import cvw::*; #(parameter cvw_t P) (
|
|||||||
if (SelHPTW) EndiannessPrivMode = P.S_MODE;
|
if (SelHPTW) EndiannessPrivMode = P.S_MODE;
|
||||||
//coverage off -item c 1 -feccondrow 1
|
//coverage off -item c 1 -feccondrow 1
|
||||||
// status.MPRV always gets reset upon leaving machine mode, so MPRV will never be high when out of machine mode
|
// status.MPRV always gets reset upon leaving machine mode, so MPRV will never be high when out of machine mode
|
||||||
else if (PrivilegeModeW == P.M_MODE & STATUS_MPRV) EndiannessPrivMode = STATUS_MPP;
|
else if (PrivilegeModeW == P.M_MODE & STATUS_MPRV) EndiannessPrivMode = STATUS_MPP;
|
||||||
//coverage on
|
//coverage on
|
||||||
else EndiannessPrivMode = PrivilegeModeW;
|
else EndiannessPrivMode = PrivilegeModeW;
|
||||||
|
|
||||||
case (EndiannessPrivMode)
|
case (EndiannessPrivMode)
|
||||||
P.M_MODE: BigEndianM = STATUS_MBE;
|
P.M_MODE: BigEndianM = STATUS_MBE;
|
||||||
P.S_MODE: BigEndianM = STATUS_SBE;
|
P.S_MODE: BigEndianM = STATUS_SBE;
|
||||||
default: BigEndianM = STATUS_UBE;
|
default: BigEndianM = STATUS_UBE;
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
end else begin: endianmux
|
end else begin: endianmux
|
||||||
@ -140,22 +140,22 @@ module csrsr import cvw::*; #(parameter cvw_t P) (
|
|||||||
// complex register with reset, write enable, and the ability to update other bits in certain cases
|
// complex register with reset, write enable, and the ability to update other bits in certain cases
|
||||||
always_ff @(posedge clk) //, posedge reset)
|
always_ff @(posedge clk) //, posedge reset)
|
||||||
if (reset) begin
|
if (reset) begin
|
||||||
STATUS_TSR_INT <= #1 0;
|
STATUS_TSR_INT <= #1 0;
|
||||||
STATUS_TW_INT <= #1 0;
|
STATUS_TW_INT <= #1 0;
|
||||||
STATUS_TVM_INT <= #1 0;
|
STATUS_TVM_INT <= #1 0;
|
||||||
STATUS_MXR_INT <= #1 0;
|
STATUS_MXR_INT <= #1 0;
|
||||||
STATUS_SUM_INT <= #1 0;
|
STATUS_SUM_INT <= #1 0;
|
||||||
STATUS_MPRV_INT <= #1 0; // Per Priv 3.3
|
STATUS_MPRV_INT <= #1 0; // Per Priv 3.3
|
||||||
STATUS_FS_INT <= #1 P.F_SUPPORTED ? 2'b00 : 2'b00; // leave floating-point off until activated, even if F_SUPPORTED
|
STATUS_FS_INT <= #1 P.F_SUPPORTED ? 2'b00 : 2'b00; // leave floating-point off until activated, even if F_SUPPORTED
|
||||||
STATUS_MPP <= #1 0;
|
STATUS_MPP <= #1 0;
|
||||||
STATUS_SPP <= #1 0;
|
STATUS_SPP <= #1 0;
|
||||||
STATUS_MPIE <= #1 0;
|
STATUS_MPIE <= #1 0;
|
||||||
STATUS_SPIE <= #1 0;
|
STATUS_SPIE <= #1 0;
|
||||||
STATUS_MIE <= #1 0;
|
STATUS_MIE <= #1 0;
|
||||||
STATUS_SIE <= #1 0;
|
STATUS_SIE <= #1 0;
|
||||||
STATUS_MBE <= #1 0;
|
STATUS_MBE <= #1 0;
|
||||||
STATUS_SBE <= #1 0;
|
STATUS_SBE <= #1 0;
|
||||||
STATUS_UBE <= #1 0;
|
STATUS_UBE <= #1 0;
|
||||||
end else if (~StallW) begin
|
end else if (~StallW) begin
|
||||||
if (TrapM) begin
|
if (TrapM) begin
|
||||||
// Update interrupt enables per Privileged Spec p. 21
|
// Update interrupt enables per Privileged Spec p. 21
|
||||||
@ -164,54 +164,54 @@ module csrsr import cvw::*; #(parameter cvw_t P) (
|
|||||||
// Modes: 11 = Machine, 01 = Supervisor, 00 = User
|
// Modes: 11 = Machine, 01 = Supervisor, 00 = User
|
||||||
if (NextPrivilegeModeM == P.M_MODE) begin
|
if (NextPrivilegeModeM == P.M_MODE) begin
|
||||||
STATUS_MPIE <= #1 STATUS_MIE;
|
STATUS_MPIE <= #1 STATUS_MIE;
|
||||||
STATUS_MIE <= #1 0;
|
STATUS_MIE <= #1 0;
|
||||||
STATUS_MPP <= #1 PrivilegeModeW;
|
STATUS_MPP <= #1 PrivilegeModeW;
|
||||||
end else begin // supervisor mode
|
end else begin // supervisor mode
|
||||||
STATUS_SPIE <= #1 STATUS_SIE;
|
STATUS_SPIE <= #1 STATUS_SIE;
|
||||||
STATUS_SIE <= #1 0;
|
STATUS_SIE <= #1 0;
|
||||||
STATUS_SPP <= #1 PrivilegeModeW[0];
|
STATUS_SPP <= #1 PrivilegeModeW[0];
|
||||||
end
|
end
|
||||||
end else if (mretM) begin // Privileged 3.1.6.1
|
end else if (mretM) begin // Privileged 3.1.6.1
|
||||||
STATUS_MIE <= #1 STATUS_MPIE; // restore global interrupt enable
|
STATUS_MIE <= #1 STATUS_MPIE; // restore global interrupt enable
|
||||||
STATUS_MPIE <= #1 1; //
|
STATUS_MPIE <= #1 1; //
|
||||||
STATUS_MPP <= #1 P.U_SUPPORTED ? P.U_MODE : P.M_MODE; // set MPP to lowest supported privilege level
|
STATUS_MPP <= #1 P.U_SUPPORTED ? P.U_MODE : P.M_MODE; // set MPP to lowest supported privilege level
|
||||||
STATUS_MPRV_INT <= #1 STATUS_MPRV_INT & (STATUS_MPP == P.M_MODE); // page 21 of privileged spec.
|
STATUS_MPRV_INT <= #1 STATUS_MPRV_INT & (STATUS_MPP == P.M_MODE); // page 21 of privileged spec.
|
||||||
end else if (sretM) begin
|
end else if (sretM) begin
|
||||||
STATUS_SIE <= #1 STATUS_SPIE; // restore global interrupt enable
|
STATUS_SIE <= #1 STATUS_SPIE; // restore global interrupt enable
|
||||||
STATUS_SPIE <= #1 P.S_SUPPORTED;
|
STATUS_SPIE <= #1 P.S_SUPPORTED;
|
||||||
STATUS_SPP <= #1 0; // set SPP to lowest supported privilege level to catch bugs
|
STATUS_SPP <= #1 0; // set SPP to lowest supported privilege level to catch bugs
|
||||||
STATUS_MPRV_INT <= #1 0; // always clear MPRV
|
STATUS_MPRV_INT <= #1 0; // always clear MPRV
|
||||||
end else if (WriteMSTATUSM) begin
|
end else if (WriteMSTATUSM) begin
|
||||||
STATUS_TSR_INT <= #1 CSRWriteValM[22];
|
STATUS_TSR_INT <= #1 CSRWriteValM[22];
|
||||||
STATUS_TW_INT <= #1 CSRWriteValM[21];
|
STATUS_TW_INT <= #1 CSRWriteValM[21];
|
||||||
STATUS_TVM_INT <= #1 CSRWriteValM[20];
|
STATUS_TVM_INT <= #1 CSRWriteValM[20];
|
||||||
STATUS_MXR_INT <= #1 CSRWriteValM[19];
|
STATUS_MXR_INT <= #1 CSRWriteValM[19];
|
||||||
STATUS_SUM_INT <= #1 CSRWriteValM[18];
|
STATUS_SUM_INT <= #1 CSRWriteValM[18];
|
||||||
STATUS_MPRV_INT <= #1 CSRWriteValM[17];
|
STATUS_MPRV_INT <= #1 CSRWriteValM[17];
|
||||||
STATUS_FS_INT <= #1 CSRWriteValM[14:13];
|
STATUS_FS_INT <= #1 CSRWriteValM[14:13];
|
||||||
STATUS_MPP <= #1 STATUS_MPP_NEXT;
|
STATUS_MPP <= #1 STATUS_MPP_NEXT;
|
||||||
STATUS_SPP <= #1 P.S_SUPPORTED & CSRWriteValM[8];
|
STATUS_SPP <= #1 P.S_SUPPORTED & CSRWriteValM[8];
|
||||||
STATUS_MPIE <= #1 CSRWriteValM[7];
|
STATUS_MPIE <= #1 CSRWriteValM[7];
|
||||||
STATUS_SPIE <= #1 P.S_SUPPORTED & CSRWriteValM[5];
|
STATUS_SPIE <= #1 P.S_SUPPORTED & CSRWriteValM[5];
|
||||||
STATUS_MIE <= #1 CSRWriteValM[3];
|
STATUS_MIE <= #1 CSRWriteValM[3];
|
||||||
STATUS_SIE <= #1 P.S_SUPPORTED & CSRWriteValM[1];
|
STATUS_SIE <= #1 P.S_SUPPORTED & CSRWriteValM[1];
|
||||||
STATUS_UBE <= #1 CSRWriteValM[6] & P.U_SUPPORTED & P.BIGENDIAN_SUPPORTED;
|
STATUS_UBE <= #1 CSRWriteValM[6] & P.U_SUPPORTED & P.BIGENDIAN_SUPPORTED;
|
||||||
STATUS_MBE <= #1 nextMBE;
|
STATUS_MBE <= #1 nextMBE;
|
||||||
STATUS_SBE <= #1 nextSBE;
|
STATUS_SBE <= #1 nextSBE;
|
||||||
// coverage off
|
// coverage off
|
||||||
// MSTATUSH only exists in 32-bit configurations, will not be hit on rv64gc
|
// MSTATUSH only exists in 32-bit configurations, will not be hit on rv64gc
|
||||||
end else if (WriteMSTATUSHM) begin
|
end else if (WriteMSTATUSHM) begin
|
||||||
STATUS_MBE <= #1 CSRWriteValM[5] & P.BIGENDIAN_SUPPORTED;
|
STATUS_MBE <= #1 CSRWriteValM[5] & P.BIGENDIAN_SUPPORTED;
|
||||||
STATUS_SBE <= #1 CSRWriteValM[4] & P.S_SUPPORTED & P.BIGENDIAN_SUPPORTED;
|
STATUS_SBE <= #1 CSRWriteValM[4] & P.S_SUPPORTED & P.BIGENDIAN_SUPPORTED;
|
||||||
// coverage on
|
// coverage on
|
||||||
end else if (WriteSSTATUSM) begin // write a subset of the STATUS bits
|
end else if (WriteSSTATUSM) begin // write a subset of the STATUS bits
|
||||||
STATUS_MXR_INT <= #1 CSRWriteValM[19];
|
STATUS_MXR_INT <= #1 CSRWriteValM[19];
|
||||||
STATUS_SUM_INT <= #1 CSRWriteValM[18];
|
STATUS_SUM_INT <= #1 CSRWriteValM[18];
|
||||||
STATUS_FS_INT <= #1 CSRWriteValM[14:13];
|
STATUS_FS_INT <= #1 CSRWriteValM[14:13];
|
||||||
STATUS_SPP <= #1 P.S_SUPPORTED & CSRWriteValM[8];
|
STATUS_SPP <= #1 P.S_SUPPORTED & CSRWriteValM[8];
|
||||||
STATUS_SPIE <= #1 P.S_SUPPORTED & CSRWriteValM[5];
|
STATUS_SPIE <= #1 P.S_SUPPORTED & CSRWriteValM[5];
|
||||||
STATUS_SIE <= #1 P.S_SUPPORTED & CSRWriteValM[1];
|
STATUS_SIE <= #1 P.S_SUPPORTED & CSRWriteValM[1];
|
||||||
STATUS_UBE <= #1 CSRWriteValM[6] & P.U_SUPPORTED & P.BIGENDIAN_SUPPORTED;
|
STATUS_UBE <= #1 CSRWriteValM[6] & P.U_SUPPORTED & P.BIGENDIAN_SUPPORTED;
|
||||||
end else if (FRegWriteM | WriteFRMM | WriteFFLAGSM) STATUS_FS_INT <= #1 2'b11;
|
end else if (FRegWriteM | WriteFRMM | WriteFFLAGSM) STATUS_FS_INT <= #1 2'b11;
|
||||||
end
|
end
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -27,40 +27,40 @@
|
|||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
module csru import cvw::*; #(parameter cvw_t P) (
|
module csru import cvw::*; #(parameter cvw_t P) (
|
||||||
input logic clk, reset,
|
input logic clk, reset,
|
||||||
input logic InstrValidNotFlushedM,
|
input logic InstrValidNotFlushedM,
|
||||||
input logic CSRUWriteM,
|
input logic CSRUWriteM,
|
||||||
input logic [11:0] CSRAdrM,
|
input logic [11:0] CSRAdrM,
|
||||||
input logic [P.XLEN-1:0] CSRWriteValM,
|
input logic [P.XLEN-1:0] CSRWriteValM,
|
||||||
input logic [1:0] STATUS_FS,
|
input logic [1:0] STATUS_FS,
|
||||||
output logic [P.XLEN-1:0] CSRUReadValM,
|
output logic [P.XLEN-1:0] CSRUReadValM,
|
||||||
input logic [4:0] SetFflagsM,
|
input logic [4:0] SetFflagsM,
|
||||||
output logic [2:0] FRM_REGW,
|
output logic [2:0] FRM_REGW,
|
||||||
output logic WriteFRMM, WriteFFLAGSM,
|
output logic WriteFRMM, WriteFFLAGSM,
|
||||||
output logic IllegalCSRUAccessM
|
output logic IllegalCSRUAccessM
|
||||||
);
|
);
|
||||||
|
|
||||||
localparam FFLAGS = 12'h001;
|
localparam FFLAGS = 12'h001;
|
||||||
localparam FRM = 12'h002;
|
localparam FRM = 12'h002;
|
||||||
localparam FCSR = 12'h003;
|
localparam FCSR = 12'h003;
|
||||||
|
|
||||||
logic [4:0] FFLAGS_REGW;
|
logic [4:0] FFLAGS_REGW;
|
||||||
logic [2:0] NextFRMM;
|
logic [2:0] NextFRMM;
|
||||||
logic [4:0] NextFFLAGSM;
|
logic [4:0] NextFFLAGSM;
|
||||||
logic SetOrWriteFFLAGSM;
|
logic SetOrWriteFFLAGSM;
|
||||||
|
|
||||||
// Write enables
|
// Write enables
|
||||||
assign WriteFRMM = CSRUWriteM & (STATUS_FS != 2'b00) & (CSRAdrM == FRM | CSRAdrM == FCSR);
|
assign WriteFRMM = CSRUWriteM & (STATUS_FS != 2'b00) & (CSRAdrM == FRM | CSRAdrM == FCSR);
|
||||||
assign WriteFFLAGSM = CSRUWriteM & (STATUS_FS != 2'b00) & (CSRAdrM == FFLAGS | CSRAdrM == FCSR);
|
assign WriteFFLAGSM = CSRUWriteM & (STATUS_FS != 2'b00) & (CSRAdrM == FFLAGS | CSRAdrM == FCSR);
|
||||||
|
|
||||||
// Write Values
|
// Write Values
|
||||||
assign NextFRMM = (CSRAdrM == FCSR) ? CSRWriteValM[7:5] : CSRWriteValM[2:0];
|
assign NextFRMM = (CSRAdrM == FCSR) ? CSRWriteValM[7:5] : CSRWriteValM[2:0];
|
||||||
assign NextFFLAGSM = WriteFFLAGSM ? CSRWriteValM[4:0] : FFLAGS_REGW | SetFflagsM;
|
assign NextFFLAGSM = WriteFFLAGSM ? CSRWriteValM[4:0] : FFLAGS_REGW | SetFflagsM;
|
||||||
assign SetOrWriteFFLAGSM = WriteFFLAGSM | (|SetFflagsM & InstrValidNotFlushedM);
|
assign SetOrWriteFFLAGSM = WriteFFLAGSM | (|SetFflagsM & InstrValidNotFlushedM);
|
||||||
|
|
||||||
// CSRs
|
// CSRs
|
||||||
flopenr #(3) FRMreg(clk, reset, WriteFRMM, NextFRMM, FRM_REGW);
|
flopenr #(3) FRMreg(clk, reset, WriteFRMM, NextFRMM, FRM_REGW);
|
||||||
flopenr #(5) FFLAGSreg(clk, reset, SetOrWriteFFLAGSM, NextFFLAGSM, FFLAGS_REGW);
|
flopenr #(5) FFLAGSreg(clk, reset, SetOrWriteFFLAGSM, NextFFLAGSM, FFLAGS_REGW);
|
||||||
|
|
||||||
// CSR Reads
|
// CSR Reads
|
||||||
always_comb begin
|
always_comb begin
|
||||||
|
@ -28,91 +28,90 @@
|
|||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
|
|
||||||
module privileged import cvw::*; #(parameter cvw_t P) (
|
module privileged import cvw::*; #(parameter cvw_t P) (
|
||||||
input logic clk, reset,
|
input logic clk, reset,
|
||||||
input logic StallD, StallE, StallM, StallW,
|
input logic StallD, StallE, StallM, StallW,
|
||||||
input logic FlushD, FlushE, FlushM, FlushW,
|
input logic FlushD, FlushE, FlushM, FlushW,
|
||||||
// CSR Reads and Writes, and values needed for traps
|
// CSR Reads and Writes, and values needed for traps
|
||||||
input logic CSRReadM, CSRWriteM, // Read or write CSRs
|
input logic CSRReadM, CSRWriteM, // Read or write CSRs
|
||||||
input logic [P.XLEN-1:0] SrcAM, // GPR register to write
|
input logic [P.XLEN-1:0] SrcAM, // GPR register to write
|
||||||
input logic [31:0] InstrM, // Instruction
|
input logic [31:0] InstrM, // Instruction
|
||||||
input logic [31:0] InstrOrigM, // Original compressed or uncompressed instruction in Memory stage for Illegal Instruction MTVAL
|
input logic [31:0] InstrOrigM, // Original compressed or uncompressed instruction in Memory stage for Illegal Instruction MTVAL
|
||||||
input logic [P.XLEN-1:0] IEUAdrM, // address from IEU
|
input logic [P.XLEN-1:0] IEUAdrM, // address from IEU
|
||||||
input logic [P.XLEN-1:0] PCM, PC2NextF, // program counter, next PC going to trap/return PC logic
|
input logic [P.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
|
||||||
input logic PrivilegedM, // privileged instruction
|
input logic PrivilegedM, // privileged instruction
|
||||||
// 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 StoreStallD, // store instruction is stalling
|
input logic StoreStallD, // store instruction is stalling
|
||||||
input logic ICacheStallF, // I cache stalled
|
input logic ICacheStallF, // I cache stalled
|
||||||
input logic DCacheStallM, // D cache stalled
|
input logic DCacheStallM, // D cache stalled
|
||||||
input logic BPDirPredWrongM, // branch predictor guessed wrong direction
|
input logic BPDirPredWrongM, // branch predictor guessed wrong direction
|
||||||
input logic BTAWrongM, // branch predictor guessed wrong target
|
input logic BTAWrongM, // branch predictor guessed wrong target
|
||||||
input logic RASPredPCWrongM, // return adddress stack guessed wrong target
|
input logic RASPredPCWrongM, // return adddress stack guessed wrong target
|
||||||
input logic IClassWrongM, // branch predictor guessed wrong instruction class
|
input logic IClassWrongM, // branch predictor guessed wrong instruction class
|
||||||
input logic BPWrongM, // branch predictor is wrong
|
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 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 DivBusyE, // integer divide busy
|
||||||
input logic FDivBusyE, // floating point 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
|
||||||
input logic HPTWInstrAccessFaultF, // hardware page table access fault while fetching instruction PTE
|
input logic HPTWInstrAccessFaultF, // hardware page table access fault while fetching instruction PTE
|
||||||
input logic InstrPageFaultF, // page faults
|
input logic InstrPageFaultF, // page faults
|
||||||
input logic LoadPageFaultM, StoreAmoPageFaultM, // page faults
|
input logic LoadPageFaultM, StoreAmoPageFaultM, // page faults
|
||||||
input logic InstrMisalignedFaultM, // misaligned instruction fault
|
input logic InstrMisalignedFaultM, // misaligned instruction fault
|
||||||
input logic LoadMisalignedFaultM, StoreAmoMisalignedFaultM, // misaligned data fault
|
input logic LoadMisalignedFaultM, StoreAmoMisalignedFaultM, // misaligned data fault
|
||||||
input logic IllegalIEUFPUInstrD, // illegal instruction from IEU or FPU
|
input logic IllegalIEUFPUInstrD, // illegal instruction from IEU or FPU
|
||||||
input logic MTimerInt, MExtInt, SExtInt, MSwInt, // interrupt sources
|
input logic MTimerInt, MExtInt, SExtInt, MSwInt, // interrupt sources
|
||||||
input logic [63:0] MTIME_CLINT, // timer value from CLINT
|
input logic [63:0] MTIME_CLINT, // timer value from CLINT
|
||||||
input logic [4:0] SetFflagsM, // set FCSR flags from FPU
|
input logic [4:0] SetFflagsM, // set FCSR flags from FPU
|
||||||
input logic SelHPTW, // HPTW in use. Causes system to use S-mode endianness for accesses
|
input logic SelHPTW, // HPTW in use. Causes system to use S-mode endianness for accesses
|
||||||
// CSR outputs
|
// CSR outputs
|
||||||
output logic [P.XLEN-1:0] CSRReadValW, // Value read from CSR
|
output logic [P.XLEN-1:0] CSRReadValW, // Value read from CSR
|
||||||
output logic [1:0] PrivilegeModeW, // current privilege mode
|
output logic [1:0] PrivilegeModeW, // current privilege mode
|
||||||
output logic [P.XLEN-1:0] SATP_REGW, // supervisor address translation register
|
output logic [P.XLEN-1:0] SATP_REGW, // supervisor address translation register
|
||||||
output logic STATUS_MXR, STATUS_SUM, STATUS_MPRV, // status register bits
|
output logic STATUS_MXR, STATUS_SUM, STATUS_MPRV, // status register bits
|
||||||
output logic [1:0] STATUS_MPP, STATUS_FS, // status register bits
|
output logic [1:0] STATUS_MPP, STATUS_FS, // status register bits
|
||||||
output var logic [7:0] PMPCFG_ARRAY_REGW[P.PMP_ENTRIES-1:0], // PMP configuration entries to MMU
|
output var logic [7:0] PMPCFG_ARRAY_REGW[P.PMP_ENTRIES-1:0], // PMP configuration entries to MMU
|
||||||
output var logic [P.PA_BITS-3:0] PMPADDR_ARRAY_REGW [P.PMP_ENTRIES-1:0], // PMP address entries to MMU
|
output var logic [P.PA_BITS-3:0] PMPADDR_ARRAY_REGW [P.PMP_ENTRIES-1:0], // PMP address entries to MMU
|
||||||
output logic [2:0] FRM_REGW, // FPU rounding mode
|
output logic [2:0] FRM_REGW, // FPU rounding mode
|
||||||
// PC logic output in privileged unit
|
// PC logic output in privileged unit
|
||||||
output logic [P.XLEN-1:0] UnalignedPCNextF, // Next PC from trap/return PC logic
|
output logic [P.XLEN-1:0] UnalignedPCNextF, // Next PC from trap/return PC logic
|
||||||
// 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 InvalidateICacheM, // fence instruction
|
input logic InvalidateICacheM, // 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
|
||||||
output logic wfiM, IntPendingM // Stall in Memory stage for WFI until interrupt pending or timeout
|
output logic wfiM, IntPendingM // Stall in Memory stage for WFI until interrupt pending or timeout
|
||||||
);
|
);
|
||||||
|
|
||||||
logic [3:0] CauseM; // trap cause
|
logic [3:0] CauseM; // trap cause
|
||||||
logic [15:0] MEDELEG_REGW; // exception delegation CSR
|
logic [15:0] MEDELEG_REGW; // exception delegation CSR
|
||||||
logic [11:0] MIDELEG_REGW; // interrupt delegation CSR
|
logic [11:0] MIDELEG_REGW; // interrupt delegation CSR
|
||||||
logic sretM, mretM; // supervisor / machine return instruction
|
logic sretM, mretM; // supervisor / machine return instruction
|
||||||
logic IllegalCSRAccessM; // Illegal access to CSR
|
logic IllegalCSRAccessM; // Illegal access to CSR
|
||||||
logic IllegalIEUFPUInstrM; // Illegal IEU or FPU instruction, delayed to Mem stage
|
logic IllegalIEUFPUInstrM; // Illegal IEU or FPU instruction, delayed to Mem stage
|
||||||
logic InstrPageFaultM; // Instruction page fault, delayed to Mem stage
|
logic InstrPageFaultM; // Instruction page fault, delayed to Mem stage
|
||||||
logic InstrAccessFaultM; // Instruction access fault, delayed to Mem stages
|
logic InstrAccessFaultM; // Instruction access fault, delayed to Mem stages
|
||||||
logic IllegalInstrFaultM; // Illegal instruction fault
|
logic IllegalInstrFaultM; // Illegal instruction fault
|
||||||
logic STATUS_SPP, STATUS_TSR, STATUS_TW, STATUS_TVM; // Status bits needed within privileged unit
|
logic STATUS_SPP, STATUS_TSR, STATUS_TW, STATUS_TVM; // Status bits needed within privileged unit
|
||||||
logic STATUS_MIE, STATUS_SIE; // status bits: interrupt enables
|
logic STATUS_MIE, STATUS_SIE; // status bits: interrupt enables
|
||||||
logic [11:0] MIP_REGW, MIE_REGW; // interrupt pending and enable bits
|
logic [11:0] MIP_REGW, MIE_REGW; // interrupt pending and enable bits
|
||||||
logic [1:0] NextPrivilegeModeM; // next privilege mode based on trap or return
|
logic [1:0] NextPrivilegeModeM; // next privilege mode based on trap or return
|
||||||
logic DelegateM; // trap should be delegated
|
logic DelegateM; // trap should be delegated
|
||||||
logic InterruptM; // interrupt occuring
|
logic InterruptM; // interrupt occuring
|
||||||
logic ExceptionM; // Memory stage instruction caused a fault
|
logic ExceptionM; // Memory stage instruction caused a fault
|
||||||
logic HPTWInstrAccessFaultM; // Hardware page table access fault while fetching instruction PTE
|
logic HPTWInstrAccessFaultM; // Hardware page table access fault while fetching instruction PTE
|
||||||
|
|
||||||
|
|
||||||
// track the current privilege level
|
// track the current privilege level
|
||||||
privmode #(P) privmode(.clk, .reset, .StallW, .TrapM, .mretM, .sretM, .DelegateM,
|
privmode #(P) privmode(.clk, .reset, .StallW, .TrapM, .mretM, .sretM, .DelegateM,
|
||||||
.STATUS_MPP, .STATUS_SPP, .NextPrivilegeModeM, .PrivilegeModeW);
|
.STATUS_MPP, .STATUS_SPP, .NextPrivilegeModeM, .PrivilegeModeW);
|
||||||
@ -156,8 +155,3 @@ module privileged import cvw::*; #(parameter cvw_t P) (
|
|||||||
.InstrValidM, .CommittedM, .CommittedF,
|
.InstrValidM, .CommittedM, .CommittedF,
|
||||||
.TrapM, .RetM, .wfiM, .InterruptM, .ExceptionM, .IntPendingM, .DelegateM, .CauseM);
|
.TrapM, .RetM, .wfiM, .InterruptM, .ExceptionM, .IntPendingM, .DelegateM, .CauseM);
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -43,10 +43,10 @@ module privmode import cvw::*; #(parameter cvw_t P) (
|
|||||||
always_comb begin
|
always_comb begin
|
||||||
if (TrapM) begin // Change privilege based on DELEG registers (see 3.1.8)
|
if (TrapM) begin // Change privilege based on DELEG registers (see 3.1.8)
|
||||||
if (P.S_SUPPORTED & DelegateM) NextPrivilegeModeM = P.S_MODE;
|
if (P.S_SUPPORTED & DelegateM) NextPrivilegeModeM = P.S_MODE;
|
||||||
else NextPrivilegeModeM = P.M_MODE;
|
else NextPrivilegeModeM = P.M_MODE;
|
||||||
end else if (mretM) NextPrivilegeModeM = STATUS_MPP;
|
end else if (mretM) NextPrivilegeModeM = STATUS_MPP;
|
||||||
else if (sretM) NextPrivilegeModeM = {1'b0, STATUS_SPP};
|
else if (sretM) NextPrivilegeModeM = {1'b0, STATUS_SPP};
|
||||||
else NextPrivilegeModeM = PrivilegeModeW;
|
else NextPrivilegeModeM = PrivilegeModeW;
|
||||||
end
|
end
|
||||||
|
|
||||||
flopenl #(2) privmodereg(clk, reset, ~StallW, NextPrivilegeModeM, P.M_MODE, PrivilegeModeW);
|
flopenl #(2) privmodereg(clk, reset, ~StallW, NextPrivilegeModeM, P.M_MODE, PrivilegeModeW);
|
||||||
|
@ -63,13 +63,13 @@ module trap import cvw::*; #(parameter cvw_t P) (
|
|||||||
|
|
||||||
assign MIntGlobalEnM = (PrivilegeModeW != P.M_MODE) | STATUS_MIE; // if M ints enabled or lower priv 3.1.9
|
assign MIntGlobalEnM = (PrivilegeModeW != P.M_MODE) | STATUS_MIE; // if M ints enabled or lower priv 3.1.9
|
||||||
assign SIntGlobalEnM = (PrivilegeModeW == P.U_MODE) | ((PrivilegeModeW == P.S_MODE) & STATUS_SIE); // if in lower priv mode, or if S ints enabled and not in higher priv mode 3.1.9
|
assign SIntGlobalEnM = (PrivilegeModeW == P.U_MODE) | ((PrivilegeModeW == P.S_MODE) & STATUS_SIE); // if in lower priv mode, or if S ints enabled and not in higher priv mode 3.1.9
|
||||||
assign PendingIntsM = MIP_REGW & MIE_REGW;
|
assign PendingIntsM = MIP_REGW & MIE_REGW;
|
||||||
assign IntPendingM = |PendingIntsM;
|
assign IntPendingM = |PendingIntsM;
|
||||||
assign Committed = CommittedM | CommittedF;
|
assign Committed = CommittedM | CommittedF;
|
||||||
assign EnabledIntsM = ({12{MIntGlobalEnM}} & PendingIntsM & ~MIDELEG_REGW | {12{SIntGlobalEnM}} & PendingIntsM & MIDELEG_REGW);
|
assign EnabledIntsM = ({12{MIntGlobalEnM}} & PendingIntsM & ~MIDELEG_REGW | {12{SIntGlobalEnM}} & PendingIntsM & MIDELEG_REGW);
|
||||||
assign ValidIntsM = {12{~Committed}} & EnabledIntsM;
|
assign ValidIntsM = {12{~Committed}} & EnabledIntsM;
|
||||||
assign InterruptM = (|ValidIntsM) & InstrValidM; // suppress interrupt if the memory system has partially processed a request.
|
assign InterruptM = (|ValidIntsM) & InstrValidM; // suppress interrupt if the memory system has partially processed a request.
|
||||||
assign DelegateM = P.S_SUPPORTED & (InterruptM ? MIDELEG_REGW[CauseM] : MEDELEG_REGW[CauseM]) &
|
assign DelegateM = P.S_SUPPORTED & (InterruptM ? MIDELEG_REGW[CauseM] : MEDELEG_REGW[CauseM]) &
|
||||||
(PrivilegeModeW == P.U_MODE | PrivilegeModeW == P.S_MODE);
|
(PrivilegeModeW == P.U_MODE | PrivilegeModeW == P.S_MODE);
|
||||||
|
|
||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
@ -88,7 +88,7 @@ module trap import cvw::*; #(parameter cvw_t P) (
|
|||||||
LoadAccessFaultM | StoreAmoAccessFaultM;
|
LoadAccessFaultM | StoreAmoAccessFaultM;
|
||||||
// coverage on
|
// coverage on
|
||||||
assign TrapM = ExceptionM | InterruptM;
|
assign TrapM = ExceptionM | InterruptM;
|
||||||
assign RetM = mretM | sretM;
|
assign RetM = mretM | sretM;
|
||||||
|
|
||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
// Cause priority defined in table 3.7 of 20190608 privileged spec
|
// Cause priority defined in table 3.7 of 20190608 privileged spec
|
||||||
|
@ -27,27 +27,27 @@
|
|||||||
|
|
||||||
module ahbapbbridge import cvw::*; #(parameter cvw_t P,
|
module ahbapbbridge import cvw::*; #(parameter cvw_t P,
|
||||||
parameter PERIPHS = 2) (
|
parameter PERIPHS = 2) (
|
||||||
input logic HCLK, HRESETn,
|
input logic HCLK, HRESETn,
|
||||||
input logic [PERIPHS-1:0] HSEL,
|
input logic [PERIPHS-1:0] HSEL,
|
||||||
input logic [P.PA_BITS-1:0] HADDR,
|
input logic [P.PA_BITS-1:0] HADDR,
|
||||||
input logic [P.XLEN-1:0] HWDATA,
|
input logic [P.XLEN-1:0] HWDATA,
|
||||||
input logic [P.XLEN/8-1:0] HWSTRB,
|
input logic [P.XLEN/8-1:0] HWSTRB,
|
||||||
input logic HWRITE,
|
input logic HWRITE,
|
||||||
input logic [1:0] HTRANS,
|
input logic [1:0] HTRANS,
|
||||||
input logic HREADY,
|
input logic HREADY,
|
||||||
// input logic [3:0] HPROT, // not used
|
// input logic [3:0] HPROT, // not used
|
||||||
output logic [P.XLEN-1:0] HRDATA,
|
output logic [P.XLEN-1:0] HRDATA,
|
||||||
output logic HRESP, HREADYOUT,
|
output logic HRESP, HREADYOUT,
|
||||||
output logic PCLK, PRESETn,
|
output logic PCLK, PRESETn,
|
||||||
output logic [PERIPHS-1:0] PSEL,
|
output logic [PERIPHS-1:0] PSEL,
|
||||||
output logic PWRITE,
|
output logic PWRITE,
|
||||||
output logic PENABLE,
|
output logic PENABLE,
|
||||||
output logic [31:0] PADDR,
|
output logic [31:0] PADDR,
|
||||||
output logic [P.XLEN-1:0] PWDATA,
|
output logic [P.XLEN-1:0] PWDATA,
|
||||||
// output logic [2:0] PPROT, // not used
|
// output logic [2:0] PPROT, // not used
|
||||||
output logic [P.XLEN/8-1:0] PSTRB,
|
output logic [P.XLEN/8-1:0] PSTRB,
|
||||||
// output logic PWAKEUP // not used
|
// output logic PWAKEUP // not used
|
||||||
input logic [PERIPHS-1:0] PREADY,
|
input logic [PERIPHS-1:0] PREADY,
|
||||||
input var [PERIPHS-1:0][P.XLEN-1:0] PRDATA
|
input var [PERIPHS-1:0][P.XLEN-1:0] PRDATA
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -56,15 +56,15 @@ module ahbapbbridge import cvw::*; #(parameter cvw_t P,
|
|||||||
logic PREADYOUT;
|
logic PREADYOUT;
|
||||||
|
|
||||||
// convert AHB to APB signals
|
// convert AHB to APB signals
|
||||||
assign PCLK = HCLK;
|
assign PCLK = HCLK;
|
||||||
assign PRESETn = HRESETn;
|
assign PRESETn = HRESETn;
|
||||||
|
|
||||||
// identify start of a transaction
|
// identify start of a transaction
|
||||||
assign initTrans = HTRANS[1] & HREADY; // start a transaction when the bus is ready and an active transaction is requested
|
assign initTrans = HTRANS[1] & HREADY; // start a transaction when the bus is ready and an active transaction is requested
|
||||||
assign initTransSel = initTrans & |HSEL; // capture data and address if any of the peripherals are selected
|
assign initTransSel = initTrans & |HSEL; // capture data and address if any of the peripherals are selected
|
||||||
|
|
||||||
// delay AHB Address phase signals to align with AHB Data phase because APB expects them at the same time
|
// delay AHB Address phase signals to align with AHB Data phase because APB expects them at the same time
|
||||||
flopen #(32) addrreg(HCLK, HREADY, HADDR[31:0], PADDR);
|
flopen #(32) addrreg(HCLK, HREADY, HADDR[31:0], PADDR);
|
||||||
flopenr #(1) writereg(HCLK, ~HRESETn, HREADY, HWRITE, PWRITE);
|
flopenr #(1) writereg(HCLK, ~HRESETn, HREADY, HWRITE, PWRITE);
|
||||||
flopenr #(PERIPHS) selreg(HCLK, ~HRESETn, HREADY, HSEL & {PERIPHS{initTrans}}, PSEL);
|
flopenr #(PERIPHS) selreg(HCLK, ~HRESETn, HREADY, HSEL & {PERIPHS{initTrans}}, PSEL);
|
||||||
// PPROT[2:0] = {Data/InstrB, Secure, Privileged};
|
// PPROT[2:0] = {Data/InstrB, Secure, Privileged};
|
||||||
@ -73,7 +73,7 @@ module ahbapbbridge import cvw::*; #(parameter cvw_t P,
|
|||||||
|
|
||||||
// AHB Data phase signal doesn't need delay. Note that they are guaranteed to remain stable until READY is asserted
|
// AHB Data phase signal doesn't need delay. Note that they are guaranteed to remain stable until READY is asserted
|
||||||
assign PWDATA = HWDATA;
|
assign PWDATA = HWDATA;
|
||||||
assign PSTRB = HWSTRB;
|
assign PSTRB = HWSTRB;
|
||||||
|
|
||||||
// enable logic: goes high a cycle after initTrans, then back low on cycle after desired PREADY is asserted
|
// enable logic: goes high a cycle after initTrans, then back low on cycle after desired PREADY is asserted
|
||||||
// cycle1: AHB puts HADDR, HWRITE, HSEL on bus. initTrans is 1, and these are captured
|
// cycle1: AHB puts HADDR, HWRITE, HSEL on bus. initTrans is 1, and these are captured
|
||||||
@ -103,4 +103,3 @@ assign HREADYOUT = PREADYOUT & ~initTransSelD; // don't raise HREADYOUT before a
|
|||||||
// resp logic
|
// resp logic
|
||||||
assign HRESP = 0; // bridge never indicates errors
|
assign HRESP = 0; // bridge never indicates errors
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user