Overview
Cache coherence is the property that maintains data consistency across multiple caches in a multi-core system. It enables data sharing among caches and substantially reduces task computation time.[1] In multi-core cache systems, when multiple accesses target the same cache line, coherence must be enforced correctly to preserve correctness.[2]
Coherence Protocols
Canonical coherence protocols are organized around a set of stable states that describe the permitted accesses to a cached line. One well-known set of canonical states is MOESIF (Modified, Owned, Exclusive, Shared, Invalid, Forward), which is used by the open-source BedRock coherence protocol.[3]
BedRock reduces implementation burden by eliminating transient coherence states from the protocol. The protocol's design complexity, concurrency, and verification effort have been analyzed and compared against a canonical directory-based invalidate coherence protocol.[3]
BedRock System Components
The BedRock coherence system consists of three main building blocks that together maintain coherence between processor cores, coherent accelerators, and the memory system:[4]
- Coherence network — the on-chip interconnect that carries coherence messages.
- Local cache engines (LCEs) — cache controllers that manage coherence transactions for a single instruction or data L1 cache. An LCE interfaces on one side with the L1 cache and on the other with the BedRock coherence network. It issues requests on a cache miss and responds to coherence update commands received from the network, ensuring coherence for its corresponding cache.
- Cache coherence engines (CCEs) — coherence directories responsible for maintaining coherence for independent subsets of memory address space. CCEs operate as programmable microcode engines that execute both RISC-style general-purpose operations and more complex coherence-specialized operations aimed at accelerating common cache coherence transactions, with most instructions executing in a single cycle.
A BedRock CCE contains:[4]
- A fetch stage for instruction decoding, branch prediction, and redirections, and an execute stage for instruction execution and branch resolution.
- 8 64-bit general-purpose registers.
- A miss status handling register (MSHR) to track the status of the current outstanding request.
- Coherence network ports for sending and receiving messages on the BedRock network.
- Dedicated coherence directory storage, speculative memory access tracking storage, and pending bit storage.
Tile-Level Integration (BlackParrot)
A typical BlackParrot-based SoC tile contains a core, a cache coherence engine (CCE), and an L2 slice. Beyond basic tiles, several specialized tile types coexist on the same coherence network:[4]
- Coherent accelerator tiles — implement an accelerator that has access to the cache-coherent memory system.
- L2 extension tiles — allow the amount of L2 cache to be changed.
- Streaming accelerator or I/O tiles — enable flexible interfacing of a common memory system via a shared non-L1-cached address space that is routed over the coherence network.
The BlackParrot core complex is itself partitioned into a Front End, Back End, and Memory End that communicate through well-defined latency-insensitive interfaces, with the Memory End hosting the BedRock coherence system.[4]
Directory Implementations (BlackParrot-BedRock)
The BedRock protocol has been instantiated in the BlackParrot 64-bit RISC-V multicore processor through three cache coherence directory microarchitectures, collectively called BlackParrot-BedRock (BP-BedRock):[3]
- Fixed-function coherence directory engine — provides a baseline design for performance and area comparisons.
- Microcode-programmable coherence directory — demonstrates the feasibility of implementing a programmable coherence engine capable of maintaining sufficient protocol processing performance.
- Hybrid fixed-function and programmable coherence directory — blends the protocol processing performance of the fixed-function design with the programmable flexibility of the microcode-programmable design.
These implementations demonstrate the feasibility and challenges of including programmable logic within the coherence system of modern shared-memory multicore processors.[3]
Network-on-Chip (NoC) Considerations
In multi-core designs, cache coherence generates traffic that must be carried by the on-chip interconnect. Routing serves two roles: facilitating data sharing (influenced by topology) and managing NoC-level communication. Cache coherence is, however, often overlooked in routing, causing mismatches between design expectations and evaluation outcomes.[1]
Two main challenges have been identified:[1]
- The lack of specialized tools to assess cache coherence's impact.
- The neglect of topology selection in routing.
A Cache Coherence Traffic Analyzer (CCTA) has been proposed to assess coherence traffic, and a cache-coherence-aware routing approach with integrated topology selection has been shown to achieve up to 10.52% lower packet latency, 55.51% faster execution time, and 49.02% total energy savings.[1]
Failure Modes
If coherence is not enforced correctly, accesses to the same cache line can lead to:[2]
- Stale data — a core reads a value that has been updated elsewhere.
- Data corruption — concurrent updates produce an inconsistent line state.
- Stalls — cores are forced to wait while coherence is re-established.
Verification and Multi-Core Validation
Cache coherence interactions are among the behaviors that must be exercised in modern multi-core validation flows. In RISC-V verification, coverage closure refers to the process of reaching sufficient functional and code coverage to gain confidence that relevant design behaviors — including coherence interactions — have been tested.[2]
In the OpenXiangShan project, multi-core validation specifically targets cache coherence and memory ordering. The project's continuous integration uses XSNoCDiffTopConfig together with dual-core NEMU to verify cache coherence and memory ordering correctness against a reference model.[5] Performance regression tracking in the same flow runs SPEC CPU 2006 checkpoints to monitor instructions-per-cycle (IPC) and detect performance regressions that may be coherence-related.[5]
Cache coherence correctness in such multi-core validation flows is closely tied to memory consistency model compliance, since coherence defines the values a core is permitted to observe for a given line and the consistency model defines the ordering of memory operations across cores.