Line 285... |
Line 285... |
mie_msie : std_ulogic; -- mie.MSIE: machine software interrupt enable (R/W)
|
mie_msie : std_ulogic; -- mie.MSIE: machine software interrupt enable (R/W)
|
mie_meie : std_ulogic; -- mie.MEIE: machine external interrupt enable (R/W)
|
mie_meie : std_ulogic; -- mie.MEIE: machine external interrupt enable (R/W)
|
mie_mtie : std_ulogic; -- mie.MEIE: machine timer interrupt enable (R/W)
|
mie_mtie : std_ulogic; -- mie.MEIE: machine timer interrupt enable (R/W)
|
mie_firqe : std_ulogic_vector(15 downto 0); -- mie.firq*e: fast interrupt enabled (R/W)
|
mie_firqe : std_ulogic_vector(15 downto 0); -- mie.firq*e: fast interrupt enabled (R/W)
|
--
|
--
|
|
mip_clr : std_ulogic_vector(15 downto 0); -- clear pending FIRQ
|
|
--
|
mcounteren_cy : std_ulogic; -- mcounteren.cy: allow cycle[h] access from user-mode
|
mcounteren_cy : std_ulogic; -- mcounteren.cy: allow cycle[h] access from user-mode
|
mcounteren_tm : std_ulogic; -- mcounteren.tm: allow time[h] access from user-mode
|
mcounteren_tm : std_ulogic; -- mcounteren.tm: allow time[h] access from user-mode
|
mcounteren_ir : std_ulogic; -- mcounteren.ir: allow instret[h] access from user-mode
|
mcounteren_ir : std_ulogic; -- mcounteren.ir: allow instret[h] access from user-mode
|
--
|
--
|
mcountinhibit_cy : std_ulogic; -- mcounterinhibit.cy: enable auto-increment for [m]cycle[h]
|
mcountinhibit_cy : std_ulogic; -- mcounterinhibit.cy: enable auto-increment for [m]cycle[h]
|
Line 390... |
Line 392... |
fetch_engine.restart <= '1';
|
fetch_engine.restart <= '1';
|
fetch_engine.pc <= (others => def_rst_val_c);
|
fetch_engine.pc <= (others => def_rst_val_c);
|
elsif rising_edge(clk_i) then
|
elsif rising_edge(clk_i) then
|
fetch_engine.state <= fetch_engine.state_nxt;
|
fetch_engine.state <= fetch_engine.state_nxt;
|
fetch_engine.state_prev <= fetch_engine.state;
|
fetch_engine.state_prev <= fetch_engine.state;
|
fetch_engine.restart <= fetch_engine.restart_nxt;
|
fetch_engine.restart <= fetch_engine.restart_nxt or fetch_engine.reset;
|
if (fetch_engine.restart = '1') then
|
if (fetch_engine.restart = '1') then
|
fetch_engine.pc <= execute_engine.pc(data_width_c-1 downto 1) & '0'; -- initialize with "real" application PC
|
fetch_engine.pc <= execute_engine.pc(data_width_c-1 downto 1) & '0'; -- initialize with "real" application PC
|
else
|
else
|
fetch_engine.pc <= fetch_engine.pc_nxt;
|
fetch_engine.pc <= fetch_engine.pc_nxt;
|
end if;
|
end if;
|
Line 412... |
Line 414... |
-- arbiter defaults --
|
-- arbiter defaults --
|
bus_fast_ir <= '0';
|
bus_fast_ir <= '0';
|
fetch_engine.state_nxt <= fetch_engine.state;
|
fetch_engine.state_nxt <= fetch_engine.state;
|
fetch_engine.pc_nxt <= fetch_engine.pc;
|
fetch_engine.pc_nxt <= fetch_engine.pc;
|
fetch_engine.bus_err_ack <= '0';
|
fetch_engine.bus_err_ack <= '0';
|
fetch_engine.restart_nxt <= fetch_engine.restart or fetch_engine.reset;
|
fetch_engine.restart_nxt <= fetch_engine.restart;
|
|
|
-- instruction prefetch buffer interface --
|
-- instruction prefetch buffer defaults --
|
ipb.we <= '0';
|
ipb.we <= '0';
|
ipb.wdata <= be_instr_i & ma_instr_i & instr_i(31 downto 0); -- store exception info and instruction word
|
ipb.wdata <= be_instr_i & ma_instr_i & instr_i(31 downto 0); -- store exception info and instruction word
|
ipb.clear <= fetch_engine.restart;
|
ipb.clear <= fetch_engine.restart;
|
|
|
-- state machine --
|
-- state machine --
|
Line 428... |
Line 430... |
-- ------------------------------------------------------------
|
-- ------------------------------------------------------------
|
if (ipb.free = '1') and (fetch_engine.restart = '0') then -- free entry in buffer AND no reset request?
|
if (ipb.free = '1') and (fetch_engine.restart = '0') then -- free entry in buffer AND no reset request?
|
bus_fast_ir <= '1'; -- fast instruction fetch request
|
bus_fast_ir <= '1'; -- fast instruction fetch request
|
fetch_engine.state_nxt <= IFETCH_ISSUE;
|
fetch_engine.state_nxt <= IFETCH_ISSUE;
|
end if;
|
end if;
|
if (fetch_engine.restart = '1') then -- reset request?
|
|
fetch_engine.restart_nxt <= '0';
|
fetch_engine.restart_nxt <= '0';
|
end if;
|
|
|
|
when IFETCH_ISSUE => -- store instruction data to prefetch buffer
|
when IFETCH_ISSUE => -- store instruction data to prefetch buffer
|
-- ------------------------------------------------------------
|
-- ------------------------------------------------------------
|
fetch_engine.bus_err_ack <= be_instr_i or ma_instr_i; -- ACK bus/alignment errors
|
fetch_engine.bus_err_ack <= be_instr_i or ma_instr_i; -- ACK bus/alignment errors
|
if (bus_i_wait_i = '0') or (be_instr_i = '1') or (ma_instr_i = '1') then -- wait for bus response
|
if (bus_i_wait_i = '0') or (be_instr_i = '1') or (ma_instr_i = '1') then -- wait for bus response
|
fetch_engine.pc_nxt <= std_ulogic_vector(unsigned(fetch_engine.pc) + 4);
|
fetch_engine.pc_nxt <= std_ulogic_vector(unsigned(fetch_engine.pc) + 4);
|
ipb.we <= not fetch_engine.restart; -- write to IPB if not being reset
|
ipb.we <= not fetch_engine.restart; -- write to IPB if not being reset
|
if (fetch_engine.restart = '1') then -- reset request?
|
|
fetch_engine.restart_nxt <= '0';
|
fetch_engine.restart_nxt <= '0';
|
end if;
|
|
fetch_engine.state_nxt <= IFETCH_REQUEST;
|
fetch_engine.state_nxt <= IFETCH_REQUEST;
|
end if;
|
end if;
|
|
|
when others => -- undefined
|
when others => -- undefined
|
-- ------------------------------------------------------------
|
-- ------------------------------------------------------------
|
Line 502... |
Line 500... |
if (CPU_EXTENSION_RISCV_C = true) and (execute_engine.pc(1) = '1') then -- branch to unaligned address?
|
if (CPU_EXTENSION_RISCV_C = true) and (execute_engine.pc(1) = '1') then -- branch to unaligned address?
|
issue_engine.state <= ISSUE_REALIGN;
|
issue_engine.state <= ISSUE_REALIGN;
|
issue_engine.align <= '1'; -- aligned on 16-bit boundary
|
issue_engine.align <= '1'; -- aligned on 16-bit boundary
|
else
|
else
|
issue_engine.state <= issue_engine.state_nxt;
|
issue_engine.state <= issue_engine.state_nxt;
|
issue_engine.align <= '0'; -- always aligned on 32-bit boundaries
|
issue_engine.align <= '0'; -- aligned on 32-bit boundary
|
end if;
|
end if;
|
else
|
else
|
issue_engine.state <= issue_engine.state_nxt;
|
issue_engine.state <= issue_engine.state_nxt;
|
issue_engine.align <= issue_engine.align_nxt;
|
issue_engine.align <= issue_engine.align_nxt;
|
end if;
|
end if;
|
Line 539... |
Line 537... |
-- ------------------------------------------------------------
|
-- ------------------------------------------------------------
|
if (ipb.avail = '1') then -- instructions available?
|
if (ipb.avail = '1') then -- instructions available?
|
|
|
if (issue_engine.align = '0') or (CPU_EXTENSION_RISCV_C = false) then -- begin check in LOW instruction half-word
|
if (issue_engine.align = '0') or (CPU_EXTENSION_RISCV_C = false) then -- begin check in LOW instruction half-word
|
if (execute_engine.state = DISPATCH) then -- ready to issue new command?
|
if (execute_engine.state = DISPATCH) then -- ready to issue new command?
|
|
ipb.re <= '1';
|
cmd_issue.valid <= '1';
|
cmd_issue.valid <= '1';
|
issue_engine.buf_nxt <= ipb.rdata(33 downto 32) & ipb.rdata(31 downto 16); -- store high half-word - we might need it for an unaligned uncompressed instruction
|
issue_engine.buf_nxt <= ipb.rdata(33 downto 32) & ipb.rdata(31 downto 16); -- store high half-word - we might need it for an unaligned uncompressed instruction
|
if (ipb.rdata(1 downto 0) = "11") or (CPU_EXTENSION_RISCV_C = false) then -- uncompressed and "aligned"
|
if (ipb.rdata(1 downto 0) = "11") or (CPU_EXTENSION_RISCV_C = false) then -- uncompressed and "aligned"
|
ipb.re <= '1';
|
|
cmd_issue.data <= '0' & ipb.rdata(33 downto 32) & '0' & ipb.rdata(31 downto 0);
|
cmd_issue.data <= '0' & ipb.rdata(33 downto 32) & '0' & ipb.rdata(31 downto 0);
|
else -- compressed
|
else -- compressed
|
ipb.re <= '1';
|
|
cmd_issue.data <= ci_illegal & ipb.rdata(33 downto 32) & '1' & ci_instr32;
|
cmd_issue.data <= ci_illegal & ipb.rdata(33 downto 32) & '1' & ci_instr32;
|
issue_engine.align_nxt <= '1';
|
issue_engine.align_nxt <= '1';
|
end if;
|
end if;
|
end if;
|
end if;
|
|
|
Line 785... |
Line 782... |
ctrl_o(ctrl_priv_lvl_msb_c downto ctrl_priv_lvl_lsb_c) <= csr.privilege_rd;
|
ctrl_o(ctrl_priv_lvl_msb_c downto ctrl_priv_lvl_lsb_c) <= csr.privilege_rd;
|
-- register addresses --
|
-- register addresses --
|
ctrl_o(ctrl_rf_rs1_adr4_c downto ctrl_rf_rs1_adr0_c) <= execute_engine.i_reg(instr_rs1_msb_c downto instr_rs1_lsb_c);
|
ctrl_o(ctrl_rf_rs1_adr4_c downto ctrl_rf_rs1_adr0_c) <= execute_engine.i_reg(instr_rs1_msb_c downto instr_rs1_lsb_c);
|
ctrl_o(ctrl_rf_rs2_adr4_c downto ctrl_rf_rs2_adr0_c) <= execute_engine.i_reg(instr_rs2_msb_c downto instr_rs2_lsb_c);
|
ctrl_o(ctrl_rf_rs2_adr4_c downto ctrl_rf_rs2_adr0_c) <= execute_engine.i_reg(instr_rs2_msb_c downto instr_rs2_lsb_c);
|
ctrl_o(ctrl_rf_rd_adr4_c downto ctrl_rf_rd_adr0_c) <= execute_engine.i_reg(instr_rd_msb_c downto instr_rd_lsb_c);
|
ctrl_o(ctrl_rf_rd_adr4_c downto ctrl_rf_rd_adr0_c) <= execute_engine.i_reg(instr_rd_msb_c downto instr_rd_lsb_c);
|
-- fast bus access requests --
|
-- instruction fetch request --
|
ctrl_o(ctrl_bus_if_c) <= bus_fast_ir;
|
ctrl_o(ctrl_bus_if_c) <= bus_fast_ir;
|
-- bus error control --
|
-- bus error control --
|
ctrl_o(ctrl_bus_ierr_ack_c) <= fetch_engine.bus_err_ack; -- instruction fetch bus access error ACK
|
ctrl_o(ctrl_bus_ierr_ack_c) <= fetch_engine.bus_err_ack; -- instruction fetch bus access error ACK
|
ctrl_o(ctrl_bus_derr_ack_c) <= trap_ctrl.env_start_ack; -- data access bus error access ACK
|
ctrl_o(ctrl_bus_derr_ack_c) <= trap_ctrl.env_start_ack; -- data access bus error access ACK
|
-- memory access size / sign --
|
-- memory access size / sign --
|
Line 1038... |
Line 1035... |
ctrl_nxt(ctrl_alu_op2_c downto ctrl_alu_op0_c) <= alu_op_or_c;
|
ctrl_nxt(ctrl_alu_op2_c downto ctrl_alu_op0_c) <= alu_op_or_c;
|
when others => -- AND(I), multi-cycle / co-processor operations
|
when others => -- AND(I), multi-cycle / co-processor operations
|
ctrl_nxt(ctrl_alu_op2_c downto ctrl_alu_op0_c) <= alu_op_and_c;
|
ctrl_nxt(ctrl_alu_op2_c downto ctrl_alu_op0_c) <= alu_op_and_c;
|
end case;
|
end case;
|
|
|
-- Check if single-cycle or multi-cycle (co-processor) operation --
|
-- co-processor MULDIV operation (multi-cycle)? --
|
-- co-processor MULDIV operation? --
|
|
if ((CPU_EXTENSION_RISCV_M = true) and ((decode_aux.is_m_mul = '1') or (decode_aux.is_m_div = '1'))) or -- MUL/DIV
|
if ((CPU_EXTENSION_RISCV_M = true) and ((decode_aux.is_m_mul = '1') or (decode_aux.is_m_div = '1'))) or -- MUL/DIV
|
((CPU_EXTENSION_RISCV_Zmmul = true) and (decode_aux.is_m_mul = '1')) then -- MUL
|
((CPU_EXTENSION_RISCV_Zmmul = true) and (decode_aux.is_m_mul = '1')) then -- MUL
|
ctrl_nxt(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) <= cp_sel_muldiv_c; -- use MULDIV CP
|
ctrl_nxt(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) <= cp_sel_muldiv_c; -- use MULDIV CP
|
ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_copro_c;
|
ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_copro_c;
|
execute_engine.state_nxt <= ALU_WAIT;
|
execute_engine.state_nxt <= ALU_WAIT;
|
-- co-processor BIT-MANIPULATION operation? --
|
-- co-processor BIT-MANIPULATION operation (multi-cycle)? --
|
elsif (CPU_EXTENSION_RISCV_B = true) and
|
elsif (CPU_EXTENSION_RISCV_B = true) and
|
(((execute_engine.i_reg(instr_opcode_lsb_c+5) = opcode_alu_c(5)) and (decode_aux.is_bitmanip_reg = '1')) or -- register operation
|
(((execute_engine.i_reg(instr_opcode_lsb_c+5) = opcode_alu_c(5)) and (decode_aux.is_bitmanip_reg = '1')) or -- register operation
|
((execute_engine.i_reg(instr_opcode_lsb_c+5) = opcode_alui_c(5)) and (decode_aux.is_bitmanip_imm = '1'))) then -- immediate operation
|
((execute_engine.i_reg(instr_opcode_lsb_c+5) = opcode_alui_c(5)) and (decode_aux.is_bitmanip_imm = '1'))) then -- immediate operation
|
ctrl_nxt(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) <= cp_sel_bitmanip_c; -- use BITMANIP CP
|
ctrl_nxt(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) <= cp_sel_bitmanip_c; -- use BITMANIP CP
|
ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_copro_c;
|
ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_copro_c;
|
execute_engine.state_nxt <= ALU_WAIT;
|
execute_engine.state_nxt <= ALU_WAIT;
|
-- co-processor SHIFT operation? --
|
-- co-processor SHIFT operation (multi-cycle)? --
|
elsif (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sll_c) or
|
elsif (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sll_c) or
|
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sr_c) then
|
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sr_c) then
|
ctrl_nxt(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) <= cp_sel_shifter_c; -- use SHIFTER CP (only relevant for shift operations)
|
ctrl_nxt(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) <= cp_sel_shifter_c; -- use SHIFTER CP (only relevant for shift operations)
|
ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_copro_c;
|
ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_copro_c;
|
execute_engine.state_nxt <= ALU_WAIT;
|
execute_engine.state_nxt <= ALU_WAIT;
|
-- ALU core operations (single-cycle) --
|
-- ALU CORE operation (single-cycle) --
|
else
|
else
|
ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_core_c;
|
ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_core_c;
|
ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back
|
ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back
|
execute_engine.state_nxt <= DISPATCH;
|
execute_engine.state_nxt <= DISPATCH;
|
end if;
|
end if;
|
Line 1175... |
Line 1171... |
-- ------------------------------------------------------------
|
-- ------------------------------------------------------------
|
-- CSR write access --
|
-- CSR write access --
|
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrw_c) or
|
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrw_c) or
|
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrwi_c) then -- CSRRW(I)
|
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrwi_c) then -- CSRRW(I)
|
csr.we_nxt <= '1'; -- always write CSR
|
csr.we_nxt <= '1'; -- always write CSR
|
else -- CSRRS(I) / CSRRC(I) [invalid CSR instruction are already checked by the illegal instruction logic]
|
else -- CSRRS(I) / CSRRC(I) [invalid CSR instructions are already checked by the illegal instruction logic]
|
csr.we_nxt <= not decode_aux.rs1_zero; -- write CSR if rs1/imm is not zero
|
csr.we_nxt <= not decode_aux.rs1_zero; -- write CSR if rs1/imm is not zero
|
end if;
|
end if;
|
-- register file write back --
|
-- register file write back --
|
ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_csrr_c;
|
ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_csrr_c;
|
ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back
|
ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back
|
Line 1292... |
Line 1288... |
csr_acc_valid <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zfinx); -- full access for everyone if FPU implemented
|
csr_acc_valid <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zfinx); -- full access for everyone if FPU implemented
|
|
|
-- machine trap setup/handling & counters --
|
-- machine trap setup/handling & counters --
|
when csr_mstatus_c | csr_mstatush_c | csr_misa_c | csr_mie_c | csr_mtvec_c | csr_mscratch_c | csr_mepc_c | csr_mcause_c | csr_mip_c | csr_mtval_c |
|
when csr_mstatus_c | csr_mstatush_c | csr_misa_c | csr_mie_c | csr_mtvec_c | csr_mscratch_c | csr_mepc_c | csr_mcause_c | csr_mip_c | csr_mtval_c |
|
csr_mcycle_c | csr_mcycleh_c | csr_minstret_c | csr_minstreth_c | csr_mcountinhibit_c =>
|
csr_mcycle_c | csr_mcycleh_c | csr_minstret_c | csr_minstreth_c | csr_mcountinhibit_c =>
|
-- NOTE: MISA, MIP and MTVAL are read-only in the NEORV32 but we do not cause an exception here for compatibility.
|
-- NOTE: MISA and MTVAL are read-only in the NEORV32 but we do not cause an exception here for compatibility.
|
-- Machine-level code should read-back those CSRs after writing them to realize they are read-only.
|
-- Machine-level code should read-back those CSRs after writing them to realize they are read-only.
|
csr_acc_valid <= csr.priv_m_mode; -- M-mode only
|
csr_acc_valid <= csr.priv_m_mode; -- M-mode only
|
|
|
-- machine information registers, read-only --
|
-- machine information registers, read-only --
|
when csr_mvendorid_c | csr_marchid_c | csr_mimpid_c | csr_mhartid_c | csr_mconfigptr_c =>
|
when csr_mvendorid_c | csr_marchid_c | csr_mimpid_c | csr_mhartid_c | csr_mconfigptr_c =>
|
Line 1630... |
Line 1626... |
-- interrupt buffer: machine software/external/timer interrupt --
|
-- interrupt buffer: machine software/external/timer interrupt --
|
trap_ctrl.irq_buf(interrupt_msw_irq_c) <= csr.mie_msie and msw_irq_i;
|
trap_ctrl.irq_buf(interrupt_msw_irq_c) <= csr.mie_msie and msw_irq_i;
|
trap_ctrl.irq_buf(interrupt_mext_irq_c) <= csr.mie_meie and mext_irq_i;
|
trap_ctrl.irq_buf(interrupt_mext_irq_c) <= csr.mie_meie and mext_irq_i;
|
trap_ctrl.irq_buf(interrupt_mtime_irq_c) <= csr.mie_mtie and mtime_irq_i;
|
trap_ctrl.irq_buf(interrupt_mtime_irq_c) <= csr.mie_mtie and mtime_irq_i;
|
|
|
-- interrupt buffer: NEORV32-specific fast interrupts (FIRQ) --
|
-- interrupt queue: NEORV32-specific fast interrupts (FIRQ) --
|
trap_ctrl.irq_buf(interrupt_firq_15_c downto interrupt_firq_0_c) <= csr.mie_firqe(15 downto 0) and firq_i(15 downto 0);
|
trap_ctrl.irq_buf(interrupt_firq_15_c downto interrupt_firq_0_c) <= (trap_ctrl.irq_buf(interrupt_firq_15_c downto interrupt_firq_0_c) or (csr.mie_firqe and firq_i)) and (not csr.mip_clr);
|
|
|
-- trap environment control --
|
-- trap environment control --
|
if (trap_ctrl.env_start = '0') then -- no started trap handler
|
if (trap_ctrl.env_start = '0') then -- no started trap handler
|
if (trap_ctrl.exc_fire = '1') or ((trap_ctrl.irq_fire = '1') and -- exception triggered!
|
if (trap_ctrl.exc_fire = '1') or ((trap_ctrl.irq_fire = '1') and -- exception triggered!
|
((execute_engine.state = EXECUTE) or (execute_engine.state = TRAP_ENTER))) then -- fire IRQs in EXECUTE or TRAP state only to continue execution even on permanent IRQ
|
((execute_engine.state = EXECUTE) or (execute_engine.state = TRAP_ENTER))) then -- fire IRQs in EXECUTE or TRAP state only to continue execution even on permanent IRQ
|
Line 1720... |
Line 1716... |
elsif (trap_ctrl.exc_buf(exception_laccess_c) = '1') then
|
elsif (trap_ctrl.exc_buf(exception_laccess_c) = '1') then
|
trap_ctrl.cause_nxt <= trap_lbe_c;
|
trap_ctrl.cause_nxt <= trap_lbe_c;
|
|
|
|
|
-- ----------------------------------------------------------------------------------------
|
-- ----------------------------------------------------------------------------------------
|
-- (re-)enter debug mode requests; basically, these are standard traps that have some
|
-- (re-)enter debug mode requests: basically, these are standard traps that have some
|
-- special handling - they have the highest INTERRUPT priority in order to go to debug when requested
|
-- special handling - they have the highest INTERRUPT priority in order to go to debug when requested
|
-- even if other IRQs are pending right now
|
-- even if other IRQs are pending right now
|
-- ----------------------------------------------------------------------------------------
|
-- ----------------------------------------------------------------------------------------
|
|
|
-- break instruction --
|
-- break instruction --
|
Line 1876... |
Line 1872... |
csr.mtvec <= (others => def_rst_val_c);
|
csr.mtvec <= (others => def_rst_val_c);
|
csr.mscratch <= x"19880704";
|
csr.mscratch <= x"19880704";
|
csr.mepc <= (others => def_rst_val_c);
|
csr.mepc <= (others => def_rst_val_c);
|
csr.mcause <= (others => def_rst_val_c);
|
csr.mcause <= (others => def_rst_val_c);
|
csr.mtval <= (others => def_rst_val_c);
|
csr.mtval <= (others => def_rst_val_c);
|
|
csr.mip_clr <= (others => def_rst_val_c);
|
--
|
--
|
csr.pmpcfg <= (others => (others => '0'));
|
csr.pmpcfg <= (others => (others => '0'));
|
csr.pmpaddr <= (others => (others => def_rst_val_c));
|
csr.pmpaddr <= (others => (others => def_rst_val_c));
|
--
|
--
|
csr.mhpmevent <= (others => (others => def_rst_val_c));
|
csr.mhpmevent <= (others => (others => def_rst_val_c));
|
Line 1905... |
Line 1902... |
|
|
elsif rising_edge(clk_i) then
|
elsif rising_edge(clk_i) then
|
-- write access? --
|
-- write access? --
|
csr.we <= csr.we_nxt;
|
csr.we <= csr.we_nxt;
|
|
|
|
-- defaults --
|
|
csr.mip_clr <= (others => '0');
|
|
|
if (CPU_EXTENSION_RISCV_Zicsr = true) then
|
if (CPU_EXTENSION_RISCV_Zicsr = true) then
|
-- --------------------------------------------------------------------------------
|
-- --------------------------------------------------------------------------------
|
-- CSR access by application software
|
-- CSR access by application software
|
-- --------------------------------------------------------------------------------
|
-- --------------------------------------------------------------------------------
|
if (csr.we = '1') and (trap_ctrl.exc_buf(exception_iillegal_c) = '0') then -- manual write access and not illegal instruction
|
if (csr.we = '1') and (trap_ctrl.exc_buf(exception_iillegal_c) = '0') then -- manual write access and not illegal instruction
|
Line 1963... |
Line 1963... |
end if;
|
end if;
|
end if;
|
end if;
|
|
|
-- machine trap handling --
|
-- machine trap handling --
|
-- --------------------------------------------------------------------
|
-- --------------------------------------------------------------------
|
if (csr.addr(11 downto 3) = csr_class_trap_c) then -- machine trap handling CSR class
|
if (csr.addr(11 downto 4) = csr_class_trap_c) then -- machine trap handling CSR class
|
-- R/W: mscratch - machine scratch register --
|
-- R/W: mscratch - machine scratch register --
|
if (csr.addr(2 downto 0) = csr_mscratch_c(2 downto 0)) then
|
if (csr.addr(3 downto 0) = csr_mscratch_c(3 downto 0)) then
|
csr.mscratch <= csr.wdata;
|
csr.mscratch <= csr.wdata;
|
end if;
|
end if;
|
-- R/W: mepc - machine exception program counter --
|
-- R/W: mepc - machine exception program counter --
|
if (csr.addr(2 downto 0) = csr_mepc_c(2 downto 0)) then
|
if (csr.addr(3 downto 0) = csr_mepc_c(3 downto 0)) then
|
csr.mepc <= csr.wdata;
|
csr.mepc <= csr.wdata;
|
end if;
|
end if;
|
-- R/W: mcause - machine trap cause --
|
-- R/W: mcause - machine trap cause --
|
if (csr.addr(2 downto 0) = csr_mcause_c(2 downto 0)) then
|
if (csr.addr(3 downto 0) = csr_mcause_c(3 downto 0)) then
|
csr.mcause(csr.mcause'left) <= csr.wdata(31); -- 1: async/interrupt, 0: sync/exception
|
csr.mcause(csr.mcause'left) <= csr.wdata(31); -- 1: async/interrupt, 0: sync/exception
|
csr.mcause(4 downto 0) <= csr.wdata(4 downto 0); -- identifier
|
csr.mcause(4 downto 0) <= csr.wdata(4 downto 0); -- identifier
|
end if;
|
end if;
|
|
-- R/W: mip - machine interrupt pending --
|
|
if (csr.addr(3 downto 0) = csr_mip_c(3 downto 0)) then
|
|
csr.mip_clr <= csr.wdata(31 downto 16);
|
|
end if;
|
end if;
|
end if;
|
|
|
-- physical memory protection: R/W: pmpcfg* - PMP configuration registers --
|
-- physical memory protection: R/W: pmpcfg* - PMP configuration registers --
|
-- --------------------------------------------------------------------
|
-- --------------------------------------------------------------------
|
if (PMP_NUM_REGIONS > 0) then
|
if (PMP_NUM_REGIONS > 0) then
|
Line 2489... |
Line 2493... |
when csr_mcause_c => -- mcause (r/w): machine trap cause
|
when csr_mcause_c => -- mcause (r/w): machine trap cause
|
csr.rdata(31) <= csr.mcause(csr.mcause'left);
|
csr.rdata(31) <= csr.mcause(csr.mcause'left);
|
csr.rdata(csr.mcause'left-1 downto 0) <= csr.mcause(csr.mcause'left-1 downto 0);
|
csr.rdata(csr.mcause'left-1 downto 0) <= csr.mcause(csr.mcause'left-1 downto 0);
|
when csr_mtval_c => -- mtval (r/-): machine bad address or instruction
|
when csr_mtval_c => -- mtval (r/-): machine bad address or instruction
|
csr.rdata <= csr.mtval;
|
csr.rdata <= csr.mtval;
|
when csr_mip_c => -- mip (r/-): machine interrupt pending
|
when csr_mip_c => -- mip (r/w): machine interrupt pending
|
csr.rdata(03) <= trap_ctrl.irq_buf(interrupt_msw_irq_c);
|
csr.rdata(03) <= trap_ctrl.irq_buf(interrupt_msw_irq_c);
|
csr.rdata(07) <= trap_ctrl.irq_buf(interrupt_mtime_irq_c);
|
csr.rdata(07) <= trap_ctrl.irq_buf(interrupt_mtime_irq_c);
|
csr.rdata(11) <= trap_ctrl.irq_buf(interrupt_mext_irq_c);
|
csr.rdata(11) <= trap_ctrl.irq_buf(interrupt_mext_irq_c);
|
for i in 0 to 15 loop -- fast interrupt channels 0..15 pending
|
for i in 0 to 15 loop -- fast interrupt channels 0..15 pending
|
csr.rdata(16+i) <= trap_ctrl.irq_buf(interrupt_firq_0_c+i);
|
csr.rdata(16+i) <= trap_ctrl.irq_buf(interrupt_firq_0_c+i);
|