Skip to content

Commit

Permalink
🐛 [FPU] fix bug in FPU trap handling (#609)
Browse files Browse the repository at this point in the history
  • Loading branch information
stnolting committed May 4, 2023
2 parents ed073c8 + c2ec072 commit 77fedae
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 35 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ mimpid = 0x01080200 => Version 01.08.02.00 => v1.8.2

| Date (*dd.mm.yyyy*) | Version | Comment |
|:-------------------:|:-------:|:--------|
| 03.05.2023 | 1.8.4.7 | :bug: fix bug in FPU (terminate FPU sub-module operations if an exception has been raised); [#609](https://github.com/stnolting/neorv32/pull/609) |
| 02.05.2023 | 1.8.4.6 | make SDI FIFO access entirely synchronous; upgrade processor memory modules; update test setup wrappers; [#608]((https://github.com/stnolting/neorv32/pull/608) |
| 30.04.2023 | 1.8.4.5 | rework processor-internal bus system; [#607](https://github.com/stnolting/neorv32/pull/607) |
| 27.04.2023 | 1.8.4.4 | minor hardware edits and switching activity optimizations of CPU bus unit; [#605](https://github.com/stnolting/neorv32/pull/605) |
Expand Down
44 changes: 22 additions & 22 deletions rtl/core/neorv32_cpu_control.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ architecture neorv32_cpu_control_rtl of neorv32_cpu_control is
epc : std_ulogic_vector(XLEN-1 downto 0); -- exception program counter
--
env_start : std_ulogic; -- start trap handler env
env_start_ack : std_ulogic; -- start of trap handler acknowledged
env_ack : std_ulogic; -- start of trap handler acknowledged
env_end : std_ulogic; -- end trap handler env
wakeup : std_ulogic; -- wakeup from sleep due to an enabled pending IRQ
--
Expand Down Expand Up @@ -830,7 +830,7 @@ begin
fetch_engine.reset <= '0';

-- trap environment control defaults --
trap_ctrl.env_start_ack <= '0';
trap_ctrl.env_ack <= '0';
trap_ctrl.env_end <= '0';
trap_ctrl.instr_be <= '0';
trap_ctrl.instr_ma <= '0';
Expand Down Expand Up @@ -876,7 +876,7 @@ begin
when TRAP_ENTER => -- Start trap environment and get trap vector
-- ------------------------------------------------------------
if (trap_ctrl.env_start = '1') then
trap_ctrl.env_start_ack <= '1';
trap_ctrl.env_ack <= '1';
execute_engine.state_nxt <= TRAP_EXECUTE;
end if;

Expand Down Expand Up @@ -1164,7 +1164,7 @@ begin
-- cpu status --
ctrl_o.cpu_priv <= csr.privilege_eff;
ctrl_o.cpu_sleep <= '1' when (execute_engine.state = CPU_SLEEP) else '0';
ctrl_o.cpu_trap <= trap_ctrl.env_start_ack;
ctrl_o.cpu_trap <= trap_ctrl.env_ack;
ctrl_o.cpu_debug <= debug_ctrl.running;


Expand Down Expand Up @@ -1441,33 +1441,33 @@ begin
-- ----------------------------------------------------------------------

-- misaligned load/store/instruction address --
trap_ctrl.exc_buf(exc_lalign_c) <= (trap_ctrl.exc_buf(exc_lalign_c) or ma_load_i) and (not trap_ctrl.env_start_ack);
trap_ctrl.exc_buf(exc_salign_c) <= (trap_ctrl.exc_buf(exc_salign_c) or ma_store_i) and (not trap_ctrl.env_start_ack);
trap_ctrl.exc_buf(exc_ialign_c) <= (trap_ctrl.exc_buf(exc_ialign_c) or trap_ctrl.instr_ma) and (not trap_ctrl.env_start_ack);
trap_ctrl.exc_buf(exc_lalign_c) <= (trap_ctrl.exc_buf(exc_lalign_c) or ma_load_i) and (not trap_ctrl.env_ack);
trap_ctrl.exc_buf(exc_salign_c) <= (trap_ctrl.exc_buf(exc_salign_c) or ma_store_i) and (not trap_ctrl.env_ack);
trap_ctrl.exc_buf(exc_ialign_c) <= (trap_ctrl.exc_buf(exc_ialign_c) or trap_ctrl.instr_ma) and (not trap_ctrl.env_ack);

-- load/store/instruction bus access fault --
trap_ctrl.exc_buf(exc_laccess_c) <= (trap_ctrl.exc_buf(exc_laccess_c) or be_load_i) and (not trap_ctrl.env_start_ack);
trap_ctrl.exc_buf(exc_saccess_c) <= (trap_ctrl.exc_buf(exc_saccess_c) or be_store_i) and (not trap_ctrl.env_start_ack);
trap_ctrl.exc_buf(exc_iaccess_c) <= (trap_ctrl.exc_buf(exc_iaccess_c) or trap_ctrl.instr_be) and (not trap_ctrl.env_start_ack);
trap_ctrl.exc_buf(exc_laccess_c) <= (trap_ctrl.exc_buf(exc_laccess_c) or be_load_i) and (not trap_ctrl.env_ack);
trap_ctrl.exc_buf(exc_saccess_c) <= (trap_ctrl.exc_buf(exc_saccess_c) or be_store_i) and (not trap_ctrl.env_ack);
trap_ctrl.exc_buf(exc_iaccess_c) <= (trap_ctrl.exc_buf(exc_iaccess_c) or trap_ctrl.instr_be) and (not trap_ctrl.env_ack);

-- illegal instruction & environment call --
trap_ctrl.exc_buf(exc_ecall_c) <= (trap_ctrl.exc_buf(exc_ecall_c) or trap_ctrl.env_call) and (not trap_ctrl.env_start_ack);
trap_ctrl.exc_buf(exc_iillegal_c) <= (trap_ctrl.exc_buf(exc_iillegal_c) or trap_ctrl.instr_il) and (not trap_ctrl.env_start_ack);
trap_ctrl.exc_buf(exc_ecall_c) <= (trap_ctrl.exc_buf(exc_ecall_c) or trap_ctrl.env_call) and (not trap_ctrl.env_ack);
trap_ctrl.exc_buf(exc_iillegal_c) <= (trap_ctrl.exc_buf(exc_iillegal_c) or trap_ctrl.instr_il) and (not trap_ctrl.env_ack);

-- break point --
if (CPU_EXTENSION_RISCV_Sdext = true) then
trap_ctrl.exc_buf(exc_ebreak_c) <= (not trap_ctrl.env_start_ack) and (trap_ctrl.exc_buf(exc_ebreak_c) or
trap_ctrl.exc_buf(exc_ebreak_c) <= (not trap_ctrl.env_ack) and (trap_ctrl.exc_buf(exc_ebreak_c) or
(hw_trigger_fire and (not csr.tdata1_action)) or -- trigger module fires and enter-debug is disabled
(trap_ctrl.break_point and ( csr.privilege) and (not csr.dcsr_ebreakm) and (not debug_ctrl.running)) or -- enter M-mode handler on ebreak in M-mode
(trap_ctrl.break_point and (not csr.privilege) and (not csr.dcsr_ebreaku) and (not debug_ctrl.running))); -- enter M-mode handler on ebreak in U-mode
else
trap_ctrl.exc_buf(exc_ebreak_c) <= (trap_ctrl.exc_buf(exc_ebreak_c) or trap_ctrl.break_point or hw_trigger_fire) and (not trap_ctrl.env_start_ack);
trap_ctrl.exc_buf(exc_ebreak_c) <= (trap_ctrl.exc_buf(exc_ebreak_c) or trap_ctrl.break_point or hw_trigger_fire) and (not trap_ctrl.env_ack);
end if;

-- debug-mode entry --
if (CPU_EXTENSION_RISCV_Sdext = true) then
trap_ctrl.exc_buf(exc_db_break_c) <= (trap_ctrl.exc_buf(exc_db_break_c) or debug_ctrl.trig_break) and (not trap_ctrl.env_start_ack);
trap_ctrl.exc_buf(exc_db_hw_c) <= (trap_ctrl.exc_buf(exc_db_hw_c) or debug_ctrl.trig_hw) and (not trap_ctrl.env_start_ack);
trap_ctrl.exc_buf(exc_db_break_c) <= (trap_ctrl.exc_buf(exc_db_break_c) or debug_ctrl.trig_break) and (not trap_ctrl.env_ack);
trap_ctrl.exc_buf(exc_db_hw_c) <= (trap_ctrl.exc_buf(exc_db_hw_c) or debug_ctrl.trig_hw) and (not trap_ctrl.env_ack);
else
trap_ctrl.exc_buf(exc_db_break_c) <= '0';
trap_ctrl.exc_buf(exc_db_hw_c) <= '0';
Expand Down Expand Up @@ -1531,14 +1531,14 @@ begin
trap_ctrl.wakeup <= '0';
trap_ctrl.env_start <= '0';
elsif rising_edge(clk_i) then
trap_ctrl.wakeup <= or_reduce_f(trap_ctrl.irq_buf); -- wakeup from sleep on any pending IRQ (including debug IRQs)
trap_ctrl.wakeup <= or_reduce_f(trap_ctrl.irq_buf); -- wakeup from sleep on any pending IRQ (including debug IRQs)
if (trap_ctrl.env_start = '0') then -- no started trap handler yet
-- trigger IRQ only in EXECUTE state to continue execution even on permanent IRQ
if (trap_ctrl.exc_fire = '1') or ((trap_ctrl.irq_fire = '1') and (execute_engine.state = EXECUTE)) then
trap_ctrl.env_start <= '1'; -- now execute engine can start trap handling
end if;
else -- trap environment ready to start
if (trap_ctrl.env_start_ack = '1') then -- start of trap handler acknowledged by execute engine
if (trap_ctrl.env_ack = '1') then -- start of trap handler acknowledged by execute engine
trap_ctrl.env_start <= '0';
end if;
end if;
Expand Down Expand Up @@ -1816,7 +1816,7 @@ begin
-- --------------------------------------------------------------------
-- TRAP ENTER
-- --------------------------------------------------------------------
if (trap_ctrl.env_start_ack = '1') then -- trap handler starting?
if (trap_ctrl.env_ack = '1') then -- trap handler starting?

-- NORMAL trap entry: write mcause, mepc and mtval - no update when in debug-mode! --
-- --------------------------------------------------------------------
Expand Down Expand Up @@ -2458,8 +2458,8 @@ begin
cnt_event(hpmcnt_event_tbranch_c) <= '1' when (execute_engine.state = BRANCHED) and (execute_engine.state_prev = BRANCH) and
(execute_engine.ir(instr_opcode_lsb_c+2) = '0') else '0'; -- taken branch (conditional)

cnt_event(hpmcnt_event_trap_c) <= '1' when (trap_ctrl.env_start_ack = '1') else '0'; -- entered trap
cnt_event(hpmcnt_event_illegal_c) <= '1' when (trap_ctrl.env_start_ack = '1') and (trap_ctrl.cause = trap_iil_c) else '0'; -- illegal operation
cnt_event(hpmcnt_event_trap_c) <= '1' when (trap_ctrl.env_ack = '1') else '0'; -- entered trap
cnt_event(hpmcnt_event_illegal_c) <= '1' when (trap_ctrl.env_ack = '1') and (trap_ctrl.cause = trap_iil_c) else '0'; -- illegal operation


-- ****************************************************************************************************************************
Expand All @@ -2479,7 +2479,7 @@ begin
case debug_ctrl.state is -- state machine

when DEBUG_OFFLINE => -- waiting to start debug mode
if (trap_ctrl.env_start_ack = '1') and (trap_ctrl.cause(5) = '1') then -- processing trap entry into debug mode
if (trap_ctrl.env_ack = '1') and (trap_ctrl.cause(5) = '1') then -- processing trap entry into debug mode
debug_ctrl.state <= DEBUG_ONLINE;
end if;

Expand Down
31 changes: 19 additions & 12 deletions rtl/core/neorv32_cpu_cp_fpu.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -88,14 +88,12 @@ architecture neorv32_cpu_cp_fpu_rtl of neorv32_cpu_cp_fpu is

-- float-to-integer unit --
component neorv32_cpu_cp_fpu_f2i
generic (
XLEN : in natural -- data path width
);
port (
-- control --
clk_i : in std_ulogic; -- global clock, rising edge
rstn_i : in std_ulogic; -- global reset, low-active, async
start_i : in std_ulogic; -- trigger operation
abort_i : in std_ulogic; -- abort current operation
rmode_i : in std_ulogic_vector(02 downto 0); -- rounding mode
funct_i : in std_ulogic; -- 0=signed, 1=unsigned
-- input --
Expand All @@ -117,6 +115,7 @@ architecture neorv32_cpu_cp_fpu_rtl of neorv32_cpu_cp_fpu is
clk_i : in std_ulogic; -- global clock, rising edge
rstn_i : in std_ulogic; -- global reset, low-active, async
start_i : in std_ulogic; -- trigger operation
abort_i : in std_ulogic; -- abort current operation
rmode_i : in std_ulogic_vector(02 downto 0); -- rounding mode
funct_i : in std_ulogic; -- operating mode (0=norm&round, 1=int-to-float)
-- input --
Expand Down Expand Up @@ -549,14 +548,12 @@ begin
-- Convert: Float to [unsigned] Integer (FCVT.S.W) ----------------------------------------
-- -------------------------------------------------------------------------------------------
neorv32_cpu_cp_fpu_f2i_inst: neorv32_cpu_cp_fpu_f2i
generic map (
XLEN => XLEN -- data path width
)
port map (
-- control --
clk_i => clk_i, -- global clock, rising edge
rstn_i => rstn_i, -- global reset, low-active, async
start_i => fu_conv_f2i.start, -- trigger operation
abort_i => ctrl_i.cpu_trap, -- abort current operation
rmode_i => fpu_operands.frm, -- rounding mode
funct_i => ctrl_i.ir_funct12(0), -- 0=signed, 1=unsigned
-- input --
Expand Down Expand Up @@ -1088,6 +1085,7 @@ begin
clk_i => clk_i, -- global clock, rising edge
rstn_i => rstn_i, -- global reset, low-active, async
start_i => normalizer.start, -- trigger operation
abort_i => ctrl_i.cpu_trap, -- abort current operation
rmode_i => fpu_operands.frm, -- rounding mode
funct_i => normalizer.mode, -- operation mode
-- input --
Expand All @@ -1108,7 +1106,7 @@ begin
-- FPU Core - Result
-- ****************************************************************************************************************************

-- Result Output to CPU Pipeline ----------------------------------------------------------
-- Output Result to CPU Pipeline ----------------------------------------------------------
-- -------------------------------------------------------------------------------------------
output_gate: process(clk_i)
begin
Expand Down Expand Up @@ -1199,6 +1197,7 @@ entity neorv32_cpu_cp_fpu_normalizer is
clk_i : in std_ulogic; -- global clock, rising edge
rstn_i : in std_ulogic; -- global reset, low-active, async
start_i : in std_ulogic; -- trigger operation
abort_i : in std_ulogic; -- abort current operation
rmode_i : in std_ulogic_vector(02 downto 0); -- rounding mode
funct_i : in std_ulogic; -- operating mode (0=norm&round, 1=int-to-float)
-- input --
Expand Down Expand Up @@ -1430,11 +1429,11 @@ begin
elsif (ctrl.cnt(7 downto 0) = x"FF") then -- infinity
ctrl.flags(fp_exc_of_c) <= '1';
end if;
ctrl.state <= S_FINALIZE;
ctrl.state <= S_FINALIZE;

when S_FINALIZE => -- result finalization
-- ------------------------------------------------------------
-- generate result word (the ORDER of checks is imporatant here!) --
-- generate result word (the ORDER of checks is important here!) --
if (ctrl.class(fp_class_snan_c) = '1') or (ctrl.class(fp_class_qnan_c) = '1') then -- sNaN / qNaN
ctrl.res_sgn <= fp_single_qnan_c(31);
ctrl.res_exp <= fp_single_qnan_c(30 downto 23);
Expand Down Expand Up @@ -1467,6 +1466,11 @@ begin
ctrl.state <= S_IDLE;

end case;

-- override: abort operation --
if (abort_i = '1') then
ctrl.state <= S_IDLE;
end if;
end if;
end process ctrl_engine;

Expand Down Expand Up @@ -1589,14 +1593,12 @@ library neorv32;
use neorv32.neorv32_package.all;

entity neorv32_cpu_cp_fpu_f2i is
generic (
XLEN : natural -- data path width
);
port (
-- control --
clk_i : in std_ulogic; -- global clock, rising edge
rstn_i : in std_ulogic; -- global reset, low-active, async
start_i : in std_ulogic; -- trigger operation
abort_i : in std_ulogic; -- abort current operation
rmode_i : in std_ulogic_vector(02 downto 0); -- rounding mode
funct_i : in std_ulogic; -- 0=signed, 1=unsigned
-- input --
Expand Down Expand Up @@ -1786,6 +1788,11 @@ begin
ctrl.state <= S_IDLE;

end case;

-- override: abort operation --
if (abort_i = '1') then
ctrl.state <= S_IDLE;
end if;
end if;
end process ctrl_engine;

Expand Down
2 changes: 1 addition & 1 deletion rtl/core/neorv32_package.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ package neorv32_package is

-- Architecture Constants -----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01080406"; -- hardware version
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01080407"; -- hardware version
constant archid_c : natural := 19; -- official RISC-V architecture ID
constant XLEN : natural := 32; -- native data path width, do not change!

Expand Down

0 comments on commit 77fedae

Please sign in to comment.