Line 58... |
Line 58... |
CPU_EXTENSION_RISCV_M : boolean := false; -- implement muld/div extension?
|
CPU_EXTENSION_RISCV_M : boolean := false; -- implement muld/div extension?
|
CPU_EXTENSION_RISCV_U : boolean := false; -- implement user mode extension?
|
CPU_EXTENSION_RISCV_U : boolean := false; -- implement user mode extension?
|
CPU_EXTENSION_RISCV_Zfinx : boolean := false; -- implement 32-bit floating-point extension (using INT reg!)
|
CPU_EXTENSION_RISCV_Zfinx : boolean := false; -- implement 32-bit floating-point extension (using INT reg!)
|
CPU_EXTENSION_RISCV_Zicsr : boolean := true; -- implement CSR system?
|
CPU_EXTENSION_RISCV_Zicsr : boolean := true; -- implement CSR system?
|
CPU_EXTENSION_RISCV_Zifencei : boolean := false; -- implement instruction stream sync.?
|
CPU_EXTENSION_RISCV_Zifencei : boolean := false; -- implement instruction stream sync.?
|
|
CPU_EXTENSION_RISCV_Zmmul : boolean := false; -- implement multiply-only M sub-extension?
|
CPU_EXTENSION_RISCV_DEBUG : boolean := false; -- implement CPU debug mode?
|
CPU_EXTENSION_RISCV_DEBUG : boolean := false; -- implement CPU debug mode?
|
-- Extension Options --
|
-- Extension Options --
|
CPU_CNT_WIDTH : natural := 64; -- total width of CPU cycle and instret counters (0..64)
|
CPU_CNT_WIDTH : natural := 64; -- total width of CPU cycle and instret counters (0..64)
|
-- Physical memory protection (PMP) --
|
-- Physical memory protection (PMP) --
|
PMP_NUM_REGIONS : natural := 0; -- number of regions (0..64)
|
PMP_NUM_REGIONS : natural := 0; -- number of regions (0..64)
|
Line 74... |
Line 75... |
-- global control --
|
-- global control --
|
clk_i : in std_ulogic; -- global clock, rising edge
|
clk_i : in std_ulogic; -- global clock, rising edge
|
rstn_i : in std_ulogic; -- global reset, low-active, async
|
rstn_i : in std_ulogic; -- global reset, low-active, async
|
ctrl_o : out std_ulogic_vector(ctrl_width_c-1 downto 0); -- main control bus
|
ctrl_o : out std_ulogic_vector(ctrl_width_c-1 downto 0); -- main control bus
|
-- status input --
|
-- status input --
|
alu_wait_i : in std_ulogic; -- wait for ALU
|
alu_idone_i : in std_ulogic; -- ALU iterative operation done
|
bus_i_wait_i : in std_ulogic; -- wait for bus
|
bus_i_wait_i : in std_ulogic; -- wait for bus
|
bus_d_wait_i : in std_ulogic; -- wait for bus
|
bus_d_wait_i : in std_ulogic; -- wait for bus
|
excl_state_i : in std_ulogic; -- atomic/exclusive access lock status
|
excl_state_i : in std_ulogic; -- atomic/exclusive access lock status
|
-- data input --
|
-- data input --
|
instr_i : in std_ulogic_vector(data_width_c-1 downto 0); -- instruction
|
instr_i : in std_ulogic_vector(data_width_c-1 downto 0); -- instruction
|
Line 89... |
Line 90... |
imm_o : out std_ulogic_vector(data_width_c-1 downto 0); -- immediate
|
imm_o : out std_ulogic_vector(data_width_c-1 downto 0); -- immediate
|
fetch_pc_o : out std_ulogic_vector(data_width_c-1 downto 0); -- PC for instruction fetch
|
fetch_pc_o : out std_ulogic_vector(data_width_c-1 downto 0); -- PC for instruction fetch
|
curr_pc_o : out std_ulogic_vector(data_width_c-1 downto 0); -- current PC (corresponding to current instruction)
|
curr_pc_o : out std_ulogic_vector(data_width_c-1 downto 0); -- current PC (corresponding to current instruction)
|
csr_rdata_o : out std_ulogic_vector(data_width_c-1 downto 0); -- CSR read data
|
csr_rdata_o : out std_ulogic_vector(data_width_c-1 downto 0); -- CSR read data
|
-- FPU interface --
|
-- FPU interface --
|
fpu_rm_o : out std_ulogic_vector(02 downto 0); -- rounding mode
|
|
fpu_flags_i : in std_ulogic_vector(04 downto 0); -- exception flags
|
fpu_flags_i : in std_ulogic_vector(04 downto 0); -- exception flags
|
-- debug mode (halt) request --
|
-- debug mode (halt) request --
|
db_halt_req_i : in std_ulogic;
|
db_halt_req_i : in std_ulogic;
|
-- non-maskable interrupt --
|
-- non-maskable interrupt --
|
nm_irq_i : in std_ulogic;
|
nm_irq_i : in std_ulogic;
|
Line 101... |
Line 101... |
msw_irq_i : in std_ulogic; -- machine software interrupt
|
msw_irq_i : in std_ulogic; -- machine software interrupt
|
mext_irq_i : in std_ulogic; -- machine external interrupt
|
mext_irq_i : in std_ulogic; -- machine external interrupt
|
mtime_irq_i : in std_ulogic; -- machine timer interrupt
|
mtime_irq_i : in std_ulogic; -- machine timer interrupt
|
-- fast interrupts (custom) --
|
-- fast interrupts (custom) --
|
firq_i : in std_ulogic_vector(15 downto 0);
|
firq_i : in std_ulogic_vector(15 downto 0);
|
firq_ack_o : out std_ulogic_vector(15 downto 0);
|
|
-- system time input from MTIME --
|
-- system time input from MTIME --
|
time_i : in std_ulogic_vector(63 downto 0); -- current system time
|
time_i : in std_ulogic_vector(63 downto 0); -- current system time
|
-- physical memory protection --
|
-- physical memory protection --
|
pmp_addr_o : out pmp_addr_if_t; -- addresses
|
pmp_addr_o : out pmp_addr_if_t; -- addresses
|
pmp_ctrl_o : out pmp_ctrl_if_t; -- configs
|
pmp_ctrl_o : out pmp_ctrl_if_t; -- configs
|
Line 143... |
Line 142... |
reset : std_ulogic;
|
reset : std_ulogic;
|
bus_err_ack : std_ulogic;
|
bus_err_ack : std_ulogic;
|
end record;
|
end record;
|
signal fetch_engine : fetch_engine_t;
|
signal fetch_engine : fetch_engine_t;
|
|
|
-- instruction prefetch buffer (IPB, real FIFO) --
|
-- instruction prefetch buffer (FIFO) interface --
|
type ipb_data_fifo_t is array (0 to ipb_entries_c-1) of std_ulogic_vector(2+31 downto 0);
|
|
type ipb_t is record
|
type ipb_t is record
|
wdata : std_ulogic_vector(2+31 downto 0); -- write status (bus_error, align_error) + 32-bit instruction data
|
wdata : std_ulogic_vector(2+31 downto 0); -- write status (bus_error, align_error) + 32-bit instruction data
|
we : std_ulogic; -- trigger write
|
we : std_ulogic; -- trigger write
|
free : std_ulogic; -- free entry available?
|
free : std_ulogic; -- free entry available?
|
clear : std_ulogic; -- clear all entries
|
clear : std_ulogic; -- clear all entries
|
--
|
--
|
rdata : std_ulogic_vector(2+31 downto 0); -- read data: status (bus_error, align_error) + 32-bit instruction data
|
rdata : std_ulogic_vector(2+31 downto 0); -- read data: status (bus_error, align_error) + 32-bit instruction data
|
re : std_ulogic; -- read enable
|
re : std_ulogic; -- read enable
|
avail : std_ulogic; -- data available?
|
avail : std_ulogic; -- data available?
|
--
|
|
w_pnt : std_ulogic_vector(index_size_f(ipb_entries_c) downto 0); -- write pointer
|
|
r_pnt : std_ulogic_vector(index_size_f(ipb_entries_c) downto 0); -- read pointer
|
|
match : std_ulogic;
|
|
empty : std_ulogic;
|
|
full : std_ulogic;
|
|
--
|
|
data : ipb_data_fifo_t; -- fifo memory
|
|
end record;
|
end record;
|
signal ipb : ipb_t;
|
signal ipb : ipb_t;
|
|
|
-- pre-decoder --
|
-- pre-decoder --
|
signal ci_instr16 : std_ulogic_vector(15 downto 0);
|
signal ci_instr16 : std_ulogic_vector(15 downto 0);
|
Line 197... |
Line 187... |
rs1_is_r0 : std_ulogic;
|
rs1_is_r0 : std_ulogic;
|
is_atomic_lr : std_ulogic;
|
is_atomic_lr : std_ulogic;
|
is_atomic_sc : std_ulogic;
|
is_atomic_sc : std_ulogic;
|
is_float_op : std_ulogic;
|
is_float_op : std_ulogic;
|
sys_env_cmd : std_ulogic_vector(11 downto 0);
|
sys_env_cmd : std_ulogic_vector(11 downto 0);
|
|
is_m_mul : std_ulogic;
|
|
is_m_div : std_ulogic;
|
end record;
|
end record;
|
signal decode_aux : decode_aux_t;
|
signal decode_aux : decode_aux_t;
|
|
|
-- instruction execution engine --
|
-- instruction execution engine --
|
type execute_engine_state_t is (SYS_WAIT, DISPATCH, TRAP_ENTER, TRAP_EXIT, TRAP_EXECUTE, EXECUTE, ALU_WAIT, BRANCH,
|
type execute_engine_state_t is (SYS_WAIT, DISPATCH, TRAP_ENTER, TRAP_EXIT, TRAP_EXECUTE, EXECUTE, ALU_WAIT, BRANCH,
|
Line 214... |
Line 206... |
i_reg_nxt : std_ulogic_vector(31 downto 0);
|
i_reg_nxt : std_ulogic_vector(31 downto 0);
|
i_reg_last : std_ulogic_vector(31 downto 0); -- last executed instruction
|
i_reg_last : std_ulogic_vector(31 downto 0); -- last executed instruction
|
--
|
--
|
is_ci : std_ulogic; -- current instruction is de-compressed instruction
|
is_ci : std_ulogic; -- current instruction is de-compressed instruction
|
is_ci_nxt : std_ulogic;
|
is_ci_nxt : std_ulogic;
|
is_cp_op : std_ulogic; -- current instruction is a co-processor operation
|
|
is_cp_op_nxt : std_ulogic;
|
|
--
|
--
|
branch_taken : std_ulogic; -- branch condition fulfilled
|
branch_taken : std_ulogic; -- branch condition fulfilled
|
pc : std_ulogic_vector(data_width_c-1 downto 0); -- actual PC, corresponding to current executed instruction
|
pc : std_ulogic_vector(data_width_c-1 downto 0); -- actual PC, corresponding to current executed instruction
|
pc_mux_sel : std_ulogic; -- source select for PC update
|
pc_mux_sel : std_ulogic; -- source select for PC update
|
pc_we : std_ulogic; -- PC update enabled
|
pc_we : std_ulogic; -- PC update enabled
|
Line 269... |
Line 259... |
-- RISC-V control and status registers (CSRs) --
|
-- RISC-V control and status registers (CSRs) --
|
type pmp_ctrl_t is array (0 to PMP_NUM_REGIONS-1) of std_ulogic_vector(7 downto 0);
|
type pmp_ctrl_t is array (0 to PMP_NUM_REGIONS-1) of std_ulogic_vector(7 downto 0);
|
type pmp_addr_t is array (0 to PMP_NUM_REGIONS-1) of std_ulogic_vector(data_width_c-1 downto 0);
|
type pmp_addr_t is array (0 to PMP_NUM_REGIONS-1) of std_ulogic_vector(data_width_c-1 downto 0);
|
type pmp_ctrl_rd_t is array (0 to 63) of std_ulogic_vector(7 downto 0);
|
type pmp_ctrl_rd_t is array (0 to 63) of std_ulogic_vector(7 downto 0);
|
type mhpmevent_t is array (0 to HPM_NUM_CNTS-1) of std_ulogic_vector(hpmcnt_event_size_c-1 downto 0);
|
type mhpmevent_t is array (0 to HPM_NUM_CNTS-1) of std_ulogic_vector(hpmcnt_event_size_c-1 downto 0);
|
type mhpmcnt_t is array (0 to HPM_NUM_CNTS-1) of std_ulogic_vector(32 downto 0); -- 32-bit, plus 1-bit overflow
|
type mhpmcnt_t is array (0 to HPM_NUM_CNTS-1) of std_ulogic_vector(31 downto 0);
|
type mhpmcnth_t is array (0 to HPM_NUM_CNTS-1) of std_ulogic_vector(31 downto 0); -- 32-bit
|
type mhpmcnt_nxt_t is array (0 to HPM_NUM_CNTS-1) of std_ulogic_vector(32 downto 0);
|
|
type mhpmcnt_ovfl_t is array (0 to HPM_NUM_CNTS-1) of std_ulogic_vector(0 downto 0);
|
type mhpmcnt_rd_t is array (0 to 29) of std_ulogic_vector(31 downto 0);
|
type mhpmcnt_rd_t is array (0 to 29) of std_ulogic_vector(31 downto 0);
|
type mhpmcnth_rd_t is array (0 to 29) of std_ulogic_vector(31 downto 0);
|
|
type csr_t is record
|
type csr_t is record
|
addr : std_ulogic_vector(11 downto 0); -- csr address
|
addr : std_ulogic_vector(11 downto 0); -- csr address
|
we : std_ulogic; -- csr write enable
|
we : std_ulogic; -- csr write enable
|
we_nxt : std_ulogic;
|
we_nxt : std_ulogic;
|
re : std_ulogic; -- csr read enable
|
re : std_ulogic; -- csr read enable
|
Line 294... |
Line 284... |
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)
|
--
|
--
|
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
|
mcounteren_hpm : std_ulogic_vector(HPM_NUM_CNTS-1 downto 0); -- mcounteren.hpmx: allow mhpmcounterx[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]
|
mcountinhibit_ir : std_ulogic; -- mcounterinhibit.ir: enable auto-increment for [m]instret[h]
|
mcountinhibit_ir : std_ulogic; -- mcounterinhibit.ir: enable auto-increment for [m]instret[h]
|
mcountinhibit_hpm : std_ulogic_vector(HPM_NUM_CNTS-1 downto 0); -- mcounterinhibit.hpm3: enable auto-increment for mhpmcounterx[h]
|
mcountinhibit_hpm : std_ulogic_vector(HPM_NUM_CNTS-1 downto 0); -- mcounterinhibit.hpm3: enable auto-increment for mhpmcounterx[h]
|
--
|
--
|
Line 314... |
Line 303... |
--
|
--
|
mhpmevent : mhpmevent_t; -- mhpmevent*: machine performance-monitoring event selector (R/W)
|
mhpmevent : mhpmevent_t; -- mhpmevent*: machine performance-monitoring event selector (R/W)
|
--
|
--
|
mscratch : std_ulogic_vector(data_width_c-1 downto 0); -- mscratch: scratch register (R/W)
|
mscratch : std_ulogic_vector(data_width_c-1 downto 0); -- mscratch: scratch register (R/W)
|
--
|
--
|
mcycle : std_ulogic_vector(32 downto 0); -- mcycle (R/W), plus carry bit
|
mcycle : std_ulogic_vector(31 downto 0); -- mcycle (R/W)
|
mcycle_msb : std_ulogic; -- counter low-to-high-word overflow
|
mcycle_nxt : std_ulogic_vector(32 downto 0);
|
|
mcycle_ovfl : std_ulogic_vector(00 downto 0); -- counter low-to-high-word overflow
|
mcycleh : std_ulogic_vector(31 downto 0); -- mcycleh (R/W)
|
mcycleh : std_ulogic_vector(31 downto 0); -- mcycleh (R/W)
|
minstret : std_ulogic_vector(32 downto 0); -- minstret (R/W), plus carry bit
|
minstret : std_ulogic_vector(31 downto 0); -- minstret (R/W)
|
minstret_msb : std_ulogic; -- counter low-to-high-word overflow
|
minstret_nxt : std_ulogic_vector(32 downto 0);
|
|
minstret_ovfl : std_ulogic_vector(00 downto 0); -- counter low-to-high-word overflow
|
minstreth : std_ulogic_vector(31 downto 0); -- minstreth (R/W)
|
minstreth : std_ulogic_vector(31 downto 0); -- minstreth (R/W)
|
--
|
--
|
mhpmcounter : mhpmcnt_t; -- mhpmcounter* (R/W), plus carry bit
|
mhpmcounter : mhpmcnt_t; -- mhpmcounter* (R/W), plus carry bit
|
mhpmcounter_msb : std_ulogic_vector(HPM_NUM_CNTS-1 downto 0); -- counter low-to-high-word overflow
|
mhpmcounter_nxt : mhpmcnt_nxt_t;
|
mhpmcounterh : mhpmcnth_t; -- mhpmcounter*h (R/W)
|
mhpmcounter_ovfl : mhpmcnt_ovfl_t; -- counter low-to-high-word overflow
|
|
mhpmcounterh : mhpmcnt_t; -- mhpmcounter*h (R/W)
|
mhpmcounter_rd : mhpmcnt_rd_t; -- mhpmcounter* (R/W): actual read data
|
mhpmcounter_rd : mhpmcnt_rd_t; -- mhpmcounter* (R/W): actual read data
|
mhpmcounterh_rd : mhpmcnth_rd_t; -- mhpmcounter*h (R/W): actual read data
|
mhpmcounterh_rd : mhpmcnt_rd_t; -- mhpmcounter*h (R/W): actual read data
|
--
|
--
|
pmpcfg : pmp_ctrl_t; -- physical memory protection - configuration registers
|
pmpcfg : pmp_ctrl_t; -- physical memory protection - configuration registers
|
pmpcfg_rd : pmp_ctrl_rd_t; -- physical memory protection - actual read data
|
pmpcfg_rd : pmp_ctrl_rd_t; -- physical memory protection - actual read data
|
pmpaddr : pmp_addr_t; -- physical memory protection - address registers
|
pmpaddr : pmp_addr_t; -- physical memory protection - address registers
|
--
|
--
|
Line 462... |
Line 454... |
-- Instruction Prefetch Buffer
|
-- Instruction Prefetch Buffer
|
-- ****************************************************************************************************************************
|
-- ****************************************************************************************************************************
|
|
|
-- Instruction Prefetch Buffer (FIFO) -----------------------------------------------------
|
-- Instruction Prefetch Buffer (FIFO) -----------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
instr_prefetch_buffer_ctrl: process(rstn_i, clk_i)
|
instr_prefetch_buffer: neorv32_fifo
|
begin
|
generic map (
|
if (rstn_i = '0') then
|
FIFO_DEPTH => ipb_entries_c, -- number of fifo entries; has to be a power of two; min 1
|
ipb.w_pnt <= (others => def_rst_val_c);
|
FIFO_WIDTH => ipb.wdata'length, -- size of data elements in fifo
|
ipb.r_pnt <= (others => def_rst_val_c);
|
FIFO_RSYNC => false, -- we NEED to read data asynchronously
|
elsif rising_edge(clk_i) then
|
FIFO_SAFE => false -- no safe access required (ensured by FIFO-external control)
|
|
)
|
|
port map (
|
|
-- control --
|
|
clk_i => clk_i, -- clock, rising edge
|
|
rstn_i => '1', -- async reset, low-active
|
|
clear_i => ipb.clear, -- sync reset, high-active
|
-- write port --
|
-- write port --
|
if (ipb.clear = '1') then
|
wdata_i => ipb.wdata, -- write data
|
ipb.w_pnt <= (others => '0');
|
we_i => ipb.we, -- write enable
|
elsif (ipb.we = '1') then
|
free_o => ipb.free, -- at least one entry is free when set
|
ipb.w_pnt <= std_ulogic_vector(unsigned(ipb.w_pnt) + 1);
|
|
end if;
|
|
-- read port --
|
-- read port --
|
if (ipb.clear = '1') then
|
re_i => ipb.re, -- read enable
|
ipb.r_pnt <= (others => '0');
|
rdata_o => ipb.rdata, -- read data
|
elsif (ipb.re = '1') then
|
avail_o => ipb.avail -- data available when set
|
ipb.r_pnt <= std_ulogic_vector(unsigned(ipb.r_pnt) + 1);
|
);
|
end if;
|
|
end if;
|
|
end process instr_prefetch_buffer_ctrl;
|
|
|
|
instr_prefetch_buffer_data: process(clk_i)
|
|
begin
|
|
if rising_edge(clk_i) then
|
|
if (ipb.we = '1') then -- write access
|
|
ipb.data(to_integer(unsigned(ipb.w_pnt(ipb.w_pnt'left-1 downto 0)))) <= ipb.wdata;
|
|
end if;
|
|
end if;
|
|
end process instr_prefetch_buffer_data;
|
|
|
|
-- async read --
|
|
ipb.rdata <= ipb.data(to_integer(unsigned(ipb.r_pnt(ipb.r_pnt'left-1 downto 0))));
|
|
|
|
-- status --
|
|
ipb.match <= '1' when (ipb.r_pnt(ipb.r_pnt'left-1 downto 0) = ipb.w_pnt(ipb.w_pnt'left-1 downto 0)) else '0';
|
|
ipb.full <= '1' when (ipb.r_pnt(ipb.r_pnt'left) /= ipb.w_pnt(ipb.w_pnt'left)) and (ipb.match = '1') else '0';
|
|
ipb.empty <= '1' when (ipb.r_pnt(ipb.r_pnt'left) = ipb.w_pnt(ipb.w_pnt'left)) and (ipb.match = '1') else '0';
|
|
ipb.free <= not ipb.full;
|
|
ipb.avail <= not ipb.empty;
|
|
|
|
|
|
-- ****************************************************************************************************************************
|
-- ****************************************************************************************************************************
|
-- Instruction Issue (recoding of compressed instructions and 32-bit instruction word construction)
|
-- Instruction Issue (recoding of compressed instructions and 32-bit instruction word construction)
|
-- ****************************************************************************************************************************
|
-- ****************************************************************************************************************************
|
Line 717... |
Line 691... |
execute_engine.branched <= '1'; -- reset is a branch from "somewhere"
|
execute_engine.branched <= '1'; -- reset is a branch from "somewhere"
|
-- no dedicated RESET required --
|
-- no dedicated RESET required --
|
execute_engine.state_prev <= SYS_WAIT;
|
execute_engine.state_prev <= SYS_WAIT;
|
execute_engine.i_reg <= (others => def_rst_val_c);
|
execute_engine.i_reg <= (others => def_rst_val_c);
|
execute_engine.is_ci <= def_rst_val_c;
|
execute_engine.is_ci <= def_rst_val_c;
|
execute_engine.is_cp_op <= def_rst_val_c;
|
|
execute_engine.last_pc <= (others => def_rst_val_c);
|
execute_engine.last_pc <= (others => def_rst_val_c);
|
execute_engine.i_reg_last <= (others => def_rst_val_c);
|
execute_engine.i_reg_last <= (others => def_rst_val_c);
|
execute_engine.next_pc <= (others => def_rst_val_c);
|
execute_engine.next_pc <= (others => def_rst_val_c);
|
ctrl <= (others => def_rst_val_c);
|
ctrl <= (others => def_rst_val_c);
|
--
|
--
|
Line 736... |
Line 709... |
execute_engine.pc <= alu_add_i(data_width_c-1 downto 1) & '0'; -- jump/taken_branch
|
execute_engine.pc <= alu_add_i(data_width_c-1 downto 1) & '0'; -- jump/taken_branch
|
end if;
|
end if;
|
end if;
|
end if;
|
--
|
--
|
execute_engine.state <= execute_engine.state_nxt;
|
execute_engine.state <= execute_engine.state_nxt;
|
execute_engine.sleep <= execute_engine.sleep_nxt;
|
execute_engine.sleep <= execute_engine.sleep_nxt and (not debug_ctrl.running); -- do not execute when in debug mode
|
execute_engine.branched <= execute_engine.branched_nxt;
|
execute_engine.branched <= execute_engine.branched_nxt;
|
--
|
--
|
execute_engine.state_prev <= execute_engine.state;
|
execute_engine.state_prev <= execute_engine.state;
|
execute_engine.i_reg <= execute_engine.i_reg_nxt;
|
execute_engine.i_reg <= execute_engine.i_reg_nxt;
|
execute_engine.is_ci <= execute_engine.is_ci_nxt;
|
execute_engine.is_ci <= execute_engine.is_ci_nxt;
|
execute_engine.is_cp_op <= execute_engine.is_cp_op_nxt;
|
|
|
|
-- PC & IR of "last executed" instruction --
|
-- PC & IR of "last executed" instruction --
|
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;
|
Line 827... |
Line 799... |
if (CPU_EXTENSION_RISCV_DEBUG = true) then
|
if (CPU_EXTENSION_RISCV_DEBUG = true) then
|
ctrl_o(ctrl_debug_running_c) <= debug_ctrl.running; -- cpu is currently in debug mode
|
ctrl_o(ctrl_debug_running_c) <= debug_ctrl.running; -- cpu is currently in debug mode
|
else
|
else
|
ctrl_o(ctrl_debug_running_c) <= '0';
|
ctrl_o(ctrl_debug_running_c) <= '0';
|
end if;
|
end if;
|
|
-- FPU rounding mode --
|
|
ctrl_o(ctrl_alu_frm2_c downto ctrl_alu_frm0_c) <= csr.frm;
|
end process ctrl_output;
|
end process ctrl_output;
|
|
|
|
|
-- Decoding Helper Logic ------------------------------------------------------------------
|
-- Decoding Helper Logic ------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
Line 841... |
Line 815... |
decode_aux.alu_immediate <= '0';
|
decode_aux.alu_immediate <= '0';
|
decode_aux.rs1_is_r0 <= '0';
|
decode_aux.rs1_is_r0 <= '0';
|
decode_aux.is_atomic_lr <= '0';
|
decode_aux.is_atomic_lr <= '0';
|
decode_aux.is_atomic_sc <= '0';
|
decode_aux.is_atomic_sc <= '0';
|
decode_aux.is_float_op <= '0';
|
decode_aux.is_float_op <= '0';
|
|
decode_aux.is_m_mul <= '0';
|
|
decode_aux.is_m_div <= '0';
|
|
|
-- is immediate ALU operation? --
|
-- is immediate ALU operation? --
|
decode_aux.alu_immediate <= not execute_engine.i_reg(instr_opcode_msb_c-1);
|
decode_aux.alu_immediate <= not execute_engine.i_reg(instr_opcode_msb_c-1);
|
|
|
-- is rs1 == r0? --
|
-- is rs1 == r0? --
|
Line 869... |
Line 845... |
end if;
|
end if;
|
|
|
-- system/environment instructions --
|
-- system/environment instructions --
|
sys_env_cmd_mask_v := funct12_ecall_c or funct12_ebreak_c or funct12_mret_c or funct12_wfi_c or funct12_dret_c; -- sum-up set bits
|
sys_env_cmd_mask_v := funct12_ecall_c or funct12_ebreak_c or funct12_mret_c or funct12_wfi_c or funct12_dret_c; -- sum-up set bits
|
decode_aux.sys_env_cmd <= execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) and sys_env_cmd_mask_v; -- set unused bits to always-zero
|
decode_aux.sys_env_cmd <= execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) and sys_env_cmd_mask_v; -- set unused bits to always-zero
|
|
|
|
-- integer MUL (M/Zmmul) / DIV (M) operation --
|
|
if (execute_engine.i_reg(instr_opcode_lsb_c+5) = opcode_alu_c(5)) and
|
|
(execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0000001") then
|
|
decode_aux.is_m_mul <= not execute_engine.i_reg(instr_funct3_msb_c);
|
|
decode_aux.is_m_div <= execute_engine.i_reg(instr_funct3_msb_c);
|
|
end if;
|
end process decode_helper;
|
end process decode_helper;
|
|
|
|
|
-- Execute Engine FSM Comb ----------------------------------------------------------------
|
-- Execute Engine FSM Comb ----------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
execute_engine_fsm_comb: process(execute_engine, debug_ctrl, decode_aux, fetch_engine, cmd_issue, trap_ctrl, csr, ctrl, csr_acc_valid,
|
execute_engine_fsm_comb: process(execute_engine, debug_ctrl, trap_ctrl, decode_aux, fetch_engine, cmd_issue,
|
alu_wait_i, bus_d_wait_i, ma_load_i, be_load_i, ma_store_i, be_store_i, excl_state_i)
|
csr, ctrl, csr_acc_valid, alu_idone_i, bus_d_wait_i, excl_state_i)
|
variable opcode_v : std_ulogic_vector(6 downto 0);
|
variable opcode_v : std_ulogic_vector(6 downto 0);
|
begin
|
begin
|
-- arbiter defaults --
|
-- arbiter defaults --
|
execute_engine.state_nxt <= execute_engine.state;
|
execute_engine.state_nxt <= execute_engine.state;
|
execute_engine.i_reg_nxt <= execute_engine.i_reg;
|
execute_engine.i_reg_nxt <= execute_engine.i_reg;
|
execute_engine.is_cp_op_nxt <= execute_engine.is_cp_op;
|
|
execute_engine.is_ci_nxt <= execute_engine.is_ci;
|
execute_engine.is_ci_nxt <= execute_engine.is_ci;
|
execute_engine.sleep_nxt <= execute_engine.sleep;
|
execute_engine.sleep_nxt <= execute_engine.sleep;
|
execute_engine.branched_nxt <= execute_engine.branched;
|
execute_engine.branched_nxt <= execute_engine.branched;
|
--
|
--
|
execute_engine.pc_mux_sel <= '0';
|
execute_engine.pc_mux_sel <= '0';
|
Line 937... |
Line 919... |
|
|
when SYS_WAIT => -- System delay cycle (used to wait for side effects to kick in) [and to init r0 with zero if it is a physical register]
|
when SYS_WAIT => -- System delay cycle (used to wait for side effects to kick in) [and to init r0 with zero if it is a physical register]
|
-- ------------------------------------------------------------
|
-- ------------------------------------------------------------
|
-- set reg_file's r0 to zero --
|
-- set reg_file's r0 to zero --
|
if (rf_r0_is_reg_c = true) then -- is r0 implemented as physical register, which has to be set to zero?
|
if (rf_r0_is_reg_c = true) then -- is r0 implemented as physical register, which has to be set to zero?
|
ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_copro_c; -- hacky! CSR read-access CP selected without a valid CSR-read -> results zero
|
ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_csrr_c; -- hacky! CSR read-access without a valid CSR-read -> results zero
|
ctrl_nxt(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) <= cp_sel_csr_rd_c; -- use CSR-READ CP
|
|
ctrl_nxt(ctrl_rf_r0_we_c) <= '1'; -- force RF write access and force rd=r0
|
ctrl_nxt(ctrl_rf_r0_we_c) <= '1'; -- force RF write access and force rd=r0
|
end if;
|
end if;
|
--
|
--
|
execute_engine.state_nxt <= DISPATCH;
|
execute_engine.state_nxt <= DISPATCH;
|
|
|
|
|
when DISPATCH => -- Get new command from instruction issue engine
|
when DISPATCH => -- Get new command from instruction issue engine
|
-- ------------------------------------------------------------
|
-- ------------------------------------------------------------
|
-- housekeeping --
|
|
execute_engine.is_cp_op_nxt <= '0'; -- no co-processor operation yet
|
|
-- PC update --
|
-- PC update --
|
execute_engine.pc_mux_sel <= '0'; -- linear next PC
|
execute_engine.pc_mux_sel <= '0'; -- linear next PC
|
-- IR update --
|
-- IR update --
|
execute_engine.is_ci_nxt <= cmd_issue.data(32); -- flag to indicate a de-compressed instruction
|
execute_engine.is_ci_nxt <= cmd_issue.data(32); -- flag to indicate a de-compressed instruction
|
execute_engine.i_reg_nxt <= cmd_issue.data(31 downto 0);
|
execute_engine.i_reg_nxt <= cmd_issue.data(31 downto 0);
|
Line 964... |
Line 943... |
-- IR update - exceptions --
|
-- IR update - exceptions --
|
trap_ctrl.instr_ma <= cmd_issue.data(33); -- misaligned instruction fetch address
|
trap_ctrl.instr_ma <= cmd_issue.data(33); -- misaligned instruction fetch address
|
trap_ctrl.instr_be <= cmd_issue.data(34); -- bus access fault during instruction fetch
|
trap_ctrl.instr_be <= cmd_issue.data(34); -- bus access fault during instruction fetch
|
illegal_compressed <= cmd_issue.data(35); -- invalid decompressed instruction
|
illegal_compressed <= cmd_issue.data(35); -- invalid decompressed instruction
|
-- any reason to go to trap state? --
|
-- any reason to go to trap state? --
|
if (execute_engine.sleep = '1') or (trap_ctrl.env_start = '1') or (trap_ctrl.exc_fire = '1') or ((cmd_issue.data(33) or cmd_issue.data(34)) = '1') then
|
if (execute_engine.sleep = '1') or -- WFI instruction - this will enter sleep state
|
|
(trap_ctrl.env_start = '1') or -- pending trap (IRQ or exception)
|
|
((cmd_issue.data(33) or cmd_issue.data(34)) = '1') then -- exception during instruction fetch of the CURRENT instruction
|
execute_engine.state_nxt <= TRAP_ENTER;
|
execute_engine.state_nxt <= TRAP_ENTER;
|
else
|
else
|
execute_engine.state_nxt <= EXECUTE;
|
execute_engine.state_nxt <= EXECUTE;
|
end if;
|
end if;
|
end if;
|
end if;
|
Line 984... |
Line 965... |
when TRAP_EXIT => -- Return from trap environment - get EPC
|
when TRAP_EXIT => -- Return from trap environment - get EPC
|
-- ------------------------------------------------------------
|
-- ------------------------------------------------------------
|
trap_ctrl.env_end <= '1';
|
trap_ctrl.env_end <= '1';
|
execute_engine.state_nxt <= TRAP_EXECUTE;
|
execute_engine.state_nxt <= TRAP_EXECUTE;
|
|
|
when TRAP_EXECUTE => -- Start trap environment -> jump to TVEC / return from trap environment -> jump to EPC
|
when TRAP_EXECUTE => -- Start trap environment -> jump to *TVEC / return from trap environment -> jump to EPC
|
-- ------------------------------------------------------------
|
-- ------------------------------------------------------------
|
execute_engine.pc_mux_sel <= '0'; -- next_PC
|
execute_engine.pc_mux_sel <= '0'; -- next_PC
|
fetch_engine.reset <= '1';
|
fetch_engine.reset <= '1';
|
execute_engine.pc_we <= '1';
|
execute_engine.pc_we <= '1';
|
execute_engine.sleep_nxt <= '0'; -- disable sleep mode
|
execute_engine.sleep_nxt <= '0'; -- disable sleep mode
|
Line 1029... |
Line 1010... |
when funct3_or_c => ctrl_nxt(ctrl_alu_logic1_c downto ctrl_alu_logic0_c) <= alu_logic_cmd_or_c; -- OR(I)
|
when funct3_or_c => ctrl_nxt(ctrl_alu_logic1_c downto ctrl_alu_logic0_c) <= alu_logic_cmd_or_c; -- OR(I)
|
when others => ctrl_nxt(ctrl_alu_logic1_c downto ctrl_alu_logic0_c) <= alu_logic_cmd_and_c; -- AND(I)
|
when others => ctrl_nxt(ctrl_alu_logic1_c downto ctrl_alu_logic0_c) <= alu_logic_cmd_and_c; -- AND(I)
|
end case;
|
end case;
|
|
|
-- co-processor MULDIV operation? --
|
-- co-processor MULDIV operation? --
|
if (CPU_EXTENSION_RISCV_M = true) and (execute_engine.i_reg(instr_opcode_lsb_c+5) = opcode_alu_c(5)) and (execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0000001") then -- MULDIV CP op?
|
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
|
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
|
execute_engine.is_cp_op_nxt <= '1'; -- this is a CP operation
|
|
ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_copro_c;
|
ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_copro_c;
|
-- ALU operation, function select --
|
|
else
|
else
|
execute_engine.is_cp_op_nxt <= '0'; -- no CP operation
|
-- ALU operation, function select --
|
case execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) is -- actual ALU.func operation (re-coding)
|
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)
|
when funct3_xor_c | funct3_or_c | funct3_and_c => ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_logic_c;
|
case execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) is
|
when funct3_sll_c | funct3_sr_c => ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_shift_c;
|
when funct3_sll_c | funct3_sr_c => -- SHIFT operation
|
when others => ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_arith_c;
|
ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_copro_c;
|
|
when funct3_xor_c | funct3_or_c | funct3_and_c => -- LOGIC operation
|
|
ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_logic_c;
|
|
when others => -- ARITHMETIC operation
|
|
ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_arith_c;
|
end case;
|
end case;
|
end if;
|
end if;
|
|
|
-- multi cycle ALU operation? --
|
-- multi cycle ALU operation? --
|
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sll_c) or -- SLL shift operation?
|
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sll_c) or -- SLL shift operation?
|
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sr_c) or -- SR shift operation?
|
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sr_c) or -- SR shift operation?
|
((CPU_EXTENSION_RISCV_M = true) and (execute_engine.i_reg(instr_opcode_lsb_c+5) = opcode_alu_c(5)) and (execute_engine.i_reg(instr_funct7_lsb_c) = '1')) then -- MULDIV CP op?
|
((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
|
execute_engine.state_nxt <= ALU_WAIT;
|
execute_engine.state_nxt <= ALU_WAIT;
|
else -- single cycle ALU operation
|
else -- single cycle ALU operation
|
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 1105... |
Line 1090... |
|
|
when opcode_syscsr_c => -- system/csr access
|
when opcode_syscsr_c => -- system/csr access
|
-- ------------------------------------------------------------
|
-- ------------------------------------------------------------
|
if (CPU_EXTENSION_RISCV_Zicsr = true) then
|
if (CPU_EXTENSION_RISCV_Zicsr = true) then
|
csr.re_nxt <= csr_acc_valid; -- always read CSR if valid access, only relevant for CSR-instructions
|
csr.re_nxt <= csr_acc_valid; -- always read CSR if valid access, only relevant for CSR-instructions
|
ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_copro_c; -- only relevant for CSR-instructions
|
|
ctrl_nxt(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) <= cp_sel_csr_rd_c; -- use CSR-READ CP, only relevant for CSR-instructions
|
|
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_env_c) then -- system/environment
|
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_env_c) then -- system/environment
|
execute_engine.state_nxt <= SYS_ENV;
|
execute_engine.state_nxt <= SYS_ENV;
|
else -- CSR access
|
else -- CSR access
|
execute_engine.state_nxt <= CSR_ACCESS;
|
execute_engine.state_nxt <= CSR_ACCESS;
|
end if;
|
end if;
|
Line 1119... |
Line 1102... |
end if;
|
end if;
|
|
|
when opcode_fop_c => -- floating-point operations
|
when opcode_fop_c => -- floating-point operations
|
-- ------------------------------------------------------------
|
-- ------------------------------------------------------------
|
if (CPU_EXTENSION_RISCV_Zfinx = true) and (decode_aux.is_float_op = '1') then
|
if (CPU_EXTENSION_RISCV_Zfinx = true) and (decode_aux.is_float_op = '1') then
|
ctrl_nxt(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) <= cp_sel_fpu_c; -- use FPU CP
|
ctrl_nxt(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) <= cp_sel_fpu_c; -- trigger FPU CP
|
execute_engine.is_cp_op_nxt <= '1'; -- this is a CP operation
|
|
ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_copro_c;
|
ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_copro_c;
|
execute_engine.state_nxt <= ALU_WAIT;
|
execute_engine.state_nxt <= ALU_WAIT;
|
else
|
else
|
execute_engine.state_nxt <= SYS_WAIT;
|
execute_engine.state_nxt <= SYS_WAIT;
|
end if;
|
end if;
|
Line 1141... |
Line 1123... |
execute_engine.state_nxt <= SYS_WAIT;
|
execute_engine.state_nxt <= SYS_WAIT;
|
case decode_aux.sys_env_cmd is -- use a simplified input here (with permanent zeros)
|
case decode_aux.sys_env_cmd is -- use a simplified input here (with permanent zeros)
|
when funct12_ecall_c => trap_ctrl.env_call <= '1'; -- ECALL
|
when funct12_ecall_c => trap_ctrl.env_call <= '1'; -- ECALL
|
when funct12_ebreak_c => trap_ctrl.break_point <= '1'; -- EBREAK
|
when funct12_ebreak_c => trap_ctrl.break_point <= '1'; -- EBREAK
|
when funct12_mret_c => execute_engine.state_nxt <= TRAP_EXIT; -- MRET
|
when funct12_mret_c => execute_engine.state_nxt <= TRAP_EXIT; -- MRET
|
when funct12_wfi_c => -- WFI
|
when funct12_wfi_c => execute_engine.sleep_nxt <= '1'; -- WFI
|
if (CPU_EXTENSION_RISCV_DEBUG = true) and (debug_ctrl.running = '1') then
|
|
NULL; -- just a NOP when in debug mode
|
|
else
|
|
execute_engine.sleep_nxt <= '1'; -- WFI (normal)
|
|
end if;
|
|
when funct12_dret_c => -- DRET
|
when funct12_dret_c => -- DRET
|
if (CPU_EXTENSION_RISCV_DEBUG = true) then
|
if (CPU_EXTENSION_RISCV_DEBUG = true) then
|
execute_engine.state_nxt <= TRAP_EXIT;
|
execute_engine.state_nxt <= TRAP_EXIT;
|
debug_ctrl.dret <= '1';
|
debug_ctrl.dret <= '1';
|
else
|
else
|
Line 1170... |
Line 1147... |
csr.we_nxt <= (not decode_aux.rs1_is_r0) and csr_acc_valid; -- write CSR if rs1/imm is not zero and if valid access
|
csr.we_nxt <= (not decode_aux.rs1_is_r0) and csr_acc_valid; -- write CSR if rs1/imm is not zero and if valid access
|
when others => -- invalid
|
when others => -- invalid
|
csr.we_nxt <= '0';
|
csr.we_nxt <= '0';
|
end case;
|
end case;
|
-- register file write back --
|
-- register file write back --
|
ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_copro_c;
|
ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_csrr_c;
|
ctrl_nxt(ctrl_rf_in_mux_c) <= '0'; -- RF input = ALU result
|
ctrl_nxt(ctrl_rf_in_mux_c) <= '0'; -- RF input = ALU result
|
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;
|
|
|
|
|
when ALU_WAIT => -- wait for multi-cycle ALU operation (shifter or CP) to finish
|
when ALU_WAIT => -- wait for multi-cycle ALU operation (co-processor) to finish
|
-- ------------------------------------------------------------
|
-- ------------------------------------------------------------
|
ctrl_nxt(ctrl_rf_in_mux_c) <= '0'; -- RF input = ALU result
|
ctrl_nxt(ctrl_rf_in_mux_c) <= '0'; -- RF input = ALU result
|
-- cp access or alu.shift? --
|
|
if (execute_engine.is_cp_op = '1') then
|
|
ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_copro_c;
|
ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_copro_c;
|
else
|
|
ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_shift_c;
|
|
end if;
|
|
-- wait for result --
|
-- wait for result --
|
if (alu_wait_i = '0') then
|
if (alu_idone_i = '1') then -- done
|
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 1237... |
Line 1209... |
-- ------------------------------------------------------------
|
-- ------------------------------------------------------------
|
ctrl_nxt(ctrl_bus_lock_c) <= decode_aux.is_atomic_lr; -- atomic.LR: set lock
|
ctrl_nxt(ctrl_bus_lock_c) <= decode_aux.is_atomic_lr; -- atomic.LR: set lock
|
if (execute_engine.i_reg(instr_opcode_msb_c-1) = '0') or (decode_aux.is_atomic_lr = '1') then -- normal load or atomic load-reservate
|
if (execute_engine.i_reg(instr_opcode_msb_c-1) = '0') or (decode_aux.is_atomic_lr = '1') then -- normal load or atomic load-reservate
|
ctrl_nxt(ctrl_bus_rd_c) <= '1'; -- read request
|
ctrl_nxt(ctrl_bus_rd_c) <= '1'; -- read request
|
else -- store
|
else -- store
|
if (CPU_EXTENSION_RISCV_A = true) and (decode_aux.is_atomic_sc = '1') then -- evaluate lock state
|
if (decode_aux.is_atomic_sc = '1') then -- evaluate lock state
|
if (excl_state_i = '1') then -- lock is still ok - perform write access
|
if (excl_state_i = '1') then -- lock is still ok - perform write access
|
ctrl_nxt(ctrl_bus_wr_c) <= '1'; -- write request
|
ctrl_nxt(ctrl_bus_wr_c) <= '1'; -- write request
|
end if;
|
end if;
|
else
|
else
|
ctrl_nxt(ctrl_bus_wr_c) <= '1'; -- (normal) write request
|
ctrl_nxt(ctrl_bus_wr_c) <= '1'; -- (normal) write request
|
end if;
|
end if;
|
end if;
|
end if;
|
execute_engine.state_nxt <= LOADSTORE_1;
|
execute_engine.state_nxt <= LOADSTORE_1;
|
|
|
|
|
when LOADSTORE_1 => -- memory latency
|
when LOADSTORE_1 => -- memory access latency
|
-- ------------------------------------------------------------
|
-- ------------------------------------------------------------
|
ctrl_nxt(ctrl_bus_mi_we_c) <= '1'; -- write input data to MDI (only relevant for LOAD)
|
ctrl_nxt(ctrl_bus_mi_we_c) <= '1'; -- write input data to MDI (only relevant for LOADs)
|
execute_engine.state_nxt <= LOADSTORE_2;
|
execute_engine.state_nxt <= LOADSTORE_2;
|
|
|
|
|
when LOADSTORE_2 => -- wait for bus transaction to finish
|
when LOADSTORE_2 => -- wait for bus transaction to finish
|
-- ------------------------------------------------------------
|
-- ------------------------------------------------------------
|
ctrl_nxt(ctrl_bus_mi_we_c) <= '1'; -- keep writing input data to MDI (only relevant for load (and SC.W) operations)
|
ctrl_nxt(ctrl_bus_mi_we_c) <= '1'; -- keep writing input data to MDI (only relevant for load (and SC.W) operations)
|
ctrl_nxt(ctrl_rf_in_mux_c) <= '1'; -- RF input = memory input (only relevant for LOADs)
|
ctrl_nxt(ctrl_rf_in_mux_c) <= '1'; -- RF input = memory input (only relevant for LOADs)
|
-- wait for memory response --
|
-- wait for memory response / exception --
|
if ((ma_load_i or be_load_i or ma_store_i or be_store_i) = '1') then -- abort if exception
|
if (trap_ctrl.env_start = '1') then -- abort if exception
|
execute_engine.state_nxt <= DISPATCH;
|
execute_engine.state_nxt <= SYS_WAIT;
|
elsif (bus_d_wait_i = '0') then -- wait for bus to finish transaction
|
elsif (bus_d_wait_i = '0') then -- wait for bus to finish transaction
|
-- remove atomic lock if this is NOT the LR.W instruction used to SET the lock --
|
|
if (CPU_EXTENSION_RISCV_A = true) and (decode_aux.is_atomic_lr = '0') then -- execute and evaluate atomic store-conditional
|
|
ctrl_nxt(ctrl_bus_de_lock_c) <= '1';
|
|
end if;
|
|
-- data write-back --
|
-- data write-back --
|
if (execute_engine.i_reg(instr_opcode_msb_c-1) = '0') or -- normal load
|
if (execute_engine.i_reg(instr_opcode_msb_c-1) = '0') or -- normal load
|
(decode_aux.is_atomic_lr = '1') or -- atomic load-reservate
|
(decode_aux.is_atomic_lr = '1') or -- atomic load-reservate
|
(decode_aux.is_atomic_sc = '1') then -- atomic store-conditional
|
(decode_aux.is_atomic_sc = '1') then -- atomic store-conditional
|
ctrl_nxt(ctrl_rf_wb_en_c) <= '1';
|
ctrl_nxt(ctrl_rf_wb_en_c) <= '1';
|
end if;
|
end if;
|
|
-- remove atomic lock if this is NOT the LR.W instruction used to SET the lock --
|
|
if (decode_aux.is_atomic_lr = '0') then -- execute and evaluate atomic store-conditional
|
|
ctrl_nxt(ctrl_bus_de_lock_c) <= '1';
|
|
end if;
|
execute_engine.state_nxt <= DISPATCH;
|
execute_engine.state_nxt <= DISPATCH;
|
end if;
|
end if;
|
|
|
|
|
when others => -- undefined
|
when others => -- undefined
|
Line 1292... |
Line 1264... |
|
|
-- CSR Access Check -----------------------------------------------------------------------
|
-- CSR Access Check -----------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
csr_access_check: process(execute_engine.i_reg, csr, debug_ctrl)
|
csr_access_check: process(execute_engine.i_reg, csr, debug_ctrl)
|
variable csr_wacc_v : std_ulogic; -- to check access to read-only CSRs
|
variable csr_wacc_v : std_ulogic; -- to check access to read-only CSRs
|
variable csr_mcounteren_hpm_v : std_ulogic_vector(31 downto 0); -- max 29 HPM counters, plus 3 LSB-aligned dummy bits
|
|
begin
|
begin
|
-- is this CSR instruction really going to write to a CSR? --
|
-- is this CSR instruction really going to write to a CSR? --
|
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
|
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrwi_c) then
|
csr_wacc_v := '1'; -- always write CSR
|
csr_wacc_v := '1'; -- always write CSR
|
else -- clear/set
|
else -- clear/set
|
csr_wacc_v := or_reduce_f(execute_engine.i_reg(instr_rs1_msb_c downto instr_rs1_lsb_c)); -- write allowed if rs1/uimm5 != 0
|
csr_wacc_v := or_reduce_f(execute_engine.i_reg(instr_rs1_msb_c downto instr_rs1_lsb_c)); -- write allowed if rs1/uimm5 != 0
|
end if;
|
end if;
|
|
|
-- low privilege level access to hpm counters? --
|
|
csr_mcounteren_hpm_v := (others => '0');
|
|
if (CPU_EXTENSION_RISCV_U = true) and (HPM_NUM_CNTS /= 0) then
|
|
csr_mcounteren_hpm_v(3+(HPM_NUM_CNTS-1) downto 3+0) := csr.mcounteren_hpm(HPM_NUM_CNTS-1 downto 0);
|
|
else -- 'mcounteren' CSR is hardwired to zero if user mode is not implemented
|
|
csr_mcounteren_hpm_v := (others => '0');
|
|
end if;
|
|
|
|
-- check CSR access --
|
-- check CSR access --
|
csr_acc_valid <= '0'; -- default = invalid access
|
csr_acc_valid <= '0'; -- default = invalid access
|
case csr.addr is
|
case csr.addr is
|
|
|
-- floating-point CSRs --
|
-- floating-point CSRs --
|
Line 1328... |
Line 1291... |
when csr_mstatus_c | csr_misa_c | csr_mie_c | csr_mtvec_c | csr_mcounteren_c | csr_mscratch_c | csr_mepc_c | csr_mcause_c =>
|
when csr_mstatus_c | csr_misa_c | csr_mie_c | csr_mtvec_c | csr_mcounteren_c | csr_mscratch_c | csr_mepc_c | csr_mcause_c =>
|
csr_acc_valid <= csr.priv_m_mode; -- M-mode only, NOTE: MISA is read-only in the NEORV32 but we do not cause an exception here for compatibility
|
csr_acc_valid <= csr.priv_m_mode; -- M-mode only, NOTE: MISA is read-only in the NEORV32 but we do not cause an exception here for compatibility
|
when csr_mip_c | csr_mtval_c => -- NOTE: MIP and MTVAL are read-only in the NEORV32!
|
when csr_mip_c | csr_mtval_c => -- NOTE: MIP and MTVAL are read-only in the NEORV32!
|
csr_acc_valid <= (not csr_wacc_v) and csr.priv_m_mode; -- M-mode only, read-only
|
csr_acc_valid <= (not csr_wacc_v) and csr.priv_m_mode; -- M-mode only, read-only
|
|
|
-- physical memory protection - address & configuration --
|
-- physical memory protection (PMP) - address & configuration --
|
when csr_pmpaddr0_c | csr_pmpaddr1_c | csr_pmpaddr2_c | csr_pmpaddr3_c | csr_pmpaddr4_c | csr_pmpaddr5_c | csr_pmpaddr6_c | csr_pmpaddr7_c |
|
when csr_pmpaddr0_c | csr_pmpaddr1_c | csr_pmpaddr2_c | csr_pmpaddr3_c | csr_pmpaddr4_c | csr_pmpaddr5_c | csr_pmpaddr6_c | csr_pmpaddr7_c |
|
csr_pmpaddr8_c | csr_pmpaddr9_c | csr_pmpaddr10_c | csr_pmpaddr11_c | csr_pmpaddr12_c | csr_pmpaddr13_c | csr_pmpaddr14_c | csr_pmpaddr15_c |
|
csr_pmpaddr8_c | csr_pmpaddr9_c | csr_pmpaddr10_c | csr_pmpaddr11_c | csr_pmpaddr12_c | csr_pmpaddr13_c | csr_pmpaddr14_c | csr_pmpaddr15_c |
|
csr_pmpaddr16_c | csr_pmpaddr17_c | csr_pmpaddr18_c | csr_pmpaddr19_c | csr_pmpaddr20_c | csr_pmpaddr21_c | csr_pmpaddr22_c | csr_pmpaddr23_c |
|
csr_pmpaddr16_c | csr_pmpaddr17_c | csr_pmpaddr18_c | csr_pmpaddr19_c | csr_pmpaddr20_c | csr_pmpaddr21_c | csr_pmpaddr22_c | csr_pmpaddr23_c |
|
csr_pmpaddr24_c | csr_pmpaddr25_c | csr_pmpaddr26_c | csr_pmpaddr27_c | csr_pmpaddr28_c | csr_pmpaddr29_c | csr_pmpaddr30_c | csr_pmpaddr31_c |
|
csr_pmpaddr24_c | csr_pmpaddr25_c | csr_pmpaddr26_c | csr_pmpaddr27_c | csr_pmpaddr28_c | csr_pmpaddr29_c | csr_pmpaddr30_c | csr_pmpaddr31_c |
|
csr_pmpaddr32_c | csr_pmpaddr33_c | csr_pmpaddr34_c | csr_pmpaddr35_c | csr_pmpaddr36_c | csr_pmpaddr37_c | csr_pmpaddr38_c | csr_pmpaddr39_c |
|
csr_pmpaddr32_c | csr_pmpaddr33_c | csr_pmpaddr34_c | csr_pmpaddr35_c | csr_pmpaddr36_c | csr_pmpaddr37_c | csr_pmpaddr38_c | csr_pmpaddr39_c |
|
Line 1345... |
Line 1308... |
csr_acc_valid <= csr.priv_m_mode; -- M-mode only
|
csr_acc_valid <= csr.priv_m_mode; -- M-mode only
|
else
|
else
|
NULL;
|
NULL;
|
end if;
|
end if;
|
|
|
-- machine counters/timers --
|
-- hardware performance monitors (HPM) --
|
when csr_mcycle_c | csr_minstret_c =>
|
when csr_mhpmcounter3_c | csr_mhpmcounter4_c | csr_mhpmcounter5_c | csr_mhpmcounter6_c | csr_mhpmcounter7_c | csr_mhpmcounter8_c | -- counter LOW
|
csr_acc_valid <= csr.priv_m_mode and bool_to_ulogic_f(boolean(cpu_cnt_lo_width_c > 0)); -- M-mode only, access valid if really implemented
|
|
when csr_mcycleh_c | csr_minstreth_c =>
|
|
csr_acc_valid <= csr.priv_m_mode and bool_to_ulogic_f(boolean(cpu_cnt_hi_width_c > 0)); -- M-mode only, access valid if really implemented
|
|
|
|
when csr_mhpmcounter3_c | csr_mhpmcounter4_c | csr_mhpmcounter5_c | csr_mhpmcounter6_c | csr_mhpmcounter7_c | csr_mhpmcounter8_c | -- LOW
|
|
csr_mhpmcounter9_c | csr_mhpmcounter10_c | csr_mhpmcounter11_c | csr_mhpmcounter12_c | csr_mhpmcounter13_c | csr_mhpmcounter14_c |
|
csr_mhpmcounter9_c | csr_mhpmcounter10_c | csr_mhpmcounter11_c | csr_mhpmcounter12_c | csr_mhpmcounter13_c | csr_mhpmcounter14_c |
|
csr_mhpmcounter15_c | csr_mhpmcounter16_c | csr_mhpmcounter17_c | csr_mhpmcounter18_c | csr_mhpmcounter19_c | csr_mhpmcounter20_c |
|
csr_mhpmcounter15_c | csr_mhpmcounter16_c | csr_mhpmcounter17_c | csr_mhpmcounter18_c | csr_mhpmcounter19_c | csr_mhpmcounter20_c |
|
csr_mhpmcounter21_c | csr_mhpmcounter22_c | csr_mhpmcounter23_c | csr_mhpmcounter24_c | csr_mhpmcounter25_c | csr_mhpmcounter26_c |
|
csr_mhpmcounter21_c | csr_mhpmcounter22_c | csr_mhpmcounter23_c | csr_mhpmcounter24_c | csr_mhpmcounter25_c | csr_mhpmcounter26_c |
|
csr_mhpmcounter27_c | csr_mhpmcounter28_c | csr_mhpmcounter29_c | csr_mhpmcounter30_c | csr_mhpmcounter31_c |
|
csr_mhpmcounter27_c | csr_mhpmcounter28_c | csr_mhpmcounter29_c | csr_mhpmcounter30_c | csr_mhpmcounter31_c |
|
csr_mhpmcounter3h_c | csr_mhpmcounter4h_c | csr_mhpmcounter5h_c | csr_mhpmcounter6h_c | csr_mhpmcounter7h_c | csr_mhpmcounter8h_c | -- HIGH
|
csr_mhpmcounter3h_c | csr_mhpmcounter4h_c | csr_mhpmcounter5h_c | csr_mhpmcounter6h_c | csr_mhpmcounter7h_c | csr_mhpmcounter8h_c | -- counter HIGH
|
csr_mhpmcounter9h_c | csr_mhpmcounter10h_c | csr_mhpmcounter11h_c | csr_mhpmcounter12h_c | csr_mhpmcounter13h_c | csr_mhpmcounter14h_c |
|
csr_mhpmcounter9h_c | csr_mhpmcounter10h_c | csr_mhpmcounter11h_c | csr_mhpmcounter12h_c | csr_mhpmcounter13h_c | csr_mhpmcounter14h_c |
|
csr_mhpmcounter15h_c | csr_mhpmcounter16h_c | csr_mhpmcounter17h_c | csr_mhpmcounter18h_c | csr_mhpmcounter19h_c | csr_mhpmcounter20h_c |
|
csr_mhpmcounter15h_c | csr_mhpmcounter16h_c | csr_mhpmcounter17h_c | csr_mhpmcounter18h_c | csr_mhpmcounter19h_c | csr_mhpmcounter20h_c |
|
csr_mhpmcounter21h_c | csr_mhpmcounter22h_c | csr_mhpmcounter23h_c | csr_mhpmcounter24h_c | csr_mhpmcounter25h_c | csr_mhpmcounter26h_c |
|
csr_mhpmcounter21h_c | csr_mhpmcounter22h_c | csr_mhpmcounter23h_c | csr_mhpmcounter24h_c | csr_mhpmcounter25h_c | csr_mhpmcounter26h_c |
|
csr_mhpmcounter27h_c | csr_mhpmcounter28h_c | csr_mhpmcounter29h_c | csr_mhpmcounter30h_c | csr_mhpmcounter31h_c =>
|
csr_mhpmcounter27h_c | csr_mhpmcounter28h_c | csr_mhpmcounter29h_c | csr_mhpmcounter30h_c | csr_mhpmcounter31h_c |
|
|
csr_mhpmevent3_c | csr_mhpmevent4_c | csr_mhpmevent5_c | csr_mhpmevent6_c | csr_mhpmevent7_c | csr_mhpmevent8_c | -- event configuration
|
|
csr_mhpmevent9_c | csr_mhpmevent10_c | csr_mhpmevent11_c | csr_mhpmevent12_c | csr_mhpmevent13_c | csr_mhpmevent14_c |
|
|
csr_mhpmevent15_c | csr_mhpmevent16_c | csr_mhpmevent17_c | csr_mhpmevent18_c | csr_mhpmevent19_c | csr_mhpmevent20_c |
|
|
csr_mhpmevent21_c | csr_mhpmevent22_c | csr_mhpmevent23_c | csr_mhpmevent24_c | csr_mhpmevent25_c | csr_mhpmevent26_c |
|
|
csr_mhpmevent27_c | csr_mhpmevent28_c | csr_mhpmevent29_c | csr_mhpmevent30_c | csr_mhpmevent31_c =>
|
if (HPM_NUM_CNTS > 0) then
|
if (HPM_NUM_CNTS > 0) then
|
csr_acc_valid <= csr.priv_m_mode; -- M-mode only
|
csr_acc_valid <= csr.priv_m_mode; -- M-mode only
|
else
|
else
|
NULL;
|
NULL;
|
end if;
|
end if;
|
|
|
-- user counters/timers --
|
-- counters/timers --
|
|
when csr_mcycle_c | csr_minstret_c =>
|
|
csr_acc_valid <= csr.priv_m_mode and bool_to_ulogic_f(boolean(cpu_cnt_lo_width_c > 0)); -- M-mode only, access valid if really implemented
|
|
when csr_mcycleh_c | csr_minstreth_c =>
|
|
csr_acc_valid <= csr.priv_m_mode and bool_to_ulogic_f(boolean(cpu_cnt_hi_width_c > 0)); -- M-mode only, access valid if really implemented
|
|
|
when csr_cycle_c =>
|
when csr_cycle_c =>
|
csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr.mcounteren_cy) and bool_to_ulogic_f(boolean(cpu_cnt_lo_width_c > 0)); -- M-mode, U-mode if authorized, read-only, access if implemented
|
csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr.mcounteren_cy) and bool_to_ulogic_f(boolean(cpu_cnt_lo_width_c > 0)); -- M-mode, U-mode if authorized, read-only, access if implemented
|
when csr_cycleh_c =>
|
when csr_cycleh_c =>
|
csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr.mcounteren_cy) and bool_to_ulogic_f(boolean(cpu_cnt_hi_width_c > 0)); -- M-mode, U-mode if authorized, read-only, access if implemented
|
csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr.mcounteren_cy) and bool_to_ulogic_f(boolean(cpu_cnt_hi_width_c > 0)); -- M-mode, U-mode if authorized, read-only, access if implemented
|
when csr_instret_c =>
|
when csr_instret_c =>
|
Line 1380... |
Line 1348... |
csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr.mcounteren_ir) and bool_to_ulogic_f(boolean(cpu_cnt_hi_width_c > 0)); -- M-mode, U-mode if authorized, read-only, access if implemented
|
csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr.mcounteren_ir) and bool_to_ulogic_f(boolean(cpu_cnt_hi_width_c > 0)); -- M-mode, U-mode if authorized, read-only, access if implemented
|
|
|
when csr_time_c | csr_timeh_c =>
|
when csr_time_c | csr_timeh_c =>
|
csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr.mcounteren_tm); -- M-mode, U-mode if authorized, read-only
|
csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr.mcounteren_tm); -- M-mode, U-mode if authorized, read-only
|
|
|
when csr_hpmcounter3_c | csr_hpmcounter4_c | csr_hpmcounter5_c | csr_hpmcounter6_c | csr_hpmcounter7_c | csr_hpmcounter8_c | -- LOW
|
|
csr_hpmcounter9_c | csr_hpmcounter10_c | csr_hpmcounter11_c | csr_hpmcounter12_c | csr_hpmcounter13_c | csr_hpmcounter14_c |
|
|
csr_hpmcounter15_c | csr_hpmcounter16_c | csr_hpmcounter17_c | csr_hpmcounter18_c | csr_hpmcounter19_c | csr_hpmcounter20_c |
|
|
csr_hpmcounter21_c | csr_hpmcounter22_c | csr_hpmcounter23_c | csr_hpmcounter24_c | csr_hpmcounter25_c | csr_hpmcounter26_c |
|
|
csr_hpmcounter27_c | csr_hpmcounter28_c | csr_hpmcounter29_c | csr_hpmcounter30_c | csr_hpmcounter31_c |
|
|
csr_hpmcounter3h_c | csr_hpmcounter4h_c | csr_hpmcounter5h_c | csr_hpmcounter6h_c | csr_hpmcounter7h_c | csr_hpmcounter8h_c | -- HIGH
|
|
csr_hpmcounter9h_c | csr_hpmcounter10h_c | csr_hpmcounter11h_c | csr_hpmcounter12h_c | csr_hpmcounter13h_c | csr_hpmcounter14h_c |
|
|
csr_hpmcounter15h_c | csr_hpmcounter16h_c | csr_hpmcounter17h_c | csr_hpmcounter18h_c | csr_hpmcounter19h_c | csr_hpmcounter20h_c |
|
|
csr_hpmcounter21h_c | csr_hpmcounter22h_c | csr_hpmcounter23h_c | csr_hpmcounter24h_c | csr_hpmcounter25h_c | csr_hpmcounter26h_c |
|
|
csr_hpmcounter27h_c | csr_hpmcounter28h_c | csr_hpmcounter29h_c | csr_hpmcounter30h_c | csr_hpmcounter31h_c =>
|
|
if (HPM_NUM_CNTS > 0) then
|
|
csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(to_integer(unsigned(csr.addr(4 downto 0))))); -- M-mode, U-mode if authorized, read-only
|
|
else
|
|
NULL;
|
|
end if;
|
|
|
|
-- machine counter setup --
|
|
when csr_mcountinhibit_c =>
|
when csr_mcountinhibit_c =>
|
csr_acc_valid <= csr.priv_m_mode; -- M-mode only
|
csr_acc_valid <= csr.priv_m_mode; -- M-mode only
|
|
|
when csr_mhpmevent3_c | csr_mhpmevent4_c | csr_mhpmevent5_c | csr_mhpmevent6_c | csr_mhpmevent7_c | csr_mhpmevent8_c |
|
|
csr_mhpmevent9_c | csr_mhpmevent10_c | csr_mhpmevent11_c | csr_mhpmevent12_c | csr_mhpmevent13_c | csr_mhpmevent14_c |
|
|
csr_mhpmevent15_c | csr_mhpmevent16_c | csr_mhpmevent17_c | csr_mhpmevent18_c | csr_mhpmevent19_c | csr_mhpmevent20_c |
|
|
csr_mhpmevent21_c | csr_mhpmevent22_c | csr_mhpmevent23_c | csr_mhpmevent24_c | csr_mhpmevent25_c | csr_mhpmevent26_c |
|
|
csr_mhpmevent27_c | csr_mhpmevent28_c | csr_mhpmevent29_c | csr_mhpmevent30_c | csr_mhpmevent31_c =>
|
|
if (HPM_NUM_CNTS > 0) then
|
|
csr_acc_valid <= csr.priv_m_mode; -- M-mode only
|
|
else
|
|
NULL;
|
|
end if;
|
|
|
|
-- machine information registers & custom (NEORV32-specific) read-only CSRs --
|
-- machine information registers & custom (NEORV32-specific) read-only CSRs --
|
when csr_mvendorid_c | csr_marchid_c | csr_mimpid_c | csr_mhartid_c | csr_mzext_c =>
|
when csr_mvendorid_c | csr_marchid_c | csr_mimpid_c | csr_mhartid_c | csr_mzext_c =>
|
csr_acc_valid <= (not csr_wacc_v) and csr.priv_m_mode; -- M-mode only, read-only
|
csr_acc_valid <= (not csr_wacc_v) and csr.priv_m_mode; -- M-mode only, read-only
|
|
|
Line 1453... |
Line 1394... |
|
|
-- check instructions --
|
-- check instructions --
|
opcode_v := execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c+2) & "11"; -- save some bits here, LSBs are always 11 for rv32
|
opcode_v := execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c+2) & "11"; -- save some bits here, LSBs are always 11 for rv32
|
case opcode_v is
|
case opcode_v is
|
|
|
|
|
when opcode_lui_c | opcode_auipc_c | opcode_jal_c => -- check sufficient LUI, UIPC, JAL (only check actual OPCODE)
|
when opcode_lui_c | opcode_auipc_c | opcode_jal_c => -- check sufficient LUI, UIPC, JAL (only check actual OPCODE)
|
-- ------------------------------------------------------------
|
-- ------------------------------------------------------------
|
illegal_instruction <= '0';
|
illegal_instruction <= '0';
|
-- illegal E-CPU register? --
|
-- illegal E-CPU register? --
|
if (CPU_EXTENSION_RISCV_E = true) and (execute_engine.i_reg(instr_rd_msb_c) = '1') then
|
if (CPU_EXTENSION_RISCV_E = true) and (execute_engine.i_reg(instr_rd_msb_c) = '1') then
|
illegal_register <= '1';
|
illegal_register <= '1';
|
end if;
|
end if;
|
|
|
when opcode_alu_c => -- check ALU.funct3 & ALU.funct7
|
when opcode_alu_c => -- check ALU.funct3 & ALU.funct7
|
-- ------------------------------------------------------------
|
-- ------------------------------------------------------------
|
if (execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0000001") then -- MULDIV
|
if (decode_aux.is_m_mul = '1') then -- MUL
|
|
if (CPU_EXTENSION_RISCV_M = false) and (CPU_EXTENSION_RISCV_Zmmul = false) then -- not implemented
|
|
illegal_instruction <= '1';
|
|
end if;
|
|
elsif (decode_aux.is_m_div = '1') then -- DIV
|
if (CPU_EXTENSION_RISCV_M = false) then -- not implemented
|
if (CPU_EXTENSION_RISCV_M = false) then -- not implemented
|
illegal_instruction <= '1';
|
illegal_instruction <= '1';
|
end if;
|
end if;
|
elsif ((execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_subadd_c) or
|
elsif ((execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_subadd_c) or
|
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sr_c)) and -- ADD/SUB or SRA/SRL check
|
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sr_c)) and -- ADD/SUB or SRA/SRL check
|
Line 1559... |
Line 1503... |
illegal_register <= '1';
|
illegal_register <= '1';
|
end if;
|
end if;
|
|
|
when opcode_fence_c => -- fence instructions
|
when opcode_fence_c => -- fence instructions
|
-- ------------------------------------------------------------
|
-- ------------------------------------------------------------
|
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_fencei_c) then -- FENCE.I -- NO trap if not implemented
|
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_fencei_c) or -- FENCE.I -- NO trap if not implemented
|
illegal_instruction <= '0';
|
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_fence_c) then -- FENCE
|
elsif (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_fence_c) then -- FENCE
|
|
illegal_instruction <= '0';
|
illegal_instruction <= '0';
|
else
|
else
|
illegal_instruction <= '1';
|
illegal_instruction <= '1';
|
end if;
|
end if;
|
|
|
Line 1739... |
Line 1682... |
-- any exception/interrupt? --
|
-- any exception/interrupt? --
|
trap_ctrl.exc_fire <= or_reduce_f(trap_ctrl.exc_buf); -- exceptions/faults CANNOT be masked
|
trap_ctrl.exc_fire <= or_reduce_f(trap_ctrl.exc_buf); -- exceptions/faults CANNOT be masked
|
trap_ctrl.irq_fire <= (or_reduce_f(trap_ctrl.irq_buf) and csr.mstatus_mie and trap_ctrl.db_irq_en) or trap_ctrl.db_irq_fire; -- interrupts CAN be masked
|
trap_ctrl.irq_fire <= (or_reduce_f(trap_ctrl.irq_buf) and csr.mstatus_mie and trap_ctrl.db_irq_en) or trap_ctrl.db_irq_fire; -- interrupts CAN be masked
|
|
|
-- debug mode (entry) interrupts --
|
-- debug mode (entry) interrupts --
|
trap_ctrl.db_irq_en <= '1' when (CPU_EXTENSION_RISCV_DEBUG = false) else
|
trap_ctrl.db_irq_en <= '0' when (CPU_EXTENSION_RISCV_DEBUG = true) and ((debug_ctrl.running = '1') or (csr.dcsr_step = '1')) else '1'; -- no interrupts when IN debug mode or IN single-step mode
|
'0' when (debug_ctrl.running = '1') or (csr.dcsr_step = '1') else '1'; -- no interrupts when IN debug mode or IN single-step mode
|
|
trap_ctrl.db_irq_fire <= (trap_ctrl.irq_buf(interrupt_db_step_c) or trap_ctrl.irq_buf(interrupt_db_halt_c)) when (CPU_EXTENSION_RISCV_DEBUG = true) else '0'; -- "NMI" for debug mode entry
|
trap_ctrl.db_irq_fire <= (trap_ctrl.irq_buf(interrupt_db_step_c) or trap_ctrl.irq_buf(interrupt_db_halt_c)) when (CPU_EXTENSION_RISCV_DEBUG = true) else '0'; -- "NMI" for debug mode entry
|
|
|
-- acknowledge mask output --
|
|
firq_ack_o <= trap_ctrl.irq_ack(interrupt_firq_15_c downto interrupt_firq_0_c);
|
|
|
|
|
|
-- Trap Priority Encoder ------------------------------------------------------------------
|
-- Trap Priority Encoder ------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
trap_priority: process(trap_ctrl)
|
trap_priority: process(trap_ctrl)
|
begin
|
begin
|
Line 1999... |
Line 1938... |
csr.mhpmevent <= (others => (others => def_rst_val_c));
|
csr.mhpmevent <= (others => (others => def_rst_val_c));
|
--
|
--
|
csr.mcounteren_cy <= def_rst_val_c;
|
csr.mcounteren_cy <= def_rst_val_c;
|
csr.mcounteren_tm <= def_rst_val_c;
|
csr.mcounteren_tm <= def_rst_val_c;
|
csr.mcounteren_ir <= def_rst_val_c;
|
csr.mcounteren_ir <= def_rst_val_c;
|
csr.mcounteren_hpm <= (others => def_rst_val_c);
|
|
--
|
--
|
csr.mcountinhibit_cy <= def_rst_val_c;
|
csr.mcountinhibit_cy <= def_rst_val_c;
|
csr.mcountinhibit_ir <= def_rst_val_c;
|
csr.mcountinhibit_ir <= def_rst_val_c;
|
csr.mcountinhibit_hpm <= (others => def_rst_val_c);
|
csr.mcountinhibit_hpm <= (others => def_rst_val_c);
|
--
|
--
|
Line 2076... |
Line 2014... |
if (CPU_EXTENSION_RISCV_U = true) then -- this CSR is hardwired to zero if user mode is not implemented
|
if (CPU_EXTENSION_RISCV_U = true) then -- this CSR is hardwired to zero if user mode is not implemented
|
if (csr.addr(3 downto 0) = csr_mcounteren_c(3 downto 0)) then
|
if (csr.addr(3 downto 0) = csr_mcounteren_c(3 downto 0)) then
|
csr.mcounteren_cy <= csr.wdata(0); -- enable user-level access to cycle[h]
|
csr.mcounteren_cy <= csr.wdata(0); -- enable user-level access to cycle[h]
|
csr.mcounteren_tm <= csr.wdata(1); -- enable user-level access to time[h]
|
csr.mcounteren_tm <= csr.wdata(1); -- enable user-level access to time[h]
|
csr.mcounteren_ir <= csr.wdata(2); -- enable user-level access to instret[h]
|
csr.mcounteren_ir <= csr.wdata(2); -- enable user-level access to instret[h]
|
csr.mcounteren_hpm <= csr.wdata(csr.mcounteren_hpm'left+3 downto 3); -- enable user-level access to hpmcounterx[h]
|
|
end if;
|
end if;
|
end if;
|
end if;
|
end if;
|
end if;
|
|
|
-- machine trap handling --
|
-- machine trap handling --
|
Line 2226... |
Line 2163... |
csr.mtval <= (others => '0');
|
csr.mtval <= (others => '0');
|
end case;
|
end case;
|
|
|
end if;
|
end if;
|
|
|
-- trap enter: write dpc and dcsr --
|
-- DEBUG MODE (trap) enter: write dpc and dcsr --
|
-- --------------------------------------------------------------------
|
-- --------------------------------------------------------------------
|
if (CPU_EXTENSION_RISCV_DEBUG = true) and (trap_ctrl.cause(5) = '1') and (debug_ctrl.running = '0') then -- debug mode entry exception
|
if (CPU_EXTENSION_RISCV_DEBUG = true) and (trap_ctrl.cause(5) = '1') and (debug_ctrl.running = '0') then -- debug mode entry exception
|
|
|
-- trap cause ID code --
|
-- trap cause ID code --
|
csr.dcsr_cause <= trap_ctrl.cause(2 downto 0); -- why did we enter debug mode?
|
csr.dcsr_cause <= trap_ctrl.cause(2 downto 0); -- why did we enter debug mode?
|
Line 2290... |
Line 2227... |
csr.privilege <= priv_mode_m_c;
|
csr.privilege <= priv_mode_m_c;
|
csr.mstatus_mpp <= priv_mode_m_c;
|
csr.mstatus_mpp <= priv_mode_m_c;
|
csr.mcounteren_cy <= '0';
|
csr.mcounteren_cy <= '0';
|
csr.mcounteren_tm <= '0';
|
csr.mcounteren_tm <= '0';
|
csr.mcounteren_ir <= '0';
|
csr.mcounteren_ir <= '0';
|
csr.mcounteren_hpm <= (others => '0');
|
|
csr.dcsr_ebreaku <= '0';
|
csr.dcsr_ebreaku <= '0';
|
csr.dcsr_prv <= priv_mode_m_c;
|
csr.dcsr_prv <= priv_mode_m_c;
|
end if;
|
end if;
|
|
|
-- pmp disabled --
|
-- pmp disabled --
|
Line 2304... |
Line 2240... |
end if;
|
end if;
|
|
|
-- hpms disabled --
|
-- hpms disabled --
|
if (HPM_NUM_CNTS = 0) then
|
if (HPM_NUM_CNTS = 0) then
|
csr.mhpmevent <= (others => (others => '0'));
|
csr.mhpmevent <= (others => (others => '0'));
|
csr.mcounteren_hpm <= (others => '0');
|
|
csr.mcountinhibit_hpm <= (others => '0');
|
csr.mcountinhibit_hpm <= (others => '0');
|
end if;
|
end if;
|
|
|
-- cpu counters disabled --
|
-- cpu counters disabled --
|
if (CPU_CNT_WIDTH = 0) then
|
if (CPU_CNT_WIDTH = 0) then
|
Line 2336... |
Line 2271... |
|
|
end if;
|
end if;
|
end process csr_write_access;
|
end process csr_write_access;
|
|
|
-- decode current privilege mode --
|
-- decode current privilege mode --
|
csr.privilege_rd <= priv_mode_m_c when (CPU_EXTENSION_RISCV_E) and (debug_ctrl.running = '1') else csr.privilege; -- effective privilege mode ("machine" when in debug mode)
|
csr.privilege_rd <= priv_mode_m_c when (CPU_EXTENSION_RISCV_DEBUG = true) and (debug_ctrl.running = '1') else csr.privilege; -- effective privilege mode ("machine" when in debug mode)
|
csr.priv_m_mode <= '1' when (csr.privilege_rd = priv_mode_m_c) else '0';
|
csr.priv_m_mode <= '1' when (csr.privilege_rd = priv_mode_m_c) else '0';
|
csr.priv_u_mode <= '1' when (csr.privilege_rd = priv_mode_u_c) and (CPU_EXTENSION_RISCV_U = true) else '0';
|
csr.priv_u_mode <= '1' when (csr.privilege_rd = priv_mode_u_c) and (CPU_EXTENSION_RISCV_U = true) else '0';
|
|
|
-- PMP configuration output to bus unit --
|
-- PMP configuration output to bus unit --
|
pmp_output: process(csr)
|
pmp_output: process(csr)
|
Line 2365... |
Line 2300... |
csr.pmpcfg_rd(i) <= csr.pmpcfg(i);
|
csr.pmpcfg_rd(i) <= csr.pmpcfg(i);
|
end loop; -- i
|
end loop; -- i
|
end if;
|
end if;
|
end process pmp_rd_dummy;
|
end process pmp_rd_dummy;
|
|
|
-- FPU rounding mode --
|
|
fpu_rm_o <= csr.frm;
|
|
|
|
|
|
-- Control and Status Registers - Counters ------------------------------------------------
|
-- Control and Status Registers - Counters ------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
csr_counters: process(rstn_i, clk_i)
|
csr_counters: process(rstn_i, clk_i)
|
begin
|
begin
|
-- Counter CSRs (each counter is split into two 32-bit counters - coupled via an MSB overflow detector)
|
-- Counter CSRs (each counter is split into two 32-bit counters - coupled via an MSB overflow detector)
|
if (rstn_i = '0') then
|
if (rstn_i = '0') then
|
csr.mcycle <= (others => def_rst_val_c);
|
csr.mcycle <= (others => def_rst_val_c);
|
csr.mcycle_msb <= def_rst_val_c;
|
csr.mcycle_ovfl <= (others => def_rst_val_c);
|
csr.mcycleh <= (others => def_rst_val_c);
|
csr.mcycleh <= (others => def_rst_val_c);
|
csr.minstret <= (others => def_rst_val_c);
|
csr.minstret <= (others => def_rst_val_c);
|
csr.minstret_msb <= def_rst_val_c;
|
csr.minstret_ovfl <= (others => def_rst_val_c);
|
csr.minstreth <= (others => def_rst_val_c);
|
csr.minstreth <= (others => def_rst_val_c);
|
csr.mhpmcounter <= (others => (others => def_rst_val_c));
|
csr.mhpmcounter <= (others => (others => def_rst_val_c));
|
csr.mhpmcounter_msb <= (others => def_rst_val_c);
|
csr.mhpmcounter_ovfl <= (others => (others => def_rst_val_c));
|
csr.mhpmcounterh <= (others => (others => def_rst_val_c));
|
csr.mhpmcounterh <= (others => (others => def_rst_val_c));
|
elsif rising_edge(clk_i) then
|
elsif rising_edge(clk_i) then
|
|
|
-- [m]cycle --
|
-- [m]cycle --
|
if (cpu_cnt_lo_width_c > 0) then
|
if (cpu_cnt_lo_width_c > 0) then
|
csr.mcycle_msb <= csr.mcycle(csr.mcycle'left);
|
csr.mcycle_ovfl(0) <= csr.mcycle_nxt(csr.mcycle_nxt'left);
|
if (csr.we = '1') and (csr.addr = csr_mcycle_c) then -- write access
|
if (csr.we = '1') and (csr.addr = csr_mcycle_c) then -- write access
|
csr.mcycle(cpu_cnt_lo_width_c downto 0) <= '0' & csr.wdata(cpu_cnt_lo_width_c-1 downto 0);
|
csr.mcycle(cpu_cnt_lo_width_c-1 downto 0) <= csr.wdata(cpu_cnt_lo_width_c-1 downto 0);
|
elsif (csr.mcountinhibit_cy = '0') and (cnt_event(hpmcnt_event_cy_c) = '1') then -- non-inhibited automatic update
|
elsif (csr.mcountinhibit_cy = '0') and (cnt_event(hpmcnt_event_cy_c) = '1') then -- non-inhibited automatic update
|
csr.mcycle(cpu_cnt_lo_width_c downto 0) <= std_ulogic_vector(unsigned('0' & csr.mcycle(cpu_cnt_lo_width_c-1 downto 0)) + 1);
|
csr.mcycle(cpu_cnt_lo_width_c-1 downto 0) <= csr.mcycle_nxt(cpu_cnt_lo_width_c-1 downto 0);
|
end if;
|
end if;
|
else
|
else
|
csr.mcycle <= (others => '-');
|
csr.mcycle <= (others => '-');
|
csr.mcycle_msb <= '-';
|
csr.mcycle_ovfl(0) <= '-';
|
end if;
|
end if;
|
|
|
-- [m]cycleh --
|
-- [m]cycleh --
|
if (cpu_cnt_hi_width_c > 0) then
|
if (cpu_cnt_hi_width_c > 0) then
|
if (csr.we = '1') and (csr.addr = csr_mcycleh_c) then -- write access
|
if (csr.we = '1') and (csr.addr = csr_mcycleh_c) then -- write access
|
csr.mcycleh(cpu_cnt_hi_width_c-1 downto 0) <= csr.wdata(cpu_cnt_hi_width_c-1 downto 0);
|
csr.mcycleh(cpu_cnt_hi_width_c-1 downto 0) <= csr.wdata(cpu_cnt_hi_width_c-1 downto 0);
|
elsif (csr.mcycle_msb = '0') and (csr.mcycle(csr.mcycle'left) = '1') then -- automatic update (continued)
|
elsif (csr.mcountinhibit_cy = '0') and (cnt_event(hpmcnt_event_cy_c) = '1') then -- non-inhibited automatic update
|
csr.mcycleh(cpu_cnt_hi_width_c-1 downto 0) <= std_ulogic_vector(unsigned(csr.mcycleh(cpu_cnt_hi_width_c-1 downto 0)) + 1);
|
csr.mcycleh(cpu_cnt_hi_width_c-1 downto 0) <= std_ulogic_vector(unsigned(csr.mcycleh(cpu_cnt_hi_width_c-1 downto 0)) + unsigned(csr.mcycle_ovfl));
|
end if;
|
end if;
|
else
|
else
|
csr.mcycleh <= (others => '-');
|
csr.mcycleh <= (others => '-');
|
end if;
|
end if;
|
|
|
|
|
-- [m]instret --
|
-- [m]instret --
|
if (cpu_cnt_lo_width_c > 0) then
|
if (cpu_cnt_lo_width_c > 0) then
|
csr.minstret_msb <= csr.minstret(csr.minstret'left);
|
csr.minstret_ovfl(0) <= csr.minstret_nxt(csr.minstret_nxt'left);
|
if (csr.we = '1') and (csr.addr = csr_minstret_c) then -- write access
|
if (csr.we = '1') and (csr.addr = csr_minstret_c) then -- write access
|
csr.minstret(cpu_cnt_lo_width_c downto 0) <= '0' & csr.wdata(cpu_cnt_lo_width_c-1 downto 0);
|
csr.minstret(cpu_cnt_lo_width_c-1 downto 0) <= csr.wdata(cpu_cnt_lo_width_c-1 downto 0);
|
elsif (csr.mcountinhibit_ir = '0') and (cnt_event(hpmcnt_event_ir_c) = '1') then -- non-inhibited automatic update
|
elsif (csr.mcountinhibit_ir = '0') and (cnt_event(hpmcnt_event_ir_c) = '1') then -- non-inhibited automatic update
|
csr.minstret(cpu_cnt_lo_width_c downto 0) <= std_ulogic_vector(unsigned('0' & csr.minstret(cpu_cnt_lo_width_c-1 downto 0)) + 1);
|
csr.minstret(cpu_cnt_lo_width_c-1 downto 0) <= csr.minstret_nxt(cpu_cnt_lo_width_c-1 downto 0);
|
end if;
|
end if;
|
else
|
else
|
csr.minstret <= (others => '-');
|
csr.minstret <= (others => '-');
|
csr.minstret_msb <= '-';
|
csr.minstret_ovfl(0) <= '-';
|
end if;
|
end if;
|
|
|
-- [m]instreth --
|
-- [m]instreth --
|
if (cpu_cnt_hi_width_c > 0) then
|
if (cpu_cnt_hi_width_c > 0) then
|
if (csr.we = '1') and (csr.addr = csr_minstreth_c) then -- write access
|
if (csr.we = '1') and (csr.addr = csr_minstreth_c) then -- write access
|
csr.minstreth(cpu_cnt_hi_width_c-1 downto 0) <= csr.wdata(cpu_cnt_hi_width_c-1 downto 0);
|
csr.minstreth(cpu_cnt_hi_width_c-1 downto 0) <= csr.wdata(cpu_cnt_hi_width_c-1 downto 0);
|
elsif (csr.minstret_msb = '0') and (csr.minstret(csr.minstret'left) = '1') then -- automatic update (continued)
|
elsif (csr.mcountinhibit_ir = '0') and (cnt_event(hpmcnt_event_ir_c) = '1') then -- non-inhibited automatic update
|
csr.minstreth(cpu_cnt_hi_width_c-1 downto 0) <= std_ulogic_vector(unsigned(csr.minstreth(cpu_cnt_hi_width_c-1 downto 0)) + 1);
|
csr.minstreth(cpu_cnt_hi_width_c-1 downto 0) <= std_ulogic_vector(unsigned(csr.minstreth(cpu_cnt_hi_width_c-1 downto 0)) + unsigned(csr.minstret_ovfl));
|
end if;
|
end if;
|
else
|
else
|
csr.minstreth <= (others => '-');
|
csr.minstreth <= (others => '-');
|
end if;
|
end if;
|
|
|
Line 2441... |
Line 2373... |
-- [machine] hardware performance monitors (counters) --
|
-- [machine] hardware performance monitors (counters) --
|
for i in 0 to HPM_NUM_CNTS-1 loop
|
for i in 0 to HPM_NUM_CNTS-1 loop
|
|
|
-- [m]hpmcounter* --
|
-- [m]hpmcounter* --
|
if (hpm_cnt_lo_width_c > 0) then
|
if (hpm_cnt_lo_width_c > 0) then
|
csr.mhpmcounter_msb(i) <= csr.mhpmcounter(i)(csr.mhpmcounter(i)'left);
|
csr.mhpmcounter_ovfl(i)(0) <= csr.mhpmcounter_nxt(i)(csr.mhpmcounter_nxt(i)'left);
|
if (csr.we = '1') and (csr.addr = std_ulogic_vector(unsigned(csr_mhpmcounter3_c) + i)) then -- write access
|
if (csr.we = '1') and (csr.addr = std_ulogic_vector(unsigned(csr_mhpmcounter3_c) + i)) then -- write access
|
csr.mhpmcounter(i)(hpm_cnt_lo_width_c downto 0) <= '0' & csr.wdata(hpm_cnt_lo_width_c-1 downto 0);
|
csr.mhpmcounter(i)(hpm_cnt_lo_width_c-1 downto 0) <= csr.wdata(hpm_cnt_lo_width_c-1 downto 0);
|
elsif (csr.mcountinhibit_hpm(i) = '0') and (hpmcnt_trigger(i) = '1') then -- non-inhibited automatic update
|
elsif (csr.mcountinhibit_hpm(i) = '0') and (hpmcnt_trigger(i) = '1') then -- non-inhibited automatic update
|
csr.mhpmcounter(i)(hpm_cnt_lo_width_c downto 0) <= std_ulogic_vector(unsigned('0' & csr.mhpmcounter(i)(hpm_cnt_lo_width_c-1 downto 0)) + 1);
|
csr.mhpmcounter(i)(hpm_cnt_lo_width_c-1 downto 0) <= csr.mhpmcounter_nxt(i)(hpm_cnt_lo_width_c-1 downto 0);
|
end if;
|
end if;
|
else
|
else
|
csr.mhpmcounter(i) <= (others => '-');
|
csr.mhpmcounter(i) <= (others => '-');
|
csr.mhpmcounter_msb(i) <= '-';
|
csr.mhpmcounter_ovfl(i)(0) <= '-';
|
end if;
|
end if;
|
|
|
-- [m]hpmcounter*h --
|
-- [m]hpmcounter*h --
|
if (hpm_cnt_hi_width_c > 0) then
|
if (hpm_cnt_hi_width_c > 0) then
|
if (csr.we = '1') and (csr.addr = std_ulogic_vector(unsigned(csr_mhpmcounter3h_c) + i)) then -- write access
|
if (csr.we = '1') and (csr.addr = std_ulogic_vector(unsigned(csr_mhpmcounter3h_c) + i)) then -- write access
|
csr.mhpmcounterh(i)(hpm_cnt_hi_width_c-1 downto 0) <= csr.wdata(hpm_cnt_hi_width_c-1 downto 0);
|
csr.mhpmcounterh(i)(hpm_cnt_hi_width_c-1 downto 0) <= csr.wdata(hpm_cnt_hi_width_c-1 downto 0);
|
elsif (csr.mhpmcounter_msb(i) = '0') and (csr.mhpmcounter(i)(csr.mhpmcounter(i)'left) = '1') then -- automatic update (continued)
|
elsif (csr.mcountinhibit_hpm(i) = '0') and (hpmcnt_trigger(i) = '1') then -- non-inhibited automatic update
|
csr.mhpmcounterh(i)(hpm_cnt_hi_width_c-1 downto 0) <= std_ulogic_vector(unsigned(csr.mhpmcounterh(i)(hpm_cnt_hi_width_c-1 downto 0)) + 1);
|
csr.mhpmcounterh(i)(hpm_cnt_hi_width_c-1 downto 0) <= std_ulogic_vector(unsigned(csr.mhpmcounterh(i)(hpm_cnt_hi_width_c-1 downto 0)) + unsigned(csr.mhpmcounter_ovfl(i)));
|
end if;
|
end if;
|
else
|
else
|
csr.mhpmcounterh(i) <= (others => '-');
|
csr.mhpmcounterh(i) <= (others => '-');
|
end if;
|
end if;
|
|
|
Line 2469... |
Line 2401... |
|
|
end if;
|
end if;
|
end process csr_counters;
|
end process csr_counters;
|
|
|
|
|
-- hpm counters read dummy --
|
-- mcycle & minstret increment LOW --
|
|
csr.mcycle_nxt <= std_ulogic_vector(unsigned('0' & csr.mcycle) + 1);
|
|
csr.minstret_nxt <= std_ulogic_vector(unsigned('0' & csr.minstret) + 1);
|
|
|
|
-- hpm counter increment LOW --
|
|
hmp_cnt_lo_inc:
|
|
for i in 0 to HPM_NUM_CNTS-1 generate
|
|
csr.mhpmcounter_nxt(i) <= std_ulogic_vector(unsigned('0' & csr.mhpmcounter(i)) + 1);
|
|
end generate;
|
|
|
|
|
|
-- hpm counter read --
|
hpm_rd_dummy: process(csr)
|
hpm_rd_dummy: process(csr)
|
begin
|
begin
|
csr.mhpmcounter_rd <= (others => (others => '0'));
|
csr.mhpmcounter_rd <= (others => (others => '0'));
|
csr.mhpmcounterh_rd <= (others => (others => '0'));
|
csr.mhpmcounterh_rd <= (others => (others => '0'));
|
if (HPM_NUM_CNTS /= 0) then
|
if (HPM_NUM_CNTS /= 0) then
|
Line 2535... |
Line 2478... |
|
|
-- Control and Status Registers - Read Access ---------------------------------------------
|
-- Control and Status Registers - Read Access ---------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
csr_read_access: process(rstn_i, clk_i)
|
csr_read_access: process(rstn_i, clk_i)
|
begin
|
begin
|
if (rstn_i = '0') then
|
if rising_edge(clk_i) then
|
csr.re <= def_rst_val_c;
|
|
csr.rdata <= (others => def_rst_val_c);
|
|
elsif rising_edge(clk_i) then
|
|
csr.re <= csr.re_nxt; -- read access?
|
csr.re <= csr.re_nxt; -- read access?
|
csr.rdata <= (others => '0'); -- default output
|
csr.rdata <= (others => '0'); -- default output
|
if (CPU_EXTENSION_RISCV_Zicsr = true) and (csr.re = '1') then
|
if (CPU_EXTENSION_RISCV_Zicsr = true) and (csr.re = '1') then
|
case csr.addr is
|
case csr.addr is
|
|
|
Line 2586... |
Line 2526... |
NULL;
|
NULL;
|
else
|
else
|
csr.rdata(0) <= csr.mcounteren_cy; -- enable user-level access to cycle[h]
|
csr.rdata(0) <= csr.mcounteren_cy; -- enable user-level access to cycle[h]
|
csr.rdata(1) <= csr.mcounteren_tm; -- enable user-level access to time[h]
|
csr.rdata(1) <= csr.mcounteren_tm; -- enable user-level access to time[h]
|
csr.rdata(2) <= csr.mcounteren_ir; -- enable user-level access to instret[h]
|
csr.rdata(2) <= csr.mcounteren_ir; -- enable user-level access to instret[h]
|
csr.rdata(csr.mcounteren_hpm'left+3 downto 3) <= csr.mcounteren_hpm; -- enable user-level access to hpmcounterx[h]
|
|
end if;
|
end if;
|
|
|
-- machine trap handling --
|
-- machine trap handling --
|
-- --------------------------------------------------------------------
|
-- --------------------------------------------------------------------
|
when csr_mscratch_c => -- mscratch (r/w): machine scratch register
|
when csr_mscratch_c => -- mscratch (r/w): machine scratch register
|
Line 2750... |
Line 2689... |
when csr_time_c => csr.rdata <= time_i(31 downto 0); -- time (r/-): System time LOW (from MTIME unit)
|
when csr_time_c => csr.rdata <= time_i(31 downto 0); -- time (r/-): System time LOW (from MTIME unit)
|
when csr_timeh_c => csr.rdata <= time_i(63 downto 32); -- timeh (r/-): System time HIGH (from MTIME unit)
|
when csr_timeh_c => csr.rdata <= time_i(63 downto 32); -- timeh (r/-): System time HIGH (from MTIME unit)
|
|
|
-- hardware performance counters --
|
-- hardware performance counters --
|
-- --------------------------------------------------------------------
|
-- --------------------------------------------------------------------
|
when csr_hpmcounter3_c | csr_mhpmcounter3_c => if (HPM_NUM_CNTS > 00) then csr.rdata <= csr.mhpmcounter_rd(00); else NULL; end if; -- (R)/(W): [m]hpmcounter3 - low
|
when csr_mhpmcounter3_c => if (HPM_NUM_CNTS > 00) then csr.rdata <= csr.mhpmcounter_rd(00); else NULL; end if; -- r/w: mhpmcounter3 - low
|
when csr_hpmcounter4_c | csr_mhpmcounter4_c => if (HPM_NUM_CNTS > 01) then csr.rdata <= csr.mhpmcounter_rd(01); else NULL; end if; -- (R)/(W): [m]hpmcounter4 - low
|
when csr_mhpmcounter4_c => if (HPM_NUM_CNTS > 01) then csr.rdata <= csr.mhpmcounter_rd(01); else NULL; end if; -- r/w: mhpmcounter4 - low
|
when csr_hpmcounter5_c | csr_mhpmcounter5_c => if (HPM_NUM_CNTS > 02) then csr.rdata <= csr.mhpmcounter_rd(02); else NULL; end if; -- (R)/(W): [m]hpmcounter5 - low
|
when csr_mhpmcounter5_c => if (HPM_NUM_CNTS > 02) then csr.rdata <= csr.mhpmcounter_rd(02); else NULL; end if; -- r/w: mhpmcounter5 - low
|
when csr_hpmcounter6_c | csr_mhpmcounter6_c => if (HPM_NUM_CNTS > 03) then csr.rdata <= csr.mhpmcounter_rd(03); else NULL; end if; -- (R)/(W): [m]hpmcounter6 - low
|
when csr_mhpmcounter6_c => if (HPM_NUM_CNTS > 03) then csr.rdata <= csr.mhpmcounter_rd(03); else NULL; end if; -- r/w: mhpmcounter6 - low
|
when csr_hpmcounter7_c | csr_mhpmcounter7_c => if (HPM_NUM_CNTS > 04) then csr.rdata <= csr.mhpmcounter_rd(04); else NULL; end if; -- (R)/(W): [m]hpmcounter7 - low
|
when csr_mhpmcounter7_c => if (HPM_NUM_CNTS > 04) then csr.rdata <= csr.mhpmcounter_rd(04); else NULL; end if; -- r/w: mhpmcounter7 - low
|
when csr_hpmcounter8_c | csr_mhpmcounter8_c => if (HPM_NUM_CNTS > 05) then csr.rdata <= csr.mhpmcounter_rd(05); else NULL; end if; -- (R)/(W): [m]hpmcounter8 - low
|
when csr_mhpmcounter8_c => if (HPM_NUM_CNTS > 05) then csr.rdata <= csr.mhpmcounter_rd(05); else NULL; end if; -- r/w: mhpmcounter8 - low
|
when csr_hpmcounter9_c | csr_mhpmcounter9_c => if (HPM_NUM_CNTS > 06) then csr.rdata <= csr.mhpmcounter_rd(06); else NULL; end if; -- (R)/(W): [m]hpmcounter9 - low
|
when csr_mhpmcounter9_c => if (HPM_NUM_CNTS > 06) then csr.rdata <= csr.mhpmcounter_rd(06); else NULL; end if; -- r/w: mhpmcounter9 - low
|
when csr_hpmcounter10_c | csr_mhpmcounter10_c => if (HPM_NUM_CNTS > 07) then csr.rdata <= csr.mhpmcounter_rd(07); else NULL; end if; -- (R)/(W): [m]hpmcounter10 - low
|
when csr_mhpmcounter10_c => if (HPM_NUM_CNTS > 07) then csr.rdata <= csr.mhpmcounter_rd(07); else NULL; end if; -- r/w: mhpmcounter10 - low
|
when csr_hpmcounter11_c | csr_mhpmcounter11_c => if (HPM_NUM_CNTS > 08) then csr.rdata <= csr.mhpmcounter_rd(08); else NULL; end if; -- (R)/(W): [m]hpmcounter11 - low
|
when csr_mhpmcounter11_c => if (HPM_NUM_CNTS > 08) then csr.rdata <= csr.mhpmcounter_rd(08); else NULL; end if; -- r/w: mhpmcounter11 - low
|
when csr_hpmcounter12_c | csr_mhpmcounter12_c => if (HPM_NUM_CNTS > 09) then csr.rdata <= csr.mhpmcounter_rd(09); else NULL; end if; -- (R)/(W): [m]hpmcounter12 - low
|
when csr_mhpmcounter12_c => if (HPM_NUM_CNTS > 09) then csr.rdata <= csr.mhpmcounter_rd(09); else NULL; end if; -- r/w: mhpmcounter12 - low
|
when csr_hpmcounter13_c | csr_mhpmcounter13_c => if (HPM_NUM_CNTS > 10) then csr.rdata <= csr.mhpmcounter_rd(10); else NULL; end if; -- (R)/(W): [m]hpmcounter13 - low
|
when csr_mhpmcounter13_c => if (HPM_NUM_CNTS > 10) then csr.rdata <= csr.mhpmcounter_rd(10); else NULL; end if; -- r/w: mhpmcounter13 - low
|
when csr_hpmcounter14_c | csr_mhpmcounter14_c => if (HPM_NUM_CNTS > 11) then csr.rdata <= csr.mhpmcounter_rd(11); else NULL; end if; -- (R)/(W): [m]hpmcounter14 - low
|
when csr_mhpmcounter14_c => if (HPM_NUM_CNTS > 11) then csr.rdata <= csr.mhpmcounter_rd(11); else NULL; end if; -- r/w: mhpmcounter14 - low
|
when csr_hpmcounter15_c | csr_mhpmcounter15_c => if (HPM_NUM_CNTS > 12) then csr.rdata <= csr.mhpmcounter_rd(12); else NULL; end if; -- (R)/(W): [m]hpmcounter15 - low
|
when csr_mhpmcounter15_c => if (HPM_NUM_CNTS > 12) then csr.rdata <= csr.mhpmcounter_rd(12); else NULL; end if; -- r/w: mhpmcounter15 - low
|
when csr_hpmcounter16_c | csr_mhpmcounter16_c => if (HPM_NUM_CNTS > 13) then csr.rdata <= csr.mhpmcounter_rd(13); else NULL; end if; -- (R)/(W): [m]hpmcounter16 - low
|
when csr_mhpmcounter16_c => if (HPM_NUM_CNTS > 13) then csr.rdata <= csr.mhpmcounter_rd(13); else NULL; end if; -- r/w: mhpmcounter16 - low
|
when csr_hpmcounter17_c | csr_mhpmcounter17_c => if (HPM_NUM_CNTS > 14) then csr.rdata <= csr.mhpmcounter_rd(14); else NULL; end if; -- (R)/(W): [m]hpmcounter17 - low
|
when csr_mhpmcounter17_c => if (HPM_NUM_CNTS > 14) then csr.rdata <= csr.mhpmcounter_rd(14); else NULL; end if; -- r/w: mhpmcounter17 - low
|
when csr_hpmcounter18_c | csr_mhpmcounter18_c => if (HPM_NUM_CNTS > 15) then csr.rdata <= csr.mhpmcounter_rd(15); else NULL; end if; -- (R)/(W): [m]hpmcounter18 - low
|
when csr_mhpmcounter18_c => if (HPM_NUM_CNTS > 15) then csr.rdata <= csr.mhpmcounter_rd(15); else NULL; end if; -- r/w: mhpmcounter18 - low
|
when csr_hpmcounter19_c | csr_mhpmcounter19_c => if (HPM_NUM_CNTS > 16) then csr.rdata <= csr.mhpmcounter_rd(16); else NULL; end if; -- (R)/(W): [m]hpmcounter19 - low
|
when csr_mhpmcounter19_c => if (HPM_NUM_CNTS > 16) then csr.rdata <= csr.mhpmcounter_rd(16); else NULL; end if; -- r/w: mhpmcounter19 - low
|
when csr_hpmcounter20_c | csr_mhpmcounter20_c => if (HPM_NUM_CNTS > 17) then csr.rdata <= csr.mhpmcounter_rd(17); else NULL; end if; -- (R)/(W): [m]hpmcounter20 - low
|
when csr_mhpmcounter20_c => if (HPM_NUM_CNTS > 17) then csr.rdata <= csr.mhpmcounter_rd(17); else NULL; end if; -- r/w: mhpmcounter20 - low
|
when csr_hpmcounter21_c | csr_mhpmcounter21_c => if (HPM_NUM_CNTS > 18) then csr.rdata <= csr.mhpmcounter_rd(18); else NULL; end if; -- (R)/(W): [m]hpmcounter21 - low
|
when csr_mhpmcounter21_c => if (HPM_NUM_CNTS > 18) then csr.rdata <= csr.mhpmcounter_rd(18); else NULL; end if; -- r/w: mhpmcounter21 - low
|
when csr_hpmcounter22_c | csr_mhpmcounter22_c => if (HPM_NUM_CNTS > 19) then csr.rdata <= csr.mhpmcounter_rd(19); else NULL; end if; -- (R)/(W): [m]hpmcounter22 - low
|
when csr_mhpmcounter22_c => if (HPM_NUM_CNTS > 19) then csr.rdata <= csr.mhpmcounter_rd(19); else NULL; end if; -- r/w: mhpmcounter22 - low
|
when csr_hpmcounter23_c | csr_mhpmcounter23_c => if (HPM_NUM_CNTS > 20) then csr.rdata <= csr.mhpmcounter_rd(20); else NULL; end if; -- (R)/(W): [m]hpmcounter23 - low
|
when csr_mhpmcounter23_c => if (HPM_NUM_CNTS > 20) then csr.rdata <= csr.mhpmcounter_rd(20); else NULL; end if; -- r/w: mhpmcounter23 - low
|
when csr_hpmcounter24_c | csr_mhpmcounter24_c => if (HPM_NUM_CNTS > 21) then csr.rdata <= csr.mhpmcounter_rd(21); else NULL; end if; -- (R)/(W): [m]hpmcounter24 - low
|
when csr_mhpmcounter24_c => if (HPM_NUM_CNTS > 21) then csr.rdata <= csr.mhpmcounter_rd(21); else NULL; end if; -- r/w: mhpmcounter24 - low
|
when csr_hpmcounter25_c | csr_mhpmcounter25_c => if (HPM_NUM_CNTS > 22) then csr.rdata <= csr.mhpmcounter_rd(22); else NULL; end if; -- (R)/(W): [m]hpmcounter25 - low
|
when csr_mhpmcounter25_c => if (HPM_NUM_CNTS > 22) then csr.rdata <= csr.mhpmcounter_rd(22); else NULL; end if; -- r/w: mhpmcounter25 - low
|
when csr_hpmcounter26_c | csr_mhpmcounter26_c => if (HPM_NUM_CNTS > 23) then csr.rdata <= csr.mhpmcounter_rd(23); else NULL; end if; -- (R)/(W): [m]hpmcounter26 - low
|
when csr_mhpmcounter26_c => if (HPM_NUM_CNTS > 23) then csr.rdata <= csr.mhpmcounter_rd(23); else NULL; end if; -- r/w: mhpmcounter26 - low
|
when csr_hpmcounter27_c | csr_mhpmcounter27_c => if (HPM_NUM_CNTS > 24) then csr.rdata <= csr.mhpmcounter_rd(24); else NULL; end if; -- (R)/(W): [m]hpmcounter27 - low
|
when csr_mhpmcounter27_c => if (HPM_NUM_CNTS > 24) then csr.rdata <= csr.mhpmcounter_rd(24); else NULL; end if; -- r/w: mhpmcounter27 - low
|
when csr_hpmcounter28_c | csr_mhpmcounter28_c => if (HPM_NUM_CNTS > 25) then csr.rdata <= csr.mhpmcounter_rd(25); else NULL; end if; -- (R)/(W): [m]hpmcounter28 - low
|
when csr_mhpmcounter28_c => if (HPM_NUM_CNTS > 25) then csr.rdata <= csr.mhpmcounter_rd(25); else NULL; end if; -- r/w: mhpmcounter28 - low
|
when csr_hpmcounter29_c | csr_mhpmcounter29_c => if (HPM_NUM_CNTS > 26) then csr.rdata <= csr.mhpmcounter_rd(26); else NULL; end if; -- (R)/(W): [m]hpmcounter29 - low
|
when csr_mhpmcounter29_c => if (HPM_NUM_CNTS > 26) then csr.rdata <= csr.mhpmcounter_rd(26); else NULL; end if; -- r/w: mhpmcounter29 - low
|
when csr_hpmcounter30_c | csr_mhpmcounter30_c => if (HPM_NUM_CNTS > 27) then csr.rdata <= csr.mhpmcounter_rd(27); else NULL; end if; -- (R)/(W): [m]hpmcounter30 - low
|
when csr_mhpmcounter30_c => if (HPM_NUM_CNTS > 27) then csr.rdata <= csr.mhpmcounter_rd(27); else NULL; end if; -- r/w: mhpmcounter30 - low
|
when csr_hpmcounter31_c | csr_mhpmcounter31_c => if (HPM_NUM_CNTS > 28) then csr.rdata <= csr.mhpmcounter_rd(28); else NULL; end if; -- (R)/(W): [m]hpmcounter31 - low
|
when csr_mhpmcounter31_c => if (HPM_NUM_CNTS > 28) then csr.rdata <= csr.mhpmcounter_rd(28); else NULL; end if; -- r/w: mhpmcounter31 - low
|
|
|
when csr_hpmcounter3h_c | csr_mhpmcounter3h_c => if (HPM_NUM_CNTS > 00) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(00); else NULL; end if; -- (R)/(W): [m]hpmcounter3h - high
|
when csr_mhpmcounter3h_c => if (HPM_NUM_CNTS > 00) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(00); else NULL; end if; -- r/w: mhpmcounter3h - high
|
when csr_hpmcounter4h_c | csr_mhpmcounter4h_c => if (HPM_NUM_CNTS > 01) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(01); else NULL; end if; -- (R)/(W): [m]hpmcounter4h - high
|
when csr_mhpmcounter4h_c => if (HPM_NUM_CNTS > 01) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(01); else NULL; end if; -- r/w: mhpmcounter4h - high
|
when csr_hpmcounter5h_c | csr_mhpmcounter5h_c => if (HPM_NUM_CNTS > 02) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(02); else NULL; end if; -- (R)/(W): [m]hpmcounter5h - high
|
when csr_mhpmcounter5h_c => if (HPM_NUM_CNTS > 02) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(02); else NULL; end if; -- r/w: mhpmcounter5h - high
|
when csr_hpmcounter6h_c | csr_mhpmcounter6h_c => if (HPM_NUM_CNTS > 03) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(03); else NULL; end if; -- (R)/(W): [m]hpmcounter6h - high
|
when csr_mhpmcounter6h_c => if (HPM_NUM_CNTS > 03) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(03); else NULL; end if; -- r/w: mhpmcounter6h - high
|
when csr_hpmcounter7h_c | csr_mhpmcounter7h_c => if (HPM_NUM_CNTS > 04) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(04); else NULL; end if; -- (R)/(W): [m]hpmcounter7h - high
|
when csr_mhpmcounter7h_c => if (HPM_NUM_CNTS > 04) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(04); else NULL; end if; -- r/w: mhpmcounter7h - high
|
when csr_hpmcounter8h_c | csr_mhpmcounter8h_c => if (HPM_NUM_CNTS > 05) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(05); else NULL; end if; -- (R)/(W): [m]hpmcounter8h - high
|
when csr_mhpmcounter8h_c => if (HPM_NUM_CNTS > 05) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(05); else NULL; end if; -- r/w: mhpmcounter8h - high
|
when csr_hpmcounter9h_c | csr_mhpmcounter9h_c => if (HPM_NUM_CNTS > 06) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(06); else NULL; end if; -- (R)/(W): [m]hpmcounter9h - high
|
when csr_mhpmcounter9h_c => if (HPM_NUM_CNTS > 06) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(06); else NULL; end if; -- r/w: mhpmcounter9h - high
|
when csr_hpmcounter10h_c | csr_mhpmcounter10h_c => if (HPM_NUM_CNTS > 07) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(07); else NULL; end if; -- (R)/(W): [m]hpmcounter10h - high
|
when csr_mhpmcounter10h_c => if (HPM_NUM_CNTS > 07) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(07); else NULL; end if; -- r/w: mhpmcounter10h - high
|
when csr_hpmcounter11h_c | csr_mhpmcounter11h_c => if (HPM_NUM_CNTS > 08) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(08); else NULL; end if; -- (R)/(W): [m]hpmcounter11h - high
|
when csr_mhpmcounter11h_c => if (HPM_NUM_CNTS > 08) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(08); else NULL; end if; -- r/w: mhpmcounter11h - high
|
when csr_hpmcounter12h_c | csr_mhpmcounter12h_c => if (HPM_NUM_CNTS > 09) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(09); else NULL; end if; -- (R)/(W): [m]hpmcounter12h - high
|
when csr_mhpmcounter12h_c => if (HPM_NUM_CNTS > 09) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(09); else NULL; end if; -- r/w: mhpmcounter12h - high
|
when csr_hpmcounter13h_c | csr_mhpmcounter13h_c => if (HPM_NUM_CNTS > 10) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(10); else NULL; end if; -- (R)/(W): [m]hpmcounter13h - high
|
when csr_mhpmcounter13h_c => if (HPM_NUM_CNTS > 10) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(10); else NULL; end if; -- r/w: mhpmcounter13h - high
|
when csr_hpmcounter14h_c | csr_mhpmcounter14h_c => if (HPM_NUM_CNTS > 11) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(11); else NULL; end if; -- (R)/(W): [m]hpmcounter14h - high
|
when csr_mhpmcounter14h_c => if (HPM_NUM_CNTS > 11) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(11); else NULL; end if; -- r/w: mhpmcounter14h - high
|
when csr_hpmcounter15h_c | csr_mhpmcounter15h_c => if (HPM_NUM_CNTS > 12) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(12); else NULL; end if; -- (R)/(W): [m]hpmcounter15h - high
|
when csr_mhpmcounter15h_c => if (HPM_NUM_CNTS > 12) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(12); else NULL; end if; -- r/w: mhpmcounter15h - high
|
when csr_hpmcounter16h_c | csr_mhpmcounter16h_c => if (HPM_NUM_CNTS > 13) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(13); else NULL; end if; -- (R)/(W): [m]hpmcounter16h - high
|
when csr_mhpmcounter16h_c => if (HPM_NUM_CNTS > 13) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(13); else NULL; end if; -- r/w: mhpmcounter16h - high
|
when csr_hpmcounter17h_c | csr_mhpmcounter17h_c => if (HPM_NUM_CNTS > 14) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(14); else NULL; end if; -- (R)/(W): [m]hpmcounter17h - high
|
when csr_mhpmcounter17h_c => if (HPM_NUM_CNTS > 14) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(14); else NULL; end if; -- r/w: mhpmcounter17h - high
|
when csr_hpmcounter18h_c | csr_mhpmcounter18h_c => if (HPM_NUM_CNTS > 15) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(15); else NULL; end if; -- (R)/(W): [m]hpmcounter18h - high
|
when csr_mhpmcounter18h_c => if (HPM_NUM_CNTS > 15) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(15); else NULL; end if; -- r/w: mhpmcounter18h - high
|
when csr_hpmcounter19h_c | csr_mhpmcounter19h_c => if (HPM_NUM_CNTS > 16) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(16); else NULL; end if; -- (R)/(W): [m]hpmcounter19h - high
|
when csr_mhpmcounter19h_c => if (HPM_NUM_CNTS > 16) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(16); else NULL; end if; -- r/w: mhpmcounter19h - high
|
when csr_hpmcounter20h_c | csr_mhpmcounter20h_c => if (HPM_NUM_CNTS > 17) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(17); else NULL; end if; -- (R)/(W): [m]hpmcounter20h - high
|
when csr_mhpmcounter20h_c => if (HPM_NUM_CNTS > 17) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(17); else NULL; end if; -- r/w: mhpmcounter20h - high
|
when csr_hpmcounter21h_c | csr_mhpmcounter21h_c => if (HPM_NUM_CNTS > 18) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(18); else NULL; end if; -- (R)/(W): [m]hpmcounter21h - high
|
when csr_mhpmcounter21h_c => if (HPM_NUM_CNTS > 18) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(18); else NULL; end if; -- r/w: mhpmcounter21h - high
|
when csr_hpmcounter22h_c | csr_mhpmcounter22h_c => if (HPM_NUM_CNTS > 19) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(19); else NULL; end if; -- (R)/(W): [m]hpmcounter22h - high
|
when csr_mhpmcounter22h_c => if (HPM_NUM_CNTS > 19) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(19); else NULL; end if; -- r/w: mhpmcounter22h - high
|
when csr_hpmcounter23h_c | csr_mhpmcounter23h_c => if (HPM_NUM_CNTS > 20) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(20); else NULL; end if; -- (R)/(W): [m]hpmcounter23h - high
|
when csr_mhpmcounter23h_c => if (HPM_NUM_CNTS > 20) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(20); else NULL; end if; -- r/w: mhpmcounter23h - high
|
when csr_hpmcounter24h_c | csr_mhpmcounter24h_c => if (HPM_NUM_CNTS > 21) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(21); else NULL; end if; -- (R)/(W): [m]hpmcounter24h - high
|
when csr_mhpmcounter24h_c => if (HPM_NUM_CNTS > 21) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(21); else NULL; end if; -- r/w: mhpmcounter24h - high
|
when csr_hpmcounter25h_c | csr_mhpmcounter25h_c => if (HPM_NUM_CNTS > 22) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(22); else NULL; end if; -- (R)/(W): [m]hpmcounter25h - high
|
when csr_mhpmcounter25h_c => if (HPM_NUM_CNTS > 22) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(22); else NULL; end if; -- r/w: mhpmcounter25h - high
|
when csr_hpmcounter26h_c | csr_mhpmcounter26h_c => if (HPM_NUM_CNTS > 23) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(23); else NULL; end if; -- (R)/(W): [m]hpmcounter26h - high
|
when csr_mhpmcounter26h_c => if (HPM_NUM_CNTS > 23) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(23); else NULL; end if; -- r/w: mhpmcounter26h - high
|
when csr_hpmcounter27h_c | csr_mhpmcounter27h_c => if (HPM_NUM_CNTS > 24) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(24); else NULL; end if; -- (R)/(W): [m]hpmcounter27h - high
|
when csr_mhpmcounter27h_c => if (HPM_NUM_CNTS > 24) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(24); else NULL; end if; -- r/w: mhpmcounter27h - high
|
when csr_hpmcounter28h_c | csr_mhpmcounter28h_c => if (HPM_NUM_CNTS > 25) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(25); else NULL; end if; -- (R)/(W): [m]hpmcounter28h - high
|
when csr_mhpmcounter28h_c => if (HPM_NUM_CNTS > 25) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(25); else NULL; end if; -- r/w: mhpmcounter28h - high
|
when csr_hpmcounter29h_c | csr_mhpmcounter29h_c => if (HPM_NUM_CNTS > 26) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(26); else NULL; end if; -- (R)/(W): [m]hpmcounter29h - high
|
when csr_mhpmcounter29h_c => if (HPM_NUM_CNTS > 26) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(26); else NULL; end if; -- r/w: mhpmcounter29h - high
|
when csr_hpmcounter30h_c | csr_mhpmcounter30h_c => if (HPM_NUM_CNTS > 27) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(27); else NULL; end if; -- (R)/(W): [m]hpmcounter30h - high
|
when csr_mhpmcounter30h_c => if (HPM_NUM_CNTS > 27) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(27); else NULL; end if; -- r/w: mhpmcounter30h - high
|
when csr_hpmcounter31h_c | csr_mhpmcounter31h_c => if (HPM_NUM_CNTS > 28) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(28); else NULL; end if; -- (R)/(W): [m]hpmcounter31h - high
|
when csr_mhpmcounter31h_c => if (HPM_NUM_CNTS > 28) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(28); else NULL; end if; -- r/w: mhpmcounter31h - high
|
|
|
-- machine information registers --
|
-- machine information registers --
|
-- --------------------------------------------------------------------
|
-- --------------------------------------------------------------------
|
when csr_mvendorid_c => csr.rdata <= (others => '0'); -- mvendorid (r/-): vendor ID
|
-- when csr_mvendorid_c => csr.rdata <= (others => '0'); -- mvendorid (r/-): vendor ID, implemented but always zero
|
when csr_marchid_c => csr.rdata(4 downto 0) <= "10011"; -- marchid (r/-): arch ID - official RISC-V open-source arch ID
|
when csr_marchid_c => csr.rdata(4 downto 0) <= "10011"; -- marchid (r/-): arch ID - official RISC-V open-source arch ID
|
when csr_mimpid_c => csr.rdata <= hw_version_c; -- mimpid (r/-): implementation ID -- NEORV32 hardware version
|
when csr_mimpid_c => csr.rdata <= hw_version_c; -- mimpid (r/-): implementation ID -- NEORV32 hardware version
|
when csr_mhartid_c => csr.rdata <= std_ulogic_vector(to_unsigned(HW_THREAD_ID, 32)); -- mhartid (r/-): hardware thread ID
|
when csr_mhartid_c => csr.rdata <= std_ulogic_vector(to_unsigned(HW_THREAD_ID, 32)); -- mhartid (r/-): hardware thread ID
|
|
|
-- custom machine read-only CSRs --
|
-- custom machine read-only CSRs --
|
-- --------------------------------------------------------------------
|
-- --------------------------------------------------------------------
|
when csr_mzext_c => -- mzext (r/-): available RISC-V Z* sub-extensions
|
when csr_mzext_c => -- mzext (r/-): available RISC-V Z* sub-extensions
|
csr.rdata(0) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zicsr); -- Zicsr
|
csr.rdata(0) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zicsr); -- Zicsr
|
csr.rdata(1) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zifencei); -- Zifencei
|
csr.rdata(1) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zifencei); -- Zifencei
|
|
csr.rdata(2) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zmmul); -- Zmmul
|
|
-- ... --
|
csr.rdata(5) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zfinx); -- Zfinx ("F-alternative")
|
csr.rdata(5) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zfinx); -- Zfinx ("F-alternative")
|
if (CPU_CNT_WIDTH = 64) then
|
if (CPU_CNT_WIDTH = 64) then
|
csr.rdata(6) <= '0'; -- Zxscnt (custom)
|
csr.rdata(6) <= '0'; -- Zxscnt (custom)
|
csr.rdata(7) <= '0'; -- Zxnocnt (custom)
|
csr.rdata(7) <= '0'; -- Zxnocnt (custom)
|
elsif (CPU_CNT_WIDTH = 0) then
|
elsif (CPU_CNT_WIDTH = 0) then
|