Minor cache updates (#851)

This commit is contained in:
stnolting 2024-03-16 09:26:53 +01:00 committed by GitHub
commit a51fa8d9f0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 162 additions and 93 deletions

View file

@ -17,7 +17,6 @@ a 8x4-bit BCD (binary-coded decimal) format to represent the current version. Ex
mimpid = 0x01040312 -> Version 01.04.03.12 -> v1.4.3.12
```
### Version History
* :bug: bug-fix
@ -30,6 +29,7 @@ mimpid = 0x01040312 -> Version 01.04.03.12 -> v1.4.3.12
| Date | Version | Comment | Link |
|:----:|:-------:|:--------|:----:|
| 16.03.2024 | 1.9.6.7 | cache optimizations: add read-only option, add option to disable direct/uncached accesses | [#851](https://github.com/stnolting/neorv32/pull/851) |
| 15.03.2024 | 1.9.6.6 | :warning: clean-up configuration generics (remove XBUS endianness configuration; refine JEDED/VENDORID configuration); rearrange SYSINFO.SOC bits | [#850](https://github.com/stnolting/neorv32/pull/850) |
| 14.03.2024 | 1.9.6.5 | :sparkles: add optional external bus interface cache (XCACHE) | [#]846(https://github.com/stnolting/neorv32/pull/849) |
| 12.03.2024 | 1.9.6.4 | :warning: :warning: rename external bus/memory interface and according generics ("WISHBONE/MEM_EXT" -> "XBUS"); also rename bus interface ports (`wb_* -> xbus_*`) | [#846](https://github.com/stnolting/neorv32/pull/846) |
@ -49,14 +49,14 @@ mimpid = 0x01040312 -> Version 01.04.03.12 -> v1.4.3.12
| 16.02.2024 | 1.9.5.1 | :sparkles: add two new generics to exclude certain PMP modes from synthesis | [#808](https://github.com/stnolting/neorv32/pull/808) |
| 16.02.2024 | [**:rocket:1.9.5**](https://github.com/stnolting/neorv32/releases/tag/v1.9.5) | **New release** | |
| 15.02.2023 | 1.9.4.13 | allow the DMA to issue a FENCE operation | [#807](https://github.com/stnolting/neorv32/pull/807) |
| 14.02.2024 | 1.9.4.12 | :bug: close another illegal compressed instruction encoding loophole | [#806](https://github.com/stnolting/neorv32/pull/806) |
| 14.02.2024 | 1.9.4.12 | :lock: close another illegal compressed instruction encoding loophole | [#806](https://github.com/stnolting/neorv32/pull/806) |
| 11.02.2024 | 1.9.4.11 | :bug: fix several FPU bugs and design flaws | [#794](https://github.com/stnolting/neorv32/pull/794) |
| 11.02.2024 | 1.9.4.10 | minor additions to previous version (1.9.4.9): fix HPM configuration read-back | [#804](https://github.com/stnolting/neorv32/pull/804) |
| 10.02.2024 | 1.9.4.9 | fixing HPM configuration's null range assertions | [#803](https://github.com/stnolting/neorv32/pull/803) |
| 10.02.2024 | 1.9.4.8 | :bug: fix missing fence pass-through in caches | [#802](https://github.com/stnolting/neorv32/pull/802) |
| 09.02.2024 | 1.9.4.7 | :warning: integrate fence signal into CPU bus, remove top entity's fence signals | [#800](https://github.com/stnolting/neorv32/pull/800) |
| 09.02.2024 | 1.9.4.6 | :sparkles: add configurable XIP cache | [#799](https://github.com/stnolting/neorv32/pull/799) |
| 09.02.2024 | 1.9.4.5 | :bug: close further illegal compressed instruction encoding loopholes | [#797](https://github.com/stnolting/neorv32/pull/797) |
| 09.02.2024 | 1.9.4.5 | :lock: close further illegal compressed instruction encoding loopholes | [#797](https://github.com/stnolting/neorv32/pull/797) |
| 04.02.2024 | 1.9.4.4 | :bug: fix minor bug: CPU instruction bus privilege signal did not remain stable during the entire request | [#792](https://github.com/stnolting/neorv32/pull/792) |
| 03.02.2024 | 1.9.4.3 | :bug: fix minor bug: CPU instruction bus privilege signal was hardwired to "user-mode" | [#790](https://github.com/stnolting/neorv32/pull/790) |
| 01.02.2024 | 1.9.4.2 | :sparkles: add support for page fault exceptions (yet unused) | [#786](https://github.com/stnolting/neorv32/pull/786) |
@ -441,7 +441,7 @@ mimpid = 0x01040312 -> Version 01.04.03.12 -> v1.4.3.12
| 11.09.2021 | [**:rocket:1.6.0**](https://github.com/stnolting/neorv32/releases/tag/v1.6.0) | **New release** |
| 11.09.2021 | 1.5.9.9 | removed `mstatus.SD` flag (is always 0 for `Zfinx` extension as the current state is already defined entirely by the `x` register file); tied `mstatus.fs` as it must not affect trapping of `Zfinx` instructions (according to RISC-V specs.) |
| 09.09.2021 | 1.5.9.8 | added flags to `SYSINFO` module to determine configuration of `FAST_MUL_EN` and `FAST_SHIFT_EN` generics by software |
| 09.09.2021 | 1.5.9.7 | `FAST_SHIFT_EN` option will now also implement full-parallel computation logic (like barel shifters) for _all_ `Zbb` shift-related instructions (population count, count leading/trailing zeros, circular shifts) |
| 09.09.2021 | 1.5.9.7 | `FAST_SHIFT_EN` option will now also implement full-parallel computation logic (like barrel shifters) for _all_ `Zbb` shift-related instructions (population count, count leading/trailing zeros, circular shifts) |
| 08.09.2021 | 1.5.9.6 | :sparkles: added support for RISC-V `Zbb` CPU extension (**basic bit-manipulation operations**), enabled via new top generic `CPU_EXTENSION_RISCV_Zbb`; added example software project providing a `Zbb` "intrinsic" library |
| 08.09.2021 | 1.5.9.5 | :bug: fixed missing `flash_sdi_i` in Radiant-related example setups and processor wrappers |
| 19.08.2021 | 1.5.9.4 | :warning: removed custom `mzext` CPU CSR, moved all information flags to new `SYSINFO_CPU` register in the system information memory module (`SYSINFO`) |

View file

@ -13,6 +13,9 @@
-- # before invalidating all cache blocks to force a re-fetch from main memory. After this, the #
-- # fence request is forwarded to the downstream memory system. #
-- # #
-- # Optionally, the cache can be configured as fully-cached disabling any direct/uncached #
-- # accesses. Furthermore, the cache can be entirely read-only removing any write-related logic. #
-- # #
-- # Simplified cache architecture ("-->" = direction of access requests): #
-- # #
-- # Direct Access +----------+ #
@ -63,9 +66,11 @@ use neorv32.neorv32_package.all;
entity neorv32_cache is
generic (
NUM_BLOCKS : natural range 2 to 4096; -- number of cache blocks (min 2), has to be a power of 2
BLOCK_SIZE : natural range 4 to 4096; -- cache block size in bytes (min 4), has to be a power of 2
UC_BEGIN : std_ulogic_vector(3 downto 0) -- begin of uncached address space (page number / 4 MSBs)
NUM_BLOCKS : natural range 2 to 4096; -- number of cache blocks (min 2), has to be a power of 2
BLOCK_SIZE : natural range 4 to 4096; -- cache block size in bytes (min 4), has to be a power of 2
UC_BEGIN : std_ulogic_vector(3 downto 0); -- begin of uncached address space (page number / 4 MSBs of address)
UC_ENABLE : boolean; -- enable direct/uncached accesses
READ_ONLY : boolean -- read-only accesses for host
);
port (
clk_i : in std_ulogic; -- global clock, rising edge
@ -81,6 +86,9 @@ architecture neorv32_cache_rtl of neorv32_cache is
-- host access arbiter (handle CPU accesses to cache) --
component neorv32_cache_host
generic (
READ_ONLY : boolean
);
port (
rstn_i : in std_ulogic;
clk_i : in std_ulogic;
@ -105,7 +113,8 @@ architecture neorv32_cache_rtl of neorv32_cache is
component neorv32_cache_memory
generic (
NUM_BLOCKS : natural;
BLOCK_SIZE : natural
BLOCK_SIZE : natural;
READ_ONLY : boolean
);
port (
rstn_i : in std_ulogic;
@ -130,7 +139,8 @@ architecture neorv32_cache_rtl of neorv32_cache is
component neorv32_cache_bus
generic (
NUM_BLOCKS : natural;
BLOCK_SIZE : natural
BLOCK_SIZE : natural;
READ_ONLY : boolean
);
port (
rstn_i : in std_ulogic;
@ -163,7 +173,7 @@ architecture neorv32_cache_rtl of neorv32_cache is
-- internal bus system --
signal bus_req, dir_req_d, dir_req_q, cache_req : bus_req_t;
signal bus_rsp, dir_rsp_d, dir_rsp_q, cache_rsp: bus_rsp_t;
signal bus_rsp, dir_rsp_d, dir_rsp_q, cache_rsp : bus_rsp_t;
-- cache memory module interface --
type cache_in_t is record
@ -185,18 +195,16 @@ architecture neorv32_cache_rtl of neorv32_cache is
signal cache_stat_dirty, cache_stat_hit : std_ulogic;
signal cache_stat_base : std_ulogic_vector(31 downto 0);
-- cache commands --
signal cache_cmd_inval, cache_cmd_new, cache_cmd_dirty : std_ulogic;
-- bus arbiter commands --
signal cmd_sync, cmd_miss, cmd_busy : std_ulogic;
-- operation commands --
signal cache_cmd_inval, cache_cmd_new, cache_cmd_dirty, bus_cmd_sync, bus_cmd_miss, bus_cmd_busy : std_ulogic;
begin
-- Check if Direct/Uncached Access --------------------------------------------------------
-- -------------------------------------------------------------------------------------------
dir_acc_d <= '1' when (host_req_i.addr(31 downto 28) >= UC_BEGIN) or -- uncached memory page
(host_req_i.rvso = '1') else '0'; -- atomic (reservation set) operation
dir_acc_d <= '1' when (UC_ENABLE = true) and -- direct accesses implemented
((host_req_i.addr(31 downto 28) >= UC_BEGIN) or -- uncached memory page
(host_req_i.rvso = '1')) else '0'; -- atomic (reservation set) operation
-- request splitter: cached or direct access --
req_splitter: process(host_req_i, dir_acc_d)
@ -212,30 +220,52 @@ begin
end process req_splitter;
-- direct/uncached access path pipeline stage --
bus_buffer: process(rstn_i, clk_i)
begin
if (rstn_i = '0') then
dir_acc_q <= '0';
dir_req_q <= req_terminate_c;
dir_rsp_q <= rsp_terminate_c;
elsif rising_edge(clk_i) then
if (dir_acc_q = '0') and (host_req_i.stb = '1') and (dir_acc_d = '1') then
dir_acc_q <= '1';
elsif (dir_acc_q = '1') and ((dir_rsp_q.ack = '1') or (dir_rsp_q.err = '1')) then
direct_acc_enable:
if UC_ENABLE generate
bus_buffer: process(rstn_i, clk_i)
begin
if (rstn_i = '0') then
dir_acc_q <= '0';
dir_req_q <= req_terminate_c;
dir_rsp_q <= rsp_terminate_c;
elsif rising_edge(clk_i) then
if (dir_acc_q = '0') and (host_req_i.stb = '1') and (dir_acc_d = '1') then
dir_acc_q <= '1';
elsif (dir_acc_q = '1') and ((dir_rsp_q.ack = '1') or (dir_rsp_q.err = '1')) then
dir_acc_q <= '0';
end if;
if (READ_ONLY = true) then -- do not propagate STB on write access, issue ERR instead
dir_req_q <= dir_req_d;
dir_req_q.stb <= dir_req_d.stb and (not dir_req_d.rw); -- read accesses only
dir_rsp_q <= dir_rsp_d;
dir_rsp_q.err <= dir_rsp_d.err or (dir_req_d.stb and dir_req_d.rw); -- error on write access
else
dir_req_q <= dir_req_d;
dir_rsp_q <= dir_rsp_d;
end if;
end if;
dir_req_q <= dir_req_d;
dir_rsp_q <= dir_rsp_d;
end if;
end process bus_buffer;
end process bus_buffer;
-- response switch --
host_rsp_o <= cache_rsp when (dir_acc_q = '0') else dir_rsp_q;
-- internal response switch --
host_rsp_o <= cache_rsp when (dir_acc_q = '0') else dir_rsp_q;
end generate;
-- direct accesses not implemented --
direct_acc_disable:
if not UC_ENABLE generate
dir_acc_q <= '0';
dir_req_q <= req_terminate_c;
dir_rsp_q <= rsp_terminate_c;
host_rsp_o <= cache_rsp;
end generate;
-- Host Access Arbiter (Handle *Cached* CPU Bus Requests) ---------------------------------
-- -------------------------------------------------------------------------------------------
neorv32_cache_host_inst: neorv32_cache_host
generic map (
READ_ONLY => READ_ONLY -- host accesses are read-only
)
port map (
-- global control --
rstn_i => rstn_i, -- global reset, async, low-active
@ -244,9 +274,9 @@ begin
req_i => cache_req, -- request
rsp_o => cache_rsp, -- response
-- bus unit interface --
bus_sync_o => cmd_sync, -- sync cache and main memory
bus_miss_o => cmd_miss, -- cache miss
bus_busy_i => cmd_busy, -- bus operation in progress
bus_sync_o => bus_cmd_sync, -- sync cache and main memory
bus_miss_o => bus_cmd_miss, -- cache miss
bus_busy_i => bus_cmd_busy, -- bus operation in progress
-- cache status interface --
dirty_o => cache_cmd_dirty, -- make accessed block dirty
hit_i => cache_stat_hit, -- cache hit
@ -265,8 +295,9 @@ begin
-- -------------------------------------------------------------------------------------------
neorv32_cache_memory_inst: neorv32_cache_memory
generic map (
NUM_BLOCKS => block_num_c, -- number of blocks (min 2), has to be a power of 2
BLOCK_SIZE => block_size_c -- block size in bytes (min 4), has to be a power of 2
NUM_BLOCKS => block_num_c, -- number of blocks (min 2), has to be a power of 2
BLOCK_SIZE => block_size_c, -- block size in bytes (min 4), has to be a power of 2
READ_ONLY => READ_ONLY -- cache is read-only (for host)
)
port map (
-- global control --
@ -291,15 +322,16 @@ begin
);
-- cache access switch --
cache_in <= cache_in_host when (cmd_busy = '0') else cache_in_bus;
cache_in <= cache_in_host when (bus_cmd_busy = '0') else cache_in_bus;
-- Bus Access Arbiter (Handle Cache Miss and Flush/Reload) --------------------------------
-- -------------------------------------------------------------------------------------------
neorv32_cache_bus_inst: neorv32_cache_bus
generic map (
NUM_BLOCKS => block_num_c, -- number of blocks (min 2), has to be a power of 2
BLOCK_SIZE => block_size_c -- block size in bytes (min 4), has to be a power of 2
NUM_BLOCKS => block_num_c, -- number of blocks (min 2), has to be a power of 2
BLOCK_SIZE => block_size_c, -- block size in bytes (min 4), has to be a power of 2
READ_ONLY => READ_ONLY -- read-only bus accesses
)
port map (
-- global control --
@ -311,9 +343,9 @@ begin
bus_req_o => bus_req, -- request
bus_rsp_i => bus_rsp, -- response
-- operation interface --
cmd_sync_i => cmd_sync, -- sync cache and main memory
cmd_miss_i => cmd_miss, -- cache miss
cmd_busy_o => cmd_busy, -- bus operation in progress
cmd_sync_i => bus_cmd_sync, -- sync cache and main memory
cmd_miss_i => bus_cmd_miss, -- cache miss
cmd_busy_o => bus_cmd_busy, -- bus operation in progress
-- cache status interface --
inval_o => cache_cmd_inval, -- invalidate accessed block
new_o => cache_cmd_new, -- set new cache entry
@ -331,23 +363,32 @@ begin
-- Bus Access Switch ----------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- Use a real switch here to buffer direct access requests
-- during out-of-band cache operation (fence / cache flush).
neorv32_cache_bus_switch: entity neorv32.neorv32_bus_switch
generic map (
PORT_A_READ_ONLY => false,
PORT_B_READ_ONLY => false
)
port map (
clk_i => clk_i,
rstn_i => rstn_i,
a_req_i => bus_req,
a_rsp_o => bus_rsp,
b_req_i => dir_req_q,
b_rsp_o => dir_rsp_d,
x_req_o => bus_req_o,
x_rsp_i => bus_rsp_i
);
bus_switch_enable:
if UC_ENABLE generate
-- Use a real switch here to buffer direct access requests during
-- out-of-band cache operations (downstream memory synchronization).
neorv32_cache_bus_switch: entity neorv32.neorv32_bus_switch
generic map (
PORT_A_READ_ONLY => READ_ONLY,
PORT_B_READ_ONLY => READ_ONLY
)
port map (
clk_i => clk_i,
rstn_i => rstn_i,
a_req_i => bus_req,
a_rsp_o => bus_rsp,
b_req_i => dir_req_q,
b_rsp_o => dir_rsp_d,
x_req_o => bus_req_o,
x_rsp_i => bus_rsp_i
);
end generate;
bus_switch_disable:
if not UC_ENABLE generate
bus_req_o <= bus_req;
bus_rsp <= bus_rsp_i;
end generate;
end neorv32_cache_rtl;
@ -402,6 +443,9 @@ library neorv32;
use neorv32.neorv32_package.all;
entity neorv32_cache_host is
generic (
READ_ONLY : boolean -- host accesses are read-only
);
port (
-- global control --
rstn_i : in std_ulogic; -- global reset, async, low-active
@ -430,7 +474,7 @@ end neorv32_cache_host;
architecture neorv32_cache_host_rtl of neorv32_cache_host is
-- control engine --
type ctrl_state_t is (S_IDLE, S_CHECK, S_WAIT_MISS, S_WAIT_SYNC);
type ctrl_state_t is (S_IDLE, S_CHECK, S_WAIT_MISS, S_WAIT_SYNC, S_ERROR);
type ctrl_t is record
state, state_nxt : ctrl_state_t; -- FSM state
req_buf, req_buf_nxt : std_ulogic; -- access request buffer
@ -465,7 +509,7 @@ begin
ctrl.req_buf_nxt <= ctrl.req_buf or req_i.stb;
ctrl.sync_buf_nxt <= ctrl.sync_buf or req_i.fence;
-- cache defaults --
-- cache access defaults --
dirty_o <= '0';
addr_o <= req_i.addr;
we_o <= (others => '0');
@ -473,7 +517,7 @@ begin
wdata_o <= req_i.data;
wstat_o <= '0'; -- host cannot alter status bits
-- bus unit interface defaults --
-- bus unit command defaults --
bus_sync_o <= '0';
bus_miss_o <= '0';
@ -489,7 +533,11 @@ begin
bus_sync_o <= '1'; -- trigger bus unit: sync operation
ctrl.state_nxt <= S_WAIT_SYNC;
elsif (req_i.stb = '1') or (ctrl.req_buf = '1') then -- (pending) access request
ctrl.state_nxt <= S_CHECK;
if (req_i.rw = '1') and (READ_ONLY = true) then -- invalid write access?
ctrl.state_nxt <= S_ERROR;
else
ctrl.state_nxt <= S_CHECK;
end if;
end if;
when S_CHECK => -- check if cache hit
@ -497,7 +545,7 @@ begin
rsp_o.data <= rdata_i; -- output read data
ctrl.req_buf_nxt <= '0'; -- access request completed
if (hit_i = '1') then
if (req_i.rw = '1') then -- write access
if (req_i.rw = '1') and (READ_ONLY = false) then -- write access
dirty_o <= '1'; -- cache block is dirty now
we_o <= req_i.ben; -- finalize write access
end if;
@ -522,6 +570,11 @@ begin
ctrl.state_nxt <= S_CHECK; -- redo cache access
end if;
when S_ERROR => -- access error
-- ------------------------------------------------------------
rsp_o.err <= '1';
ctrl.state_nxt <= S_IDLE;
when others => -- undefined
-- ------------------------------------------------------------
ctrl.state_nxt <= S_IDLE;
@ -580,7 +633,8 @@ use neorv32.neorv32_package.all;
entity neorv32_cache_memory is
generic (
NUM_BLOCKS : natural; -- number of blocks (min 2), has to be a power of 2
BLOCK_SIZE : natural -- block size in bytes (min 4), has to be a power of 2
BLOCK_SIZE : natural; -- block size in bytes (min 4), has to be a power of 2
READ_ONLY : boolean -- cache is read-only (for host)
);
port (
-- global control --
@ -700,7 +754,7 @@ begin
-- Access Status (1 Cycle Latency) --------------------------------------------------------
-- -------------------------------------------------------------------------------------------
hit_o <= '1' when (valid_mem_rd = '1') and (acc_tag_ff = tag_mem_rd) else '0'; -- cache access hit
dirty_o <= '1' when (valid_mem_rd = '1') and (dirty_mem_rd = '1') else '0'; -- accessed block is dirty
dirty_o <= '1' when (valid_mem_rd = '1') and (dirty_mem_rd = '1') and (READ_ONLY = false) else '0'; -- accessed block is dirty
-- base address of accessed block --
base_o(31 downto 31-(tag_size_c-1)) <= tag_mem_rd;
@ -793,7 +847,8 @@ use neorv32.neorv32_package.all;
entity neorv32_cache_bus is
generic (
NUM_BLOCKS : natural; -- number of blocks (min 2), has to be a power of 2
BLOCK_SIZE : natural -- block size in bytes (min 4), has to be a power of 2
BLOCK_SIZE : natural; -- block size in bytes (min 4), has to be a power of 2
READ_ONLY : boolean -- read-only bus accesses
);
port (
-- global control --
@ -885,7 +940,7 @@ begin
upret_nxt <= upret;
addr_nxt <= addr;
-- cache defaults --
-- cache access defaults --
addr_o <= addr.tag & addr.idx & addr.ofs & "00"; -- always word-aligned
we_o <= (others => '0');
swe_o <= '0';
@ -920,7 +975,7 @@ begin
-- ------------------------------------------------------------
upret_nxt <= S_DOWNLOAD_REQ; -- go straight to S_DOWNLOAD_REQ when S_UPLOAD_GET has completed (if executed)
addr_nxt.idx <= baddr.idx; -- index of reference cache block
if (dirty_i = '1') then -- block is dirty, upload first
if (dirty_i = '1') and (READ_ONLY = false) then -- block is dirty, upload first
addr_nxt.tag <= baddr.tag; -- base address (tag + index) of accessed block
state_nxt <= S_UPLOAD_GET;
else -- block is clean, download new block
@ -953,25 +1008,37 @@ begin
when S_UPLOAD_GET => -- upload dirty cache block: read word from cache
-- ------------------------------------------------------------
bus_req_o.rw <= '1'; -- write access
state_nxt <= S_UPLOAD_REQ;
if (READ_ONLY = true) then
state_nxt <= S_IDLE;
else
bus_req_o.rw <= '1'; -- write access
state_nxt <= S_UPLOAD_REQ;
end if;
when S_UPLOAD_REQ => -- upload dirty cache block: request bus write
-- ------------------------------------------------------------
bus_req_o.rw <= '1'; -- write access
bus_req_o.stb <= '1'; -- request new transfer
state_nxt <= S_UPLOAD_RSP;
if (READ_ONLY = true) then
state_nxt <= S_IDLE;
else
bus_req_o.rw <= '1'; -- write access
bus_req_o.stb <= '1'; -- request new transfer
state_nxt <= S_UPLOAD_RSP;
end if;
when S_UPLOAD_RSP => -- upload dirty cache block: wait for bus response
-- ------------------------------------------------------------
bus_req_o.rw <= '1'; -- write access
new_o <= '1'; -- set new block (set tag, make valid, make clean)
if (bus_rsp_i.ack = '1') or (bus_rsp_i.err = '1') then -- wait for response
addr_nxt.ofs <= std_ulogic_vector(unsigned(addr.ofs) + 1);
if (and_reduce_f(addr.ofs) = '1') then -- block completed? offset will be all-zero again after block completion
state_nxt <= upret; -- go back to "upload-done return state"
else -- get next word
state_nxt <= S_UPLOAD_GET;
if (READ_ONLY = true) then
state_nxt <= S_IDLE;
else
bus_req_o.rw <= '1'; -- write access
new_o <= '1'; -- set new block (set tag, make valid, make clean)
if (bus_rsp_i.ack = '1') or (bus_rsp_i.err = '1') then -- wait for response
addr_nxt.ofs <= std_ulogic_vector(unsigned(addr.ofs) + 1);
if (and_reduce_f(addr.ofs) = '1') then -- block completed? offset will be all-zero again after block completion
state_nxt <= upret; -- go back to "upload-done return state"
else -- get next word
state_nxt <= S_UPLOAD_GET;
end if;
end if;
end if;
@ -990,8 +1057,8 @@ begin
-- ------------------------------------------------------------
addr_nxt.tag <= baddr.tag; -- tag of currently index block
inval_o <= '1'; -- invalidate currently index block
if (dirty_i = '1') then -- block dirty?
state_nxt <= S_UPLOAD_GET;
if (dirty_i = '1') and (READ_ONLY = false) then -- block dirty?
state_nxt <= S_UPLOAD_GET;
else -- move on to next block
addr_nxt.idx <= std_ulogic_vector(unsigned(addr.idx) + 1);
if (and_reduce_f(addr.idx) = '1') then -- all blocks done?
@ -1010,7 +1077,7 @@ begin
end case;
end process ctrl_engine_comb;
-- bus arbiter operation in progress (host keeps allying cache address while bud unit reports idle state) --
-- bus arbiter operation in progress (host keeps allying cache address while bus unit reports idle state) --
cmd_busy_o <= '0' when (state = S_IDLE) or (state = S_CHECK) else '1';

View file

@ -188,8 +188,8 @@ begin
bus_req_o.addr <= ctrl.addr_reg;
bus_req_o.rw <= '0'; -- read-only
bus_req_o.stb <= '0';
bus_req_o.rvso <= cpu_req_i.rvso;
bus_req_o.fence <= cpu_req_i.fence;
bus_req_o.rvso <= '0'; -- no reservation set operations
bus_req_o.fence <= '0';
-- fsm --
case ctrl.state is
@ -268,6 +268,7 @@ begin
-- ------------------------------------------------------------
ctrl.clear_buf_nxt <= '0';
cache.clear <= '1';
bus_req_o.fence <= '1'; -- send sync request to downstream memories
ctrl.state_nxt <= S_IDLE;
when others => -- undefined

View file

@ -3,6 +3,7 @@
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # The NEORV32 RISC-V Processor, https://github.com/stnolting/neorv32 #
-- # Copyright (c) 2024, Stephan Nolting. All rights reserved. #
-- # #
-- # Redistribution and use in source and binary forms, with or without modification, are #
@ -28,8 +29,6 @@
-- # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING #
-- # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED #
-- # OF THE POSSIBILITY OF SUCH DAMAGE. #
-- # ********************************************************************************************* #
-- # The NEORV32 RISC-V Processor - https://github.com/stnolting/neorv32 (c) Stephan Nolting #
-- #################################################################################################
library ieee;
@ -53,7 +52,7 @@ package neorv32_package is
-- Architecture Constants -----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01090606"; -- hardware version
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01090607"; -- hardware version
constant archid_c : natural := 19; -- official RISC-V architecture ID
constant XLEN : natural := 32; -- native data path width

View file

@ -950,7 +950,9 @@ begin
generic map (
NUM_BLOCKS => XBUS_CACHE_NUM_BLOCKS,
BLOCK_SIZE => XBUS_CACHE_BLOCK_SIZE,
UC_BEGIN => uncached_begin_c(31 downto 28)
UC_BEGIN => uncached_begin_c(31 downto 28),
UC_ENABLE => true,
READ_ONLY => false
)
port map (
clk_i => clk_i,