diff --git a/src/mmu/pmpadrdec.sv b/src/mmu/pmpadrdec.sv index 3e21c6bc9..52f08aeab 100644 --- a/src/mmu/pmpadrdec.sv +++ b/src/mmu/pmpadrdec.sv @@ -40,20 +40,17 @@ module pmpadrdec import cvw::*; #(parameter cvw_t P) ( input logic PAgePMPAdrIn, output logic PAgePMPAdrOut, output logic Match, - output logic [P.PA_BITS-1:0] PMPTop, output logic L, X, W, R ); // define PMP addressing mode codes localparam TOR = 2'b01; - localparam NA4 = 2'b10; localparam NAPOT = 2'b11; logic TORMatch, NAMatch; logic PAltPMPAdr; logic [P.PA_BITS-1:0] PMPAdrFull; logic [1:0] AdrMode; - logic [P.PA_BITS-1:0] PMPTop1, PMPTopTOR, PMPTopNaturallyAligned; assign AdrMode = PMPCfg[4:3]; @@ -78,16 +75,9 @@ module pmpadrdec import cvw::*; #(parameter cvw_t P) ( // finally pick the appropriate match for the access type assign Match = (AdrMode == TOR) ? TORMatch : - (AdrMode == NA4 | AdrMode == NAPOT) ? NAMatch : + (AdrMode[1]) ? NAMatch : // NA4 or NAPOT 1'b0; // OFF never matches - // Report top of region for first matching region - // PMP should match but fail if the size is too big (8-byte accesses spanning to TOR or NA4 region) - assign PMPTopTOR = {PMPAdr-1, 2'b11}; // TOR goes to (pmpaddr << 2) - 1 - assign PMPTopNaturallyAligned = PMPAdrFull | NAMask; // top of the pmp region for NA4 and NAPOT. All 1s in the lower bits. Used to check the address doesn't pass the top - assign PMPTop1 = (AdrMode == TOR) ? PMPTopTOR : PMPTopNaturallyAligned; - assign PMPTop = FirstMatch ? PMPTop1 : '0; // AND portion of distributed AND-OR mux (OR portion in pmpchhecker) - assign L = PMPCfg[7]; assign X = PMPCfg[2]; assign W = PMPCfg[1]; diff --git a/src/mmu/pmpchecker.sv b/src/mmu/pmpchecker.sv index ebe83a710..2f3df12cf 100644 --- a/src/mmu/pmpchecker.sv +++ b/src/mmu/pmpchecker.sv @@ -56,12 +56,10 @@ module pmpchecker import cvw::*; #(parameter cvw_t P) ( logic [P.PMP_ENTRIES-1:0] FirstMatch; // onehot encoding for the first pmpaddr to match the current address. logic [P.PMP_ENTRIES-1:0] L, X, W, R; // PMP matches and has flag set logic [P.PMP_ENTRIES-1:0] PAgePMPAdr; // for TOR PMP matching, PhysicalAddress > PMPAdr[i] - logic [P.PA_BITS-1:0] PMPTop[P.PMP_ENTRIES-1:0]; // Upper end of each region, for checking that the access is fully within the region logic PMPCMOAccessFault, PMPCBOMAccessFault, PMPCBOZAccessFault; logic [2:0] SizeBytesMinus1; logic MatchingR, MatchingW, MatchingX, MatchingL; - logic [P.PA_BITS-1:0] MatchingPMPTop, PhysicalAddressTop; - logic TooBig; + if (P.PMP_ENTRIES > 0) begin: pmp // prevent complaints about array of no elements when PMP_ENTRIES = 0 pmpadrdec #(P) pmpadrdecs[P.PMP_ENTRIES-1:0]( @@ -72,34 +70,16 @@ module pmpchecker import cvw::*; #(parameter cvw_t P) ( .FirstMatch, .PAgePMPAdrIn({PAgePMPAdr[P.PMP_ENTRIES-2:0], 1'b1}), .PAgePMPAdrOut(PAgePMPAdr), - .Match, .PMPTop, .L, .X, .W, .R); + .Match, .L, .X, .W, .R); end priorityonehot #(P.PMP_ENTRIES) pmppriority(.a(Match), .y(FirstMatch)); // combine the match signal from all the address decoders to find the first one that matches. // Distributed AND-OR mux to select the first matching results - // If the access does not match all bytes of the PMP region, it is too big and the matches are disabled - assign MatchingR = |(R & FirstMatch) & ~TooBig; - assign MatchingW = |(W & FirstMatch) & ~TooBig; - assign MatchingX = |(X & FirstMatch) & ~TooBig; + assign MatchingR = |(R & FirstMatch); + assign MatchingW = |(W & FirstMatch); + assign MatchingX = |(X & FirstMatch); assign MatchingL = |(L & FirstMatch); - or_rows #(P.PMP_ENTRIES, P.PA_BITS) PTEOr(PMPTop, MatchingPMPTop); - - // Matching PMP entry must match all bytes of an access, or the access fails (Priv Spec 3.7.1.3) - // First find the size of the access in terms of the offset to the most significant byte - always_comb - case (Size) - 2'b00: SizeBytesMinus1 = 3'd0; - 2'b01: SizeBytesMinus1 = 3'd1; - 2'b10: SizeBytesMinus1 = 3'd3; - 2'b11: SizeBytesMinus1 = 3'd7; - endcase - // Then find the top of the access and see if it is beyond the top of the region - assign PhysicalAddressTop = PhysicalAddress + {{P.PA_BITS-3{1'b0}}, SizeBytesMinus1}; // top of the access range - // DH 5/27/25 *** TooBig should never occur because granularity is a line size, and anything wrapping line should be decomposed into multiple accesses. - // Therefore, it should be possilbe to remove TooBig and all the logic that depends on it - // including PhysicalAddressTop, SizeBytesMinus1, and the pmpadrdecs PMPTop output, which is expensive - assign TooBig = PhysicalAddressTop > MatchingPMPTop; // check if the access goes beyond the top of the PMP region // Only enforce PMP checking for effective S and U modes (accounting for mstatus.MPRV) or in Machine mode when L bit is set in selected region assign EnforcePMP = (EffectivePrivilegeModeW != P.M_MODE) | MatchingL;