mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-11 06:05:49 +00:00
PM(P/A) checkers parameterized based on Lim's work.
This commit is contained in:
parent
fcb1c63f5f
commit
70c8828ac2
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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) ;
|
||||
|
Loading…
Reference in New Issue
Block a user