diff --git a/src/ieu/datapath.sv b/src/ieu/datapath.sv index cb013ee9d..40a72926e 100644 --- a/src/ieu/datapath.sv +++ b/src/ieu/datapath.sv @@ -28,55 +28,55 @@ //////////////////////////////////////////////////////////////////////////////////////////////// module datapath import cvw::*; #(parameter cvw_t P) ( - input logic clk, reset, + input logic clk, reset, // Decode stage signals - input logic [2:0] ImmSrcD, // Selects type of immediate extension - input logic [31:0] InstrD, // Instruction in Decode stage + input logic [2:0] ImmSrcD, // Selects type of immediate extension + input logic [31:0] InstrD, // Instruction in Decode stage // Execute stage signals 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 [2:0] Funct3E, // Funct3 field of instruction in Execute stage - input logic StallE, FlushE, // Stall, flush Execute stage - input logic [1:0] ForwardAE, ForwardBE, // Forward ALU operands from later stages - input logic W64E, // W64-type instruction - input logic SubArithE, // Subtraction or arithmetic shift - input logic ALUSrcAE, ALUSrcBE, // ALU operands - input logic ALUResultSrcE, // Selects result to pass on to Memory stage - input logic [2:0] ALUSelectE, // ALU mux select signal - input logic JumpE, // Is a jump (j) instruction - 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 [2:0] ZBBSelectE, // ZBB mux select signal - input logic [2:0] BALUControlE, // ALU Control signals for B instructions in Execute Stage - output logic [1:0] FlagsE, // Comparison flags ({eq, lt}) + input logic [2:0] Funct3E, // Funct3 field of instruction in Execute stage + input logic StallE, FlushE, // Stall, flush Execute stage + input logic [1:0] ForwardAE, ForwardBE, // Forward ALU operands from later stages + input logic W64E, // W64-type instruction + input logic SubArithE, // Subtraction or arithmetic shift + input logic ALUSrcAE, ALUSrcBE, // ALU operands + input logic ALUResultSrcE, // Selects result to pass on to Memory stage + input logic [2:0] ALUSelectE, // ALU mux select signal + input logic JumpE, // Is a jump (j) instruction + 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 [2:0] ZBBSelectE, // ZBB mux select signal + 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 [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 // Memory stage signals - input logic StallM, FlushM, // Stall, flush Memory stage - input logic FWriteIntM, FCvtIntW, // FPU writes integer register file, FPU converts float to int + input logic StallM, FlushM, // Stall, flush Memory stage + input logic FWriteIntM, FCvtIntW, // FPU writes integer register file, FPU converts float to int 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] WriteDataM, // Write data in Memory stage // Writeback stage signals - input logic StallW, FlushW, // Stall, flush Writeback stage - input logic RegWriteW, IntDivW, // Write register file, integer divide instruction - 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 StallW, FlushW, // Stall, flush Writeback stage + input logic RegWriteW, IntDivW, // Write register file, integer divide instruction + 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 [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] CSRReadValW, // CSR read 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 // Hazard Unit signals - 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] 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 ); // Fetch stage signals // Decode stage signals 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 [4:0] RdD; // Destination register in Decode stage + logic [4:0] RdD; // Destination register in Decode stage // Execute stage signals logic [P.XLEN-1:0] R1E, R2E; // Source operands read from register file 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) RD2EReg(clk, reset, FlushE, ~StallE, R2D, R2E); flopenrc #(P.XLEN) ImmExtEReg(clk, reset, FlushE, ~StallE, ImmExtD, ImmExtE); - flopenrc #(5) Rs1EReg(clk, reset, FlushE, ~StallE, Rs1D, Rs1E); - flopenrc #(5) Rs2EReg(clk, reset, FlushE, ~StallE, Rs2D, Rs2E); - flopenrc #(5) RdEReg(clk, reset, FlushE, ~StallE, RdD, RdE); + flopenrc #(5) Rs1EReg(clk, reset, FlushE, ~StallE, Rs1D, Rs1E); + flopenrc #(5) Rs2EReg(clk, reset, FlushE, ~StallE, Rs2D, Rs2E); + flopenrc #(5) RdEReg(clk, reset, FlushE, ~StallE, RdD, RdE); mux3 #(P.XLEN) faemux(R1E, ResultW, IFResultM, ForwardAE, ForwardedSrcAE); 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 if (P.A_SUPPORTED) assign SCResultW = {{(P.XLEN-1){1'b0}}, SquashSCW}; - else assign SCResultW = 0; + else assign SCResultW = 0; endmodule diff --git a/src/ieu/extend.sv b/src/ieu/extend.sv index 70a429b16..e0551e9dc 100644 --- a/src/ieu/extend.sv +++ b/src/ieu/extend.sv @@ -30,7 +30,7 @@ module extend #(parameter XLEN, A_SUPPORTED) ( 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 - 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 @@ -45,10 +45,10 @@ module extend #(parameter XLEN, A_SUPPORTED) ( // J-type (jal) 3'b011: ImmExtD = {{(XLEN-20){InstrD[31]}}, InstrD[19:12], InstrD[20], InstrD[30:21], 1'b0}; // 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 3'b101: if (A_SUPPORTED) ImmExtD = 0; - else ImmExtD = undefined; + else ImmExtD = undefined; default: ImmExtD = undefined; // undefined endcase endmodule diff --git a/src/ieu/ieu.sv b/src/ieu/ieu.sv index daebc98f6..8e22fd864 100644 --- a/src/ieu/ieu.sv +++ b/src/ieu/ieu.sv @@ -26,7 +26,6 @@ // and limitations under the License. //////////////////////////////////////////////////////////////////////////////////////////////// - module ieu import cvw::*; #(parameter cvw_t P) ( input logic clk, reset, // Decode stage signals @@ -34,36 +33,36 @@ module ieu import cvw::*; #(parameter cvw_t P) ( input logic IllegalIEUFPUInstrD, // Illegal instruction output logic IllegalBaseInstrD, // Illegal I-type instruction, or illegal RV32 access to upper 16 registers // Execute stage signals - input logic [P.XLEN-1:0] PCE, // PC - input logic [P.XLEN-1:0] PCLinkE, // PC + 4 + input logic [P.XLEN-1:0] PCE, // PC + input logic [P.XLEN-1:0] PCLinkE, // PC + 4 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 - 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 [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 // Memory stage signals input logic SquashSCW, // Squash store conditional, from LSU output logic [1:0] MemRWM, // Read/write 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 [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 - 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 InstrValidD, InstrValidE, InstrValidM,// Instruction is valid + output logic InstrValidD, InstrValidE, InstrValidM, // Instruction is valid output logic BranchD, BranchE, output logic JumpD, JumpE, // Writeback stage signals - 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] 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] FIntDivResultW, // Integer divide result from FPU fdivsqrt) + 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] FCvtIntResW, // FPU's float to int conversion result input logic FCvtIntW, // FPU converts float to int 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 input logic StallD, StallE, StallM, StallW, // Stall signals from hazard unit input logic FlushD, FlushE, FlushM, FlushW, // Flush signals @@ -118,4 +117,3 @@ module ieu import cvw::*; #(parameter cvw_t P) ( .FCvtIntE, .SCE, .ForwardAE, .ForwardBE, .FCvtIntStallD, .LoadStallD, .MDUStallD, .CSRRdStallD); endmodule - diff --git a/src/ieu/regfile.sv b/src/ieu/regfile.sv index 5eff24022..2b76bca17 100644 --- a/src/ieu/regfile.sv +++ b/src/ieu/regfile.sv @@ -31,10 +31,10 @@ module regfile #(parameter XLEN, E_SUPPORTED) ( input logic clk, reset, 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 [XLEN-1:0] wd3, // Write data for port 3 - output logic [XLEN-1:0] rd1, rd2); // Read data for ports 1, 2 + input logic [XLEN-1:0] wd3, // Write data for port 3 + 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]; integer i; @@ -50,7 +50,7 @@ module regfile #(parameter XLEN, E_SUPPORTED) ( always_ff @(negedge clk) if (reset) for(i=1; i> Offset; assign Y = ZShift[`XLEN-1:0]; endmodule - - diff --git a/src/ifu/CodeAligner.py b/src/ifu/CodeAligner.py deleted file mode 100644 index 579fd6237..000000000 --- a/src/ifu/CodeAligner.py +++ /dev/null @@ -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) \ No newline at end of file diff --git a/src/ifu/decompress.sv b/src/ifu/decompress.sv index 582dbecbe..5ce5ab683 100644 --- a/src/ifu/decompress.sv +++ b/src/ifu/decompress.sv @@ -181,4 +181,3 @@ module decompress #(parameter XLEN)( endcase end endmodule - diff --git a/src/ifu/ifu.sv b/src/ifu/ifu.sv index f33c150d0..e47115ed1 100644 --- a/src/ifu/ifu.sv +++ b/src/ifu/ifu.sv @@ -26,116 +26,115 @@ //////////////////////////////////////////////////////////////////////////////////////////////// module ifu import cvw::*; #(parameter cvw_t P) ( - input logic clk, reset, - input logic StallF, StallD, StallE, StallM, StallW, - input logic FlushD, FlushE, FlushM, FlushW, - output logic IFUStallF, // IFU stalsl pipeline during a multicycle operation + input logic clk, reset, + input logic StallF, StallD, StallE, StallM, StallW, + input logic FlushD, FlushE, FlushM, FlushW, + output logic IFUStallF, // IFU stalsl pipeline during a multicycle operation // Command from CPU - input logic InvalidateICacheM, // Clears all instruction cache valid bits - input logic CSRWriteFenceM, // CSR write or fence instruction, PCNextF = the next valid PC (typically PCE) - input logic InstrValidD, InstrValidE, InstrValidM, - input logic BranchD, BranchE, - input logic JumpD, JumpE, + input logic InvalidateICacheM, // Clears all instruction cache valid bits + input logic CSRWriteFenceM, // CSR write or fence instruction, PCNextF = the next valid PC (typically PCE) + input logic InstrValidD, InstrValidE, InstrValidM, + input logic BranchD, BranchE, + input logic JumpD, JumpE, // Bus interface 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 IFUHREADY, // Bus ready 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] IFUHBURST, // Bus burst from IFU to EBU - output logic [1:0] IFUHTRANS, // Bus transaction type 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 [2:0] IFUHSIZE, // Bus operation size 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 [P.XLEN-1:0] PCSpillF, // PCF with possible + 2 to handle spill to HPTW // Execute 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] IEUAdrM, // The branch/jump target address output logic [P.XLEN-1:0] PCE, // Execution stage instruction address - output logic BPWrongE, // Prediction is wrong - output logic BPWrongM, // Prediction is wrong + output logic BPWrongE, // Prediction is wrong + output logic BPWrongM, // Prediction is wrong // 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. 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] 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] InstrD, // The decoded instruction in Decode 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 [P.XLEN-1:0] PCM, // Memory stage instruction address // branch predictor - 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 BTAWrongM, // Prediction target wrong - output logic RASPredPCWrongM, // RAS prediction is wrong - output logic IClassWrongM, // Class prediction is wrong - output logic ICacheStallF, // I$ busy with multicycle operation + 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 BTAWrongM, // Prediction target wrong + output logic RASPredPCWrongM, // RAS prediction is wrong + output logic IClassWrongM, // Class prediction is wrong + output logic ICacheStallF, // I$ busy with multicycle operation // Faults - input logic IllegalBaseInstrD, // Illegal non-compressed instruction - input logic IllegalFPUInstrD, // Illegal FP instruction - output logic InstrPageFaultF, // Instruction page fault - 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) + input logic IllegalBaseInstrD, // Illegal non-compressed instruction + input logic IllegalFPUInstrD, // Illegal FP instruction + output logic InstrPageFaultF, // Instruction page fault + 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) // 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 [1:0] PageType, // Hardware page table walker (HPTW) writes PageType to ITLB - input logic ITLBWriteF, // Writes PTE and 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 [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_SUM, // Status CSR: Supervisor access to user memory - input logic STATUS_MPRV, // Status CSR: modify machine privilege - input logic [1:0] STATUS_MPP, // Status CSR: previous machine privilege level - input logic sfencevmaM, // Virtual memory address fence, invalidate TLB entries - output logic ITLBMissF, // ITLB miss causes HPTW (hardware pagetable walker) walk - 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 [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 ICacheAccess, // Report I$ read to performance counters - output logic ICacheMiss // Report I$ miss to performance counters + input logic STATUS_MXR, // Status CSR: make executable page readable + input logic STATUS_SUM, // Status CSR: Supervisor access to user memory + input logic STATUS_MPRV, // Status CSR: modify machine privilege + input logic [1:0] STATUS_MPP, // Status CSR: previous machine privilege level + input logic sfencevmaM, // Virtual memory address fence, invalidate TLB entries + output logic ITLBMissF, // ITLB miss causes HPTW (hardware pagetable walker) walk + 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 [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 ICacheAccess, // Report I$ read 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 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] 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: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] 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.PA_BITS-1:0] PCPF; // Physical address after address translation - logic [P.XLEN+1:0] PCFExt; // + 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 [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] 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: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] PCF; // Fetch stage instruction address + logic [P.PA_BITS-1:0] PCPF; // Physical address after address translation + logic [P.XLEN+1:0] PCFExt; - logic [31:0] IROMInstrF; // Instruction from the IROM - logic [31:0] ICacheInstrF; // Instruction from the I$ - logic [31:0] InstrRawF; // Instruction from the IROM, I$, or bus - logic CompressedF; // The fetched instruction is compressed - logic CompressedD; // The decoded instruction is compressed - logic CompressedE; // 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] InstrRawD; // Non-decompressed instruction in the Decode stage - logic IllegalIEUInstrD; // IEU Instruction (regular or compressed) is not good + logic [31:0] IROMInstrF; // Instruction from the IROM + logic [31:0] ICacheInstrF; // Instruction from the I$ + logic [31:0] InstrRawF; // Instruction from the IROM, I$, or bus + logic CompressedF; // The fetched instruction is compressed + logic CompressedD; // The decoded instruction is compressed + logic CompressedE; // 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] InstrRawD; // Non-decompressed instruction in the Decode stage + logic IllegalIEUInstrD; // IEU Instruction (regular or compressed) is not good - logic [1:0] IFURWF; // IFU alreays read IFURWF = 10 - logic [31:0] InstrE; // Instruction in the Execution stage - logic [31:0] NextInstrD, NextInstrE; // Instruction into the next stage after possible stage flush + logic [1:0] IFURWF; // IFU alreays read IFURWF = 10 + logic [31:0] InstrE; // Instruction in the Execution stage + logic [31:0] NextInstrD, NextInstrE; // Instruction into the next stage after possible stage flush - - logic CacheableF; // PMA indicates instruction address is cacheable - logic SelSpillNextF; // In a spill, stall pipeline and gate local stallF - logic BusStall; // Bus interface busy with multicycle operation - logic IFUCacheBusStallF; // EIther I$ or bus busy with multicycle operation - logic GatedStallD; // StallD gated by selected next spill + logic CacheableF; // PMA indicates instruction address is cacheable + logic SelSpillNextF; // In a spill, stall pipeline and gate local stallF + logic BusStall; // Bus interface busy with multicycle operation + logic IFUCacheBusStallF; // EIther I$ or bus busy with multicycle operation + logic GatedStallD; // StallD gated by selected next spill // branch predictor signal - logic [P.XLEN-1:0] PC1NextF; // Branch predictor next PCF - logic BusCommittedF; // Bus memory operation in flight, delay interrupts - logic CacheCommittedF; // I$ memory operation started, delay interrupts - logic SelIROM; // PMA indicates instruction address is in the IROM - logic [15:0] InstrRawE, InstrRawM; + logic [P.XLEN-1:0] PC1NextF; // Branch predictor next PCF + logic BusCommittedF; // Bus memory operation in flight, delay interrupts + logic CacheCommittedF; // I$ memory operation started, delay interrupts + logic SelIROM; // PMA indicates instruction address is in the IROM + logic [15:0] InstrRawE, InstrRawM; assign PCFExt = {2'b00, PCSpillF}; @@ -199,6 +198,7 @@ module ifu import cvw::*; #(parameter cvw_t P) ( //////////////////////////////////////////////////////////////////////////////////////////////// // Memory //////////////////////////////////////////////////////////////////////////////////////////////// + // 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 // 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. assign CommittedF = CacheCommittedF | BusCommittedF; - logic IgnoreRequest; + logic IgnoreRequest; assign IgnoreRequest = ITLBMissF | FlushD; // 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 LOGBWPL = P.ICACHE_SUPPORTED ? $clog2(WORDSPERLINE) : 1; if(P.ICACHE_SUPPORTED) begin : icache - 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) - logic [LINELEN-1:0] FetchBuffer; + 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) + logic [LINELEN-1:0] FetchBuffer; logic [P.PA_BITS-1:0] ICacheBusAdr; - logic ICacheBusAck; - logic [1:0] CacheBusRW, BusRW, CacheRWF; + logic ICacheBusAck; + logic [1:0] CacheBusRW, BusRW, CacheRWF; assign BusRW = ~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(), .Funct3(3'b010), .HADDR(IFUHADDR), .HREADY(IFUHREADY), .HWRITE(IFUHWRITE), .CacheBusAdr(ICacheBusAdr), .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), .BusRW, .Stall(GatedStallD), .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 = {PCPlus4F, PCF[1:0]}; // add 4 - //////////////////////////////////////////////////////////////////////////////////////////////// // Branch and Jump Predictor //////////////////////////////////////////////////////////////////////////////////////////////// @@ -341,10 +340,10 @@ module ifu import cvw::*; #(parameter cvw_t P) ( assign NextValidPCE = PCE; end - //////////////////////////////////////////////////////////////////////////////////////////////// // Decode stage pipeline register and compressed instruction decoding. //////////////////////////////////////////////////////////////////////////////////////////////// + // Decode stage pipeline register and logic 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 // Cannot use flopenrc for Instr(E/M) as it resets to NOP not 0. - mux2 #(32) FlushInstrEMux(InstrD, nop, FlushE, NextInstrD); - mux2 #(32) FlushInstrMMux(InstrE, nop, FlushM, NextInstrE); - flopenr #(32) InstrEReg(clk, reset, ~StallE, NextInstrD, InstrE); - flopenr #(32) InstrMReg(clk, reset, ~StallM, NextInstrE, InstrM); + mux2 #(32) FlushInstrEMux(InstrD, nop, FlushE, NextInstrD); + mux2 #(32) FlushInstrMMux(InstrE, nop, FlushM, NextInstrE); + flopenr #(32) InstrEReg(clk, reset, ~StallE, NextInstrD, InstrE); + flopenr #(32) InstrMReg(clk, reset, ~StallM, NextInstrE, InstrM); flopenr #(P.XLEN) PCEReg(clk, reset, ~StallE, PCD, PCE); flopenr #(P.XLEN) PCMReg(clk, reset, ~StallM, PCE, PCM); //flopenr #(P.XLEN) PCPDReg(clk, reset, ~StallD, PCPlus2or4F, PCLinkD); diff --git a/src/ifu/irom.sv b/src/ifu/irom.sv index 321dd9fa8..1339c26fa 100644 --- a/src/ifu/irom.sv +++ b/src/ifu/irom.sv @@ -25,10 +25,10 @@ //////////////////////////////////////////////////////////////////////////////////////////////// module irom import cvw::*; #(parameter cvw_t P) ( - input logic clk, - input logic ce, // Chip Enable. 0: Holds IROMInstrF constant + input logic clk, + input logic ce, // Chip Enable. 0: Holds IROMInstrF constant 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 @@ -36,14 +36,13 @@ module irom import cvw::*; #(parameter cvw_t P) ( localparam OFFSET = $clog2(XLENBYTES); logic [P.XLEN-1:0] IROMInstrFFull; - logic [31:0] RawIROMInstrF; - - logic [1:0] AdrD; + logic [31:0] RawIROMInstrF; + logic [1:0] 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)); 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 // haves. Adr is the Next PCF not PCF so we delay 1 cycle. 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. assign IROMInstrF = AdrD[0] ? {16'b0, RawIROMInstrF[31:16]} : RawIROMInstrF; endmodule - diff --git a/src/ifu/spill.sv b/src/ifu/spill.sv index 27eaa4107..d499b1db3 100644 --- a/src/ifu/spill.sv +++ b/src/ifu/spill.sv @@ -32,33 +32,33 @@ `include "wally-config.vh" module spill import cvw::*; #(parameter cvw_t P) ( - input logic clk, - input logic reset, - input logic StallD, FlushD, + input logic clk, + input logic reset, + input logic StallD, FlushD, 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: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 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 InstrUpdateDAF, // Ignore memory request if the hptw support write and a DA page fault occurs (hptw is still active) + 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 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) 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 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 CompressedF); // The fetched instruction is compressed + 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 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] - typedef enum logic [1:0] {STATE_READY, STATE_SPILL} statetype; - localparam SPILLTHRESHOLD = P.ICACHE_SUPPORTED ? P.ICACHE_LINELENINBITS/32 : 1; + typedef enum logic [1:0] {STATE_READY, STATE_SPILL} statetype; + localparam SPILLTHRESHOLD = P.ICACHE_SUPPORTED ? P.ICACHE_LINELENINBITS/32 : 1; - statetype CurrState, NextState; + statetype CurrState, NextState; logic [P.XLEN-1:0] PCPlus2F; - logic TakeSpillF; - logic SpillF; - logic SelSpillF; - logic SpillSaveF; - logic [15:0] InstrFirstHalfF; + logic TakeSpillF; + logic SpillF; + logic SelSpillF; + logic SpillSaveF; + logic [15:0] InstrFirstHalfF; //////////////////////////////////////////////////////////////////////////////////////////////////// // PC logic @@ -71,7 +71,6 @@ module spill import cvw::*; #(parameter cvw_t P) ( // select between PCF and PCF+2 mux2 #(P.XLEN) pcspillmux(.d0(PCF), .d1(PCPlus2F), .s(SelSpillF), .y(PCSpillF)); - //////////////////////////////////////////////////////////////////////////////////////////////////// // Detect spill //////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/lsu/amoalu.sv b/src/lsu/amoalu.sv index 524a4cf75..c8b7ccee3 100644 --- a/src/lsu/amoalu.sv +++ b/src/lsu/amoalu.sv @@ -30,8 +30,8 @@ module amoalu import cvw::*; #(parameter cvw_t P) ( input logic [P.XLEN-1:0] ReadDataM, // LSU's ReadData input logic [P.XLEN-1:0] IHWriteDataM, // LSU's WriteData - input logic [6:0] LSUFunct7M, // ALU Operation - input logic [2:0] LSUFunct3M, // Memoy access width + input logic [6:0] LSUFunct7M, // ALU Operation + input logic [2:0] LSUFunct3M, // Memoy access width output logic [P.XLEN-1:0] AMOResultM // ALU output ); @@ -72,4 +72,3 @@ module amoalu import cvw::*; #(parameter cvw_t P) ( end end endmodule - diff --git a/src/lsu/atomic.sv b/src/lsu/atomic.sv index 5c2035699..117a42c2b 100644 --- a/src/lsu/atomic.sv +++ b/src/lsu/atomic.sv @@ -28,24 +28,24 @@ //////////////////////////////////////////////////////////////////////////////////////////////// module atomic import cvw::*; #(parameter cvw_t P) ( - input logic clk, - input logic reset, - input logic StallW, + input logic clk, + input logic reset, + 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] 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 [6:0] LSUFunct7M, // AMO alu operation gated by HPTW - 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] PreLSURWM, // IEU or HPTW Read/Write signal - input logic IgnoreRequest, // On FlushM or TLB miss ignore memory operation + input logic [6:0] LSUFunct7M, // AMO alu operation gated by HPTW + 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] PreLSURWM, // IEU or HPTW Read/Write signal + 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 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 SquashSCW, // Store conditional failed disable write to GPR + output logic [1:0] LSURWM // IEU or HPTW Read/Write signal gated by LR/SC ); logic [P.XLEN-1:0] AMOResultM; - logic MemReadM; + logic MemReadM; amoalu #(P) amoalu(.ReadDataM, .IHWriteDataM, .LSUFunct7M, .LSUFunct3M, .AMOResultM); diff --git a/src/lsu/dtim.sv b/src/lsu/dtim.sv index 36b3af1a3..896a047c2 100644 --- a/src/lsu/dtim.sv +++ b/src/lsu/dtim.sv @@ -28,17 +28,17 @@ //////////////////////////////////////////////////////////////////////////////////////////////// module dtim import cvw::*; #(parameter cvw_t P) ( - input logic clk, - input logic FlushW, - input logic ce, // Chip Enable. 0: Holds ReadDataWordM - input logic [1:0] MemRWM, // Read/Write control + input logic clk, + input logic FlushW, + input logic ce, // Chip Enable. 0: Holds ReadDataWordM + 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.LLEN-1:0] WriteDataM, // Write data from IEU 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 ); - logic we; + logic we; localparam LLENBYTES = P.LLEN/8; // verilator lint_off WIDTH @@ -52,4 +52,3 @@ module dtim import cvw::*; #(parameter cvw_t P) ( ram1p1rwbe #(.DEPTH(DEPTH), .WIDTH(P.LLEN)) ram(.clk, .ce, .we, .bwe(ByteMaskM), .addr(DTIMAdr[ADDR_WDITH+OFFSET-1:OFFSET]), .dout(ReadDataWordM), .din(WriteDataM)); endmodule - diff --git a/src/lsu/lrsc.sv b/src/lsu/lrsc.sv index a1fbe6fdb..cc6c94ba8 100644 --- a/src/lsu/lrsc.sv +++ b/src/lsu/lrsc.sv @@ -29,23 +29,23 @@ //////////////////////////////////////////////////////////////////////////////////////////////// module lrsc import cvw::*; #(parameter cvw_t P) ( - input logic clk, - input logic reset, - input logic StallW, - input logic MemReadM, // Memory read - 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 - input logic [1:0] LSUAtomicM, // Atomic memory operaiton + input logic clk, + input logic reset, + input logic StallW, + input logic MemReadM, // Memory read + 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 + input logic [1:0] LSUAtomicM, // Atomic memory operaiton 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. // Handle atomic load reserved / store conditional logic [P.PA_BITS-1:2] ReservationPAdrW; - logic ReservationValidM, ReservationValidW; - logic lrM, scM, WriteAdrMatchM; - logic SquashSCM; + logic ReservationValidM, ReservationValidW; + logic lrM, scM, WriteAdrMatchM; + logic SquashSCM; assign lrM = MemReadM & LSUAtomicM[0]; assign scM = PreLSURWM[0] & LSUAtomicM[0]; diff --git a/src/lsu/lsu.sv b/src/lsu/lsu.sv index 595f1eec4..5a4358605 100644 --- a/src/lsu/lsu.sv +++ b/src/lsu/lsu.sv @@ -30,63 +30,63 @@ ///////////////////////////////////////////////////////////////////////////////////////////////////////// module lsu import cvw::*; #(parameter cvw_t P) ( - input logic clk, reset, - input logic StallM, FlushM, StallW, FlushW, - output logic LSUStallM, // LSU stalls pipeline during a multicycle operation + input logic clk, reset, + input logic StallM, FlushM, StallW, FlushW, + output logic LSUStallM, // LSU stalls pipeline during a multicycle operation // connected to cpu (controls) - input logic [1:0] MemRWM, // Read/Write control - input logic [2:0] Funct3M, // Size of memory operation - input logic [6:0] Funct7M, // Atomic memory operation function - input logic [1:0] AtomicM, // Atomic memory operation - input logic FlushDCacheM, // Flush D cache to next level of memory - output logic CommittedM, // Delay interrupts while memory operation in flight - output logic SquashSCW, // Store conditional failed disable write to GPR - output logic DCacheMiss, // D cache miss for performance counters - output logic DCacheAccess, // D cache memory access for performance counters + input logic [1:0] MemRWM, // Read/Write control + input logic [2:0] Funct3M, // Size of memory operation + input logic [6:0] Funct7M, // Atomic memory operation function + input logic [1:0] AtomicM, // Atomic memory operation + input logic FlushDCacheM, // Flush D cache to next level of memory + output logic CommittedM, // Delay interrupts while memory operation in flight + output logic SquashSCW, // Store conditional failed disable write to GPR + output logic DCacheMiss, // D cache miss for performance counters + output logic DCacheAccess, // D cache memory access for performance counters // address and write data - input logic [P.XLEN-1:0] IEUAdrE, // Execution 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 - output logic [P.LLEN-1:0] ReadDataW, // Read data to IEU or FPU + input logic [P.XLEN-1:0] IEUAdrE, // Execution 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 + output logic [P.LLEN-1:0] ReadDataW, // Read data to IEU or FPU // cpu privilege - input logic [1:0] PrivilegeModeW, // Current privilege mode - input logic BigEndianM, // Swap byte order to big endian - input logic sfencevmaM, // Virtual memory address fence, invalidate TLB entries - output logic DCacheStallM, // D$ busy with multicycle operation + input logic [1:0] PrivilegeModeW, // Current privilege mode + input logic BigEndianM, // Swap byte order to big endian + input logic sfencevmaM, // Virtual memory address fence, invalidate TLB entries + output logic DCacheStallM, // D$ busy with multicycle operation // fpu - input logic [P.FLEN-1:0] FWriteDataM, // Write data from FPU - input logic FpLoadStoreM, // Selects FPU as store for write data + input logic [P.FLEN-1:0] FWriteDataM, // Write data from FPU + input logic FpLoadStoreM, // Selects FPU as store for write data // faults - output logic LoadPageFaultM, StoreAmoPageFaultM, // Page fault exceptions - output logic LoadMisalignedFaultM, // Load address misaligned fault - output logic LoadAccessFaultM, // Load access fault (PMA) - output logic HPTWInstrAccessFaultF, // HPTW generated access fault during instruction fetch + output logic LoadPageFaultM, StoreAmoPageFaultM, // Page fault exceptions + output logic LoadMisalignedFaultM, // Load address misaligned fault + output logic LoadAccessFaultM, // Load access fault (PMA) + output logic HPTWInstrAccessFaultF, // HPTW generated access fault during instruction fetch // cpu hazard unit (trap) - output logic StoreAmoMisalignedFaultM, // Store or AMO address misaligned fault - output logic StoreAmoAccessFaultM, // Store or AMO access fault + output logic StoreAmoMisalignedFaultM, // Store or AMO address misaligned fault + output logic StoreAmoAccessFaultM, // Store or AMO access fault // connect to ahb - 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 - output logic [P.XLEN-1:0] LSUHWDATA, // Bus write data 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 [2:0] LSUHSIZE, // Bus operation size 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 [P.XLEN/8-1:0] LSUHWSTRB, // Bus byte write enables 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 + output logic [P.XLEN-1:0] LSUHWDATA, // Bus write data 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 [2:0] LSUHSIZE, // Bus operation size 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 [P.XLEN/8-1:0] LSUHWSTRB, // Bus byte write enables from LSU to EBU // page table walker - 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 [1:0] STATUS_MPP, // Machine previous privilege mode - input logic [P.XLEN-1:0] PCSpillF, // Fetch PC - input logic ITLBMissF, // ITLB miss causes HPTW (hardware pagetable walker) walk - 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 [1:0] PageType, // Type of page table entry to write to ITLB - output logic ITLBWriteF, // Write PTE to ITLB - 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 [P.PA_BITS-3:0] PMPADDR_ARRAY_REGW[P.PMP_ENTRIES-1:0] // PMP address from privileged unit + 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 [1:0] STATUS_MPP, // Machine previous privilege mode + input logic [P.XLEN-1:0] PCSpillF, // Fetch PC + input logic ITLBMissF, // ITLB miss causes HPTW (hardware pagetable walker) walk + 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 [1:0] PageType, // Type of page table entry to write to ITLB + output logic ITLBWriteF, // Write PTE to ITLB + 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 [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 @@ -94,20 +94,20 @@ module lsu import cvw::*; #(parameter cvw_t P) ( logic [P.PA_BITS-1:0] PAdrM; // Physical 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] LSURWM; // IEU or HPTW Read/Write signal gated by LR/SC - logic [2:0] LSUFunct3M; // IEU or HPTW memory operation size - logic [6:0] LSUFunct7M; // AMO function gated by HPTW - logic [1:0] LSUAtomicM; // AMO signal gated by HPTW + 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 [2:0] LSUFunct3M; // IEU or HPTW memory operation size + logic [6:0] LSUFunct7M; // AMO function 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 HPTWStall; // HPTW busy with multicycle operation + logic BusStall; // Bus interface busy with multicycle operation + logic HPTWStall; // HPTW busy with multicycle operation - logic CacheableM; // PMA indicates memory address is cacheable - logic BusCommittedM; // Bus memory operation in flight, delay interrupts - logic DCacheCommittedM; // D$ memory operation started, delay interrupts + logic CacheableM; // PMA indicates memory address is cacheable + logic BusCommittedM; // Bus memory operation in flight, delay interrupts + logic DCacheCommittedM; // D$ memory operation started, delay interrupts logic [P.LLEN-1:0] DTIMReadDataWordM; // DTIM 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)/8:0] ByteMaskM; // Selects which bytes within a word to write - logic DTLBMissM; // DTLB miss causes HPTW walk - logic DTLBWriteM; // Writes PTE and PageType to DTLB - logic DataUpdateDAM; // DTLB hit needs to update dirty or access bits - logic LSULoadAccessFaultM; // Load acces fault - logic LSUStoreAmoAccessFaultM; // Store access fault - 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 SelDTIM; // Select DTIM rather than bus or D$ + logic DTLBMissM; // DTLB miss causes HPTW walk + logic DTLBWriteM; // Writes PTE and PageType to DTLB + logic DataUpdateDAM; // DTLB hit needs to update dirty or access bits + logic LSULoadAccessFaultM; // Load acces fault + logic LSUStoreAmoAccessFaultM; // Store access fault + 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 SelDTIM; // Select DTIM rather than bus or D$ - ///////////////////////////////////////////////////////////////////////////////////////////// // Pipeline for IEUAdr E to M // 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 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. 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.DCACHE_SUPPORTED) begin : dcache 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 AHBWLOGBWPL = $clog2(BEATSPERLINE); // Log2 of ^ - localparam LINELEN = P.DCACHE_LINELENINBITS; // Number of bits in cacheline + localparam AHBWLOGBWPL = $clog2(BEATSPERLINE); // Log2 of ^ + 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) - 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 [AHBWLOGBWPL-1:0] BeatCount; // Position within a cacheline. ahbcacheinterface to cache - logic DCacheBusAck; // ahbcacheinterface completed fetch or writeback - logic SelBusBeat; // ahbcacheinterface selects postion in cacheline with BeatCount - logic [1:0] CacheBusRW; // Cache sends request to ahbcacheinterface - logic [1:0] BusRW; // Uncached bus memory access - 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] CacheAtomicM; // Cache AMO - logic FlushDCache; // Suppress d cache flush if there is an ITLB miss. + 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 [AHBWLOGBWPL-1:0] BeatCount; // Position within a cacheline. ahbcacheinterface to cache + logic DCacheBusAck; // ahbcacheinterface completed fetch or writeback + logic SelBusBeat; // ahbcacheinterface selects postion in cacheline with BeatCount + logic [1:0] CacheBusRW; // Cache sends request to ahbcacheinterface + logic [1:0] BusRW; // Uncached bus memory access + 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] CacheAtomicM; // Cache AMO + logic FlushDCache; // Suppress d cache flush if there is an ITLB miss. assign BusRW = ~CacheableM & ~IgnoreRequestTLB & ~SelDTIM ? LSURWM : '0; assign CacheableOrFlushCacheM = CacheableM | FlushDCacheM; @@ -320,6 +319,7 @@ module lsu import cvw::*; #(parameter cvw_t P) ( ///////////////////////////////////////////////////////////////////////////////////////////// // Atomic operations ///////////////////////////////////////////////////////////////////////////////////////////// + if (P.A_SUPPORTED) begin:atomic atomic #(P) atomic(.clk, .reset, .StallW, .ReadDataM(ReadDataM[P.XLEN-1:0]), .IHWriteDataM, .PAdrM, .LSUFunct7M, .LSUFunct3M, .LSUAtomicM, .PreLSURWM, .IgnoreRequest, @@ -335,6 +335,7 @@ module lsu import cvw::*; #(parameter cvw_t P) ( ///////////////////////////////////////////////////////////////////////////////////////////// // Subword Accesses ///////////////////////////////////////////////////////////////////////////////////////////// + subwordread #(P.LLEN) subwordread(.ReadDataWordMuxM(LittleEndianReadDataWordM), .PAdrM(PAdrM[2:0]), .BigEndianM, .FpLoadStoreM, .Funct3M(LSUFunct3M), .ReadDataM); subwordwrite #(P.LLEN) subwordwrite(.LSUFunct3M, .IMAFWriteDataM, .LittleEndianWriteDataM); @@ -361,5 +362,4 @@ module lsu import cvw::*; #(parameter cvw_t P) ( assign LSUWriteDataM = LittleEndianWriteDataM; assign LittleEndianReadDataWordM = ReadDataWordMuxM; end - endmodule diff --git a/src/lsu/subwordread.sv b/src/lsu/subwordread.sv index 4c529ec07..e5666eb84 100644 --- a/src/lsu/subwordread.sv +++ b/src/lsu/subwordread.sv @@ -29,12 +29,12 @@ 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] Funct3M, input logic FpLoadStoreM, input logic BigEndianM, - output logic [LLEN-1:0] ReadDataM + output logic [LLEN-1:0] ReadDataM ); 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'b101: ReadDataM = {{LLEN-16{1'b0}}, HalfwordM[15:0]}; // lhu 3'b110: ReadDataM = {{LLEN-32{1'b0}}, WordM[31:0]}; // lwu - default: ReadDataM = ReadDataWordMuxM; // Shouldn't happen + default: ReadDataM = ReadDataWordMuxM; // Shouldn't happen endcase end else begin:swrmux // 32-bit diff --git a/src/lsu/subwordwrite.sv b/src/lsu/subwordwrite.sv index f53f121e7..ad21b3c25 100644 --- a/src/lsu/subwordwrite.sv +++ b/src/lsu/subwordwrite.sv @@ -28,8 +28,8 @@ //////////////////////////////////////////////////////////////////////////////////////////////// module subwordwrite #(parameter LLEN) ( - input logic [2:0] LSUFunct3M, - input logic [LLEN-1:0] IMAFWriteDataM, + input logic [2:0] LSUFunct3M, + input logic [LLEN-1:0] IMAFWriteDataM, output logic [LLEN-1:0] LittleEndianWriteDataM ); @@ -46,18 +46,18 @@ module subwordwrite #(parameter LLEN) ( end else if (LLEN == 64) begin:sww always_comb case(LSUFunct3M[1:0]) - 2'b00: LittleEndianWriteDataM = {8{IMAFWriteDataM[7:0]}}; // sb - 2'b01: LittleEndianWriteDataM = {4{IMAFWriteDataM[15:0]}}; // sh - 2'b10: LittleEndianWriteDataM = {2{IMAFWriteDataM[31:0]}}; // sw - 2'b11: LittleEndianWriteDataM = IMAFWriteDataM; // sd + 2'b00: LittleEndianWriteDataM = {8{IMAFWriteDataM[7:0]}}; // sb + 2'b01: LittleEndianWriteDataM = {4{IMAFWriteDataM[15:0]}}; // sh + 2'b10: LittleEndianWriteDataM = {2{IMAFWriteDataM[31:0]}}; // sw + 2'b11: LittleEndianWriteDataM = IMAFWriteDataM; // sd endcase end else begin:sww // 32-bit always_comb case(LSUFunct3M[1:0]) - 2'b00: LittleEndianWriteDataM = {4{IMAFWriteDataM[7:0]}}; // sb - 2'b01: LittleEndianWriteDataM = {2{IMAFWriteDataM[15:0]}}; // sh - 2'b10: LittleEndianWriteDataM = IMAFWriteDataM; // sw - default: LittleEndianWriteDataM = IMAFWriteDataM; // shouldn't happen + 2'b00: LittleEndianWriteDataM = {4{IMAFWriteDataM[7:0]}}; // sb + 2'b01: LittleEndianWriteDataM = {2{IMAFWriteDataM[15:0]}}; // sh + 2'b10: LittleEndianWriteDataM = IMAFWriteDataM; // sw + default: LittleEndianWriteDataM = IMAFWriteDataM; // shouldn't happen endcase end endmodule diff --git a/src/lsu/swbytemask.sv b/src/lsu/swbytemask.sv index 51076fc7d..ad20a4414 100644 --- a/src/lsu/swbytemask.sv +++ b/src/lsu/swbytemask.sv @@ -28,9 +28,9 @@ //////////////////////////////////////////////////////////////////////////////////////////////// module swbytemask #(parameter WORDLEN)( - input logic [2:0] Size, - input logic [$clog2(WORDLEN/8)-1:0] Adr, - output logic [WORDLEN/8-1:0] ByteMask + input logic [2:0] Size, + input logic [$clog2(WORDLEN/8)-1:0] Adr, + output logic [WORDLEN/8-1:0] ByteMask ); assign ByteMask = ((2**(2**Size))-1) << Adr; diff --git a/src/mdu/div.sv b/src/mdu/div.sv index a05e88f6d..a6eb0a686 100644 --- a/src/mdu/div.sv +++ b/src/mdu/div.sv @@ -27,38 +27,38 @@ //////////////////////////////////////////////////////////////////////////////////////////////// module div import cvw::*; #(parameter cvw_t P) ( - input logic clk, - input logic reset, - input logic StallM, - input logic FlushE, - input logic IntDivE, // integer division/remainder instruction of any type - input logic DivSignedE, // signed division - 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 - output logic DivBusyE, // Divide is busy - stall pipeline - output logic [P.XLEN-1:0] QuotM, RemM // Quotient and remainder outputs + input logic clk, + input logic reset, + input logic StallM, + input logic FlushE, + input logic IntDivE, // integer division/remainder instruction of any type + input logic DivSignedE, // signed division + 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 + output logic DivBusyE, // Divide is busy - stall pipeline + output logic [P.XLEN-1:0] QuotM, RemM // Quotient and remainder outputs ); 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; 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] 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] DnE; // DnE = ~DinE - 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] XnE; // DXnE = ~XinE - 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 [STEPBITS:0] step; // division step - logic Div0E, Div0M; // divide by 0 - logic DivStartE; // start integer division - logic SignXE, SignDE; // sign of dividend and divisor - logic NegQE, NegWM, NegQM; // negate quotient or residual during postprocessing + 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] DnE; // DnE = ~DinE + 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] XnE; // DXnE = ~XinE + 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 [STEPBITS:0] step; // division step + logic Div0E, Div0M; // divide by 0 + logic DivStartE; // start integer division + logic SignXE, SignDE; // sign of dividend and divisor + 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 @@ -131,7 +131,7 @@ module div import cvw::*; #(parameter cvw_t P) ( step <= 1; if (Div0E) state <= DONE; 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 state <= DONE; end diff --git a/src/mdu/mdu.sv b/src/mdu/mdu.sv index 1736c966a..72a908698 100644 --- a/src/mdu/mdu.sv +++ b/src/mdu/mdu.sv @@ -27,21 +27,21 @@ //////////////////////////////////////////////////////////////////////////////////////////////// module mdu import cvw::*; #(parameter cvw_t P) ( - input logic clk, reset, - input logic StallM, StallW, - input logic FlushE, FlushM, FlushW, + input logic clk, reset, + input logic StallM, StallW, + input logic FlushE, FlushM, FlushW, 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 IntDivE, W64E, // Integer division/remainder, and W-type instrutions + input logic [2:0] Funct3E, Funct3M, // type of MDU operation + input logic IntDivE, W64E, // Integer division/remainder, and W-type instrutions 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-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] MDUResultM; // result after W truncation - logic W64M; // W-type instruction + logic W64M; // W-type instruction // Multiplier 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 case (Funct3M) 3'b000: PrelimResultM = ProdM[P.XLEN-1:0]; // mul - 3'b001: PrelimResultM = ProdM[P.XLEN*2-1:P.XLEN]; // mulh - 3'b010: PrelimResultM = ProdM[P.XLEN*2-1:P.XLEN]; // mulhsu - 3'b011: PrelimResultM = ProdM[P.XLEN*2-1:P.XLEN]; // mulhu - 3'b100: PrelimResultM = QuotM; // div - 3'b101: PrelimResultM = QuotM; // divu - 3'b110: PrelimResultM = RemM; // rem - 3'b111: PrelimResultM = RemM; // remu + 3'b001: PrelimResultM = ProdM[P.XLEN*2-1:P.XLEN]; // mulh + 3'b010: PrelimResultM = ProdM[P.XLEN*2-1:P.XLEN]; // mulhsu + 3'b011: PrelimResultM = ProdM[P.XLEN*2-1:P.XLEN]; // mulhu + 3'b100: PrelimResultM = QuotM; // div + 3'b101: PrelimResultM = QuotM; // divu + 3'b110: PrelimResultM = RemM; // rem + 3'b111: PrelimResultM = RemM; // remu endcase // Handle sign extension for W-type instructions @@ -84,5 +84,3 @@ module mdu import cvw::*; #(parameter cvw_t P) ( // Writeback stage pipeline register flopenrc #(P.XLEN) MDUResultWReg(clk, reset, FlushW, ~StallW, MDUResultM, MDUResultW); endmodule // mdu - - diff --git a/src/mdu/mul.sv b/src/mdu/mul.sv index 4fe64a246..a5946b95c 100644 --- a/src/mdu/mul.sv +++ b/src/mdu/mul.sv @@ -29,9 +29,9 @@ module mul #(parameter XLEN) ( input logic clk, reset, 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 - output logic [XLEN*2-1:0] ProdM // double-widthproduct + output logic [XLEN*2-1:0] ProdM // double-widthproduct ); // Number systems @@ -48,12 +48,12 @@ module mul #(parameter XLEN) ( // Signed * 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 [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 [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] PP1E, PP2E, PP3E, PP4E; // partial products + logic [XLEN*2-1:0] PP1M, PP2M, PP3M, PP4M; // registered partial proudcts ////////////////////////////// // 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 assign ProdM = PP1M + PP2M + PP3M + PP4M; //ForwardedSrcAE * ForwardedSrcBE; endmodule - diff --git a/src/mmu/adrdec.sv b/src/mmu/adrdec.sv index d2d2a1740..492d55372 100644 --- a/src/mmu/adrdec.sv +++ b/src/mmu/adrdec.sv @@ -27,8 +27,8 @@ //////////////////////////////////////////////////////////////////////////////////////////////// module adrdec #(parameter PA_BITS) ( - 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] PhysicalAddress, // Physical address to decode + input logic [PA_BITS-1:0] Base, Range, // Base and range of peripheral addresses input logic Supported, // Is this peripheral supported? input logic AccessValid, // Is the access type valid? 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 assign Sel = Match & Supported & AccessValid & SizeValid; endmodule - diff --git a/src/mmu/adrdecs.sv b/src/mmu/adrdecs.sv index feda0d40b..fd15cdd8b 100644 --- a/src/mmu/adrdecs.sv +++ b/src/mmu/adrdecs.sv @@ -30,12 +30,12 @@ module adrdecs import cvw::*; #(parameter cvw_t P) ( input logic [P.PA_BITS-1:0] PhysicalAddress, - input logic AccessRW, AccessRX, AccessRWX, - input logic [1:0] Size, - output logic [10:0] SelRegions + input logic AccessRW, AccessRX, AccessRWX, + input logic [1:0] Size, + 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 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]); diff --git a/src/mmu/hptw.sv b/src/mmu/hptw.sv index 244bd2cbd..029c718df 100644 --- a/src/mmu/hptw.sv +++ b/src/mmu/hptw.sv @@ -30,39 +30,39 @@ /////////////////////////////////////////// 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] PCSpillF, // 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 - input logic STATUS_MXR, STATUS_SUM, STATUS_MPRV, - input logic [1:0] STATUS_MPP, - input logic [1:0] PrivilegeModeW, + input logic STATUS_MXR, STATUS_SUM, STATUS_MPRV, + input logic [1:0] STATUS_MPP, + input logic [1:0] PrivilegeModeW, input logic [P.XLEN-1:0] ReadDataM, // page table entry from LSU input logic [P.XLEN-1:0] WriteDataM, - input logic DCacheStallM, // stall from LSU - input logic [2:0] Funct3M, - input logic [6:0] Funct7M, - input logic ITLBMissF, - input logic DTLBMissM, - input logic FlushW, - input logic InstrUpdateDAF, - input logic DataUpdateDAM, + input logic DCacheStallM, // stall from LSU + input logic [2:0] Funct3M, + input logic [6:0] Funct7M, + input logic ITLBMissF, + input logic DTLBMissM, + input logic FlushW, + input logic InstrUpdateDAF, + input logic DataUpdateDAM, output logic [P.XLEN-1:0] PTE, // page table entry to TLBs - output logic [1:0] PageType, // page type to TLBs - output logic ITLBWriteF, DTLBWriteM, // write TLB with new entry - output logic [1:0] PreLSURWM, + output logic [1:0] PageType, // page type to TLBs + output logic ITLBWriteF, DTLBWriteM, // write TLB with new entry + output logic [1:0] PreLSURWM, output logic [P.XLEN+1:0] IHAdrM, output logic [P.XLEN-1:0] IHWriteDataM, - output logic [1:0] LSUAtomicM, - output logic [2:0] LSUFunct3M, - output logic [6:0] LSUFunct7M, - output logic IgnoreRequestTLB, - output logic SelHPTW, - output logic HPTWStall, - input logic LSULoadAccessFaultM, LSUStoreAmoAccessFaultM, - output logic LoadAccessFaultM, StoreAmoAccessFaultM, HPTWInstrAccessFaultF + output logic [1:0] LSUAtomicM, + output logic [2:0] LSUFunct3M, + output logic [6:0] LSUFunct7M, + output logic IgnoreRequestTLB, + output logic SelHPTW, + output logic HPTWStall, + input logic LSULoadAccessFaultM, LSUStoreAmoAccessFaultM, + output logic LoadAccessFaultM, StoreAmoAccessFaultM, HPTWInstrAccessFaultF ); 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, 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] CurrentPPN; - logic Executable, Writable, Readable, Valid, PTE_U; - logic Misaligned, MegapageMisaligned; - logic ValidPTE, LeafPTE, ValidLeafPTE, ValidNonLeafPTE; - logic StartWalk; - logic TLBMiss; - logic PRegEn; - logic [1:0] NextPageType; + logic Executable, Writable, Readable, Valid, PTE_U; + logic Misaligned, MegapageMisaligned; + logic ValidPTE, LeafPTE, ValidLeafPTE, ValidNonLeafPTE; + logic StartWalk; + logic TLBMiss; + logic PRegEn; + logic [1:0] NextPageType; logic [P.SVMODE_BITS-1:0] SvMode; logic [P.XLEN-1:0] TranslationVAdr; logic [P.XLEN-1:0] NextPTE; - logic UpdatePTE; - logic HPTWUpdateDA; + logic UpdatePTE; + logic HPTWUpdateDA; logic [P.PA_BITS-1:0] HPTWReadAdr; - logic SelHPTWAdr; + logic SelHPTWAdr; logic [P.XLEN+1:0] HPTWAdrExt; - logic ITLBMissOrUpdateDAF; - logic DTLBMissOrUpdateDAM; - logic LSUAccessFaultM; + logic ITLBMissOrUpdateDAF; + logic DTLBMissOrUpdateDAM; + logic LSUAccessFaultM; logic [P.PA_BITS-1:0] HPTWAdr; - logic [1:0] HPTWRW; - logic [2:0] HPTWSize; // 32 or 64 bit access - statetype WalkerState, NextWalkerState, InitialWalkerState; - logic HPTWLoadAccessFault, HPTWStoreAmoAccessFault, HPTWInstrAccessFault; - logic HPTWLoadAccessFaultDelay, HPTWStoreAmoAccessFaultDelay, HPTWInstrAccessFaultDelay; - logic HPTWAccessFaultDelay; - logic TakeHPTWFault, TakeHPTWFaultDelay; + logic [1:0] HPTWRW; + logic [2:0] HPTWSize; // 32 or 64 bit access + statetype WalkerState, NextWalkerState, InitialWalkerState; + logic HPTWLoadAccessFault, HPTWStoreAmoAccessFault, HPTWInstrAccessFault; + logic HPTWLoadAccessFaultDelay, HPTWStoreAmoAccessFaultDelay, HPTWInstrAccessFaultDelay; + logic HPTWAccessFaultDelay; + logic TakeHPTWFault, TakeHPTWFaultDelay; // map hptw access faults onto either the original LSU load/store fault or instruction access fault - assign LSUAccessFaultM = LSULoadAccessFaultM | LSUStoreAmoAccessFaultM; - assign HPTWLoadAccessFault = LSUAccessFaultM & DTLBWalk & MemRWM[1] & ~MemRWM[0]; + assign LSUAccessFaultM = LSULoadAccessFaultM | LSUStoreAmoAccessFaultM; + assign HPTWLoadAccessFault = LSUAccessFaultM & DTLBWalk & MemRWM[1] & ~MemRWM[0]; assign HPTWStoreAmoAccessFault = LSUAccessFaultM & DTLBWalk & MemRWM[0]; assign HPTWInstrAccessFault = LSUAccessFaultM & ~DTLBWalk; @@ -140,16 +140,16 @@ module hptw import cvw::*; #(parameter cvw_t P) ( assign ValidNonLeafPTE = ValidPTE & ~LeafPTE; if(P.SVADU_SUPPORTED) begin : hptwwrites - logic ReadAccess, WriteAccess; - logic InvalidRead, InvalidWrite, InvalidOp; - logic UpperBitsUnequal; - logic OtherPageFault; - logic [1:0] EffectivePrivilegeMode; - logic ImproperPrivilege; - logic SaveHPTWAdr, SelHPTWWriteAdr; + logic ReadAccess, WriteAccess; + logic InvalidRead, InvalidWrite, InvalidOp; + logic UpperBitsUnequal; + logic OtherPageFault; + logic [1:0] EffectivePrivilegeMode; + logic ImproperPrivilege; + logic SaveHPTWAdr, SelHPTWWriteAdr; logic [P.PA_BITS-1:0] HPTWWriteAdr; - logic SetDirty; - logic Dirty, Accessed; + logic SetDirty; + logic Dirty, Accessed; 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 @@ -194,8 +194,8 @@ module hptw import cvw::*; #(parameter cvw_t P) ( end // Enable and select signals based on states - assign StartWalk = (WalkerState == IDLE) & TLBMiss; - assign HPTWRW[1] = (WalkerState == L3_RD) | (WalkerState == L2_RD) | (WalkerState == L1_RD) | (WalkerState == L0_RD); + assign StartWalk = (WalkerState == IDLE) & TLBMiss; + assign HPTWRW[1] = (WalkerState == L3_RD) | (WalkerState == L2_RD) | (WalkerState == L1_RD) | (WalkerState == L0_RD); assign DTLBWriteM = (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 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 #(3) sizemux(Funct3M, HPTWSize, SelHPTW, LSUFunct3M); mux2 #(7) funct7mux(Funct7M, 7'b0, SelHPTW, LSUFunct7M); diff --git a/src/mmu/mmu.sv b/src/mmu/mmu.sv index f095d9986..f05073fcf 100644 --- a/src/mmu/mmu.sv +++ b/src/mmu/mmu.sv @@ -28,48 +28,48 @@ module mmu import cvw::*; #(parameter cvw_t P, parameter TLB_ENTRIES = 8, IMMU = 0) ( - input logic clk, reset, - 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_SUM, // Status CSR: Supervisor access to user memory - 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] 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 [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 [P.XLEN-1:0] PTE, // page table entry - input logic [1:0] PageTypeWriteVal, // page type - input logic TLBWrite, // write TLB entry - input logic TLBFlush, // Invalidate all TLB entries + input logic clk, reset, + 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_SUM, // Status CSR: Supervisor access to user memory + 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] 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 [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 [P.XLEN-1:0] PTE, // page table entry + input logic [1:0] PageTypeWriteVal, // page type + input logic TLBWrite, // write TLB entry + 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 TLBMiss, // Miss TLB - output logic Cacheable, // PMA indicates memory address is cachable - output logic Idempotent, // PMA indicates memory address is idempotent - output logic SelTIM, // Select a tightly integrated memory + output logic TLBMiss, // Miss TLB + output logic Cacheable, // PMA indicates memory address is cachable + output logic Idempotent, // PMA indicates memory address is idempotent + output logic SelTIM, // Select a tightly integrated memory // Faults - output logic InstrAccessFaultF, LoadAccessFaultM, StoreAmoAccessFaultM, // access fault sources - output logic InstrPageFaultF, LoadPageFaultM, StoreAmoPageFaultM, // page fault sources - output logic UpdateDA, // page fault due to setting dirty or access bit - output logic LoadMisalignedFaultM, StoreAmoMisalignedFaultM, // misaligned fault sources + output logic InstrAccessFaultF, LoadAccessFaultM, StoreAmoAccessFaultM, // access fault sources + output logic InstrPageFaultF, LoadPageFaultM, StoreAmoPageFaultM, // page fault sources + output logic UpdateDA, // page fault due to setting dirty or access bit + output logic LoadMisalignedFaultM, StoreAmoMisalignedFaultM, // misaligned fault sources // PMA checker signals - 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 [P.PA_BITS-3:0] PMPADDR_ARRAY_REGW[P.PMP_ENTRIES-1:0] // PMP addresses + 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 [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 PMAInstrAccessFaultF; // Instruction access fault from PMA - logic PMPInstrAccessFaultF; // Instruction access fault from PMP - logic PMALoadAccessFaultM; // Load access fault from PMA - logic PMPLoadAccessFaultM; // Load access fault from PMP - logic PMAStoreAmoAccessFaultM; // Store or AMO access fault from PMA - logic PMPStoreAmoAccessFaultM; // Store or AMO access fault from PMP - logic DataMisalignedM; // load or store misaligned - logic Translate; // Translation occurs when virtual memory is active and DisableTranslation is off - logic TLBHit; // Hit in TLB - logic TLBPageFault; // Page fault from TLB - logic ReadNoAmoAccessM; // Read that is not part of atomic operation causes Load faults. Otherwise StoreAmo faults + logic [P.PA_BITS-1:0] TLBPAdr; // physical address for TLB + logic PMAInstrAccessFaultF; // Instruction access fault from PMA + logic PMPInstrAccessFaultF; // Instruction access fault from PMP + logic PMALoadAccessFaultM; // Load access fault from PMA + logic PMPLoadAccessFaultM; // Load access fault from PMP + logic PMAStoreAmoAccessFaultM; // Store or AMO access fault from PMA + logic PMPStoreAmoAccessFaultM; // Store or AMO access fault from PMP + logic DataMisalignedM; // load or store misaligned + logic Translate; // Translation occurs when virtual memory is active and DisableTranslation is off + logic TLBHit; // Hit in TLB + logic TLBPageFault; // Page fault from TLB + logic ReadNoAmoAccessM; // Read that is not part of atomic operation causes Load faults. Otherwise StoreAmo faults // only instantiate TLB if Virtual Memory is supported if (P.VIRTMEM_SUPPORTED) begin:tlb @@ -86,9 +86,9 @@ module mmu import cvw::*; #(parameter cvw_t P, .TLBWrite, .TLBFlush, .TLBPAdr, .TLBMiss, .TLBHit, .Translate, .TLBPageFault, .UpdateDA); end else begin:tlb // just pass address through as physical - assign Translate = 0; - assign TLBMiss = 0; - assign TLBHit = 1; // *** is this necessary + assign Translate = 0; + assign TLBMiss = 0; + assign TLBHit = 1; // *** is this necessary assign TLBPageFault = 0; end diff --git a/src/mmu/pmachecker.sv b/src/mmu/pmachecker.sv index e39915a32..41d8f9b74 100644 --- a/src/mmu/pmachecker.sv +++ b/src/mmu/pmachecker.sv @@ -30,26 +30,26 @@ module pmachecker import cvw::*; #(parameter cvw_t P) ( input logic [P.PA_BITS-1:0] PhysicalAddress, - input logic [1:0] Size, - input logic AtomicAccessM, // Atomic access - input logic ExecuteAccessF, // Execute access - input logic WriteAccessM, // Write access - input logic ReadAccessM, // Read access - output logic Cacheable, Idempotent, SelTIM, - output logic PMAInstrAccessFaultF, - output logic PMALoadAccessFaultM, - output logic PMAStoreAmoAccessFaultM + input logic [1:0] Size, + input logic AtomicAccessM, // Atomic access + input logic ExecuteAccessF, // Execute access + input logic WriteAccessM, // Write access + input logic ReadAccessM, // Read access + output logic Cacheable, Idempotent, SelTIM, + output logic PMAInstrAccessFaultF, + output logic PMALoadAccessFaultM, + output logic PMAStoreAmoAccessFaultM ); - logic PMAAccessFault; - logic AccessRW, AccessRWX, AccessRX; - logic [10:0] SelRegions; - logic AtomicAllowed; + logic PMAAccessFault; + logic AccessRW, AccessRWX, AccessRX; + logic [10:0] SelRegions; + logic AtomicAllowed; // Determine what type of access is being made - assign AccessRW = ReadAccessM | WriteAccessM; + assign AccessRW = ReadAccessM | WriteAccessM; assign AccessRWX = ReadAccessM | WriteAccessM | ExecuteAccessF; - assign AccessRX = ReadAccessM | ExecuteAccessF; + assign AccessRX = ReadAccessM | ExecuteAccessF; // Determine which region of physical memory (if any) is being accessed 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 // Detect access faults - assign PMAAccessFault = (SelRegions[0]) & AccessRWX | AtomicAccessM & ~AtomicAllowed; - assign PMAInstrAccessFaultF = ExecuteAccessF & PMAAccessFault; - assign PMALoadAccessFaultM = ReadAccessM & PMAAccessFault; + assign PMAAccessFault = (SelRegions[0]) & AccessRWX | AtomicAccessM & ~AtomicAllowed; + assign PMAInstrAccessFaultF = ExecuteAccessF & PMAAccessFault; + assign PMALoadAccessFaultM = ReadAccessM & PMAAccessFault; assign PMAStoreAmoAccessFaultM = WriteAccessM & PMAAccessFault; endmodule - diff --git a/src/mmu/pmpadrdec.sv b/src/mmu/pmpadrdec.sv index 4c8e1d002..9f283772d 100644 --- a/src/mmu/pmpadrdec.sv +++ b/src/mmu/pmpadrdec.sv @@ -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 // implementation will not detect the failure. endmodule - diff --git a/src/mmu/pmpchecker.sv b/src/mmu/pmpchecker.sv index 0b4cec4a1..fd1243031 100644 --- a/src/mmu/pmpchecker.sv +++ b/src/mmu/pmpchecker.sv @@ -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, // which we might not intend. 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, output logic PMPInstrAccessFaultF, 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 - 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] 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] PAgePMPAdr; // for TOR PMP matching, PhysicalAddress > PMPAdr[i] + 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] 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] 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 pmpadrdec #(P) pmpadrdecs[P.PMP_ENTRIES-1:0]( diff --git a/src/privileged/csr.sv b/src/privileged/csr.sv index 7bf2bf7d5..fba8a89c5 100644 --- a/src/privileged/csr.sv +++ b/src/privileged/csr.sv @@ -29,66 +29,66 @@ //////////////////////////////////////////////////////////////////////////////////////////////// module csr import cvw::*; #(parameter cvw_t P) ( - input logic clk, reset, - input logic FlushM, FlushW, - input logic StallE, StallM, StallW, - 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 [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 CSRReadM, CSRWriteM, // read or write CSR - input logic TrapM, // trap is occurring - 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 InterruptM, // interrupt is occurring - input logic ExceptionM, // interrupt is occurring - input logic MTimerInt, // timer interrupt - input logic MExtInt, SExtInt, // external interrupt (from PLIC) - input logic MSwInt, // software interrupt - input logic [63:0] MTIME_CLINT, // TIME value from CLINT - input logic InstrValidM, // current instruction is valid - 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 [1:0] NextPrivilegeModeM, // STATUS bits updated based on next privilege mode - input logic [1:0] PrivilegeModeW, // current privilege mode - input logic [3:0] CauseM, // Trap cause - input logic SelHPTW, // hardware page table walker active, so base endianness on supervisor mode + input logic clk, reset, + input logic FlushM, FlushW, + input logic StallE, StallM, StallW, + 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 [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 CSRReadM, CSRWriteM, // read or write CSR + input logic TrapM, // trap is occurring + 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 InterruptM, // interrupt is occurring + input logic ExceptionM, // interrupt is occurring + input logic MTimerInt, // timer interrupt + input logic MExtInt, SExtInt, // external interrupt (from PLIC) + input logic MSwInt, // software interrupt + input logic [63:0] MTIME_CLINT, // TIME value from CLINT + input logic InstrValidM, // current instruction is valid + 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 [1:0] NextPrivilegeModeM, // STATUS bits updated based on next privilege mode + input logic [1:0] PrivilegeModeW, // current privilege mode + input logic [3:0] CauseM, // Trap cause + input logic SelHPTW, // hardware page table walker active, so base endianness on supervisor mode // inputs for performance counters - input logic LoadStallD, - input logic StoreStallD, - input logic ICacheStallF, - input logic DCacheStallM, - input logic BPDirPredWrongM, - input logic BTAWrongM, - input logic RASPredPCWrongM, - input logic IClassWrongM, - input logic BPWrongM, // branch predictor is wrong - input logic [3:0] InstrClassM, - input logic DCacheMiss, - input logic DCacheAccess, - input logic ICacheMiss, - input logic ICacheAccess, - input logic sfencevmaM, - input logic InvalidateICacheM, - input logic DivBusyE, // integer divide busy - input logic FDivBusyE, // floating point divide busy + input logic LoadStallD, + input logic StoreStallD, + input logic ICacheStallF, + input logic DCacheStallM, + input logic BPDirPredWrongM, + input logic BTAWrongM, + input logic RASPredPCWrongM, + input logic IClassWrongM, + input logic BPWrongM, // branch predictor is wrong + input logic [3:0] InstrClassM, + input logic DCacheMiss, + input logic DCacheAccess, + input logic ICacheMiss, + input logic ICacheAccess, + input logic sfencevmaM, + input logic InvalidateICacheM, + input logic DivBusyE, // integer divide busy + input logic FDivBusyE, // floating point divide busy // outputs from CSRs - output logic [1:0] STATUS_MPP, - output logic STATUS_SPP, STATUS_TSR, STATUS_TVM, - output logic [15:0] MEDELEG_REGW, - output logic [P.XLEN-1:0] SATP_REGW, - output logic [11:0] MIP_REGW, MIE_REGW, MIDELEG_REGW, - output logic STATUS_MIE, STATUS_SIE, - output logic STATUS_MXR, STATUS_SUM, STATUS_MPRV, STATUS_TW, - output logic [1:0] STATUS_FS, - output var logic [7:0] PMPCFG_ARRAY_REGW[P.PMP_ENTRIES-1:0], + output logic [1:0] STATUS_MPP, + output logic STATUS_SPP, STATUS_TSR, STATUS_TVM, + output logic [15:0] MEDELEG_REGW, + output logic [P.XLEN-1:0] SATP_REGW, + output logic [11:0] MIP_REGW, MIE_REGW, MIDELEG_REGW, + output logic STATUS_MIE, STATUS_SIE, + output logic STATUS_MXR, STATUS_SUM, STATUS_MPRV, STATUS_TW, + output logic [1:0] STATUS_FS, + 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 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] 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 BigEndianM // memory access is big-endian based on privilege mode and STATUS register endian fields + 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 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 ); localparam MIP = 12'h344; @@ -180,13 +180,13 @@ module csr import cvw::*; #(parameter cvw_t P) ( else CSRReadVal2M = CSRReadValM; // Compute AND/OR modification - CSRRWM = CSRSrcM; - CSRRSM = CSRReadVal2M | CSRSrcM; - CSRRCM = CSRReadVal2M & ~CSRSrcM; + CSRRWM = CSRSrcM; + CSRRSM = CSRReadVal2M | CSRSrcM; + CSRRCM = CSRReadVal2M & ~CSRSrcM; case (InstrM[13:12]) - 2'b01: CSRWriteValM = CSRRWM; - 2'b10: CSRWriteValM = CSRRSM; - 2'b11: CSRWriteValM = CSRRCM; + 2'b01: CSRWriteValM = CSRRWM; + 2'b10: CSRWriteValM = CSRRSM; + 2'b11: CSRWriteValM = CSRRCM; default: CSRWriteValM = CSRReadValM; endcase end diff --git a/src/privileged/csrc.sv b/src/privileged/csrc.sv index f6f228dd8..0ee13d865 100644 --- a/src/privileged/csrc.sv +++ b/src/privileged/csrc.sv @@ -1,5 +1,3 @@ - - /////////////////////////////////////////// // csrc.sv // @@ -31,57 +29,57 @@ //////////////////////////////////////////////////////////////////////////////////////////////// module csrc import cvw::*; #(parameter cvw_t P) ( - input logic clk, reset, - input logic StallE, StallM, - input logic FlushM, - input logic InstrValidNotFlushedM, LoadStallD, StoreStallD, - input logic CSRMWriteM, CSRWriteM, - input logic BPDirPredWrongM, - input logic BTAWrongM, - input logic RASPredPCWrongM, - input logic IClassWrongM, - input logic BPWrongM, // branch predictor is wrong - input logic [3:0] InstrClassM, - input logic DCacheMiss, - input logic DCacheAccess, - input logic ICacheMiss, - input logic ICacheAccess, - input logic ICacheStallF, - input logic DCacheStallM, - input logic sfencevmaM, - input logic InterruptM, - input logic ExceptionM, - input logic InvalidateICacheM, - input logic DivBusyE, // integer divide busy - input logic FDivBusyE, // floating point divide busy - input logic [11:0] CSRAdrM, - input logic [1:0] PrivilegeModeW, + input logic clk, reset, + input logic StallE, StallM, + input logic FlushM, + input logic InstrValidNotFlushedM, LoadStallD, StoreStallD, + input logic CSRMWriteM, CSRWriteM, + input logic BPDirPredWrongM, + input logic BTAWrongM, + input logic RASPredPCWrongM, + input logic IClassWrongM, + input logic BPWrongM, // branch predictor is wrong + input logic [3:0] InstrClassM, + input logic DCacheMiss, + input logic DCacheAccess, + input logic ICacheMiss, + input logic ICacheAccess, + input logic ICacheStallF, + input logic DCacheStallM, + input logic sfencevmaM, + input logic InterruptM, + input logic ExceptionM, + input logic InvalidateICacheM, + input logic DivBusyE, // integer divide busy + input logic FDivBusyE, // floating point divide busy + input logic [11:0] CSRAdrM, + input logic [1:0] PrivilegeModeW, input logic [P.XLEN-1:0] CSRWriteValM, - input logic [31:0] MCOUNTINHIBIT_REGW, MCOUNTEREN_REGW, SCOUNTEREN_REGW, - input logic [63:0] MTIME_CLINT, + input logic [31:0] MCOUNTINHIBIT_REGW, MCOUNTEREN_REGW, SCOUNTEREN_REGW, + input logic [63:0] MTIME_CLINT, output logic [P.XLEN-1:0] CSRCReadValM, - output logic IllegalCSRCAccessM + output logic IllegalCSRCAccessM ); - localparam MHPMCOUNTERBASE = 12'hB00; - localparam MTIME = 12'hB01; // this is a memory-mapped register; no such CSR exists, and access should faul; + localparam MHPMCOUNTERBASE = 12'hB00; + localparam MTIME = 12'hB01; // this is a memory-mapped register; no such CSR exists, and access should faul; localparam MHPMCOUNTERHBASE = 12'hB80; - localparam MTIMEH = 12'hB81; // this is a memory-mapped register; no such CSR exists, and access should fault - localparam MHPMEVENTBASE = 12'h320; - localparam HPMCOUNTERBASE = 12'hC00; - localparam HPMCOUNTERHBASE = 12'hC80; - localparam TIME = 12'hC01; - localparam TIMEH = 12'hC81; + localparam MTIMEH = 12'hB81; // this is a memory-mapped register; no such CSR exists, and access should fault + localparam MHPMEVENTBASE = 12'h320; + localparam HPMCOUNTERBASE = 12'hC00; + localparam HPMCOUNTERHBASE = 12'hC80; + localparam TIME = 12'hC01; + localparam TIMEH = 12'hC81; logic [4:0] CounterNumM; - 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] HPMCOUNTER_REGW[P.COUNTERS-1:0]; + logic [P.XLEN-1:0] HPMCOUNTERH_REGW[P.COUNTERS-1:0]; logic LoadStallE, LoadStallM; logic StoreStallE, StoreStallM; - logic [P.COUNTERS-1:0] WriteHPMCOUNTERM; - logic [P.COUNTERS-1:0] CounterEvent; + logic [P.COUNTERS-1:0] WriteHPMCOUNTERM; + logic [P.COUNTERS-1:0] CounterEvent; 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; // 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})); // Determine when to increment each counter - assign CounterEvent[0] = 1'b1; // MCYCLE always increments - assign CounterEvent[1] = 1'b0; // Counter 1 doesn't exist - assign CounterEvent[2] = InstrValidNotFlushedM; // MINSTRET instructions retired - if (P.ZIHPM_SUPPORTED) begin: cevent // User-defined counters - assign CounterEvent[3] = InstrClassM[0] & InstrValidNotFlushedM; // branch instruction - assign CounterEvent[4] = InstrClassM[1] & ~InstrClassM[2] & InstrValidNotFlushedM; // jump and not return instructions - assign CounterEvent[5] = InstrClassM[2] & InstrValidNotFlushedM; // return instructions - assign CounterEvent[6] = BPWrongM & InstrValidNotFlushedM; // branch predictor wrong - assign CounterEvent[7] = BPDirPredWrongM & InstrValidNotFlushedM; // Branch predictor wrong direction - assign CounterEvent[8] = BTAWrongM & InstrValidNotFlushedM; // branch predictor wrong target - assign CounterEvent[9] = RASPredPCWrongM & InstrValidNotFlushedM; // return address stack wrong address - 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[12] = StoreStallM; // Store Stall - 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[15] = DCacheStallM; // d cache miss cycles - assign CounterEvent[16] = ICacheAccess & InstrValidNotFlushedM; // instruction cache access - assign CounterEvent[17] = ICacheMiss; // instruction cache miss. Miss asserted 1 cycle at start of cache miss - assign CounterEvent[18] = ICacheStallF; // i cache miss cycles - assign CounterEvent[19] = CSRWriteM & InstrValidNotFlushedM; // CSR writes - assign CounterEvent[20] = InvalidateICacheM & InstrValidNotFlushedM; // fence.i - assign CounterEvent[21] = sfencevmaM & InstrValidNotFlushedM; // sfence.vma - assign CounterEvent[22] = InterruptM; // interrupt, InstrValidNotFlushedM will be low - assign CounterEvent[23] = ExceptionM; // exceptions, InstrValidNotFlushedM will be low + assign CounterEvent[0] = 1'b1; // MCYCLE always increments + assign CounterEvent[1] = 1'b0; // Counter 1 doesn't exist + assign CounterEvent[2] = InstrValidNotFlushedM; // MINSTRET instructions retired + if (P.ZIHPM_SUPPORTED) begin: cevent // User-defined counters + assign CounterEvent[3] = InstrClassM[0] & InstrValidNotFlushedM; // branch instruction + assign CounterEvent[4] = InstrClassM[1] & ~InstrClassM[2] & InstrValidNotFlushedM; // jump and not return instructions + assign CounterEvent[5] = InstrClassM[2] & InstrValidNotFlushedM; // return instructions + assign CounterEvent[6] = BPWrongM & InstrValidNotFlushedM; // branch predictor wrong + assign CounterEvent[7] = BPDirPredWrongM & InstrValidNotFlushedM; // Branch predictor wrong direction + assign CounterEvent[8] = BTAWrongM & InstrValidNotFlushedM; // branch predictor wrong target + assign CounterEvent[9] = RASPredPCWrongM & InstrValidNotFlushedM; // return address stack wrong address + 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[12] = StoreStallM; // Store Stall + 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[15] = DCacheStallM; // d cache miss cycles + assign CounterEvent[16] = ICacheAccess & InstrValidNotFlushedM; // instruction cache access + assign CounterEvent[17] = ICacheMiss; // instruction cache miss. Miss asserted 1 cycle at start of cache miss + assign CounterEvent[18] = ICacheStallF; // i cache miss cycles + assign CounterEvent[19] = CSRWriteM & InstrValidNotFlushedM; // CSR writes + assign CounterEvent[20] = InvalidateICacheM & InstrValidNotFlushedM; // fence.i + assign CounterEvent[21] = sfencevmaM & InstrValidNotFlushedM; // sfence.vma + assign CounterEvent[22] = InterruptM; // interrupt, InstrValidNotFlushedM will be low + assign CounterEvent[23] = ExceptionM; // exceptions, InstrValidNotFlushedM will be low // coverage off // 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 assign CounterEvent[P.COUNTERS-1:25] = 0; // eventually give these sources, including FP instructions, I$/D$ misses, branches and mispredictions end else begin: cevent @@ -158,7 +156,7 @@ module csrc import cvw::*; #(parameter cvw_t P) ( /* verilator lint_on WIDTH */ else if (CSRAdrM >= MHPMCOUNTERBASE & CSRAdrM < MHPMCOUNTERBASE+P.COUNTERS & CSRAdrM != MTIME) CSRCReadValM = HPMCOUNTER_REGW[CounterNumM]; - else if (CSRAdrM >= HPMCOUNTERBASE & CSRAdrM < HPMCOUNTERBASE+P.COUNTERS) + else if (CSRAdrM >= HPMCOUNTERBASE & CSRAdrM < HPMCOUNTERBASE+P.COUNTERS) CSRCReadValM = HPMCOUNTER_REGW[CounterNumM]; else begin CSRCReadValM = 0; @@ -189,4 +187,4 @@ module csrc import cvw::*; #(parameter cvw_t P) ( end endmodule -// mounteren should only exist if u-mode exists +// mounteren should only exist if u-mode exists \ No newline at end of file diff --git a/src/privileged/csri.sv b/src/privileged/csri.sv index c7e6ca51a..ca89617d9 100644 --- a/src/privileged/csri.sv +++ b/src/privileged/csri.sv @@ -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 (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, MTimerInt, 1'b0, STIP, 1'b0, MSwInt, 1'b0, MIP_REGW_writeable[1], 1'b0}; diff --git a/src/privileged/csrm.sv b/src/privileged/csrm.sv index 40dc73996..61226f790 100644 --- a/src/privileged/csrm.sv +++ b/src/privileged/csrm.sv @@ -62,44 +62,44 @@ module csrm import cvw::*; #(parameter cvw_t P) ( logic WriteMENVCFGM; // Machine CSRs - localparam MVENDORID = 12'hF11; - localparam MARCHID = 12'hF12; - localparam MIMPID = 12'hF13; - localparam MHARTID = 12'hF14; - localparam MCONFIGPTR = 12'hF15; - localparam MSTATUS = 12'h300; - localparam MISA_ADR = 12'h301; - localparam MEDELEG = 12'h302; - localparam MIDELEG = 12'h303; - localparam MIE = 12'h304; - localparam MTVEC = 12'h305; - localparam MCOUNTEREN = 12'h306; - localparam MENVCFG = 12'h30A; - localparam MSTATUSH = 12'h310; - localparam MENVCFGH = 12'h31A; + localparam MVENDORID = 12'hF11; + localparam MARCHID = 12'hF12; + localparam MIMPID = 12'hF13; + localparam MHARTID = 12'hF14; + localparam MCONFIGPTR = 12'hF15; + localparam MSTATUS = 12'h300; + localparam MISA_ADR = 12'h301; + localparam MEDELEG = 12'h302; + localparam MIDELEG = 12'h303; + localparam MIE = 12'h304; + localparam MTVEC = 12'h305; + localparam MCOUNTEREN = 12'h306; + localparam MENVCFG = 12'h30A; + localparam MSTATUSH = 12'h310; + localparam MENVCFGH = 12'h31A; localparam MCOUNTINHIBIT = 12'h320; - localparam MSCRATCH = 12'h340; - localparam MEPC = 12'h341; - localparam MCAUSE = 12'h342; - localparam MTVAL = 12'h343; - localparam MIP = 12'h344; - localparam MTINST = 12'h34A; - localparam PMPCFG0 = 12'h3A0; + localparam MSCRATCH = 12'h340; + localparam MEPC = 12'h341; + localparam MCAUSE = 12'h342; + localparam MTVAL = 12'h343; + localparam MIP = 12'h344; + localparam MTINST = 12'h34A; + localparam PMPCFG0 = 12'h3A0; // .. up to 15 more at consecutive addresses - localparam PMPADDR0 = 12'h3B0; + localparam PMPADDR0 = 12'h3B0; // ... up to 63 more at consecutive addresses - localparam TSELECT = 12'h7A0; - localparam TDATA1 = 12'h7A1; - localparam TDATA2 = 12'h7A2; - localparam TDATA3 = 12'h7A3; - localparam DCSR = 12'h7B0; - localparam DPC = 12'h7B1; - localparam DSCRATCH0 = 12'h7B2; - localparam DSCRATCH1 = 12'h7B3; + localparam TSELECT = 12'h7A0; + localparam TDATA1 = 12'h7A1; + localparam TDATA2 = 12'h7A2; + localparam TDATA3 = 12'h7A3; + localparam DCSR = 12'h7B0; + localparam DPC = 12'h7B1; + localparam DSCRATCH0 = 12'h7B2; + localparam DSCRATCH1 = 12'h7B3; // Constants localparam ZERO = {(P.XLEN){1'b0}}; - localparam MEDELEG_MASK = 16'hB3FF; - localparam MIDELEG_MASK = 12'h222; // we choose to not make machine interrupts delegable + localparam MEDELEG_MASK = 16'hB3FF; + 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 genvar i; @@ -137,17 +137,17 @@ module csrm import cvw::*; #(parameter cvw_t P) ( assign MHARTID_REGW = 0; // Write machine Mode CSRs - assign WriteMSTATUSM = CSRMWriteM & (CSRAdrM == MSTATUS); - assign WriteMSTATUSHM = CSRMWriteM & (CSRAdrM == MSTATUSH) & (P.XLEN==32); - assign WriteMTVECM = CSRMWriteM & (CSRAdrM == MTVEC); - assign WriteMEDELEGM = CSRMWriteM & (CSRAdrM == MEDELEG); - assign WriteMIDELEGM = CSRMWriteM & (CSRAdrM == MIDELEG); - assign WriteMSCRATCHM = CSRMWriteM & (CSRAdrM == MSCRATCH); - assign WriteMEPCM = MTrapM | (CSRMWriteM & (CSRAdrM == MEPC)); - assign WriteMCAUSEM = MTrapM | (CSRMWriteM & (CSRAdrM == MCAUSE)); - assign WriteMTVALM = MTrapM | (CSRMWriteM & (CSRAdrM == MTVAL)); - assign WriteMCOUNTERENM = CSRMWriteM & (CSRAdrM == MCOUNTEREN); - assign WriteMENVCFGM = CSRMWriteM & (CSRAdrM == MENVCFG); + assign WriteMSTATUSM = CSRMWriteM & (CSRAdrM == MSTATUS); + assign WriteMSTATUSHM = CSRMWriteM & (CSRAdrM == MSTATUSH) & (P.XLEN==32); + assign WriteMTVECM = CSRMWriteM & (CSRAdrM == MTVEC); + assign WriteMEDELEGM = CSRMWriteM & (CSRAdrM == MEDELEG); + assign WriteMIDELEGM = CSRMWriteM & (CSRAdrM == MIDELEG); + assign WriteMSCRATCHM = CSRMWriteM & (CSRAdrM == MSCRATCH); + assign WriteMEPCM = MTrapM | (CSRMWriteM & (CSRAdrM == MEPC)); + assign WriteMCAUSEM = MTrapM | (CSRMWriteM & (CSRAdrM == MCAUSE)); + assign WriteMTVALM = MTrapM | (CSRMWriteM & (CSRAdrM == MTVAL)); + assign WriteMCOUNTERENM = CSRMWriteM & (CSRAdrM == MCOUNTEREN); + assign WriteMENVCFGM = CSRMWriteM & (CSRAdrM == MENVCFG); assign WriteMCOUNTINHIBITM = CSRMWriteM & (CSRAdrM == MCOUNTINHIBIT); 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]; // Uncomment these other fields when they are defined // 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_CBIE = MENVCFG_REGW[5:4]; - // assign MENVCFG_FIOM = MENVCFG_REGW[0]; + // assign MENVCFG_CBIE = MENVCFG_REGW[5:4]; + // assign MENVCFG_FIOM = MENVCFG_REGW[0]; // Read machine mode CSRs // verilator lint_off WIDTH @@ -222,28 +222,28 @@ module csrm import cvw::*; #(parameter cvw_t P) ( end end else case (CSRAdrM) - MISA_ADR: CSRMReadValM = MISA_REGW; - MVENDORID: CSRMReadValM = 0; - MARCHID: CSRMReadValM = 0; - MIMPID: CSRMReadValM = {{P.XLEN-12{1'b0}}, 12'h100}; // pipelined implementation - MHARTID: CSRMReadValM = MHARTID_REGW; // hardwired to 0 - MCONFIGPTR: CSRMReadValM = 0; // hardwired to 0 - MSTATUS: CSRMReadValM = MSTATUS_REGW; - MSTATUSH: CSRMReadValM = MSTATUSH_REGW; - MTVEC: CSRMReadValM = MTVEC_REGW; - MEDELEG: CSRMReadValM = {{(P.XLEN-16){1'b0}}, MEDELEG_REGW}; - MIDELEG: CSRMReadValM = {{(P.XLEN-12){1'b0}}, MIDELEG_REGW}; - MIP: CSRMReadValM = {{(P.XLEN-12){1'b0}}, MIP_REGW}; - MIE: CSRMReadValM = {{(P.XLEN-12){1'b0}}, MIE_REGW}; - MSCRATCH: CSRMReadValM = MSCRATCH_REGW; - MEPC: CSRMReadValM = MEPC_REGW; - MCAUSE: CSRMReadValM = MCAUSE_REGW; - MTVAL: CSRMReadValM = MTVAL_REGW; - MTINST: CSRMReadValM = 0; // implemented as trivial zero - MCOUNTEREN:CSRMReadValM = {{(P.XLEN-32){1'b0}}, MCOUNTEREN_REGW}; - MENVCFG: CSRMReadValM = MENVCFG_REGW[P.XLEN-1:0]; - MENVCFGH: CSRMReadValM = MENVCFGH_REGW; - MCOUNTINHIBIT:CSRMReadValM = {{(P.XLEN-32){1'b0}}, MCOUNTINHIBIT_REGW}; + MISA_ADR: CSRMReadValM = MISA_REGW; + MVENDORID: CSRMReadValM = 0; + MARCHID: CSRMReadValM = 0; + MIMPID: CSRMReadValM = {{P.XLEN-12{1'b0}}, 12'h100}; // pipelined implementation + MHARTID: CSRMReadValM = MHARTID_REGW; // hardwired to 0 + MCONFIGPTR: CSRMReadValM = 0; // hardwired to 0 + MSTATUS: CSRMReadValM = MSTATUS_REGW; + MSTATUSH: CSRMReadValM = MSTATUSH_REGW; + MTVEC: CSRMReadValM = MTVEC_REGW; + MEDELEG: CSRMReadValM = {{(P.XLEN-16){1'b0}}, MEDELEG_REGW}; + MIDELEG: CSRMReadValM = {{(P.XLEN-12){1'b0}}, MIDELEG_REGW}; + MIP: CSRMReadValM = {{(P.XLEN-12){1'b0}}, MIP_REGW}; + MIE: CSRMReadValM = {{(P.XLEN-12){1'b0}}, MIE_REGW}; + MSCRATCH: CSRMReadValM = MSCRATCH_REGW; + MEPC: CSRMReadValM = MEPC_REGW; + MCAUSE: CSRMReadValM = MCAUSE_REGW; + MTVAL: CSRMReadValM = MTVAL_REGW; + MTINST: CSRMReadValM = 0; // implemented as trivial zero + MCOUNTEREN: CSRMReadValM = {{(P.XLEN-32){1'b0}}, MCOUNTEREN_REGW}; + MENVCFG: CSRMReadValM = MENVCFG_REGW[P.XLEN-1:0]; + MENVCFGH: CSRMReadValM = MENVCFGH_REGW; + MCOUNTINHIBIT: CSRMReadValM = {{(P.XLEN-32){1'b0}}, MCOUNTINHIBIT_REGW}; default: begin CSRMReadValM = 0; @@ -252,4 +252,4 @@ module csrm import cvw::*; #(parameter cvw_t P) ( endcase end // verilator lint_on WIDTH -endmodule +endmodule \ No newline at end of file diff --git a/src/privileged/csrs.sv b/src/privileged/csrs.sv index e28ec79da..97c8b3f22 100644 --- a/src/privileged/csrs.sv +++ b/src/privileged/csrs.sv @@ -51,21 +51,21 @@ module csrs import cvw::*; #(parameter cvw_t P) ( ); // Supervisor CSRs - localparam SSTATUS = 12'h100; - localparam SIE = 12'h104; - localparam STVEC = 12'h105; + localparam SSTATUS = 12'h100; + localparam SIE = 12'h104; + localparam STVEC = 12'h105; localparam SCOUNTEREN = 12'h106; - localparam SENVCFG = 12'h10A; - localparam SSCRATCH = 12'h140; - localparam SEPC = 12'h141; - localparam SCAUSE = 12'h142; - localparam STVAL = 12'h143; - localparam SIP= 12'h144; - localparam STIMECMP = 12'h14D; - localparam STIMECMPH = 12'h15D; - localparam SATP = 12'h180; + localparam SENVCFG = 12'h10A; + localparam SSCRATCH = 12'h140; + localparam SEPC = 12'h141; + localparam SCAUSE = 12'h142; + localparam STVAL = 12'h143; + localparam SIP = 12'h144; + localparam STIMECMP = 12'h14D; + localparam STIMECMPH = 12'h15D; + localparam SATP = 12'h180; // 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); logic WriteSTVECM; @@ -81,17 +81,17 @@ module csrs import cvw::*; #(parameter cvw_t P) ( logic [63:0] STIMECMP_REGW; // write enables - assign WriteSSTATUSM = CSRSWriteM & (CSRAdrM == SSTATUS); - assign WriteSTVECM = CSRSWriteM & (CSRAdrM == STVEC); - assign WriteSSCRATCHM = CSRSWriteM & (CSRAdrM == SSCRATCH); - assign WriteSEPCM = STrapM | (CSRSWriteM & (CSRAdrM == SEPC)); - assign WriteSCAUSEM = STrapM | (CSRSWriteM & (CSRAdrM == SCAUSE)); - assign WriteSTVALM = STrapM | (CSRSWriteM & (CSRAdrM == STVAL)); - assign WriteSATPM = CSRSWriteM & (CSRAdrM == SATP) & (PrivilegeModeW == P.M_MODE | ~STATUS_TVM); + assign WriteSSTATUSM = CSRSWriteM & (CSRAdrM == SSTATUS); + assign WriteSTVECM = CSRSWriteM & (CSRAdrM == STVEC); + assign WriteSSCRATCHM = CSRSWriteM & (CSRAdrM == SSCRATCH); + assign WriteSEPCM = STrapM | (CSRSWriteM & (CSRAdrM == SEPC)); + assign WriteSCAUSEM = STrapM | (CSRSWriteM & (CSRAdrM == SCAUSE)); + assign WriteSTVALM = STrapM | (CSRSWriteM & (CSRAdrM == STVAL)); + assign WriteSATPM = CSRSWriteM & (CSRAdrM == SATP) & (PrivilegeModeW == P.M_MODE | ~STATUS_TVM); assign WriteSCOUNTERENM = CSRSWriteM & (CSRAdrM == SCOUNTEREN); - assign WriteSENVCFGM = CSRSWriteM & (CSRAdrM == SENVCFG); - 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 WriteSENVCFGM = CSRSWriteM & (CSRAdrM == SENVCFG); + 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); // CSRs 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 // Spec is a bit peculiar - Machine timer interrupts are produced in CLINT, while Supervisor timer interrupts are in CSRs 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 assign STimerInt = 0; @@ -133,10 +133,10 @@ module csrs import cvw::*; #(parameter cvw_t P) ( // Extract bit fields // Uncomment these other fields when they are defined // 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_CBIE = SENVCFG_REGW[5:4]; - // assign SENVCFG_FIOM = SENVCFG_REGW[0]; + // assign SENVCFG_CBIE = SENVCFG_REGW[5:4]; + // assign SENVCFG_FIOM = SENVCFG_REGW[0]; // CSR Reads always_comb begin:csrr @@ -175,4 +175,4 @@ module csrs import cvw::*; #(parameter cvw_t P) ( end endcase end -endmodule +endmodule \ No newline at end of file diff --git a/src/privileged/csrsr.sv b/src/privileged/csrsr.sv index a4b89297f..55db35f63 100644 --- a/src/privileged/csrsr.sv +++ b/src/privileged/csrsr.sv @@ -28,22 +28,22 @@ //////////////////////////////////////////////////////////////////////////////////////////////// module csrsr import cvw::*; #(parameter cvw_t P) ( - input logic clk, reset, StallW, - input logic WriteMSTATUSM, WriteMSTATUSHM, WriteSSTATUSM, - input logic TrapM, FRegWriteM, - input logic [1:0] NextPrivilegeModeM, PrivilegeModeW, - input logic mretM, sretM, - input logic WriteFRMM, WriteFFLAGSM, + input logic clk, reset, StallW, + input logic WriteMSTATUSM, WriteMSTATUSHM, WriteSSTATUSM, + input logic TrapM, FRegWriteM, + input logic [1:0] NextPrivilegeModeM, PrivilegeModeW, + input logic mretM, sretM, + input logic WriteFRMM, WriteFFLAGSM, 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 [1:0] STATUS_MPP, - output logic STATUS_SPP, STATUS_TSR, STATUS_TW, - output logic STATUS_MIE, STATUS_SIE, - output logic STATUS_MXR, STATUS_SUM, - output logic STATUS_MPRV, STATUS_TVM, - output logic [1:0] STATUS_FS, - output logic BigEndianM + output logic [1:0] STATUS_MPP, + output logic STATUS_SPP, STATUS_TSR, STATUS_TW, + output logic STATUS_MIE, STATUS_SIE, + output logic STATUS_MXR, STATUS_SUM, + output logic STATUS_MPRV, STATUS_TVM, + output logic [1:0] STATUS_FS, + output logic BigEndianM ); 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 // *** consider adding MBE, SBE, UBE fields, parameterized to be fixed or adjustable if (P.XLEN==64) begin: csrsr64 // RV64 - 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_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}; - assign SSTATUS_REGW = {STATUS_SD, /*27'b0, */ 29'b0, /*STATUS_SXL, */ {P.QEMU ? 2'b0 : STATUS_UXL}, /*9'b0, */ 12'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_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}; + 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_XS, STATUS_FS, /*STATUS_MPP, 2'b0*/ 4'b0, - STATUS_SPP, /*STATUS_MPIE*/ 1'b0, STATUS_UBE, STATUS_SPIE, + STATUS_XS, STATUS_FS, /*STATUS_MPP, 2'b0*/ 4'b0, + STATUS_SPP, /*STATUS_MPIE*/ 1'b0, STATUS_UBE, STATUS_SPIE, /*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. end else begin: csrsr32 // RV32 - assign MSTATUS_REGW = {STATUS_SD, 8'b0, - STATUS_TSR, STATUS_TW, STATUS_TVM, STATUS_MXR, STATUS_SUM, STATUS_MPRV, - 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}; + assign MSTATUS_REGW = {STATUS_SD, 8'b0, + STATUS_TSR, STATUS_TW, STATUS_TVM, STATUS_MXR, STATUS_SUM, STATUS_MPRV, + 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}; 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_XS, STATUS_FS, /*STATUS_MPP, 2'b0*/ 4'b0, - STATUS_SPP, /*STATUS_MPIE*/ 1'b0, STATUS_UBE, STATUS_SPIE, + STATUS_XS, STATUS_FS, /*STATUS_MPP, 2'b0*/ 4'b0, + STATUS_SPP, /*STATUS_MPIE*/ 1'b0, STATUS_UBE, STATUS_SPIE, /*1'b0, STATUS_MIE, 1'b0*/ 3'b0, STATUS_SIE, 1'b0}; end @@ -90,21 +90,21 @@ module csrsr import cvw::*; #(parameter cvw_t P) ( end // harwired STATUS bits - 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_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_UBE = 0; // little-endian - assign STATUS_SBE = 0; // little-endian - assign STATUS_MBE = 0; // little-endian */ + 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_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_UBE = 0; // little-endian + assign STATUS_SBE = 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 - 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_SUM = P.S_SUPPORTED & P.VIRTMEM_SUPPORTED & STATUS_SUM_INT; // override reigster with 0 if supervisor mode not 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_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_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_XS = 2'b00; // No additional user-mode state to be dirty + 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_XS = 2'b00; // No additional user-mode state to be dirty always_comb 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; //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 - else if (PrivilegeModeW == P.M_MODE & STATUS_MPRV) EndiannessPrivMode = STATUS_MPP; + else if (PrivilegeModeW == P.M_MODE & STATUS_MPRV) EndiannessPrivMode = STATUS_MPP; //coverage on else EndiannessPrivMode = PrivilegeModeW; case (EndiannessPrivMode) P.M_MODE: BigEndianM = STATUS_MBE; P.S_MODE: BigEndianM = STATUS_SBE; - default: BigEndianM = STATUS_UBE; + default: BigEndianM = STATUS_UBE; endcase end 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 always_ff @(posedge clk) //, posedge reset) if (reset) begin - STATUS_TSR_INT <= #1 0; - STATUS_TW_INT <= #1 0; - STATUS_TVM_INT <= #1 0; - STATUS_MXR_INT <= #1 0; - STATUS_SUM_INT <= #1 0; + STATUS_TSR_INT <= #1 0; + STATUS_TW_INT <= #1 0; + STATUS_TVM_INT <= #1 0; + STATUS_MXR_INT <= #1 0; + STATUS_SUM_INT <= #1 0; 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_MPP <= #1 0; - STATUS_SPP <= #1 0; - STATUS_MPIE <= #1 0; - STATUS_SPIE <= #1 0; - STATUS_MIE <= #1 0; - STATUS_SIE <= #1 0; - STATUS_MBE <= #1 0; - STATUS_SBE <= #1 0; - STATUS_UBE <= #1 0; + 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_SPP <= #1 0; + STATUS_MPIE <= #1 0; + STATUS_SPIE <= #1 0; + STATUS_MIE <= #1 0; + STATUS_SIE <= #1 0; + STATUS_MBE <= #1 0; + STATUS_SBE <= #1 0; + STATUS_UBE <= #1 0; end else if (~StallW) begin if (TrapM) begin // 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 if (NextPrivilegeModeM == P.M_MODE) begin STATUS_MPIE <= #1 STATUS_MIE; - STATUS_MIE <= #1 0; - STATUS_MPP <= #1 PrivilegeModeW; + STATUS_MIE <= #1 0; + STATUS_MPP <= #1 PrivilegeModeW; end else begin // supervisor mode STATUS_SPIE <= #1 STATUS_SIE; - STATUS_SIE <= #1 0; - STATUS_SPP <= #1 PrivilegeModeW[0]; + STATUS_SIE <= #1 0; + STATUS_SPP <= #1 PrivilegeModeW[0]; end end else if (mretM) begin // Privileged 3.1.6.1 - STATUS_MIE <= #1 STATUS_MPIE; // restore global interrupt enable - STATUS_MPIE <= #1 1; // - 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_MIE <= #1 STATUS_MPIE; // restore global interrupt enable + STATUS_MPIE <= #1 1; // + 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. end else if (sretM) begin - STATUS_SIE <= #1 STATUS_SPIE; // restore global interrupt enable - STATUS_SPIE <= #1 P.S_SUPPORTED; - STATUS_SPP <= #1 0; // set SPP to lowest supported privilege level to catch bugs + STATUS_SIE <= #1 STATUS_SPIE; // restore global interrupt enable + STATUS_SPIE <= #1 P.S_SUPPORTED; + STATUS_SPP <= #1 0; // set SPP to lowest supported privilege level to catch bugs STATUS_MPRV_INT <= #1 0; // always clear MPRV end else if (WriteMSTATUSM) begin - STATUS_TSR_INT <= #1 CSRWriteValM[22]; - STATUS_TW_INT <= #1 CSRWriteValM[21]; - STATUS_TVM_INT <= #1 CSRWriteValM[20]; - STATUS_MXR_INT <= #1 CSRWriteValM[19]; - STATUS_SUM_INT <= #1 CSRWriteValM[18]; + STATUS_TSR_INT <= #1 CSRWriteValM[22]; + STATUS_TW_INT <= #1 CSRWriteValM[21]; + STATUS_TVM_INT <= #1 CSRWriteValM[20]; + STATUS_MXR_INT <= #1 CSRWriteValM[19]; + STATUS_SUM_INT <= #1 CSRWriteValM[18]; STATUS_MPRV_INT <= #1 CSRWriteValM[17]; - STATUS_FS_INT <= #1 CSRWriteValM[14:13]; - STATUS_MPP <= #1 STATUS_MPP_NEXT; - STATUS_SPP <= #1 P.S_SUPPORTED & CSRWriteValM[8]; - STATUS_MPIE <= #1 CSRWriteValM[7]; - STATUS_SPIE <= #1 P.S_SUPPORTED & CSRWriteValM[5]; - STATUS_MIE <= #1 CSRWriteValM[3]; - STATUS_SIE <= #1 P.S_SUPPORTED & CSRWriteValM[1]; - STATUS_UBE <= #1 CSRWriteValM[6] & P.U_SUPPORTED & P.BIGENDIAN_SUPPORTED; - STATUS_MBE <= #1 nextMBE; - STATUS_SBE <= #1 nextSBE; + STATUS_FS_INT <= #1 CSRWriteValM[14:13]; + STATUS_MPP <= #1 STATUS_MPP_NEXT; + STATUS_SPP <= #1 P.S_SUPPORTED & CSRWriteValM[8]; + STATUS_MPIE <= #1 CSRWriteValM[7]; + STATUS_SPIE <= #1 P.S_SUPPORTED & CSRWriteValM[5]; + STATUS_MIE <= #1 CSRWriteValM[3]; + STATUS_SIE <= #1 P.S_SUPPORTED & CSRWriteValM[1]; + STATUS_UBE <= #1 CSRWriteValM[6] & P.U_SUPPORTED & P.BIGENDIAN_SUPPORTED; + STATUS_MBE <= #1 nextMBE; + STATUS_SBE <= #1 nextSBE; // coverage off // MSTATUSH only exists in 32-bit configurations, will not be hit on rv64gc end else if (WriteMSTATUSHM) begin - STATUS_MBE <= #1 CSRWriteValM[5] & P.BIGENDIAN_SUPPORTED; - STATUS_SBE <= #1 CSRWriteValM[4] & P.S_SUPPORTED & P.BIGENDIAN_SUPPORTED; + STATUS_MBE <= #1 CSRWriteValM[5] & P.BIGENDIAN_SUPPORTED; + STATUS_SBE <= #1 CSRWriteValM[4] & P.S_SUPPORTED & P.BIGENDIAN_SUPPORTED; // coverage on end else if (WriteSSTATUSM) begin // write a subset of the STATUS bits - STATUS_MXR_INT <= #1 CSRWriteValM[19]; - STATUS_SUM_INT <= #1 CSRWriteValM[18]; - STATUS_FS_INT <= #1 CSRWriteValM[14:13]; - STATUS_SPP <= #1 P.S_SUPPORTED & CSRWriteValM[8]; - STATUS_SPIE <= #1 P.S_SUPPORTED & CSRWriteValM[5]; - STATUS_SIE <= #1 P.S_SUPPORTED & CSRWriteValM[1]; - STATUS_UBE <= #1 CSRWriteValM[6] & P.U_SUPPORTED & P.BIGENDIAN_SUPPORTED; + STATUS_MXR_INT <= #1 CSRWriteValM[19]; + STATUS_SUM_INT <= #1 CSRWriteValM[18]; + STATUS_FS_INT <= #1 CSRWriteValM[14:13]; + STATUS_SPP <= #1 P.S_SUPPORTED & CSRWriteValM[8]; + STATUS_SPIE <= #1 P.S_SUPPORTED & CSRWriteValM[5]; + STATUS_SIE <= #1 P.S_SUPPORTED & CSRWriteValM[1]; + STATUS_UBE <= #1 CSRWriteValM[6] & P.U_SUPPORTED & P.BIGENDIAN_SUPPORTED; end else if (FRegWriteM | WriteFRMM | WriteFFLAGSM) STATUS_FS_INT <= #1 2'b11; end endmodule diff --git a/src/privileged/csru.sv b/src/privileged/csru.sv index d394594ae..3a0f8c909 100644 --- a/src/privileged/csru.sv +++ b/src/privileged/csru.sv @@ -27,40 +27,40 @@ //////////////////////////////////////////////////////////////////////////////////////////////// module csru import cvw::*; #(parameter cvw_t P) ( - input logic clk, reset, - input logic InstrValidNotFlushedM, - input logic CSRUWriteM, - input logic [11:0] CSRAdrM, + input logic clk, reset, + input logic InstrValidNotFlushedM, + input logic CSRUWriteM, + input logic [11:0] CSRAdrM, 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, - input logic [4:0] SetFflagsM, - output logic [2:0] FRM_REGW, - output logic WriteFRMM, WriteFFLAGSM, - output logic IllegalCSRUAccessM + input logic [4:0] SetFflagsM, + output logic [2:0] FRM_REGW, + output logic WriteFRMM, WriteFFLAGSM, + output logic IllegalCSRUAccessM ); localparam FFLAGS = 12'h001; - localparam FRM = 12'h002; - localparam FCSR = 12'h003; + localparam FRM = 12'h002; + localparam FCSR = 12'h003; - logic [4:0] FFLAGS_REGW; - logic [2:0] NextFRMM; - logic [4:0] NextFFLAGSM; - logic SetOrWriteFFLAGSM; + logic [4:0] FFLAGS_REGW; + logic [2:0] NextFRMM; + logic [4:0] NextFFLAGSM; + logic SetOrWriteFFLAGSM; // 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); // Write Values - assign NextFRMM = (CSRAdrM == FCSR) ? CSRWriteValM[7:5] : CSRWriteValM[2:0]; - assign NextFFLAGSM = WriteFFLAGSM ? CSRWriteValM[4:0] : FFLAGS_REGW | SetFflagsM; + assign NextFRMM = (CSRAdrM == FCSR) ? CSRWriteValM[7:5] : CSRWriteValM[2:0]; + assign NextFFLAGSM = WriteFFLAGSM ? CSRWriteValM[4:0] : FFLAGS_REGW | SetFflagsM; assign SetOrWriteFFLAGSM = WriteFFLAGSM | (|SetFflagsM & InstrValidNotFlushedM); // CSRs 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 always_comb begin diff --git a/src/privileged/privileged.sv b/src/privileged/privileged.sv index 659a00f24..95ba2b0bd 100644 --- a/src/privileged/privileged.sv +++ b/src/privileged/privileged.sv @@ -28,91 +28,90 @@ /////////////////////////////////////////// module privileged import cvw::*; #(parameter cvw_t P) ( - input logic clk, reset, - input logic StallD, StallE, StallM, StallW, - input logic FlushD, FlushE, FlushM, FlushW, + input logic clk, reset, + input logic StallD, StallE, StallM, StallW, + input logic FlushD, FlushE, FlushM, FlushW, // 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 [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] InstrM, // Instruction + 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] PCM, PC2NextF, // program counter, next PC going to trap/return PC logic // control signals - input logic InstrValidM, // Current instruction is valid (not flushed) - input logic CommittedM, CommittedF, // current instruction is using bus; don't interrupt - input logic PrivilegedM, // privileged instruction + input logic InstrValidM, // Current instruction is valid (not flushed) + input logic CommittedM, CommittedF, // current instruction is using bus; don't interrupt + input logic PrivilegedM, // privileged instruction // processor events for performance counter logging - input logic FRegWriteM, // instruction will write floating-point registers - input logic LoadStallD, // load instruction is stalling - input logic StoreStallD, // store instruction is stalling - input logic ICacheStallF, // I cache stalled - input logic DCacheStallM, // D cache stalled - input logic BPDirPredWrongM, // branch predictor guessed wrong direction - input logic BTAWrongM, // branch predictor guessed wrong target - input logic RASPredPCWrongM, // return adddress stack guessed wrong target - input logic IClassWrongM, // branch predictor guessed wrong instruction class - input logic BPWrongM, // branch predictor is wrong - input logic [3:0] InstrClassM, // actual instruction class - input logic DCacheMiss, // data cache miss - input logic DCacheAccess, // data cache accessed (hit or miss) - input logic ICacheMiss, // instruction cache miss - input logic ICacheAccess, // instruction cache access - input logic DivBusyE, // integer divide busy - input logic FDivBusyE, // floating point divide busy + input logic FRegWriteM, // instruction will write floating-point registers + input logic LoadStallD, // load instruction is stalling + input logic StoreStallD, // store instruction is stalling + input logic ICacheStallF, // I cache stalled + input logic DCacheStallM, // D cache stalled + input logic BPDirPredWrongM, // branch predictor guessed wrong direction + input logic BTAWrongM, // branch predictor guessed wrong target + input logic RASPredPCWrongM, // return adddress stack guessed wrong target + input logic IClassWrongM, // branch predictor guessed wrong instruction class + input logic BPWrongM, // branch predictor is wrong + input logic [3:0] InstrClassM, // actual instruction class + input logic DCacheMiss, // data cache miss + input logic DCacheAccess, // data cache accessed (hit or miss) + input logic ICacheMiss, // instruction cache miss + input logic ICacheAccess, // instruction cache access + input logic DivBusyE, // integer divide busy + input logic FDivBusyE, // floating point divide busy // fault sources - input logic InstrAccessFaultF, // instruction 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 InstrPageFaultF, // page faults - input logic LoadPageFaultM, StoreAmoPageFaultM, // page faults - input logic InstrMisalignedFaultM, // misaligned instruction fault - input logic LoadMisalignedFaultM, StoreAmoMisalignedFaultM, // misaligned data fault - input logic IllegalIEUFPUInstrD, // illegal instruction from IEU or FPU - input logic MTimerInt, MExtInt, SExtInt, MSwInt, // interrupt sources - input logic [63:0] MTIME_CLINT, // timer value from CLINT - 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 InstrAccessFaultF, // instruction 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 InstrPageFaultF, // page faults + input logic LoadPageFaultM, StoreAmoPageFaultM, // page faults + input logic InstrMisalignedFaultM, // misaligned instruction fault + input logic LoadMisalignedFaultM, StoreAmoMisalignedFaultM, // misaligned data fault + input logic IllegalIEUFPUInstrD, // illegal instruction from IEU or FPU + input logic MTimerInt, MExtInt, SExtInt, MSwInt, // interrupt sources + input logic [63:0] MTIME_CLINT, // timer value from CLINT + 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 // CSR outputs 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 STATUS_MXR, STATUS_SUM, STATUS_MPRV, // 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 [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 STATUS_MXR, STATUS_SUM, STATUS_MPRV, // 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 [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 // PC logic output in privileged unit output logic [P.XLEN-1:0] UnalignedPCNextF, // Next PC from trap/return PC logic // control outputs - output logic RetM, TrapM, // return instruction, or trap - output logic sfencevmaM, // sfence.vma instruction - input logic InvalidateICacheM, // fence instruction - output logic BigEndianM, // Use big endian in current privilege mode + output logic RetM, TrapM, // return instruction, or trap + output logic sfencevmaM, // sfence.vma instruction + input logic InvalidateICacheM, // fence instruction + output logic BigEndianM, // Use big endian in current privilege mode // Fault outputs - 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 BreakpointFaultM, EcallFaultM, // breakpoint and Ecall traps should retire + output logic wfiM, IntPendingM // Stall in Memory stage for WFI until interrupt pending or timeout ); - logic [3:0] CauseM; // trap cause - logic [15:0] MEDELEG_REGW; // exception delegation CSR - logic [11:0] MIDELEG_REGW; // interrupt delegation CSR - logic sretM, mretM; // supervisor / machine return instruction - logic IllegalCSRAccessM; // Illegal access to CSR - logic IllegalIEUFPUInstrM; // Illegal IEU or FPU instruction, delayed to Mem stage - logic InstrPageFaultM; // Instruction page fault, delayed to Mem stage - logic InstrAccessFaultM; // Instruction access fault, delayed to Mem stages - logic IllegalInstrFaultM; // Illegal instruction fault - 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 [11:0] MIP_REGW, MIE_REGW; // interrupt pending and enable bits - logic [1:0] NextPrivilegeModeM; // next privilege mode based on trap or return - logic DelegateM; // trap should be delegated - logic InterruptM; // interrupt occuring - logic ExceptionM; // Memory stage instruction caused a fault - logic HPTWInstrAccessFaultM; // Hardware page table access fault while fetching instruction PTE + logic [3:0] CauseM; // trap cause + logic [15:0] MEDELEG_REGW; // exception delegation CSR + logic [11:0] MIDELEG_REGW; // interrupt delegation CSR + logic sretM, mretM; // supervisor / machine return instruction + logic IllegalCSRAccessM; // Illegal access to CSR + logic IllegalIEUFPUInstrM; // Illegal IEU or FPU instruction, delayed to Mem stage + logic InstrPageFaultM; // Instruction page fault, delayed to Mem stage + logic InstrAccessFaultM; // Instruction access fault, delayed to Mem stages + logic IllegalInstrFaultM; // Illegal instruction fault + 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 [11:0] MIP_REGW, MIE_REGW; // interrupt pending and enable bits + logic [1:0] NextPrivilegeModeM; // next privilege mode based on trap or return + logic DelegateM; // trap should be delegated + logic InterruptM; // interrupt occuring + logic ExceptionM; // Memory stage instruction caused a fault + logic HPTWInstrAccessFaultM; // Hardware page table access fault while fetching instruction PTE - // track the current privilege level privmode #(P) privmode(.clk, .reset, .StallW, .TrapM, .mretM, .sretM, .DelegateM, .STATUS_MPP, .STATUS_SPP, .NextPrivilegeModeM, .PrivilegeModeW); @@ -156,8 +155,3 @@ module privileged import cvw::*; #(parameter cvw_t P) ( .InstrValidM, .CommittedM, .CommittedF, .TrapM, .RetM, .wfiM, .InterruptM, .ExceptionM, .IntPendingM, .DelegateM, .CauseM); endmodule - - - - - diff --git a/src/privileged/privmode.sv b/src/privileged/privmode.sv index aa111732d..5ac4cae78 100644 --- a/src/privileged/privmode.sv +++ b/src/privileged/privmode.sv @@ -43,10 +43,10 @@ module privmode import cvw::*; #(parameter cvw_t P) ( always_comb begin if (TrapM) begin // Change privilege based on DELEG registers (see 3.1.8) if (P.S_SUPPORTED & DelegateM) NextPrivilegeModeM = P.S_MODE; - else NextPrivilegeModeM = P.M_MODE; - end else if (mretM) NextPrivilegeModeM = STATUS_MPP; - else if (sretM) NextPrivilegeModeM = {1'b0, STATUS_SPP}; - else NextPrivilegeModeM = PrivilegeModeW; + else NextPrivilegeModeM = P.M_MODE; + end else if (mretM) NextPrivilegeModeM = STATUS_MPP; + else if (sretM) NextPrivilegeModeM = {1'b0, STATUS_SPP}; + else NextPrivilegeModeM = PrivilegeModeW; end flopenl #(2) privmodereg(clk, reset, ~StallW, NextPrivilegeModeM, P.M_MODE, PrivilegeModeW); diff --git a/src/privileged/trap.sv b/src/privileged/trap.sv index 0d8002d18..2720570de 100644 --- a/src/privileged/trap.sv +++ b/src/privileged/trap.sv @@ -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 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 IntPendingM = |PendingIntsM; - assign Committed = CommittedM | CommittedF; - assign EnabledIntsM = ({12{MIntGlobalEnM}} & PendingIntsM & ~MIDELEG_REGW | {12{SIntGlobalEnM}} & PendingIntsM & MIDELEG_REGW); - assign ValidIntsM = {12{~Committed}} & EnabledIntsM; - 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 PendingIntsM = MIP_REGW & MIE_REGW; + assign IntPendingM = |PendingIntsM; + assign Committed = CommittedM | CommittedF; + assign EnabledIntsM = ({12{MIntGlobalEnM}} & PendingIntsM & ~MIDELEG_REGW | {12{SIntGlobalEnM}} & PendingIntsM & MIDELEG_REGW); + assign ValidIntsM = {12{~Committed}} & EnabledIntsM; + 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]) & (PrivilegeModeW == P.U_MODE | PrivilegeModeW == P.S_MODE); /////////////////////////////////////////// @@ -88,7 +88,7 @@ module trap import cvw::*; #(parameter cvw_t P) ( LoadAccessFaultM | StoreAmoAccessFaultM; // coverage on assign TrapM = ExceptionM | InterruptM; - assign RetM = mretM | sretM; + assign RetM = mretM | sretM; /////////////////////////////////////////// // Cause priority defined in table 3.7 of 20190608 privileged spec diff --git a/src/uncore/ahbapbbridge.sv b/src/uncore/ahbapbbridge.sv index 5aed30300..381297f00 100644 --- a/src/uncore/ahbapbbridge.sv +++ b/src/uncore/ahbapbbridge.sv @@ -27,27 +27,27 @@ module ahbapbbridge import cvw::*; #(parameter cvw_t P, parameter PERIPHS = 2) ( - input logic HCLK, HRESETn, - input logic [PERIPHS-1:0] HSEL, + input logic HCLK, HRESETn, + input logic [PERIPHS-1:0] HSEL, input logic [P.PA_BITS-1:0] HADDR, input logic [P.XLEN-1:0] HWDATA, input logic [P.XLEN/8-1:0] HWSTRB, - input logic HWRITE, - input logic [1:0] HTRANS, - input logic HREADY, + input logic HWRITE, + input logic [1:0] HTRANS, + input logic HREADY, // input logic [3:0] HPROT, // not used output logic [P.XLEN-1:0] HRDATA, - output logic HRESP, HREADYOUT, - output logic PCLK, PRESETn, - output logic [PERIPHS-1:0] PSEL, - output logic PWRITE, - output logic PENABLE, - output logic [31:0] PADDR, + output logic HRESP, HREADYOUT, + output logic PCLK, PRESETn, + output logic [PERIPHS-1:0] PSEL, + output logic PWRITE, + output logic PENABLE, + output logic [31:0] PADDR, output logic [P.XLEN-1:0] PWDATA, // output logic [2:0] PPROT, // not used output logic [P.XLEN/8-1:0] PSTRB, // 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 ); @@ -56,15 +56,15 @@ module ahbapbbridge import cvw::*; #(parameter cvw_t P, logic PREADYOUT; // convert AHB to APB signals - assign PCLK = HCLK; + assign PCLK = HCLK; assign PRESETn = HRESETn; // 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 // 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 #(PERIPHS) selreg(HCLK, ~HRESETn, HREADY, HSEL & {PERIPHS{initTrans}}, PSEL); // 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 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 // 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 assign HRESP = 0; // bridge never indicates errors endmodule -