Line 73... |
Line 73... |
ma_store_o : out std_ulogic; -- misaligned store data address
|
ma_store_o : out std_ulogic; -- misaligned store data address
|
be_load_o : out std_ulogic; -- bus error on load data access
|
be_load_o : out std_ulogic; -- bus error on load data access
|
be_store_o : out std_ulogic; -- bus error on store data access
|
be_store_o : out std_ulogic; -- bus error on store data access
|
-- physical memory protection --
|
-- physical memory protection --
|
pmp_addr_i : in pmp_addr_if_t; -- addresses
|
pmp_addr_i : in pmp_addr_if_t; -- addresses
|
pmp_maddr_o : out pmp_addr_if_t; -- masked addresses
|
|
pmp_ctrl_i : in pmp_ctrl_if_t; -- configs
|
pmp_ctrl_i : in pmp_ctrl_if_t; -- configs
|
priv_mode_i : in std_ulogic_vector(1 downto 0); -- current CPU privilege level
|
priv_mode_i : in std_ulogic_vector(1 downto 0); -- current CPU privilege level
|
-- instruction bus --
|
-- instruction bus --
|
i_bus_addr_o : out std_ulogic_vector(data_width_c-1 downto 0); -- bus access address
|
i_bus_addr_o : out std_ulogic_vector(data_width_c-1 downto 0); -- bus access address
|
i_bus_rdata_i : in std_ulogic_vector(data_width_c-1 downto 0); -- bus read data
|
i_bus_rdata_i : in std_ulogic_vector(data_width_c-1 downto 0); -- bus read data
|
Line 142... |
Line 141... |
|
|
-- physical memory protection --
|
-- physical memory protection --
|
type pmp_addr34_t is array (0 to PMP_NUM_REGIONS-1) of std_ulogic_vector(data_width_c+1 downto 0);
|
type pmp_addr34_t is array (0 to PMP_NUM_REGIONS-1) of std_ulogic_vector(data_width_c+1 downto 0);
|
type pmp_addr_t is array (0 to PMP_NUM_REGIONS-1) of std_ulogic_vector(data_width_c-1 downto 0);
|
type pmp_addr_t is array (0 to PMP_NUM_REGIONS-1) of std_ulogic_vector(data_width_c-1 downto 0);
|
type pmp_t is record
|
type pmp_t is record
|
addr_mask : pmp_addr34_t; -- 34-bit
|
addr_mask : pmp_addr34_t; -- 34-bit physical address
|
|
region_base : pmp_addr_t; -- masked region base address for comparator
|
|
region_i_addr : pmp_addr_t; -- masked instruction access base address for comparator
|
|
region_d_addr : pmp_addr_t; -- masked data access base address for comparator
|
i_match : std_ulogic_vector(PMP_NUM_REGIONS-1 downto 0); -- region match for instruction interface
|
i_match : std_ulogic_vector(PMP_NUM_REGIONS-1 downto 0); -- region match for instruction interface
|
d_match : std_ulogic_vector(PMP_NUM_REGIONS-1 downto 0); -- region match for data interface
|
d_match : std_ulogic_vector(PMP_NUM_REGIONS-1 downto 0); -- region match for data interface
|
if_fault : std_ulogic_vector(PMP_NUM_REGIONS-1 downto 0); -- region access fault for fetch operation
|
if_fault : std_ulogic_vector(PMP_NUM_REGIONS-1 downto 0); -- region access fault for fetch operation
|
ld_fault : std_ulogic_vector(PMP_NUM_REGIONS-1 downto 0); -- region access fault for load operation
|
ld_fault : std_ulogic_vector(PMP_NUM_REGIONS-1 downto 0); -- region access fault for load operation
|
st_fault : std_ulogic_vector(PMP_NUM_REGIONS-1 downto 0); -- region access fault for store operation
|
st_fault : std_ulogic_vector(PMP_NUM_REGIONS-1 downto 0); -- region access fault for store operation
|
Line 409... |
Line 411... |
|
|
|
|
-- Physical Memory Protection (PMP) -------------------------------------------------------
|
-- Physical Memory Protection (PMP) -------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- compute address masks --
|
-- compute address masks --
|
pmp_masks: process(pmp_addr_i, pmp, pmp_ctrl_i)
|
pmp_masks: process(pmp_addr_i)
|
begin
|
begin
|
for r in 0 to PMP_NUM_REGIONS-1 loop -- iterate over all regions
|
for r in 0 to PMP_NUM_REGIONS-1 loop -- iterate over all regions
|
pmp.addr_mask(r) <= (others => '0'); -- default
|
pmp.addr_mask(r) <= (others => '0'); -- default
|
for i in PMP_GRANULARITY+2 to 33 loop
|
for i in PMP_GRANULARITY+1 to 33 loop
|
if (i = PMP_GRANULARITY+2) then
|
if (i = PMP_GRANULARITY+1) then
|
if (pmp_ctrl_i(r)(pmp_cfg_ah_c downto pmp_cfg_al_c) = pmp_napot_mode_c) then
|
|
pmp.addr_mask(r)(i) <= '0';
|
pmp.addr_mask(r)(i) <= '0';
|
else -- OFF or unsupported mode
|
else -- current bit = not AND(all previous bits)
|
pmp.addr_mask(r)(i) <= '1'; -- required for SW to check min granularity when entry is disabled
|
pmp.addr_mask(r)(i) <= not (and_all_f(pmp_addr_i(r)(i-1 downto PMP_GRANULARITY)));
|
end if;
|
|
else
|
|
if (pmp_ctrl_i(r)(pmp_cfg_ah_c downto pmp_cfg_al_c) = pmp_napot_mode_c) then
|
|
-- current bit = not AND(all previous bits)
|
|
pmp.addr_mask(r)(i) <= not and_all_f(pmp_addr_i(r)(i-1 downto PMP_GRANULARITY+2));
|
|
else -- OFF or unsupported mode
|
|
pmp.addr_mask(r)(i) <= '1'; -- required for SW to check min granularity when entry is disabled
|
|
end if;
|
|
end if;
|
end if;
|
end loop; -- i
|
end loop; -- i
|
end loop; -- r
|
end loop; -- r
|
end process pmp_masks;
|
end process pmp_masks;
|
|
|
|
|
-- masked pmpaddr output for CSR read-back --
|
-- compute operands for comparator --
|
pmp_masked_output: process(pmp_addr_i, pmp)
|
pmp_prepare_check:
|
begin
|
for r in 0 to PMP_NUM_REGIONS-1 generate -- iterate over all regions
|
pmp_maddr_o <= (others => (others => '0'));
|
-- ignore lowest 3 bits of access addresses -> minimal region size = 8 bytes
|
for r in 0 to PMP_NUM_REGIONS-1 loop -- iterate over all regions
|
pmp.region_i_addr(r) <= (fetch_pc_i(31 downto 3) & "000") and pmp.addr_mask(r)(33 downto 2);
|
pmp_maddr_o(r) <= pmp_addr_i(r) and pmp.addr_mask(r);
|
pmp.region_d_addr(r) <= (mar(31 downto 3) & "000") and pmp.addr_mask(r)(33 downto 2);
|
end loop; -- r
|
pmp.region_base(r) <= pmp_addr_i(r)(33 downto 2) and pmp.addr_mask(r)(33 downto 2);
|
end process pmp_masked_output;
|
end generate; -- r
|
|
|
|
|
-- check for access address match --
|
-- check for access address match --
|
pmp_addr_check: process (pmp, fetch_pc_i, mar, pmp_addr_i)
|
pmp_addr_check: process (pmp)
|
variable i_cmp_v : std_ulogic_vector(31 downto 0);
|
|
variable d_cmp_v : std_ulogic_vector(31 downto 0);
|
|
variable b_cmp_v : std_ulogic_vector(31 downto 0);
|
|
begin
|
begin
|
for r in 0 to PMP_NUM_REGIONS-1 loop -- iterate over all regions
|
for r in 0 to PMP_NUM_REGIONS-1 loop -- iterate over all regions
|
b_cmp_v := pmp_addr_i(r)(33 downto 2) and pmp.addr_mask(r)(33 downto 2);
|
|
-- instruction interface --
|
-- instruction interface --
|
i_cmp_v := fetch_pc_i and pmp.addr_mask(r)(33 downto 2);
|
|
if (i_cmp_v(31 downto PMP_GRANULARITY+2) = b_cmp_v(31 downto PMP_GRANULARITY+2)) then
|
|
pmp.i_match(r) <= '1';
|
|
else
|
|
pmp.i_match(r) <= '0';
|
pmp.i_match(r) <= '0';
|
|
if (pmp.region_i_addr(r)(31 downto PMP_GRANULARITY+2) = pmp.region_base(r)(31 downto PMP_GRANULARITY+2)) then
|
|
pmp.i_match(r) <= '1';
|
end if;
|
end if;
|
-- data interface --
|
-- data interface --
|
d_cmp_v := mar and pmp.addr_mask(r)(33 downto 2);
|
|
if (d_cmp_v(31 downto PMP_GRANULARITY+2) = b_cmp_v(31 downto PMP_GRANULARITY+2)) then
|
|
pmp.d_match(r) <= '1';
|
|
else
|
|
pmp.d_match(r) <= '0';
|
pmp.d_match(r) <= '0';
|
|
if (pmp.region_d_addr(r)(31 downto PMP_GRANULARITY+2) = pmp.region_base(r)(31 downto PMP_GRANULARITY+2)) then
|
|
pmp.d_match(r) <= '1';
|
end if;
|
end if;
|
end loop; -- r
|
end loop; -- r
|
end process pmp_addr_check;
|
end process pmp_addr_check;
|
|
|
|
|