2021-04-22 19:34:02 +00:00
|
|
|
///////////////////////////////////////////
|
2021-04-29 06:20:39 +00:00
|
|
|
// pmpchecker.sv
|
2021-04-22 19:34:02 +00:00
|
|
|
//
|
2021-04-29 06:20:39 +00:00
|
|
|
// Written: tfleming@hmc.edu & jtorrey@hmc.edu 28 April 2021
|
2021-04-22 19:34:02 +00:00
|
|
|
// Modified:
|
|
|
|
//
|
2021-04-29 06:20:39 +00:00
|
|
|
// Purpose: Examines all physical memory accesses and checks them against the
|
|
|
|
// current values of the physical memory protection (PMP) registers.
|
|
|
|
// Can raise an access fault on illegal reads, writes, and instruction
|
|
|
|
// fetches.
|
2021-04-22 19:34:02 +00:00
|
|
|
//
|
|
|
|
// A component of the Wally configurable RISC-V project.
|
|
|
|
//
|
|
|
|
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
|
|
|
|
//
|
|
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
|
|
|
|
// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
|
|
|
|
// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
|
|
|
|
// is furnished to do so, subject to the following conditions:
|
|
|
|
//
|
|
|
|
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
|
|
//
|
|
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
|
|
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
|
|
|
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
|
|
|
|
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
///////////////////////////////////////////
|
|
|
|
|
|
|
|
`include "wally-config.vh"
|
|
|
|
|
2021-04-29 06:20:39 +00:00
|
|
|
module pmpchecker (
|
2021-06-24 23:59:29 +00:00
|
|
|
input logic [`PA_BITS-1:0] PhysicalAddress,
|
2021-07-03 06:25:31 +00:00
|
|
|
input logic [1:0] PrivilegeModeW,
|
2021-04-29 06:20:39 +00:00
|
|
|
|
2021-05-04 19:18:08 +00:00
|
|
|
// *** ModelSim has a switch -svinputport which controls whether input ports
|
|
|
|
// are nets (wires) or vars by default. The default setting of this switch is
|
|
|
|
// `relaxed`, which means that signals are nets if and only if they are
|
|
|
|
// scalars or one-dimensional vectors. Since this is a two-dimensional vector,
|
|
|
|
// 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.
|
2021-07-02 15:04:13 +00:00
|
|
|
input var logic [63:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES/8-1:0],
|
2021-06-21 05:17:08 +00:00
|
|
|
input var logic [`XLEN-1:0] PMPADDR_ARRAY_REGW [`PMP_ENTRIES-1:0],
|
2021-04-22 19:34:02 +00:00
|
|
|
|
2021-05-03 21:37:42 +00:00
|
|
|
input logic ExecuteAccessF, WriteAccessM, ReadAccessM,
|
2021-04-22 19:34:02 +00:00
|
|
|
|
2021-05-03 21:37:42 +00:00
|
|
|
output logic PMPSquashBusAccess,
|
2021-04-22 19:34:02 +00:00
|
|
|
|
2021-05-03 21:37:42 +00:00
|
|
|
output logic PMPInstrAccessFaultF,
|
|
|
|
output logic PMPLoadAccessFaultM,
|
|
|
|
output logic PMPStoreAccessFaultM
|
2021-04-22 19:34:02 +00:00
|
|
|
);
|
|
|
|
|
2021-05-03 21:37:42 +00:00
|
|
|
|
2021-07-03 07:29:33 +00:00
|
|
|
// Bit i is high when the address falls in PMP region i
|
|
|
|
logic EnforcePMP;
|
2021-07-04 14:51:56 +00:00
|
|
|
logic [7:0] PMPCfg[`PMP_ENTRIES-1:0];
|
2021-07-03 07:29:33 +00:00
|
|
|
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
|
2021-07-04 14:51:56 +00:00
|
|
|
// verilator lint_off UNOPTFLAT
|
|
|
|
logic [`PMP_ENTRIES-1:0] NoLowerMatch; // None of the lower PMP entries match
|
|
|
|
// verilator lint_on UNOPTFLAT
|
|
|
|
logic [`PMP_ENTRIES-1:0] PAgePMPAdr; // for TOR PMP matching, PhysicalAddress > PMPAdr[i]
|
2021-07-02 15:04:13 +00:00
|
|
|
genvar i,j;
|
2021-07-04 14:51:56 +00:00
|
|
|
|
|
|
|
generate // extract 8-bit chunks from PMPCFG array
|
2021-07-03 07:29:33 +00:00
|
|
|
for (j=0; j<`PMP_ENTRIES; j = j+8)
|
2021-07-04 14:51:56 +00:00
|
|
|
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];
|
2021-07-02 15:04:13 +00:00
|
|
|
endgenerate
|
|
|
|
|
2021-07-04 14:51:56 +00:00
|
|
|
pmpadrdec pmpadrdec[`PMP_ENTRIES-1:0](
|
|
|
|
.PhysicalAddress,
|
|
|
|
.PMPCfg,
|
|
|
|
.PMPAdr(PMPADDR_ARRAY_REGW),
|
|
|
|
.PAgePMPAdrIn({PAgePMPAdr[`PMP_ENTRIES-2:0], 1'b1}),
|
|
|
|
.PAgePMPAdrOut(PAgePMPAdr),
|
|
|
|
.NoLowerMatchIn({NoLowerMatch[`PMP_ENTRIES-2:0], 1'b1}),
|
|
|
|
.NoLowerMatchOut(NoLowerMatch),
|
|
|
|
.Match, .Active, .L, .X, .W, .R);
|
|
|
|
|
|
|
|
|
2021-07-02 15:04:13 +00:00
|
|
|
// 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
|
2021-07-03 07:29:33 +00:00
|
|
|
assign EnforcePMP = (PrivilegeModeW == `M_MODE) ? |L : |Active;
|
2021-07-02 15:04:13 +00:00
|
|
|
|
2021-07-03 07:29:33 +00:00
|
|
|
assign PMPInstrAccessFaultF = EnforcePMP && ExecuteAccessF && ~|X;
|
|
|
|
assign PMPStoreAccessFaultM = EnforcePMP && WriteAccessM && ~|W;
|
|
|
|
assign PMPLoadAccessFaultM = EnforcePMP && ReadAccessM && ~|R;
|
2021-05-04 05:56:05 +00:00
|
|
|
|
2021-06-24 23:59:29 +00:00
|
|
|
assign PMPSquashBusAccess = PMPInstrAccessFaultF | PMPLoadAccessFaultM | PMPStoreAccessFaultM;
|
2021-04-22 19:34:02 +00:00
|
|
|
|
2021-04-26 16:48:58 +00:00
|
|
|
endmodule
|