The privileged unit is parameterized using Lim's method.

This commit is contained in:
Ross Thompson 2023-05-26 12:03:46 -05:00
parent 4d961bd080
commit 8cf38b28aa
13 changed files with 238 additions and 263 deletions

View File

@ -28,18 +28,14 @@
// and limitations under the License. // and limitations under the License.
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
`include "wally-config.vh" module csr import cvw::*; #(parameter cvw_t P, MIP = 12'h344, SIP = 12'h144) (
module csr #(parameter
MIP = 12'h344,
SIP = 12'h144) (
input logic clk, reset, input logic clk, reset,
input logic FlushM, FlushW, input logic FlushM, FlushW,
input logic StallE, StallM, StallW, input logic StallE, StallM, StallW,
input logic [31:0] InstrM, // current instruction input logic [31:0] InstrM, // current instruction
input logic [31:0] InstrOrigM, // Original compressed or uncompressed instruction in Memory stage for Illegal Instruction MTVAL input logic [31:0] InstrOrigM, // Original compressed or uncompressed instruction in Memory stage for Illegal Instruction MTVAL
input logic [`XLEN-1:0] PCM, PC2NextF, // program counter, next PC going to trap/return logic input logic [P.XLEN-1:0] PCM, PC2NextF, // program counter, next PC going to trap/return logic
input logic [`XLEN-1:0] SrcAM, IEUAdrM, // SrcA and memory address from IEU input logic [P.XLEN-1:0] SrcAM, IEUAdrM, // SrcA and memory address from IEU
input logic CSRReadM, CSRWriteM, // read or write CSR input logic CSRReadM, CSRWriteM, // read or write CSR
input logic TrapM, // trap is occurring input logic TrapM, // trap is occurring
input logic mretM, sretM, wfiM, // return or WFI instruction input logic mretM, sretM, wfiM, // return or WFI instruction
@ -80,48 +76,48 @@ module csr #(parameter
output logic [1:0] STATUS_MPP, output logic [1:0] STATUS_MPP,
output logic STATUS_SPP, STATUS_TSR, STATUS_TVM, output logic STATUS_SPP, STATUS_TSR, STATUS_TVM,
output logic [15:0] MEDELEG_REGW, output logic [15:0] MEDELEG_REGW,
output logic [`XLEN-1:0] SATP_REGW, output logic [P.XLEN-1:0] SATP_REGW,
output logic [11:0] MIP_REGW, MIE_REGW, MIDELEG_REGW, output logic [11:0] MIP_REGW, MIE_REGW, MIDELEG_REGW,
output logic STATUS_MIE, STATUS_SIE, output logic STATUS_MIE, STATUS_SIE,
output logic STATUS_MXR, STATUS_SUM, STATUS_MPRV, STATUS_TW, output logic STATUS_MXR, STATUS_SUM, STATUS_MPRV, STATUS_TW,
output logic [1:0] STATUS_FS, output logic [1:0] STATUS_FS,
output var logic [7:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES-1:0], output var logic [7:0] PMPCFG_ARRAY_REGW[P.PMP_ENTRIES-1:0],
output var logic [`PA_BITS-3:0] PMPADDR_ARRAY_REGW[`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 [`XLEN-1:0] CSRReadValW, // value read from CSR output logic [P.XLEN-1:0] CSRReadValW, // value read from CSR
output logic [`XLEN-1:0] UnalignedPCNextF, // Next PC, accounting for traps and returns output logic [P.XLEN-1:0] UnalignedPCNextF, // Next PC, accounting for traps and returns
output logic IllegalCSRAccessM, // Illegal CSR access: CSR doesn't exist or is inaccessible at this privilege level output logic IllegalCSRAccessM, // Illegal CSR access: CSR doesn't exist or is inaccessible at this privilege level
output logic BigEndianM // memory access is big-endian based on privilege mode and STATUS register endian fields output logic BigEndianM // memory access is big-endian based on privilege mode and STATUS register endian fields
); );
logic [`XLEN-1:0] CSRMReadValM, CSRSReadValM, CSRUReadValM, CSRCReadValM; logic [P.XLEN-1:0] CSRMReadValM, CSRSReadValM, CSRUReadValM, CSRCReadValM;
logic [`XLEN-1:0] CSRReadValM; logic [P.XLEN-1:0] CSRReadValM;
logic [`XLEN-1:0] CSRSrcM; logic [P.XLEN-1:0] CSRSrcM;
logic [`XLEN-1:0] CSRRWM, CSRRSM, CSRRCM; logic [P.XLEN-1:0] CSRRWM, CSRRSM, CSRRCM;
logic [`XLEN-1:0] CSRWriteValM; logic [P.XLEN-1:0] CSRWriteValM;
logic [`XLEN-1:0] MSTATUS_REGW, SSTATUS_REGW, MSTATUSH_REGW; logic [P.XLEN-1:0] MSTATUS_REGW, SSTATUS_REGW, MSTATUSH_REGW;
logic [`XLEN-1:0] STVEC_REGW, MTVEC_REGW; logic [P.XLEN-1:0] STVEC_REGW, MTVEC_REGW;
logic [`XLEN-1:0] MEPC_REGW, SEPC_REGW; logic [P.XLEN-1:0] MEPC_REGW, SEPC_REGW;
logic [31:0] MCOUNTINHIBIT_REGW, MCOUNTEREN_REGW, SCOUNTEREN_REGW; logic [31:0] MCOUNTINHIBIT_REGW, MCOUNTEREN_REGW, SCOUNTEREN_REGW;
logic WriteMSTATUSM, WriteMSTATUSHM, WriteSSTATUSM; logic WriteMSTATUSM, WriteMSTATUSHM, WriteSSTATUSM;
logic CSRMWriteM, CSRSWriteM, CSRUWriteM; logic CSRMWriteM, CSRSWriteM, CSRUWriteM;
logic UngatedCSRMWriteM; logic UngatedCSRMWriteM;
logic WriteFRMM, WriteFFLAGSM; logic WriteFRMM, WriteFFLAGSM;
logic [`XLEN-1:0] UnalignedNextEPCM, NextEPCM, NextMtvalM; logic [P.XLEN-1:0] UnalignedNextEPCM, NextEPCM, NextMtvalM;
logic [4:0] NextCauseM; logic [4:0] NextCauseM;
logic [11:0] CSRAdrM; logic [11:0] CSRAdrM;
logic IllegalCSRCAccessM, IllegalCSRMAccessM, IllegalCSRSAccessM, IllegalCSRUAccessM; logic IllegalCSRCAccessM, IllegalCSRMAccessM, IllegalCSRSAccessM, IllegalCSRUAccessM;
logic InsufficientCSRPrivilegeM; logic InsufficientCSRPrivilegeM;
logic IllegalCSRMWriteReadonlyM; logic IllegalCSRMWriteReadonlyM;
logic [`XLEN-1:0] CSRReadVal2M; logic [P.XLEN-1:0] CSRReadVal2M;
logic [11:0] MIP_REGW_writeable; logic [11:0] MIP_REGW_writeable;
logic [`XLEN-1:0] TVecM, TrapVectorM, NextFaultMtvalM; logic [P.XLEN-1:0] TVecM, TrapVectorM, NextFaultMtvalM;
logic MTrapM, STrapM; logic MTrapM, STrapM;
logic [`XLEN-1:0] EPC; logic [P.XLEN-1:0] EPC;
logic RetM; logic RetM;
logic SelMtvecM; logic SelMtvecM;
logic [`XLEN-1:0] TVecAlignedM; logic [P.XLEN-1:0] TVecAlignedM;
logic InstrValidNotFlushedM; logic InstrValidNotFlushedM;
logic STimerInt; logic STimerInt;
@ -136,7 +132,7 @@ module csr #(parameter
if (InterruptM) NextFaultMtvalM = 0; if (InterruptM) NextFaultMtvalM = 0;
else case (CauseM) else case (CauseM)
12, 1, 3: NextFaultMtvalM = PCM; // Instruction page/access faults, breakpoint 12, 1, 3: NextFaultMtvalM = PCM; // Instruction page/access faults, breakpoint
2: NextFaultMtvalM = {{(`XLEN-32){1'b0}}, InstrOrigM}; // Illegal instruction fault 2: NextFaultMtvalM = {{(P.XLEN-32){1'b0}}, InstrOrigM}; // Illegal instruction fault
0, 4, 6, 13, 15, 5, 7: NextFaultMtvalM = IEUAdrM; // Instruction misaligned, Load/Store Misaligned/page/access faults 0, 4, 6, 13, 15, 5, 7: NextFaultMtvalM = IEUAdrM; // Instruction misaligned, Load/Store Misaligned/page/access faults
default: NextFaultMtvalM = 0; // Ecall, interrupts default: NextFaultMtvalM = 0; // Ecall, interrupts
endcase endcase
@ -146,17 +142,17 @@ module csr #(parameter
/////////////////////////////////////////// ///////////////////////////////////////////
// Select trap vector from STVEC or MTVEC and word-align // Select trap vector from STVEC or MTVEC and word-align
assign SelMtvecM = (NextPrivilegeModeM == `M_MODE); assign SelMtvecM = (NextPrivilegeModeM == P.M_MODE);
mux2 #(`XLEN) tvecmux(STVEC_REGW, MTVEC_REGW, SelMtvecM, TVecM); mux2 #(P.XLEN) tvecmux(STVEC_REGW, MTVEC_REGW, SelMtvecM, TVecM);
assign TVecAlignedM = {TVecM[`XLEN-1:2], 2'b00}; assign TVecAlignedM = {TVecM[P.XLEN-1:2], 2'b00};
// Support vectored interrupts // Support vectored interrupts
if(`VECTORED_INTERRUPTS_SUPPORTED) begin:vec if(P.VECTORED_INTERRUPTS_SUPPORTED) begin:vec
logic VectoredM; logic VectoredM;
logic [`XLEN-1:0] TVecPlusCauseM; logic [P.XLEN-1:0] TVecPlusCauseM;
assign VectoredM = InterruptM & (TVecM[1:0] == 2'b01); assign VectoredM = InterruptM & (TVecM[1:0] == 2'b01);
assign TVecPlusCauseM = {TVecAlignedM[`XLEN-1:6], CauseM, 2'b00}; // 64-byte alignment allows concatenation rather than addition assign TVecPlusCauseM = {TVecAlignedM[P.XLEN-1:6], CauseM, 2'b00}; // 64-byte alignment allows concatenation rather than addition
mux2 #(`XLEN) trapvecmux(TVecAlignedM, TVecPlusCauseM, VectoredM, TrapVectorM); mux2 #(P.XLEN) trapvecmux(TVecAlignedM, TVecPlusCauseM, VectoredM, TrapVectorM);
end else end else
assign TrapVectorM = TVecAlignedM; // unvectored interrupt handler can be at any word-aligned address. This is called Sstvecd assign TrapVectorM = TVecAlignedM; // unvectored interrupt handler can be at any word-aligned address. This is called Sstvecd
@ -164,8 +160,8 @@ module csr #(parameter
// A trap sets the PC to TrapVector // A trap sets the PC to TrapVector
// A return sets the PC to MEPC or SEPC // A return sets the PC to MEPC or SEPC
assign RetM = mretM | sretM; assign RetM = mretM | sretM;
mux2 #(`XLEN) epcmux(SEPC_REGW, MEPC_REGW, mretM, EPC); mux2 #(P.XLEN) epcmux(SEPC_REGW, MEPC_REGW, mretM, EPC);
mux3 #(`XLEN) pcmux3(PC2NextF, EPC, TrapVectorM, {TrapM, RetM}, UnalignedPCNextF); mux3 #(P.XLEN) pcmux3(PC2NextF, EPC, TrapVectorM, {TrapM, RetM}, UnalignedPCNextF);
/////////////////////////////////////////// ///////////////////////////////////////////
// CSRWriteValM // CSRWriteValM
@ -173,10 +169,10 @@ module csr #(parameter
always_comb begin always_comb begin
// Choose either rs1 or uimm[4:0] as source // Choose either rs1 or uimm[4:0] as source
CSRSrcM = InstrM[14] ? {{(`XLEN-5){1'b0}}, InstrM[19:15]} : SrcAM; CSRSrcM = InstrM[14] ? {{(P.XLEN-5){1'b0}}, InstrM[19:15]} : SrcAM;
// CSR set and clear for MIP/SIP should only touch internal state, not interrupt inputs // CSR set and clear for MIP/SIP should only touch internal state, not interrupt inputs
if (CSRAdrM == MIP | CSRAdrM == SIP) CSRReadVal2M = {{(`XLEN-12){1'b0}}, MIP_REGW_writeable}; if (CSRAdrM == MIP | CSRAdrM == SIP) CSRReadVal2M = {{(P.XLEN-12){1'b0}}, MIP_REGW_writeable};
else CSRReadVal2M = CSRReadValM; else CSRReadVal2M = CSRReadValM;
// Compute AND/OR modification // Compute AND/OR modification
@ -197,26 +193,26 @@ module csr #(parameter
assign CSRAdrM = InstrM[31:20]; assign CSRAdrM = InstrM[31:20];
assign UnalignedNextEPCM = TrapM ? ((wfiM & IntPendingM) ? PCM+4 : PCM) : CSRWriteValM; assign UnalignedNextEPCM = TrapM ? ((wfiM & IntPendingM) ? PCM+4 : PCM) : CSRWriteValM;
assign NextEPCM = `C_SUPPORTED ? {UnalignedNextEPCM[`XLEN-1:1], 1'b0} : {UnalignedNextEPCM[`XLEN-1:2], 2'b00}; // 3.1.15 alignment assign NextEPCM = P.C_SUPPORTED ? {UnalignedNextEPCM[P.XLEN-1:1], 1'b0} : {UnalignedNextEPCM[P.XLEN-1:2], 2'b00}; // 3.1.15 alignment
assign NextCauseM = TrapM ? {InterruptM, CauseM}: {CSRWriteValM[`XLEN-1], CSRWriteValM[3:0]}; assign NextCauseM = TrapM ? {InterruptM, CauseM}: {CSRWriteValM[P.XLEN-1], CSRWriteValM[3:0]};
assign NextMtvalM = TrapM ? NextFaultMtvalM : CSRWriteValM; assign NextMtvalM = TrapM ? NextFaultMtvalM : CSRWriteValM;
assign UngatedCSRMWriteM = CSRWriteM & (PrivilegeModeW == `M_MODE); assign UngatedCSRMWriteM = CSRWriteM & (PrivilegeModeW == P.M_MODE);
assign CSRMWriteM = UngatedCSRMWriteM & InstrValidNotFlushedM; assign CSRMWriteM = UngatedCSRMWriteM & InstrValidNotFlushedM;
assign CSRSWriteM = CSRWriteM & (|PrivilegeModeW) & InstrValidNotFlushedM; assign CSRSWriteM = CSRWriteM & (|PrivilegeModeW) & InstrValidNotFlushedM;
assign CSRUWriteM = CSRWriteM & InstrValidNotFlushedM; assign CSRUWriteM = CSRWriteM & InstrValidNotFlushedM;
assign MTrapM = TrapM & (NextPrivilegeModeM == `M_MODE); assign MTrapM = TrapM & (NextPrivilegeModeM == P.M_MODE);
assign STrapM = TrapM & (NextPrivilegeModeM == `S_MODE) & `S_SUPPORTED; assign STrapM = TrapM & (NextPrivilegeModeM == P.S_MODE) & P.S_SUPPORTED;
/////////////////////////////////////////// ///////////////////////////////////////////
// CSRs // CSRs
/////////////////////////////////////////// ///////////////////////////////////////////
csri csri(.clk, .reset, csri #(P) csri(.clk, .reset,
.CSRMWriteM, .CSRSWriteM, .CSRWriteValM, .CSRAdrM, .CSRMWriteM, .CSRSWriteM, .CSRWriteValM, .CSRAdrM,
.MExtInt, .SExtInt, .MTimerInt, .STimerInt, .MSwInt, .MExtInt, .SExtInt, .MTimerInt, .STimerInt, .MSwInt,
.MIDELEG_REGW, .MIP_REGW, .MIE_REGW, .MIP_REGW_writeable); .MIDELEG_REGW, .MIP_REGW, .MIE_REGW, .MIP_REGW_writeable);
csrsr csrsr(.clk, .reset, .StallW, csrsr #(P) csrsr(.clk, .reset, .StallW,
.WriteMSTATUSM, .WriteMSTATUSHM, .WriteSSTATUSM, .WriteMSTATUSM, .WriteMSTATUSHM, .WriteSSTATUSM,
.TrapM, .FRegWriteM, .NextPrivilegeModeM, .PrivilegeModeW, .TrapM, .FRegWriteM, .NextPrivilegeModeM, .PrivilegeModeW,
.mretM, .sretM, .WriteFRMM, .WriteFFLAGSM, .CSRWriteValM, .SelHPTW, .mretM, .sretM, .WriteFRMM, .WriteFFLAGSM, .CSRWriteValM, .SelHPTW,
@ -225,7 +221,7 @@ module csr #(parameter
.STATUS_MIE, .STATUS_SIE, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_TVM, .STATUS_MIE, .STATUS_SIE, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_TVM,
.STATUS_FS, .BigEndianM); .STATUS_FS, .BigEndianM);
csrm csrm(.clk, .reset, csrm #(P) csrm(.clk, .reset,
.UngatedCSRMWriteM, .CSRMWriteM, .MTrapM, .CSRAdrM, .UngatedCSRMWriteM, .CSRMWriteM, .MTrapM, .CSRAdrM,
.NextEPCM, .NextCauseM, .NextMtvalM, .MSTATUS_REGW, .MSTATUSH_REGW, .NextEPCM, .NextCauseM, .NextMtvalM, .MSTATUS_REGW, .MSTATUSH_REGW,
.CSRWriteValM, .CSRMReadValM, .MTVEC_REGW, .CSRWriteValM, .CSRMReadValM, .MTVEC_REGW,
@ -235,8 +231,8 @@ module csr #(parameter
.IllegalCSRMAccessM, .IllegalCSRMWriteReadonlyM); .IllegalCSRMAccessM, .IllegalCSRMWriteReadonlyM);
if (`S_SUPPORTED) begin:csrs if (P.S_SUPPORTED) begin:csrs
csrs csrs(.clk, .reset, csrs #(P) csrs(.clk, .reset,
.CSRSWriteM, .STrapM, .CSRAdrM, .CSRSWriteM, .STrapM, .CSRAdrM,
.NextEPCM, .NextCauseM, .NextMtvalM, .SSTATUS_REGW, .NextEPCM, .NextCauseM, .NextMtvalM, .SSTATUS_REGW,
.STATUS_TVM, .MCOUNTEREN_TM(MCOUNTEREN_REGW[1]), .STATUS_TVM, .MCOUNTEREN_TM(MCOUNTEREN_REGW[1]),
@ -256,8 +252,8 @@ module csr #(parameter
end end
// Floating Point CSRs in User Mode only needed if Floating Point is supported // Floating Point CSRs in User Mode only needed if Floating Point is supported
if (`F_SUPPORTED | `D_SUPPORTED) begin:csru if (P.F_SUPPORTED | P.D_SUPPORTED) begin:csru
csru csru(.clk, .reset, .InstrValidNotFlushedM, csru #(P) csru(.clk, .reset, .InstrValidNotFlushedM,
.CSRUWriteM, .CSRAdrM, .CSRWriteValM, .STATUS_FS, .CSRUReadValM, .CSRUWriteM, .CSRAdrM, .CSRWriteValM, .STATUS_FS, .CSRUReadValM,
.SetFflagsM, .FRM_REGW, .WriteFRMM, .WriteFFLAGSM, .SetFflagsM, .FRM_REGW, .WriteFRMM, .WriteFFLAGSM,
.IllegalCSRUAccessM); .IllegalCSRUAccessM);
@ -267,8 +263,8 @@ module csr #(parameter
assign IllegalCSRUAccessM = 1; assign IllegalCSRUAccessM = 1;
end end
if (`ZICOUNTERS_SUPPORTED) begin:counters if (P.ZICOUNTERS_SUPPORTED) begin:counters
csrc counters(.clk, .reset, .StallE, .StallM, .FlushM, csrc #(P) counters(.clk, .reset, .StallE, .StallM, .FlushM,
.InstrValidNotFlushedM, .LoadStallD, .StoreStallD, .CSRWriteM, .CSRMWriteM, .InstrValidNotFlushedM, .LoadStallD, .StoreStallD, .CSRWriteM, .CSRMWriteM,
.BPDirPredWrongM, .BTAWrongM, .RASPredPCWrongM, .IClassWrongM, .BPWrongM, .BPDirPredWrongM, .BTAWrongM, .RASPredPCWrongM, .IClassWrongM, .BPWrongM,
.InstrClassM, .DCacheMiss, .DCacheAccess, .ICacheMiss, .ICacheAccess, .sfencevmaM, .InstrClassM, .DCacheMiss, .DCacheAccess, .ICacheMiss, .ICacheAccess, .sfencevmaM,
@ -283,11 +279,11 @@ module csr #(parameter
// merge CSR Reads // merge CSR Reads
assign CSRReadValM = CSRUReadValM | CSRSReadValM | CSRMReadValM | CSRCReadValM; assign CSRReadValM = CSRUReadValM | CSRSReadValM | CSRMReadValM | CSRCReadValM;
flopenrc #(`XLEN) CSRValWReg(clk, reset, FlushW, ~StallW, CSRReadValM, CSRReadValW); flopenrc #(P.XLEN) CSRValWReg(clk, reset, FlushW, ~StallW, CSRReadValM, CSRReadValW);
// merge illegal accesses: illegal if none of the CSR addresses is legal or privilege is insufficient // merge illegal accesses: illegal if none of the CSR addresses is legal or privilege is insufficient
assign InsufficientCSRPrivilegeM = (CSRAdrM[9:8] == 2'b11 & PrivilegeModeW != `M_MODE) | assign InsufficientCSRPrivilegeM = (CSRAdrM[9:8] == 2'b11 & PrivilegeModeW != P.M_MODE) |
(CSRAdrM[9:8] == 2'b01 & PrivilegeModeW == `U_MODE); (CSRAdrM[9:8] == 2'b01 & PrivilegeModeW == P.U_MODE);
assign IllegalCSRAccessM = ((IllegalCSRCAccessM & IllegalCSRMAccessM & assign IllegalCSRAccessM = ((IllegalCSRCAccessM & IllegalCSRMAccessM &
IllegalCSRSAccessM & IllegalCSRUAccessM | IllegalCSRSAccessM & IllegalCSRUAccessM |
InsufficientCSRPrivilegeM) & CSRReadM) | IllegalCSRMWriteReadonlyM; InsufficientCSRPrivilegeM) & CSRReadM) | IllegalCSRMWriteReadonlyM;

View File

@ -30,8 +30,7 @@
// and limitations under the License. // and limitations under the License.
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
`include "wally-config.vh" module csrc import cvw::*; #(parameter cvw_t P,
module csrc #(parameter
MHPMCOUNTERBASE = 12'hB00, MHPMCOUNTERBASE = 12'hB00,
MTIME = 12'hB01, // this is a memory-mapped register; no such CSR exists, and access should fault MTIME = 12'hB01, // this is a memory-mapped register; no such CSR exists, and access should fault
MHPMCOUNTERHBASE = 12'hB80, MHPMCOUNTERHBASE = 12'hB80,
@ -67,22 +66,22 @@ module csrc #(parameter
input logic FDivBusyE, // floating point divide busy input logic FDivBusyE, // floating point divide busy
input logic [11:0] CSRAdrM, input logic [11:0] CSRAdrM,
input logic [1:0] PrivilegeModeW, input logic [1:0] PrivilegeModeW,
input logic [`XLEN-1:0] CSRWriteValM, input logic [P.XLEN-1:0] CSRWriteValM,
input logic [31:0] MCOUNTINHIBIT_REGW, MCOUNTEREN_REGW, SCOUNTEREN_REGW, input logic [31:0] MCOUNTINHIBIT_REGW, MCOUNTEREN_REGW, SCOUNTEREN_REGW,
input logic [63:0] MTIME_CLINT, input logic [63:0] MTIME_CLINT,
output logic [`XLEN-1:0] CSRCReadValM, output logic [P.XLEN-1:0] CSRCReadValM,
output logic IllegalCSRCAccessM output logic IllegalCSRCAccessM
); );
logic [4:0] CounterNumM; logic [4:0] CounterNumM;
logic [`XLEN-1:0] HPMCOUNTER_REGW[`COUNTERS-1:0]; logic [P.XLEN-1:0] HPMCOUNTER_REGW[P.COUNTERS-1:0];
logic [`XLEN-1:0] HPMCOUNTERH_REGW[`COUNTERS-1:0]; logic [P.XLEN-1:0] HPMCOUNTERH_REGW[P.COUNTERS-1:0];
logic LoadStallE, LoadStallM; logic LoadStallE, LoadStallM;
logic StoreStallE, StoreStallM; logic StoreStallE, StoreStallM;
logic [`COUNTERS-1:0] WriteHPMCOUNTERM; logic [P.COUNTERS-1:0] WriteHPMCOUNTERM;
logic [`COUNTERS-1:0] CounterEvent; logic [P.COUNTERS-1:0] CounterEvent;
logic [63:0] HPMCOUNTERPlusM[`COUNTERS-1:0]; logic [63:0] HPMCOUNTERPlusM[P.COUNTERS-1:0];
logic [`XLEN-1:0] NextHPMCOUNTERM[`COUNTERS-1:0]; logic [P.XLEN-1:0] NextHPMCOUNTERM[P.COUNTERS-1:0];
genvar i; genvar i;
// Interface signals // Interface signals
@ -93,8 +92,8 @@ module csrc #(parameter
assign CounterEvent[0] = 1'b1; // MCYCLE always increments assign CounterEvent[0] = 1'b1; // MCYCLE always increments
assign CounterEvent[1] = 1'b0; // Counter 1 doesn't exist assign CounterEvent[1] = 1'b0; // Counter 1 doesn't exist
assign CounterEvent[2] = InstrValidNotFlushedM; // MINSTRET instructions retired assign CounterEvent[2] = InstrValidNotFlushedM; // MINSTRET instructions retired
if(`QEMU) begin: cevent // No other performance counters in QEMU if(P.QEMU) begin: cevent // No other performance counters in QEMU
assign CounterEvent[`COUNTERS-1:3] = 0; assign CounterEvent[P.COUNTERS-1:3] = 0;
end else begin: cevent // User-defined counters end else begin: cevent // User-defined counters
assign CounterEvent[3] = InstrClassM[0] & InstrValidNotFlushedM; // branch instruction assign CounterEvent[3] = InstrClassM[0] & InstrValidNotFlushedM; // branch instruction
assign CounterEvent[4] = InstrClassM[1] & ~InstrClassM[2] & InstrValidNotFlushedM; // jump and not return instructions assign CounterEvent[4] = InstrClassM[1] & ~InstrClassM[2] & InstrValidNotFlushedM; // jump and not return instructions
@ -121,26 +120,26 @@ module csrc #(parameter
// DivBusyE will never be assert high since this configuration uses the FPU to do integer division // DivBusyE will never be assert high since this configuration uses the FPU to do integer division
assign CounterEvent[24] = DivBusyE | FDivBusyE; // division cycles *** RT: might need to be delay until the next cycle assign CounterEvent[24] = DivBusyE | FDivBusyE; // division cycles *** RT: might need to be delay until the next cycle
// coverage on // coverage on
assign CounterEvent[`COUNTERS-1:25] = 0; // eventually give these sources, including FP instructions, I$/D$ misses, branches and mispredictions assign CounterEvent[P.COUNTERS-1:25] = 0; // eventually give these sources, including FP instructions, I$/D$ misses, branches and mispredictions
end end
// Counter update and write logic // Counter update and write logic
for (i = 0; i < `COUNTERS; i = i+1) begin:cntr for (i = 0; i < P.COUNTERS; i = i+1) begin:cntr
assign WriteHPMCOUNTERM[i] = CSRMWriteM & (CSRAdrM == MHPMCOUNTERBASE + i); assign WriteHPMCOUNTERM[i] = CSRMWriteM & (CSRAdrM == MHPMCOUNTERBASE + i);
assign NextHPMCOUNTERM[i][`XLEN-1:0] = WriteHPMCOUNTERM[i] ? CSRWriteValM : HPMCOUNTERPlusM[i][`XLEN-1:0]; assign NextHPMCOUNTERM[i][P.XLEN-1:0] = WriteHPMCOUNTERM[i] ? CSRWriteValM : HPMCOUNTERPlusM[i][P.XLEN-1:0];
always_ff @(posedge clk) //, posedge reset) // ModelSim doesn't like syntax of passing array element to flop always_ff @(posedge clk) //, posedge reset) // ModelSim doesn't like syntax of passing array element to flop
if (reset) HPMCOUNTER_REGW[i][`XLEN-1:0] <= #1 0; if (reset) HPMCOUNTER_REGW[i][P.XLEN-1:0] <= #1 0;
else HPMCOUNTER_REGW[i][`XLEN-1:0] <= #1 NextHPMCOUNTERM[i]; else HPMCOUNTER_REGW[i][P.XLEN-1:0] <= #1 NextHPMCOUNTERM[i];
if (`XLEN==32) begin // write high and low separately if (P.XLEN==32) begin // write high and low separately
logic [`COUNTERS-1:0] WriteHPMCOUNTERHM; logic [P.COUNTERS-1:0] WriteHPMCOUNTERHM;
logic [`XLEN-1:0] NextHPMCOUNTERHM[`COUNTERS-1:0]; logic [P.XLEN-1:0] NextHPMCOUNTERHM[P.COUNTERS-1:0];
assign HPMCOUNTERPlusM[i] = {HPMCOUNTERH_REGW[i], HPMCOUNTER_REGW[i]} + {63'b0, CounterEvent[i] & ~MCOUNTINHIBIT_REGW[i]}; assign HPMCOUNTERPlusM[i] = {HPMCOUNTERH_REGW[i], HPMCOUNTER_REGW[i]} + {63'b0, CounterEvent[i] & ~MCOUNTINHIBIT_REGW[i]};
assign WriteHPMCOUNTERHM[i] = CSRMWriteM & (CSRAdrM == MHPMCOUNTERHBASE + i); assign WriteHPMCOUNTERHM[i] = CSRMWriteM & (CSRAdrM == MHPMCOUNTERHBASE + i);
assign NextHPMCOUNTERHM[i] = WriteHPMCOUNTERHM[i] ? CSRWriteValM : HPMCOUNTERPlusM[i][63:32]; assign NextHPMCOUNTERHM[i] = WriteHPMCOUNTERHM[i] ? CSRWriteValM : HPMCOUNTERPlusM[i][63:32];
always_ff @(posedge clk) //, posedge reset) // ModelSim doesn't like syntax of passing array element to flop always_ff @(posedge clk) //, posedge reset) // ModelSim doesn't like syntax of passing array element to flop
if (reset) HPMCOUNTERH_REGW[i][`XLEN-1:0] <= #1 0; if (reset) HPMCOUNTERH_REGW[i][P.XLEN-1:0] <= #1 0;
else HPMCOUNTERH_REGW[i][`XLEN-1:0] <= #1 NextHPMCOUNTERHM[i]; else HPMCOUNTERH_REGW[i][P.XLEN-1:0] <= #1 NextHPMCOUNTERHM[i];
end else begin // XLEN=64; write entire register end else begin // XLEN=64; write entire register
assign HPMCOUNTERPlusM[i] = HPMCOUNTER_REGW[i] + {63'b0, CounterEvent[i] & ~MCOUNTINHIBIT_REGW[i]}; assign HPMCOUNTERPlusM[i] = HPMCOUNTER_REGW[i] + {63'b0, CounterEvent[i] & ~MCOUNTINHIBIT_REGW[i]};
end end
@ -149,17 +148,17 @@ module csrc #(parameter
// Read Counters, or cause excepiton if insufficient privilege in light of COUNTEREN flags // Read Counters, or cause excepiton if insufficient privilege in light of COUNTEREN flags
assign CounterNumM = CSRAdrM[4:0]; // which counter to read? assign CounterNumM = CSRAdrM[4:0]; // which counter to read?
always_comb always_comb
if (PrivilegeModeW == `M_MODE | if (PrivilegeModeW == P.M_MODE |
MCOUNTEREN_REGW[CounterNumM] & (!`S_SUPPORTED | PrivilegeModeW == `S_MODE | SCOUNTEREN_REGW[CounterNumM])) begin MCOUNTEREN_REGW[CounterNumM] & (!P.S_SUPPORTED | PrivilegeModeW == P.S_MODE | SCOUNTEREN_REGW[CounterNumM])) begin
IllegalCSRCAccessM = 0; IllegalCSRCAccessM = 0;
if (`XLEN==64) begin // 64-bit counter reads if (P.XLEN==64) begin // 64-bit counter reads
// Veri lator doesn't realize this only occurs for XLEN=64 // Veri lator doesn't realize this only occurs for XLEN=64
/* verilator lint_off WIDTH */ /* verilator lint_off WIDTH */
if (CSRAdrM == TIME) CSRCReadValM = MTIME_CLINT; // TIME register is a shadow of the memory-mapped MTIME from the CLINT if (CSRAdrM == TIME) CSRCReadValM = MTIME_CLINT; // TIME register is a shadow of the memory-mapped MTIME from the CLINT
/* verilator lint_on WIDTH */ /* verilator lint_on WIDTH */
else if (CSRAdrM >= MHPMCOUNTERBASE & CSRAdrM < MHPMCOUNTERBASE+`COUNTERS & CSRAdrM != MTIME) else if (CSRAdrM >= MHPMCOUNTERBASE & CSRAdrM < MHPMCOUNTERBASE+P.COUNTERS & CSRAdrM != MTIME)
CSRCReadValM = HPMCOUNTER_REGW[CounterNumM]; CSRCReadValM = HPMCOUNTER_REGW[CounterNumM];
else if (CSRAdrM >= HPMCOUNTERBASE & CSRAdrM < HPMCOUNTERBASE+`COUNTERS) else if (CSRAdrM >= HPMCOUNTERBASE & CSRAdrM < HPMCOUNTERBASE+P.COUNTERS)
CSRCReadValM = HPMCOUNTER_REGW[CounterNumM]; CSRCReadValM = HPMCOUNTER_REGW[CounterNumM];
else begin else begin
CSRCReadValM = 0; CSRCReadValM = 0;
@ -171,13 +170,13 @@ module csrc #(parameter
if (CSRAdrM == TIME) CSRCReadValM = MTIME_CLINT[31:0];// TIME register is a shadow of the memory-mapped MTIME from the CLINT if (CSRAdrM == TIME) CSRCReadValM = MTIME_CLINT[31:0];// TIME register is a shadow of the memory-mapped MTIME from the CLINT
else if (CSRAdrM == TIMEH) CSRCReadValM = MTIME_CLINT[63:32]; else if (CSRAdrM == TIMEH) CSRCReadValM = MTIME_CLINT[63:32];
/* verilator lint_on WIDTH */ /* verilator lint_on WIDTH */
else if (CSRAdrM >= MHPMCOUNTERBASE & CSRAdrM < MHPMCOUNTERBASE+`COUNTERS & CSRAdrM != MTIME) else if (CSRAdrM >= MHPMCOUNTERBASE & CSRAdrM < MHPMCOUNTERBASE+P.COUNTERS & CSRAdrM != MTIME)
CSRCReadValM = HPMCOUNTER_REGW[CounterNumM]; CSRCReadValM = HPMCOUNTER_REGW[CounterNumM];
else if (CSRAdrM >= HPMCOUNTERBASE & CSRAdrM < HPMCOUNTERBASE+`COUNTERS) else if (CSRAdrM >= HPMCOUNTERBASE & CSRAdrM < HPMCOUNTERBASE+P.COUNTERS)
CSRCReadValM = HPMCOUNTER_REGW[CounterNumM]; CSRCReadValM = HPMCOUNTER_REGW[CounterNumM];
else if (CSRAdrM >= MHPMCOUNTERHBASE & CSRAdrM < MHPMCOUNTERHBASE+`COUNTERS & CSRAdrM != MTIMEH) else if (CSRAdrM >= MHPMCOUNTERHBASE & CSRAdrM < MHPMCOUNTERHBASE+P.COUNTERS & CSRAdrM != MTIMEH)
CSRCReadValM = HPMCOUNTERH_REGW[CounterNumM]; CSRCReadValM = HPMCOUNTERH_REGW[CounterNumM];
else if (CSRAdrM >= HPMCOUNTERHBASE & CSRAdrM < HPMCOUNTERHBASE+`COUNTERS) else if (CSRAdrM >= HPMCOUNTERHBASE & CSRAdrM < HPMCOUNTERHBASE+P.COUNTERS)
CSRCReadValM = HPMCOUNTERH_REGW[CounterNumM]; CSRCReadValM = HPMCOUNTERH_REGW[CounterNumM];
else begin else begin
CSRCReadValM = 0; CSRCReadValM = 0;

View File

@ -27,16 +27,14 @@
// and limitations under the License. // and limitations under the License.
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
`include "wally-config.vh" module csri import cvw::*; #(parameter cvw_t P,
module csri #(parameter
MIE = 12'h304, MIE = 12'h304,
MIP = 12'h344, MIP = 12'h344,
SIE = 12'h104, SIE = 12'h104,
SIP = 12'h144) ( SIP = 12'h144) (
input logic clk, reset, input logic clk, reset,
input logic CSRMWriteM, CSRSWriteM, input logic CSRMWriteM, CSRSWriteM,
input logic [`XLEN-1:0] CSRWriteValM, input logic [P.XLEN-1:0] CSRWriteValM,
input logic [11:0] CSRAdrM, input logic [11:0] CSRAdrM,
input logic MExtInt, SExtInt, MTimerInt, STimerInt, MSwInt, input logic MExtInt, SExtInt, MTimerInt, STimerInt, MSwInt,
input logic [11:0] MIDELEG_REGW, input logic [11:0] MIDELEG_REGW,
@ -58,8 +56,8 @@ module csri #(parameter
// MEIP, MTIP, MSIP are read-only // MEIP, MTIP, MSIP are read-only
// SEIP, STIP, SSIP is writable in MIP if S mode exists // SEIP, STIP, SSIP is writable in MIP if S mode exists
// SSIP is writable in SIP if S mode exists // SSIP is writable in SIP if S mode exists
if (`S_SUPPORTED) begin:mask if (P.S_SUPPORTED) begin:mask
if (`SSTC_SUPPORTED) begin if (P.SSTC_SUPPORTED) begin
assign MIP_WRITE_MASK = 12'h202; // SEIP and SSIP are writable, but STIP is not writable when STIMECMP is implemented (see SSTC spec) assign MIP_WRITE_MASK = 12'h202; // SEIP and SSIP are writable, but STIP is not writable when STIMECMP is implemented (see SSTC spec)
assign STIP = STimerInt; assign STIP = STimerInt;
end else begin end else begin

View File

@ -31,9 +31,7 @@
// and limitations under the License. // and limitations under the License.
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
`include "wally-config.vh" module csrm import cvw::*; #(parameter cvw_t P,
module csrm #(parameter
// Machine CSRs // Machine CSRs
MVENDORID = 12'hF11, MVENDORID = 12'hF11,
MARCHID = 12'hF12, MARCHID = 12'hF12,
@ -68,52 +66,52 @@ module csrm #(parameter
DSCRATCH0 = 12'h7B2, DSCRATCH0 = 12'h7B2,
DSCRATCH1 = 12'h7B3, DSCRATCH1 = 12'h7B3,
// Constants // Constants
ZERO = {(`XLEN){1'b0}}, ZERO = {(P.XLEN){1'b0}},
MEDELEG_MASK = 16'hB3FF, MEDELEG_MASK = 16'hB3FF,
MIDELEG_MASK = 12'h222 // we choose to not make machine interrupts delegable MIDELEG_MASK = 12'h222 // we choose to not make machine interrupts delegable
) ( ) (
input logic clk, reset, input logic clk, reset,
input logic UngatedCSRMWriteM, CSRMWriteM, MTrapM, input logic UngatedCSRMWriteM, CSRMWriteM, MTrapM,
input logic [11:0] CSRAdrM, input logic [11:0] CSRAdrM,
input logic [`XLEN-1:0] NextEPCM, NextMtvalM, MSTATUS_REGW, MSTATUSH_REGW, input logic [P.XLEN-1:0] NextEPCM, NextMtvalM, MSTATUS_REGW, MSTATUSH_REGW,
input logic [4:0] NextCauseM, input logic [4:0] NextCauseM,
input logic [`XLEN-1:0] CSRWriteValM, input logic [P.XLEN-1:0] CSRWriteValM,
input logic [11:0] MIP_REGW, MIE_REGW, input logic [11:0] MIP_REGW, MIE_REGW,
output logic [`XLEN-1:0] CSRMReadValM, MTVEC_REGW, output logic [P.XLEN-1:0] CSRMReadValM, MTVEC_REGW,
output logic [`XLEN-1:0] MEPC_REGW, output logic [P.XLEN-1:0] MEPC_REGW,
output logic [31:0] MCOUNTEREN_REGW, MCOUNTINHIBIT_REGW, output logic [31:0] MCOUNTEREN_REGW, MCOUNTINHIBIT_REGW,
output logic [15:0] MEDELEG_REGW, output logic [15:0] MEDELEG_REGW,
output logic [11:0] MIDELEG_REGW, output logic [11:0] MIDELEG_REGW,
output var logic [7:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES-1:0], output var logic [7:0] PMPCFG_ARRAY_REGW[P.PMP_ENTRIES-1:0],
output var logic [`PA_BITS-3:0] PMPADDR_ARRAY_REGW [`PMP_ENTRIES-1:0], output var logic [P.PA_BITS-3:0] PMPADDR_ARRAY_REGW [P.PMP_ENTRIES-1:0],
output logic WriteMSTATUSM, WriteMSTATUSHM, output logic WriteMSTATUSM, WriteMSTATUSHM,
output logic IllegalCSRMAccessM, IllegalCSRMWriteReadonlyM output logic IllegalCSRMAccessM, IllegalCSRMWriteReadonlyM
); );
logic [`XLEN-1:0] MISA_REGW, MHARTID_REGW; logic [P.XLEN-1:0] MISA_REGW, MHARTID_REGW;
logic [`XLEN-1:0] MSCRATCH_REGW, MTVAL_REGW, MCAUSE_REGW; logic [P.XLEN-1:0] MSCRATCH_REGW, MTVAL_REGW, MCAUSE_REGW;
logic WriteMTVECM, WriteMEDELEGM, WriteMIDELEGM; logic WriteMTVECM, WriteMEDELEGM, WriteMIDELEGM;
logic WriteMSCRATCHM, WriteMEPCM, WriteMCAUSEM, WriteMTVALM; logic WriteMSCRATCHM, WriteMEPCM, WriteMCAUSEM, WriteMTVALM;
logic WriteMCOUNTERENM, WriteMCOUNTINHIBITM; logic WriteMCOUNTERENM, WriteMCOUNTINHIBITM;
// There are PMP_ENTRIES = 0, 16, or 64 PMPADDR registers, each of which has its own flop // There are PMP_ENTRIES = 0, 16, or 64 PMPADDR registers, each of which has its own flop
genvar i; genvar i;
if (`PMP_ENTRIES > 0) begin:pmp if (P.PMP_ENTRIES > 0) begin:pmp
logic [`PMP_ENTRIES-1:0] WritePMPCFGM; logic [P.PMP_ENTRIES-1:0] WritePMPCFGM;
logic [`PMP_ENTRIES-1:0] WritePMPADDRM ; logic [P.PMP_ENTRIES-1:0] WritePMPADDRM ;
logic [`PMP_ENTRIES-1:0] ADDRLocked, CFGLocked; logic [P.PMP_ENTRIES-1:0] ADDRLocked, CFGLocked;
for(i=0; i<`PMP_ENTRIES; i++) begin for(i=0; i<P.PMP_ENTRIES; i++) begin
// when the lock bit is set, don't allow writes to the PMPCFG or PMPADDR // when the lock bit is set, don't allow writes to the PMPCFG or PMPADDR
// also, when the lock bit of the next entry is set and the next entry is TOR, don't allow writes to this entry PMPADDR // also, when the lock bit of the next entry is set and the next entry is TOR, don't allow writes to this entry PMPADDR
assign CFGLocked[i] = PMPCFG_ARRAY_REGW[i][7]; assign CFGLocked[i] = PMPCFG_ARRAY_REGW[i][7];
if (i == `PMP_ENTRIES-1) if (i == P.PMP_ENTRIES-1)
assign ADDRLocked[i] = PMPCFG_ARRAY_REGW[i][7]; assign ADDRLocked[i] = PMPCFG_ARRAY_REGW[i][7];
else else
assign ADDRLocked[i] = PMPCFG_ARRAY_REGW[i][7] | (PMPCFG_ARRAY_REGW[i+1][7] & PMPCFG_ARRAY_REGW[i+1][4:3] == 2'b01); assign ADDRLocked[i] = PMPCFG_ARRAY_REGW[i][7] | (PMPCFG_ARRAY_REGW[i+1][7] & PMPCFG_ARRAY_REGW[i+1][4:3] == 2'b01);
assign WritePMPADDRM[i] = (CSRMWriteM & (CSRAdrM == (PMPADDR0+i))) & ~ADDRLocked[i]; assign WritePMPADDRM[i] = (CSRMWriteM & (CSRAdrM == (PMPADDR0+i))) & ~ADDRLocked[i];
flopenr #(`PA_BITS-2) PMPADDRreg(clk, reset, WritePMPADDRM[i], CSRWriteValM[`PA_BITS-3:0], PMPADDR_ARRAY_REGW[i]); flopenr #(P.PA_BITS-2) PMPADDRreg(clk, reset, WritePMPADDRM[i], CSRWriteValM[P.PA_BITS-3:0], PMPADDR_ARRAY_REGW[i]);
if (`XLEN==64) begin if (P.XLEN==64) begin
assign WritePMPCFGM[i] = (CSRMWriteM & (CSRAdrM == (PMPCFG0+2*(i/8)))) & ~CFGLocked[i]; assign WritePMPCFGM[i] = (CSRMWriteM & (CSRAdrM == (PMPCFG0+2*(i/8)))) & ~CFGLocked[i];
flopenr #(8) PMPCFGreg(clk, reset, WritePMPCFGM[i], CSRWriteValM[(i%8)*8+7:(i%8)*8], PMPCFG_ARRAY_REGW[i]); flopenr #(8) PMPCFGreg(clk, reset, WritePMPCFGM[i], CSRWriteValM[(i%8)*8+7:(i%8)*8], PMPCFG_ARRAY_REGW[i]);
end else begin end else begin
@ -123,17 +121,17 @@ module csrm #(parameter
end end
end end
localparam MISA_26 = (`MISA) & 32'h03ffffff; localparam MISA_26 = (P.MISA) & 32'h03ffffff;
// MISA is hardwired. Spec says it could be written to disable features, but this is not supported by Wally // MISA is hardwired. Spec says it could be written to disable features, but this is not supported by Wally
assign MISA_REGW = {(`XLEN == 32 ? 2'b01 : 2'b10), {(`XLEN-28){1'b0}}, MISA_26[25:0]}; assign MISA_REGW = {(P.XLEN == 32 ? 2'b01 : 2'b10), {(P.XLEN-28){1'b0}}, MISA_26[25:0]};
// MHARTID is hardwired. It only exists as a signal so that the testbench can easily see it. // MHARTID is hardwired. It only exists as a signal so that the testbench can easily see it.
assign MHARTID_REGW = 0; assign MHARTID_REGW = 0;
// Write machine Mode CSRs // Write machine Mode CSRs
assign WriteMSTATUSM = CSRMWriteM & (CSRAdrM == MSTATUS); assign WriteMSTATUSM = CSRMWriteM & (CSRAdrM == MSTATUS);
assign WriteMSTATUSHM = CSRMWriteM & (CSRAdrM == MSTATUSH)& (`XLEN==32); assign WriteMSTATUSHM = CSRMWriteM & (CSRAdrM == MSTATUSH)& (P.XLEN==32);
assign WriteMTVECM = CSRMWriteM & (CSRAdrM == MTVEC); assign WriteMTVECM = CSRMWriteM & (CSRAdrM == MTVEC);
assign WriteMEDELEGM = CSRMWriteM & (CSRAdrM == MEDELEG); assign WriteMEDELEGM = CSRMWriteM & (CSRAdrM == MEDELEG);
assign WriteMIDELEGM = CSRMWriteM & (CSRAdrM == MIDELEG); assign WriteMIDELEGM = CSRMWriteM & (CSRAdrM == MIDELEG);
@ -147,19 +145,19 @@ module csrm #(parameter
assign IllegalCSRMWriteReadonlyM = UngatedCSRMWriteM & (CSRAdrM == MVENDORID | CSRAdrM == MARCHID | CSRAdrM == MIMPID | CSRAdrM == MHARTID); assign IllegalCSRMWriteReadonlyM = UngatedCSRMWriteM & (CSRAdrM == MVENDORID | CSRAdrM == MARCHID | CSRAdrM == MIMPID | CSRAdrM == MHARTID);
// CSRs // CSRs
flopenr #(`XLEN) MTVECreg(clk, reset, WriteMTVECM, {CSRWriteValM[`XLEN-1:2], 1'b0, CSRWriteValM[0]}, MTVEC_REGW); flopenr #(P.XLEN) MTVECreg(clk, reset, WriteMTVECM, {CSRWriteValM[P.XLEN-1:2], 1'b0, CSRWriteValM[0]}, MTVEC_REGW);
if (`S_SUPPORTED) begin:deleg // DELEG registers should exist if (P.S_SUPPORTED) begin:deleg // DELEG registers should exist
flopenr #(16) MEDELEGreg(clk, reset, WriteMEDELEGM, CSRWriteValM[15:0] & MEDELEG_MASK, MEDELEG_REGW); flopenr #(16) MEDELEGreg(clk, reset, WriteMEDELEGM, CSRWriteValM[15:0] & MEDELEG_MASK, MEDELEG_REGW);
flopenr #(12) MIDELEGreg(clk, reset, WriteMIDELEGM, CSRWriteValM[11:0] & MIDELEG_MASK, MIDELEG_REGW); flopenr #(12) MIDELEGreg(clk, reset, WriteMIDELEGM, CSRWriteValM[11:0] & MIDELEG_MASK, MIDELEG_REGW);
end else assign {MEDELEG_REGW, MIDELEG_REGW} = 0; end else assign {MEDELEG_REGW, MIDELEG_REGW} = 0;
flopenr #(`XLEN) MSCRATCHreg(clk, reset, WriteMSCRATCHM, CSRWriteValM, MSCRATCH_REGW); flopenr #(P.XLEN) MSCRATCHreg(clk, reset, WriteMSCRATCHM, CSRWriteValM, MSCRATCH_REGW);
flopenr #(`XLEN) MEPCreg(clk, reset, WriteMEPCM, NextEPCM, MEPC_REGW); flopenr #(P.XLEN) MEPCreg(clk, reset, WriteMEPCM, NextEPCM, MEPC_REGW);
flopenr #(`XLEN) MCAUSEreg(clk, reset, WriteMCAUSEM, {NextCauseM[4], {(`XLEN-5){1'b0}}, NextCauseM[3:0]}, MCAUSE_REGW); flopenr #(P.XLEN) MCAUSEreg(clk, reset, WriteMCAUSEM, {NextCauseM[4], {(P.XLEN-5){1'b0}}, NextCauseM[3:0]}, MCAUSE_REGW);
if(`QEMU) assign MTVAL_REGW = `XLEN'b0; // MTVAL tied to 0 in QEMU configuration if(P.QEMU) assign MTVAL_REGW = '0; // MTVAL tied to 0 in QEMU configuration
else flopenr #(`XLEN) MTVALreg(clk, reset, WriteMTVALM, NextMtvalM, MTVAL_REGW); else flopenr #(P.XLEN) MTVALreg(clk, reset, WriteMTVALM, NextMtvalM, MTVAL_REGW);
flopenr #(32) MCOUNTINHIBITreg(clk, reset, WriteMCOUNTINHIBITM, CSRWriteValM[31:0], MCOUNTINHIBIT_REGW); flopenr #(32) MCOUNTINHIBITreg(clk, reset, WriteMCOUNTINHIBITM, CSRWriteValM[31:0], MCOUNTINHIBIT_REGW);
if (`U_SUPPORTED) begin: mcounteren // MCOUNTEREN only exists when user mode is supported if (P.U_SUPPORTED) begin: mcounteren // MCOUNTEREN only exists when user mode is supported
flopenr #(32) MCOUNTERENreg(clk, reset, WriteMCOUNTERENM, CSRWriteValM[31:0], MCOUNTEREN_REGW); flopenr #(32) MCOUNTERENreg(clk, reset, WriteMCOUNTERENM, CSRWriteValM[31:0], MCOUNTEREN_REGW);
end else assign MCOUNTEREN_REGW = '0; end else assign MCOUNTEREN_REGW = '0;
@ -168,12 +166,12 @@ module csrm #(parameter
logic [5:0] entry; logic [5:0] entry;
always_comb begin always_comb begin
entry = '0; entry = '0;
IllegalCSRMAccessM = !(`S_SUPPORTED) & (CSRAdrM == MEDELEG | CSRAdrM == MIDELEG); // trap on DELEG register access when no S or N-mode IllegalCSRMAccessM = !(P.S_SUPPORTED) & (CSRAdrM == MEDELEG | CSRAdrM == MIDELEG); // trap on DELEG register access when no S or N-mode
if (CSRAdrM >= PMPADDR0 & CSRAdrM < PMPADDR0 + `PMP_ENTRIES) // reading a PMP entry if (CSRAdrM >= PMPADDR0 & CSRAdrM < PMPADDR0 + P.PMP_ENTRIES) // reading a PMP entry
CSRMReadValM = {{(`XLEN-(`PA_BITS-2)){1'b0}}, PMPADDR_ARRAY_REGW[CSRAdrM - PMPADDR0]}; CSRMReadValM = {{(P.XLEN-(P.PA_BITS-2)){1'b0}}, PMPADDR_ARRAY_REGW[CSRAdrM - PMPADDR0]};
else if (CSRAdrM >= PMPCFG0 & CSRAdrM < PMPCFG0 + `PMP_ENTRIES/4 & (`XLEN==32 | CSRAdrM[0] == 0)) begin else if (CSRAdrM >= PMPCFG0 & CSRAdrM < PMPCFG0 + P.PMP_ENTRIES/4 & (P.XLEN==32 | CSRAdrM[0] == 0)) begin
// only odd-numbered PMPCFG entries exist in RV64 // only odd-numbered PMPCFG entries exist in RV64
if (`XLEN==64) begin if (P.XLEN==64) begin
entry = ({CSRAdrM[11:1], 1'b0} - PMPCFG0)*4; // disregard odd entries in RV64 entry = ({CSRAdrM[11:1], 1'b0} - PMPCFG0)*4; // disregard odd entries in RV64
CSRMReadValM = {PMPCFG_ARRAY_REGW[entry+7],PMPCFG_ARRAY_REGW[entry+6],PMPCFG_ARRAY_REGW[entry+5],PMPCFG_ARRAY_REGW[entry+4], CSRMReadValM = {PMPCFG_ARRAY_REGW[entry+7],PMPCFG_ARRAY_REGW[entry+6],PMPCFG_ARRAY_REGW[entry+5],PMPCFG_ARRAY_REGW[entry+4],
PMPCFG_ARRAY_REGW[entry+3],PMPCFG_ARRAY_REGW[entry+2],PMPCFG_ARRAY_REGW[entry+1],PMPCFG_ARRAY_REGW[entry]}; PMPCFG_ARRAY_REGW[entry+3],PMPCFG_ARRAY_REGW[entry+2],PMPCFG_ARRAY_REGW[entry+1],PMPCFG_ARRAY_REGW[entry]};
@ -186,23 +184,23 @@ module csrm #(parameter
MISA_ADR: CSRMReadValM = MISA_REGW; MISA_ADR: CSRMReadValM = MISA_REGW;
MVENDORID: CSRMReadValM = 0; MVENDORID: CSRMReadValM = 0;
MARCHID: CSRMReadValM = 0; MARCHID: CSRMReadValM = 0;
MIMPID: CSRMReadValM = `XLEN'h100; // pipelined implementation MIMPID: CSRMReadValM = {{P.XLEN-12{1'b0}}, 12'h100}; // pipelined implementation
MHARTID: CSRMReadValM = MHARTID_REGW; // hardwired to 0 MHARTID: CSRMReadValM = MHARTID_REGW; // hardwired to 0
MCONFIGPTR: CSRMReadValM = 0; // hardwired to 0 MCONFIGPTR: CSRMReadValM = 0; // hardwired to 0
MSTATUS: CSRMReadValM = MSTATUS_REGW; MSTATUS: CSRMReadValM = MSTATUS_REGW;
MSTATUSH: CSRMReadValM = MSTATUSH_REGW; MSTATUSH: CSRMReadValM = MSTATUSH_REGW;
MTVEC: CSRMReadValM = MTVEC_REGW; MTVEC: CSRMReadValM = MTVEC_REGW;
MEDELEG: CSRMReadValM = {{(`XLEN-16){1'b0}}, MEDELEG_REGW}; MEDELEG: CSRMReadValM = {{(P.XLEN-16){1'b0}}, MEDELEG_REGW};
MIDELEG: CSRMReadValM = {{(`XLEN-12){1'b0}}, MIDELEG_REGW}; MIDELEG: CSRMReadValM = {{(P.XLEN-12){1'b0}}, MIDELEG_REGW};
MIP: CSRMReadValM = {{(`XLEN-12){1'b0}}, MIP_REGW}; MIP: CSRMReadValM = {{(P.XLEN-12){1'b0}}, MIP_REGW};
MIE: CSRMReadValM = {{(`XLEN-12){1'b0}}, MIE_REGW}; MIE: CSRMReadValM = {{(P.XLEN-12){1'b0}}, MIE_REGW};
MSCRATCH: CSRMReadValM = MSCRATCH_REGW; MSCRATCH: CSRMReadValM = MSCRATCH_REGW;
MEPC: CSRMReadValM = MEPC_REGW; MEPC: CSRMReadValM = MEPC_REGW;
MCAUSE: CSRMReadValM = MCAUSE_REGW; MCAUSE: CSRMReadValM = MCAUSE_REGW;
MTVAL: CSRMReadValM = MTVAL_REGW; MTVAL: CSRMReadValM = MTVAL_REGW;
MTINST: CSRMReadValM = 0; // implemented as trivial zero MTINST: CSRMReadValM = 0; // implemented as trivial zero
MCOUNTEREN:CSRMReadValM = {{(`XLEN-32){1'b0}}, MCOUNTEREN_REGW}; MCOUNTEREN:CSRMReadValM = {{(P.XLEN-32){1'b0}}, MCOUNTEREN_REGW};
MCOUNTINHIBIT:CSRMReadValM = {{(`XLEN-32){1'b0}}, MCOUNTINHIBIT_REGW}; MCOUNTINHIBIT:CSRMReadValM = {{(P.XLEN-32){1'b0}}, MCOUNTINHIBIT_REGW};
default: begin default: begin
CSRMReadValM = 0; CSRMReadValM = 0;

View File

@ -28,9 +28,7 @@
// and limitations under the License. // and limitations under the License.
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
`include "wally-config.vh" module csrs import cvw::*; #(parameter cvw_t P,
module csrs #(parameter
// Supervisor CSRs // Supervisor CSRs
SSTATUS = 12'h100, SSTATUS = 12'h100,
SIE = 12'h104, SIE = 12'h104,
@ -47,16 +45,16 @@ module csrs #(parameter
input logic clk, reset, input logic clk, reset,
input logic CSRSWriteM, STrapM, input logic CSRSWriteM, STrapM,
input logic [11:0] CSRAdrM, input logic [11:0] CSRAdrM,
input logic [`XLEN-1:0] NextEPCM, NextMtvalM, SSTATUS_REGW, input logic [P.XLEN-1:0] NextEPCM, NextMtvalM, SSTATUS_REGW,
input logic [4:0] NextCauseM, input logic [4:0] NextCauseM,
input logic STATUS_TVM, input logic STATUS_TVM,
input logic MCOUNTEREN_TM, // TM bit (1) of MCOUNTEREN; cause illegal instruction when trying to access STIMECMP if clear input logic MCOUNTEREN_TM, // TM bit (1) of MCOUNTEREN; cause illegal instruction when trying to access STIMECMP if clear
input logic [`XLEN-1:0] CSRWriteValM, input logic [P.XLEN-1:0] CSRWriteValM,
input logic [1:0] PrivilegeModeW, input logic [1:0] PrivilegeModeW,
output logic [`XLEN-1:0] CSRSReadValM, STVEC_REGW, output logic [P.XLEN-1:0] CSRSReadValM, STVEC_REGW,
output logic [`XLEN-1:0] SEPC_REGW, output logic [P.XLEN-1:0] SEPC_REGW,
output logic [31:0] SCOUNTEREN_REGW, output logic [31:0] SCOUNTEREN_REGW,
output logic [`XLEN-1:0] SATP_REGW, output logic [P.XLEN-1:0] SATP_REGW,
input logic [11:0] MIP_REGW, MIE_REGW, MIDELEG_REGW, input logic [11:0] MIP_REGW, MIE_REGW, MIDELEG_REGW,
input logic [63:0] MTIME_CLINT, input logic [63:0] MTIME_CLINT,
output logic WriteSSTATUSM, output logic WriteSSTATUSM,
@ -65,14 +63,14 @@ module csrs #(parameter
); );
// Constants // Constants
localparam ZERO = {(`XLEN){1'b0}}; localparam ZERO = {(P.XLEN){1'b0}};
localparam SEDELEG_MASK = ~(ZERO | `XLEN'b111 << 9); localparam SEDELEG_MASK = ~(ZERO | {{P.XLEN-3{1'b0}}, 3'b111} << 9);
logic WriteSTVECM; logic WriteSTVECM;
logic WriteSSCRATCHM, WriteSEPCM; logic WriteSSCRATCHM, WriteSEPCM;
logic WriteSCAUSEM, WriteSTVALM, WriteSATPM, WriteSCOUNTERENM; logic WriteSCAUSEM, WriteSTVALM, WriteSATPM, WriteSCOUNTERENM;
logic WriteSTIMECMPM, WriteSTIMECMPHM; logic WriteSTIMECMPM, WriteSTIMECMPHM;
logic [`XLEN-1:0] SSCRATCH_REGW, STVAL_REGW, SCAUSE_REGW; logic [P.XLEN-1:0] SSCRATCH_REGW, STVAL_REGW, SCAUSE_REGW;
logic [63:0] STIMECMP_REGW; logic [63:0] STIMECMP_REGW;
// write enables // write enables
@ -82,34 +80,34 @@ module csrs #(parameter
assign WriteSEPCM = STrapM | (CSRSWriteM & (CSRAdrM == SEPC)); assign WriteSEPCM = STrapM | (CSRSWriteM & (CSRAdrM == SEPC));
assign WriteSCAUSEM = STrapM | (CSRSWriteM & (CSRAdrM == SCAUSE)); assign WriteSCAUSEM = STrapM | (CSRSWriteM & (CSRAdrM == SCAUSE));
assign WriteSTVALM = STrapM | (CSRSWriteM & (CSRAdrM == STVAL)); assign WriteSTVALM = STrapM | (CSRSWriteM & (CSRAdrM == STVAL));
assign WriteSATPM = CSRSWriteM & (CSRAdrM == SATP) & (PrivilegeModeW == `M_MODE | ~STATUS_TVM); assign WriteSATPM = CSRSWriteM & (CSRAdrM == SATP) & (PrivilegeModeW == P.M_MODE | ~STATUS_TVM);
assign WriteSCOUNTERENM = CSRSWriteM & (CSRAdrM == SCOUNTEREN); assign WriteSCOUNTERENM = CSRSWriteM & (CSRAdrM == SCOUNTEREN);
assign WriteSTIMECMPM = CSRSWriteM & (CSRAdrM == STIMECMP) & (PrivilegeModeW == `M_MODE | MCOUNTEREN_TM); assign WriteSTIMECMPM = CSRSWriteM & (CSRAdrM == STIMECMP) & (PrivilegeModeW == P.M_MODE | MCOUNTEREN_TM);
assign WriteSTIMECMPHM = CSRSWriteM & (CSRAdrM == STIMECMPH) & (PrivilegeModeW == `M_MODE | MCOUNTEREN_TM) & (`XLEN == 32); assign WriteSTIMECMPHM = CSRSWriteM & (CSRAdrM == STIMECMPH) & (PrivilegeModeW == P.M_MODE | MCOUNTEREN_TM) & (P.XLEN == 32);
// CSRs // CSRs
flopenr #(`XLEN) STVECreg(clk, reset, WriteSTVECM, {CSRWriteValM[`XLEN-1:2], 1'b0, CSRWriteValM[0]}, STVEC_REGW); flopenr #(P.XLEN) STVECreg(clk, reset, WriteSTVECM, {CSRWriteValM[P.XLEN-1:2], 1'b0, CSRWriteValM[0]}, STVEC_REGW);
flopenr #(`XLEN) SSCRATCHreg(clk, reset, WriteSSCRATCHM, CSRWriteValM, SSCRATCH_REGW); flopenr #(P.XLEN) SSCRATCHreg(clk, reset, WriteSSCRATCHM, CSRWriteValM, SSCRATCH_REGW);
flopenr #(`XLEN) SEPCreg(clk, reset, WriteSEPCM, NextEPCM, SEPC_REGW); flopenr #(P.XLEN) SEPCreg(clk, reset, WriteSEPCM, NextEPCM, SEPC_REGW);
flopenr #(`XLEN) SCAUSEreg(clk, reset, WriteSCAUSEM, {NextCauseM[4], {(`XLEN-5){1'b0}}, NextCauseM[3:0]}, SCAUSE_REGW); flopenr #(P.XLEN) SCAUSEreg(clk, reset, WriteSCAUSEM, {NextCauseM[4], {(P.XLEN-5){1'b0}}, NextCauseM[3:0]}, SCAUSE_REGW);
flopenr #(`XLEN) STVALreg(clk, reset, WriteSTVALM, NextMtvalM, STVAL_REGW); flopenr #(P.XLEN) STVALreg(clk, reset, WriteSTVALM, NextMtvalM, STVAL_REGW);
if (`VIRTMEM_SUPPORTED) if (P.VIRTMEM_SUPPORTED)
flopenr #(`XLEN) SATPreg(clk, reset, WriteSATPM, CSRWriteValM, SATP_REGW); flopenr #(P.XLEN) SATPreg(clk, reset, WriteSATPM, CSRWriteValM, SATP_REGW);
else else
assign SATP_REGW = 0; // hardwire to zero if virtual memory not supported assign SATP_REGW = 0; // hardwire to zero if virtual memory not supported
flopenr #(32) SCOUNTERENreg(clk, reset, WriteSCOUNTERENM, CSRWriteValM[31:0], SCOUNTEREN_REGW); flopenr #(32) SCOUNTERENreg(clk, reset, WriteSCOUNTERENM, CSRWriteValM[31:0], SCOUNTEREN_REGW);
if (`SSTC_SUPPORTED) begin : sstc if (P.SSTC_SUPPORTED) begin : sstc
if (`XLEN == 64) begin : sstc64 if (P.XLEN == 64) begin : sstc64
flopenl #(`XLEN) STIMECMPreg(clk, reset, WriteSTIMECMPM, CSRWriteValM, 64'hFFFFFFFFFFFFFFFF, STIMECMP_REGW); flopenl #(P.XLEN) STIMECMPreg(clk, reset, WriteSTIMECMPM, CSRWriteValM, 64'hFFFFFFFFFFFFFFFF, STIMECMP_REGW);
end else begin : sstc32 end else begin : sstc32
flopenl #(`XLEN) STIMECMPreg(clk, reset, WriteSTIMECMPM, CSRWriteValM, 32'hFFFFFFFF, STIMECMP_REGW[31:0]); flopenl #(P.XLEN) STIMECMPreg(clk, reset, WriteSTIMECMPM, CSRWriteValM, 32'hFFFFFFFF, STIMECMP_REGW[31:0]);
flopenl #(`XLEN) STIMECMPHreg(clk, reset, WriteSTIMECMPHM, CSRWriteValM, 32'hFFFFFFFF, STIMECMP_REGW[63:32]); flopenl #(P.XLEN) STIMECMPHreg(clk, reset, WriteSTIMECMPHM, CSRWriteValM, 32'hFFFFFFFF, STIMECMP_REGW[63:32]);
end end
end else assign STIMECMP_REGW = 0; end else assign STIMECMP_REGW = 0;
// Supervisor timer interrupt logic // Supervisor timer interrupt logic
// Spec is a bit peculiar - Machine timer interrupts are produced in CLINT, while Supervisor timer interrupts are in CSRs // Spec is a bit peculiar - Machine timer interrupts are produced in CLINT, while Supervisor timer interrupts are in CSRs
if (`SSTC_SUPPORTED) if (P.SSTC_SUPPORTED)
assign STimerInt = ({1'b0, MTIME_CLINT} >= {1'b0, STIMECMP_REGW}); // unsigned comparison assign STimerInt = ({1'b0, MTIME_CLINT} >= {1'b0, STIMECMP_REGW}); // unsigned comparison
else else
assign STimerInt = 0; assign STimerInt = 0;
@ -120,24 +118,24 @@ module csrs #(parameter
case (CSRAdrM) case (CSRAdrM)
SSTATUS: CSRSReadValM = SSTATUS_REGW; SSTATUS: CSRSReadValM = SSTATUS_REGW;
STVEC: CSRSReadValM = STVEC_REGW; STVEC: CSRSReadValM = STVEC_REGW;
SIP: CSRSReadValM = {{(`XLEN-12){1'b0}}, MIP_REGW & 12'h222 & MIDELEG_REGW}; // only read supervisor fields SIP: CSRSReadValM = {{(P.XLEN-12){1'b0}}, MIP_REGW & 12'h222 & MIDELEG_REGW}; // only read supervisor fields
SIE: CSRSReadValM = {{(`XLEN-12){1'b0}}, MIE_REGW & 12'h222 & MIDELEG_REGW}; // only read supervisor fields SIE: CSRSReadValM = {{(P.XLEN-12){1'b0}}, MIE_REGW & 12'h222 & MIDELEG_REGW}; // only read supervisor fields
SSCRATCH: CSRSReadValM = SSCRATCH_REGW; SSCRATCH: CSRSReadValM = SSCRATCH_REGW;
SEPC: CSRSReadValM = SEPC_REGW; SEPC: CSRSReadValM = SEPC_REGW;
SCAUSE: CSRSReadValM = SCAUSE_REGW; SCAUSE: CSRSReadValM = SCAUSE_REGW;
STVAL: CSRSReadValM = STVAL_REGW; STVAL: CSRSReadValM = STVAL_REGW;
SATP: if (`VIRTMEM_SUPPORTED & (PrivilegeModeW == `M_MODE | ~STATUS_TVM)) CSRSReadValM = SATP_REGW; SATP: if (P.VIRTMEM_SUPPORTED & (PrivilegeModeW == P.M_MODE | ~STATUS_TVM)) CSRSReadValM = SATP_REGW;
else begin else begin
CSRSReadValM = 0; CSRSReadValM = 0;
IllegalCSRSAccessM = 1; IllegalCSRSAccessM = 1;
end end
SCOUNTEREN:CSRSReadValM = {{(`XLEN-32){1'b0}}, SCOUNTEREN_REGW}; SCOUNTEREN:CSRSReadValM = {{(P.XLEN-32){1'b0}}, SCOUNTEREN_REGW};
STIMECMP: if (`SSTC_SUPPORTED & (PrivilegeModeW == `M_MODE | MCOUNTEREN_TM)) CSRSReadValM = STIMECMP_REGW[`XLEN-1:0]; STIMECMP: if (P.SSTC_SUPPORTED & (PrivilegeModeW == P.M_MODE | MCOUNTEREN_TM)) CSRSReadValM = STIMECMP_REGW[P.XLEN-1:0];
else begin else begin
CSRSReadValM = 0; CSRSReadValM = 0;
IllegalCSRSAccessM = 1; IllegalCSRSAccessM = 1;
end end
STIMECMPH: if (`SSTC_SUPPORTED & (`XLEN == 32) & (PrivilegeModeW == `M_MODE | MCOUNTEREN_TM)) CSRSReadValM[31:0] = STIMECMP_REGW[63:32]; STIMECMPH: if (P.SSTC_SUPPORTED & (P.XLEN == 32) & (PrivilegeModeW == P.M_MODE | MCOUNTEREN_TM)) CSRSReadValM[31:0] = STIMECMP_REGW[63:32];
else begin // not supported for RV64 else begin // not supported for RV64
CSRSReadValM = 0; CSRSReadValM = 0;
IllegalCSRSAccessM = 1; IllegalCSRSAccessM = 1;

View File

@ -27,18 +27,16 @@
// and limitations under the License. // and limitations under the License.
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
`include "wally-config.vh" module csrsr import cvw::*; #(parameter cvw_t P) (
module csrsr (
input logic clk, reset, StallW, input logic clk, reset, StallW,
input logic WriteMSTATUSM, WriteMSTATUSHM, WriteSSTATUSM, input logic WriteMSTATUSM, WriteMSTATUSHM, WriteSSTATUSM,
input logic TrapM, FRegWriteM, input logic TrapM, FRegWriteM,
input logic [1:0] NextPrivilegeModeM, PrivilegeModeW, input logic [1:0] NextPrivilegeModeM, PrivilegeModeW,
input logic mretM, sretM, input logic mretM, sretM,
input logic WriteFRMM, WriteFFLAGSM, input logic WriteFRMM, WriteFFLAGSM,
input logic [`XLEN-1:0] CSRWriteValM, input logic [P.XLEN-1:0] CSRWriteValM,
input logic SelHPTW, input logic SelHPTW,
output logic [`XLEN-1:0] MSTATUS_REGW, SSTATUS_REGW, MSTATUSH_REGW, output logic [P.XLEN-1:0] MSTATUS_REGW, SSTATUS_REGW, MSTATUSH_REGW,
output logic [1:0] STATUS_MPP, output logic [1:0] STATUS_MPP,
output logic STATUS_SPP, STATUS_TSR, STATUS_TW, output logic STATUS_SPP, STATUS_TSR, STATUS_TW,
output logic STATUS_MIE, STATUS_SIE, output logic STATUS_MIE, STATUS_SIE,
@ -57,13 +55,13 @@ module csrsr (
// See Privileged Spec Section 3.1.6 // See Privileged Spec Section 3.1.6
// Lower privilege status registers are a subset of the full status register // Lower privilege status registers are a subset of the full status register
// *** consider adding MBE, SBE, UBE fields, parameterized to be fixed or adjustable // *** consider adding MBE, SBE, UBE fields, parameterized to be fixed or adjustable
if (`XLEN==64) begin: csrsr64 // RV64 if (P.XLEN==64) begin: csrsr64 // RV64
assign MSTATUS_REGW = {STATUS_SD, 25'b0, STATUS_MBE, STATUS_SBE, STATUS_SXL, STATUS_UXL, 9'b0, assign MSTATUS_REGW = {STATUS_SD, 25'b0, STATUS_MBE, STATUS_SBE, STATUS_SXL, STATUS_UXL, 9'b0,
STATUS_TSR, STATUS_TW, STATUS_TVM, STATUS_MXR, STATUS_SUM, STATUS_MPRV, STATUS_TSR, STATUS_TW, STATUS_TVM, STATUS_MXR, STATUS_SUM, STATUS_MPRV,
STATUS_XS, STATUS_FS, STATUS_MPP, 2'b0, STATUS_XS, STATUS_FS, STATUS_MPP, 2'b0,
STATUS_SPP, STATUS_MPIE, STATUS_UBE, STATUS_SPIE, 1'b0, STATUS_SPP, STATUS_MPIE, STATUS_UBE, STATUS_SPIE, 1'b0,
STATUS_MIE, 1'b0, STATUS_SIE, 1'b0}; STATUS_MIE, 1'b0, STATUS_SIE, 1'b0};
assign SSTATUS_REGW = {STATUS_SD, /*27'b0, */ 29'b0, /*STATUS_SXL, */ {`QEMU ? 2'b0 : STATUS_UXL}, /*9'b0, */ 12'b0, assign SSTATUS_REGW = {STATUS_SD, /*27'b0, */ 29'b0, /*STATUS_SXL, */ {P.QEMU ? 2'b0 : STATUS_UXL}, /*9'b0, */ 12'b0,
/*STATUS_TSR, STATUS_TW, STATUS_TVM, */STATUS_MXR, STATUS_SUM, /* STATUS_MPRV, */ 1'b0, /*STATUS_TSR, STATUS_TW, STATUS_TVM, */STATUS_MXR, STATUS_SUM, /* STATUS_MPRV, */ 1'b0,
STATUS_XS, STATUS_FS, /*STATUS_MPP, 2'b0*/ 4'b0, STATUS_XS, STATUS_FS, /*STATUS_MPP, 2'b0*/ 4'b0,
STATUS_SPP, /*STATUS_MPIE*/ 1'b0, STATUS_UBE, STATUS_SPIE, STATUS_SPP, /*STATUS_MPIE*/ 1'b0, STATUS_UBE, STATUS_SPIE,
@ -83,54 +81,54 @@ module csrsr (
end end
// extract values to write to upper status register on 64/32-bit access // extract values to write to upper status register on 64/32-bit access
if (`XLEN==64) begin:upperstatus if (P.XLEN==64) begin:upperstatus
assign nextMBE = CSRWriteValM[37] & `BIGENDIAN_SUPPORTED; assign nextMBE = CSRWriteValM[37] & P.BIGENDIAN_SUPPORTED;
assign nextSBE = CSRWriteValM[36] & `S_SUPPORTED & `BIGENDIAN_SUPPORTED; assign nextSBE = CSRWriteValM[36] & P.S_SUPPORTED & P.BIGENDIAN_SUPPORTED;
end else begin:upperstatus end else begin:upperstatus
assign nextMBE = STATUS_MBE; assign nextMBE = STATUS_MBE;
assign nextSBE = STATUS_SBE; assign nextSBE = STATUS_SBE;
end end
// harwired STATUS bits // harwired STATUS bits
assign STATUS_TSR = `S_SUPPORTED & STATUS_TSR_INT; // override reigster with 0 if supervisor mode not supported assign STATUS_TSR = P.S_SUPPORTED & STATUS_TSR_INT; // override reigster with 0 if supervisor mode not supported
assign STATUS_TW = (`S_SUPPORTED | `U_SUPPORTED) & STATUS_TW_INT; // override register with 0 if only machine mode supported assign STATUS_TW = (P.S_SUPPORTED | P.U_SUPPORTED) & STATUS_TW_INT; // override register with 0 if only machine mode supported
assign STATUS_TVM = `S_SUPPORTED & STATUS_TVM_INT; // override reigster with 0 if supervisor mode not supported assign STATUS_TVM = P.S_SUPPORTED & STATUS_TVM_INT; // override reigster with 0 if supervisor mode not supported
assign STATUS_MXR = `S_SUPPORTED & STATUS_MXR_INT; // override reigster with 0 if supervisor mode not supported assign STATUS_MXR = P.S_SUPPORTED & STATUS_MXR_INT; // override reigster with 0 if supervisor mode not supported
/* assign STATUS_UBE = 0; // little-endian /* assign STATUS_UBE = 0; // little-endian
assign STATUS_SBE = 0; // little-endian assign STATUS_SBE = 0; // little-endian
assign STATUS_MBE = 0; // little-endian */ assign STATUS_MBE = 0; // little-endian */
// SXL and UXL bits only matter for RV64. Set to 10 for RV64 if mode is supported, or 0 if not // SXL and UXL bits only matter for RV64. Set to 10 for RV64 if mode is supported, or 0 if not
assign STATUS_SXL = `S_SUPPORTED ? 2'b10 : 2'b00; // 10 if supervisor mode supported assign STATUS_SXL = P.S_SUPPORTED ? 2'b10 : 2'b00; // 10 if supervisor mode supported
assign STATUS_UXL = `U_SUPPORTED ? 2'b10 : 2'b00; // 10 if user mode supported assign STATUS_UXL = P.U_SUPPORTED ? 2'b10 : 2'b00; // 10 if user mode supported
assign STATUS_SUM = `S_SUPPORTED & `VIRTMEM_SUPPORTED & STATUS_SUM_INT; // override reigster with 0 if supervisor mode not supported assign STATUS_SUM = P.S_SUPPORTED & P.VIRTMEM_SUPPORTED & STATUS_SUM_INT; // override reigster with 0 if supervisor mode not supported
assign STATUS_MPRV = `U_SUPPORTED & STATUS_MPRV_INT; // override with 0 if user mode not supported assign STATUS_MPRV = P.U_SUPPORTED & STATUS_MPRV_INT; // override with 0 if user mode not supported
assign STATUS_FS = (`S_SUPPORTED & (`F_SUPPORTED | `D_SUPPORTED)) ? STATUS_FS_INT : 2'b00; // off if no FP assign STATUS_FS = (P.S_SUPPORTED & (P.F_SUPPORTED | P.D_SUPPORTED)) ? STATUS_FS_INT : 2'b00; // off if no FP
assign STATUS_SD = (STATUS_FS == 2'b11) | (STATUS_XS == 2'b11); // dirty state logic assign STATUS_SD = (STATUS_FS == 2'b11) | (STATUS_XS == 2'b11); // dirty state logic
assign STATUS_XS = 2'b00; // No additional user-mode state to be dirty assign STATUS_XS = 2'b00; // No additional user-mode state to be dirty
always_comb always_comb
if (CSRWriteValM[12:11] == `U_MODE & `U_SUPPORTED) STATUS_MPP_NEXT = `U_MODE; if (CSRWriteValM[12:11] == P.U_MODE & P.U_SUPPORTED) STATUS_MPP_NEXT = P.U_MODE;
else if (CSRWriteValM[12:11] == `S_MODE & `S_SUPPORTED) STATUS_MPP_NEXT = `S_MODE; else if (CSRWriteValM[12:11] == P.S_MODE & P.S_SUPPORTED) STATUS_MPP_NEXT = P.S_MODE;
else STATUS_MPP_NEXT = `M_MODE; else STATUS_MPP_NEXT = P.M_MODE;
/////////////////////////////////////////// ///////////////////////////////////////////
// Endianness logic Privileged Spec 3.1.6.4 // Endianness logic Privileged Spec 3.1.6.4
/////////////////////////////////////////// ///////////////////////////////////////////
if (`BIGENDIAN_SUPPORTED) begin: endianmux if (P.BIGENDIAN_SUPPORTED) begin: endianmux
// determine whether big endian accesses should be made // determine whether big endian accesses should be made
logic [1:0] EndiannessPrivMode; logic [1:0] EndiannessPrivMode;
always_comb begin always_comb begin
if (SelHPTW) EndiannessPrivMode = `S_MODE; if (SelHPTW) EndiannessPrivMode = P.S_MODE;
//coverage off -item c 1 -feccondrow 1 //coverage off -item c 1 -feccondrow 1
// status.MPRV always gets reset upon leaving machine mode, so MPRV will never be high when out of machine mode // status.MPRV always gets reset upon leaving machine mode, so MPRV will never be high when out of machine mode
else if (PrivilegeModeW == `M_MODE & STATUS_MPRV) EndiannessPrivMode = STATUS_MPP; else if (PrivilegeModeW == P.M_MODE & STATUS_MPRV) EndiannessPrivMode = STATUS_MPP;
//coverage on //coverage on
else EndiannessPrivMode = PrivilegeModeW; else EndiannessPrivMode = PrivilegeModeW;
case (EndiannessPrivMode) case (EndiannessPrivMode)
`M_MODE: BigEndianM = STATUS_MBE; P.M_MODE: BigEndianM = STATUS_MBE;
`S_MODE: BigEndianM = STATUS_SBE; P.S_MODE: BigEndianM = STATUS_SBE;
default: BigEndianM = STATUS_UBE; default: BigEndianM = STATUS_UBE;
endcase endcase
end end
@ -148,7 +146,7 @@ module csrsr (
STATUS_MXR_INT <= #1 0; STATUS_MXR_INT <= #1 0;
STATUS_SUM_INT <= #1 0; STATUS_SUM_INT <= #1 0;
STATUS_MPRV_INT <= #1 0; // Per Priv 3.3 STATUS_MPRV_INT <= #1 0; // Per Priv 3.3
STATUS_FS_INT <= #1 `F_SUPPORTED ? 2'b00 : 2'b00; // leave floating-point off until activated, even if F_SUPPORTED STATUS_FS_INT <= #1 P.F_SUPPORTED ? 2'b00 : 2'b00; // leave floating-point off until activated, even if F_SUPPORTED
STATUS_MPP <= #1 0; STATUS_MPP <= #1 0;
STATUS_SPP <= #1 0; STATUS_SPP <= #1 0;
STATUS_MPIE <= #1 0; STATUS_MPIE <= #1 0;
@ -164,7 +162,7 @@ module csrsr (
// y = PrivilegeModeW // y = PrivilegeModeW
// x = NextPrivilegeModeM // x = NextPrivilegeModeM
// Modes: 11 = Machine, 01 = Supervisor, 00 = User // Modes: 11 = Machine, 01 = Supervisor, 00 = User
if (NextPrivilegeModeM == `M_MODE) begin if (NextPrivilegeModeM == P.M_MODE) begin
STATUS_MPIE <= #1 STATUS_MIE; STATUS_MPIE <= #1 STATUS_MIE;
STATUS_MIE <= #1 0; STATUS_MIE <= #1 0;
STATUS_MPP <= #1 PrivilegeModeW; STATUS_MPP <= #1 PrivilegeModeW;
@ -176,11 +174,11 @@ module csrsr (
end else if (mretM) begin // Privileged 3.1.6.1 end else if (mretM) begin // Privileged 3.1.6.1
STATUS_MIE <= #1 STATUS_MPIE; // restore global interrupt enable STATUS_MIE <= #1 STATUS_MPIE; // restore global interrupt enable
STATUS_MPIE <= #1 1; // STATUS_MPIE <= #1 1; //
STATUS_MPP <= #1 `U_SUPPORTED ? `U_MODE : `M_MODE; // set MPP to lowest supported privilege level STATUS_MPP <= #1 P.U_SUPPORTED ? P.U_MODE : P.M_MODE; // set MPP to lowest supported privilege level
STATUS_MPRV_INT <= #1 STATUS_MPRV_INT & (STATUS_MPP == `M_MODE); // page 21 of privileged spec. STATUS_MPRV_INT <= #1 STATUS_MPRV_INT & (STATUS_MPP == P.M_MODE); // page 21 of privileged spec.
end else if (sretM) begin end else if (sretM) begin
STATUS_SIE <= #1 STATUS_SPIE; // restore global interrupt enable STATUS_SIE <= #1 STATUS_SPIE; // restore global interrupt enable
STATUS_SPIE <= #1 `S_SUPPORTED; STATUS_SPIE <= #1 P.S_SUPPORTED;
STATUS_SPP <= #1 0; // set SPP to lowest supported privilege level to catch bugs STATUS_SPP <= #1 0; // set SPP to lowest supported privilege level to catch bugs
STATUS_MPRV_INT <= #1 0; // always clear MPRV STATUS_MPRV_INT <= #1 0; // always clear MPRV
end else if (WriteMSTATUSM) begin end else if (WriteMSTATUSM) begin
@ -192,28 +190,28 @@ module csrsr (
STATUS_MPRV_INT <= #1 CSRWriteValM[17]; STATUS_MPRV_INT <= #1 CSRWriteValM[17];
STATUS_FS_INT <= #1 CSRWriteValM[14:13]; STATUS_FS_INT <= #1 CSRWriteValM[14:13];
STATUS_MPP <= #1 STATUS_MPP_NEXT; STATUS_MPP <= #1 STATUS_MPP_NEXT;
STATUS_SPP <= #1 `S_SUPPORTED & CSRWriteValM[8]; STATUS_SPP <= #1 P.S_SUPPORTED & CSRWriteValM[8];
STATUS_MPIE <= #1 CSRWriteValM[7]; STATUS_MPIE <= #1 CSRWriteValM[7];
STATUS_SPIE <= #1 `S_SUPPORTED & CSRWriteValM[5]; STATUS_SPIE <= #1 P.S_SUPPORTED & CSRWriteValM[5];
STATUS_MIE <= #1 CSRWriteValM[3]; STATUS_MIE <= #1 CSRWriteValM[3];
STATUS_SIE <= #1 `S_SUPPORTED & CSRWriteValM[1]; STATUS_SIE <= #1 P.S_SUPPORTED & CSRWriteValM[1];
STATUS_UBE <= #1 CSRWriteValM[6] & `U_SUPPORTED & `BIGENDIAN_SUPPORTED; STATUS_UBE <= #1 CSRWriteValM[6] & P.U_SUPPORTED & P.BIGENDIAN_SUPPORTED;
STATUS_MBE <= #1 nextMBE; STATUS_MBE <= #1 nextMBE;
STATUS_SBE <= #1 nextSBE; STATUS_SBE <= #1 nextSBE;
// coverage off // coverage off
// MSTATUSH only exists in 32-bit configurations, will not be hit on rv64gc // MSTATUSH only exists in 32-bit configurations, will not be hit on rv64gc
end else if (WriteMSTATUSHM) begin end else if (WriteMSTATUSHM) begin
STATUS_MBE <= #1 CSRWriteValM[5] & `BIGENDIAN_SUPPORTED; STATUS_MBE <= #1 CSRWriteValM[5] & P.BIGENDIAN_SUPPORTED;
STATUS_SBE <= #1 CSRWriteValM[4] & `S_SUPPORTED & `BIGENDIAN_SUPPORTED; STATUS_SBE <= #1 CSRWriteValM[4] & P.S_SUPPORTED & P.BIGENDIAN_SUPPORTED;
// coverage on // coverage on
end else if (WriteSSTATUSM) begin // write a subset of the STATUS bits end else if (WriteSSTATUSM) begin // write a subset of the STATUS bits
STATUS_MXR_INT <= #1 CSRWriteValM[19]; STATUS_MXR_INT <= #1 CSRWriteValM[19];
STATUS_SUM_INT <= #1 CSRWriteValM[18]; STATUS_SUM_INT <= #1 CSRWriteValM[18];
STATUS_FS_INT <= #1 CSRWriteValM[14:13]; STATUS_FS_INT <= #1 CSRWriteValM[14:13];
STATUS_SPP <= #1 `S_SUPPORTED & CSRWriteValM[8]; STATUS_SPP <= #1 P.S_SUPPORTED & CSRWriteValM[8];
STATUS_SPIE <= #1 `S_SUPPORTED & CSRWriteValM[5]; STATUS_SPIE <= #1 P.S_SUPPORTED & CSRWriteValM[5];
STATUS_SIE <= #1 `S_SUPPORTED & CSRWriteValM[1]; STATUS_SIE <= #1 P.S_SUPPORTED & CSRWriteValM[1];
STATUS_UBE <= #1 CSRWriteValM[6] & `U_SUPPORTED & `BIGENDIAN_SUPPORTED; STATUS_UBE <= #1 CSRWriteValM[6] & P.U_SUPPORTED & P.BIGENDIAN_SUPPORTED;
end else if (FRegWriteM | WriteFRMM | WriteFFLAGSM) STATUS_FS_INT <= #1 2'b11; end else if (FRegWriteM | WriteFRMM | WriteFFLAGSM) STATUS_FS_INT <= #1 2'b11;
end end
endmodule endmodule

View File

@ -26,9 +26,7 @@
// and limitations under the License. // and limitations under the License.
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
`include "wally-config.vh" module csru import cvw::*; #(parameter cvw_t P,
module csru #(parameter
FFLAGS = 12'h001, FFLAGS = 12'h001,
FRM = 12'h002, FRM = 12'h002,
FCSR = 12'h003) ( FCSR = 12'h003) (
@ -36,9 +34,9 @@ module csru #(parameter
input logic InstrValidNotFlushedM, input logic InstrValidNotFlushedM,
input logic CSRUWriteM, input logic CSRUWriteM,
input logic [11:0] CSRAdrM, input logic [11:0] CSRAdrM,
input logic [`XLEN-1:0] CSRWriteValM, input logic [P.XLEN-1:0] CSRWriteValM,
input logic [1:0] STATUS_FS, input logic [1:0] STATUS_FS,
output logic [`XLEN-1:0] CSRUReadValM, output logic [P.XLEN-1:0] CSRUReadValM,
input logic [4:0] SetFflagsM, input logic [4:0] SetFflagsM,
output logic [2:0] FRM_REGW, output logic [2:0] FRM_REGW,
output logic WriteFRMM, WriteFFLAGSM, output logic WriteFRMM, WriteFFLAGSM,
@ -71,9 +69,9 @@ module csru #(parameter
end else begin end else begin
IllegalCSRUAccessM = 0; IllegalCSRUAccessM = 0;
case (CSRAdrM) case (CSRAdrM)
FFLAGS: CSRUReadValM = {{(`XLEN-5){1'b0}}, FFLAGS_REGW}; FFLAGS: CSRUReadValM = {{(P.XLEN-5){1'b0}}, FFLAGS_REGW};
FRM: CSRUReadValM = {{(`XLEN-3){1'b0}}, FRM_REGW}; FRM: CSRUReadValM = {{(P.XLEN-3){1'b0}}, FRM_REGW};
FCSR: CSRUReadValM = {{(`XLEN-8){1'b0}}, FRM_REGW, FFLAGS_REGW}; FCSR: CSRUReadValM = {{(P.XLEN-8){1'b0}}, FRM_REGW, FFLAGS_REGW};
default: begin default: begin
CSRUReadValM = 0; CSRUReadValM = 0;
IllegalCSRUAccessM = 1; IllegalCSRUAccessM = 1;

View File

@ -27,9 +27,7 @@
// and limitations under the License. // and limitations under the License.
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
`include "wally-config.vh" module privdec import cvw::*; #(parameter cvw_t P) (
module privdec (
input logic clk, reset, input logic clk, reset,
input logic StallM, input logic StallM,
input logic [31:20] InstrM, // privileged instruction function field input logic [31:20] InstrM, // privileged instruction function field
@ -52,26 +50,26 @@ module privdec (
// Decode privileged instructions // Decode privileged instructions
/////////////////////////////////////////// ///////////////////////////////////////////
assign sretM = PrivilegedM & (InstrM[31:20] == 12'b000100000010) & `S_SUPPORTED & assign sretM = PrivilegedM & (InstrM[31:20] == 12'b000100000010) & P.S_SUPPORTED &
(PrivilegeModeW == `M_MODE | PrivilegeModeW == `S_MODE & ~STATUS_TSR); (PrivilegeModeW == P.M_MODE | PrivilegeModeW == P.S_MODE & ~STATUS_TSR);
assign mretM = PrivilegedM & (InstrM[31:20] == 12'b001100000010) & (PrivilegeModeW == `M_MODE); assign mretM = PrivilegedM & (InstrM[31:20] == 12'b001100000010) & (PrivilegeModeW == P.M_MODE);
assign ecallM = PrivilegedM & (InstrM[31:20] == 12'b000000000000); assign ecallM = PrivilegedM & (InstrM[31:20] == 12'b000000000000);
assign ebreakM = PrivilegedM & (InstrM[31:20] == 12'b000000000001); assign ebreakM = PrivilegedM & (InstrM[31:20] == 12'b000000000001);
assign wfiM = PrivilegedM & (InstrM[31:20] == 12'b000100000101); assign wfiM = PrivilegedM & (InstrM[31:20] == 12'b000100000101);
assign sfencevmaM = PrivilegedM & (InstrM[31:25] == 7'b0001001) & assign sfencevmaM = PrivilegedM & (InstrM[31:25] == 7'b0001001) &
(PrivilegeModeW == `M_MODE | (PrivilegeModeW == `S_MODE & ~STATUS_TVM)); (PrivilegeModeW == P.M_MODE | (PrivilegeModeW == P.S_MODE & ~STATUS_TVM));
/////////////////////////////////////////// ///////////////////////////////////////////
// WFI timeout Privileged Spec 3.1.6.5 // WFI timeout Privileged Spec 3.1.6.5
/////////////////////////////////////////// ///////////////////////////////////////////
if (`U_SUPPORTED) begin:wfi if (P.U_SUPPORTED) begin:wfi
logic [`WFI_TIMEOUT_BIT:0] WFICount, WFICountPlus1; logic [P.WFI_TIMEOUT_BIT:0] WFICount, WFICountPlus1;
assign WFICountPlus1 = WFICount + 1; assign WFICountPlus1 = WFICount + 1;
floprc #(`WFI_TIMEOUT_BIT+1) wficountreg(clk, reset, ~wfiM, WFICountPlus1, WFICount); // count while in WFI floprc #(P.WFI_TIMEOUT_BIT+1) wficountreg(clk, reset, ~wfiM, WFICountPlus1, WFICount); // count while in WFI
// coverage off -item e 1 -fecexprrow 1 // coverage off -item e 1 -fecexprrow 1
// WFI Timout trap will not occur when STATUS_TW is low while in supervisor mode, so the system gets stuck waiting for an interrupt and triggers a watchdog timeout. // WFI Timout trap will not occur when STATUS_TW is low while in supervisor mode, so the system gets stuck waiting for an interrupt and triggers a watchdog timeout.
assign WFITimeoutM = ((STATUS_TW & PrivilegeModeW != `M_MODE) | (`S_SUPPORTED & PrivilegeModeW == `U_MODE)) & WFICount[`WFI_TIMEOUT_BIT]; assign WFITimeoutM = ((STATUS_TW & PrivilegeModeW != P.M_MODE) | (P.S_SUPPORTED & PrivilegeModeW == P.U_MODE)) & WFICount[P.WFI_TIMEOUT_BIT];
// coverage on // coverage on
end else assign WFITimeoutM = 0; end else assign WFITimeoutM = 0;

View File

@ -27,19 +27,17 @@
// SOFTWARE. // SOFTWARE.
/////////////////////////////////////////// ///////////////////////////////////////////
`include "wally-config.vh" module privileged import cvw::*; #(parameter cvw_t P) (
module privileged (
input logic clk, reset, input logic clk, reset,
input logic StallD, StallE, StallM, StallW, input logic StallD, StallE, StallM, StallW,
input logic FlushD, FlushE, FlushM, FlushW, input logic FlushD, FlushE, FlushM, FlushW,
// CSR Reads and Writes, and values needed for traps // CSR Reads and Writes, and values needed for traps
input logic CSRReadM, CSRWriteM, // Read or write CSRs input logic CSRReadM, CSRWriteM, // Read or write CSRs
input logic [`XLEN-1:0] SrcAM, // GPR register to write input logic [P.XLEN-1:0] SrcAM, // GPR register to write
input logic [31:0] InstrM, // Instruction input logic [31:0] InstrM, // Instruction
input logic [31:0] InstrOrigM, // Original compressed or uncompressed instruction in Memory stage for Illegal Instruction MTVAL input logic [31:0] InstrOrigM, // Original compressed or uncompressed instruction in Memory stage for Illegal Instruction MTVAL
input logic [`XLEN-1:0] IEUAdrM, // address from IEU input logic [P.XLEN-1:0] IEUAdrM, // address from IEU
input logic [`XLEN-1:0] PCM, PC2NextF, // program counter, next PC going to trap/return PC logic input logic [P.XLEN-1:0] PCM, PC2NextF, // program counter, next PC going to trap/return PC logic
// control signals // control signals
input logic InstrValidM, // Current instruction is valid (not flushed) input logic InstrValidM, // Current instruction is valid (not flushed)
input logic CommittedM, CommittedF, // current instruction is using bus; don't interrupt input logic CommittedM, CommittedF, // current instruction is using bus; don't interrupt
@ -76,16 +74,16 @@ module privileged (
input logic [4:0] SetFflagsM, // set FCSR flags from FPU input logic [4:0] SetFflagsM, // set FCSR flags from FPU
input logic SelHPTW, // HPTW in use. Causes system to use S-mode endianness for accesses input logic SelHPTW, // HPTW in use. Causes system to use S-mode endianness for accesses
// CSR outputs // CSR outputs
output logic [`XLEN-1:0] CSRReadValW, // Value read from CSR output logic [P.XLEN-1:0] CSRReadValW, // Value read from CSR
output logic [1:0] PrivilegeModeW, // current privilege mode output logic [1:0] PrivilegeModeW, // current privilege mode
output logic [`XLEN-1:0] SATP_REGW, // supervisor address translation register output logic [P.XLEN-1:0] SATP_REGW, // supervisor address translation register
output logic STATUS_MXR, STATUS_SUM, STATUS_MPRV, // status register bits output logic STATUS_MXR, STATUS_SUM, STATUS_MPRV, // status register bits
output logic [1:0] STATUS_MPP, STATUS_FS, // status register bits output logic [1:0] STATUS_MPP, STATUS_FS, // status register bits
output var logic [7:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES-1:0], // PMP configuration entries to MMU output var logic [7:0] PMPCFG_ARRAY_REGW[P.PMP_ENTRIES-1:0], // PMP configuration entries to MMU
output var logic [`PA_BITS-3:0] PMPADDR_ARRAY_REGW [`PMP_ENTRIES-1:0], // PMP address entries to MMU output var logic [P.PA_BITS-3:0] PMPADDR_ARRAY_REGW [P.PMP_ENTRIES-1:0], // PMP address entries to MMU
output logic [2:0] FRM_REGW, // FPU rounding mode output logic [2:0] FRM_REGW, // FPU rounding mode
// PC logic output in privileged unit // PC logic output in privileged unit
output logic [`XLEN-1:0] UnalignedPCNextF, // Next PC from trap/return PC logic output logic [P.XLEN-1:0] UnalignedPCNextF, // Next PC from trap/return PC logic
// control outputs // control outputs
output logic RetM, TrapM, // return instruction, or trap output logic RetM, TrapM, // return instruction, or trap
output logic sfencevmaM, // sfence.vma instruction output logic sfencevmaM, // sfence.vma instruction
@ -116,17 +114,17 @@ module privileged (
// track the current privilege level // track the current privilege level
privmode privmode(.clk, .reset, .StallW, .TrapM, .mretM, .sretM, .DelegateM, privmode #(P) privmode(.clk, .reset, .StallW, .TrapM, .mretM, .sretM, .DelegateM,
.STATUS_MPP, .STATUS_SPP, .NextPrivilegeModeM, .PrivilegeModeW); .STATUS_MPP, .STATUS_SPP, .NextPrivilegeModeM, .PrivilegeModeW);
// decode privileged instructions // decode privileged instructions
privdec pmd(.clk, .reset, .StallM, .InstrM(InstrM[31:20]), privdec #(P) pmd(.clk, .reset, .StallM, .InstrM(InstrM[31:20]),
.PrivilegedM, .IllegalIEUFPUInstrM, .IllegalCSRAccessM, .PrivilegedM, .IllegalIEUFPUInstrM, .IllegalCSRAccessM,
.PrivilegeModeW, .STATUS_TSR, .STATUS_TVM, .STATUS_TW, .IllegalInstrFaultM, .PrivilegeModeW, .STATUS_TSR, .STATUS_TVM, .STATUS_TW, .IllegalInstrFaultM,
.EcallFaultM, .BreakpointFaultM, .sretM, .mretM, .wfiM, .sfencevmaM); .EcallFaultM, .BreakpointFaultM, .sretM, .mretM, .wfiM, .sfencevmaM);
// Control and Status Registers // Control and Status Registers
csr csr(.clk, .reset, .FlushM, .FlushW, .StallE, .StallM, .StallW, csr #(P) csr(.clk, .reset, .FlushM, .FlushW, .StallE, .StallM, .StallW,
.InstrM, .InstrOrigM, .PCM, .SrcAM, .IEUAdrM, .PC2NextF, .InstrM, .InstrOrigM, .PCM, .SrcAM, .IEUAdrM, .PC2NextF,
.CSRReadM, .CSRWriteM, .TrapM, .mretM, .sretM, .wfiM, .IntPendingM, .InterruptM, .CSRReadM, .CSRWriteM, .TrapM, .mretM, .sretM, .wfiM, .IntPendingM, .InterruptM,
.MTimerInt, .MExtInt, .SExtInt, .MSwInt, .MTimerInt, .MExtInt, .SExtInt, .MSwInt,
@ -148,7 +146,7 @@ module privileged (
.InstrPageFaultM, .InstrAccessFaultM, .HPTWInstrAccessFaultM, .IllegalIEUFPUInstrM); .InstrPageFaultM, .InstrAccessFaultM, .HPTWInstrAccessFaultM, .IllegalIEUFPUInstrM);
// trap logic // trap logic
trap trap(.reset, trap #(P) trap(.reset,
.InstrMisalignedFaultM, .InstrAccessFaultM, .HPTWInstrAccessFaultM, .IllegalInstrFaultM, .InstrMisalignedFaultM, .InstrAccessFaultM, .HPTWInstrAccessFaultM, .IllegalInstrFaultM,
.BreakpointFaultM, .LoadMisalignedFaultM, .StoreAmoMisalignedFaultM, .BreakpointFaultM, .LoadMisalignedFaultM, .StoreAmoMisalignedFaultM,
.LoadAccessFaultM, .StoreAmoAccessFaultM, .EcallFaultM, .InstrPageFaultM, .LoadAccessFaultM, .StoreAmoAccessFaultM, .EcallFaultM, .InstrPageFaultM,

View File

@ -26,9 +26,7 @@
// and limitations under the License. // and limitations under the License.
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
`include "wally-config.vh" module privmode import cvw::*; #(parameter cvw_t P) (
module privmode (
input logic clk, reset, input logic clk, reset,
input logic StallW, input logic StallW,
input logic TrapM, // Trap input logic TrapM, // Trap
@ -40,20 +38,20 @@ module privmode (
output logic [1:0] PrivilegeModeW // current privilege mode output logic [1:0] PrivilegeModeW // current privilege mode
); );
if (`U_SUPPORTED) begin:privmode if (P.U_SUPPORTED) begin:privmode
// PrivilegeMode FSM // PrivilegeMode FSM
always_comb begin always_comb begin
if (TrapM) begin // Change privilege based on DELEG registers (see 3.1.8) if (TrapM) begin // Change privilege based on DELEG registers (see 3.1.8)
if (`S_SUPPORTED & DelegateM) NextPrivilegeModeM = `S_MODE; if (P.S_SUPPORTED & DelegateM) NextPrivilegeModeM = P.S_MODE;
else NextPrivilegeModeM = `M_MODE; else NextPrivilegeModeM = P.M_MODE;
end else if (mretM) NextPrivilegeModeM = STATUS_MPP; end else if (mretM) NextPrivilegeModeM = STATUS_MPP;
else if (sretM) NextPrivilegeModeM = {1'b0, STATUS_SPP}; else if (sretM) NextPrivilegeModeM = {1'b0, STATUS_SPP};
else NextPrivilegeModeM = PrivilegeModeW; else NextPrivilegeModeM = PrivilegeModeW;
end end
flopenl #(2) privmodereg(clk, reset, ~StallW, NextPrivilegeModeM, `M_MODE, PrivilegeModeW); flopenl #(2) privmodereg(clk, reset, ~StallW, NextPrivilegeModeM, P.M_MODE, PrivilegeModeW);
end else begin // only machine mode supported end else begin // only machine mode supported
assign NextPrivilegeModeM = `M_MODE; assign NextPrivilegeModeM = P.M_MODE;
assign PrivilegeModeW = `M_MODE; assign PrivilegeModeW = P.M_MODE;
end end
endmodule endmodule

View File

@ -26,8 +26,6 @@
// and limitations under the License. // and limitations under the License.
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
`include "wally-config.vh"
module privpiperegs ( module privpiperegs (
input logic clk, reset, input logic clk, reset,
input logic StallD, StallE, StallM, input logic StallD, StallE, StallM,

View File

@ -26,9 +26,7 @@
// and limitations under the License. // and limitations under the License.
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
`include "wally-config.vh" module trap import cvw::*; #(parameter cvw_t P) (
module trap (
input logic reset, input logic reset,
input logic InstrMisalignedFaultM, InstrAccessFaultM, HPTWInstrAccessFaultM, IllegalInstrFaultM, input logic InstrMisalignedFaultM, InstrAccessFaultM, HPTWInstrAccessFaultM, IllegalInstrFaultM,
input logic BreakpointFaultM, LoadMisalignedFaultM, StoreAmoMisalignedFaultM, input logic BreakpointFaultM, LoadMisalignedFaultM, StoreAmoMisalignedFaultM,
@ -63,16 +61,16 @@ module trap (
// & with ~CommittedM to make sure MEPC isn't chosen so as to rerun the same instr twice // & with ~CommittedM to make sure MEPC isn't chosen so as to rerun the same instr twice
/////////////////////////////////////////// ///////////////////////////////////////////
assign MIntGlobalEnM = (PrivilegeModeW != `M_MODE) | STATUS_MIE; // if M ints enabled or lower priv 3.1.9 assign MIntGlobalEnM = (PrivilegeModeW != P.M_MODE) | STATUS_MIE; // if M ints enabled or lower priv 3.1.9
assign SIntGlobalEnM = (PrivilegeModeW == `U_MODE) | ((PrivilegeModeW == `S_MODE) & STATUS_SIE); // if in lower priv mode, or if S ints enabled and not in higher priv mode 3.1.9 assign SIntGlobalEnM = (PrivilegeModeW == P.U_MODE) | ((PrivilegeModeW == P.S_MODE) & STATUS_SIE); // if in lower priv mode, or if S ints enabled and not in higher priv mode 3.1.9
assign PendingIntsM = MIP_REGW & MIE_REGW; assign PendingIntsM = MIP_REGW & MIE_REGW;
assign IntPendingM = |PendingIntsM; assign IntPendingM = |PendingIntsM;
assign Committed = CommittedM | CommittedF; assign Committed = CommittedM | CommittedF;
assign EnabledIntsM = ({12{MIntGlobalEnM}} & PendingIntsM & ~MIDELEG_REGW | {12{SIntGlobalEnM}} & PendingIntsM & MIDELEG_REGW); assign EnabledIntsM = ({12{MIntGlobalEnM}} & PendingIntsM & ~MIDELEG_REGW | {12{SIntGlobalEnM}} & PendingIntsM & MIDELEG_REGW);
assign ValidIntsM = {12{~Committed}} & EnabledIntsM; assign ValidIntsM = {12{~Committed}} & EnabledIntsM;
assign InterruptM = (|ValidIntsM) & InstrValidM; // suppress interrupt if the memory system has partially processed a request. assign InterruptM = (|ValidIntsM) & InstrValidM; // suppress interrupt if the memory system has partially processed a request.
assign DelegateM = `S_SUPPORTED & (InterruptM ? MIDELEG_REGW[CauseM] : MEDELEG_REGW[CauseM]) & assign DelegateM = P.S_SUPPORTED & (InterruptM ? MIDELEG_REGW[CauseM] : MEDELEG_REGW[CauseM]) &
(PrivilegeModeW == `U_MODE | PrivilegeModeW == `S_MODE); (PrivilegeModeW == P.U_MODE | PrivilegeModeW == P.S_MODE);
/////////////////////////////////////////// ///////////////////////////////////////////
// Trigger Traps and RET // Trigger Traps and RET

View File

@ -270,7 +270,7 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) (
// privileged unit // privileged unit
if (P.ZICSR_SUPPORTED) begin:priv if (P.ZICSR_SUPPORTED) begin:priv
privileged priv( privileged #(P) priv(
.clk, .reset, .clk, .reset,
.FlushD, .FlushE, .FlushM, .FlushW, .StallD, .StallE, .StallM, .StallW, .FlushD, .FlushE, .FlushM, .FlushW, .StallD, .StallE, .StallM, .StallW,
.CSRReadM, .CSRWriteM, .SrcAM, .PCM, .PC2NextF, .CSRReadM, .CSRWriteM, .SrcAM, .PCM, .PC2NextF,