mirror of
https://github.com/stnolting/neorv32.git
synced 2025-04-19 11:55:05 -04:00
Minor rtl edits and cleanup; 🐛 fix multiple drivers bug (#1151)
This commit is contained in:
commit
01e88db0fd
13 changed files with 121 additions and 112 deletions
|
@ -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) |
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 ---------------------------------------------------------------------------
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
-- ****************************************************************************************************************************
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 ---------------------------------------------------------------
|
||||
|
|
|
@ -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 //
|
||||
// ================================================================================ //
|
||||
|
|
|
@ -2409,4 +2409,6 @@ int core1_main(void) {
|
|||
|
||||
// trigger software interrupt of core0
|
||||
neorv32_clint_msi_set(0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue