mirror of
https://github.com/stnolting/neorv32.git
synced 2025-04-24 06:07:52 -04:00
fixed issue: using regs above x15 when E extensions is enabled will now correctly trigger an illegal instruction exception
This commit is contained in:
parent
92df5839a7
commit
e057b213ff
2 changed files with 71 additions and 41 deletions
|
@ -255,27 +255,6 @@ begin
|
|||
-- Instruction Fetch
|
||||
-- ****************************************************************************************************************************
|
||||
|
||||
-- Compressed Instructions Recoding -------------------------------------------------------
|
||||
-- -------------------------------------------------------------------------------------------
|
||||
neorv32_cpu_decompressor_inst_true:
|
||||
if (CPU_EXTENSION_RISCV_C = true) generate
|
||||
neorv32_cpu_decompressor_inst: neorv32_cpu_decompressor
|
||||
port map (
|
||||
-- instruction input --
|
||||
ci_instr16_i => fetch_engine.ci_input, -- compressed instruction input
|
||||
-- instruction output --
|
||||
ci_illegal_o => ci_illegal, -- is an illegal compressed instruction
|
||||
ci_instr32_o => ci_instr32 -- 32-bit decompressed instruction
|
||||
);
|
||||
end generate;
|
||||
|
||||
neorv32_cpu_decompressor_inst_false:
|
||||
if (CPU_EXTENSION_RISCV_C = false) generate
|
||||
ci_instr32 <= (others => '0');
|
||||
ci_illegal <= '0';
|
||||
end generate;
|
||||
|
||||
|
||||
-- Fetch Engine FSM Sync ------------------------------------------------------------------
|
||||
-- -------------------------------------------------------------------------------------------
|
||||
-- for registers that require a specific reset state --
|
||||
|
@ -404,6 +383,27 @@ begin
|
|||
end process fetch_engine_fsm_comb;
|
||||
|
||||
|
||||
-- Compressed Instructions Recoding -------------------------------------------------------
|
||||
-- -------------------------------------------------------------------------------------------
|
||||
neorv32_cpu_decompressor_inst_true:
|
||||
if (CPU_EXTENSION_RISCV_C = true) generate
|
||||
neorv32_cpu_decompressor_inst: neorv32_cpu_decompressor
|
||||
port map (
|
||||
-- instruction input --
|
||||
ci_instr16_i => fetch_engine.ci_input, -- compressed instruction input
|
||||
-- instruction output --
|
||||
ci_illegal_o => ci_illegal, -- is an illegal compressed instruction
|
||||
ci_instr32_o => ci_instr32 -- 32-bit decompressed instruction
|
||||
);
|
||||
end generate;
|
||||
|
||||
neorv32_cpu_decompressor_inst_false:
|
||||
if (CPU_EXTENSION_RISCV_C = false) generate
|
||||
ci_instr32 <= (others => '0');
|
||||
ci_illegal <= '0';
|
||||
end generate;
|
||||
|
||||
|
||||
-- ****************************************************************************************************************************
|
||||
-- Instruction Prefetch Buffer
|
||||
-- ****************************************************************************************************************************
|
||||
|
@ -527,7 +527,7 @@ begin
|
|||
execute_engine.last_pc <= CPU_BOOT_ADDR(data_width_c-1 downto 1) & '0';
|
||||
execute_engine.state <= SYS_WAIT;
|
||||
execute_engine.sleep <= '0';
|
||||
execute_engine.if_rst <= '1'; -- IF is reset after system reset
|
||||
execute_engine.if_rst <= '1'; -- instruction fetch is reset after system reset
|
||||
elsif rising_edge(clk_i) then
|
||||
execute_engine.pc <= execute_engine.pc_nxt(data_width_c-1 downto 1) & '0';
|
||||
if (execute_engine.state = EXECUTE) then
|
||||
|
@ -953,17 +953,17 @@ begin
|
|||
when x"343" => csr_acc_valid <= is_m_mode_v; -- mtval
|
||||
when x"344" => csr_acc_valid <= is_m_mode_v; -- mip
|
||||
--
|
||||
when x"3a0" => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 1)) and is_m_mode_v; -- pmpacfg0
|
||||
when x"3a1" => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 5)) and is_m_mode_v; -- pmpacfg1
|
||||
when x"3a0" => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 1)) and is_m_mode_v; -- pmpacfg0
|
||||
when x"3a1" => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 5)) and is_m_mode_v; -- pmpacfg1
|
||||
--
|
||||
when x"3b0" => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 1)) and is_m_mode_v; -- pmpaddr0
|
||||
when x"3b1" => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 2)) and is_m_mode_v; -- pmpaddr1
|
||||
when x"3b2" => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 3)) and is_m_mode_v; -- pmpaddr2
|
||||
when x"3b3" => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 4)) and is_m_mode_v; -- pmpaddr3
|
||||
when x"3b4" => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 5)) and is_m_mode_v; -- pmpaddr4
|
||||
when x"3b5" => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 6)) and is_m_mode_v; -- pmpaddr5
|
||||
when x"3b6" => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 7)) and is_m_mode_v; -- pmpaddr6
|
||||
when x"3b7" => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 8)) and is_m_mode_v; -- pmpaddr7
|
||||
when x"3b0" => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 1)) and is_m_mode_v; -- pmpaddr0
|
||||
when x"3b1" => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 2)) and is_m_mode_v; -- pmpaddr1
|
||||
when x"3b2" => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 3)) and is_m_mode_v; -- pmpaddr2
|
||||
when x"3b3" => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 4)) and is_m_mode_v; -- pmpaddr3
|
||||
when x"3b4" => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 5)) and is_m_mode_v; -- pmpaddr4
|
||||
when x"3b5" => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 6)) and is_m_mode_v; -- pmpaddr5
|
||||
when x"3b6" => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 7)) and is_m_mode_v; -- pmpaddr6
|
||||
when x"3b7" => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 8)) and is_m_mode_v; -- pmpaddr7
|
||||
--
|
||||
when x"c00" => csr_acc_valid <= bool_to_ulogic_f(CSR_COUNTERS_USE); -- cycle
|
||||
when x"c01" => csr_acc_valid <= bool_to_ulogic_f(CSR_COUNTERS_USE); -- time
|
||||
|
@ -984,7 +984,7 @@ begin
|
|||
--
|
||||
when x"fc0" => csr_acc_valid <= is_m_mode_v; -- mzext (custom CSR)
|
||||
--
|
||||
when others => csr_acc_valid <= '0'; -- undefined
|
||||
when others => csr_acc_valid <= '0'; -- undefined, invalid access
|
||||
end case;
|
||||
end process invalid_csr_access_check;
|
||||
|
||||
|
@ -1000,19 +1000,16 @@ begin
|
|||
illegal_instruction <= '0';
|
||||
illegal_register <= '0';
|
||||
|
||||
-- check if using reg >= 16 for E-CPUs --
|
||||
--if (CPU_EXTENSION_RISCV_E = true) then
|
||||
-- illegal_register <= ????? FIXME
|
||||
--else
|
||||
-- illegal_register <= '0';
|
||||
--end if;
|
||||
|
||||
-- check instructions --
|
||||
case execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c) is
|
||||
|
||||
-- OPCODE check sufficient: LUI, UIPC, JAL --
|
||||
when opcode_lui_c | opcode_auipc_c | opcode_jal_c =>
|
||||
illegal_instruction <= '0';
|
||||
-- illegal E-CPU register? --
|
||||
if (CPU_EXTENSION_RISCV_E = true) and (execute_engine.i_reg(instr_rd_msb_c) = '1') then
|
||||
illegal_register <= '1';
|
||||
end if;
|
||||
|
||||
when opcode_alui_c => -- check ALUI funct7
|
||||
if ((execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sll_c) and
|
||||
|
@ -1024,6 +1021,10 @@ begin
|
|||
else
|
||||
illegal_instruction <= '0';
|
||||
end if;
|
||||
-- illegal E-CPU register? --
|
||||
if (CPU_EXTENSION_RISCV_E = true) and ((execute_engine.i_reg(instr_rs1_msb_c) = '1') or (execute_engine.i_reg(instr_rd_msb_c) = '1')) then
|
||||
illegal_register <= '1';
|
||||
end if;
|
||||
|
||||
when opcode_load_c => -- check LOAD funct3
|
||||
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_lb_c) or
|
||||
|
@ -1035,6 +1036,10 @@ begin
|
|||
else
|
||||
illegal_instruction <= '1';
|
||||
end if;
|
||||
-- illegal E-CPU register? --
|
||||
if (CPU_EXTENSION_RISCV_E = true) and ((execute_engine.i_reg(instr_rs1_msb_c) = '1') or (execute_engine.i_reg(instr_rd_msb_c) = '1')) then
|
||||
illegal_register <= '1';
|
||||
end if;
|
||||
|
||||
when opcode_store_c => -- check STORE funct3
|
||||
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sb_c) or
|
||||
|
@ -1044,6 +1049,10 @@ begin
|
|||
else
|
||||
illegal_instruction <= '1';
|
||||
end if;
|
||||
-- illegal E-CPU register? --
|
||||
if (CPU_EXTENSION_RISCV_E = true) and ((execute_engine.i_reg(instr_rs2_msb_c) = '1') or (execute_engine.i_reg(instr_rs1_msb_c) = '1')) then
|
||||
illegal_register <= '1';
|
||||
end if;
|
||||
|
||||
when opcode_branch_c => -- check BRANCH funct3
|
||||
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_beq_c) or
|
||||
|
@ -1056,6 +1065,10 @@ begin
|
|||
else
|
||||
illegal_instruction <= '1';
|
||||
end if;
|
||||
-- illegal E-CPU register? --
|
||||
if (CPU_EXTENSION_RISCV_E = true) and ((execute_engine.i_reg(instr_rs2_msb_c) = '1') or (execute_engine.i_reg(instr_rs1_msb_c) = '1')) then
|
||||
illegal_register <= '1';
|
||||
end if;
|
||||
|
||||
when opcode_jalr_c => -- check JALR funct3
|
||||
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "000") then
|
||||
|
@ -1063,6 +1076,10 @@ begin
|
|||
else
|
||||
illegal_instruction <= '1';
|
||||
end if;
|
||||
-- illegal E-CPU register? --
|
||||
if (CPU_EXTENSION_RISCV_E = true) and ((execute_engine.i_reg(instr_rs1_msb_c) = '1') or (execute_engine.i_reg(instr_rd_msb_c) = '1')) then
|
||||
illegal_register <= '1';
|
||||
end if;
|
||||
|
||||
when opcode_alu_c => -- check ALU funct3 & funct7
|
||||
if (execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0000001") then -- MULDIV
|
||||
|
@ -1077,6 +1094,11 @@ begin
|
|||
else
|
||||
illegal_instruction <= '0';
|
||||
end if;
|
||||
-- illegal E-CPU register? --
|
||||
if (CPU_EXTENSION_RISCV_E = true) and
|
||||
((execute_engine.i_reg(instr_rs2_msb_c) = '1') or (execute_engine.i_reg(instr_rs1_msb_c) = '1') or (execute_engine.i_reg(instr_rd_msb_c) = '1')) then
|
||||
illegal_register <= '1';
|
||||
end if;
|
||||
|
||||
when opcode_fence_c => -- fence instructions --
|
||||
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_fencei_c) and (CPU_EXTENSION_RISCV_Zifencei = true) then -- FENCE.I
|
||||
|
@ -1101,6 +1123,14 @@ begin
|
|||
else
|
||||
illegal_instruction <= '1';
|
||||
end if;
|
||||
-- illegal E-CPU register? --
|
||||
if (CPU_EXTENSION_RISCV_E = true) then
|
||||
if (execute_engine.i_reg(instr_funct3_msb_c) = '0') then -- reg-reg CSR
|
||||
illegal_register <= execute_engine.i_reg(instr_rs1_msb_c) or execute_engine.i_reg(instr_rd_msb_c);
|
||||
else -- reg-imm CSR
|
||||
illegal_register <= execute_engine.i_reg(instr_rd_msb_c);
|
||||
end if;
|
||||
end if;
|
||||
|
||||
-- ecall, ebreak, mret, wfi --
|
||||
elsif (execute_engine.i_reg(instr_rd_msb_c downto instr_rd_lsb_c) = "00000") and
|
||||
|
|
|
@ -41,7 +41,7 @@ package neorv32_package is
|
|||
-- Architecture Constants -----------------------------------------------------------------
|
||||
-- -------------------------------------------------------------------------------------------
|
||||
constant data_width_c : natural := 32; -- data width - FIXED!
|
||||
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01040000"; -- no touchy!
|
||||
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01040001"; -- no touchy!
|
||||
constant pmp_max_r_c : natural := 8; -- max PMP regions
|
||||
constant ipb_entries_c : natural := 2; -- entries in instruction prefetch buffer, must be a power of 2, default=2
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue