ruby โ Coherence Protocol Simulation
Protocol-driven memory system using SLICC-generated controllers, network-on-chip models, and detailed coherence state machines for multiprocessor simulation.
Table of Contents
Overview
📚 What is this & why does it exist?
Think of Ruby as a city-wide traffic management system. Each intersection (Cache Hierarchy | gem5 Wiki" href="../cache/index.html">cache controller) has its own traffic lights (coherence state machine) that follow a rulebook (SLICC protocol). The road network (on-chip network) carries messages between intersections. A central dispatch (directory controller) keeps track of where every vehicle (cache line) is located, ensuring no two intersections claim exclusive rights to the same road. The Sequencer is the on-ramp where CPUs enter the highway, and MessageBuffers are the traffic lanes connecting intersections.
Ruby is gem5's detailed coherence protocol simulator. Unlike the Classic cache system (which has coherence logic hardcoded in C++), Ruby uses SLICC (Specification Language for Implementing Cache Coherence) to define protocol state machines. This makes it straightforward to implement and test new coherence protocols โ from Atomic and Timing Simple CPUs โ gem5 Wiki" href="../../cpu_doc/simple/index.html">simple MI to complex MOESI_CMP_directory.
Key features:
- SLICC-generated controllers โ Coherence logic defined in a high-level DSL, compiled to C++
- Network models โ Simple network (abstract) and Garnet (detailed NoC with routers, VCs, flow control)
- Directory-based coherence โ Scalable multiprocessor coherence via directory controllers
- GPU coalescer โ Specialized memory interface for GPU compute units
- HTM support โ Hardware Transactional Memory via HTMSequencer
- Profiling โ Detailed coherence protocol statistics and event tracking
Architecture
flowchart TD
CPU0["CPU 0"]
CPU1["CPU 1"]
GPU["GPU CU"]
SEQ0["Sequencer 0"]
SEQ1["Sequencer 1"]
GPUC["GPUCoalescer"]
L1C0["L1 Controller 0"]
L1C1["L1 Controller 1"]
L1CG["GPU L1 Controller"]
NET["On-Chip Network\n(Simple / Garnet)"]
L2C["L2 Controller"]
DIR["Directory Controller"]
MC["Memory Controller"]
DRAM["DRAM"]
CPU0 --> SEQ0
CPU1 --> SEQ1
GPU --> GPUC
SEQ0 --> L1C0
SEQ1 --> L1C1
GPUC --> L1CG
L1C0 -->|"MessageBuffer"| NET
L1C1 -->|"MessageBuffer"| NET
L1CG -->|"MessageBuffer"| NET
NET --> L2C
NET --> DIR
L2C -->|"MessageBuffer"| NET
DIR --> MC
MC --> DRAM
SLICC Protocol System
SLICC (Specification Language for Implementing Cache Coherence) is a domain-specific language that compiles into C++ controller code. Each protocol defines:
- States โ Cache line states (e.g., I, S, M, O, E and transient states)
- Events โ Triggers (e.g., Load, Store, Fwd_GetS, Data_from_Dir)
- Transitions โ State ร Event โ Actions + New State
- Actions โ Atomic operations (send message, allocate TBE, set permissions)
stateDiagram-v2
[*] --> I : Initial
I --> IS_D : Load / send GetS
IS_D --> S : Data_from_Dir
I --> IM_AD : Store / send GetX
IM_AD --> IM_A : Data_from_Dir
IM_A --> M : Ack_all
S --> SM_AD : Store / send Upgrade
SM_AD --> SM_A : Data_from_Dir
SM_A --> M : Ack_all
M --> MI_A : Replacement / send PutX
MI_A --> I : Put_Ack
M --> S : Fwd_GetS / send data
M --> I : Fwd_GetX / send data
S --> I : Replacement / send PutS
SLICC Compilation Pipeline
.sm files defining states, events, transitions, and actions for each controller type (L1Cache, L2Cache, Directory).src/mem/slicc/) parses the .sm files and generates C++ controller classes.AbstractController and plug into the network via MessageBuffer ports.Key Classes Reference
| Class | Location | Description |
|---|---|---|
RubySystem | system/RubySystem.hh | Top-level Ruby container. Manages all controllers, the network, and provides the global clock. Handles warm-up and cool-down phases. |
Sequencer | system/Sequencer.hh | CPU-facing interface. Accepts memory requests from the CPU, converts them to Ruby protocol events, and handles responses. Enforces ordering and manages pending request tables. |
DMASequencer | system/DMASequencer.hh | Specialized sequencer for DMA devices that need to access coherent memory. |
GPUCoalescer | system/GPUCoalescer.hh | Memory interface for GPU compute units. Coalesces requests from multiple GPU threads before injecting into the coherence network. |
HTMSequencer | system/HTMSequencer.hh | Extends Sequencer with Hardware Transactional Memory support โ tracks read/write sets and handles conflict detection. |
RubyPort | system/RubyPort.hh | Bridge between gem5 classic ports and Ruby. Translates between Packet-based and Ruby message-based interfaces. |
AbstractController | slicc_interface/AbstractController.hh | Base class for all SLICC-generated controllers. Provides message buffer management, wake-up logic, and statistics. |
CacheMemory | structures/CacheMemory.hh | Ruby's internal cache storage. Provides tag lookup, allocation, and replacement for controller-local caches. |
DirectoryMemory | structures/DirectoryMemory.hh | Stores directory entries mapping cache line addresses to sharing/owner information. |
Network | network/Network.hh | Abstract network interface. Subclassed by SimpleNetwork and GarnetNetwork. |
MessageBuffer | network/MessageBuffer.hh | FIFO message queue connecting controllers to the network. Supports enqueue/dequeue with configurable latency. |
Topology | network/Topology.hh | Defines the network topology (mesh, crossbar, custom) and computes routing tables. |
CacheRecorder | system/CacheRecorder.hh | Records cache state for checkpointing and warm-up acceleration. |
RubyRequest | slicc_interface/RubyRequest.hh | Ruby-internal request representation carrying address, type, data, and requestor info. |
Network Models
Ruby provides two network implementations with different fidelity/speed trade-offs:
Simple Network
An abstract network model that delivers messages with fixed latency. No contention modeling โ messages never block each other. Fast simulation for protocol debugging.
- Fixed per-hop latency
- Infinite bandwidth links
- No router microarchitecture
- Best for: protocol correctness testing, large-scale studies where network detail isn't critical
Garnet Network
A detailed on-chip network model with cycle-accurate router pipelines, virtual channels, credit-based flow control, and configurable topologies.
- 5-stage router pipeline (buffer write โ route compute โ VC allocate โ switch allocate โ switch traverse)
- Wormhole routing with virtual channels (VCs)
- Credit-based flow control
- Configurable link bandwidth, latency, and buffer depths
- Support for mesh, torus, custom topologies
- Fault injection modeling
- Best for: NoC research, detailed performance studies
flowchart LR
subgraph Router["Garnet Router Pipeline"]
BW["Buffer\nWrite"]
RC["Route\nCompute"]
VA["VC\nAllocate"]
SA["Switch\nAllocate"]
ST["Switch\nTraverse"]
LT["Link\nTraverse"]
BW --> RC --> VA --> SA --> ST --> LT
end
NI_IN["Network\nInterface\n(Inbound)"] --> Router
Router --> NI_OUT["Network\nInterface\n(Outbound)"]
Ruby Structures
The structures/ directory contains storage components used by controllers:
| Structure | File | Purpose |
|---|---|---|
CacheMemory | CacheMemory.hh | Set-associative tag+data store for L1/L2 caches within controllers. Supports replacement policies and banked access. |
DirectoryMemory | DirectoryMemory.hh | Maps addresses to directory entries containing owner/sharer bitmasks. |
PerfectCacheMemory | PerfectCacheMemory.hh | Unbounded cache for ideal studies โ every access hits. |
PersistentTable | PersistentTable.hh | Tracks persistent (starvation-prevention) requests from Token protocols. |
BankedArray | BankedArray.hh | Models banked storage with bank conflict detection for timing accuracy. |
ALUFreeListArray | ALUFreeListArray.hh | Manages ALU availability for TBE processing in controllers. |
MN_TBETable | MN_TBETable.hh | Transaction Buffer Entry table โ tracks in-flight coherence transactions. |
RubyPrefetcher | RubyPrefetcher.hh | Simple stride prefetcher integrated into Ruby controllers. |
Request Flow Walkthrough
Trace a CPU load through the Ruby coherence system:
makeRequest() on the L1 cache controller.Load event. If the block is in state S or M, it returns data immediately.I, the controller transitions to IS_D and enqueues a GetS message into the network.Data_from_Dir.IS_D to S, allocates the cache block, and notifies the Sequencer.Available Protocols
gem5 ships with several pre-defined SLICC protocols:
| Protocol | Description | Use Case |
|---|---|---|
MI_example | Minimal 2-state protocol (Modified / Invalid). Teaching and debugging. | Tutorial, baseline |
MESI_Two_Level | MESI protocol with private L1 and shared L2. Classic multi-core. | Multi-core CPU |
MESI_Three_Level | Three-level MESI with L0, L1, and L2 caches. | Complex hierarchy |
MOESI_CMP_directory | MOESI with CMP-style directory. Supports Owned state for reduced memory traffic. | Large-scale CMP |
MOESI_hammer | AMD Hammer-style broadcast protocol with MOESI states. | AMD-style systems |
GPU_VIPER | GPU-specific protocol supporting compute unit coalescing and scope-based synchronization. | GPU simulation |
CHI | AArch32, AArch64, TrustZone security extensions, SVE/SVE2 vector processing, PMU, and hardware transactional memory." href="../../arch_doc/arm/index.html">Arm CHI (Coherent Hub Interface) protocol implementation. | Arm-based systems |
Sub-module Overview
system/
Core Ruby infrastructure: RubySystem, Sequencer, DMASequencer, GPUCoalescer, HTMSequencer, RubyPort, CacheRecorder. The interface between gem5 CPUs and Ruby's protocol world.
network/
On-chip network models. Includes SimpleNetwork (abstract), Garnet (detailed NoC), MessageBuffer, Topology, BasicRouter, BasicLink. Contains garnet/ and simple/ sub-directories.
structures/
Storage components: CacheMemory, DirectoryMemory, PerfectCacheMemory, BankedArray, TBE tables, PersistentTable, RubyPrefetcher.
slicc_interface/
SLICC runtime: AbstractController, AbstractCacheEntry, RubyRequest, Message, ProtocolInfo. Base classes that SLICC-generated code extends.
protocol/
SLICC protocol source files (.sm). This directory is populated based on the selected protocol at build time. Contains the state machine definitions.
profiler/
Ruby-specific profiling and statistics collection. Tracks protocol events, cache hit/miss rates, network utilization, and coherence transition counts.
Cross-Module Connections
flowchart TD
subgraph gem5_Core["gem5 Core"]
PKT["mem/packet.hh\nPacket"]
PORT["mem/port.hh\nRequestPort / ResponsePort"]
end
subgraph Ruby["mem/ruby/"]
RP["RubyPort\n(Port adapter)"]
SEQ["Sequencer"]
CTRL["AbstractController\n(SLICC-generated)"]
CM["CacheMemory"]
MB["MessageBuffer"]
NET["Network"]
end
subgraph Memory["mem/"]
MEMCTRL["MemCtrl\nDRAM Controller"]
end
PKT --> RP
PORT --> RP
RP --> SEQ
SEQ --> CTRL
CTRL --> CM
CTRL --> MB
MB --> NET
NET --> MB
CTRL --> MEMCTRL
Directory Map
Configuration Reference
| Parameter | SimObject | Description | Default |
|---|---|---|---|
num_l1_controllers | RubySystem | Number of L1 cache controllers | Per-core |
cache_size | CacheMemory | Total cache capacity | 32 kB - 2 MB |
cache_assoc | CacheMemory | Set associativity | 4-16 |
number_of_virtual_networks | Network | Virtual network count for message classes | Protocol-specific |
vcs_per_vnet | GarnetNetwork | Virtual channels per virtual network | 4 |
ni_flit_size | GarnetNetwork | Flit size in bytes | 16 |
routing_algorithm | GarnetNetwork | Routing algorithm (XY, custom) | 0 (XY) |
buffer_size | MessageBuffer | Maximum messages in buffer (0 = infinite) | 0 |
latency | BasicLink | Per-link latency in cycles | 1 |