fixed issue: using regs above x15 when E extensions is enabled will now correctly trigger an illegal instruction exception

This commit is contained in:
stnolting 2020-09-01 22:03:30 +02:00
parent 92df5839a7
commit e057b213ff
2 changed files with 71 additions and 41 deletions

View file

@ -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

View file

@ -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