Removed TooBig logic and PMP Top checking now that grain size is set to prevent accesses that wrap a region

This commit is contained in:
David Harris 2025-06-01 06:48:18 -07:00
parent 874d8d2efd
commit e013c57b9b
2 changed files with 6 additions and 36 deletions

View file

@ -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];

View file

@ -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;