Line 7... |
Line 7... |
-- # handling controller and the RISC-V status and control register set (CSRs) including the #
|
-- # handling controller and the RISC-V status and control register set (CSRs) including the #
|
-- # hardware performance monitor counters. #
|
-- # hardware performance monitor counters. #
|
-- # ********************************************************************************************* #
|
-- # ********************************************************************************************* #
|
-- # BSD 3-Clause License #
|
-- # BSD 3-Clause License #
|
-- # #
|
-- # #
|
-- # Copyright (c) 2021, Stephan Nolting. All rights reserved. #
|
-- # Copyright (c) 2022, Stephan Nolting. All rights reserved. #
|
-- # #
|
-- # #
|
-- # Redistribution and use in source and binary forms, with or without modification, are #
|
-- # Redistribution and use in source and binary forms, with or without modification, are #
|
-- # permitted provided that the following conditions are met: #
|
-- # permitted provided that the following conditions are met: #
|
-- # #
|
-- # #
|
-- # 1. Redistributions of source code must retain the above copyright notice, this list of #
|
-- # 1. Redistributions of source code must retain the above copyright notice, this list of #
|
Line 393... |
Line 393... |
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 or fetch_engine.reset;
|
fetch_engine.restart <= fetch_engine.restart_nxt or fetch_engine.reset;
|
if (fetch_engine.restart = '1') then
|
if (fetch_engine.restart = '1') and (fetch_engine.state = IFETCH_REQUEST) then -- only update PC if no fetch request is pending
|
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;
|
end if;
|
end if;
|
Line 419... |
Line 419... |
fetch_engine.restart_nxt <= fetch_engine.restart;
|
fetch_engine.restart_nxt <= fetch_engine.restart;
|
|
|
-- instruction prefetch buffer defaults --
|
-- 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; -- clear instruction buffer while being reset
|
|
|
-- state machine --
|
-- state machine --
|
case fetch_engine.state is
|
case fetch_engine.state is
|
|
|
when IFETCH_REQUEST => -- request new 32-bit-aligned instruction word
|
when IFETCH_REQUEST => -- request new 32-bit-aligned instruction word
|
Line 438... |
Line 438... |
-- ------------------------------------------------------------
|
-- ------------------------------------------------------------
|
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
|
fetch_engine.restart_nxt <= '0';
|
|
fetch_engine.state_nxt <= IFETCH_REQUEST;
|
fetch_engine.state_nxt <= IFETCH_REQUEST;
|
end if;
|
end if;
|
|
|
when others => -- undefined
|
when others => -- undefined
|
-- ------------------------------------------------------------
|
-- ------------------------------------------------------------
|
Line 723... |
Line 722... |
if (execute_engine.state = EXECUTE) then
|
if (execute_engine.state = EXECUTE) then
|
execute_engine.last_pc <= execute_engine.pc;
|
execute_engine.last_pc <= execute_engine.pc;
|
execute_engine.i_reg_last <= execute_engine.i_reg;
|
execute_engine.i_reg_last <= execute_engine.i_reg;
|
end if;
|
end if;
|
|
|
-- next PC --
|
-- next PC logic --
|
case execute_engine.state is
|
case execute_engine.state is
|
when TRAP_ENTER => -- ENTERING trap environment
|
when TRAP_ENTER => -- ENTERING trap environment
|
if (CPU_EXTENSION_RISCV_DEBUG = false) then -- normal trapping
|
if (CPU_EXTENSION_RISCV_DEBUG = false) then -- normal trapping
|
execute_engine.next_pc <= csr.mtvec(data_width_c-1 downto 1) & '0'; -- trap enter
|
execute_engine.next_pc <= csr.mtvec(data_width_c-1 downto 1) & '0'; -- trap enter
|
else -- DEBUG MODE enabled
|
else -- DEBUG MODE enabled
|
Line 2403... |
Line 2402... |
end if;
|
end if;
|
end process hpmcnt_ctrl;
|
end process hpmcnt_ctrl;
|
|
|
-- counter event trigger - RISC-V-specific --
|
-- counter event trigger - RISC-V-specific --
|
cnt_event(hpmcnt_event_cy_c) <= not execute_engine.sleep; -- active cycle
|
cnt_event(hpmcnt_event_cy_c) <= not execute_engine.sleep; -- active cycle
|
cnt_event(hpmcnt_event_never_c) <= '0'; -- undefined (never)
|
cnt_event(hpmcnt_event_never_c) <= '0'; -- "never"
|
cnt_event(hpmcnt_event_ir_c) <= '1' when (execute_engine.state = EXECUTE) else '0'; -- retired instruction
|
cnt_event(hpmcnt_event_ir_c) <= '1' when (execute_engine.state = EXECUTE) else '0'; -- (any) retired instruction
|
|
|
-- counter event trigger - custom / NEORV32-specific --
|
-- counter event trigger - custom / NEORV32-specific --
|
cnt_event(hpmcnt_event_cir_c) <= '1' when (execute_engine.state = EXECUTE) and (execute_engine.is_ci = '1') else '0'; -- retired compressed instruction
|
cnt_event(hpmcnt_event_cir_c) <= '1' when (execute_engine.state = EXECUTE) and (execute_engine.is_ci = '1') else '0'; -- retired compressed instruction
|
cnt_event(hpmcnt_event_wait_if_c) <= '1' when (fetch_engine.state = IFETCH_ISSUE) and (fetch_engine.state_prev = IFETCH_ISSUE) else '0'; -- instruction fetch memory wait cycle
|
cnt_event(hpmcnt_event_wait_if_c) <= '1' when (fetch_engine.state = IFETCH_ISSUE) and (fetch_engine.state_prev = IFETCH_ISSUE) else '0'; -- instruction fetch memory wait cycle
|
cnt_event(hpmcnt_event_wait_ii_c) <= '1' when (execute_engine.state = DISPATCH) and (execute_engine.state_prev = DISPATCH) else '0'; -- instruction issue wait cycle
|
cnt_event(hpmcnt_event_wait_ii_c) <= '1' when (execute_engine.state = DISPATCH) and (execute_engine.state_prev = DISPATCH) else '0'; -- instruction issue wait cycle
|