mirror of
https://github.com/stnolting/neorv32.git
synced 2025-04-24 22:27:21 -04:00
⚠️ [rtl] remove Zalrsc ISA; replace by Zaamo
This commit is contained in:
parent
c0c5068683
commit
e5833c9431
9 changed files with 226 additions and 174 deletions
|
@ -29,6 +29,7 @@ mimpid = 0x01040312 -> Version 01.04.03.12 -> v1.4.3.12
|
|||
|
||||
| Date | Version | Comment | Ticket |
|
||||
|:----:|:-------:|:--------|:------:|
|
||||
| 03.01.2025 | 1.10.8.7 | :warning: :sparkles: replace `Zalrsc` ISA extensions (reservation-set operations) by `Zaamo` ISA extension (atomic read-modify-write operations) | [#]() |
|
||||
| 01.01.2025 | 1.10.8.6 | :sparkles: :test_tube: add smp dual-core option | [#1135](https://github.com/stnolting/neorv32/pull/1135) |
|
||||
| 29.12.2024 | 1.10.8.5 | :test_tube: add multi-hart support to debug module | [#1132](https://github.com/stnolting/neorv32/pull/1132) |
|
||||
| 29.12.2024 | 1.10.8.4 | :warning: rename `SYSINFO.MEM -> SYSINFO.MISC`; add new `SYSINFO.MISC` entry for number of CPU cores (hardwired to one) | [#1134](https://github.com/stnolting/neorv32/pull/1134) |
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
-- -------------------------------------------------------------------------------- --
|
||||
-- The NEORV32 RISC-V Processor - https://github.com/stnolting/neorv32 --
|
||||
-- Copyright (c) NEORV32 contributors. --
|
||||
-- Copyright (c) 2020 - 2024 Stephan Nolting. All rights reserved. --
|
||||
-- Copyright (c) 2020 - 2025 Stephan Nolting. All rights reserved. --
|
||||
-- Licensed under the BSD-3-Clause license, see LICENSE for details. --
|
||||
-- SPDX-License-Identifier: BSD-3-Clause --
|
||||
-- ================================================================================ --
|
||||
|
@ -172,7 +172,8 @@ begin
|
|||
-- Request Switch -------------------------------------------------------------------------
|
||||
-- -------------------------------------------------------------------------------------------
|
||||
x_req_o.addr <= a_req_i.addr when (sel = '0') else b_req_i.addr;
|
||||
x_req_o.rvso <= a_req_i.rvso when (sel = '0') else b_req_i.rvso;
|
||||
x_req_o.amo <= a_req_i.amo when (sel = '0') else b_req_i.amo;
|
||||
x_req_o.amoop <= a_req_i.amoop when (sel = '0') else b_req_i.amoop;
|
||||
x_req_o.priv <= a_req_i.priv when (sel = '0') else b_req_i.priv;
|
||||
x_req_o.src <= a_req_i.src when (sel = '0') else b_req_i.src;
|
||||
x_req_o.rw <= a_req_i.rw when (sel = '0') else b_req_i.rw;
|
||||
|
@ -738,11 +739,11 @@ end neorv32_bus_io_switch_rtl;
|
|||
|
||||
|
||||
-- ================================================================================ --
|
||||
-- NEORV32 SoC - Processor Bus Infrastructure: Reservation Set Control --
|
||||
-- NEORV32 SoC - Processor Bus Infrastructure: Atomic Memory Operations Controller --
|
||||
-- -------------------------------------------------------------------------------- --
|
||||
-- Reservation set controller for the A (atomic) ISA extension's LR.W --
|
||||
-- (load-reservate) and SC.W (store-conditional) instructions. Only a single --
|
||||
-- reservation set (granularity = 4 bytes) is supported. T --
|
||||
-- Read-modify-write controller for the RISC-V A/Zaamp ISA extension. --
|
||||
-- [WARNING] Load-reservate and store-conditional operations (Zalrsc ISA extension) --
|
||||
-- are NOT supported! --
|
||||
-- -------------------------------------------------------------------------------- --
|
||||
-- The NEORV32 RISC-V Processor - https://github.com/stnolting/neorv32 --
|
||||
-- Copyright (c) NEORV32 contributors. --
|
||||
|
@ -753,136 +754,158 @@ end neorv32_bus_io_switch_rtl;
|
|||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
library neorv32;
|
||||
use neorv32.neorv32_package.all;
|
||||
|
||||
entity neorv32_bus_reservation_set is
|
||||
entity neorv32_bus_amo_ctrl is
|
||||
port (
|
||||
-- global control --
|
||||
clk_i : in std_ulogic; -- global clock, rising edge
|
||||
rstn_i : in std_ulogic; -- global reset, low-active, async
|
||||
-- external status and control --
|
||||
rvs_addr_o : out std_ulogic_vector(31 downto 0);
|
||||
rvs_valid_o : out std_ulogic;
|
||||
rvs_clear_i : in std_ulogic;
|
||||
clk_i : in std_ulogic; -- global clock, rising edge
|
||||
rstn_i : in std_ulogic; -- global reset, low-active, async
|
||||
-- core port --
|
||||
core_req_i : in bus_req_t;
|
||||
core_rsp_o : out bus_rsp_t;
|
||||
core_req_i : in bus_req_t;
|
||||
core_rsp_o : out bus_rsp_t;
|
||||
-- system port --
|
||||
sys_req_o : out bus_req_t;
|
||||
sys_rsp_i : in bus_rsp_t
|
||||
sys_req_o : out bus_req_t;
|
||||
sys_rsp_i : in bus_rsp_t
|
||||
);
|
||||
end neorv32_bus_reservation_set;
|
||||
end neorv32_bus_amo_ctrl;
|
||||
|
||||
architecture neorv32_bus_reservation_set_rtl of neorv32_bus_reservation_set is
|
||||
architecture neorv32_bus_amo_ctrl_rtl of neorv32_bus_amo_ctrl is
|
||||
|
||||
-- reservation set --
|
||||
type rsvs_t is record
|
||||
state : std_ulogic_vector(1 downto 0);
|
||||
addr : std_ulogic_vector(31 downto 2); -- reservated address; 4-byte granularity
|
||||
valid : std_ulogic;
|
||||
match : std_ulogic;
|
||||
-- arbiter --
|
||||
type state_t is (S_IDLE, S_READ_WAIT, S_EXECUTE, S_WRITE, S_WRITE_WAIT);
|
||||
type arbiter_t is record
|
||||
state : state_t;
|
||||
cmd : std_ulogic_vector(3 downto 0);
|
||||
rdata : std_ulogic_vector(31 downto 0);
|
||||
wdata : std_ulogic_vector(31 downto 0);
|
||||
ack : std_ulogic;
|
||||
end record;
|
||||
signal rsvs : rsvs_t;
|
||||
signal arbiter, arbiter_nxt : arbiter_t;
|
||||
|
||||
-- ACK override for failed SC.W --
|
||||
signal ack_local : std_ulogic;
|
||||
-- internal data ALU --
|
||||
signal alu_res : std_ulogic_vector(31 downto 0);
|
||||
|
||||
-- comparator --
|
||||
signal cmp_opa : std_ulogic_vector(32 downto 0);
|
||||
signal cmp_opb : std_ulogic_vector(32 downto 0);
|
||||
signal cmp_less : std_ulogic;
|
||||
signal cmp_res : std_ulogic_vector(31 downto 0);
|
||||
|
||||
begin
|
||||
|
||||
-- Reservation Set Control ----------------------------------------------------------------
|
||||
-- Arbiter Sync ---------------------------------------------------------------------------
|
||||
-- -------------------------------------------------------------------------------------------
|
||||
rvs_control: process(rstn_i, clk_i)
|
||||
arbiter_sync: process(rstn_i, clk_i)
|
||||
begin
|
||||
if (rstn_i = '0') then
|
||||
rsvs.state <= "00";
|
||||
rsvs.addr <= (others => '0');
|
||||
arbiter.state <= S_IDLE;
|
||||
arbiter.cmd <= (others => '0');
|
||||
arbiter.rdata <= (others => '0');
|
||||
arbiter.wdata <= (others => '0');
|
||||
elsif rising_edge(clk_i) then
|
||||
case rsvs.state is
|
||||
arbiter <= arbiter_nxt;
|
||||
end if;
|
||||
end process arbiter_sync;
|
||||
|
||||
when "10" => -- active reservation: wait for condition to invalidate reservation
|
||||
-- --------------------------------------------------------------------
|
||||
if (core_req_i.stb = '1') and (core_req_i.rw = '0') and (core_req_i.rvso = '1') then -- another LR instruction overriding the current reservation
|
||||
rsvs.addr <= core_req_i.addr(31 downto 2);
|
||||
end if;
|
||||
--
|
||||
if (rvs_clear_i = '1') then -- external clear request (highest priority)
|
||||
rsvs.state <= "00"; -- invalidate reservation
|
||||
elsif (core_req_i.stb = '1') and (core_req_i.rw = '1') then -- write access
|
||||
|
||||
if (core_req_i.rvso = '1') then -- this is a SC operation
|
||||
if (rsvs.match = '1') then -- SC to reservated address
|
||||
rsvs.state <= "11"; -- execute SC instruction (reservation still valid)
|
||||
else -- SC to any other address
|
||||
rsvs.state <= "00"; -- invalidate reservation
|
||||
end if;
|
||||
-- Arbiter Comb ---------------------------------------------------------------------------
|
||||
-- -------------------------------------------------------------------------------------------
|
||||
arbiter_comb: process(arbiter, core_req_i, sys_rsp_i)
|
||||
begin
|
||||
arbiter_nxt <= arbiter; -- defaults
|
||||
case arbiter.state is
|
||||
|
||||
elsif (rsvs.match = '1') then -- normal write to reservated address
|
||||
rsvs.state <= "00"; -- invalidate reservation
|
||||
end if;
|
||||
when S_IDLE => -- wait for AMO request
|
||||
-- ------------------------------------------------------------
|
||||
if (core_req_i.stb = '1') and (core_req_i.amo = '1') then
|
||||
arbiter_nxt.cmd <= core_req_i.amoop;
|
||||
arbiter_nxt.wdata <= core_req_i.data;
|
||||
arbiter_nxt.state <= S_READ_WAIT;
|
||||
end if;
|
||||
|
||||
end if;
|
||||
when S_READ_WAIT => -- wait for device read-access to complete
|
||||
-- ------------------------------------------------------------
|
||||
arbiter_nxt.rdata <= sys_rsp_i.data;
|
||||
if (sys_rsp_i.ack = '1') or (sys_rsp_i.err = '1') then
|
||||
arbiter_nxt.state <= S_EXECUTE;
|
||||
end if;
|
||||
|
||||
when "11" => -- active reservation: invalidate reservation at the end of bus access
|
||||
-- --------------------------------------------------------------------
|
||||
if (sys_rsp_i.ack = '1') or (sys_rsp_i.err = '1') then
|
||||
rsvs.state <= "00";
|
||||
end if;
|
||||
when S_EXECUTE => -- execute atomic data operation
|
||||
-- ------------------------------------------------------------
|
||||
arbiter_nxt.state <= S_WRITE;
|
||||
|
||||
when others => -- "0-" no active reservation: wait for new registration request
|
||||
-- --------------------------------------------------------------------
|
||||
if (core_req_i.stb = '1') and (core_req_i.rw = '0') and (core_req_i.rvso = '1') then -- load-reservate instruction
|
||||
rsvs.addr <= core_req_i.addr(31 downto 2);
|
||||
rsvs.state <= "10";
|
||||
end if;
|
||||
when S_WRITE => -- wait operation result to device
|
||||
-- ------------------------------------------------------------
|
||||
arbiter_nxt.state <= S_WRITE_WAIT;
|
||||
|
||||
when S_WRITE_WAIT => -- wait for device write-access to complete
|
||||
-- ------------------------------------------------------------
|
||||
if (sys_rsp_i.ack = '1') or (sys_rsp_i.err = '1') then
|
||||
arbiter_nxt.state <= S_IDLE;
|
||||
end if;
|
||||
|
||||
when others => -- undefined
|
||||
-- ------------------------------------------------------------
|
||||
arbiter_nxt.state <= S_IDLE;
|
||||
|
||||
end case;
|
||||
end process arbiter_comb;
|
||||
|
||||
-- request switch --
|
||||
sys_req_o.addr <= core_req_i.addr;
|
||||
sys_req_o.data <= alu_res when (arbiter.state = S_WRITE) or (arbiter.state = S_WRITE_WAIT) else core_req_i.data;
|
||||
sys_req_o.ben <= core_req_i.ben;
|
||||
sys_req_o.stb <= '1' when (arbiter.state = S_WRITE) else core_req_i.stb;
|
||||
sys_req_o.rw <= '1' when (arbiter.state = S_WRITE) or (arbiter.state = S_WRITE_WAIT) else core_req_i.rw;
|
||||
sys_req_o.src <= core_req_i.src;
|
||||
sys_req_o.priv <= core_req_i.priv;
|
||||
sys_req_o.amo <= core_req_i.amo;
|
||||
sys_req_o.amoop <= (others => '0'); -- the specific operation type should not matter after this point
|
||||
sys_req_o.fence <= core_req_i.fence;
|
||||
sys_req_o.sleep <= core_req_i.sleep;
|
||||
sys_req_o.debug <= core_req_i.debug;
|
||||
|
||||
-- response switch --
|
||||
core_rsp_o.data <= sys_rsp_i.data when (arbiter.state = S_IDLE) else arbiter.rdata;
|
||||
core_rsp_o.err <= sys_rsp_i.err when (arbiter.state = S_IDLE) or (arbiter.state = S_WRITE_WAIT) else '0';
|
||||
core_rsp_o.ack <= sys_rsp_i.ack when (arbiter.state = S_IDLE) or (arbiter.state = S_WRITE_WAIT) else '0';
|
||||
|
||||
|
||||
-- Arbiter Sync ---------------------------------------------------------------------------
|
||||
-- -------------------------------------------------------------------------------------------
|
||||
amo_alu: process(rstn_i, clk_i)
|
||||
begin
|
||||
if (rstn_i = '0') then
|
||||
alu_res <= (others => '0');
|
||||
elsif rising_edge(clk_i) then
|
||||
case arbiter.cmd(2 downto 0) is
|
||||
when "000" => alu_res <= arbiter.wdata; -- AMOSWAP
|
||||
when "001" => alu_res <= std_ulogic_vector(unsigned(arbiter.rdata) + unsigned(arbiter.wdata)); -- AMOADD
|
||||
when "010" => alu_res <= arbiter.rdata xor arbiter.wdata; -- AMOXOR
|
||||
when "011" => alu_res <= arbiter.rdata and arbiter.wdata; -- AMOAND
|
||||
when "100" => alu_res <= arbiter.rdata or arbiter.wdata; -- AMOOR
|
||||
when others => alu_res <= cmp_res; -- AMOMIN[U] / AMOMAX[U]
|
||||
end case;
|
||||
end if;
|
||||
end process rvs_control;
|
||||
end process amo_alu;
|
||||
|
||||
-- address match? --
|
||||
rsvs.match <= '1' when (core_req_i.addr(31 downto 2) = rsvs.addr) else '0';
|
||||
-- -000 : SWAP
|
||||
-- -001 : ADD
|
||||
-- -010 : XOR
|
||||
-- -011 : AND
|
||||
-- -100 : OR
|
||||
-- s110 : MIN
|
||||
-- s111 : MAX
|
||||
|
||||
-- reservation valid? --
|
||||
rsvs.valid <= rsvs.state(1);
|
||||
|
||||
-- status for external system --
|
||||
rvs_valid_o <= rsvs.valid;
|
||||
rvs_addr_o <= rsvs.addr & "00";
|
||||
-- comparator logic (min/max and signed/unsigned) --
|
||||
cmp_opa <= (arbiter.rdata(arbiter.rdata'left) and arbiter.cmd(3)) & arbiter.rdata; -- sign-extend if signed operation
|
||||
cmp_opb <= (arbiter.wdata(arbiter.wdata'left) and arbiter.cmd(3)) & arbiter.wdata; -- sign-extend if signed operation
|
||||
cmp_less <= '1' when (signed(cmp_opa) < signed(cmp_opb)) else '0';
|
||||
cmp_res <= cmp_opa(31 downto 0) when ((cmp_less xor arbiter.cmd(0)) = '1') else cmp_opb(31 downto 0);
|
||||
|
||||
|
||||
-- System Bus Interface -------------------------------------------------------------------
|
||||
-- -------------------------------------------------------------------------------------------
|
||||
|
||||
-- gated request --
|
||||
bus_request: process(core_req_i, rsvs.valid)
|
||||
begin
|
||||
sys_req_o <= core_req_i;
|
||||
if (core_req_i.rvso = '1') and (core_req_i.rw = '1') then -- SC operation
|
||||
sys_req_o.stb <= core_req_i.stb and rsvs.valid; -- write allowed if reservation still valid
|
||||
else -- normal memory request or LR
|
||||
sys_req_o.stb <= core_req_i.stb;
|
||||
end if;
|
||||
end process bus_request;
|
||||
|
||||
-- if a SC.W instruction fails there will be no write-request being send to the bus system
|
||||
-- so we need to provide a local ACK to complete the bus access
|
||||
ack_override: process(rstn_i, clk_i)
|
||||
begin
|
||||
if (rstn_i = '0') then
|
||||
ack_local <= '0';
|
||||
elsif rising_edge(clk_i) then
|
||||
ack_local <= core_req_i.rvso and core_req_i.stb and core_req_i.rw and (not rsvs.valid);
|
||||
end if;
|
||||
end process ack_override;
|
||||
|
||||
-- response --
|
||||
core_rsp_o.err <= sys_rsp_i.err;
|
||||
core_rsp_o.ack <= sys_rsp_i.ack or ack_local; -- generate local ACK if SC fails
|
||||
-- inject 1 into read data's LSB if SC fails --
|
||||
core_rsp_o.data(31 downto 1) <= sys_rsp_i.data(31 downto 1);
|
||||
core_rsp_o.data(0) <= sys_rsp_i.data(0) or (core_req_i.rvso and core_req_i.rw and (not rsvs.valid));
|
||||
|
||||
|
||||
end neorv32_bus_reservation_set_rtl;
|
||||
end neorv32_bus_amo_ctrl_rtl;
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
-- -------------------------------------------------------------------------------- --
|
||||
-- The NEORV32 RISC-V Processor - https://github.com/stnolting/neorv32 --
|
||||
-- Copyright (c) NEORV32 contributors. --
|
||||
-- Copyright (c) 2020 - 2024 Stephan Nolting. All rights reserved. --
|
||||
-- Copyright (c) 2020 - 2025 Stephan Nolting. All rights reserved. --
|
||||
-- Licensed under the BSD-3-Clause license, see LICENSE for details. --
|
||||
-- SPDX-License-Identifier: BSD-3-Clause --
|
||||
-- ================================================================================ --
|
||||
|
@ -178,7 +178,7 @@ begin
|
|||
-- -------------------------------------------------------------------------------------------
|
||||
dir_acc_d <= '1' when UC_ENABLE and -- direct accesses implemented
|
||||
((unsigned(host_req_i.addr(31 downto 28)) >= unsigned(UC_BEGIN)) or -- uncached memory page
|
||||
(host_req_i.rvso = '1')) else '0'; -- atomic (reservation set) operation
|
||||
(host_req_i.amo = '1')) else '0'; -- atomic memory operation
|
||||
|
||||
-- request splitter: cached or direct access --
|
||||
req_splitter: process(host_req_i, dir_acc_d)
|
||||
|
@ -378,7 +378,7 @@ end neorv32_cache_rtl;
|
|||
-- -------------------------------------------------------------------------------- --
|
||||
-- The NEORV32 RISC-V Processor - https://github.com/stnolting/neorv32 --
|
||||
-- Copyright (c) NEORV32 contributors. --
|
||||
-- Copyright (c) 2020 - 2024 Stephan Nolting. All rights reserved. --
|
||||
-- Copyright (c) 2020 - 2025 Stephan Nolting. All rights reserved. --
|
||||
-- Licensed under the BSD-3-Clause license, see LICENSE for details. --
|
||||
-- SPDX-License-Identifier: BSD-3-Clause --
|
||||
-- ================================================================================ --
|
||||
|
@ -538,7 +538,7 @@ end neorv32_cache_host_rtl;
|
|||
-- -------------------------------------------------------------------------------- --
|
||||
-- The NEORV32 RISC-V Processor - https://github.com/stnolting/neorv32 --
|
||||
-- Copyright (c) NEORV32 contributors. --
|
||||
-- Copyright (c) 2020 - 2024 Stephan Nolting. All rights reserved. --
|
||||
-- Copyright (c) 2020 - 2025 Stephan Nolting. All rights reserved. --
|
||||
-- Licensed under the BSD-3-Clause license, see LICENSE for details. --
|
||||
-- SPDX-License-Identifier: BSD-3-Clause --
|
||||
-- ================================================================================ --
|
||||
|
@ -725,7 +725,7 @@ end neorv32_cache_memory_rtl;
|
|||
-- -------------------------------------------------------------------------------- --
|
||||
-- The NEORV32 RISC-V Processor - https://github.com/stnolting/neorv32 --
|
||||
-- Copyright (c) NEORV32 contributors. --
|
||||
-- Copyright (c) 2020 - 2024 Stephan Nolting. All rights reserved. --
|
||||
-- Copyright (c) 2020 - 2025 Stephan Nolting. All rights reserved. --
|
||||
-- Licensed under the BSD-3-Clause license, see LICENSE for details. --
|
||||
-- SPDX-License-Identifier: BSD-3-Clause --
|
||||
-- ================================================================================ --
|
||||
|
@ -851,7 +851,8 @@ begin
|
|||
bus_req_o.ben <= (others => '1'); -- full-word writes only
|
||||
bus_req_o.src <= '0'; -- cache accesses are always data accesses
|
||||
bus_req_o.priv <= '0'; -- cache accesses are always "unprivileged" accesses
|
||||
bus_req_o.rvso <= '0'; -- cache accesses can never be a reservation set operation
|
||||
bus_req_o.amo <= '0'; -- cache accesses can never be an atomic memory operation set operation
|
||||
bus_req_o.amoop <= (others => '0'); -- cache accesses can never be an atomic memory operation set operation
|
||||
bus_req_o.debug <= host_req_i.debug;
|
||||
if (state = S_IDLE) then
|
||||
bus_req_o.sleep <= host_req_i.sleep;
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
-- -------------------------------------------------------------------------------- --
|
||||
-- The NEORV32 RISC-V Processor - https://github.com/stnolting/neorv32 --
|
||||
-- Copyright (c) NEORV32 contributors. --
|
||||
-- Copyright (c) 2020 - 2024 Stephan Nolting. All rights reserved. --
|
||||
-- Copyright (c) 2020 - 2025 Stephan Nolting. All rights reserved. --
|
||||
-- Licensed under the BSD-3-Clause license, see LICENSE for details. --
|
||||
-- SPDX-License-Identifier: BSD-3-Clause --
|
||||
-- ================================================================================ --
|
||||
|
@ -32,7 +32,7 @@ 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_Zalrsc : boolean; -- implement atomic reservation-set extension
|
||||
RISCV_ISA_Zaamo : boolean; -- implement atomic memory 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
|
||||
|
@ -138,7 +138,7 @@ begin
|
|||
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_Zalrsc, "_zalrsc", "" ) &
|
||||
cond_sel_string_f(RISCV_ISA_Zaamo, "_zaamo", "" ) &
|
||||
cond_sel_string_f(RISCV_ISA_Zba, "_zba", "" ) &
|
||||
cond_sel_string_f(RISCV_ISA_Zbb, "_zbb", "" ) &
|
||||
cond_sel_string_f(RISCV_ISA_Zbkb, "_zbkb", "" ) &
|
||||
|
@ -213,7 +213,7 @@ begin
|
|||
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_Zalrsc => RISCV_ISA_Zalrsc, -- implement atomic reservation-set extension
|
||||
RISCV_ISA_Zaamo => RISCV_ISA_Zaamo, -- implement atomic memory 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
|
||||
|
@ -367,24 +367,24 @@ begin
|
|||
-- -------------------------------------------------------------------------------------------
|
||||
neorv32_cpu_lsu_inst: entity neorv32.neorv32_cpu_lsu
|
||||
generic map (
|
||||
AMO_LRSC_ENABLE => RISCV_ISA_Zalrsc -- enable atomic LR/SC operations
|
||||
AMO_EN => RISCV_ISA_Zaamo -- enable atomic memory operations
|
||||
)
|
||||
port map (
|
||||
-- global control --
|
||||
clk_i => clk_gated, -- global clock, rising edge
|
||||
rstn_i => rstn_i, -- global reset, low-active, async
|
||||
ctrl_i => ctrl, -- main control bus
|
||||
clk_i => clk_gated, -- global clock, rising edge
|
||||
rstn_i => rstn_i, -- global reset, low-active, async
|
||||
ctrl_i => ctrl, -- main control bus
|
||||
-- cpu data access interface --
|
||||
addr_i => alu_add, -- access address
|
||||
wdata_i => rs2, -- write data
|
||||
rdata_o => lsu_rdata, -- read data
|
||||
mar_o => lsu_mar, -- memory address register
|
||||
wait_o => lsu_wait, -- wait for access to complete
|
||||
err_o => lsu_err, -- alignment/access errors
|
||||
pmp_fault_i => pmp_fault, -- PMP read/write access fault
|
||||
addr_i => alu_add, -- access address
|
||||
wdata_i => rs2, -- write data
|
||||
rdata_o => lsu_rdata, -- read data
|
||||
mar_o => lsu_mar, -- memory address register
|
||||
wait_o => lsu_wait, -- wait for access to complete
|
||||
err_o => lsu_err, -- alignment/access errors
|
||||
pmp_fault_i => pmp_fault, -- PMP read/write access fault
|
||||
-- data bus --
|
||||
dbus_req_o => dbus_req_o, -- request
|
||||
dbus_rsp_i => dbus_rsp_i -- response
|
||||
dbus_req_o => dbus_req_o, -- request
|
||||
dbus_rsp_i => dbus_rsp_i -- response
|
||||
);
|
||||
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
-- -------------------------------------------------------------------------------- --
|
||||
-- The NEORV32 RISC-V Processor - https://github.com/stnolting/neorv32 --
|
||||
-- Copyright (c) NEORV32 contributors. --
|
||||
-- Copyright (c) 2020 - 2024 Stephan Nolting. All rights reserved. --
|
||||
-- Copyright (c) 2020 - 2025 Stephan Nolting. All rights reserved. --
|
||||
-- Licensed under the BSD-3-Clause license, see LICENSE for details. --
|
||||
-- SPDX-License-Identifier: BSD-3-Clause --
|
||||
-- ================================================================================ --
|
||||
|
@ -40,7 +40,7 @@ entity neorv32_cpu_control is
|
|||
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_Zalrsc : boolean; -- implement atomic reservation-set extension
|
||||
RISCV_ISA_Zaamo : boolean; -- implement atomic memory 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
|
||||
|
@ -368,7 +368,8 @@ begin
|
|||
ibus_req_o.ben <= (others => '0'); -- read-only
|
||||
ibus_req_o.rw <= '0'; -- read-only
|
||||
ibus_req_o.src <= '1'; -- source = instruction fetch
|
||||
ibus_req_o.rvso <= '0'; -- cannot be a reservation set operation
|
||||
ibus_req_o.amo <= '0'; -- cannot be an atomic memory operation
|
||||
ibus_req_o.amoop <= (others => '0'); -- cannot be an atomic memory operation
|
||||
ibus_req_o.fence <= ctrl.lsu_fence; -- fence operation, valid without STB being set
|
||||
ibus_req_o.sleep <= sleep_mode; -- sleep mode, valid without STB being set
|
||||
ibus_req_o.debug <= debug_ctrl.run; -- debug mode, valid without STB being set
|
||||
|
@ -622,8 +623,8 @@ begin
|
|||
end case;
|
||||
|
||||
-- memory read/write access --
|
||||
if RISCV_ISA_Zalrsc and (opcode(2) = opcode_amo_c(2)) then -- atomic lr/sc
|
||||
ctrl_nxt.lsu_rw <= exe_engine.ir(instr_funct7_lsb_c+2);
|
||||
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';
|
||||
else -- normal load/store
|
||||
ctrl_nxt.lsu_rw <= exe_engine.ir(5);
|
||||
end if;
|
||||
|
@ -806,7 +807,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
|
||||
if (RISCV_ISA_Zalrsc and (opcode(2) = opcode_amo_c(2))) or (opcode(5) = '0') then -- atomic operation / normal load
|
||||
if (RISCV_ISA_Zaamo and (opcode(2) = opcode_amo_c(2))) or (opcode(5) = '0') then -- atomic operation / normal load
|
||||
ctrl_nxt.rf_wb_en <= '1'; -- allow write-back to register file (won't happen in case of exception)
|
||||
end if;
|
||||
exe_engine_nxt.state <= EX_DISPATCH;
|
||||
|
@ -1033,10 +1034,12 @@ begin
|
|||
when others => illegal_cmd <= '1';
|
||||
end case;
|
||||
|
||||
when opcode_amo_c => -- atomic memory operation (LR/SC)
|
||||
if (exe_engine.ir(instr_funct3_msb_c downto instr_funct3_lsb_c) = "010") and RISCV_ISA_Zalrsc and
|
||||
(exe_engine.ir(instr_funct7_lsb_c+6 downto instr_funct7_lsb_c+3) = "0001") then -- LR.W/SC.W
|
||||
illegal_cmd <= '0';
|
||||
when opcode_amo_c => -- atomic memory operation
|
||||
if (exe_engine.ir(instr_funct3_msb_c downto instr_funct3_lsb_c) = "010") then
|
||||
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 others => illegal_cmd <= '1';
|
||||
end case;
|
||||
end if;
|
||||
|
||||
when opcode_alu_c | opcode_alui_c | opcode_fop_c | opcode_cust0_c | opcode_cust1_c => -- ALU[I] / FPU / custom operations
|
||||
|
@ -1852,9 +1855,9 @@ begin
|
|||
csr.rdata(20) <= bool_to_ulogic_f(RISCV_ISA_Zksed); -- Zksed: ShangMi block cyphers
|
||||
csr.rdata(21) <= bool_to_ulogic_f(RISCV_ISA_Zks); -- Zks: ShangMi algorithm suite
|
||||
csr.rdata(22) <= bool_to_ulogic_f(RISCV_ISA_Zba); -- Zba: shifted-add bit-manipulation
|
||||
csr.rdata(23) <= bool_to_ulogic_f(RISCV_ISA_Zbb); -- Zbb: basic bit-manipulation extension
|
||||
csr.rdata(24) <= bool_to_ulogic_f(RISCV_ISA_Zbs); -- Zbs: single-bit bit-manipulation extension
|
||||
csr.rdata(25) <= bool_to_ulogic_f(RISCV_ISA_Zalrsc); -- Zalrsc: reservation set extension
|
||||
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(27) <= '0'; -- reserved
|
||||
-- tuning options --
|
||||
|
|
|
@ -16,7 +16,7 @@ use neorv32.neorv32_package.all;
|
|||
|
||||
entity neorv32_cpu_lsu is
|
||||
generic (
|
||||
AMO_LRSC_ENABLE : boolean -- enable atomic LR/SC operations
|
||||
AMO_EN : boolean -- enable atomic memory operations
|
||||
);
|
||||
port (
|
||||
-- global control --
|
||||
|
@ -43,6 +43,7 @@ architecture neorv32_cpu_lsu_rtl of neorv32_cpu_lsu is
|
|||
signal misaligned : std_ulogic; -- misaligned address
|
||||
signal arbiter_req : std_ulogic; -- pending bus request
|
||||
signal arbiter_err : std_ulogic; -- access error
|
||||
signal amo_cmd : std_ulogic_vector(3 downto 0); -- atomic memory operation type
|
||||
|
||||
begin
|
||||
|
||||
|
@ -75,17 +76,19 @@ begin
|
|||
mem_do_reg: process(rstn_i, clk_i)
|
||||
begin
|
||||
if (rstn_i = '0') then
|
||||
dbus_req_o.rw <= '0';
|
||||
dbus_req_o.priv <= '0';
|
||||
dbus_req_o.rvso <= '0';
|
||||
dbus_req_o.data <= (others => '0');
|
||||
dbus_req_o.ben <= (others => '0');
|
||||
dbus_req_o.rw <= '0';
|
||||
dbus_req_o.priv <= '0';
|
||||
dbus_req_o.amo <= '0';
|
||||
dbus_req_o.amoop <= (others => '0');
|
||||
dbus_req_o.data <= (others => '0');
|
||||
dbus_req_o.ben <= (others => '0');
|
||||
elsif rising_edge(clk_i) then
|
||||
if (ctrl_i.lsu_mo_we = '1') then
|
||||
-- type identifiers --
|
||||
dbus_req_o.rw <= ctrl_i.lsu_rw; -- read/write
|
||||
dbus_req_o.priv <= ctrl_i.lsu_priv; -- privilege level
|
||||
dbus_req_o.rvso <= bool_to_ulogic_f(AMO_LRSC_ENABLE) and ctrl_i.ir_opcode(2); -- reservation set operation
|
||||
dbus_req_o.rw <= ctrl_i.lsu_rw; -- read/write
|
||||
dbus_req_o.priv <= ctrl_i.lsu_priv; -- privilege level
|
||||
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
|
||||
when "00" => -- byte
|
||||
|
@ -111,6 +114,27 @@ begin
|
|||
dbus_req_o.debug <= ctrl_i.cpu_debug; -- out-of-band: this is valid without STB being set
|
||||
|
||||
|
||||
-- atomic memory access operation encoding --
|
||||
amo_encode: process(ctrl_i.ir_funct12)
|
||||
begin
|
||||
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;
|
||||
else
|
||||
amo_cmd <= (others => '0');
|
||||
end if;
|
||||
end process;
|
||||
|
||||
|
||||
-- Data Input: Alignment and Sign-Extension -----------------------------------------------
|
||||
-- -------------------------------------------------------------------------------------------
|
||||
mem_di_reg: process(rstn_i, clk_i)
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
-- -------------------------------------------------------------------------------- --
|
||||
-- The NEORV32 RISC-V Processor - https://github.com/stnolting/neorv32 --
|
||||
-- Copyright (c) NEORV32 contributors. --
|
||||
-- Copyright (c) 2020 - 2024 Stephan Nolting. All rights reserved. --
|
||||
-- Copyright (c) 2020 - 2025 Stephan Nolting. All rights reserved. --
|
||||
-- Licensed under the BSD-3-Clause license, see LICENSE for details. --
|
||||
-- SPDX-License-Identifier: BSD-3-Clause --
|
||||
-- ================================================================================ --
|
||||
|
@ -308,7 +308,8 @@ begin
|
|||
dma_req_o.priv <= priv_mode_m_c; -- DMA accesses are always privileged
|
||||
dma_req_o.src <= '0'; -- source = data access
|
||||
dma_req_o.addr <= engine.src_addr when (engine.state = S_READ) else engine.dst_addr;
|
||||
dma_req_o.rvso <= '0'; -- no reservation set operation possible
|
||||
dma_req_o.amo <= '0'; -- no atomic memory operation possible
|
||||
dma_req_o.amoop <= (others => '0'); -- no atomic memory operation possible
|
||||
dma_req_o.fence <= cfg.enable and cfg.fence and engine.done; -- issue FENCE operation when transfer is done
|
||||
dma_req_o.sleep <= '1' when (engine.state = S_IDLE) else '0'; -- idle = sleep mode
|
||||
dma_req_o.debug <= '0'; -- can never ever be in debug mode
|
||||
|
|
|
@ -29,7 +29,7 @@ package neorv32_package is
|
|||
|
||||
-- Architecture Constants -----------------------------------------------------------------
|
||||
-- -------------------------------------------------------------------------------------------
|
||||
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01100806"; -- hardware version
|
||||
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01100807"; -- hardware version
|
||||
constant archid_c : natural := 19; -- official RISC-V architecture ID
|
||||
constant XLEN : natural := 32; -- native data path width
|
||||
|
||||
|
@ -128,7 +128,8 @@ package neorv32_package is
|
|||
rw : std_ulogic; -- 0=read, 1=write
|
||||
src : std_ulogic; -- access source (1=instruction fetch, 0=data access)
|
||||
priv : std_ulogic; -- set if privileged (machine-mode) access
|
||||
rvso : std_ulogic; -- set if reservation set operation (atomic LR/SC)
|
||||
amo : std_ulogic; -- set if atomic memory operation
|
||||
amoop : std_ulogic_vector(3 downto 0); -- type of atomic memory operation
|
||||
-- out-of-band signals --
|
||||
fence : std_ulogic; -- set if fence(.i) request by upstream device, single-shot
|
||||
sleep : std_ulogic; -- set if ALL upstream sources are in sleep mode
|
||||
|
@ -151,7 +152,8 @@ package neorv32_package is
|
|||
rw => '0',
|
||||
src => '0',
|
||||
priv => '0',
|
||||
rvso => '0',
|
||||
amo => '0',
|
||||
amoop => (others => '0'),
|
||||
fence => '0',
|
||||
sleep => '1',
|
||||
debug => '0'
|
||||
|
@ -736,7 +738,7 @@ package neorv32_package is
|
|||
RISCV_ISA_E : boolean := false;
|
||||
RISCV_ISA_M : boolean := false;
|
||||
RISCV_ISA_U : boolean := false;
|
||||
RISCV_ISA_Zalrsc : boolean := false;
|
||||
RISCV_ISA_Zaamo : boolean := false;
|
||||
RISCV_ISA_Zba : boolean := false;
|
||||
RISCV_ISA_Zbb : boolean := false;
|
||||
RISCV_ISA_Zbkb : boolean := false;
|
||||
|
|
|
@ -43,7 +43,7 @@ entity neorv32_top is
|
|||
RISCV_ISA_E : boolean := false; -- implement embedded RF extension
|
||||
RISCV_ISA_M : boolean := false; -- implement mul/div extension
|
||||
RISCV_ISA_U : boolean := false; -- implement user mode extension
|
||||
RISCV_ISA_Zalrsc : boolean := false; -- implement atomic reservation-set extension
|
||||
RISCV_ISA_Zaamo : boolean := false; -- implement atomic memory operations extension
|
||||
RISCV_ISA_Zba : boolean := false; -- implement shifted-add bit-manipulation extension
|
||||
RISCV_ISA_Zbb : boolean := false; -- implement basic bit-manipulation extension
|
||||
RISCV_ISA_Zbkb : boolean := false; -- implement bit-manipulation instructions for cryptography
|
||||
|
@ -508,7 +508,7 @@ begin
|
|||
RISCV_ISA_E => RISCV_ISA_E,
|
||||
RISCV_ISA_M => RISCV_ISA_M,
|
||||
RISCV_ISA_U => RISCV_ISA_U,
|
||||
RISCV_ISA_Zalrsc => RISCV_ISA_Zalrsc,
|
||||
RISCV_ISA_Zaamo => RISCV_ISA_Zaamo,
|
||||
RISCV_ISA_Zba => RISCV_ISA_Zba,
|
||||
RISCV_ISA_Zbb => RISCV_ISA_Zbb,
|
||||
RISCV_ISA_Zbkb => RISCV_ISA_Zbkb,
|
||||
|
@ -727,27 +727,24 @@ begin
|
|||
|
||||
|
||||
-- **************************************************************************************************************************
|
||||
-- Reservation Set Controller (for atomic LR/SC accesses)
|
||||
-- Read-Modify-Write Controller for Atomic Memory Operations
|
||||
-- **************************************************************************************************************************
|
||||
|
||||
neorv32_bus_reservation_set_true:
|
||||
if RISCV_ISA_Zalrsc generate
|
||||
neorv32_bus_reservation_set_inst: entity neorv32.neorv32_bus_reservation_set
|
||||
neorv32_bus_amo_ctrl_true:
|
||||
if RISCV_ISA_Zaamo generate
|
||||
neorv32_bus_amo_ctrl_inst: entity neorv32.neorv32_bus_amo_ctrl
|
||||
port map (
|
||||
clk_i => clk_i,
|
||||
rstn_i => rstn_sys,
|
||||
rvs_addr_o => open, -- yet unused
|
||||
rvs_valid_o => open, -- yet unused
|
||||
rvs_clear_i => '0', -- yet unused
|
||||
core_req_i => main_req,
|
||||
core_rsp_o => main_rsp,
|
||||
sys_req_o => main2_req,
|
||||
sys_rsp_i => main2_rsp
|
||||
clk_i => clk_i,
|
||||
rstn_i => rstn_sys,
|
||||
core_req_i => main_req,
|
||||
core_rsp_o => main_rsp,
|
||||
sys_req_o => main2_req,
|
||||
sys_rsp_i => main2_rsp
|
||||
);
|
||||
end generate;
|
||||
|
||||
neorv32_bus_reservation_set_false:
|
||||
if not RISCV_ISA_Zalrsc generate
|
||||
neorv32_bus_amo_ctrl_false:
|
||||
if not RISCV_ISA_Zaamo generate
|
||||
main2_req <= main_req;
|
||||
main_rsp <= main2_rsp;
|
||||
end generate;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue