Line 51... |
Line 51... |
HW_THREAD_ID : natural := 0; -- hardware thread id (32-bit)
|
HW_THREAD_ID : natural := 0; -- hardware thread id (32-bit)
|
CPU_BOOT_ADDR : std_ulogic_vector(31 downto 0) := x"00000000"; -- cpu boot address
|
CPU_BOOT_ADDR : std_ulogic_vector(31 downto 0) := x"00000000"; -- cpu boot address
|
CPU_DEBUG_ADDR : std_ulogic_vector(31 downto 0) := x"00000000"; -- cpu debug mode start address
|
CPU_DEBUG_ADDR : std_ulogic_vector(31 downto 0) := x"00000000"; -- cpu debug mode start address
|
-- RISC-V CPU Extensions --
|
-- RISC-V CPU Extensions --
|
CPU_EXTENSION_RISCV_A : boolean := false; -- implement atomic extension?
|
CPU_EXTENSION_RISCV_A : boolean := false; -- implement atomic extension?
|
CPU_EXTENSION_RISCV_B : boolean := false; -- implement bit manipulation extensions?
|
|
CPU_EXTENSION_RISCV_C : boolean := false; -- implement compressed extension?
|
CPU_EXTENSION_RISCV_C : boolean := false; -- implement compressed extension?
|
CPU_EXTENSION_RISCV_E : boolean := false; -- implement embedded RF extension?
|
CPU_EXTENSION_RISCV_E : boolean := false; -- implement embedded RF extension?
|
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!)
|
Line 67... |
Line 66... |
-- 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)
|
PMP_MIN_GRANULARITY : natural := 64*1024; -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes
|
PMP_MIN_GRANULARITY : natural := 64*1024; -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes
|
-- Hardware Performance Monitors (HPM) --
|
-- Hardware Performance Monitors (HPM) --
|
HPM_NUM_CNTS : natural := 0; -- number of implemented HPM counters (0..29)
|
HPM_NUM_CNTS : natural := 0; -- number of implemented HPM counters (0..29)
|
HPM_CNT_WIDTH : natural := 40 -- total size of HPM counters (1..64)
|
HPM_CNT_WIDTH : natural := 40 -- total size of HPM counters (0..64)
|
);
|
);
|
port (
|
port (
|
-- 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
|
Line 196... |
Line 195... |
type decode_aux_t is record
|
type decode_aux_t is record
|
alu_immediate : std_ulogic;
|
alu_immediate : std_ulogic;
|
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_bitmanip_imm : std_ulogic;
|
|
is_bitmanip_reg : 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);
|
end record;
|
end record;
|
signal decode_aux : decode_aux_t;
|
signal decode_aux : decode_aux_t;
|
|
|
Line 318... |
Line 315... |
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(32 downto 0); -- mcycle (R/W), plus carry bit
|
minstret : std_ulogic_vector(32 downto 0); -- minstret (R/W), plus carry bit
|
mcycle_msb : std_ulogic; -- 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_msb : std_ulogic; -- 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
|
mhpmcounterh : mhpmcnth_t; -- mhpmcounter*h (R/W)
|
mhpmcounterh : mhpmcnth_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 : mhpmcnth_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
|
Line 337... |
Line 337... |
fflags : std_ulogic_vector(04 downto 0); -- fflags (R/W): FPU exception flags
|
fflags : std_ulogic_vector(04 downto 0); -- fflags (R/W): FPU exception flags
|
--
|
--
|
dcsr_ebreakm : std_ulogic; -- dcsr.ebreakm (R/W): behavior of ebreak instruction on m-mode
|
dcsr_ebreakm : std_ulogic; -- dcsr.ebreakm (R/W): behavior of ebreak instruction on m-mode
|
dcsr_ebreaku : std_ulogic; -- dcsr.ebreaku (R/W): behavior of ebreak instruction on u-mode
|
dcsr_ebreaku : std_ulogic; -- dcsr.ebreaku (R/W): behavior of ebreak instruction on u-mode
|
dcsr_step : std_ulogic; -- dcsr.step (R/W): single-step mode
|
dcsr_step : std_ulogic; -- dcsr.step (R/W): single-step mode
|
dcsr_stepie : std_ulogic; -- dcsr.stepie (R/W): enable IRQs in single-step mode
|
|
dcsr_prv : std_ulogic_vector(01 downto 0); -- dcsr.prv (R/W): current privilege level when entering debug mode
|
dcsr_prv : std_ulogic_vector(01 downto 0); -- dcsr.prv (R/W): current privilege level when entering debug mode
|
dcsr_cause : std_ulogic_vector(02 downto 0); -- dcsr.cause (R/-): why was debug mode entered
|
dcsr_cause : std_ulogic_vector(02 downto 0); -- dcsr.cause (R/-): why was debug mode entered
|
dcsr_rd : std_ulogic_vector(data_width_c-1 downto 0); -- dcsr (R/(W)): debug mode control and status register
|
dcsr_rd : std_ulogic_vector(data_width_c-1 downto 0); -- dcsr (R/(W)): debug mode control and status register
|
dpc : std_ulogic_vector(data_width_c-1 downto 0); -- dpc (R/W): debug mode program counter
|
dpc : std_ulogic_vector(data_width_c-1 downto 0); -- dpc (R/W): debug mode program counter
|
dscratch0 : std_ulogic_vector(data_width_c-1 downto 0); -- dscratch0 (R/W): debug mode scratch register 0
|
dscratch0 : std_ulogic_vector(data_width_c-1 downto 0); -- dscratch0 (R/W): debug mode scratch register 0
|
Line 364... |
Line 363... |
-- misc --
|
-- misc --
|
ext_halt_req : std_ulogic_vector(1 downto 0); -- rising edge detector for external halt request
|
ext_halt_req : std_ulogic_vector(1 downto 0); -- rising edge detector for external halt request
|
end record;
|
end record;
|
signal debug_ctrl : debug_ctrl_t;
|
signal debug_ctrl : debug_ctrl_t;
|
|
|
-- counter low-to-high-word carry --
|
|
signal mcycle_msb : std_ulogic;
|
|
signal minstret_msb : std_ulogic;
|
|
signal mhpmcounter_msb : std_ulogic_vector(HPM_NUM_CNTS-1 downto 0);
|
|
|
|
-- (hpm) counter events --
|
-- (hpm) counter events --
|
signal cnt_event, cnt_event_nxt : std_ulogic_vector(hpmcnt_event_size_c-1 downto 0);
|
signal cnt_event, cnt_event_nxt : std_ulogic_vector(hpmcnt_event_size_c-1 downto 0);
|
signal hpmcnt_trigger : std_ulogic_vector(HPM_NUM_CNTS-1 downto 0);
|
signal hpmcnt_trigger : std_ulogic_vector(HPM_NUM_CNTS-1 downto 0);
|
|
|
-- illegal instruction check --
|
-- illegal instruction check --
|
Line 800... |
Line 794... |
csr.addr <= execute_engine.i_reg(instr_csr_id_msb_c downto instr_csr_id_lsb_c);
|
csr.addr <= execute_engine.i_reg(instr_csr_id_msb_c downto instr_csr_id_lsb_c);
|
|
|
|
|
-- CPU Control Bus Output -----------------------------------------------------------------
|
-- CPU Control Bus Output -----------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
ctrl_output: process(ctrl, fetch_engine, trap_ctrl, bus_fast_ir, execute_engine, csr)
|
ctrl_output: process(ctrl, fetch_engine, trap_ctrl, bus_fast_ir, execute_engine, csr, debug_ctrl)
|
begin
|
begin
|
-- signals from execute engine --
|
-- signals from execute engine --
|
ctrl_o <= ctrl;
|
ctrl_o <= ctrl;
|
-- current privilege level --
|
-- current privilege level --
|
ctrl_o(ctrl_priv_lvl_msb_c downto ctrl_priv_lvl_lsb_c) <= csr.privilege_rd;
|
ctrl_o(ctrl_priv_lvl_msb_c downto ctrl_priv_lvl_lsb_c) <= csr.privilege_rd;
|
Line 846... |
Line 840... |
-- defaults --
|
-- defaults --
|
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_bitmanip_imm <= '0';
|
|
decode_aux.is_bitmanip_reg <= '0';
|
|
decode_aux.is_float_op <= '0';
|
decode_aux.is_float_op <= '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? --
|
decode_aux.rs1_is_r0 <= not or_all_f(execute_engine.i_reg(instr_rs1_msb_c downto instr_rs1_lsb_c));
|
decode_aux.rs1_is_r0 <= not or_reduce_f(execute_engine.i_reg(instr_rs1_msb_c downto instr_rs1_lsb_c));
|
|
|
-- is atomic load-reservate/store-conditional? --
|
-- is atomic load-reservate/store-conditional? --
|
if (CPU_EXTENSION_RISCV_A = true) and (execute_engine.i_reg(instr_opcode_lsb_c+3 downto instr_opcode_lsb_c+2) = "11") then -- valid atomic sub-opcode
|
if (CPU_EXTENSION_RISCV_A = true) and (execute_engine.i_reg(instr_opcode_lsb_c+3 downto instr_opcode_lsb_c+2) = "11") then -- valid atomic sub-opcode
|
decode_aux.is_atomic_lr <= not execute_engine.i_reg(instr_funct5_lsb_c);
|
decode_aux.is_atomic_lr <= not execute_engine.i_reg(instr_funct5_lsb_c);
|
decode_aux.is_atomic_sc <= execute_engine.i_reg(instr_funct5_lsb_c);
|
decode_aux.is_atomic_sc <= execute_engine.i_reg(instr_funct5_lsb_c);
|
end if;
|
end if;
|
|
|
-- is BITMANIP instruction? --
|
|
-- pretty complex as we have to extract this from the ALU/ALUI instruction space --
|
|
-- immediate operation --
|
|
if ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0110000") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "001") and
|
|
(
|
|
(execute_engine.i_reg(instr_funct12_lsb_c+4 downto instr_funct12_lsb_c) = "00000") or -- CLZ
|
|
(execute_engine.i_reg(instr_funct12_lsb_c+4 downto instr_funct12_lsb_c) = "00001") or -- CTZ
|
|
(execute_engine.i_reg(instr_funct12_lsb_c+4 downto instr_funct12_lsb_c) = "00010") or -- PCNT
|
|
(execute_engine.i_reg(instr_funct12_lsb_c+4 downto instr_funct12_lsb_c) = "00100") or -- SEXT.B
|
|
(execute_engine.i_reg(instr_funct12_lsb_c+4 downto instr_funct12_lsb_c) = "00101") -- SEXT.H
|
|
)
|
|
) or
|
|
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "01001") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "001")) or -- SBCLRI
|
|
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "00101") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "001")) or -- SBSETI
|
|
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "01101") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "001")) or -- SBINVI
|
|
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "01001") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "101")) or -- SBEXTI
|
|
--
|
|
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "01100") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "101")) or -- RORI
|
|
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "00101") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "101") and (execute_engine.i_reg(instr_imm12_lsb_c+6 downto instr_imm12_lsb_c) = "0000111")) or -- GORCI.b 7 (orc.b)
|
|
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "01101") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "101") and (execute_engine.i_reg(instr_imm12_lsb_c+6 downto instr_imm12_lsb_c) = "0011000")) then -- GREVI.-8 (rev8)
|
|
decode_aux.is_bitmanip_imm <= '1';
|
|
end if;
|
|
-- register operation --
|
|
if ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0110000") and (execute_engine.i_reg(instr_funct3_msb_c-1 downto instr_funct3_lsb_c) = "01")) or -- ROR / ROL
|
|
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0000101") and (execute_engine.i_reg(instr_funct3_msb_c) = '1')) or -- MIN[U] / MAX[U]
|
|
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0000100") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "100")) or -- PACK
|
|
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0100000") and
|
|
(
|
|
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "111") or -- ANDN
|
|
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "110") or -- ORN
|
|
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "100") -- XORN
|
|
)
|
|
) or
|
|
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0010000") and
|
|
(
|
|
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "010") or -- SH1ADD
|
|
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "100") or -- SH2ADD
|
|
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "110") -- SH3ADD
|
|
)
|
|
) or
|
|
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0100100") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "001")) or -- SBCLR
|
|
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0010100") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "001")) or -- SBSET
|
|
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0110100") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "001")) or -- SBINV
|
|
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0100100") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "101")) then -- SBSEXT
|
|
decode_aux.is_bitmanip_reg <= '1';
|
|
end if;
|
|
|
|
-- floating-point operations (Zfinx) --
|
-- floating-point operations (Zfinx) --
|
if ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+3) = "0000")) or -- FADD.S / FSUB.S
|
if ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+3) = "0000")) or -- FADD.S / FSUB.S
|
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "00010")) or -- FMUL.S
|
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "00010")) or -- FMUL.S
|
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "11100") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "001")) or -- FCLASS.S
|
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "11100") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "001")) or -- FCLASS.S
|
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "00100") and (execute_engine.i_reg(instr_funct3_msb_c) = '0')) or -- FSGNJ[N/X].S
|
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "00100") and (execute_engine.i_reg(instr_funct3_msb_c) = '0')) or -- FSGNJ[N/X].S
|
Line 923... |
Line 868... |
decode_aux.is_float_op <= '1';
|
decode_aux.is_float_op <= '1';
|
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(11 downto 0) <= execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) and sys_env_cmd_mask_v; -- set unsued 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
|
end process decode_helper;
|
end process decode_helper;
|
|
|
|
|
-- Execute Engine FSM Comb ----------------------------------------------------------------
|
-- Execute Engine FSM Comb ----------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
Line 1039... |
Line 984... |
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 (csr.mtvec)
|
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
|
execute_engine.state_nxt <= SYS_WAIT;
|
execute_engine.state_nxt <= SYS_WAIT;
|
|
|
|
|
when EXECUTE => -- Decode and execute instruction (control has to be here for excatly 1 cyle in any case!)
|
when EXECUTE => -- Decode and execute instruction (control has to be here for exactly 1 cycle in any case!)
|
-- ------------------------------------------------------------
|
-- ------------------------------------------------------------
|
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_alu_c | opcode_alui_c => -- (immediate) ALU operation
|
when opcode_alu_c | opcode_alui_c => -- (register/immediate) ALU operation
|
-- ------------------------------------------------------------
|
-- ------------------------------------------------------------
|
ctrl_nxt(ctrl_alu_opa_mux_c) <= '0'; -- use RS1 as ALU.OPA
|
ctrl_nxt(ctrl_alu_opa_mux_c) <= '0'; -- use RS1 as ALU.OPA
|
ctrl_nxt(ctrl_alu_opb_mux_c) <= decode_aux.alu_immediate; -- use IMM as ALU.OPB for immediate operations
|
ctrl_nxt(ctrl_alu_opb_mux_c) <= decode_aux.alu_immediate; -- use IMM as ALU.OPB for immediate operations
|
ctrl_nxt(ctrl_rf_in_mux_c) <= '0'; -- RF input = ALU result
|
ctrl_nxt(ctrl_rf_in_mux_c) <= '0'; -- RF input = ALU result
|
|
|
-- ALU arithmetic operation type and ADD/SUB --
|
-- ALU arithmetic operation type --
|
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_slt_c) or
|
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_slt_c) or
|
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sltu_c) then
|
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sltu_c) then
|
ctrl_nxt(ctrl_alu_arith_c) <= alu_arith_cmd_slt_c;
|
ctrl_nxt(ctrl_alu_arith_c) <= alu_arith_cmd_slt_c;
|
else
|
else
|
ctrl_nxt(ctrl_alu_arith_c) <= alu_arith_cmd_addsub_c;
|
ctrl_nxt(ctrl_alu_arith_c) <= alu_arith_cmd_addsub_c;
|
Line 1088... |
Line 1033... |
-- 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 (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?
|
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
|
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;
|
-- co-processor bit manipulation operation? --
|
|
elsif (CPU_EXTENSION_RISCV_B = true) and
|
|
(((execute_engine.i_reg(instr_opcode_lsb_c+5) = opcode_alu_c(5)) and (decode_aux.is_bitmanip_reg = '1')) or -- register operation
|
|
((execute_engine.i_reg(instr_opcode_lsb_c+5) = opcode_alui_c(5)) and (decode_aux.is_bitmanip_imm = '1'))) then -- immediate operation
|
|
ctrl_nxt(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) <= cp_sel_bitmanip_c; -- use BITMANIP CP
|
|
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;
|
|
-- ALU operation, function select --
|
-- ALU operation, function select --
|
else
|
else
|
execute_engine.is_cp_op_nxt <= '0'; -- no CP operation
|
execute_engine.is_cp_op_nxt <= '0'; -- no CP operation
|
case execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) is -- actual ALU.func operation (re-coding)
|
case execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) is -- actual ALU.func operation (re-coding)
|
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;
|
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;
|
Line 1108... |
Line 1046... |
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')) or -- MULDIV CP op?
|
((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_B = true) and (
|
|
((execute_engine.i_reg(instr_opcode_lsb_c+5) = opcode_alu_c(5)) and (decode_aux.is_bitmanip_reg = '1')) or -- BITMANIP CP register operation?
|
|
((execute_engine.i_reg(instr_opcode_lsb_c+5) = opcode_alui_c(5)) and (decode_aux.is_bitmanip_imm = '1'))) ) then -- BITMANIP CP immediate operation?
|
|
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 1206... |
Line 1141... |
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 =>
|
when funct12_wfi_c => -- WFI
|
if (CPU_EXTENSION_RISCV_DEBUG = true) and (debug_ctrl.running = '1') then
|
if (CPU_EXTENSION_RISCV_DEBUG = true) and (debug_ctrl.running = '1') then
|
NULL; -- just a NOP when in debug mode
|
NULL; -- just a NOP when in debug mode
|
else
|
else
|
execute_engine.sleep_nxt <= '1'; -- WFI (normal)
|
execute_engine.sleep_nxt <= '1'; -- WFI (normal)
|
end if;
|
end if;
|
Line 1364... |
Line 1299... |
-- 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_all_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? --
|
-- low privilege level access to hpm counters? --
|
csr_mcounteren_hpm_v := (others => '0');
|
csr_mcounteren_hpm_v := (others => '0');
|
if (CPU_EXTENSION_RISCV_U = true) and (HPM_NUM_CNTS /= 0) then
|
if (CPU_EXTENSION_RISCV_U = true) and (HPM_NUM_CNTS /= 0) then
|
Line 1387... |
Line 1322... |
csr_acc_valid <= '1'; -- full access for everyone if Zfinx extension is implemented
|
csr_acc_valid <= '1'; -- full access for everyone if Zfinx extension is implemented
|
else
|
else
|
NULL;
|
NULL;
|
end if;
|
end if;
|
|
|
-- machine trap setup --
|
-- machine trap setup & handling --
|
when csr_mstatus_c | csr_misa_c | csr_mie_c | csr_mtvec_c | csr_mcounteren_c | csr_mstatush_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!
|
-- machine trap handling --
|
|
when csr_mscratch_c | csr_mepc_c | csr_mcause_c | csr_mtval_c =>
|
|
csr_acc_valid <= csr.priv_m_mode; -- M-mode only
|
|
when csr_mip_c => -- NOTE: MIP is 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 - configuration --
|
-- physical memory protection - address & configuration --
|
when csr_pmpcfg0_c | csr_pmpcfg1_c | csr_pmpcfg2_c | csr_pmpcfg3_c | csr_pmpcfg4_c | csr_pmpcfg5_c | csr_pmpcfg6_c | csr_pmpcfg7_c |
|
|
csr_pmpcfg8_c | csr_pmpcfg9_c | csr_pmpcfg10_c | csr_pmpcfg11_c | csr_pmpcfg12_c | csr_pmpcfg13_c | csr_pmpcfg14_c | csr_pmpcfg15_c =>
|
|
if (PMP_NUM_REGIONS > 0) then
|
|
csr_acc_valid <= csr.priv_m_mode; -- M-mode only
|
|
else
|
|
NULL;
|
|
end if;
|
|
|
|
-- physical memory protection - address --
|
|
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 |
|
csr_pmpaddr40_c | csr_pmpaddr41_c | csr_pmpaddr42_c | csr_pmpaddr43_c | csr_pmpaddr44_c | csr_pmpaddr45_c | csr_pmpaddr46_c | csr_pmpaddr47_c |
|
csr_pmpaddr40_c | csr_pmpaddr41_c | csr_pmpaddr42_c | csr_pmpaddr43_c | csr_pmpaddr44_c | csr_pmpaddr45_c | csr_pmpaddr46_c | csr_pmpaddr47_c |
|
csr_pmpaddr48_c | csr_pmpaddr49_c | csr_pmpaddr50_c | csr_pmpaddr51_c | csr_pmpaddr52_c | csr_pmpaddr53_c | csr_pmpaddr54_c | csr_pmpaddr55_c |
|
csr_pmpaddr48_c | csr_pmpaddr49_c | csr_pmpaddr50_c | csr_pmpaddr51_c | csr_pmpaddr52_c | csr_pmpaddr53_c | csr_pmpaddr54_c | csr_pmpaddr55_c |
|
csr_pmpaddr56_c | csr_pmpaddr57_c | csr_pmpaddr58_c | csr_pmpaddr59_c | csr_pmpaddr60_c | csr_pmpaddr61_c | csr_pmpaddr62_c | csr_pmpaddr63_c =>
|
csr_pmpaddr56_c | csr_pmpaddr57_c | csr_pmpaddr58_c | csr_pmpaddr59_c | csr_pmpaddr60_c | csr_pmpaddr61_c | csr_pmpaddr62_c | csr_pmpaddr63_c |
|
|
csr_pmpcfg0_c | csr_pmpcfg1_c | csr_pmpcfg2_c | csr_pmpcfg3_c | csr_pmpcfg4_c | csr_pmpcfg5_c | csr_pmpcfg6_c | csr_pmpcfg7_c |
|
|
csr_pmpcfg8_c | csr_pmpcfg9_c | csr_pmpcfg10_c | csr_pmpcfg11_c | csr_pmpcfg12_c | csr_pmpcfg13_c | csr_pmpcfg14_c | csr_pmpcfg15_c =>
|
if (PMP_NUM_REGIONS > 0) then
|
if (PMP_NUM_REGIONS > 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;
|
Line 1494... |
Line 1418... |
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
|
|
|
-- debug mode CSRs --
|
-- debug mode CSRs --
|
when csr_dcsr_c | csr_dpc_c | csr_dscratch0_c =>
|
when csr_dcsr_c | csr_dpc_c | csr_dscratch0_c =>
|
if (CPU_EXTENSION_RISCV_DEBUG = true) then
|
if (CPU_EXTENSION_RISCV_DEBUG = true) then
|
csr_acc_valid <= debug_ctrl.running; -- DEBUG-mode only
|
csr_acc_valid <= debug_ctrl.running; -- access in only in debug-mode
|
else
|
else
|
NULL;
|
NULL;
|
end if;
|
end if;
|
|
|
-- undefined / not implemented --
|
-- undefined / not implemented --
|
Line 1526... |
Line 1450... |
else
|
else
|
illegal_opcode_lsbs <= '1';
|
illegal_opcode_lsbs <= '1';
|
end if;
|
end if;
|
|
|
-- check instructions --
|
-- check instructions --
|
opcode_v := execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c+2) & "11";
|
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)
|
-- ------------------------------------------------------------
|
-- ------------------------------------------------------------
|
Line 1544... |
Line 1468... |
-- ------------------------------------------------------------
|
-- ------------------------------------------------------------
|
if (execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0000001") then -- MULDIV
|
if (execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0000001") then -- MULDIV
|
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 (decode_aux.is_bitmanip_reg = '1') then -- bit manipulation
|
|
if (CPU_EXTENSION_RISCV_B = false) then -- not implemented
|
|
illegal_instruction <= '1';
|
|
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
|
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) /= "0000000") and
|
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) /= "0000000") and
|
(execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) /= "0100000")) then -- ADD/SUB or SRA/SRL select
|
(execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) /= "0100000")) then -- ADD/SUB or SRA/SRL select
|
illegal_instruction <= '1';
|
illegal_instruction <= '1';
|
Line 1564... |
Line 1484... |
illegal_register <= '1';
|
illegal_register <= '1';
|
end if;
|
end if;
|
|
|
when opcode_alui_c => -- check ALUI.funct7
|
when opcode_alui_c => -- check ALUI.funct7
|
-- ------------------------------------------------------------
|
-- ------------------------------------------------------------
|
if (decode_aux.is_bitmanip_imm = '1') then -- bit manipulation
|
if ((execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sll_c) and
|
if (CPU_EXTENSION_RISCV_B = false) then -- not implemented
|
|
illegal_instruction <= '1';
|
|
end if;
|
|
elsif ((execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sll_c) and
|
|
(execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) /= "0000000")) or -- shift logical left
|
(execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) /= "0000000")) or -- shift logical left
|
((execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sr_c) and
|
((execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sr_c) and
|
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) /= "0000000") and
|
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) /= "0000000") and
|
(execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) /= "0100000"))) then -- shift right
|
(execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) /= "0100000"))) then -- shift right
|
illegal_instruction <= '1';
|
illegal_instruction <= '1';
|
Line 1675... |
Line 1591... |
else -- reg-imm CSR
|
else -- reg-imm CSR
|
illegal_register <= execute_engine.i_reg(instr_rd_msb_c);
|
illegal_register <= execute_engine.i_reg(instr_rd_msb_c);
|
end if;
|
end if;
|
end if;
|
end if;
|
|
|
-- ecall, ebreak, mret, wfi --
|
-- ecall, ebreak, mret, wfi, dret --
|
elsif (execute_engine.i_reg(instr_rd_msb_c downto instr_rd_lsb_c) = "00000") and
|
elsif (execute_engine.i_reg(instr_rd_msb_c downto instr_rd_lsb_c) = "00000") and
|
(execute_engine.i_reg(instr_rs1_msb_c downto instr_rs1_lsb_c) = "00000") then
|
(execute_engine.i_reg(instr_rs1_msb_c downto instr_rs1_lsb_c) = "00000") then
|
if (execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = funct12_ecall_c) or -- ECALL
|
if (execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = funct12_ecall_c) or -- ECALL
|
(execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = funct12_ebreak_c) or -- EBREAK
|
(execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = funct12_ebreak_c) or -- EBREAK
|
(execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = funct12_mret_c) or -- MRET
|
(execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = funct12_mret_c) or -- MRET
|
((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = (funct12_dret_c)) and (CPU_EXTENSION_RISCV_DEBUG = true) and (debug_ctrl.running = '1')) or
|
((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = (funct12_dret_c)) and (CPU_EXTENSION_RISCV_DEBUG = true) and (debug_ctrl.running = '1')) or -- DRET
|
(execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = funct12_wfi_c) then -- WFI
|
(execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = funct12_wfi_c) then -- WFI
|
illegal_instruction <= '0';
|
illegal_instruction <= '0';
|
else
|
else
|
illegal_instruction <= '1';
|
illegal_instruction <= '1';
|
end if;
|
end if;
|
Line 1819... |
Line 1735... |
end if;
|
end if;
|
end if;
|
end if;
|
end process trap_controller;
|
end process trap_controller;
|
|
|
-- any exception/interrupt? --
|
-- any exception/interrupt? --
|
trap_ctrl.exc_fire <= or_all_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_all_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 <= '1' when (CPU_EXTENSION_RISCV_DEBUG = false) else
|
'0' when (debug_ctrl.running = '1') else -- no interrupts when IN debug 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
|
csr.dcsr_stepie when (csr.dcsr_step = '1') else '1'; -- allow IRQ in single-step mode when dcsr.stepie is set
|
|
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 --
|
-- acknowledge mask output --
|
firq_ack_o <= trap_ctrl.irq_ack(interrupt_firq_15_c downto interrupt_firq_0_c);
|
firq_ack_o <= trap_ctrl.irq_ack(interrupt_firq_15_c downto interrupt_firq_0_c);
|
|
|
Line 2096... |
Line 2011... |
csr.frm <= (others => def_rst_val_c);
|
csr.frm <= (others => def_rst_val_c);
|
--
|
--
|
csr.dcsr_ebreakm <= '0';
|
csr.dcsr_ebreakm <= '0';
|
csr.dcsr_ebreaku <= '0';
|
csr.dcsr_ebreaku <= '0';
|
csr.dcsr_step <= '0';
|
csr.dcsr_step <= '0';
|
csr.dcsr_stepie <= '0';
|
|
csr.dcsr_prv <= (others => def_rst_val_c);
|
csr.dcsr_prv <= (others => def_rst_val_c);
|
csr.dcsr_cause <= (others => def_rst_val_c);
|
csr.dcsr_cause <= (others => def_rst_val_c);
|
csr.dpc <= (others => def_rst_val_c);
|
csr.dpc <= (others => def_rst_val_c);
|
csr.dscratch0 <= (others => def_rst_val_c);
|
csr.dscratch0 <= (others => def_rst_val_c);
|
|
|
Line 2183... |
Line 2097... |
-- R/W: mcause - machine trap cause --
|
-- R/W: mcause - machine trap cause --
|
if (csr.addr(3 downto 0) = csr_mcause_c(3 downto 0)) then
|
if (csr.addr(3 downto 0) = csr_mcause_c(3 downto 0)) then
|
csr.mcause(csr.mcause'left) <= csr.wdata(31); -- 1: interrupt, 0: exception
|
csr.mcause(csr.mcause'left) <= csr.wdata(31); -- 1: interrupt, 0: exception
|
csr.mcause(4 downto 0) <= csr.wdata(4 downto 0); -- identifier
|
csr.mcause(4 downto 0) <= csr.wdata(4 downto 0); -- identifier
|
end if;
|
end if;
|
-- R/W: mtval - machine bad address/instruction --
|
|
if (csr.addr(3 downto 0) = csr_mtval_c(3 downto 0)) then
|
|
csr.mtval <= csr.wdata;
|
|
end if;
|
|
end if;
|
end if;
|
|
|
-- physical memory protection: R/W: pmpcfg* - PMP configuration registers --
|
-- physical memory protection: R/W: pmpcfg* - PMP configuration registers --
|
-- --------------------------------------------------------------------
|
-- --------------------------------------------------------------------
|
if (PMP_NUM_REGIONS > 0) then
|
if (PMP_NUM_REGIONS > 0) then
|
Line 2251... |
Line 2161... |
if (CPU_EXTENSION_RISCV_DEBUG = true) then
|
if (CPU_EXTENSION_RISCV_DEBUG = true) then
|
if (csr.addr(11 downto 2) = csr_class_debug_c) then -- debug CSR class
|
if (csr.addr(11 downto 2) = csr_class_debug_c) then -- debug CSR class
|
-- R/W: dcsr - debug mode control and status register --
|
-- R/W: dcsr - debug mode control and status register --
|
if (csr.addr(1 downto 0) = csr_dcsr_c(1 downto 0)) then
|
if (csr.addr(1 downto 0) = csr_dcsr_c(1 downto 0)) then
|
csr.dcsr_ebreakm <= csr.wdata(15);
|
csr.dcsr_ebreakm <= csr.wdata(15);
|
csr.dcsr_stepie <= csr.wdata(2);
|
|
csr.dcsr_step <= csr.wdata(2);
|
csr.dcsr_step <= csr.wdata(2);
|
if (CPU_EXTENSION_RISCV_U = true) then -- user mode implemented
|
if (CPU_EXTENSION_RISCV_U = true) then -- user mode implemented
|
csr.dcsr_ebreaku <= csr.wdata(12);
|
csr.dcsr_ebreaku <= csr.wdata(12);
|
csr.dcsr_prv(0) <= csr.wdata(1) or csr.wdata(0);
|
csr.dcsr_prv(0) <= csr.wdata(1) or csr.wdata(0);
|
csr.dcsr_prv(1) <= csr.wdata(1) or csr.wdata(0);
|
csr.dcsr_prv(1) <= csr.wdata(1) or csr.wdata(0);
|
Line 2362... |
Line 2271... |
else -- return from "normal trap"
|
else -- return from "normal trap"
|
csr.mstatus_mie <= csr.mstatus_mpie; -- restore global IRQ enable flag
|
csr.mstatus_mie <= csr.mstatus_mpie; -- restore global IRQ enable flag
|
csr.mstatus_mpie <= '1';
|
csr.mstatus_mpie <= '1';
|
if (CPU_EXTENSION_RISCV_U = true) then -- implement user mode
|
if (CPU_EXTENSION_RISCV_U = true) then -- implement user mode
|
csr.privilege <= csr.mstatus_mpp; -- go back to previous privilege mode
|
csr.privilege <= csr.mstatus_mpp; -- go back to previous privilege mode
|
csr.mstatus_mpp <= priv_mode_m_c;
|
csr.mstatus_mpp <= (others => '0');
|
end if;
|
end if;
|
end if;
|
end if;
|
end if;
|
end if;
|
|
|
-- user mode NOT implemented --
|
|
if (CPU_EXTENSION_RISCV_U = false) then
|
|
csr.privilege <= priv_mode_m_c;
|
|
csr.mstatus_mpp <= priv_mode_m_c;
|
|
end if;
|
|
|
|
end if; -- /hardware csr access
|
end if; -- /hardware csr access
|
end if;
|
end if;
|
|
|
-- --------------------------------------------------------------------------------
|
-- --------------------------------------------------------------------------------
|
-- override write access for disabled functions
|
-- override write access for disabled functions
|
Line 2389... |
Line 2292... |
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.mcounteren_hpm <= (others => '0');
|
csr.dcsr_ebreaku <= '0';
|
csr.dcsr_ebreaku <= '0';
|
|
csr.dcsr_prv <= priv_mode_m_c;
|
end if;
|
end if;
|
|
|
-- pmp disabled --
|
-- pmp disabled --
|
if (PMP_NUM_REGIONS = 0) then
|
if (PMP_NUM_REGIONS = 0) then
|
csr.pmpcfg <= (others => (others => '0'));
|
csr.pmpcfg <= (others => (others => '0'));
|
Line 2423... |
Line 2327... |
-- debug mode disabled --
|
-- debug mode disabled --
|
if (CPU_EXTENSION_RISCV_DEBUG = false) then
|
if (CPU_EXTENSION_RISCV_DEBUG = false) then
|
csr.dcsr_ebreakm <= '0';
|
csr.dcsr_ebreakm <= '0';
|
csr.dcsr_ebreaku <= '0';
|
csr.dcsr_ebreaku <= '0';
|
csr.dcsr_step <= '0';
|
csr.dcsr_step <= '0';
|
csr.dcsr_stepie <= '0';
|
|
csr.dcsr_prv <= (others => '0');
|
|
csr.dcsr_cause <= (others => '0');
|
csr.dcsr_cause <= (others => '0');
|
csr.dpc <= (others => '0');
|
csr.dpc <= (others => '0');
|
csr.dscratch0 <= (others => '0');
|
csr.dscratch0 <= (others => '0');
|
end if;
|
end if;
|
|
|
Line 2474... |
Line 2376... |
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);
|
mcycle_msb <= def_rst_val_c;
|
csr.mcycle_msb <= 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);
|
minstret_msb <= def_rst_val_c;
|
csr.minstret_msb <= 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));
|
mhpmcounter_msb <= (others => def_rst_val_c);
|
csr.mhpmcounter_msb <= (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 --
|
csr.mcycle(csr.mcycle'left downto cpu_cnt_lo_width_c+1) <= (others => '0'); -- set unused bits to zero
|
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 <= (others => '0');
|
if (csr.we = '1') and (csr.addr = csr_mcycle_c) then -- write access
|
mcycle_msb <= '0';
|
|
elsif (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 downto 0) <= '0' & csr.wdata(cpu_cnt_lo_width_c-1 downto 0);
|
mcycle_msb <= '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(csr.mcycle(cpu_cnt_lo_width_c downto 0)) + 1);
|
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);
|
mcycle_msb <= csr.mcycle(cpu_cnt_lo_width_c);
|
end if;
|
|
else
|
|
csr.mcycle <= (others => '-');
|
|
csr.mcycle_msb <= '-';
|
end if;
|
end if;
|
|
|
-- [m]cycleh --
|
-- [m]cycleh --
|
csr.mcycleh(csr.mcycleh'left downto cpu_cnt_hi_width_c+1) <= (others => '0'); -- set unused bits to zero
|
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
|
csr.mcycleh <= (others => '0');
|
|
elsif (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 ((mcycle_msb xor csr.mcycle(cpu_cnt_lo_width_c)) = '1') then -- automatic update (continued)
|
elsif (csr.mcycle_msb = '0') and (csr.mcycle(csr.mcycle'left) = '1') then -- automatic update (continued)
|
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)) + 1);
|
end if;
|
end if;
|
|
else
|
|
csr.mcycleh <= (others => '-');
|
|
end if;
|
|
|
|
|
-- [m]instret --
|
-- [m]instret --
|
csr.minstret(csr.minstret'left downto cpu_cnt_lo_width_c+1) <= (others => '0'); -- set unused bits to zero
|
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 <= (others => '0');
|
if (csr.we = '1') and (csr.addr = csr_minstret_c) then -- write access
|
minstret_msb <= '0';
|
|
elsif (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 downto 0) <= '0' & csr.wdata(cpu_cnt_lo_width_c-1 downto 0);
|
minstret_msb <= '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(csr.minstret(cpu_cnt_lo_width_c downto 0)) + 1);
|
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);
|
minstret_msb <= csr.minstret(csr.minstret'left);
|
end if;
|
|
else
|
|
csr.minstret <= (others => '-');
|
|
csr.minstret_msb <= '-';
|
end if;
|
end if;
|
|
|
-- [m]instreth --
|
-- [m]instreth --
|
csr.minstreth(csr.minstreth'left downto cpu_cnt_hi_width_c+1) <= (others => '0'); -- set unsued bits to zero
|
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
|
csr.minstreth <= (others => '0');
|
|
elsif (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 ((minstret_msb xor csr.minstret(cpu_cnt_lo_width_c)) = '1') then -- automatic update (continued)
|
elsif (csr.minstret_msb = '0') and (csr.minstret(csr.minstret'left) = '1') then -- automatic update (continued)
|
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)) + 1);
|
end if;
|
end if;
|
|
else
|
|
csr.minstreth <= (others => '-');
|
|
end if;
|
|
|
|
|
-- [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
|
csr.mhpmcounter(i)(csr.mhpmcounter(i)'left downto hpm_cnt_lo_width_c+1) <= (others => '0'); -- set unused bits to zero
|
|
if (hpm_cnt_lo_width_c = 0) then
|
|
csr.mhpmcounter(i) <= (others => '0');
|
|
mhpmcounter_msb(i) <= '0';
|
|
else
|
|
-- [m]hpmcounter* --
|
-- [m]hpmcounter* --
|
|
if (hpm_cnt_lo_width_c > 0) then
|
|
csr.mhpmcounter_msb(i) <= csr.mhpmcounter(i)(csr.mhpmcounter(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 downto 0) <= '0' & csr.wdata(hpm_cnt_lo_width_c-1 downto 0);
|
mhpmcounter_msb(i) <= '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(csr.mhpmcounter(i)(hpm_cnt_lo_width_c downto 0)) + 1);
|
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);
|
mhpmcounter_msb(i) <= csr.mhpmcounter(i)(csr.mhpmcounter(i)'left);
|
|
end if;
|
end if;
|
|
else
|
|
csr.mhpmcounter(i) <= (others => '-');
|
|
csr.mhpmcounter_msb(i) <= '-';
|
end if;
|
end if;
|
|
|
-- [m]hpmcounter*h --
|
-- [m]hpmcounter*h --
|
csr.mhpmcounterh(i)(csr.mhpmcounterh(i)'left downto hpm_cnt_hi_width_c+1) <= (others => '0'); -- set unused bits to zero
|
if (hpm_cnt_hi_width_c > 0) then
|
if (hpm_cnt_hi_width_c = 0) then
|
|
csr.mhpmcounterh(i) <= (others => '0');
|
|
else
|
|
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 ((mhpmcounter_msb(i) xor csr.mhpmcounter(i)(hpm_cnt_lo_width_c)) = '1') then -- automatic update (continued)
|
elsif (csr.mhpmcounter_msb(i) = '0') and (csr.mhpmcounter(i)(csr.mhpmcounter(i)'left) = '1') then -- automatic update (continued)
|
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)) + 1);
|
end if;
|
end if;
|
|
else
|
|
csr.mhpmcounterh(i) <= (others => '-');
|
end if;
|
end if;
|
|
|
end loop; -- i
|
end loop; -- i
|
|
|
end if;
|
end if;
|
end process csr_counters;
|
end process csr_counters;
|
|
|
|
|
-- hpm counters read dummy --
|
-- hpm counters read dummy --
|
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'));
|
Line 2596... |
Line 2502... |
-- enable selected triggers by ANDing actual events and according CSR configuration bits --
|
-- enable selected triggers by ANDing actual events and according CSR configuration bits --
|
-- OR everything to see if counter should increment --
|
-- OR everything to see if counter should increment --
|
hpmcnt_trigger <= (others => '0'); -- default
|
hpmcnt_trigger <= (others => '0'); -- default
|
if (HPM_NUM_CNTS /= 0) then
|
if (HPM_NUM_CNTS /= 0) then
|
for i in 0 to HPM_NUM_CNTS-1 loop
|
for i in 0 to HPM_NUM_CNTS-1 loop
|
hpmcnt_trigger(i) <= or_all_f(cnt_event and csr.mhpmevent(i)(cnt_event'left downto 0));
|
hpmcnt_trigger(i) <= or_reduce_f(cnt_event and csr.mhpmevent(i)(cnt_event'left downto 0));
|
end loop; -- i
|
end loop; -- i
|
end if;
|
end if;
|
end if;
|
end if;
|
end process hpmcnt_ctrl;
|
end process hpmcnt_ctrl;
|
|
|
Line 2651... |
Line 2557... |
|
|
-- machine trap setup --
|
-- machine trap setup --
|
-- --------------------------------------------------------------------
|
-- --------------------------------------------------------------------
|
when csr_mstatus_c => -- mstatus (r/w): machine status register
|
when csr_mstatus_c => -- mstatus (r/w): machine status register
|
csr.rdata(03) <= csr.mstatus_mie; -- MIE
|
csr.rdata(03) <= csr.mstatus_mie; -- MIE
|
csr.rdata(06) <= '1' and bool_to_ulogic_f(CPU_EXTENSION_RISCV_U); -- UBE: CPU/Processor is BIG-ENDIAN (in user-mode)
|
|
csr.rdata(07) <= csr.mstatus_mpie; -- MPIE
|
csr.rdata(07) <= csr.mstatus_mpie; -- MPIE
|
csr.rdata(11) <= csr.mstatus_mpp(0); -- MPP: machine previous privilege mode low
|
csr.rdata(11) <= csr.mstatus_mpp(0); -- MPP: machine previous privilege mode low
|
csr.rdata(12) <= csr.mstatus_mpp(1); -- MPP: machine previous privilege mode high
|
csr.rdata(12) <= csr.mstatus_mpp(1); -- MPP: machine previous privilege mode high
|
when csr_mstatush_c => -- mstatush (r/-): machine status register - high part
|
|
csr.rdata(05) <= '1'; -- MBE: CPU/Processor is BIG-ENDIAN (in machine-mode)
|
|
when csr_misa_c => -- misa (r/-): ISA and extensions
|
when csr_misa_c => -- misa (r/-): ISA and extensions
|
csr.rdata(00) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_A); -- A CPU extension
|
csr.rdata(00) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_A); -- A CPU extension
|
csr.rdata(01) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_B); -- B CPU extension
|
|
csr.rdata(02) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_C); -- C CPU extension
|
csr.rdata(02) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_C); -- C CPU extension
|
csr.rdata(04) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_E); -- E CPU extension
|
csr.rdata(04) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_E); -- E CPU extension
|
csr.rdata(08) <= not bool_to_ulogic_f(CPU_EXTENSION_RISCV_E); -- I CPU extension (if not E)
|
csr.rdata(08) <= not bool_to_ulogic_f(CPU_EXTENSION_RISCV_E); -- I CPU extension (if not E)
|
csr.rdata(12) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_M); -- M CPU extension
|
csr.rdata(12) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_M); -- M CPU extension
|
csr.rdata(20) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_U); -- U CPU extension
|
csr.rdata(20) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_U); -- U CPU extension
|
Line 2920... |
Line 2822... |
-- 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_B); -- Zbb (B)
|
|
csr.rdata(3) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_B); -- Zbs (B)
|
|
csr.rdata(4) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_B); -- Zba (B)
|
|
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
|
Line 2947... |
Line 2846... |
when csr_dscratch0_c => if (CPU_EXTENSION_RISCV_DEBUG = true) then csr.rdata <= csr.dscratch0; else NULL; end if; -- dscratch0 (r/w): debug mode scratch register 0
|
when csr_dscratch0_c => if (CPU_EXTENSION_RISCV_DEBUG = true) then csr.rdata <= csr.dscratch0; else NULL; end if; -- dscratch0 (r/w): debug mode scratch register 0
|
|
|
-- undefined/unavailable --
|
-- undefined/unavailable --
|
-- --------------------------------------------------------------------
|
-- --------------------------------------------------------------------
|
when others =>
|
when others =>
|
NULL; -- not implemented
|
NULL; -- not implemented, read as zero if read access is granted
|
|
|
end case;
|
end case;
|
end if;
|
end if;
|
end if;
|
end if;
|
end process csr_read_access;
|
end process csr_read_access;
|
Line 3013... |
Line 2912... |
debug_ctrl.pending <= '1' when (debug_ctrl.state = DEBUG_PENDING) and (CPU_EXTENSION_RISCV_DEBUG = true) else '0';
|
debug_ctrl.pending <= '1' when (debug_ctrl.state = DEBUG_PENDING) and (CPU_EXTENSION_RISCV_DEBUG = true) else '0';
|
debug_ctrl.running <= '1' when ((debug_ctrl.state = DEBUG_ONLINE) or (debug_ctrl.state = DEBUG_EXIT)) and (CPU_EXTENSION_RISCV_DEBUG = true) else '0';
|
debug_ctrl.running <= '1' when ((debug_ctrl.state = DEBUG_ONLINE) or (debug_ctrl.state = DEBUG_EXIT)) and (CPU_EXTENSION_RISCV_DEBUG = true) else '0';
|
|
|
-- entry debug mode triggers --
|
-- entry debug mode triggers --
|
debug_ctrl.trig_break <= trap_ctrl.break_point and (debug_ctrl.running or -- we are in debug mode: re-enter debug mode
|
debug_ctrl.trig_break <= trap_ctrl.break_point and (debug_ctrl.running or -- we are in debug mode: re-enter debug mode
|
(csr.priv_m_mode and csr.dcsr_ebreakm and (not debug_ctrl.running)) or -- enable goto-debug-mode in machine mode on "ebreak"
|
(csr.priv_m_mode and csr.dcsr_ebreakm and (not debug_ctrl.running)) or -- enabled goto-debug-mode in machine mode on "ebreak"
|
(csr.priv_u_mode and csr.dcsr_ebreaku and (not debug_ctrl.running))); -- enable goto-debug-mode in user mode on "ebreak"
|
(csr.priv_u_mode and csr.dcsr_ebreaku and (not debug_ctrl.running))); -- enabled goto-debug-mode in user mode on "ebreak"
|
debug_ctrl.trig_halt <= (not debug_ctrl.ext_halt_req(1)) and debug_ctrl.ext_halt_req(0) and (not debug_ctrl.running); -- rising edge detector from external halt request (if not halted already)
|
debug_ctrl.trig_halt <= (not debug_ctrl.ext_halt_req(1)) and debug_ctrl.ext_halt_req(0) and (not debug_ctrl.running); -- rising edge detector from external halt request (if not halted already)
|
debug_ctrl.trig_step <= csr.dcsr_step and (not debug_ctrl.running); -- single-step mode (trigger when NOT CURRENTLY in debug mode)
|
debug_ctrl.trig_step <= csr.dcsr_step and (not debug_ctrl.running); -- single-step mode (trigger when NOT CURRENTLY in debug mode)
|
|
|
|
|
-- Debug Control and Status Register (dcsr) - Read-Back -----------------------------------
|
-- Debug Control and Status Register (dcsr) - Read-Back -----------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
dcsr_readback_false:
|
dcsr_readback_false:
|
if (CPU_EXTENSION_RISCV_DEBUG = false) generate
|
if (CPU_EXTENSION_RISCV_DEBUG = false) generate
|
csr.dcsr_rd <= (others => '0');
|
csr.dcsr_rd <= (others => '-');
|
end generate;
|
end generate;
|
|
|
dcsr_readback_true:
|
dcsr_readback_true:
|
if (CPU_EXTENSION_RISCV_DEBUG = true) generate
|
if (CPU_EXTENSION_RISCV_DEBUG = true) generate
|
csr.dcsr_rd(31 downto 28) <= "0100"; -- xdebugver: external debug support compatible to spec
|
csr.dcsr_rd(31 downto 28) <= "0100"; -- xdebugver: external debug support compatible to spec
|
csr.dcsr_rd(27 downto 16) <= (others => '0'); -- reserved
|
csr.dcsr_rd(27 downto 16) <= (others => '0'); -- reserved
|
csr.dcsr_rd(15) <= csr.dcsr_ebreakm; -- ebreakm: what happens on ebreak in m-mode? (normal trap OR debug-enter)
|
csr.dcsr_rd(15) <= csr.dcsr_ebreakm; -- ebreakm: what happens on ebreak in m-mode? (normal trap OR debug-enter)
|
csr.dcsr_rd(14) <= '0'; -- ebreakh: not available
|
csr.dcsr_rd(14) <= '0'; -- ebreakh: not available
|
csr.dcsr_rd(13) <= '0'; -- ebreaks: not available
|
csr.dcsr_rd(13) <= '0'; -- ebreaks: not available
|
csr.dcsr_rd(12) <= csr.dcsr_ebreaku when (CPU_EXTENSION_RISCV_U = true) else '0'; -- ebreaku: what happens on ebreak in u-mode? (normal trap OR debug-enter)
|
csr.dcsr_rd(12) <= csr.dcsr_ebreaku when (CPU_EXTENSION_RISCV_U = true) else '0'; -- ebreaku: what happens on ebreak in u-mode? (normal trap OR debug-enter)
|
csr.dcsr_rd(11) <= csr.dcsr_stepie; -- stepie: interrupts enabled during single-stepping?
|
csr.dcsr_rd(11) <= '0'; -- stepie: interrupts are disabled during single-stepping
|
csr.dcsr_rd(10) <= '0'; -- stopcount: counters increment as usual FIXME ???
|
csr.dcsr_rd(10) <= '0'; -- stopcount: counters increment as usual FIXME ???
|
csr.dcsr_rd(09) <= '0'; -- stoptime: timers increment as usual FIXME ???
|
csr.dcsr_rd(09) <= '0'; -- stoptime: timers increment as usual
|
csr.dcsr_rd(08 downto 06) <= csr.dcsr_cause; -- cause
|
csr.dcsr_rd(08 downto 06) <= csr.dcsr_cause; -- debug mode entry cause
|
csr.dcsr_rd(05) <= '0'; -- reserved
|
csr.dcsr_rd(05) <= '0'; -- reserved
|
csr.dcsr_rd(04) <= '0'; -- mprven: mstatus.mprv is ignored in debug mode
|
csr.dcsr_rd(04) <= '0'; -- mprven: mstatus.mprv is ignored in debug mode
|
csr.dcsr_rd(03) <= trap_ctrl.irq_buf(interrupt_nm_irq_c); -- nmip: pending non-maskable interrupt
|
csr.dcsr_rd(03) <= trap_ctrl.irq_buf(interrupt_nm_irq_c); -- nmip: pending non-maskable interrupt
|
csr.dcsr_rd(02) <= csr.dcsr_step; -- step: single-step mode
|
csr.dcsr_rd(02) <= csr.dcsr_step; -- step: single-step mode
|
csr.dcsr_rd(01 downto 00) <= csr.dcsr_prv; -- prv: privilege mode when debug mode was entered
|
csr.dcsr_rd(01 downto 00) <= csr.dcsr_prv; -- prv: privilege mode when debug mode was entered
|