Line 890... |
Line 890... |
NULL;
|
NULL;
|
end case;
|
end case;
|
-- RF write back --
|
-- RF write back --
|
ctrl_nxt(ctrl_rf_in_mux_msb_c downto ctrl_rf_in_mux_lsb_c) <= "11"; -- RF input = CSR output register
|
ctrl_nxt(ctrl_rf_in_mux_msb_c downto ctrl_rf_in_mux_lsb_c) <= "11"; -- RF input = CSR output register
|
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; -- FIXME should be SYS_WAIT? have another cycle to let side-effects kick in
|
|
|
when ALU_WAIT => -- wait for multi-cycle ALU operation to finish
|
when ALU_WAIT => -- wait for multi-cycle ALU operation to finish
|
-- ------------------------------------------------------------
|
-- ------------------------------------------------------------
|
ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_operation_v; -- actual ALU operation
|
ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_operation_v; -- actual ALU operation
|
ctrl_nxt(ctrl_rf_in_mux_msb_c downto ctrl_rf_in_mux_lsb_c) <= "00"; -- RF input = ALU result
|
ctrl_nxt(ctrl_rf_in_mux_msb_c downto ctrl_rf_in_mux_lsb_c) <= "00"; -- RF input = ALU result
|
Line 1197... |
Line 1197... |
begin
|
begin
|
-- defaults --
|
-- defaults --
|
trap_ctrl.cause_nxt <= (others => '0');
|
trap_ctrl.cause_nxt <= (others => '0');
|
trap_ctrl.irq_ack_nxt <= (others => '0');
|
trap_ctrl.irq_ack_nxt <= (others => '0');
|
|
|
|
-- the following traps are caused by asynchronous exceptions (-> interrupts)
|
|
-- here we do need an acknowledge mask since several sources can trigger at once
|
|
|
-- interrupt: 1.11 machine external interrupt --
|
-- interrupt: 1.11 machine external interrupt --
|
if (trap_ctrl.irq_buf(interrupt_mext_irq_c) = '1') then
|
if (trap_ctrl.irq_buf(interrupt_mext_irq_c) = '1') then
|
trap_ctrl.cause_nxt(data_width_c-1) <= '1';
|
trap_ctrl.cause_nxt(data_width_c-1) <= '1';
|
trap_ctrl.cause_nxt(3 downto 0) <= "1011";
|
trap_ctrl.cause_nxt(3 downto 0) <= "1011";
|
trap_ctrl.irq_ack_nxt(interrupt_mext_irq_c) <= '1';
|
trap_ctrl.irq_ack_nxt(interrupt_mext_irq_c) <= '1';
|
Line 1217... |
Line 1220... |
trap_ctrl.cause_nxt(3 downto 0) <= "0011";
|
trap_ctrl.cause_nxt(3 downto 0) <= "0011";
|
trap_ctrl.irq_ack_nxt(interrupt_msw_irq_c) <= '1';
|
trap_ctrl.irq_ack_nxt(interrupt_msw_irq_c) <= '1';
|
|
|
|
|
-- the following traps are caused by synchronous exceptions
|
-- the following traps are caused by synchronous exceptions
|
-- here we do not need an acknowledge mask since only one exception can trigger at the same time
|
-- here we do not need an acknowledge mask since only one exception (the one
|
|
-- with highest priority) can trigger at once
|
|
|
-- trap/fault: 0.0 instruction address misaligned --
|
-- trap/fault: 0.0 instruction address misaligned --
|
elsif (trap_ctrl.exc_buf(exception_ialign_c) = '1') then
|
elsif (trap_ctrl.exc_buf(exception_ialign_c) = '1') then
|
trap_ctrl.cause_nxt(data_width_c-1) <= '0';
|
trap_ctrl.cause_nxt(data_width_c-1) <= '0';
|
trap_ctrl.cause_nxt(3 downto 0) <= "0000";
|
trap_ctrl.cause_nxt(3 downto 0) <= "0000";
|
Line 1319... |
Line 1323... |
if (execute_engine.i_reg(23 downto 20) = x"0") then -- R/W: mstatus - machine status register
|
if (execute_engine.i_reg(23 downto 20) = x"0") then -- R/W: mstatus - machine status register
|
csr.mstatus_mie <= csr_wdata_i(03);
|
csr.mstatus_mie <= csr_wdata_i(03);
|
csr.mstatus_mpie <= csr_wdata_i(07);
|
csr.mstatus_mpie <= csr_wdata_i(07);
|
end if;
|
end if;
|
if (execute_engine.i_reg(23 downto 20) = x"1") then -- R/W: misa - machine instruction set extensions
|
if (execute_engine.i_reg(23 downto 20) = x"1") then -- R/W: misa - machine instruction set extensions
|
csr.misa_c_en <= csr_wdata_i(02); -- C extension enable/disable
|
csr.misa_c_en <= csr_wdata_i(02); -- C extension enable/disable during runtime
|
csr.misa_m_en <= csr_wdata_i(12); -- M extension enable/disable
|
csr.misa_m_en <= csr_wdata_i(12); -- M extension enable/disable during runtime
|
end if;
|
end if;
|
if (execute_engine.i_reg(23 downto 20) = x"4") then -- R/W: mie - machine interrupt-enable register
|
if (execute_engine.i_reg(23 downto 20) = x"4") then -- R/W: mie - machine interrupt-enable register
|
csr.mie_msie <= csr_wdata_i(03); -- SW IRQ enable
|
csr.mie_msie <= csr_wdata_i(03); -- SW IRQ enable
|
csr.mie_mtie <= csr_wdata_i(07); -- TIMER IRQ enable
|
csr.mie_mtie <= csr_wdata_i(07); -- TIMER IRQ enable
|
csr.mie_meie <= csr_wdata_i(11); -- EXT IRQ enable
|
csr.mie_meie <= csr_wdata_i(11); -- EXT IRQ enable
|
Line 1346... |
Line 1350... |
csr.mip_msip <= csr_wdata_i(03); -- manual SW IRQ trigger
|
csr.mip_msip <= csr_wdata_i(03); -- manual SW IRQ trigger
|
end if;
|
end if;
|
end if;
|
end if;
|
|
|
else -- automatic update by hardware
|
else -- automatic update by hardware
|
|
|
-- machine exception PC & exception value register --
|
-- machine exception PC & exception value register --
|
if (trap_ctrl.env_start_ack = '1') then -- trap handler started?
|
if (trap_ctrl.env_start_ack = '1') then -- trap handler started?
|
if (csr.mcause(data_width_c-1) = '1') then -- for INTERRUPTS only (mtval not defined for interrupts)
|
if (csr.mcause(data_width_c-1) = '1') then -- for INTERRUPTS only (mtval not defined for interrupts)
|
csr.mepc <= execute_engine.pc(data_width_c-1 downto 1) & '0'; -- this is the CURRENT pc = interrupted instruction
|
csr.mepc <= execute_engine.pc(data_width_c-1 downto 1) & '0'; -- this is the CURRENT pc = interrupted instruction
|
csr.mtval <= (others => '0');
|
csr.mtval <= (others => '0');
|
else -- for EXCEPTIONs
|
else -- for EXCEPTIONS (according to their priority)
|
csr.mepc <= execute_engine.last_pc(data_width_c-1 downto 1) & '0'; -- this is the LAST pc = last executed instruction
|
csr.mepc <= execute_engine.last_pc(data_width_c-1 downto 1) & '0'; -- this is the LAST pc = last executed instruction
|
if ((trap_ctrl.exc_src(exception_iaccess_c) or trap_ctrl.exc_src(exception_ialign_c)) = '1') then -- instruction access error OR misaligned instruction
|
if ((trap_ctrl.exc_src(exception_iaccess_c) or trap_ctrl.exc_src(exception_ialign_c)) = '1') then -- instruction access error OR misaligned instruction
|
csr.mtval <= execute_engine.pc(data_width_c-1 downto 1) & '0';
|
csr.mtval <= execute_engine.pc(data_width_c-1 downto 1) & '0'; -- address of faulting instruction
|
elsif (trap_ctrl.exc_src(exception_iillegal_c) = '1') then -- illegal instruction
|
elsif (trap_ctrl.exc_src(exception_iillegal_c) = '1') then -- illegal instruction
|
csr.mtval <= execute_engine.i_reg;
|
csr.mtval <= execute_engine.i_reg; -- the faulting instruction itself
|
else -- everything else
|
else -- load/store msialignments/access errors
|
--elsif ((trap_ctrl.exc_src(exception_lalign_c) or trap_ctrl.exc_src(exception_salign_c) or
|
csr.mtval <= mar_i; -- faulting data access address
|
-- trap_ctrl.exc_src(exception_laccess_c) or trap_ctrl.exc_src(exception_saccess_c)) = '1') then -- load/store misaligned / access error
|
|
csr.mtval <= mar_i;
|
|
end if;
|
end if;
|
end if;
|
end if;
|
end if;
|
end if;
|
|
|
-- context switch in mstatus --
|
-- context switch in mstatus --
|
if (trap_ctrl.env_start_ack = '1') then -- actually entering trap
|
if (trap_ctrl.env_start_ack = '1') then -- actually entering trap
|
csr.mstatus_mie <= '0';
|
csr.mstatus_mie <= '0';
|
if (csr.mstatus_mpie = '0') then -- FIXME: prevent loosing the prev MIE state after several traps
|
if (csr.mstatus_mpie = '0') then -- prevent loosing the prev MIE state in nested traps
|
csr.mstatus_mpie <= csr.mstatus_mie;
|
csr.mstatus_mpie <= csr.mstatus_mie;
|
end if;
|
end if;
|
elsif (trap_ctrl.env_end = '1') then -- return from exception
|
elsif (trap_ctrl.env_end = '1') then -- return from exception
|
csr.mstatus_mie <= csr.mstatus_mpie;
|
csr.mstatus_mie <= csr.mstatus_mpie;
|
end if;
|
end if;
|
|
|
end if;
|
end if;
|
end if;
|
end if;
|
end if;
|
end if;
|
end process csr_write_access;
|
end process csr_write_access;
|
|
|