Line 923... |
Line 923... |
|
|
-- Illegal CSR Access Check ---------------------------------------------------------------
|
-- Illegal CSR Access Check ---------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
invalid_csr_access_check: process(execute_engine.i_reg, csr.privilege)
|
invalid_csr_access_check: process(execute_engine.i_reg, csr.privilege)
|
variable is_m_mode_v : std_ulogic;
|
variable is_m_mode_v : std_ulogic;
|
|
variable csr_wacc_v : std_ulogic; -- to check access to read-only CSRs
|
|
-- variable csr_racc_v : std_ulogic; -- to check access to write-only CSRs
|
begin
|
begin
|
-- are we in machine mode? --
|
-- are we in machine mode? --
|
if (csr.privilege = priv_mode_m_c) then
|
if (csr.privilege = priv_mode_m_c) then
|
is_m_mode_v := '1';
|
is_m_mode_v := '1';
|
else
|
else
|
is_m_mode_v := '0';
|
is_m_mode_v := '0';
|
end if;
|
end if;
|
|
|
|
-- is this CSR instruction really going to write/read to/from a CSR? --
|
|
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrw_c) or
|
|
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrwi_c) then
|
|
csr_wacc_v := '1'; -- always write CSR
|
|
-- csr_racc_v := or_all_f(execute_engine.i_reg(instr_rd_msb_c downto instr_rd_lsb_c)); -- read allowed if rd != 0
|
|
else
|
|
csr_wacc_v := or_all_f(execute_engine.i_reg(instr_rs1_msb_c downto instr_rs1_lsb_c)); -- write allowed if rs1/uimm5 != 0
|
|
-- csr_racc_v := '1'; -- always read CSR
|
|
end if;
|
|
|
-- check CSR access --
|
-- check CSR access --
|
case execute_engine.i_reg(instr_csr_id_msb_c downto instr_csr_id_lsb_c) is
|
case execute_engine.i_reg(instr_csr_id_msb_c downto instr_csr_id_lsb_c) is
|
when csr_mstatus_c => csr_acc_valid <= is_m_mode_v;
|
when csr_mstatus_c => csr_acc_valid <= is_m_mode_v; -- M-mode only
|
when csr_misa_c => csr_acc_valid <= is_m_mode_v;
|
when csr_misa_c => csr_acc_valid <= is_m_mode_v;-- and (not csr_wacc_v); -- M-mode only, MISA is read-only for the NEORV32 but we don't cause an exception here for compatibility
|
when csr_mie_c => csr_acc_valid <= is_m_mode_v;
|
when csr_mie_c => csr_acc_valid <= is_m_mode_v; -- M-mode only
|
when csr_mtvec_c => csr_acc_valid <= is_m_mode_v;
|
when csr_mtvec_c => csr_acc_valid <= is_m_mode_v; -- M-mode only
|
when csr_mscratch_c => csr_acc_valid <= is_m_mode_v;
|
when csr_mscratch_c => csr_acc_valid <= is_m_mode_v; -- M-mode only
|
when csr_mepc_c => csr_acc_valid <= is_m_mode_v;
|
when csr_mepc_c => csr_acc_valid <= is_m_mode_v; -- M-mode only
|
when csr_mcause_c => csr_acc_valid <= is_m_mode_v;
|
when csr_mcause_c => csr_acc_valid <= is_m_mode_v; -- M-mode only
|
when csr_mtval_c => csr_acc_valid <= is_m_mode_v;
|
when csr_mtval_c => csr_acc_valid <= is_m_mode_v; -- M-mode only
|
when csr_mip_c => csr_acc_valid <= is_m_mode_v;
|
when csr_mip_c => csr_acc_valid <= is_m_mode_v; -- M-mode only
|
--
|
--
|
when csr_pmpcfg0_c => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 1)) and is_m_mode_v;
|
when csr_pmpcfg0_c => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 1)) and is_m_mode_v; -- M-mode only
|
when csr_pmpcfg1_c => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 5)) and is_m_mode_v;
|
when csr_pmpcfg1_c => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 5)) and is_m_mode_v; -- M-mode only
|
--
|
--
|
when csr_pmpaddr0_c => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 1)) and is_m_mode_v;
|
when csr_pmpaddr0_c => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 1)) and is_m_mode_v; -- M-mode only
|
when csr_pmpaddr1_c => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 2)) and is_m_mode_v;
|
when csr_pmpaddr1_c => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 2)) and is_m_mode_v; -- M-mode only
|
when csr_pmpaddr2_c => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 3)) and is_m_mode_v;
|
when csr_pmpaddr2_c => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 3)) and is_m_mode_v; -- M-mode only
|
when csr_pmpaddr3_c => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 4)) and is_m_mode_v;
|
when csr_pmpaddr3_c => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 4)) and is_m_mode_v; -- M-mode only
|
when csr_pmpaddr4_c => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 5)) and is_m_mode_v;
|
when csr_pmpaddr4_c => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 5)) and is_m_mode_v; -- M-mode only
|
when csr_pmpaddr5_c => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 6)) and is_m_mode_v;
|
when csr_pmpaddr5_c => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 6)) and is_m_mode_v; -- M-mode only
|
when csr_pmpaddr6_c => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 7)) and is_m_mode_v;
|
when csr_pmpaddr6_c => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 7)) and is_m_mode_v; -- M-mode only
|
when csr_pmpaddr7_c => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 8)) and is_m_mode_v;
|
when csr_pmpaddr7_c => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 8)) and is_m_mode_v; -- M-mode only
|
--
|
--
|
when csr_mcycle_c => csr_acc_valid <= is_m_mode_v;
|
when csr_mcycle_c => csr_acc_valid <= is_m_mode_v; -- M-mode only
|
when csr_minstret_c => csr_acc_valid <= is_m_mode_v;
|
when csr_minstret_c => csr_acc_valid <= is_m_mode_v; -- M-mode only
|
--
|
--
|
when csr_mcycleh_c => csr_acc_valid <= is_m_mode_v;
|
when csr_mcycleh_c => csr_acc_valid <= is_m_mode_v; -- M-mode only
|
when csr_minstreth_c => csr_acc_valid <= is_m_mode_v;
|
when csr_minstreth_c => csr_acc_valid <= is_m_mode_v; -- M-mode only
|
--
|
--
|
when csr_cycle_c => csr_acc_valid <= '1';
|
when csr_cycle_c => csr_acc_valid <= (not csr_wacc_v); -- all modes, read-only
|
when csr_time_c => csr_acc_valid <= '1';
|
when csr_time_c => csr_acc_valid <= (not csr_wacc_v); -- all modes, read-only
|
when csr_instret_c => csr_acc_valid <= '1';
|
when csr_instret_c => csr_acc_valid <= (not csr_wacc_v); -- all modes, read-only
|
--
|
--
|
when csr_cycleh_c => csr_acc_valid <= '1';
|
when csr_cycleh_c => csr_acc_valid <= (not csr_wacc_v); -- all modes, read-only
|
when csr_timeh_c => csr_acc_valid <= '1';
|
when csr_timeh_c => csr_acc_valid <= (not csr_wacc_v); -- all modes, read-only
|
when csr_instreth_c => csr_acc_valid <= '1';
|
when csr_instreth_c => csr_acc_valid <= (not csr_wacc_v); -- all modes, read-only
|
--
|
--
|
when csr_mvendorid_c => csr_acc_valid <= is_m_mode_v;
|
when csr_mvendorid_c => csr_acc_valid <= is_m_mode_v and (not csr_wacc_v); -- M-mode only, read-only
|
when csr_marchid_c => csr_acc_valid <= is_m_mode_v;
|
when csr_marchid_c => csr_acc_valid <= is_m_mode_v and (not csr_wacc_v); -- M-mode only, read-only
|
when csr_mimpid_c => csr_acc_valid <= is_m_mode_v;
|
when csr_mimpid_c => csr_acc_valid <= is_m_mode_v and (not csr_wacc_v); -- M-mode only, read-only
|
when csr_mhartid_c => csr_acc_valid <= is_m_mode_v;
|
when csr_mhartid_c => csr_acc_valid <= is_m_mode_v and (not csr_wacc_v); -- M-mode only, read-only
|
--
|
--
|
when csr_mzext_c => csr_acc_valid <= is_m_mode_v;
|
when csr_mzext_c => csr_acc_valid <= is_m_mode_v and (not csr_wacc_v); -- M-mode only, read-only
|
--
|
--
|
when others => csr_acc_valid <= '0'; -- undefined, invalid access
|
when others => csr_acc_valid <= '0'; -- undefined, invalid access
|
end case;
|
end case;
|
end process invalid_csr_access_check;
|
end process invalid_csr_access_check;
|
|
|
Line 1470... |
Line 1482... |
-- machine trap handling --
|
-- machine trap handling --
|
if (execute_engine.i_reg(27 downto 24) = csr_mepc_c(7 downto 4)) then
|
if (execute_engine.i_reg(27 downto 24) = csr_mepc_c(7 downto 4)) then
|
if (execute_engine.i_reg(23 downto 20) = csr_mepc_c(3 downto 0)) then -- R/W: mepc - machine exception program counter
|
if (execute_engine.i_reg(23 downto 20) = csr_mepc_c(3 downto 0)) then -- R/W: mepc - machine exception program counter
|
csr.mepc <= csr.wdata(data_width_c-1 downto 1) & '0';
|
csr.mepc <= csr.wdata(data_width_c-1 downto 1) & '0';
|
end if;
|
end if;
|
|
if (execute_engine.i_reg(23 downto 20) = csr_mcause_c(3 downto 0)) then -- R/W: mcause - machine trap cause
|
|
csr.mcause <= (others => '0');
|
|
csr.mcause(csr.mcause'left) <= csr.wdata(31); -- 1: interrupt, 0: exception
|
|
csr.mcause(4 downto 0) <= csr.wdata(4 downto 0); -- identifier
|
|
end if;
|
if (execute_engine.i_reg(23 downto 20) = csr_mtval_c(3 downto 0)) then -- R/W: mtval - machine bad address or instruction
|
if (execute_engine.i_reg(23 downto 20) = csr_mtval_c(3 downto 0)) then -- R/W: mtval - machine bad address or instruction
|
csr.mtval <= csr.wdata;
|
csr.mtval <= csr.wdata;
|
end if;
|
end if;
|
end if;
|
end if;
|
|
|
Line 1504... |
Line 1521... |
end if;
|
end if;
|
end if;
|
end if;
|
|
|
-- mstatus: context switch --
|
-- mstatus: context switch --
|
if (trap_ctrl.env_start_ack = '1') then -- ENTER: trap handler starting?
|
if (trap_ctrl.env_start_ack = '1') then -- ENTER: trap handler starting?
|
|
-- trap ID code --
|
|
csr.mcause <= (others => '0');
|
|
csr.mcause(csr.mcause'left) <= trap_ctrl.cause(trap_ctrl.cause'left); -- 1: interrupt, 0: exception
|
|
csr.mcause(4 downto 0) <= trap_ctrl.cause(4 downto 0); -- identifier
|
|
--
|
csr.mstatus_mie <= '0'; -- disable interrupts
|
csr.mstatus_mie <= '0'; -- disable interrupts
|
csr.mstatus_mpie <= csr.mstatus_mie; -- buffer previous mie state
|
csr.mstatus_mpie <= csr.mstatus_mie; -- buffer previous mie state
|
if (CPU_EXTENSION_RISCV_U = true) then -- implement user mode
|
if (CPU_EXTENSION_RISCV_U = true) then -- implement user mode
|
csr.privilege <= priv_mode_m_c; -- execute trap in machine mode
|
csr.privilege <= priv_mode_m_c; -- execute trap in machine mode
|
csr.mstatus_mpp <= csr.privilege; -- buffer previous privilege mode
|
csr.mstatus_mpp <= csr.privilege; -- buffer previous privilege mode
|
Line 1525... |
Line 1547... |
csr.privilege <= priv_mode_m_c;
|
csr.privilege <= priv_mode_m_c;
|
csr.mstatus_mpp <= priv_mode_m_c;
|
csr.mstatus_mpp <= priv_mode_m_c;
|
end if;
|
end if;
|
end if;
|
end if;
|
|
|
-- --------------------------------------------------------------------------------
|
|
-- CSRs that can be written by hardware only
|
|
-- --------------------------------------------------------------------------------
|
|
|
|
-- mcause
|
|
if (trap_ctrl.env_start_ack = '1') then -- trap handler starting?
|
|
-- trap ID code --
|
|
csr.mcause <= (others => '0');
|
|
csr.mcause(csr.mcause'left) <= trap_ctrl.cause(trap_ctrl.cause'left); -- 1: interrupt, 0: exception
|
|
csr.mcause(4 downto 0) <= trap_ctrl.cause(4 downto 0); -- identifier
|
|
end if;
|
|
|
|
end if;
|
end if;
|
end process csr_write_access;
|
end process csr_write_access;
|
|
|
|
|
-- Control and Status Registers Read Access -----------------------------------------------
|
-- Control and Status Registers Read Access -----------------------------------------------
|