diff --git a/wally-pipelined/src/ifu/ifu.sv b/wally-pipelined/src/ifu/ifu.sv index afae5ff4f..b08a1503e 100644 --- a/wally-pipelined/src/ifu/ifu.sv +++ b/wally-pipelined/src/ifu/ifu.sv @@ -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, diff --git a/wally-pipelined/src/lsu/lsu.sv b/wally-pipelined/src/lsu/lsu.sv index ffa79adfe..8c9de2ff7 100644 --- a/wally-pipelined/src/lsu/lsu.sv +++ b/wally-pipelined/src/lsu/lsu.sv @@ -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, diff --git a/wally-pipelined/src/mmu/mmu.sv b/wally-pipelined/src/mmu/mmu.sv index ff315f128..32309baaf 100644 --- a/wally-pipelined/src/mmu/mmu.sv +++ b/wally-pipelined/src/mmu/mmu.sv @@ -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, diff --git a/wally-pipelined/src/mmu/pmpchecker.sv b/wally-pipelined/src/mmu/pmpchecker.sv index f88d56fa0..5344249c7 100644 --- a/wally-pipelined/src/mmu/pmpchecker.sv +++ b/wally-pipelined/src/mmu/pmpchecker.sv @@ -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; diff --git a/wally-pipelined/src/privileged/csr.sv b/wally-pipelined/src/privileged/csr.sv index 213bcde33..dfac55711 100644 --- a/wally-pipelined/src/privileged/csr.sv +++ b/wally-pipelined/src/privileged/csr.sv @@ -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, diff --git a/wally-pipelined/src/privileged/csrm.sv b/wally-pipelined/src/privileged/csrm.sv index 33b903a83..f30ebb4ff 100644 --- a/wally-pipelined/src/privileged/csrm.sv +++ b/wally-pipelined/src/privileged/csrm.sv @@ -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 diff --git a/wally-pipelined/src/privileged/privileged.sv b/wally-pipelined/src/privileged/privileged.sv index 1275cd4b8..5ed8c8807 100644 --- a/wally-pipelined/src/privileged/privileged.sv +++ b/wally-pipelined/src/privileged/privileged.sv @@ -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 ); diff --git a/wally-pipelined/src/wally/wallypipelinedhart.sv b/wally-pipelined/src/wally/wallypipelinedhart.sv index a77c3ab01..9358417b1 100644 --- a/wally-pipelined/src/wally/wallypipelinedhart.sv +++ b/wally-pipelined/src/wally/wallypipelinedhart.sv @@ -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