diff --git a/wally-pipelined/src/ebu/ahblite.sv b/wally-pipelined/src/ebu/ahblite.sv index 70f32bf7..84e8f3b6 100644 --- a/wally-pipelined/src/ebu/ahblite.sv +++ b/wally-pipelined/src/ebu/ahblite.sv @@ -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 diff --git a/wally-pipelined/src/ifu/ifu.sv b/wally-pipelined/src/ifu/ifu.sv index 04110d9a..ddfd88cc 100644 --- a/wally-pipelined/src/ifu/ifu.sv +++ b/wally-pipelined/src/ifu/ifu.sv @@ -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), diff --git a/wally-pipelined/src/mmu/pmpadrdec.sv b/wally-pipelined/src/mmu/pmpadrdec.sv index bdd46bef..50d399ae 100644 --- a/wally-pipelined/src/mmu/pmpadrdec.sv +++ b/wally-pipelined/src/mmu/pmpadrdec.sv @@ -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 diff --git a/wally-pipelined/src/mmu/pmpchecker.sv b/wally-pipelined/src/mmu/pmpchecker.sv index 0d45229a..27c7e508 100644 --- a/wally-pipelined/src/mmu/pmpchecker.sv +++ b/wally-pipelined/src/mmu/pmpchecker.sv @@ -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; diff --git a/wally-pipelined/src/uncore/uncore.sv b/wally-pipelined/src/uncore/uncore.sv index 91aee66b..79f7a0e8 100644 --- a/wally-pipelined/src/uncore/uncore.sv +++ b/wally-pipelined/src/uncore/uncore.sv @@ -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