ruby โ€” Coherence Protocol Simulation

Protocol-driven memory system using SLICC-generated controllers, network-on-chip models, and detailed coherence state machines for multiprocessor simulation.

5
Sub-directories
SLICC
Protocol Language
2
Network Models
MOESI / MESI
Protocol Families
GPU + HTM
Specialized Support
Table of Contents

    Overview

    📚 What is this & why does it exist?

    Analogy โ€” Traffic Management

    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

    Click to expand
    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)
    Click to expand
    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

    Protocol definition โ€” Write .sm files defining states, events, transitions, and actions for each controller type (L1Cache, L2Cache, Directory).
    SLICC compiler โ€” The SLICC compiler (System and Standard Library โ€” the control plane of gem5" href="../../python/index.html">Python-based, in src/mem/slicc/) parses the .sm files and generates C++ controller classes.
    Generated code โ€” Output includes controller classes, message types, and profiling stubs that integrate with the Ruby infrastructure.
    Integration โ€” Generated controllers extend AbstractController and plug into the network via MessageBuffer ports.

    Key Classes Reference

    ClassLocationDescription
    RubySystemsystem/RubySystem.hhTop-level Ruby container. Manages all controllers, the network, and provides the global clock. Handles warm-up and cool-down phases.
    Sequencersystem/Sequencer.hhCPU-facing interface. Accepts memory requests from the CPU, converts them to Ruby protocol events, and handles responses. Enforces ordering and manages pending request tables.
    DMASequencersystem/DMASequencer.hhSpecialized sequencer for DMA devices that need to access coherent memory.
    GPUCoalescersystem/GPUCoalescer.hhMemory interface for GPU compute units. Coalesces requests from multiple GPU threads before injecting into the coherence network.
    HTMSequencersystem/HTMSequencer.hhExtends Sequencer with Hardware Transactional Memory support โ€” tracks read/write sets and handles conflict detection.
    RubyPortsystem/RubyPort.hhBridge between gem5 classic ports and Ruby. Translates between Packet-based and Ruby message-based interfaces.
    AbstractControllerslicc_interface/AbstractController.hhBase class for all SLICC-generated controllers. Provides message buffer management, wake-up logic, and statistics.
    CacheMemorystructures/CacheMemory.hhRuby's internal cache storage. Provides tag lookup, allocation, and replacement for controller-local caches.
    DirectoryMemorystructures/DirectoryMemory.hhStores directory entries mapping cache line addresses to sharing/owner information.
    Networknetwork/Network.hhAbstract network interface. Subclassed by SimpleNetwork and GarnetNetwork.
    MessageBuffernetwork/MessageBuffer.hhFIFO message queue connecting controllers to the network. Supports enqueue/dequeue with configurable latency.
    Topologynetwork/Topology.hhDefines the network topology (mesh, crossbar, custom) and computes routing tables.
    CacheRecordersystem/CacheRecorder.hhRecords cache state for checkpointing and warm-up acceleration.
    RubyRequestslicc_interface/RubyRequest.hhRuby-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
    Click to expand
    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:

    StructureFilePurpose
    CacheMemoryCacheMemory.hhSet-associative tag+data store for L1/L2 caches within controllers. Supports replacement policies and banked access.
    DirectoryMemoryDirectoryMemory.hhMaps addresses to directory entries containing owner/sharer bitmasks.
    PerfectCacheMemoryPerfectCacheMemory.hhUnbounded cache for ideal studies โ€” every access hits.
    PersistentTablePersistentTable.hhTracks persistent (starvation-prevention) requests from Token protocols.
    BankedArrayBankedArray.hhModels banked storage with bank conflict detection for timing accuracy.
    ALUFreeListArrayALUFreeListArray.hhManages ALU availability for TBE processing in controllers.
    MN_TBETableMN_TBETable.hhTransaction Buffer Entry table โ€” tracks in-flight coherence transactions.
    RubyPrefetcherRubyPrefetcher.hhSimple stride prefetcher integrated into Ruby controllers.

    Request Flow Walkthrough

    Trace a CPU load through the Ruby coherence system:

    CPU issues load โ€” The CPU sends a read request to the Sequencer via RubyPort.
    Sequencer processes โ€” The Sequencer checks its pending table for conflicts, then calls makeRequest() on the L1 cache controller.
    L1 controller event โ€” The SLICC state machine receives a Load event. If the block is in state S or M, it returns data immediately.
    Cache miss โ†’ GetS โ€” If the block is in state I, the controller transitions to IS_D and enqueues a GetS message into the network.
    Network transport โ€” The message traverses the on-chip network (Simple: fixed latency; Garnet: full router pipeline) to reach the directory.
    Directory lookup โ€” The Directory controller looks up the address. If no exclusive owner exists, it fetches data from memory and sends Data_from_Dir.
    Data response โ€” The data message travels back through the network to the requesting L1 controller.
    State transition โ€” The L1 controller receives the data, transitions from IS_D to S, allocates the cache block, and notifies the Sequencer.
    Sequencer completes โ€” The Sequencer marks the request as complete and sends the response back to the CPU via RubyPort.

    Available Protocols

    gem5 ships with several pre-defined SLICC protocols:

    ProtocolDescriptionUse Case
    MI_exampleMinimal 2-state protocol (Modified / Invalid). Teaching and debugging.Tutorial, baseline
    MESI_Two_LevelMESI protocol with private L1 and shared L2. Classic multi-core.Multi-core CPU
    MESI_Three_LevelThree-level MESI with L0, L1, and L2 caches.Complex hierarchy
    MOESI_CMP_directoryMOESI with CMP-style directory. Supports Owned state for reduced memory traffic.Large-scale CMP
    MOESI_hammerAMD Hammer-style broadcast protocol with MOESI states.AMD-style systems
    GPU_VIPERGPU-specific protocol supporting compute unit coalescing and scope-based synchronization.GPU simulation
    CHIAArch32, 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.

    20+ files ยท CPU/GPU interface

    network/

    On-chip network models. Includes SimpleNetwork (abstract), Garnet (detailed NoC), MessageBuffer, Topology, BasicRouter, BasicLink. Contains garnet/ and simple/ sub-directories.

    15+ files ยท 2 network models

    structures/

    Storage components: CacheMemory, DirectoryMemory, PerfectCacheMemory, BankedArray, TBE tables, PersistentTable, RubyPrefetcher.

    15+ files ยท Cache/directory storage

    slicc_interface/

    SLICC runtime: AbstractController, AbstractCacheEntry, RubyRequest, Message, ProtocolInfo. Base classes that SLICC-generated code extends.

    13+ files ยท Protocol runtime

    protocol/

    SLICC protocol source files (.sm). This directory is populated based on the selected protocol at build time. Contains the state machine definitions.

    Per-protocol ยท SLICC source

    profiler/

    Ruby-specific profiling and statistics collection. Tracks protocol events, cache hit/miss rates, network utilization, and coherence transition counts.

    Pipeline โ€” gem5 Wiki" class="xref">Statistics & profiling

    Cross-Module Connections

    Click to expand
    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

    src/mem/ruby/ โ”œโ”€โ”€ common/ # Shared types and utilities โ”‚ โ”œโ”€โ”€ Address.hh # Ruby address types โ”‚ โ”œโ”€โ”€ DataBlock.hh # Cache line data container โ”‚ โ””โ”€โ”€ MachineID.hh # Controller identification โ”œโ”€โ”€ network/ # Network models โ”‚ โ”œโ”€โ”€ Network.hh / .cc # Abstract Network base โ”‚ โ”œโ”€โ”€ MessageBuffer.hh / .cc # Inter-controller message FIFO โ”‚ โ”œโ”€โ”€ Topology.hh / .cc # Network topology definition โ”‚ โ”œโ”€โ”€ BasicRouter.hh / .cc # Abstract router base โ”‚ โ”œโ”€โ”€ BasicLink.hh / .cc # Abstract link base โ”‚ โ”œโ”€โ”€ simple/ # Simple (abstract) network โ”‚ โ”‚ โ”œโ”€โ”€ SimpleNetwork.hh / .cc โ”‚ โ”‚ โ””โ”€โ”€ Switch.hh / .cc โ”‚ โ””โ”€โ”€ garnet/ # Garnet detailed NoC โ”‚ โ”œโ”€โ”€ GarnetNetwork.hh / .cc โ”‚ โ”œโ”€โ”€ Router.hh / .cc โ”‚ โ”œโ”€โ”€ InputUnit.hh / .cc โ”‚ โ”œโ”€โ”€ OutputUnit.hh / .cc โ”‚ โ”œโ”€โ”€ CrossbarSwitch.hh / .cc โ”‚ โ””โ”€โ”€ NetworkLink.hh / .cc โ”œโ”€โ”€ structures/ # Storage components โ”‚ โ”œโ”€โ”€ CacheMemory.hh / .cc # Ruby cache storage โ”‚ โ”œโ”€โ”€ DirectoryMemory.hh / .cc # Directory entries โ”‚ โ”œโ”€โ”€ PerfectCacheMemory.hh # Ideal cache โ”‚ โ”œโ”€โ”€ BankedArray.hh / .cc # Banked storage model โ”‚ โ””โ”€โ”€ RubyPrefetcher.hh / .cc # Ruby prefetcher โ”œโ”€โ”€ system/ # Core runtime โ”‚ โ”œโ”€โ”€ RubySystem.hh / .cc # Top-level container โ”‚ โ”œโ”€โ”€ Sequencer.hh / .cc # CPU interface โ”‚ โ”œโ”€โ”€ DMASequencer.hh / .cc # DMA interface โ”‚ โ”œโ”€โ”€ GPUCoalescer.hh / .cc # GPU interface โ”‚ โ”œโ”€โ”€ HTMSequencer.hh / .cc # HTM interface โ”‚ โ”œโ”€โ”€ RubyPort.hh / .cc # Port adapter โ”‚ โ””โ”€โ”€ CacheRecorder.hh / .cc # Checkpoint support โ”œโ”€โ”€ slicc_interface/ # SLICC runtime base โ”‚ โ”œโ”€โ”€ AbstractController.hh / .cc โ”‚ โ”œโ”€โ”€ AbstractCacheEntry.hh / .cc โ”‚ โ”œโ”€โ”€ RubyRequest.hh / .cc โ”‚ โ”œโ”€โ”€ Message.hh โ”‚ โ””โ”€โ”€ RubySlicc_Util.hh โ”œโ”€โ”€ protocol/ # SLICC source files (build-time) โ””โ”€โ”€ profiler/ # Statistics collection

    Configuration Reference

    ParameterSimObjectDescriptionDefault
    num_l1_controllersRubySystemNumber of L1 cache controllersPer-core
    cache_sizeCacheMemoryTotal cache capacity32 kB - 2 MB
    cache_assocCacheMemorySet associativity4-16
    number_of_virtual_networksNetworkVirtual network count for message classesProtocol-specific
    vcs_per_vnetGarnetNetworkVirtual channels per virtual network4
    ni_flit_sizeGarnetNetworkFlit size in bytes16
    routing_algorithmGarnetNetworkRouting algorithm (XY, custom)0 (XY)
    buffer_sizeMessageBufferMaximum messages in buffer (0 = infinite)0
    latencyBasicLinkPer-link latency in cycles1