<<<
:sectnums:
==== Data Cache (dCache)

[cols="<3,<3,<4"]
[grid="none"]
|=======================
| Hardware source files:  | neorv32_cache.vhd     | generic cache module
|                         | neorv32_cache_ram.vhd | tag and data RAM (primitive/IP wrapper)
| Software driver files:  | none                  |
| Top entity ports:       | none                  |
| Configuration generics: | `DCACHE_EN`           | implement CPU-exclusive data cache (D$) when `true`
|                         | `DCACHE_NUM_BLOCKS`   | number of cache blocks ("cache lines"); has to be a power of two
|                         | `CACHE_BLOCK_SIZE`    | size of a cache block in bytes (global configuration for I$ and D$); has to be a power of two, min 4
|                         | `CACHE_BURSTS_EN`     | enable burst transfers for cache update
|                         | `CACHE_UC_BASE`       | base address of uncached address space; has to be 256MB-aligned
| CPU interrupts:         | none                  |
|=======================

**Key Features**

* Direct-mapped cache with _write-back_ & _write-allocated_ write policies
* Configurable number of lines
* Configurable line size
* Allows bypassing for _uncached_ accesses
* Tag and data RAM mapped to memory primitives


**Overview**

The processor features an optional data cache (d-cache) that is directly connected to the <<_cpu_loadstore_unit>>
data interface providing full-transparent accesses. The cache is _direct-mapped_ and uses _write-back_ (copy
modified cache lines back to main memory when evicted) and _write-allocate_ (fetch entire line on a write-miss)
write policies. For the <<_dual_core_configuration>> each CPU core is equipped with a private data cache.

The data cache is enabled by the `DCACHE_EN` generic. The total cache memory size in bytes is defined by
`DCACHE_NUM_BLOCKS x CACHE_BLOCK_SIZE`. `DCACHE_NUM_BLOCKS` defines the number of cache blocks ("lines")
and `CACHE_BLOCK_SIZE` defines the block (line) size in bytes; note that the latter configuration is global
for all caches.

.Retrieve Cache Configuration by Software
[TIP]
Software can retrieve the cache configuration/layout from the <<_sysinfo_cache_configuration>> register.

.Memory Primitives
[TIP]
The cache's tag and data RAM is encapsulated as individual wrapper (`neorv32_cache_ram.vhd`) that can be
replaced by a technology-specific IP. All interface ports provide static signal widths to ease replacement.


**Burst Transfers**

Cache update operations can use <<_locked_bus_accesses_and_bursts,burst transfers>> to increase performance.
Burst operations are enabled (for all caches) by the `CACHE_BURSTS_EN` top generic. When bursts are enabled
all cache block transfers are **always executed as burst transfers**. Hence, all devices, memories and endpoints
that can be accessed by the cache must also be able to process bursts (including modules connected to the
<<_processor_external_bus_interface_xbus>>).

**Cache Bypass**

The cache provides direct/uncached accesses (bypassing the cache) in order to access memory-mapped peripherals.
The base adress of the uncached address space is configured by the `CACHE_UC_BASE` generic. Note that only the
4 MSBs of this address are evaluated resulting in a 256MB granulrity. All accesses that target the address range
from `CACHE_UC_BASE` to `0xFFFFFFFF` will bypass the cache. See section <<_address_space>> for more information.

All atomic memory accesses also bypass the cache regardless of the adress; however, in this case, the cache
explicitly ensures <<_memory_coherence>>: if the address of an atomic memory access is cached, the corresponding
line is first written back to main memory if it has been modified. The corresponding line is then invalidated,
and the atomic access is finally executed as a cache-bypassing access.

**Cache Synchronization and Memory Coherence**

By executing the `fence` instruction the data cache is flushed: modified ("dirty") blocks are copied back to main
memory; all clean blocks are invalidated so that the next CPU access to any block results in a cache miss that
reloads the cache with up-to-date data from main memory. See section <<_memory_coherence>> for more information.

**Cache Bus Error Handling**

The cache responds differently to bus errors depending on which operation caused the error.

[start=1]

. **Cache Bypass**: If a bus error occurs during a cache bypass operation - for example, when accessing
memory-mapped I/O - the bus error is reported to the CPU _immediately_ and with _full precision_. The
address reported in <<_mtval>> represents the _exact_ address that caused the error.

. **Cache Miss Without Eviction**: If the CPU request results in a cache miss that can be completed without, the
according memory block is fetched from main memory. If any memory access within this block transfer causes a bus
error, the entire cache block is discarded and the bus error is reported to the CPU _immediately_ and with
_partial precision_. The address reported in <<_mtval>> represents an address within the cache/memory block
whose fetch caused the error.

. **Cache Miss With Eviction**: If the CPU request results in a cache miss that requires the write-back of
a modified ("dirty") cache block, the modified is copied back to main memory before fetching the actual requested
memory block. If this write-back causes any buss error, the modified cache block being written back is discarded
and the bus error is reported to the CPU _immediately_ and _imprecisley_. The address reported in <<_mtval>>
only represents an address inside the requested memory block - not an address within the block that the cache was
trying to write back.

.Bus-Errors During Cache Write-Back
[IMPORTANT]
This type of cache-related "background" bus error is difficult to debug and - like most other bus errors - might
be fatal when occurring in machine mode. A future version of NEORV32 will include an improved mechanism for
determining the _exact_ address of this type of bus error.

. **Cache Synchronization**: If the cache encounters a bus error while writing modified cache blocks back to main
memory during a cache synchronization operation (`fence`), the cache block that caused the error is remains valid
but also "dirty" (not sync with main memory). The next CPU access that results in a **cache miss with eviction**
of this block will encounter a bus error that is reported to the CPU _immediately_ and _imprecisley_ (see above).
