diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ed84ff9a..3349e0676 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,7 @@ mimpid = 0x01040312 -> Version 01.04.03.12 -> v1.4.3.12 | Date | Version | Comment | Link | |:----:|:-------:|:--------|:----:| +| 03.02.2024 | 1.9.4.3 | :bug: fix minor bug: CPU instruction bus privilege signal was hardwired to "user-mode" | [#790](https://github.com/stnolting/neorv32/pull/790) | | 01.02.2024 | 1.9.4.2 | :sparkles: add support for page fault exceptions (yet unused) | [#786](https://github.com/stnolting/neorv32/pull/786) | | 31.01.2024 | 1.9.4.1 | fix trap priority | [#784](https://github.com/stnolting/neorv32/pull/784) | | 31.01.2024 | [**:rocket:1.9.4**](https://github.com/stnolting/neorv32/releases/tag/v1.9.4) | **New release** | | diff --git a/rtl/core/neorv32_cpu_control.vhd b/rtl/core/neorv32_cpu_control.vhd index 3aa7f1776..f0b4c8336 100644 --- a/rtl/core/neorv32_cpu_control.vhd +++ b/rtl/core/neorv32_cpu_control.vhd @@ -429,7 +429,7 @@ begin ipb.we(1) <= '1' when (fetch_engine.state = IF_PENDING) and (fetch_engine.resp = '1') else '0'; -- bus access type -- - bus_req_o.priv <= ctrl.cpu_priv; -- current privilege mode + bus_req_o.priv <= csr.privilege_eff; -- current effective privilege level bus_req_o.data <= (others => '0'); -- read-only bus_req_o.ben <= (others => '0'); -- read-only bus_req_o.rw <= '0'; -- read-only @@ -1045,8 +1045,8 @@ begin ctrl_nxt.rf_mux <= rf_mux_mem_c; -- RF input = memory read data if (lsu_wait_i = '0') or -- bus system has completed the transaction (trap_ctrl.exc_buf(exc_saccess_c) = '1') or (trap_ctrl.exc_buf(exc_laccess_c) = '1') or -- access exception - (trap_ctrl.exc_buf(exc_salign_c) = '1') or (trap_ctrl.exc_buf(exc_lalign_c) = '1') or -- alignment exception - (trap_ctrl.exc_buf(exc_spage_c) = '1') or (trap_ctrl.exc_buf(exc_lpage_c) = '1') then -- page exception + (trap_ctrl.exc_buf(exc_salign_c) = '1') or (trap_ctrl.exc_buf(exc_lalign_c) = '1') or -- alignment exception + (trap_ctrl.exc_buf(exc_spage_c) = '1') or (trap_ctrl.exc_buf(exc_lpage_c) = '1') then -- page exception if ((CPU_EXTENSION_RISCV_A = true) and (decode_aux.opcode(2) = opcode_amo_c(2))) or -- atomic operation (execute_engine.ir(instr_opcode_msb_c-1) = '0') then -- normal load ctrl_nxt.rf_wb_en <= '1'; -- allow write-back to register file (won't happen in case of exception) diff --git a/rtl/core/neorv32_cpu_cp_fpu.vhd b/rtl/core/neorv32_cpu_cp_fpu.vhd index baf65264e..957d36c5a 100644 --- a/rtl/core/neorv32_cpu_cp_fpu.vhd +++ b/rtl/core/neorv32_cpu_cp_fpu.vhd @@ -923,27 +923,82 @@ begin if (fpu_operands.rs1(31) = fpu_operands.rs2(31)) then -- identical signs addsub.res_sign <= fpu_operands.rs1(31); else -- different signs - if (addsub.exp_comp(1) = '1') then -- exp are equal (also check relation of mantissas) - addsub.res_sign <= fpu_operands.rs1(31) xor (not addsub.man_comp); - else - addsub.res_sign <= fpu_operands.rs1(31) xor addsub.exp_comp(0); + -- if the result is not 0.0 set the sign normally + if ((to_integer(unsigned(addsub.add_stage))) /= 0 ) then + if (addsub.exp_comp(1) = '1') then -- exp are equal (also check relation of mantissas) + addsub.res_sign <= fpu_operands.rs1(31) xor (not addsub.man_comp); + else + addsub.res_sign <= fpu_operands.rs1(31) xor addsub.exp_comp(0); + end if; + else + -- roundTowardNegative; under that attribute, the sign of an exact zero sum (or difference) shall be −0 + if (fpu_operands.frm = "010") then -- round down (towards -infinity) + addsub.res_sign <= '1'; -- set the sign to 0 to generate a +0.0 result + else + addsub.res_sign <= '0'; -- set the sign to 0 to generate a +0.0 result + end if; end if; end if; else -- sub - if (fpu_operands.rs1(31) = fpu_operands.rs2(31)) then -- identical signs - if (addsub.exp_comp(1) = '1') then -- exp are equal (also check relation of mantissas) - addsub.res_sign <= fpu_operands.rs1(31) xor (not addsub.man_comp); - else - addsub.res_sign <= fpu_operands.rs1(31) xor addsub.exp_comp(0); + -- identical signs + -- if the result is not 0.0 set the sign normally + if (fpu_operands.rs1(31) = fpu_operands.rs2(31)) then + if ((to_integer(unsigned(addsub.add_stage))) /= 0 ) then + if (addsub.exp_comp(1) = '1') then -- exp are equal (also check relation of mantissas) + addsub.res_sign <= fpu_operands.rs1(31) xor (not addsub.man_comp); + else + addsub.res_sign <= fpu_operands.rs1(31) xor addsub.exp_comp(0); + end if; + else + -- roundTowardNegative; under that attribute, the sign of an exact zero sum (or difference) shall be −0 + if (fpu_operands.frm = "010") then -- round down (towards -infinity) + addsub.res_sign <= '1'; -- set the sign to 0 to generate a +0.0 result + else + addsub.res_sign <= '0'; -- set the sign to 0 to generate a +0.0 result + end if; end if; else -- different signs addsub.res_sign <= fpu_operands.rs1(31); end if; end if; - -- exception flags -- - addsub.flags(fp_exc_nv_c) <= ((fpu_operands.rs1_class(fp_class_pos_inf_c) or fpu_operands.rs1_class(fp_class_neg_inf_c)) and - (fpu_operands.rs2_class(fp_class_pos_inf_c) or fpu_operands.rs2_class(fp_class_neg_inf_c))); -- +/-inf +/- +/-inf + -- Infinities decoder ring + -- fadd: + -- Rs1 \ Rs2 | +inf | -inf | <- Rs2 + -- -------------------------------- + -- +inf | +inf | NV | + -- -------------------------------- + -- -inf | NV | -inf | + -- -------------------------------- + -- ^ + -- | + -- Rs1 + -- + -- fsub: + -- Rs1 \ Rs2 | +inf | -inf | <- Rs2 + -- -------------------------------- + -- +inf | NV | +inf | + -- -------------------------------- + -- -inf | -inf | NV | + -- -------------------------------- + -- ^ + -- | + -- Rs1 + -- Assume the operation is valid + addsub.flags(fp_exc_nv_c) <= '0'; + if (ctrl_i.ir_funct12(7) = '0') then -- add + -- Do we have 2 infinities of opposite sign? + if (((fpu_operands.rs1_class(fp_class_pos_inf_c) and fpu_operands.rs2_class(fp_class_neg_inf_c)) or + (fpu_operands.rs1_class(fp_class_neg_inf_c) and fpu_operands.rs2_class(fp_class_pos_inf_c))) = '1') then + addsub.flags(fp_exc_nv_c) <= '1'; + end if; + else -- sub + -- Do we have 2 infinities of same sign? + if (((fpu_operands.rs1_class(fp_class_pos_inf_c) and fpu_operands.rs2_class(fp_class_pos_inf_c)) or + (fpu_operands.rs1_class(fp_class_neg_inf_c) and fpu_operands.rs2_class(fp_class_neg_inf_c))) = '1') then + addsub.flags(fp_exc_nv_c) <= '1'; + end if; + end if; end if; end process adder_subtractor_core; @@ -1497,6 +1552,9 @@ begin sreg.upper(31 downto 02) <= (others => '0'); sreg.upper(01 downto 00) <= round.output(24 downto 23); sreg.lower <= round.output(22 downto 00); + -- If after the first shift we get a bit in any of the guard bitsthen independent of rounding mode + -- the end result will be inexact as we are truncating away information + ctrl.flags(fp_exc_nx_c) <= sreg.ext_g or sreg.ext_r or sreg.ext_s; sreg.ext_g <= '0'; sreg.ext_r <= '0'; sreg.ext_s <= '0'; @@ -1506,12 +1564,28 @@ begin -- ------------------------------------------------------------ if (ctrl.cnt_uf = '1') then -- underflow ctrl.flags(fp_exc_uf_c) <= '1'; + -- As is defined in '754, under default exception handling, underflow is + -- only signalled when the result is tiny and inexact. In such a case, + -- both the underflow and inexact flags are raised. + ctrl.flags(fp_exc_nx_c) <= '1'; elsif (ctrl.cnt_of = '1') then -- overflow ctrl.flags(fp_exc_of_c) <= '1'; + -- As is defined in '754, under default exception handling, overflow is + -- only signalled when the result is large and inexact. In such a case, + -- both the underflow and inexact flags are raised. + ctrl.flags(fp_exc_nx_c) <= '1'; elsif (ctrl.cnt(7 downto 0) = x"00") then -- subnormal ctrl.flags(fp_exc_uf_c) <= '1'; + -- As is defined in '754, under default exception handling, underflow is + -- only signalled when the result is tiny and inexact. In such a case, + -- both the underflow and inexact flags are raised. + ctrl.flags(fp_exc_nx_c) <= '1'; elsif (ctrl.cnt(7 downto 0) = x"FF") then -- infinity ctrl.flags(fp_exc_of_c) <= '1'; + -- As is defined in '754, under default exception handling, overflow is + -- only signalled when the result is large and inexact. In such a case, + -- both the underflow and inexact flags are raised. + ctrl.flags(fp_exc_nx_c) <= '1'; end if; ctrl.state <= S_FINALIZE; diff --git a/rtl/core/neorv32_package.vhd b/rtl/core/neorv32_package.vhd index 5eaad65cf..7990ac8fd 100644 --- a/rtl/core/neorv32_package.vhd +++ b/rtl/core/neorv32_package.vhd @@ -56,7 +56,7 @@ package neorv32_package is -- Architecture Constants ----------------------------------------------------------------- -- ------------------------------------------------------------------------------------------- - constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01090402"; -- hardware version + constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01090403"; -- hardware version constant archid_c : natural := 19; -- official RISC-V architecture ID constant XLEN : natural := 32; -- native data path width @@ -461,7 +461,7 @@ package neorv32_package is constant csr_mhpmcounter15h_c : std_ulogic_vector(11 downto 0) := x"b8f"; -- user counters/timers -- constant csr_cycle_c : std_ulogic_vector(11 downto 0) := x"c00"; - constant csr_time_c : std_ulogic_vector(11 downto 0) := x"c01"; +--constant csr_time_c : std_ulogic_vector(11 downto 0) := x"c01"; constant csr_instret_c : std_ulogic_vector(11 downto 0) := x"c02"; constant csr_hpmcounter3_c : std_ulogic_vector(11 downto 0) := x"c03"; constant csr_hpmcounter4_c : std_ulogic_vector(11 downto 0) := x"c04"; @@ -478,7 +478,7 @@ package neorv32_package is constant csr_hpmcounter15_c : std_ulogic_vector(11 downto 0) := x"c0f"; -- constant csr_cycleh_c : std_ulogic_vector(11 downto 0) := x"c80"; - constant csr_timeh_c : std_ulogic_vector(11 downto 0) := x"c81"; +--constant csr_timeh_c : std_ulogic_vector(11 downto 0) := x"c81"; constant csr_instreth_c : std_ulogic_vector(11 downto 0) := x"c82"; constant csr_hpmcounter3h_c : std_ulogic_vector(11 downto 0) := x"c83"; constant csr_hpmcounter4h_c : std_ulogic_vector(11 downto 0) := x"c84";