Changed IMMU ExecuteAccessF to 1 rather than InstrReadF to fix buildroot; simplified PMP checker

This commit is contained in:
David Harris 2021-07-03 03:29:33 -04:00
parent d44916dacf
commit 1fa4abf7b6
5 changed files with 61 additions and 70 deletions

View File

@ -146,6 +146,7 @@ module ahblite (
// (ProposedNextBusState == MMUTRANSLATE);
// The PMA and PMP checkers can decide to squash the access
// *** this probably needs to be controlled by the caches rather than EBU dh 7/2/11
assign NextBusState = (DSquashBusAccessM || ISquashBusAccessF) ? IDLE : ProposedNextBusState;
// stall signals

View File

@ -127,7 +127,7 @@ module ifu (
.TLBMiss(ITLBMissF),
.TLBHit(ITLBHitF),
.TLBPageFault(ITLBInstrPageFaultF),
.ExecuteAccessF(InstrReadF), /// *** Ross Thompson this is definitely wrong. InstrReadF changed to icache read to memory.
.ExecuteAccessF(1'b1), // ***dh -- this should eventually change to only true if an instruction fetch is occurring
.AtomicAccessM(1'b0),
.ReadAccessM(1'b0),
.WriteAccessM(1'b0),

View File

@ -31,20 +31,29 @@
module pmpadrdec (
input logic [`PA_BITS-1:0] PhysicalAddress,
input logic [1:0] AdrMode,
input logic [`XLEN-1:0] CurrentPMPAdr,
input logic AdrAtLeastPreviousPMP,
output logic AdrAtLeastCurrentPMP,
output logic Match
input logic [7:0] PMPCfg,
input logic [`XLEN-1:0] PMPAdr,
input logic PAgePMPAdrIn,
input logic NoLowerMatchIn,
output logic PAgePMPAdrOut,
output logic NoLowerMatchOut,
output logic Match, Active,
output logic L, X, W, R
);
localparam TOR = 2'b01;
localparam NA4 = 2'b10;
localparam NAPOT = 2'b11;
logic TORMatch, NAMatch;
logic AdrBelowCurrentPMP;
logic PAltPMPAdr;
logic FirstMatch;
logic [`PA_BITS-1:0] CurrentAdrFull;
logic [1:0] AdrMode;
assign AdrMode = PMPCfg[4:3];
// The two lsb of the physical address don't matter for this checking.
// The following code includes them, but hardwires the PMP checker lsbs to 00
@ -52,10 +61,10 @@ module pmpadrdec (
// Top-of-range (TOR)
// Append two implicit trailing 0's to PMPAdr value
assign CurrentAdrFull = {CurrentPMPAdr[`PA_BITS-3:0], 2'b00};
assign AdrBelowCurrentPMP = {1'b0, PhysicalAddress} < {1'b0, CurrentAdrFull}; // unsigned comparison
assign AdrAtLeastCurrentPMP = ~AdrBelowCurrentPMP;
assign TORMatch = AdrAtLeastPreviousPMP && AdrBelowCurrentPMP;
assign CurrentAdrFull = {PMPAdr[`PA_BITS-3:0], 2'b00};
assign PAltPMPAdr = {1'b0, PhysicalAddress} < {1'b0, CurrentAdrFull}; // unsigned comparison
assign PAgePMPAdrOut = ~PAltPMPAdr;
assign TORMatch = PAgePMPAdrIn && PAltPMPAdr;
// Naturally aligned regions
@ -68,7 +77,7 @@ module pmpadrdec (
assign Mask[1:0] = 2'b11;
assign Mask[2] = (AdrMode == NAPOT); // mask has 0s in upper bis for NA4 region
for (i=3; i < `PA_BITS; i=i+1)
assign Mask[i] = Mask[i-1] & CurrentPMPAdr[i-3]; // NAPOT mask: 1's indicate bits to ignore
assign Mask[i] = Mask[i-1] & PMPAdr[i-3]; // NAPOT mask: 1's indicate bits to ignore
endgenerate
// verilator lint_on UNOPTFLAT
@ -78,5 +87,12 @@ module pmpadrdec (
(AdrMode == NA4 || AdrMode == NAPOT) ? NAMatch :
0;
endmodule
assign FirstMatch = NoLowerMatchIn & Match;
assign NoLowerMatchOut = NoLowerMatchIn & ~Match;
assign L = PMPCfg[7] & FirstMatch;
assign X = PMPCfg[2] & FirstMatch;
assign W = PMPCfg[1] & FirstMatch;
assign R = PMPCfg[0] & FirstMatch;
assign Active = |PMPCfg[4:3];
endmodule

View File

@ -51,76 +51,49 @@ module pmpchecker (
output logic PMPStoreAccessFaultM
);
// verilator lint_off UNOPTFLAT
// Bit i is high when the address falls in PMP region i
logic [`PMP_ENTRIES-1:0] Regions, FirstMatch;
logic EnforcePMP;
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 [`PMP_ENTRIES-1:0] AboveRegion;
// Bit i is high if PMP register i is non-null
logic [`PMP_ENTRIES-1:0] ActiveRegion;
logic [`PMP_ENTRIES-1:0] L_Bits, X_Bits, W_Bits, R_Bits;
logic EnforcePMP;
logic [7:0] PMPCFG [`PMP_ENTRIES-1:0];
logic [`PMP_ENTRIES-1:0] Match; // PMP Entry matches
logic [`PMP_ENTRIES-1:0] Active; // PMP register i is non-null
logic [`PMP_ENTRIES-1:0] L, X, W, R; // PMP matches and has flag set
logic [`PMP_ENTRIES:0] NoLowerMatch; // None of the lower PMP entries match
logic [`PMP_ENTRIES:0] PAgePMPAdr; // for TOR PMP matching, PhysicalAddress > PMPAdr[i]
genvar i,j;
pmpadrdec pmpadrdec(.PhysicalAddress(PhysicalAddress),
.AdrMode(PMPCFG[0][4:3]),
.CurrentPMPAdr(PMPADDR_ARRAY_REGW[0]),
.AdrAtLeastPreviousPMP(1'b1),
.AdrAtLeastCurrentPMP(AboveRegion[0]),
.Match(Regions[0]));
assign ActiveRegion[0] = |PMPCFG[0][4:3];
generate // *** only for PMP_ENTRIES > 0
for (i = 1; i < `PMP_ENTRIES; i++) begin
pmpadrdec pmpadrdec(.PhysicalAddress(PhysicalAddress),
.AdrMode(PMPCFG[i][4:3]),
.CurrentPMPAdr(PMPADDR_ARRAY_REGW[i]),
.AdrAtLeastPreviousPMP(AboveRegion[i-1]),
.AdrAtLeastCurrentPMP(AboveRegion[i]),
.Match(Regions[i]));
assign ActiveRegion[i] = |PMPCFG[i][4:3];
end
endgenerate
// verilator lint_off UNOPTFLAT
logic [`PMP_ENTRIES-1:0] NoLowerMatch;
assign PAgePMPAdr[0] = 1'b1;
assign NoLowerMatch[0] = 1'b1;
generate
// verilator lint_off WIDTH
for (j=0; j<`PMP_ENTRIES; j = j+8) begin
for (j=0; j<`PMP_ENTRIES; j = j+8)
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
for (i=0; i<`PMP_ENTRIES; i++)
pmpadrdec pmpadrdec(.PhysicalAddress,
.PMPCfg(PMPCFG[i]),
.PMPAdr(PMPADDR_ARRAY_REGW[i]),
.PAgePMPAdrIn(PAgePMPAdr[i]),
.PAgePMPAdrOut(PAgePMPAdr[i+1]),
.NoLowerMatchIn(NoLowerMatch[i]),
.NoLowerMatchOut(NoLowerMatch[i+1]),
.Match(Match[i]),
.Active(Active[i]),
.L(L[i]), .X(X[i]), .W(W[i]), .R(R[i])
);
// verilator lint_on UNOPTFLAT
endgenerate
// 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 EnforcePMP = (PrivilegeModeW == `M_MODE) ? |L : |Active;
assign PMPInstrAccessFaultF = EnforcePMP && ExecuteAccessF && ~|X_Bits;
assign PMPStoreAccessFaultM = EnforcePMP && WriteAccessM && ~|W_Bits;
assign PMPLoadAccessFaultM = EnforcePMP && ReadAccessM && ~|R_Bits;
assign PMPInstrAccessFaultF = EnforcePMP && ExecuteAccessF && ~|X;
assign PMPStoreAccessFaultM = EnforcePMP && WriteAccessM && ~|W;
assign PMPLoadAccessFaultM = EnforcePMP && ReadAccessM && ~|R;
assign PMPSquashBusAccess = PMPInstrAccessFaultF | PMPLoadAccessFaultM | PMPStoreAccessFaultM;

View File

@ -74,6 +74,7 @@ module uncore (
// Determine which region of physical memory (if any) is being accessed
// Use a trimmed down portion of the PMA checker - only the address decoders
// Set access types to all 1 as don't cares because the MMU has already done access checking
adrdecs adrdecs({{(`PA_BITS-32){1'b0}}, HADDR}, 1'b1, 1'b1, 1'b1, HSIZE[1:0], HSELRegions);
// unswizzle HSEL signals