Minor rtl edits and cleanup; 🐛 fix multiple drivers bug (#1151)
Some checks failed
Documentation / SW Framework (push) Has been cancelled
Documentation / Datasheet (push) Has been cancelled
Processor / processor simulation (push) Has been cancelled
Documentation / Deploy to Releases and Pages (push) Has been cancelled

This commit is contained in:
stnolting 2025-01-11 23:56:26 +01:00 committed by GitHub
commit 01e88db0fd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 121 additions and 112 deletions

View file

@ -29,6 +29,7 @@ mimpid = 0x01040312 -> Version 01.04.03.12 -> v1.4.3.12
| Date | Version | Comment | Ticket |
|:----:|:-------:|:--------|:------:|
| 12.01.2025 | 1.10.9.5 | minor rtl cleanups; :bug: fix minor bug (multiple drivers on ICC nets; introduced in version 1.10.9.2) | [#1151](https://github.com/stnolting/neorv32/pull/1151) |
| 11.01.2025 | 1.10.9.4 | :warning: RTE: use a single, global trap handler table that applies to _both_ cores | [#1150](https://github.com/stnolting/neorv32/pull/1150) |
| 10.01.2025 | 1.10.9.3 | split functional behavior of `fence` and `fence.i` instructions | [#1149](https://github.com/stnolting/neorv32/pull/1149) |
| 10.01.2025 | 1.10.9.2 | clean-up SMP dual-core configuration (HW and SW optimizations) | [#1146](https://github.com/stnolting/neorv32/pull/1146) |

View file

@ -361,7 +361,7 @@ As software does not need to determine the interrupt cause the reduction in late
|=======================
| Name | Machine exception program counter
| Address | `0x341`
| Reset value | `BOOT_ADDR` (CPU boot address, see <<_cpu_top_entity_generics>>)
| Reset value | `0x00000000`
| ISA | `Zicsr`
| Description | The `mepc` CSR provides the instruction address where execution has stopped/failed when
an interrupt is triggered / an exception is raised. See section <<_traps_exceptions_and_interrupts>> for a list of all legal values.

View file

@ -827,7 +827,7 @@ begin
arbiter_nxt.state <= S_READ_WAIT;
end if;
when S_READ_WAIT => -- wait for device read-access to complete
when S_READ_WAIT => -- wait for read-access to complete
-- ------------------------------------------------------------
arbiter_nxt.rdata <= sys_rsp_i.data;
if (sys_rsp_i.ack = '1') or (sys_rsp_i.err = '1') then
@ -838,11 +838,11 @@ begin
-- ------------------------------------------------------------
arbiter_nxt.state <= S_WRITE;
when S_WRITE => -- wait operation result to device
when S_WRITE => -- write operation result
-- ------------------------------------------------------------
arbiter_nxt.state <= S_WRITE_WAIT;
when S_WRITE_WAIT => -- wait for device write-access to complete
when S_WRITE_WAIT => -- wait for write-access to complete
-- ------------------------------------------------------------
if (sys_rsp_i.ack = '1') or (sys_rsp_i.err = '1') then
arbiter_nxt.state <= S_IDLE;
@ -883,12 +883,12 @@ begin
alu_res <= (others => '0');
elsif rising_edge(clk_i) then
case arbiter.cmd(2 downto 0) is
when "000" => alu_res <= arbiter.wdata; -- AMOSWAP
when "001" => alu_res <= std_ulogic_vector(unsigned(arbiter.rdata) + unsigned(arbiter.wdata)); -- AMOADD
when "010" => alu_res <= arbiter.rdata xor arbiter.wdata; -- AMOXOR
when "011" => alu_res <= arbiter.rdata and arbiter.wdata; -- AMOAND
when "100" => alu_res <= arbiter.rdata or arbiter.wdata; -- AMOOR
when others => alu_res <= cmp_res; -- AMOMIN[U] / AMOMAX[U]
when "000" => alu_res <= arbiter.wdata; -- AMOSWAP.W
when "001" => alu_res <= std_ulogic_vector(unsigned(arbiter.rdata) + unsigned(arbiter.wdata)); -- AMOADD.W
when "010" => alu_res <= arbiter.rdata xor arbiter.wdata; -- AMOXOR.W
when "011" => alu_res <= arbiter.rdata and arbiter.wdata; -- AMOAND.W
when "100" => alu_res <= arbiter.rdata or arbiter.wdata; -- AMOOR.W
when others => alu_res <= cmp_res; -- AMOMIN[U].W / AMOMAX[U].W
end case;
end if;
end process amo_alu;

View file

@ -846,8 +846,8 @@ begin
bus_req_o.ben <= (others => '1'); -- full-word writes only
bus_req_o.src <= '0'; -- cache accesses are always data accesses
bus_req_o.priv <= '0'; -- cache accesses are always "unprivileged" accesses
bus_req_o.amo <= '0'; -- cache accesses can never be an atomic memory operation set operation
bus_req_o.amoop <= (others => '0'); -- cache accesses can never be an atomic memory operation set operation
bus_req_o.amo <= '0'; -- cache accesses can never be an atomic memory operation
bus_req_o.amoop <= (others => '0'); -- cache accesses can never be an atomic memory operation
bus_req_o.debug <= host_req_i.debug;
if (state = S_IDLE) then
bus_req_o.sleep <= host_req_i.sleep;

View file

@ -136,52 +136,57 @@ begin
-- Configuration Info and Sanity Checks ---------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- CPU ISA configuration (in alphabetical order - not in canonical order!) --
assert false report "[NEORV32] CPU ISA: rv32" &
cond_sel_string_f(RISCV_ISA_E, "e", "i") &
cond_sel_string_f(riscv_b_c, "b", "" ) &
cond_sel_string_f(RISCV_ISA_C, "c", "" ) &
cond_sel_string_f(RISCV_ISA_M, "m", "" ) &
cond_sel_string_f(RISCV_ISA_U, "u", "" ) &
cond_sel_string_f(true, "x", "" ) & -- always enabled
cond_sel_string_f(RISCV_ISA_Zaamo, "_zaamo", "" ) &
cond_sel_string_f(RISCV_ISA_Zba, "_zba", "" ) &
cond_sel_string_f(RISCV_ISA_Zbb, "_zbb", "" ) &
cond_sel_string_f(RISCV_ISA_Zbkb, "_zbkb", "" ) &
cond_sel_string_f(RISCV_ISA_Zbkc, "_zbkc", "" ) &
cond_sel_string_f(RISCV_ISA_Zbkx, "_zbkx", "" ) &
cond_sel_string_f(RISCV_ISA_Zbs, "_zbs", "" ) &
cond_sel_string_f(RISCV_ISA_Zicntr, "_zicntr", "" ) &
cond_sel_string_f(RISCV_ISA_Zicond, "_zicond", "" ) &
cond_sel_string_f(true, "_zicsr", "" ) & -- always enabled
cond_sel_string_f(true, "_zifencei", "" ) & -- always enabled
cond_sel_string_f(RISCV_ISA_Zihpm, "_zihpm", "" ) &
cond_sel_string_f(RISCV_ISA_Zfinx, "_zfinx", "" ) &
cond_sel_string_f(riscv_zkn_c, "_zkn", "" ) &
cond_sel_string_f(RISCV_ISA_Zknd, "_zknd", "" ) &
cond_sel_string_f(RISCV_ISA_Zkne, "_zkne", "" ) &
cond_sel_string_f(RISCV_ISA_Zknh, "_zknh", "" ) &
cond_sel_string_f(riscv_zks_c, "_zks", "" ) &
cond_sel_string_f(RISCV_ISA_Zksed, "_zksed", "" ) &
cond_sel_string_f(RISCV_ISA_Zksh, "_zksh", "" ) &
cond_sel_string_f(riscv_zkt_c, "_zkt", "" ) &
cond_sel_string_f(RISCV_ISA_Zmmul, "_zmmul", "" ) &
cond_sel_string_f(RISCV_ISA_Zxcfu, "_zxcfu", "" ) &
cond_sel_string_f(RISCV_ISA_Sdext, "_sdext", "" ) &
cond_sel_string_f(RISCV_ISA_Sdtrig, "_sdtrig", "" ) &
cond_sel_string_f(RISCV_ISA_Smpmp, "_smpmp", "" )
severity note;
hello_neorv32:
if HART_ID = 0 generate -- print only for core 0
-- CPU tuning options --
assert false report "[NEORV32] CPU tuning options: " &
cond_sel_string_f(CPU_CLOCK_GATING_EN, "clock_gating ", "") &
cond_sel_string_f(CPU_FAST_MUL_EN, "fast_mul ", "") &
cond_sel_string_f(CPU_FAST_SHIFT_EN, "fast_shift ", "") &
cond_sel_string_f(CPU_RF_HW_RST_EN, "rf_hw_rst ", "")
severity note;
-- CPU ISA configuration (in alphabetical order - not in canonical order!) --
assert false report "[NEORV32] CPU ISA: rv32" &
cond_sel_string_f(RISCV_ISA_E, "e", "i") &
cond_sel_string_f(riscv_b_c, "b", "" ) &
cond_sel_string_f(RISCV_ISA_C, "c", "" ) &
cond_sel_string_f(RISCV_ISA_M, "m", "" ) &
cond_sel_string_f(RISCV_ISA_U, "u", "" ) &
cond_sel_string_f(true, "x", "" ) & -- always enabled
cond_sel_string_f(RISCV_ISA_Zaamo, "_zaamo", "" ) &
cond_sel_string_f(RISCV_ISA_Zba, "_zba", "" ) &
cond_sel_string_f(RISCV_ISA_Zbb, "_zbb", "" ) &
cond_sel_string_f(RISCV_ISA_Zbkb, "_zbkb", "" ) &
cond_sel_string_f(RISCV_ISA_Zbkc, "_zbkc", "" ) &
cond_sel_string_f(RISCV_ISA_Zbkx, "_zbkx", "" ) &
cond_sel_string_f(RISCV_ISA_Zbs, "_zbs", "" ) &
cond_sel_string_f(RISCV_ISA_Zicntr, "_zicntr", "" ) &
cond_sel_string_f(RISCV_ISA_Zicond, "_zicond", "" ) &
cond_sel_string_f(true, "_zicsr", "" ) & -- always enabled
cond_sel_string_f(true, "_zifencei", "" ) & -- always enabled
cond_sel_string_f(RISCV_ISA_Zihpm, "_zihpm", "" ) &
cond_sel_string_f(RISCV_ISA_Zfinx, "_zfinx", "" ) &
cond_sel_string_f(riscv_zkn_c, "_zkn", "" ) &
cond_sel_string_f(RISCV_ISA_Zknd, "_zknd", "" ) &
cond_sel_string_f(RISCV_ISA_Zkne, "_zkne", "" ) &
cond_sel_string_f(RISCV_ISA_Zknh, "_zknh", "" ) &
cond_sel_string_f(riscv_zks_c, "_zks", "" ) &
cond_sel_string_f(RISCV_ISA_Zksed, "_zksed", "" ) &
cond_sel_string_f(RISCV_ISA_Zksh, "_zksh", "" ) &
cond_sel_string_f(riscv_zkt_c, "_zkt", "" ) &
cond_sel_string_f(RISCV_ISA_Zmmul, "_zmmul", "" ) &
cond_sel_string_f(RISCV_ISA_Zxcfu, "_zxcfu", "" ) &
cond_sel_string_f(RISCV_ISA_Sdext, "_sdext", "" ) &
cond_sel_string_f(RISCV_ISA_Sdtrig, "_sdtrig", "" ) &
cond_sel_string_f(RISCV_ISA_Smpmp, "_smpmp", "" )
severity note;
-- simulation notifier --
assert not is_simulation_c report "[NEORV32] Assuming this is a simulation." severity warning;
-- CPU tuning options --
assert false report "[NEORV32] CPU tuning options: " &
cond_sel_string_f(CPU_CLOCK_GATING_EN, "clock_gating ", "") &
cond_sel_string_f(CPU_FAST_MUL_EN, "fast_mul ", "") &
cond_sel_string_f(CPU_FAST_SHIFT_EN, "fast_shift ", "") &
cond_sel_string_f(CPU_RF_HW_RST_EN, "rf_hw_rst ", "")
severity note;
-- simulation notifier --
assert not is_simulation_c report "[NEORV32] Assuming this is a simulation." severity warning;
end generate;
-- Clock Gating ---------------------------------------------------------------------------

View file

@ -226,8 +226,8 @@ architecture neorv32_cpu_control_rtl of neorv32_cpu_control is
mie_mti : std_ulogic; -- machine timer interrupt enable
mie_firq : std_ulogic_vector(15 downto 0); -- fast interrupt enable
--
privilege : std_ulogic; -- current privilege mode
privilege_eff : std_ulogic; -- current *effective* privilege mode
prv_level : std_ulogic; -- current privilege level
prv_level_eff : std_ulogic; -- current *effective* privilege level
--
mepc : std_ulogic_vector(XLEN-1 downto 0); -- machine exception PC
mcause : std_ulogic_vector(5 downto 0); -- machine trap cause
@ -339,7 +339,7 @@ begin
-- ------------------------------------------------------------
fetch_engine.restart <= '0'; -- restart done
fetch_engine.pc <= exe_engine.pc2(XLEN-1 downto 1) & '0'; -- initialize from PC incl. 16-bit-alignment bit
fetch_engine.priv <= csr.privilege_eff; -- set new privilege level
fetch_engine.priv <= csr.prv_level_eff; -- set new privilege level
fetch_engine.state <= IF_REQUEST;
end case;
@ -816,9 +816,7 @@ begin
(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_illegal_c) = '1') then -- illegal instruction exception
if (RISCV_ISA_Zaamo and (opcode(2) = opcode_amo_c(2))) or (opcode(5) = '0') then -- atomic operation / normal load
ctrl_nxt.rf_wb_en <= '1'; -- allow write-back to register file (won't happen in case of exception)
end if;
ctrl_nxt.rf_wb_en <= not ctrl.lsu_rw; -- write-back to register file if read operation (won't happen in case of exception)
exe_engine_nxt.state <= EX_DISPATCH;
end if;
@ -876,13 +874,13 @@ begin
ctrl_o.lsu_rw <= ctrl.lsu_rw;
ctrl_o.lsu_mo_we <= '1' when (exe_engine.state = EX_MEM_REQ) else '0'; -- write memory output registers (data & address)
ctrl_o.lsu_fence <= ctrl.lsu_fence;
ctrl_o.lsu_priv <= csr.mstatus_mpp when (csr.mstatus_mprv = '1') else csr.privilege_eff; -- effective privilege level for loads/stores in M-mode
ctrl_o.lsu_priv <= csr.mstatus_mpp when (csr.mstatus_mprv = '1') else csr.prv_level_eff; -- effective privilege level for loads/stores in M-mode
-- instruction word bit fields --
ctrl_o.ir_funct3 <= exe_engine.ir(instr_funct3_msb_c downto instr_funct3_lsb_c);
ctrl_o.ir_funct12 <= exe_engine.ir(instr_funct12_msb_c downto instr_funct12_lsb_c);
ctrl_o.ir_opcode <= opcode;
-- cpu status --
ctrl_o.cpu_priv <= csr.privilege_eff;
ctrl_o.cpu_priv <= csr.prv_level_eff;
ctrl_o.cpu_sleep <= sleep_mode;
ctrl_o.cpu_trap <= trap_ctrl.env_enter;
ctrl_o.cpu_debug <= debug_ctrl.run;
@ -999,12 +997,12 @@ begin
if (csr_addr_v(11 downto 4) = csr_dcsr_c(11 downto 4)) and -- debug-mode-only CSR?
RISCV_ISA_Sdext and (debug_ctrl.run = '0') then -- debug-mode implemented and not running?
csr_valid(0) <= '0'; -- invalid access
elsif RISCV_ISA_Zicntr and RISCV_ISA_U and (csr.privilege_eff = '0') and -- any user-mode counters available and in user-mode?
elsif RISCV_ISA_Zicntr and RISCV_ISA_U and (csr.prv_level_eff = '0') and -- any user-mode counters available and in user-mode?
(csr_addr_v(11 downto 8) = csr_cycle_c(11 downto 8)) and -- user-mode counter access
(((csr_addr_v(1 downto 0) = csr_cycle_c(1 downto 0)) and (csr.mcounteren_cy = '0')) or -- illegal access to cycle
((csr_addr_v(1 downto 0) = csr_instret_c(1 downto 0)) and (csr.mcounteren_ir = '0'))) then -- illegal access to instret
csr_valid(0) <= '0'; -- invalid access
elsif (csr_addr_v(9 downto 8) /= "00") and (csr.privilege_eff = '0') then -- invalid privilege level
elsif (csr_addr_v(9 downto 8) /= "00") and (csr.prv_level_eff = '0') then -- invalid privilege level
csr_valid(0) <= '0'; -- invalid access
else
csr_valid(0) <= '1'; -- access granted
@ -1047,7 +1045,7 @@ begin
end case;
when opcode_amo_c => -- atomic memory operation
if RISCV_ISA_Zaamo and (exe_engine.ir(instr_funct3_msb_c downto instr_funct3_lsb_c) = "010") then
if RISCV_ISA_Zaamo and (exe_engine.ir(instr_funct3_msb_c downto instr_funct3_lsb_c) = "010") then -- word-quantity only
case exe_engine.ir(instr_funct5_msb_c downto instr_funct5_lsb_c) is
when "00001" | "00000" | "00100" | "01100" | "01000" | "10000" | "10100" | "11000" | "11100" => illegal_cmd <= '0';
when others => illegal_cmd <= '1';
@ -1068,9 +1066,9 @@ begin
case exe_engine.ir(instr_funct12_msb_c downto instr_funct12_lsb_c) is
when funct12_ecall_c => illegal_cmd <= '0'; -- ecall is always allowed
when funct12_ebreak_c => illegal_cmd <= '0'; -- ebreak is always allowed
when funct12_mret_c => illegal_cmd <= (not csr.privilege) or debug_ctrl.run; -- mret allowed in (real/non-debug) M-mode only
when funct12_mret_c => illegal_cmd <= (not csr.prv_level) or debug_ctrl.run; -- mret allowed in (real/non-debug) M-mode only
when funct12_dret_c => illegal_cmd <= not debug_ctrl.run; -- dret allowed in debug mode only
when funct12_wfi_c => illegal_cmd <= (not csr.privilege) and csr.mstatus_tw; -- wfi allowed in M-mode or if TW is zero
when funct12_wfi_c => illegal_cmd <= (not csr.prv_level) and csr.mstatus_tw; -- wfi allowed in M-mode or if TW is zero
when others => illegal_cmd <= '1'; -- undefined
end case;
end if;
@ -1128,8 +1126,8 @@ begin
if RISCV_ISA_Sdext then
trap_ctrl.exc_buf(exc_ebreak_c) <= (not trap_ctrl.env_enter) and (trap_ctrl.exc_buf(exc_ebreak_c) or
(trap_ctrl.hwtrig and (not csr.tdata1_action)) or -- trigger module fires and enter-debug-action is disabled
(trap_ctrl.ebreak and ( csr.privilege) and (not csr.dcsr_ebreakm) and (not debug_ctrl.run)) or -- enter M-mode handler on ebreak in M-mode
(trap_ctrl.ebreak and (not csr.privilege) and (not csr.dcsr_ebreaku) and (not debug_ctrl.run))); -- enter M-mode handler on ebreak in U-mode
(trap_ctrl.ebreak and ( csr.prv_level) and (not csr.dcsr_ebreakm) and (not debug_ctrl.run)) or -- enter M-mode handler on ebreak in M-mode
(trap_ctrl.ebreak and (not csr.prv_level) and (not csr.dcsr_ebreaku) and (not debug_ctrl.run))); -- 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.ebreak or (trap_ctrl.hwtrig and (not csr.tdata1_action))) and (not trap_ctrl.env_enter);
end if;
@ -1202,7 +1200,7 @@ begin
if (trap_ctrl.exc_buf(exc_iaccess_c) = '1') then trap_ctrl.cause <= trap_iaf_c; -- instruction access fault
elsif (trap_ctrl.exc_buf(exc_illegal_c) = '1') then trap_ctrl.cause <= trap_iil_c; -- illegal instruction
elsif (trap_ctrl.exc_buf(exc_ialign_c) = '1') then trap_ctrl.cause <= trap_ima_c; -- instruction address misaligned
elsif (trap_ctrl.exc_buf(exc_ecall_c) = '1') then trap_ctrl.cause <= trap_env_c(6 downto 2) & replicate_f(csr.privilege, 2); -- environment call (U/M)
elsif (trap_ctrl.exc_buf(exc_ecall_c) = '1') then trap_ctrl.cause <= trap_env_c(6 downto 2) & replicate_f(csr.prv_level, 2); -- environment call (U/M)
elsif (trap_ctrl.exc_buf(exc_ebreak_c) = '1') then trap_ctrl.cause <= trap_brk_c; -- environment breakpoint
elsif (trap_ctrl.exc_buf(exc_salign_c) = '1') then trap_ctrl.cause <= trap_sma_c; -- store address misaligned
elsif (trap_ctrl.exc_buf(exc_lalign_c) = '1') then trap_ctrl.cause <= trap_lma_c; -- load address misaligned
@ -1276,7 +1274,7 @@ begin
trap_ctrl.irq_fire(0) <= '1' when
(exe_engine.state = EX_EXECUTE) and -- trigger system IRQ only in EX_EXECUTE state
(or_reduce_f(trap_ctrl.irq_buf(irq_firq_15_c downto irq_msi_irq_c)) = '1') and -- pending system IRQ
((csr.mstatus_mie = '1') or (csr.privilege = priv_mode_u_c)) and -- IRQ only when in M-mode and MIE=1 OR when in U-mode
((csr.mstatus_mie = '1') or (csr.prv_level = priv_mode_u_c)) and -- IRQ only when in M-mode and MIE=1 OR when in U-mode
(debug_ctrl.run = '0') and (csr.dcsr_step = '0') else '0'; -- no system IRQs when in debug-mode / during single-stepping
-- debug-entry halt interrupt? --
@ -1355,7 +1353,7 @@ begin
begin
if (rstn_i = '0') then
csr.we <= '0';
csr.privilege <= priv_mode_m_c;
csr.prv_level <= priv_mode_m_c;
csr.mstatus_mie <= '0';
csr.mstatus_mpie <= '0';
csr.mstatus_mpp <= priv_mode_m_c;
@ -1366,8 +1364,8 @@ begin
csr.mie_mti <= '0';
csr.mie_firq <= (others => '0');
csr.mtvec <= (others => '0');
csr.mscratch <= x"19880704";
csr.mepc <= BOOT_ADDR(XLEN-1 downto 2) & "00"; -- 32-bit-aligned boot address
csr.mscratch <= (others => '0');
csr.mepc <= (others => '0');
csr.mcause <= (others => '0');
csr.mtval <= (others => '0');
csr.mtinst <= (others => '0');
@ -1540,16 +1538,16 @@ begin
csr.mtinst <= (others => '0');
end if;
-- update privilege level and interrupt-enable stack --
csr.privilege <= priv_mode_m_c; -- execute trap in machine mode
csr.prv_level <= priv_mode_m_c; -- execute trap in machine mode
csr.mstatus_mie <= '0'; -- disable interrupts
csr.mstatus_mpie <= csr.mstatus_mie; -- backup previous mie state
csr.mstatus_mpp <= csr.privilege; -- backup previous privilege mode
csr.mstatus_mpp <= csr.prv_level; -- backup previous privilege level
end if;
-- DEBUG trap entry - no CSR update when already in debug-mode! --
if RISCV_ISA_Sdext and (trap_ctrl.cause(5) = '1') and (debug_ctrl.run = '0') then
csr.dcsr_cause <= trap_ctrl.cause(2 downto 0); -- trap cause
csr.dcsr_prv <= csr.privilege; -- current privilege mode when debug mode was entered
csr.dcsr_prv <= csr.prv_level; -- current privilege level when debug mode was entered
csr.dpc <= trap_ctrl.epc(XLEN-1 downto 1) & '0'; -- trap PC
end if;
@ -1561,18 +1559,18 @@ begin
-- return from debug mode --
if RISCV_ISA_Sdext and (debug_ctrl.run = '1') then
if RISCV_ISA_U then
csr.privilege <= csr.dcsr_prv;
csr.prv_level <= csr.dcsr_prv;
if (csr.dcsr_prv /= priv_mode_m_c) then
csr.mstatus_mprv <= '0'; -- clear if return to priv. mode less than M
csr.mstatus_mprv <= '0'; -- clear if return to priv. level less than M
end if;
end if;
-- return from normal trap --
else
if RISCV_ISA_U then
csr.privilege <= csr.mstatus_mpp; -- restore previous privilege mode
csr.mstatus_mpp <= priv_mode_u_c; -- set to least-privileged mode that is supported
csr.prv_level <= csr.mstatus_mpp; -- restore previous privilege level
csr.mstatus_mpp <= priv_mode_u_c; -- set to least-privileged level that is supported
if (csr.mstatus_mpp /= priv_mode_m_c) then
csr.mstatus_mprv <= '0'; -- clear if return to priv. mode less than M
csr.mstatus_mprv <= '0'; -- clear if return to priv. level less than M
end if;
end if;
csr.mstatus_mie <= csr.mstatus_mpie; -- restore machine-mode IRQ enable flag
@ -1606,7 +1604,7 @@ begin
-- no user mode --
if not RISCV_ISA_U then
csr.privilege <= priv_mode_m_c;
csr.prv_level <= priv_mode_m_c;
csr.mstatus_mpp <= priv_mode_m_c;
csr.mstatus_mprv <= '0';
csr.mstatus_tw <= '0';
@ -1638,8 +1636,8 @@ begin
end if;
end process csr_write_access;
-- effective privilege mode is MACHINE when in debug mode --
csr.privilege_eff <= priv_mode_m_c when (debug_ctrl.run = '1') else csr.privilege;
-- effective privilege level is MACHINE when in debug mode --
csr.prv_level_eff <= priv_mode_m_c when (debug_ctrl.run = '1') else csr.prv_level;
-- CSR Read Access ------------------------------------------------------------------------
@ -1690,13 +1688,13 @@ begin
-- when csr_mstatush_c => csr.rdata <= (others => '0'); -- machine status register, high word - hardwired to zero
when csr_misa_c => -- ISA and extensions
csr.rdata(1) <= bool_to_ulogic_f(RISCV_ISA_B); -- B CPU extension
csr.rdata(2) <= bool_to_ulogic_f(RISCV_ISA_C); -- C CPU extension
csr.rdata(4) <= bool_to_ulogic_f(RISCV_ISA_E); -- E CPU extension
csr.rdata(8) <= bool_to_ulogic_f(not RISCV_ISA_E); -- I CPU extension (if not E)
csr.rdata(12) <= bool_to_ulogic_f(RISCV_ISA_M); -- M CPU extension
csr.rdata(20) <= bool_to_ulogic_f(RISCV_ISA_U); -- U CPU extension
csr.rdata(23) <= '1'; -- X CPU extension (non-standard / NEORV32-specific)
csr.rdata(1) <= bool_to_ulogic_f(RISCV_ISA_B);
csr.rdata(2) <= bool_to_ulogic_f(RISCV_ISA_C);
csr.rdata(4) <= bool_to_ulogic_f(RISCV_ISA_E);
csr.rdata(8) <= bool_to_ulogic_f(not RISCV_ISA_E); -- I = not E
csr.rdata(12) <= bool_to_ulogic_f(RISCV_ISA_M);
csr.rdata(20) <= bool_to_ulogic_f(RISCV_ISA_U);
csr.rdata(23) <= '1'; -- X CPU extension (non-standard / NEORV32-specific)
csr.rdata(31 downto 30) <= "01"; -- MXL = 32
when csr_mie_c => -- machine interrupt-enable register
@ -1880,7 +1878,6 @@ begin
csr.rdata(24) <= bool_to_ulogic_f(RISCV_ISA_Zbs); -- Zbs: single-bit bit-manipulation
csr.rdata(25) <= bool_to_ulogic_f(RISCV_ISA_Zaamo); -- Zaamo: atomic memory operations
csr.rdata(26) <= '0'; -- reserved
csr.rdata(27) <= '0'; -- reserved
-- tuning options --
csr.rdata(27) <= bool_to_ulogic_f(CPU_CLOCK_GATING_EN); -- enable clock gating when in sleep mode
csr.rdata(28) <= bool_to_ulogic_f(CPU_RF_HW_RST_EN); -- full hardware reset of register file
@ -2078,8 +2075,8 @@ begin
-- debug mode entry triggers --
debug_ctrl.trig_hw <= trap_ctrl.hwtrig and (not debug_ctrl.run) and csr.tdata1_action and csr.tdata1_dmode; -- enter debug mode by HW trigger module
debug_ctrl.trig_break <= trap_ctrl.ebreak and (debug_ctrl.run or -- re-enter debug mode
(( csr.privilege) and csr.dcsr_ebreakm) or -- enabled goto-debug-mode in machine mode on "ebreak"
((not csr.privilege) and csr.dcsr_ebreaku)); -- enabled goto-debug-mode in user mode on "ebreak"
(( csr.prv_level) and csr.dcsr_ebreakm) or -- enabled goto-debug-mode in machine mode on "ebreak"
((not csr.prv_level) and csr.dcsr_ebreaku)); -- enabled goto-debug-mode in user mode on "ebreak"
debug_ctrl.trig_halt <= irq_dbg_i and (not debug_ctrl.run); -- external halt request (if not halted already)
debug_ctrl.trig_step <= csr.dcsr_step and (not debug_ctrl.run); -- single-step mode (trigger when NOT CURRENTLY in debug mode)
@ -2112,7 +2109,7 @@ begin
csr.dcsr_rd(4) <= '1'; -- mprven: mstatus.mprv is also evaluated in debug mode
csr.dcsr_rd(3) <= '0'; -- nmip: no pending non-maskable interrupt
csr.dcsr_rd(2) <= csr.dcsr_step; -- step: single-step mode
csr.dcsr_rd(1 downto 0) <= (others => csr.dcsr_prv); -- prv: privilege mode when debug mode was entered
csr.dcsr_rd(1 downto 0) <= (others => csr.dcsr_prv); -- prv: privilege level when debug mode was entered
-- ****************************************************************************************************************************

View file

@ -3,7 +3,7 @@
-- -------------------------------------------------------------------------------- --
-- The NEORV32 RISC-V Processor - https://github.com/stnolting/neorv32 --
-- Copyright (c) NEORV32 contributors. --
-- Copyright (c) 2020 - 2024 Stephan Nolting. All rights reserved. --
-- Copyright (c) 2020 - 2025 Stephan Nolting. All rights reserved. --
-- Licensed under the BSD-3-Clause license, see LICENSE for details. --
-- SPDX-License-Identifier: BSD-3-Clause --
-- ================================================================================ --
@ -117,6 +117,7 @@ begin
-- atomic memory access operation encoding --
amo_encode: process(ctrl_i.ir_funct12)
begin
amo_cmd <= (others => '0'); -- default
if AMO_EN then
case ctrl_i.ir_funct12(11 downto 7) is
when "00000" => amo_cmd <= "0001"; -- ADD
@ -129,8 +130,6 @@ begin
when "11100" => amo_cmd <= "0111"; -- MAXU
when others => amo_cmd <= "0000"; -- SWAP
end case;
else
amo_cmd <= (others => '0');
end if;
end process;

View file

@ -29,7 +29,7 @@ package neorv32_package is
-- Architecture Constants -----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01100904"; -- hardware version
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01100905"; -- hardware version
constant archid_c : natural := 19; -- official RISC-V architecture ID
constant XLEN : natural := 32; -- native data path width
@ -497,6 +497,7 @@ package neorv32_package is
constant csr_mconfigptr_c : std_ulogic_vector(11 downto 0) := x"f15";
-- NEORV32-specific read-only machine registers --
constant csr_mxisa_c : std_ulogic_vector(11 downto 0) := x"fc0";
--constant csr_mxisah_c : std_ulogic_vector(11 downto 0) := x"fc1"; -- to be implemented...
-- **********************************************************************************************************
-- CPU Control

View file

@ -654,8 +654,11 @@ begin
-- Inter-Core Communication (ICC) Links ---------------------------------------------------
-- -------------------------------------------------------------------------------------------
icc_rx(icc_rx'left) <= icc_tx(icc_tx'right);
icc_rx(icc_rx'right) <= icc_tx(icc_tx'left);
icc_connect: process(icc_tx)
begin
icc_rx(icc_rx'left) <= icc_tx(icc_tx'right);
icc_rx(icc_rx'right) <= icc_tx(icc_tx'left);
end process icc_connect;
-- Core Complex Bus Arbiter ---------------------------------------------------------------

View file

@ -1,7 +1,7 @@
// ================================================================================ //
// The NEORV32 RISC-V Processor - https://github.com/stnolting/neorv32 //
// Copyright (c) NEORV32 contributors. //
// Copyright (c) 2020 - 2024 Stephan Nolting. All rights reserved. //
// Copyright (c) 2020 - 2025 Stephan Nolting. All rights reserved. //
// Licensed under the BSD-3-Clause license, see LICENSE for details. //
// SPDX-License-Identifier: BSD-3-Clause //
// ================================================================================ //

View file

@ -2409,4 +2409,6 @@ int core1_main(void) {
// trigger software interrupt of core0
neorv32_clint_msi_set(0);
return 0;
}

View file

@ -9,7 +9,6 @@
/**
* @file neorv32_aux.h
* @brief General auxiliary functions header file.
* @see https://stnolting.github.io/neorv32/sw/files.html
*/
#ifndef neorv32_aux_h
@ -51,7 +50,7 @@ uint64_t neorv32_aux_hexstr2uint64(char *buffer, unsigned int length);
uint32_t neorv32_aux_xorshift32(void);
void neorv32_aux_itoa(char *buffer, uint32_t num, uint32_t base);
void neorv32_aux_print_hw_config(void);
void neorv32_aux_print_hw_version(void);
void neorv32_aux_print_hw_version(uint32_t impid);
void neorv32_aux_print_about(void);
void neorv32_aux_print_logo(void);
void neorv32_aux_print_license(void);

View file

@ -9,7 +9,6 @@
/**
* @file neorv32_aux.c
* @brief General auxiliary functions source file.
* @see https://stnolting.github.io/neorv32/sw/files.html
*/
#include <neorv32.h>
@ -302,7 +301,7 @@ void neorv32_aux_print_hw_config(void) {
neorv32_cpu_csr_read(CSR_MIMPID));
// hardware version
neorv32_uart0_printf(" (v");
neorv32_aux_print_hw_version();
neorv32_aux_print_hw_version(neorv32_cpu_csr_read(CSR_MIMPID));
neorv32_uart0_printf(")\n");
// CPU architecture and endianness
@ -535,9 +534,12 @@ void neorv32_aux_print_hw_config(void) {
/**********************************************************************//**
* Print the processor version in human-readable format via UART0.
* Print processor version in human-readable format via UART0.
*
* @param[in] impid BCD-coded implementation ID (aka the version),
* typically from the mimpid CSR.
**************************************************************************/
void neorv32_aux_print_hw_version(void) {
void neorv32_aux_print_hw_version(uint32_t impid) {
uint32_t i;
char tmp, cnt;
@ -545,7 +547,7 @@ void neorv32_aux_print_hw_version(void) {
if (neorv32_uart0_available() != 0) { // cannot output anything if UART0 is not implemented
for (i=0; i<4; i++) {
tmp = (char)(neorv32_cpu_csr_read(CSR_MIMPID) >> (24 - 8*i));
tmp = (char)(impid >> (24 - 8*i));
// serial division
cnt = 0;