Implemented TSR, TW, TVM, MXR status bits

This commit is contained in:
David Harris 2021-07-06 01:32:05 -04:00
parent 8b23162d6d
commit f805aea236
5 changed files with 67 additions and 56 deletions

View File

@ -58,7 +58,7 @@ module csr #(parameter
output logic [`XLEN-1:0] SATP_REGW,
output logic [11:0] MIP_REGW, MIE_REGW, SIP_REGW, SIE_REGW,
output logic STATUS_MIE, STATUS_SIE,
output logic STATUS_MXR, STATUS_SUM, STATUS_MPRV,
output logic STATUS_MXR, STATUS_SUM, STATUS_MPRV, STATUS_TW,
output var logic [7:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES-1:0],
output var logic [`XLEN-1:0] PMPADDR_ARRAY_REGW [`PMP_ENTRIES-1:0],
input logic [4:0] SetFflagsM,

View File

@ -130,7 +130,7 @@ module csrs #(parameter
SATP: if (`MEM_VIRTMEM && (PrivilegeModeW == `M_MODE || ~STATUS_TVM)) CSRSReadValM = SATP_REGW;
else begin
CSRSReadValM = 0;
IllegalCSRSAccessM = 1;
if (PrivilegeModeW == `S_MODE & STATUS_TVM) IllegalCSRSAccessM = 1;
end
SCOUNTEREN:CSRSReadValM = {{(`XLEN-32){1'b0}}, SCOUNTEREN_REGW};
default: begin

View File

@ -35,13 +35,13 @@ module csrsr (
input logic [`XLEN-1:0] CSRWriteValM,
output logic [`XLEN-1:0] MSTATUS_REGW, SSTATUS_REGW, USTATUS_REGW,
output logic [1:0] STATUS_MPP,
output logic STATUS_SPP, STATUS_TSR,
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
);
logic STATUS_SD, STATUS_TW, STATUS_SUM_INT, STATUS_MPRV_INT;
logic STATUS_SD, STATUS_TW_INT, STATUS_TSR_INT, STATUS_TVM_INT, STATUS_MXR_INT, STATUS_SUM_INT, STATUS_MPRV_INT;
logic [1:0] STATUS_SXL, STATUS_UXL, STATUS_XS, STATUS_FS, STATUS_FS_INT, STATUS_MPP_NEXT;
logic STATUS_MPIE, STATUS_SPIE, STATUS_UPIE, STATUS_UIE;
@ -86,18 +86,18 @@ module csrsr (
// harwired STATUS bits
generate
assign STATUS_TSR = `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 reigster 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_MXR = `S_SUPPORTED & STATUS_MXR_INT; // override reigster with 0 if supervisor mode not supported
// 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_UXL = `U_SUPPORTED ? 2'b10 : 2'b00; // 10 if user mode supported
assign STATUS_SUM = `S_SUPPORTED & STATUS_SUM_INT; // override reigster with 0 if supervisor mode not supported
assign STATUS_SUM = `S_SUPPORTED & `MEM_VIRTMEM & 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_FS = (`S_SUPPORTED && (`F_SUPPORTED || `D_SUPPORTED)) ? STATUS_FS_INT : 2'b00; // off if no FP
endgenerate
assign STATUS_SD = (STATUS_FS == 2'b11) || (STATUS_XS == 2'b11); // dirty state logic
assign STATUS_TSR = 0; // Trap SRET not supported; revisit whether this is necessary for an OS
assign STATUS_TW = 0; // Timeout Wait not supported
assign STATUS_TVM = 0; // Trap Virtual Memory not supported (revisit if supporting virtualizations, but hooks in place for it in satp)
assign STATUS_MXR = 0; // Make Executable Readable (may need to add support for VM later)
assign STATUS_XS = 2'b00; // No additional user-mode state to be dirty
always_comb
@ -109,10 +109,13 @@ module csrsr (
// 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_MPRV_INT <= #1 0; // Per Priv 3.3
STATUS_FS_INT <= #1 0; //2'b01; // busybear: change all these reset values to 0
//STATUS_TVM_INT <= #1 0; // when S_SUPPORTED
STATUS_MPP <= #1 0; //`M_MODE;
STATUS_SPP <= #1 0; //1'b1;
STATUS_MPIE <= #1 0; //1;
@ -122,11 +125,45 @@ module csrsr (
STATUS_SIE <= #1 0; //`S_SUPPORTED;
STATUS_UIE <= #1 0; //`U_SUPPORTED;
end else if (~StallW) begin
if (WriteMSTATUSM) begin
if (FloatRegWriteW) STATUS_FS_INT <= #12'b11; // mark Float State dirty *** this should happen in M stage, be part of if/else
if (TrapM) begin
// Update interrupt enables per Privileged Spec p. 21
// y = PrivilegeModeW
// x = NextPrivilegeModeM
// Modes: 11 = Machine, 01 = Supervisor, 00 = User
if (NextPrivilegeModeM == `M_MODE) begin
STATUS_MPIE <= #1 STATUS_MIE;
STATUS_MIE <= #1 0;
STATUS_MPP <= #1 PrivilegeModeW;
end else if (NextPrivilegeModeM == `S_MODE) begin
STATUS_SPIE <= #1 STATUS_SIE;
STATUS_SIE <= #1 0;
STATUS_SPP <= #1 PrivilegeModeW[0]; // *** seems to disagree with P. 56
end else begin // user mode
STATUS_UPIE <= #1 STATUS_UIE;
STATUS_UIE <= #1 0;
end
end else if (mretM) begin // Privileged 3.1.6.1
STATUS_MIE <= #1 STATUS_MPIE;
STATUS_MPIE <= #1 1;
STATUS_MPP <= #1 `U_SUPPORTED ? `U_MODE : `M_MODE; // per spec, not sure why
STATUS_MPRV_INT <= #1 0; // per 20210108 draft spec
end else if (sretM) begin
STATUS_SIE <= #1 STATUS_SPIE;
STATUS_SPIE <= #1 `S_SUPPORTED;
STATUS_SPP <= #1 0; // Privileged 4.1.1
STATUS_MPRV_INT <= #1 0; // per 20210108 draft spec
end else if (uretM) begin
STATUS_UIE <= #1 STATUS_UPIE;
STATUS_UPIE <= #1 `U_SUPPORTED;
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_MPRV_INT <= #1 CSRWriteValM[17];
STATUS_FS_INT <= #1 CSRWriteValM[14:13];
//STATUS_TVM_INT <= #1 CSRWriteValM[]
STATUS_MPP <= #1 STATUS_MPP_NEXT;
STATUS_SPP <= #1 `S_SUPPORTED & CSRWriteValM[8];
STATUS_MPIE <= #1 CSRWriteValM[7];
@ -136,6 +173,7 @@ module csrsr (
STATUS_SIE <= #1 `S_SUPPORTED & CSRWriteValM[1];
STATUS_UIE <= #1 `U_SUPPORTED & CSRWriteValM[0];
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 `S_SUPPORTED & CSRWriteValM[8];
@ -147,40 +185,6 @@ module csrsr (
STATUS_FS_INT <= #1 CSRWriteValM[14:13];
STATUS_UPIE <= #1 `U_SUPPORTED & CSRWriteValM[4];
STATUS_UIE <= #1 `U_SUPPORTED & CSRWriteValM[0];
end else begin
if (FloatRegWriteW) STATUS_FS_INT <= #12'b11; // mark Float State dirty
if (TrapM) begin
// Update interrupt enables per Privileged Spec p. 21
// y = PrivilegeModeW
// x = NextPrivilegeModeM
// Modes: 11 = Machine, 01 = Supervisor, 00 = User
if (NextPrivilegeModeM == `M_MODE) begin
STATUS_MPIE <= #1 STATUS_MIE;
STATUS_MIE <= #1 0;
STATUS_MPP <= #1 PrivilegeModeW;
end else if (NextPrivilegeModeM == `S_MODE) begin
STATUS_SPIE <= #1 STATUS_SIE;
STATUS_SIE <= #1 0;
STATUS_SPP <= #1 PrivilegeModeW[0]; // *** seems to disagree with P. 56
end else begin // user mode
STATUS_UPIE <= #1 STATUS_UIE;
STATUS_UIE <= #1 0;
end
end else if (mretM) begin // Privileged 3.1.6.1
STATUS_MIE <= #1 STATUS_MPIE;
STATUS_MPIE <= #1 1;
STATUS_MPP <= #1 `U_SUPPORTED ? `U_MODE : `M_MODE; // per spec, not sure why
STATUS_MPRV_INT <= #1 0; // per 20210108 draft spec
end else if (sretM) begin
STATUS_SIE <= #1 STATUS_SPIE;
STATUS_SPIE <= #1 `S_SUPPORTED;
STATUS_SPP <= #1 0; // Privileged 4.1.1
STATUS_MPRV_INT <= #1 0; // per 20210108 draft spec
end else if (uretM) begin
STATUS_UIE <= #1 STATUS_UPIE;
STATUS_UPIE <= #1 `U_SUPPORTED;
end
// *** add code to track STATUS_FS_INT for dirty floating point registers
end
end
end
endmodule

View File

@ -28,7 +28,7 @@
module privdec (
input logic [31:20] InstrM,
input logic PrivilegedM, IllegalIEUInstrFaultM, IllegalCSRAccessM, IllegalFPUInstrM,
input logic PrivilegedM, IllegalIEUInstrFaultM, IllegalCSRAccessM, IllegalFPUInstrM, TrappedSRETM,
input logic [1:0] PrivilegeModeW,
input logic STATUS_TSR,
output logic IllegalInstrFaultM,
@ -47,7 +47,7 @@ module privdec (
assign wfiM = PrivilegedM & (InstrM[31:20] == 12'b000100000101);
assign sfencevmaM = PrivilegedM & (InstrM[31:25] == 7'b0001001);
assign IllegalPrivilegedInstrM = PrivilegedM & ~(uretM|sretM|mretM|ecallM|ebreakM|wfiM|sfencevmaM);
assign IllegalInstrFaultM = (IllegalIEUInstrFaultM & IllegalFPUInstrM) | IllegalPrivilegedInstrM | IllegalCSRAccessM; // *** generalize this for other instructions
assign IllegalInstrFaultM = (IllegalIEUInstrFaultM & IllegalFPUInstrM) | IllegalPrivilegedInstrM | IllegalCSRAccessM | TrappedSRETM; // *** generalize this for other instructions
// *** initially, wfi and sfencevma are nop
// *** zfenci extension?

View File

@ -89,13 +89,13 @@ module privileged (
logic InstrPageFaultF, InstrPageFaultD, InstrPageFaultE, InstrPageFaultM;
logic InstrAccessFaultF, InstrAccessFaultD, InstrAccessFaultE, InstrAccessFaultM;
logic LoadAccessFaultM, StoreAccessFaultM;
logic IllegalInstrFaultM;
logic IllegalInstrFaultM, TrappedSRETM;
logic BreakpointFaultM, EcallFaultM;
logic MTrapM, STrapM, UTrapM;
logic InterruptM;
logic STATUS_SPP, STATUS_TSR;
logic STATUS_SPP, STATUS_TSR, STATUS_TW;
logic STATUS_MIE, STATUS_SIE;
logic [11:0] MIP_REGW, MIE_REGW, SIP_REGW, SIE_REGW;
logic md, sd;
@ -112,10 +112,14 @@ module privileged (
assign sd = CauseM[`XLEN-1] ? SIDELEG_REGW[CauseM[`LOG_XLEN-1:0]] : SEDELEG_REGW[CauseM[`LOG_XLEN-1:0]]; // depricated
// PrivilegeMode FSM
always_comb
/* if (reset) NextPrivilegeModeM = `M_MODE; // Privilege resets to 11 (Machine Mode) // moved reset to flop
else */ if (mretM) NextPrivilegeModeM = STATUS_MPP;
else if (sretM) NextPrivilegeModeM = {1'b0, STATUS_SPP};
always_comb begin
TrappedSRETM = 0;
if (mretM) NextPrivilegeModeM = STATUS_MPP;
else if (sretM)
if (STATUS_TSR & PrivilegeModeW == `S_MODE) begin
TrappedSRETM = 1;
NextPrivilegeModeM = PrivilegeModeW;
end else NextPrivilegeModeM = {1'b0, STATUS_SPP};
else if (uretM) NextPrivilegeModeM = `U_MODE;
else if (TrapM) begin // Change privilege based on DELEG registers (see 3.1.8)
if (PrivilegeModeW == `U_MODE)
@ -127,6 +131,8 @@ module privileged (
else NextPrivilegeModeM = `M_MODE;
else NextPrivilegeModeM = `M_MODE;
end else NextPrivilegeModeM = PrivilegeModeW;
end
// *** WFI could be implemented here and depends on TW
flopenl #(2) privmodereg(clk, reset, ~StallW, NextPrivilegeModeM, `M_MODE, PrivilegeModeW);
@ -171,6 +177,7 @@ module privileged (
flopenrc #(4) faultregM(clk, reset, FlushM, ~StallM,
{IllegalIEUInstrFaultE, InstrPageFaultE, InstrAccessFaultE, IllegalFPUInstrE},
{IllegalIEUInstrFaultM, InstrPageFaultM, InstrAccessFaultM, IllegalFPUInstrM});
// *** it should be possible to compbine some of these faults earlier to reduce module boundary crossings and save flops dh 5 july 2021
trap trap(.*);