Optimized PMP checker logic and added support for configurable number of PMP registers

This commit is contained in:
David Harris 2021-07-02 11:04:13 -04:00
parent a7f810e2c4
commit 648c09e5ef
8 changed files with 89 additions and 84 deletions

View File

@ -79,7 +79,7 @@ module ifu (
input logic [2:0] HSIZE, HBURST,
input logic HWRITE,
input logic ExecuteAccessF, //read, write, and atomic access are all set to zero because this mmu is onlt working with instructinos in the F stage.
input logic [63:0] PMPCFG01_REGW, PMPCFG23_REGW, // *** all of these come from the privileged unit, so they're gonna have to come over into ifu and dmem
input var logic [63:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES/8-1:0],
input var logic [`XLEN-1:0] PMPADDR_ARRAY_REGW [`PMP_ENTRIES-1:0],
output logic PMPInstrAccessFaultF, PMAInstrAccessFaultF,

View File

@ -70,7 +70,7 @@ module lsu (
input logic [2:0] HSIZE, HBURST,
input logic HWRITE,
input logic AtomicAccessM, WriteAccessM, ReadAccessM, // execute access is hardwired to zero in this mmu because we're only working with data in the M stage.
input logic [63:0] PMPCFG01_REGW, PMPCFG23_REGW, // *** all of these come from the privileged unit, so thwyre gonna have to come over into ifu and dmem
input var logic [63:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES/8-1:0],
input var logic [`XLEN-1:0] PMPADDR_ARRAY_REGW [`PMP_ENTRIES-1:0], // *** this one especially has a large note attached to it in pmpchecker.
output logic PMALoadAccessFaultM, PMAStoreAccessFaultM,

View File

@ -70,8 +70,8 @@ module mmu #(parameter ENTRY_BITS = 3,
input logic [2:0] HSIZE, HBURST,
input logic HWRITE,
input logic AtomicAccessM, ExecuteAccessF, WriteAccessM, ReadAccessM,
input logic [63:0] PMPCFG01_REGW, PMPCFG23_REGW, // *** all of these come from the privileged unit, so thwyre gonna have to come over into ifu and dmem
input var logic [`XLEN-1:0] PMPADDR_ARRAY_REGW [`PMP_ENTRIES-1:0],
input var logic [63:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES/8-1:0],
input var logic [`XLEN-1:0] PMPADDR_ARRAY_REGW [`PMP_ENTRIES-1:0],
output logic SquashBusAccess, // *** send to privileged unit
output logic PMPInstrAccessFaultF, PMPLoadAccessFaultM, PMPStoreAccessFaultM,

View File

@ -35,7 +35,6 @@ module pmpchecker (
input logic [1:0] PrivilegeModeW,
input logic [63:0] PMPCFG01_REGW, PMPCFG23_REGW,
// *** ModelSim has a switch -svinputport which controls whether input ports
// are nets (wires) or vars by default. The default setting of this switch is
@ -48,6 +47,7 @@ module pmpchecker (
// boundary. It would be better to store the PMP address registers in a module
// somewhere in the CSR hierarchy and do PMP checking _within_ that module, so
// we don't have to pass around 16 whole registers.
input var logic [63:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES/8-1:0],
input var logic [`XLEN-1:0] PMPADDR_ARRAY_REGW [`PMP_ENTRIES-1:0],
input logic ExecuteAccessF, WriteAccessM, ReadAccessM,
@ -60,29 +60,23 @@ module pmpchecker (
);
// Bit i is high when the address falls in PMP region i
logic [15:0] Regions;
logic [3:0] MatchedRegion;
logic Match, EnforcePMP;
logic [`PMP_ENTRIES-1:0] Regions, FirstMatch;
//logic [3:0] MatchedRegion;
logic EnforcePMP;
logic [7:0] PMPCFG [15:0];
logic [7:0] PMPCFG [`PMP_ENTRIES-1:0];
// Bit i is high when the address is greater than or equal to PMPADR[i]
// Used for determining whether TOR PMP regions match
logic [15:0] AboveRegion;
logic [`PMP_ENTRIES-1:0] AboveRegion;
// Bit i is high if PMP register i is non-null
logic [15:0] ActiveRegion;
logic [`PMP_ENTRIES-1:0] ActiveRegion;
logic L_Bit, X_Bit, W_Bit, R_Bit;
logic InvalidExecute, InvalidWrite, InvalidRead;
logic [`PMP_ENTRIES-1:0] L_Bits, X_Bits, W_Bits, R_Bits;
//logic InvalidExecute, InvalidWrite, InvalidRead;
// *** extend to optionally 64 configurations
assign {PMPCFG[15], PMPCFG[14], PMPCFG[13], PMPCFG[12],
PMPCFG[11], PMPCFG[10], PMPCFG[9], PMPCFG[8]} = PMPCFG23_REGW;
assign {PMPCFG[7], PMPCFG[6], PMPCFG[5], PMPCFG[4],
PMPCFG[3], PMPCFG[2], PMPCFG[1], PMPCFG[0]} = PMPCFG01_REGW;
genvar i,j;
pmpadrdec pmpadrdec(.HADDR(HADDR), .AdrMode(PMPCFG[0][4:3]),
.CurrentPMPAdr(PMPADDR_ARRAY_REGW[0]),
@ -92,7 +86,6 @@ module pmpchecker (
assign ActiveRegion[0] = |PMPCFG[0][4:3];
generate // *** only for PMP_ENTRIES > 0
genvar i;
for (i = 1; i < `PMP_ENTRIES; i++) begin
pmpadrdec pmpadrdec(.HADDR(HADDR), .AdrMode(PMPCFG[i][4:3]),
.CurrentPMPAdr(PMPADDR_ARRAY_REGW[i]),
@ -104,12 +97,34 @@ module pmpchecker (
end
endgenerate
assign Match = |Regions;
//assign Match = |Regions;
// Only enforce PMP checking for S and U modes when at least one PMP is active
assign EnforcePMP = |ActiveRegion;
// *** extend to up to 64, fold bit extraction to avoid need for binary encoding of region
// verilator lint_off UNOPTFLAT
logic [`PMP_ENTRIES-1:0] NoLowerMatch;
// assign NoLowerMatch[0] = 1;
generate
// verilator lint_off WIDTH
for (j=0; j<`PMP_ENTRIES; j = j+8) begin
assign {PMPCFG[j+7], PMPCFG[j+6], PMPCFG[j+5], PMPCFG[j+4],
PMPCFG[j+3], PMPCFG[j+2], PMPCFG[j+1], PMPCFG[j]} = PMPCFG_ARRAY_REGW[j/8];
end
// verilator lint_on WIDTH
for (i=0; i<`PMP_ENTRIES; i++) begin
if (i==0) begin
assign FirstMatch[i] = Regions[i];
assign NoLowerMatch[i] = ~Regions[i];
end else begin
assign FirstMatch[i] = Regions[i] & NoLowerMatch[i];
assign NoLowerMatch[i] = NoLowerMatch[i-1] & ~Regions[i];
end
assign L_Bits[i] = PMPCFG[i][7] & FirstMatch[i];
assign X_Bits[i] = PMPCFG[i][2] & FirstMatch[i];
assign W_Bits[i] = PMPCFG[i][1] & FirstMatch[i];
assign R_Bits[i] = PMPCFG[i][0] & FirstMatch[i];
end
// verilator lint_on UNOPTFLAT
endgenerate
/* // *** extend to up to 64, fold bit extraction to avoid need for binary encoding of region
always_comb
casez (Regions)
16'b???????????????1: MatchedRegion = 0;
@ -134,22 +149,18 @@ module pmpchecker (
assign L_Bit = PMPCFG[MatchedRegion][7] && Match;
assign X_Bit = PMPCFG[MatchedRegion][2] && Match;
assign W_Bit = PMPCFG[MatchedRegion][1] && Match;
assign R_Bit = PMPCFG[MatchedRegion][0] && Match;
assign R_Bit = PMPCFG[MatchedRegion][0] && Match;
assign InvalidExecute = ExecuteAccessF && ~X_Bit;
assign InvalidWrite = WriteAccessM && ~W_Bit;
assign InvalidRead = ReadAccessM && ~R_Bit;
assign InvalidRead = ReadAccessM && ~R_Bit;*/
// *** don't cause faults when there are no PMPs
assign PMPInstrAccessFaultF = (PrivilegeModeW == `M_MODE) ?
Match && L_Bit && InvalidExecute :
EnforcePMP && InvalidExecute;
assign PMPStoreAccessFaultM = (PrivilegeModeW == `M_MODE) ?
Match && L_Bit && InvalidWrite :
EnforcePMP && InvalidWrite;
assign PMPLoadAccessFaultM = (PrivilegeModeW == `M_MODE) ?
Match && L_Bit && InvalidRead :
EnforcePMP && InvalidRead;
// Only enforce PMP checking for S and U modes when at least one PMP is active or in Machine mode when L bit is set in selected region
assign EnforcePMP = (PrivilegeModeW == `M_MODE) ? |L_Bits : |ActiveRegion;
assign PMPInstrAccessFaultF = EnforcePMP && ExecuteAccessF && ~|X_Bits;
assign PMPStoreAccessFaultM = EnforcePMP && WriteAccessM && ~|W_Bits;
assign PMPLoadAccessFaultM = EnforcePMP && ReadAccessM && ~|R_Bits;
assign PMPSquashBusAccess = PMPInstrAccessFaultF || PMPLoadAccessFaultM || PMPStoreAccessFaultM;

View File

@ -60,7 +60,7 @@ module csr #(parameter
output logic STATUS_MIE, STATUS_SIE,
output logic STATUS_MXR, STATUS_SUM,
output logic STATUS_MPRV,
output logic [63:0] PMPCFG01_REGW, PMPCFG23_REGW,
output var logic [63:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES/8-1:0],
output var logic [`XLEN-1:0] PMPADDR_ARRAY_REGW [`PMP_ENTRIES-1:0],
input logic [4:0] SetFflagsM,
output logic [2:0] FRM_REGW,

View File

@ -48,25 +48,9 @@ module csrm #(parameter
MTVAL = 12'h343,
MIP = 12'h344,
PMPCFG0 = 12'h3A0,
PMPCFG1 = 12'h3A1,
PMPCFG2 = 12'h3A2,
PMPCFG3 = 12'h3A3,
// .. up to 15 more at consecutive addresses
PMPADDR0 = 12'h3B0,
PMPADDR1 = 12'h3B1,
PMPADDR2 = 12'h3B2,
PMPADDR3 = 12'h3B3,
PMPADDR4 = 12'h3B4,
PMPADDR5 = 12'h3B5,
PMPADDR6 = 12'h3B6,
PMPADDR7 = 12'h3B7,
PMPADDR8 = 12'h3B8,
PMPADDR9 = 12'h3B9,
PMPADDR10 = 12'h3BA,
PMPADDR11 = 12'h3BB,
PMPADDR12 = 12'h3BC,
PMPADDR13 = 12'h3BD,
PMPADDR14 = 12'h3BE,
PMPADDR15 = 12'h3BF,
// ... up to 63 more at consecutive addresses
TSELECT = 12'h7A0,
TDATA1 = 12'h7A1,
TDATA2 = 12'h7A2,
@ -90,7 +74,7 @@ module csrm #(parameter
output logic [31:0] MCOUNTEREN_REGW, MCOUNTINHIBIT_REGW,
output logic [`XLEN-1:0] MEDELEG_REGW, MIDELEG_REGW,
// 64-bit registers in RV64, or two 32-bit registers in RV32
output logic [63:0] PMPCFG01_REGW, PMPCFG23_REGW,
output var logic [63:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES/8-1:0],
output var logic [`XLEN-1:0] PMPADDR_ARRAY_REGW [`PMP_ENTRIES-1:0],
input logic [11:0] MIP_REGW, MIE_REGW,
output logic WriteMSTATUSM,
@ -103,8 +87,8 @@ module csrm #(parameter
logic WriteMTVECM, WriteMEDELEGM, WriteMIDELEGM;
logic WriteMSCRATCHM, WriteMEPCM, WriteMCAUSEM, WriteMTVALM;
logic WriteMCOUNTERENM, WriteMCOUNTINHIBITM;
logic WritePMPCFG0M, WritePMPCFG2M;
logic WritePMPADDRM [15:0];
logic [`PMP_ENTRIES/8-1:0] WritePMPCFGM, WritePMPCFGHM ;
logic [`PMP_ENTRIES-1:0] WritePMPADDRM ;
localparam MISA_26 = (`MISA) & 32'h03ffffff;
@ -120,7 +104,7 @@ module csrm #(parameter
assign WriteMEPCM = MTrapM | (CSRMWriteM && (CSRAdrM == MEPC)) && ~StallW;
assign WriteMCAUSEM = MTrapM | (CSRMWriteM && (CSRAdrM == MCAUSE)) && ~StallW;
assign WriteMTVALM = MTrapM | (CSRMWriteM && (CSRAdrM == MTVAL)) && ~StallW;
assign WritePMPCFG0M = (CSRMWriteM && (CSRAdrM == PMPCFG0)) && ~StallW;
/* assign WritePMPCFG0M = (CSRMWriteM && (CSRAdrM == PMPCFG0)) && ~StallW;
assign WritePMPCFG2M = (CSRMWriteM && (CSRAdrM == PMPCFG2)) && ~StallW;
assign WritePMPADDRM[0] = (CSRMWriteM && (CSRAdrM == PMPADDR0)) && ~StallW;
assign WritePMPADDRM[1] = (CSRMWriteM && (CSRAdrM == PMPADDR1)) && ~StallW;
@ -137,10 +121,13 @@ module csrm #(parameter
assign WritePMPADDRM[12] = (CSRMWriteM && (CSRAdrM == PMPADDR12)) && ~StallW;
assign WritePMPADDRM[13] = (CSRMWriteM && (CSRAdrM == PMPADDR13)) && ~StallW;
assign WritePMPADDRM[14] = (CSRMWriteM && (CSRAdrM == PMPADDR14)) && ~StallW;
assign WritePMPADDRM[15] = (CSRMWriteM && (CSRAdrM == PMPADDR15)) && ~StallW;
assign WritePMPADDRM[15] = (CSRMWriteM && (CSRAdrM == PMPADDR15)) && ~StallW; */
assign WriteMCOUNTERENM = CSRMWriteM && (CSRAdrM == MCOUNTEREN) && ~StallW;
assign WriteMCOUNTINHIBITM = CSRMWriteM && (CSRAdrM == MCOUNTINHIBIT) && ~StallW;
assign IllegalCSRMWriteReadonlyM = CSRMWriteM && (CSRAdrM == MVENDORID || CSRAdrM == MARCHID || CSRAdrM == MIMPID || CSRAdrM == MHARTID);
// CSRs
@ -172,33 +159,39 @@ module csrm #(parameter
flopenl #(32) MCOUNTINHIBITreg(clk, reset, WriteMCOUNTINHIBITM, CSRWriteValM[31:0], 32'hFFFFFFFF, MCOUNTINHIBIT_REGW);
// There are PMP_ENTRIES = 0, 16, or 64 PMPADDR registers, each of which has its own flop
// *** need to add support for locked PMPCFG and PMPADR
genvar i;
generate
genvar i;
for (i = 0; i < `PMP_ENTRIES; i++) begin: pmp_flop
for(i=0; i<`PMP_ENTRIES; i++) begin
assign WritePMPADDRM[i] = (CSRMWriteM && (CSRAdrM == PMPADDR0+i)) && ~StallW;
flopenr #(`XLEN) PMPADDRreg(clk, reset, WritePMPADDRM[i], CSRWriteValM, PMPADDR_ARRAY_REGW[i]);
end
for (i=0; i<`PMP_ENTRIES/8; i++) begin
if (`XLEN==64) begin
assign WritePMPCFGM[i] = (CSRMWriteM && (CSRAdrM == PMPCFG0+2*i)) && ~StallW;
flopenr #(`XLEN) PMPCFGreg(clk, reset, WritePMPCFGM[i], CSRWriteValM, PMPCFG_ARRAY_REGW[i]);
end else begin
assign WritePMPCFGM[i] = (CSRMWriteM && (CSRAdrM == PMPCFG0+2*i)) && ~StallW;
assign WritePMPCFGHM[i] = (CSRMWriteM && (CSRAdrM == PMPCFG0+2*i+1)) && ~StallW;
flopenr #(`XLEN) PMPCFGreg(clk, reset, WritePMPCFGM[i], CSRWriteValM, PMPCFG_ARRAY_REGW[i][31:0]);
flopenr #(`XLEN) PMPCFGHreg(clk, reset, WritePMPCFGHM[i], CSRWriteValM, PMPCFG_ARRAY_REGW[i][63:32]);
end
end
endgenerate
// PMPCFG registers are a pair of 64-bit in RV64 and four 32-bit in RV32
generate
if (`XLEN==64) begin
flopenr #(`XLEN) PMPCFG01reg(clk, reset, WritePMPCFG0M, CSRWriteValM, PMPCFG01_REGW);
flopenr #(`XLEN) PMPCFG23reg(clk, reset, WritePMPCFG2M, CSRWriteValM, PMPCFG23_REGW);
end else begin
logic WritePMPCFG1M, WritePMPCFG3M;
assign WritePMPCFG1M = MTrapM | (CSRMWriteM && (CSRAdrM == PMPCFG1));
assign WritePMPCFG3M = MTrapM | (CSRMWriteM && (CSRAdrM == PMPCFG3));
flopenr #(`XLEN) PMPCFG0reg(clk, reset, WritePMPCFG0M, CSRWriteValM, PMPCFG01_REGW[31:0]);
flopenr #(`XLEN) PMPCFG1reg(clk, reset, WritePMPCFG1M, CSRWriteValM, PMPCFG01_REGW[63:32]);
flopenr #(`XLEN) PMPCFG2reg(clk, reset, WritePMPCFG2M, CSRWriteValM, PMPCFG23_REGW[31:0]);
flopenr #(`XLEN) PMPCFG3reg(clk, reset, WritePMPCFG3M, CSRWriteValM, PMPCFG23_REGW[63:32]);
end
endgenerate
// Read machine mode CSRs
// verilator lint_off WIDTH
always_comb begin
IllegalCSRMAccessM = !(`S_SUPPORTED | `U_SUPPORTED & `N_SUPPORTED) &&
(CSRAdrM == MEDELEG || CSRAdrM == MIDELEG); // trap on DELEG register access when no S or N-mode
case (CSRAdrM)
if (CSRAdrM >= PMPADDR0 && CSRAdrM < PMPADDR0 + `PMP_ENTRIES) // reading a PMP entry
CSRMReadValM = PMPADDR_ARRAY_REGW[CSRAdrM - PMPADDR0];
else if (CSRAdrM >= PMPCFG0 && CSRAdrM < PMPCFG0 + `PMP_ENTRIES/8) begin
if (~CSRAdrM[0]) CSRMReadValM = PMPCFG_ARRAY_REGW[CSRAdrM - PMPCFG0][`XLEN-1:0];
else CSRMReadValM = {{(`XLEN-32){1'b0}}, PMPCFG_ARRAY_REGW[CSRAdrM - PMPCFG0][63:32]};
end
else case (CSRAdrM)
MISA_ADR: CSRMReadValM = MISA_REGW;
MVENDORID: CSRMReadValM = 0;
MARCHID: CSRMReadValM = 0;
@ -219,7 +212,7 @@ module csrm #(parameter
MTVAL: CSRMReadValM = MTVAL_REGW;
MCOUNTEREN:CSRMReadValM = {{(`XLEN-32){1'b0}}, MCOUNTEREN_REGW};
MCOUNTINHIBIT:CSRMReadValM = {{(`XLEN-32){1'b0}}, MCOUNTINHIBIT_REGW};
PMPCFG0: CSRMReadValM = PMPCFG01_REGW[`XLEN-1:0];
/* PMPCFG0: CSRMReadValM = PMPCFG01_REGW[`XLEN-1:0];
PMPCFG1: CSRMReadValM = {{(`XLEN-32){1'b0}}, PMPCFG01_REGW[63:32]};
PMPCFG2: CSRMReadValM = PMPCFG23_REGW[`XLEN-1:0];
PMPCFG3: CSRMReadValM = {{(`XLEN-32){1'b0}}, PMPCFG23_REGW[63:32]};
@ -238,11 +231,12 @@ module csrm #(parameter
PMPADDR12: CSRMReadValM = PMPADDR_ARRAY_REGW[12];
PMPADDR13: CSRMReadValM = PMPADDR_ARRAY_REGW[13];
PMPADDR14: CSRMReadValM = PMPADDR_ARRAY_REGW[14];
PMPADDR15: CSRMReadValM = PMPADDR_ARRAY_REGW[15];
PMPADDR15: CSRMReadValM = PMPADDR_ARRAY_REGW[15]; */
default: begin
CSRMReadValM = 0;
IllegalCSRMAccessM = 1;
end
endcase
end
// verilator lint_on WIDTH
endmodule

View File

@ -68,7 +68,7 @@ module privileged (
output logic [1:0] PrivilegeModeW,
output logic [`XLEN-1:0] SATP_REGW,
output logic STATUS_MXR, STATUS_SUM,
output logic [63:0] PMPCFG01_REGW, PMPCFG23_REGW,
output var logic [63:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES/8-1:0],
output var logic [`XLEN-1:0] PMPADDR_ARRAY_REGW [`PMP_ENTRIES-1:0],
output logic [2:0] FRM_REGW
);

View File

@ -126,7 +126,7 @@ module wallypipelinedhart (
logic DSquashBusAccessM, ISquashBusAccessF;
logic [5:0] DHSELRegionsM, IHSELRegionsF;
var logic [`XLEN-1:0] PMPADDR_ARRAY_REGW [`PMP_ENTRIES-1:0];
logic [63:0] PMPCFG01_REGW, PMPCFG23_REGW; // signals being sent from privileged unit to pmp/pma in dmem and ifu.
var logic [63:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES/8-1:0];
assign HSELRegions = ExecuteAccessF ? IHSELRegionsF : DHSELRegionsM; // *** this is a pure guess on how one of these should be selected. it passes tests, but is it the right way to do this?
// IMem stalls