mirror of
https://github.com/stnolting/neorv32.git
synced 2025-04-23 13:47:33 -04:00
Allow disabling certain PMP modes (#808)
This commit is contained in:
commit
beab81e6b9
10 changed files with 120 additions and 77 deletions
|
@ -30,6 +30,7 @@ mimpid = 0x01040312 -> Version 01.04.03.12 -> v1.4.3.12
|
|||
|
||||
| Date | Version | Comment | Link |
|
||||
|:----:|:-------:|:--------|:----:|
|
||||
| 16.02.2024 | 1.9.5.1 | :sparkles: add two new generics to exclude certain PMP modes from synthesis | [#808](https://github.com/stnolting/neorv32/pull/808) |
|
||||
| 16.02.2024 | [**:rocket:1.9.5**](https://github.com/stnolting/neorv32/releases/tag/v1.9.5) | **New release** | |
|
||||
| 15.02.2023 | 1.9.4.13 | allow the DMA to issue a FENCE operation | [#807](https://github.com/stnolting/neorv32/pull/807) |
|
||||
| 14.02.2024 | 1.9.4.12 | :bug: close another illegal compressed instruction encoding loophole | [#806](https://github.com/stnolting/neorv32/pull/806) |
|
||||
|
|
|
@ -784,13 +784,19 @@ The NEORV32 PMP is fully compatible to the RISC-V Privileged Architecture Specif
|
|||
**grant permissions to user mode**, which by default has none, and can **revoke permissions from M-mode**, which
|
||||
by default has full permissions. The PMP is configured via the <<_machine_physical_memory_protection_csrs>>.
|
||||
|
||||
Several <<_processor_top_entity_generics>> are provided to fine-tune the CPU's PMP capabilities:
|
||||
* `PMP_NUM_REGIONS` defines the number of implemented PMP region
|
||||
* `PMP_MIN_GRANULARITY` defines the minimal granularity of each region
|
||||
* `PMP_TOR_MODE_EN` controls the implementation of the top-of-region (TOR) mode
|
||||
* `PMP_NAP_MODE_EN` controls the implementation of the naturally-aligned-power-of-two (NA4 and NAPOT) modes
|
||||
|
||||
.PMP Rules when in Debug Mode
|
||||
[NOTE]
|
||||
When in debug-mode all PMP rules are ignored making the debugger have maximum access rights.
|
||||
|
||||
[IMPORTANT]
|
||||
Instruction fetches are also triggered when denied by a certain PMP rule. However, the fetched instruction(s)
|
||||
will not be executed and will not change CPU core state to preserve memory access protection.
|
||||
will not be executed and will not change CPU core state.
|
||||
|
||||
|
||||
==== `Smcntrpmf` - ISA Extension
|
||||
|
|
|
@ -561,6 +561,11 @@ See section <<_pmp_isa_extension>> for more information.
|
|||
| 7 | `PMPCFG_L` | r/w | **L**: Lock bit, prevents further write accesses, also enforces access rights in machine-mode, can only be cleared by CPU reset
|
||||
|=======================
|
||||
|
||||
.Implemented Modes
|
||||
[NOTE]
|
||||
In order to reduce the CPU size certain PMP modes (`A` bits) can be excluded from synthesis.
|
||||
Use the `PMP_TOR_MODE_EN` and `PMP_NAP_MODE_EN` <<_processor_top_entity_generics>> to control
|
||||
implementation of the according modes.
|
||||
|
||||
{empty} +
|
||||
[discrete]
|
||||
|
@ -593,12 +598,6 @@ The `pmpaddr*` CSRs are used to configure the region's address boundaries.
|
|||
| Description | Region address configuration. The two MSBs of each CSR are hardwired to zero (= bits 33:32 of the physical address).
|
||||
|=======================
|
||||
|
||||
.Address Register Update Latency
|
||||
[IMPORTANT]
|
||||
After writing a `pmpaddr` CSR the hardware requires up to 32 clock cycles to compute the according
|
||||
address masks. Make sure to wait for this time before completing the PMP region configuration
|
||||
(only relevant for `NA4` and `NAPOT` modes).
|
||||
|
||||
|
||||
<<<
|
||||
// ####################################################################################################################
|
||||
|
|
|
@ -228,6 +228,8 @@ The generic type "`suv(x:y)`" is an abbreviation for "`std_ulogic_vector(x downt
|
|||
4+^| **Physical Memory Protection (<<_pmp_isa_extension>>)**
|
||||
| `PMP_NUM_REGIONS` | natural | 0 | Number of implemented PMP regions (0..16).
|
||||
| `PMP_MIN_GRANULARITY` | natural | 4 | Minimal region granularity in bytes. Has to be a power of two, min 4.
|
||||
| `PMP_TOR_MODE_EN` | boolean | true | Implement support for top-of-region (TOR) mode.
|
||||
| `PMP_NAP_MODE_EN` | boolean | true | Implement support for naturally-aligned power-of-two (NAPOT & NA4) modes.
|
||||
4+^| **Hardware Performance Monitors (<<_zihpm_isa_extension>>)**
|
||||
| `HPM_NUM_CNTS` | natural | 0 | Number of implemented hardware performance monitor counters (0..13).
|
||||
| `HPM_CNT_WIDTH` | natural | 40 | Total LSB-aligned size of each HPM counter. Min 0, max 64.
|
||||
|
|
|
@ -68,6 +68,8 @@ entity neorv32_cpu is
|
|||
-- Physical Memory Protection (PMP) --
|
||||
PMP_NUM_REGIONS : natural range 0 to 16; -- number of regions (0..16)
|
||||
PMP_MIN_GRANULARITY : natural; -- minimal region granularity in bytes, has to be a power of 2, min 4 bytes
|
||||
PMP_TOR_MODE_EN : boolean; -- implement TOR mode
|
||||
PMP_NAP_MODE_EN : boolean; -- implement NAPOT/NA4 modes
|
||||
-- Hardware Performance Monitors (HPM) --
|
||||
HPM_NUM_CNTS : natural range 0 to 13; -- number of implemented HPM counters (0..13)
|
||||
HPM_CNT_WIDTH : natural range 0 to 64 -- total size of HPM counters (0..64)
|
||||
|
@ -101,7 +103,7 @@ architecture neorv32_cpu_rtl of neorv32_cpu is
|
|||
constant regfile_rs4_en_c : boolean := CPU_EXTENSION_RISCV_Zxcfu; -- 4th register file read port (rs4)
|
||||
constant pmp_enable_c : boolean := boolean(PMP_NUM_REGIONS > 0);
|
||||
|
||||
-- external CSR interface --
|
||||
-- control-unit-external CSR interface --
|
||||
signal xcsr_we : std_ulogic;
|
||||
signal xcsr_addr : std_ulogic_vector(11 downto 0);
|
||||
signal xcsr_wdata : std_ulogic_vector(XLEN-1 downto 0);
|
||||
|
@ -358,8 +360,10 @@ begin
|
|||
if pmp_enable_c generate
|
||||
neorv32_cpu_pmp_inst: entity neorv32.neorv32_cpu_pmp
|
||||
generic map (
|
||||
NUM_REGIONS => PMP_NUM_REGIONS, -- number of regions (0..16)
|
||||
GRANULARITY => PMP_MIN_GRANULARITY -- minimal region granularity in bytes, has to be a power of 2, min 4 bytes
|
||||
NUM_REGIONS => PMP_NUM_REGIONS, -- number of regions (0..16)
|
||||
GRANULARITY => PMP_MIN_GRANULARITY, -- minimal region granularity in bytes, has to be a power of 2, min 4 bytes
|
||||
TOR_EN => PMP_TOR_MODE_EN, -- implement TOR mode
|
||||
NAP_EN => PMP_NAP_MODE_EN -- implement NAPOT/NA4 modes
|
||||
)
|
||||
port map (
|
||||
-- global control --
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
-- #################################################################################################
|
||||
-- # << NEORV32 CPU - Physical Memory Protection Unit >> #
|
||||
-- # ********************************************************************************************* #
|
||||
-- # Compatible to the RISC-V PMP privilege architecture specifications. #
|
||||
-- # ********************************************************************************************* #
|
||||
-- # BSD 3-Clause License #
|
||||
-- # #
|
||||
-- # The NEORV32 RISC-V Processor, https://github.com/stnolting/neorv32 #
|
||||
|
@ -41,7 +43,9 @@ use neorv32.neorv32_package.all;
|
|||
entity neorv32_cpu_pmp is
|
||||
generic (
|
||||
NUM_REGIONS : natural range 0 to 16; -- number of regions (0..16)
|
||||
GRANULARITY : natural range 4 to natural'high -- minimal region granularity in bytes, has to be a power of 2, min 4 bytes
|
||||
GRANULARITY : natural range 4 to natural'high; -- minimal region granularity in bytes, has to be a power of 2, min 4 bytes
|
||||
TOR_EN : boolean; -- implement TOR mode
|
||||
NAP_EN : boolean -- implement NAPOT/NA4 modes
|
||||
);
|
||||
port (
|
||||
-- global control --
|
||||
|
@ -112,25 +116,16 @@ architecture neorv32_cpu_pmp_rtl of neorv32_cpu_pmp is
|
|||
type addr_mask_t is array (0 to NUM_REGIONS-1) of std_ulogic_vector(XLEN-1 downto pmp_lsb_c);
|
||||
signal addr_mask_napot, addr_mask : addr_mask_t;
|
||||
type region_t is record
|
||||
i_cmp_mm : std_ulogic_vector(NUM_REGIONS-1 downto 0);
|
||||
i_cmp_ge : std_ulogic_vector(NUM_REGIONS-1 downto 0);
|
||||
i_cmp_lt : std_ulogic_vector(NUM_REGIONS-1 downto 0);
|
||||
d_cmp_mm : std_ulogic_vector(NUM_REGIONS-1 downto 0);
|
||||
d_cmp_ge : std_ulogic_vector(NUM_REGIONS-1 downto 0);
|
||||
d_cmp_lt : std_ulogic_vector(NUM_REGIONS-1 downto 0);
|
||||
i_match : std_ulogic_vector(NUM_REGIONS-1 downto 0);
|
||||
d_match : std_ulogic_vector(NUM_REGIONS-1 downto 0);
|
||||
perm_ex : std_ulogic_vector(NUM_REGIONS-1 downto 0);
|
||||
perm_rw : std_ulogic_vector(NUM_REGIONS-1 downto 0);
|
||||
i_cmp_mm, d_cmp_mm : std_ulogic_vector(NUM_REGIONS-1 downto 0); -- masked match
|
||||
i_cmp_ge, d_cmp_ge : std_ulogic_vector(NUM_REGIONS-1 downto 0); -- greater or equal
|
||||
i_cmp_lt, d_cmp_lt : std_ulogic_vector(NUM_REGIONS-1 downto 0); -- less than
|
||||
i_match, d_match : std_ulogic_vector(NUM_REGIONS-1 downto 0); -- region address match
|
||||
perm_ex, perm_rw : std_ulogic_vector(NUM_REGIONS-1 downto 0); -- region's permission
|
||||
end record;
|
||||
signal region : region_t;
|
||||
|
||||
-- permission check --
|
||||
type check_t is record
|
||||
fail_ex : std_ulogic_vector(NUM_REGIONS downto 0);
|
||||
fail_rw : std_ulogic_vector(NUM_REGIONS downto 0);
|
||||
end record;
|
||||
signal check : check_t;
|
||||
-- permission check violation --
|
||||
signal fail_ex, fail_rw : std_ulogic_vector(NUM_REGIONS downto 0);
|
||||
|
||||
begin
|
||||
|
||||
|
@ -160,6 +155,7 @@ begin
|
|||
csr_reg_gen:
|
||||
for i in 0 to NUM_REGIONS-1 generate
|
||||
csr_reg: process(rstn_i, clk_i)
|
||||
variable mode_v : std_ulogic_vector(1 downto 0);
|
||||
begin
|
||||
if (rstn_i = '0') then
|
||||
csr.cfg(i) <= (others => '0');
|
||||
|
@ -171,11 +167,17 @@ begin
|
|||
csr.cfg(i)(cfg_r_c) <= csr_wdata_i((i mod 4)*8+0); -- R (read)
|
||||
csr.cfg(i)(cfg_w_c) <= csr_wdata_i((i mod 4)*8+1); -- W (write)
|
||||
csr.cfg(i)(cfg_x_c) <= csr_wdata_i((i mod 4)*8+2); -- X (execute)
|
||||
if (granularity_c > 4) and (csr_wdata_i((i mod 4)*8+4 downto (i mod 4)*8+3) = mode_na4_c) then
|
||||
csr.cfg(i)(cfg_ah_c downto cfg_al_c) <= mode_off_c; -- NA4 not available, fall back to OFF
|
||||
else
|
||||
csr.cfg(i)(cfg_ah_c downto cfg_al_c) <= csr_wdata_i((i mod 4)*8+4 downto (i mod 4)*8+3); -- A (mode)
|
||||
-- A (mode) --
|
||||
mode_v := csr_wdata_i((i mod 4)*8+4 downto (i mod 4)*8+3);
|
||||
if ((mode_v = mode_tor_c) and (TOR_EN = false)) or -- TOR mode not implemented
|
||||
((mode_v = mode_na4_c) and (NAP_EN = false)) or -- NA4 mode not implemented
|
||||
((mode_v = mode_napot_c) and (NAP_EN = false)) or -- NAPOT mode not implemented
|
||||
((mode_v = mode_na4_c) and (granularity_c > 4)) then -- NA4 not available
|
||||
csr.cfg(i)(cfg_ah_c downto cfg_al_c) <= mode_off_c;
|
||||
else -- valid configuration
|
||||
csr.cfg(i)(cfg_ah_c downto cfg_al_c) <= mode_v;
|
||||
end if;
|
||||
--
|
||||
csr.cfg(i)(cfg_rl_c) <= '0'; -- reserved
|
||||
csr.cfg(i)(cfg_rh_c) <= '0'; -- reserved
|
||||
csr.cfg(i)(cfg_l_c) <= csr_wdata_i((i mod 4)*8+7); -- L (locked)
|
||||
|
@ -222,14 +224,18 @@ begin
|
|||
begin
|
||||
addr_rd(i) <= (others => '0');
|
||||
addr_rd(i)(XLEN-1 downto pmp_lsb_c-2) <= csr.addr(i)(XLEN-1 downto pmp_lsb_c-2);
|
||||
if (granularity_c = 8) then -- bit G-1 reads as zero in TOR or OFF mode
|
||||
if (granularity_c = 8) and TOR_EN then -- bit G-1 reads as zero in TOR or OFF mode
|
||||
if (csr.cfg(i)(cfg_ah_c) = '0') then -- TOR/OFF mode
|
||||
addr_rd(i)(pmp_lsb_c) <= '0';
|
||||
end if;
|
||||
elsif (granularity_c > 8) then
|
||||
addr_rd(i)(pmp_lsb_c-2 downto 0) <= (others => '1'); -- in NAPOT mode bits G-2:0 must read as one
|
||||
if (csr.cfg(i)(cfg_ah_c) = '0') then -- TOR/OFF mode
|
||||
addr_rd(i)(pmp_lsb_c-1 downto 0) <= (others => '0'); -- in TOR or OFF mode bits G-1:0 must read as zero
|
||||
if NAP_EN then
|
||||
addr_rd(i)(pmp_lsb_c-2 downto 0) <= (others => '1'); -- in NAPOT mode bits G-2:0 must read as one
|
||||
end if;
|
||||
if TOR_EN then
|
||||
if (csr.cfg(i)(cfg_ah_c) = '0') then -- TOR/OFF mode
|
||||
addr_rd(i)(pmp_lsb_c-1 downto 0) <= (others => '0'); -- in TOR or OFF mode bits G-1:0 must read as zero
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process address_read_back;
|
||||
|
@ -258,47 +264,52 @@ begin
|
|||
xaddr(r) <= csr.addr(r) & "00"; -- mask byte offset
|
||||
|
||||
|
||||
-- compute address masks for NAPOT mode --
|
||||
addr_mask_napot(r)(pmp_lsb_c) <= '0';
|
||||
addr_mask_napot_gen:
|
||||
for i in pmp_lsb_c+1 to XLEN-1 generate
|
||||
addr_mask_napot(r)(i) <= addr_mask_napot(r)(i-1) or (not xaddr(r)(i-1));
|
||||
end generate;
|
||||
nap_mode_enable:
|
||||
if NAP_EN generate
|
||||
|
||||
-- address mask select --
|
||||
addr_masking: process(rstn_i, clk_i)
|
||||
begin
|
||||
if (rstn_i = '0') then
|
||||
addr_mask(r) <= (others => '0');
|
||||
elsif rising_edge(clk_i) then
|
||||
if (csr.cfg(r)(cfg_al_c) = '1') then -- NAPOT
|
||||
addr_mask(r) <= addr_mask_napot(r);
|
||||
else -- NA4
|
||||
addr_mask(r) <= (others => '1');
|
||||
-- compute address masks for NAPOT mode --
|
||||
addr_mask_napot(r)(pmp_lsb_c) <= '0';
|
||||
addr_mask_napot_gen:
|
||||
for i in pmp_lsb_c+1 to XLEN-1 generate
|
||||
addr_mask_napot(r)(i) <= addr_mask_napot(r)(i-1) or (not xaddr(r)(i-1));
|
||||
end generate;
|
||||
|
||||
-- address mask select --
|
||||
addr_masking: process(rstn_i, clk_i)
|
||||
begin
|
||||
if (rstn_i = '0') then
|
||||
addr_mask(r) <= (others => '0');
|
||||
elsif rising_edge(clk_i) then
|
||||
if (csr.cfg(r)(cfg_al_c) = '1') then -- NAPOT
|
||||
addr_mask(r) <= addr_mask_napot(r);
|
||||
else -- NA4
|
||||
addr_mask(r) <= (others => '1');
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process addr_masking;
|
||||
end process addr_masking;
|
||||
|
||||
end generate;
|
||||
|
||||
|
||||
-- check region address match --
|
||||
-- NA4 and NAPOT --
|
||||
region.i_cmp_mm(r) <= '1' when ((addr_if_i(XLEN-1 downto pmp_lsb_c) and addr_mask(r)) = (xaddr(r)(XLEN-1 downto pmp_lsb_c) and addr_mask(r))) else '0';
|
||||
region.d_cmp_mm(r) <= '1' when ((addr_ls_i(XLEN-1 downto pmp_lsb_c) and addr_mask(r)) = (xaddr(r)(XLEN-1 downto pmp_lsb_c) and addr_mask(r))) else '0';
|
||||
region.i_cmp_mm(r) <= '1' when ((addr_if_i(XLEN-1 downto pmp_lsb_c) and addr_mask(r)) = (xaddr(r)(XLEN-1 downto pmp_lsb_c) and addr_mask(r))) and NAP_EN else '0';
|
||||
region.d_cmp_mm(r) <= '1' when ((addr_ls_i(XLEN-1 downto pmp_lsb_c) and addr_mask(r)) = (xaddr(r)(XLEN-1 downto pmp_lsb_c) and addr_mask(r))) and NAP_EN else '0';
|
||||
-- TOR region 0 --
|
||||
addr_match_r0_gen:
|
||||
if (r = 0) generate -- first entry: use ZERO as base and current entry as bound
|
||||
region.i_cmp_ge(r) <= '1'; -- address is always greater than or equal to zero
|
||||
region.i_cmp_ge(r) <= '1' when TOR_EN else '0'; -- address is always greater than or equal to zero (and TOR mode enabled)
|
||||
region.i_cmp_lt(r) <= '0'; -- unused
|
||||
region.d_cmp_ge(r) <= '1'; -- address is always greater than or equal to zero
|
||||
region.d_cmp_ge(r) <= '1' when TOR_EN else '0'; -- address is always greater than or equal to zero (and TOR mode enabled)
|
||||
region.d_cmp_lt(r) <= '0'; -- unused
|
||||
end generate;
|
||||
-- TOR region any --
|
||||
addr_match_rx_gen:
|
||||
if (r > 0) generate -- use previous entry as base and current entry as bound
|
||||
region.i_cmp_ge(r) <= '1' when (unsigned(addr_if_i(XLEN-1 downto pmp_lsb_c)) >= unsigned(xaddr(r-1)(XLEN-1 downto pmp_lsb_c))) else '0';
|
||||
region.i_cmp_lt(r) <= '1' when (unsigned(addr_if_i(XLEN-1 downto pmp_lsb_c)) < unsigned(xaddr(r )(XLEN-1 downto pmp_lsb_c))) else '0';
|
||||
region.d_cmp_ge(r) <= '1' when (unsigned(addr_ls_i(XLEN-1 downto pmp_lsb_c)) >= unsigned(xaddr(r-1)(XLEN-1 downto pmp_lsb_c))) else '0';
|
||||
region.d_cmp_lt(r) <= '1' when (unsigned(addr_ls_i(XLEN-1 downto pmp_lsb_c)) < unsigned(xaddr(r )(XLEN-1 downto pmp_lsb_c))) else '0';
|
||||
region.i_cmp_ge(r) <= '1' when (unsigned(addr_if_i(XLEN-1 downto pmp_lsb_c)) >= unsigned(xaddr(r-1)(XLEN-1 downto pmp_lsb_c))) and TOR_EN else '0';
|
||||
region.i_cmp_lt(r) <= '1' when (unsigned(addr_if_i(XLEN-1 downto pmp_lsb_c)) < unsigned(xaddr(r )(XLEN-1 downto pmp_lsb_c))) and TOR_EN else '0';
|
||||
region.d_cmp_ge(r) <= '1' when (unsigned(addr_ls_i(XLEN-1 downto pmp_lsb_c)) >= unsigned(xaddr(r-1)(XLEN-1 downto pmp_lsb_c))) and TOR_EN else '0';
|
||||
region.d_cmp_lt(r) <= '1' when (unsigned(addr_ls_i(XLEN-1 downto pmp_lsb_c)) < unsigned(xaddr(r )(XLEN-1 downto pmp_lsb_c))) and TOR_EN else '0';
|
||||
end generate;
|
||||
|
||||
|
||||
|
@ -310,21 +321,31 @@ begin
|
|||
region.i_match(r) <= '0';
|
||||
region.d_match(r) <= '0';
|
||||
when mode_tor_c => -- top of region
|
||||
if (r = (NUM_REGIONS-1)) then -- very last entry
|
||||
region.i_match(r) <= region.i_cmp_ge(r) and region.i_cmp_lt(r);
|
||||
region.d_match(r) <= region.d_cmp_ge(r) and region.d_cmp_lt(r);
|
||||
else -- this saves a LOT of comparators
|
||||
region.i_match(r) <= region.i_cmp_ge(r) and (not region.i_cmp_ge(r+1));
|
||||
region.d_match(r) <= region.d_cmp_ge(r) and (not region.d_cmp_ge(r+1));
|
||||
if TOR_EN then -- TOR mode implemented?
|
||||
if (r = (NUM_REGIONS-1)) then -- very last entry
|
||||
region.i_match(r) <= region.i_cmp_ge(r) and region.i_cmp_lt(r);
|
||||
region.d_match(r) <= region.d_cmp_ge(r) and region.d_cmp_lt(r);
|
||||
else -- this saves a LOT of comparators
|
||||
region.i_match(r) <= region.i_cmp_ge(r) and (not region.i_cmp_ge(r+1));
|
||||
region.d_match(r) <= region.d_cmp_ge(r) and (not region.d_cmp_ge(r+1));
|
||||
end if;
|
||||
else
|
||||
region.i_match(r) <= '0';
|
||||
region.d_match(r) <= '0';
|
||||
end if;
|
||||
when others => -- naturally-aligned region
|
||||
region.i_match(r) <= region.i_cmp_mm(r);
|
||||
region.d_match(r) <= region.d_cmp_mm(r);
|
||||
if NAP_EN then -- NAPOT/NA4 modes implemented?
|
||||
region.i_match(r) <= region.i_cmp_mm(r);
|
||||
region.d_match(r) <= region.d_cmp_mm(r);
|
||||
else
|
||||
region.i_match(r) <= '0';
|
||||
region.d_match(r) <= '0';
|
||||
end if;
|
||||
end case;
|
||||
end process match_gen;
|
||||
|
||||
|
||||
-- compute region permission --
|
||||
-- compute region permissions --
|
||||
perm_gen: process(csr.cfg, ctrl_i)
|
||||
begin
|
||||
-- execute (X) --
|
||||
|
@ -357,13 +378,13 @@ begin
|
|||
-- -------------------------------------------------------------------------------------------
|
||||
|
||||
-- check for access fault (using static prioritization) --
|
||||
check.fail_ex(NUM_REGIONS) <= '1' when (ctrl_i.cpu_priv /= priv_mode_m_c) else '0'; -- default (if not match): fault if not M-mode
|
||||
check.fail_rw(NUM_REGIONS) <= '1' when (ctrl_i.lsu_priv /= priv_mode_m_c) else '0'; -- default (if not match): fault if not M-mode
|
||||
fail_ex(NUM_REGIONS) <= '1' when (ctrl_i.cpu_priv /= priv_mode_m_c) else '0'; -- default (if not match): fault if not M-mode
|
||||
fail_rw(NUM_REGIONS) <= '1' when (ctrl_i.lsu_priv /= priv_mode_m_c) else '0'; -- default (if not match): fault if not M-mode
|
||||
-- this is a *structural* description of a prioritization logic implemented as a multiplexer chain --
|
||||
fault_check_gen:
|
||||
for r in NUM_REGIONS-1 downto 0 generate -- start with lowest priority
|
||||
check.fail_ex(r) <= not region.perm_ex(r) when (region.i_match(r) = '1') else check.fail_ex(r+1);
|
||||
check.fail_rw(r) <= not region.perm_rw(r) when (region.d_match(r) = '1') else check.fail_rw(r+1);
|
||||
fail_ex(r) <= not region.perm_ex(r) when (region.i_match(r) = '1') else fail_ex(r+1);
|
||||
fail_rw(r) <= not region.perm_rw(r) when (region.d_match(r) = '1') else fail_rw(r+1);
|
||||
end generate;
|
||||
|
||||
|
||||
|
@ -374,8 +395,8 @@ begin
|
|||
fault_ex_o <= '0';
|
||||
fault_rw_o <= '0';
|
||||
elsif rising_edge(clk_i) then
|
||||
fault_ex_o <= (not ctrl_i.cpu_debug) and check.fail_ex(0); -- ignore PMP rules when in debug mode
|
||||
fault_rw_o <= (not ctrl_i.cpu_debug) and check.fail_rw(0);
|
||||
fault_ex_o <= (not ctrl_i.cpu_debug) and fail_ex(0); -- ignore PMP rules when in debug mode
|
||||
fault_rw_o <= (not ctrl_i.cpu_debug) and fail_rw(0);
|
||||
end if;
|
||||
end process access_check;
|
||||
|
||||
|
|
|
@ -53,7 +53,7 @@ package neorv32_package is
|
|||
|
||||
-- Architecture Constants -----------------------------------------------------------------
|
||||
-- -------------------------------------------------------------------------------------------
|
||||
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01090500"; -- hardware version
|
||||
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01090501"; -- hardware version
|
||||
constant archid_c : natural := 19; -- official RISC-V architecture ID
|
||||
constant XLEN : natural := 32; -- native data path width
|
||||
|
||||
|
@ -776,6 +776,8 @@ package neorv32_package is
|
|||
-- Physical Memory Protection (PMP) --
|
||||
PMP_NUM_REGIONS : natural range 0 to 16 := 0;
|
||||
PMP_MIN_GRANULARITY : natural := 4;
|
||||
PMP_TOR_MODE_EN : boolean := true;
|
||||
PMP_NAP_MODE_EN : boolean := true;
|
||||
-- Hardware Performance Monitors (HPM) --
|
||||
HPM_NUM_CNTS : natural range 0 to 13 := 0;
|
||||
HPM_CNT_WIDTH : natural range 0 to 64 := 40;
|
||||
|
|
|
@ -78,6 +78,8 @@ entity neorv32_top is
|
|||
-- Physical Memory Protection (PMP) --
|
||||
PMP_NUM_REGIONS : natural range 0 to 16 := 0; -- number of regions (0..16)
|
||||
PMP_MIN_GRANULARITY : natural := 4; -- minimal region granularity in bytes, has to be a power of 2, min 4 bytes
|
||||
PMP_TOR_MODE_EN : boolean := true; -- implement TOR mode
|
||||
PMP_NAP_MODE_EN : boolean := true; -- implement NAPOT/NA4 modes
|
||||
|
||||
-- Hardware Performance Monitors (HPM) --
|
||||
HPM_NUM_CNTS : natural range 0 to 13 := 0; -- number of implemented HPM counters (0..13)
|
||||
|
@ -538,6 +540,8 @@ begin
|
|||
-- Physical Memory Protection (PMP) --
|
||||
PMP_NUM_REGIONS => PMP_NUM_REGIONS,
|
||||
PMP_MIN_GRANULARITY => PMP_MIN_GRANULARITY,
|
||||
PMP_TOR_MODE_EN => PMP_TOR_MODE_EN,
|
||||
PMP_NAP_MODE_EN => PMP_NAP_MODE_EN,
|
||||
-- Hardware Performance Monitors (HPM) --
|
||||
HPM_NUM_CNTS => HPM_NUM_CNTS,
|
||||
HPM_CNT_WIDTH => HPM_CNT_WIDTH
|
||||
|
|
|
@ -245,6 +245,8 @@ begin
|
|||
-- Physical Memory Protection (PMP) --
|
||||
PMP_NUM_REGIONS => 5, -- number of regions (0..16)
|
||||
PMP_MIN_GRANULARITY => 4, -- minimal region granularity in bytes, has to be a power of 2, min 4 bytes
|
||||
PMP_TOR_MODE_EN => true, -- implement TOR mode
|
||||
PMP_NAP_MODE_EN => true, -- implement NAPOT/NA4 mode
|
||||
-- Hardware Performance Monitors (HPM) --
|
||||
HPM_NUM_CNTS => 12, -- number of implemented HPM counters (0..29)
|
||||
HPM_CNT_WIDTH => 40, -- total size of HPM counters (0..64)
|
||||
|
|
|
@ -188,6 +188,8 @@ begin
|
|||
-- Physical Memory Protection (PMP) --
|
||||
PMP_NUM_REGIONS => 5, -- number of regions (0..16)
|
||||
PMP_MIN_GRANULARITY => 4, -- minimal region granularity in bytes, has to be a power of 2, min 4 bytes
|
||||
PMP_TOR_MODE_EN => true, -- implement TOR mode
|
||||
PMP_NAP_MODE_EN => true, -- implement NAPOT/NA4 mode
|
||||
-- Hardware Performance Monitors (HPM) --
|
||||
HPM_NUM_CNTS => 12, -- number of implemented HPM counters (0..29)
|
||||
HPM_CNT_WIDTH => 40, -- total size of HPM counters (0..64)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue