[cpu] add LR/SC decoding and execution

This commit is contained in:
stnolting 2025-02-08 09:57:26 +01:00
parent 7c09881bf5
commit 75caa87153
3 changed files with 41 additions and 32 deletions

View file

@ -32,7 +32,8 @@ entity neorv32_cpu is
RISCV_ISA_E : boolean; -- implement embedded RF extension
RISCV_ISA_M : boolean; -- implement mul/div extension
RISCV_ISA_U : boolean; -- implement user mode extension
RISCV_ISA_Zaamo : boolean; -- implement atomic memory operations extension
RISCV_ISA_Zaamo : boolean; -- implement atomic read-modify-write operations extension
RISCV_ISA_Zalrsc : boolean; -- implement atomic reservation-set operations extension
RISCV_ISA_Zba : boolean; -- implement shifted-add bit-manipulation extension
RISCV_ISA_Zbb : boolean; -- implement basic bit-manipulation extension
RISCV_ISA_Zbkb : boolean; -- implement bit-manipulation instructions for cryptography
@ -95,6 +96,7 @@ architecture neorv32_cpu_rtl of neorv32_cpu is
-- auto-configuration --
constant rf_rs3_en_c : boolean := RISCV_ISA_Zxcfu or RISCV_ISA_Zfinx; -- 3rd register file read port
constant riscv_a_c : boolean := RISCV_ISA_Zaamo and RISCV_ISA_Zalrsc; -- A: atomic memory operations
constant riscv_b_c : boolean := RISCV_ISA_Zba and RISCV_ISA_Zbb and RISCV_ISA_Zbs; -- B: bit manipulation
constant riscv_zkt_c : boolean := CPU_FAST_SHIFT_EN; -- Zkt: data-independent execution time for cryptographic operations
constant riscv_zkn_c : boolean := RISCV_ISA_Zbkb and RISCV_ISA_Zbkc and RISCV_ISA_Zbkx and
@ -143,12 +145,14 @@ begin
-- CPU ISA configuration (in alphabetical order - not in canonical order!) --
assert false report "[NEORV32] CPU ISA: rv32" &
cond_sel_string_f(RISCV_ISA_E, "e", "i") &
cond_sel_string_f(riscv_a_c, "a", "" ) &
cond_sel_string_f(riscv_b_c, "b", "" ) &
cond_sel_string_f(RISCV_ISA_C, "c", "" ) &
cond_sel_string_f(RISCV_ISA_M, "m", "" ) &
cond_sel_string_f(RISCV_ISA_U, "u", "" ) &
cond_sel_string_f(true, "x", "" ) & -- always enabled
cond_sel_string_f(RISCV_ISA_Zaamo, "_zaamo", "" ) &
cond_sel_string_f(RISCV_ISA_Zalrsc, "_zalrsc", "" ) &
cond_sel_string_f(RISCV_ISA_Zba, "_zba", "" ) &
cond_sel_string_f(RISCV_ISA_Zbb, "_zbb", "" ) &
cond_sel_string_f(RISCV_ISA_Zbkb, "_zbkb", "" ) &
@ -219,12 +223,14 @@ begin
DEBUG_PARK_ADDR => DEBUG_PARK_ADDR, -- cpu debug mode parking loop entry address
DEBUG_EXC_ADDR => DEBUG_EXC_ADDR, -- cpu debug mode exception entry address
-- RISC-V ISA Extensions --
RISCV_ISA_A => riscv_a_c, -- implement atomic memory operations extension
RISCV_ISA_B => riscv_b_c, -- implement bit-manipulation extension
RISCV_ISA_C => RISCV_ISA_C, -- implement compressed extension
RISCV_ISA_E => RISCV_ISA_E, -- implement embedded RF extension
RISCV_ISA_M => RISCV_ISA_M, -- implement mul/div extension
RISCV_ISA_U => RISCV_ISA_U, -- implement user mode extension
RISCV_ISA_Zaamo => RISCV_ISA_Zaamo, -- implement atomic memory operations extension
RISCV_ISA_Zaamo => RISCV_ISA_Zaamo, -- implement atomic read-modify-write operations extension
RISCV_ISA_Zalrsc => RISCV_ISA_Zalrsc, -- implement atomic reservation-set operations extension
RISCV_ISA_Zba => RISCV_ISA_Zba, -- implement shifted-add bit-manipulation extension
RISCV_ISA_Zbb => RISCV_ISA_Zbb, -- implement basic bit-manipulation extension
RISCV_ISA_Zbkb => RISCV_ISA_Zbkb, -- implement bit-manipulation instructions for cryptography
@ -380,9 +386,6 @@ begin
-- Load/Store Unit (LSU) ------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
neorv32_cpu_lsu_inst: entity neorv32.neorv32_cpu_lsu
generic map (
AMO_EN => RISCV_ISA_Zaamo -- enable atomic memory operations
)
port map (
-- global control --
clk_i => clk_gated, -- global clock, rising edge

View file

@ -34,12 +34,14 @@ entity neorv32_cpu_control is
DEBUG_PARK_ADDR : std_ulogic_vector(31 downto 0); -- cpu debug-mode parking loop entry address, 4-byte aligned
DEBUG_EXC_ADDR : std_ulogic_vector(31 downto 0); -- cpu debug-mode exception entry address, 4-byte aligned
-- RISC-V ISA Extensions --
RISCV_ISA_A : boolean; -- implement atomic memory operations extension
RISCV_ISA_B : boolean; -- implement bit-manipulation extension
RISCV_ISA_C : boolean; -- implement compressed extension
RISCV_ISA_E : boolean; -- implement embedded-class register file extension
RISCV_ISA_M : boolean; -- implement mul/div extension
RISCV_ISA_U : boolean; -- implement user mode extension
RISCV_ISA_Zaamo : boolean; -- implement atomic memory operations extension
RISCV_ISA_Zaamo : boolean; -- implement atomic read-modify-write extension
RISCV_ISA_Zalrsc : boolean; -- implement atomic reservation-set operations extension
RISCV_ISA_Zba : boolean; -- implement shifted-add bit-manipulation extension
RISCV_ISA_Zbb : boolean; -- implement basic bit-manipulation extension
RISCV_ISA_Zbkb : boolean; -- implement bit-manipulation instructions for cryptography
@ -629,11 +631,16 @@ begin
ctrl_nxt.alu_opb_mux <= '0';
end case;
-- memory read/write access --
if RISCV_ISA_Zaamo and (opcode(2) = opcode_amo_c(2)) then -- atomic memory operation (executed as single load for the CPU)
ctrl_nxt.lsu_rw <= '0';
-- (atomic) memory read/write access --
if RISCV_ISA_Zaamo and (opcode(2) = opcode_amo_c(2)) and (exe_engine.ir(instr_funct5_lsb_c+1) = '0') then -- atomic read-modify-write operation
ctrl_nxt.lsu_amo <= '1';
ctrl_nxt.lsu_rw <= '0'; -- executed as single load for the CPU
elsif RISCV_ISA_Zalrsc and (opcode(2) = opcode_amo_c(2)) and (exe_engine.ir(instr_funct5_lsb_c+1) = '1') then -- atomic reservation-set operation
ctrl_nxt.lsu_amo <= '1';
ctrl_nxt.lsu_rw <= exe_engine.ir(instr_funct5_lsb_c);
else -- normal load/store
ctrl_nxt.lsu_rw <= exe_engine.ir(5);
ctrl_nxt.lsu_amo <= '0';
ctrl_nxt.lsu_rw <= exe_engine.ir(instr_opcode_lsb_c+5);
end if;
-- state machine --
@ -830,7 +837,7 @@ begin
(trap_ctrl.exc_buf(exc_saccess_c) = '1') or (trap_ctrl.exc_buf(exc_laccess_c) = '1') or -- access exception
(trap_ctrl.exc_buf(exc_salign_c) = '1') or (trap_ctrl.exc_buf(exc_lalign_c) = '1') or -- alignment exception
(trap_ctrl.exc_buf(exc_illegal_c) = '1') then -- illegal instruction exception
ctrl_nxt.rf_wb_en <= not ctrl.lsu_rw; -- write-back to register file if read operation (won't happen in case of exception)
ctrl_nxt.rf_wb_en <= (not ctrl.lsu_rw) or ctrl.lsu_amo; -- write-back to register file if read operation (won't happen in case of exception)
exe_engine_nxt.state <= EX_DISPATCH;
end if;
@ -886,6 +893,7 @@ begin
-- load/store unit --
ctrl_o.lsu_req <= ctrl.lsu_req;
ctrl_o.lsu_rw <= ctrl.lsu_rw;
ctrl_o.lsu_amo <= ctrl.lsu_amo;
ctrl_o.lsu_mo_we <= '1' when (exe_engine.state = EX_MEM_REQ) else '0'; -- write memory output registers (data & address)
ctrl_o.lsu_fence <= ctrl.lsu_fence;
ctrl_o.lsu_priv <= csr.mstatus_mpp when (csr.mstatus_mprv = '1') else csr.prv_level_eff; -- effective privilege level for loads/stores in M-mode
@ -1059,9 +1067,10 @@ begin
end case;
when opcode_amo_c => -- atomic memory operation
if RISCV_ISA_Zaamo and (exe_engine.ir(instr_funct3_msb_c downto instr_funct3_lsb_c) = "010") then -- word-quantity only
if (exe_engine.ir(instr_funct3_msb_c downto instr_funct3_lsb_c) = "010") then -- word-quantity only
case exe_engine.ir(instr_funct5_msb_c downto instr_funct5_lsb_c) is
when "00001" | "00000" | "00100" | "01100" | "01000" | "10000" | "10100" | "11000" | "11100" => illegal_cmd <= '0';
when "00001" | "00000" | "00100" | "01100" | "01000" | "10000" | "10100" | "11000" | "11100" => illegal_cmd <= not bool_to_ulogic_f(RISCV_ISA_Zaamo);
when "00010" | "00011" => illegal_cmd <= not bool_to_ulogic_f(RISCV_ISA_Zalrsc);
when others => illegal_cmd <= '1';
end case;
end if;
@ -1702,6 +1711,7 @@ begin
-- when csr_mstatush_c => csr.rdata <= (others => '0'); -- machine status register, high word - hardwired to zero
when csr_misa_c => -- ISA and extensions
csr.rdata(0) <= bool_to_ulogic_f(RISCV_ISA_A);
csr.rdata(1) <= bool_to_ulogic_f(RISCV_ISA_B);
csr.rdata(2) <= bool_to_ulogic_f(RISCV_ISA_C);
csr.rdata(4) <= bool_to_ulogic_f(RISCV_ISA_E);
@ -1891,7 +1901,7 @@ begin
csr.rdata(23) <= bool_to_ulogic_f(RISCV_ISA_Zbb); -- Zbb: basic bit-manipulation
csr.rdata(24) <= bool_to_ulogic_f(RISCV_ISA_Zbs); -- Zbs: single-bit bit-manipulation
csr.rdata(25) <= bool_to_ulogic_f(RISCV_ISA_Zaamo); -- Zaamo: atomic memory operations
csr.rdata(26) <= '0'; -- reserved
csr.rdata(26) <= bool_to_ulogic_f(RISCV_ISA_Zalrsc); -- Zalrsc: reservation-set operations
-- tuning options --
csr.rdata(27) <= bool_to_ulogic_f(CPU_CLOCK_GATING_EN); -- enable clock gating when in sleep mode
csr.rdata(28) <= bool_to_ulogic_f(CPU_RF_HW_RST_EN); -- full hardware reset of register file

View file

@ -15,9 +15,6 @@ library neorv32;
use neorv32.neorv32_package.all;
entity neorv32_cpu_lsu is
generic (
AMO_EN : boolean -- enable atomic memory operations
);
port (
-- global control --
clk_i : in std_ulogic; -- global clock, rising edge
@ -87,9 +84,9 @@ begin
if (ctrl_i.lsu_mo_we = '1') then
-- type identifiers --
dbus_req_o.rw <= ctrl_i.lsu_rw; -- read/write
dbus_req_o.amo <= ctrl_i.lsu_amo; -- atomic memory operation
dbus_req_o.priv <= ctrl_i.lsu_priv; -- privilege level
dbus_req_o.debug <= ctrl_i.cpu_debug; -- debug-mode access
dbus_req_o.amo <= bool_to_ulogic_f(AMO_EN) and ctrl_i.ir_opcode(2); -- atomic memory operation
dbus_req_o.amoop <= amo_cmd;
-- data alignment + byte-enable --
case ctrl_i.ir_funct3(1 downto 0) is
@ -119,20 +116,19 @@ begin
-- atomic memory access operation encoding --
amo_encode: process(ctrl_i.ir_funct12)
begin
amo_cmd <= (others => '0'); -- default
if AMO_EN then
case ctrl_i.ir_funct12(11 downto 7) is
when "00000" => amo_cmd <= "0001"; -- ADD
when "00100" => amo_cmd <= "0010"; -- XOR
when "01100" => amo_cmd <= "0011"; -- AND
when "01000" => amo_cmd <= "0100"; -- OR
when "10000" => amo_cmd <= "1110"; -- MIN
when "10100" => amo_cmd <= "1111"; -- MAX
when "11000" => amo_cmd <= "0110"; -- MINU
when "11100" => amo_cmd <= "0111"; -- MAXU
when others => amo_cmd <= "0000"; -- SWAP
end case;
end if;
case ctrl_i.ir_funct12(11 downto 7) is
when "00010" => amo_cmd <= "1000"; -- LR
when "00011" => amo_cmd <= "1001"; -- SC
when "00000" => amo_cmd <= "0001"; -- ADD
when "00100" => amo_cmd <= "0010"; -- XOR
when "01100" => amo_cmd <= "0011"; -- AND
when "01000" => amo_cmd <= "0100"; -- OR
when "10000" => amo_cmd <= "1110"; -- MIN
when "10100" => amo_cmd <= "1111"; -- MAX
when "11000" => amo_cmd <= "0110"; -- MINU
when "11100" => amo_cmd <= "0111"; -- MAXU
when others => amo_cmd <= "0000"; -- SWAP
end case;
end process;