PM(P/A) checkers parameterized based on Lim's work.

This commit is contained in:
Ross Thompson 2023-05-24 17:20:55 -05:00
parent fcb1c63f5f
commit 70c8828ac2
4 changed files with 24 additions and 30 deletions

View File

@ -102,13 +102,13 @@ module mmu import cvw::*; #(parameter cvw_t P,
// Check physical memory accesses
///////////////////////////////////////////
pmachecker pmachecker(.PhysicalAddress, .Size,
pmachecker #(P.PA_BITS) pmachecker(.PhysicalAddress, .Size,
.AtomicAccessM, .ExecuteAccessF, .WriteAccessM, .ReadAccessM,
.Cacheable, .Idempotent, .SelTIM,
.PMAInstrAccessFaultF, .PMALoadAccessFaultM, .PMAStoreAmoAccessFaultM);
if (P.PMP_ENTRIES > 0) begin : pmp
pmpchecker pmpchecker(.PhysicalAddress, .PrivilegeModeW,
pmpchecker #(P) pmpchecker(.PhysicalAddress, .PrivilegeModeW,
.PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW,
.ExecuteAccessF, .WriteAccessM, .ReadAccessM,
.PMPInstrAccessFaultF, .PMPLoadAccessFaultM, .PMPStoreAmoAccessFaultM);

View File

@ -28,10 +28,8 @@
// and limitations under the License.
////////////////////////////////////////////////////////////////////////////////////////////////
`include "wally-config.vh"
module pmachecker (
input logic [`PA_BITS-1:0] PhysicalAddress,
module pmachecker #(parameter PA_BITS) (
input logic [PA_BITS-1:0] PhysicalAddress,
input logic [1:0] Size,
input logic AtomicAccessM, // Atomic access
input logic ExecuteAccessF, // Execute access

View File

@ -30,12 +30,10 @@
// and limitations under the License.
////////////////////////////////////////////////////////////////////////////////////////////////
`include "wally-config.vh"
module pmpadrdec (
input logic [`PA_BITS-1:0] PhysicalAddress,
module pmpadrdec import cvw::*; #(parameter cvw_t P) (
input logic [P.PA_BITS-1:0] PhysicalAddress,
input logic [7:0] PMPCfg,
input logic [`PA_BITS-3:0] PMPAdr,
input logic [P.PA_BITS-3:0] PMPAdr,
input logic PAgePMPAdrIn,
output logic PAgePMPAdrOut,
output logic Match,
@ -49,7 +47,7 @@ module pmpadrdec (
logic TORMatch, NAMatch;
logic PAltPMPAdr;
logic [`PA_BITS-1:0] CurrentAdrFull;
logic [P.PA_BITS-1:0] CurrentAdrFull;
logic [1:0] AdrMode;
assign AdrMode = PMPCfg[4:3];
@ -66,13 +64,13 @@ module pmpadrdec (
assign TORMatch = PAgePMPAdrIn & PAltPMPAdr; // exclusion-tag: PAgePMPAdrIn
// Naturally aligned regions
logic [`PA_BITS-1:0] NAMask, NABase;
logic [P.PA_BITS-1:0] NAMask, NABase;
assign NAMask[1:0] = {2'b11};
assign NAMask[`PA_BITS-1:2] = (PMPAdr + {{(`PA_BITS-3){1'b0}}, (AdrMode == NAPOT)}) ^ PMPAdr;
assign NAMask[P.PA_BITS-1:2] = (PMPAdr + {{(P.PA_BITS-3){1'b0}}, (AdrMode == NAPOT)}) ^ PMPAdr;
// form a mask where the bottom k bits are 1, corresponding to a size of 2^k bytes for this memory region.
// This assumes we're using at least an NA4 region, but works for any size NAPOT region.
assign NABase = {(PMPAdr & ~NAMask[`PA_BITS-1:2]), 2'b00}; // base physical address of the pmp.
assign NABase = {(PMPAdr & ~NAMask[P.PA_BITS-1:2]), 2'b00}; // base physical address of the pmp.
assign NAMatch = &((NABase ~^ PhysicalAddress) | NAMask); // check if upper bits of base address match, ignore lower bits correspoonding to inside the memory range

View File

@ -29,10 +29,8 @@
// and limitations under the License.
////////////////////////////////////////////////////////////////////////////////////////////////
`include "wally-config.vh"
module pmpchecker (
input logic [`PA_BITS-1:0] PhysicalAddress,
module pmpchecker import cvw::*; #(parameter cvw_t P) (
input logic [P.PA_BITS-1:0] PhysicalAddress,
input logic [1:0] PrivilegeModeW,
// ModelSim has a switch -svinputport which controls whether input ports
// are nets (wires) or vars by default. The default setting of this switch is
@ -41,8 +39,8 @@ module pmpchecker (
// this will be understood as a var. However, if we don't supply the `var`
// keyword, the compiler warns us that it's interpreting the signal as a var,
// which we might not intend.
input var logic [7:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES-1:0],
input var logic [`PA_BITS-3:0] PMPADDR_ARRAY_REGW [`PMP_ENTRIES-1:0],
input var logic [7:0] PMPCFG_ARRAY_REGW[P.PMP_ENTRIES-1:0],
input var logic [P.PA_BITS-3:0] PMPADDR_ARRAY_REGW [P.PMP_ENTRIES-1:0],
input logic ExecuteAccessF, WriteAccessM, ReadAccessM,
output logic PMPInstrAccessFaultF,
output logic PMPLoadAccessFaultM,
@ -51,25 +49,25 @@ module pmpchecker (
// Bit i is high when the address falls in PMP region i
logic EnforcePMP; // should PMP be checked in this privilege level
logic [`PMP_ENTRIES-1:0] Match; // physical address matches one of the pmp ranges
logic [`PMP_ENTRIES-1:0] FirstMatch; // onehot encoding for the first pmpaddr to match the current address.
logic [`PMP_ENTRIES-1:0] L, X, W, R; // PMP matches and has flag set
logic [`PMP_ENTRIES-1:0] PAgePMPAdr; // for TOR PMP matching, PhysicalAddress > PMPAdr[i]
logic [P.PMP_ENTRIES-1:0] Match; // physical address matches one of the pmp ranges
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]
if (`PMP_ENTRIES > 0) begin: pmp // prevent complaints about array of no elements when PMP_ENTRIES = 0
pmpadrdec pmpadrdecs[`PMP_ENTRIES-1:0](
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](
.PhysicalAddress,
.PMPCfg(PMPCFG_ARRAY_REGW),
.PMPAdr(PMPADDR_ARRAY_REGW),
.PAgePMPAdrIn({PAgePMPAdr[`PMP_ENTRIES-2:0], 1'b1}),
.PAgePMPAdrIn({PAgePMPAdr[P.PMP_ENTRIES-2:0], 1'b1}),
.PAgePMPAdrOut(PAgePMPAdr),
.Match, .L, .X, .W, .R);
end
priorityonehot #(`PMP_ENTRIES) pmppriority(.a(Match), .y(FirstMatch)); // combine the match signal from all the adress decoders to find the first one that matches.
priorityonehot #(P.PMP_ENTRIES) pmppriority(.a(Match), .y(FirstMatch)); // combine the match signal from all the adress decoders to find the first one that matches.
// Only enforce PMP checking for S and U modes or in Machine mode when L bit is set in selected region
assign EnforcePMP = (PrivilegeModeW != `M_MODE) | |(L & FirstMatch); // *** switch to this logic when PMP is initialized for non-machine mode
assign EnforcePMP = (PrivilegeModeW != P.M_MODE) | |(L & FirstMatch); // *** switch to this logic when PMP is initialized for non-machine mode
assign PMPInstrAccessFaultF = EnforcePMP & ExecuteAccessF & ~|(X & FirstMatch) ;
assign PMPStoreAmoAccessFaultM = EnforcePMP & WriteAccessM & ~|(W & FirstMatch) ;