arch β€” Instruction Set Architectures

ISA-specific implementations providing instruction decoding, register definitions, fault handling, and MMU logic for each supported architecture.

πŸ’‘ Think of it like…

The arch module is like a universal translator. The generic sub-module defines the grammar rules (base classes), while each ISA folder (x86, AArch32, AArch64, TrustZone security extensions, SVE/SVE2 vector processing, PMU, and hardware transactional memory." href="arm/index.html">ARM, RISC-V) is a specific language dictionary. When gem5's CPU core encounters a binary instruction, it hands it to the appropriate ISA translator to decode, execute, and handle any exceptions β€” all through the same standardized interface.

Architecture Overview

gem5 supports multiple instruction set architectures through a plugin-style design. The arch/generic directory defines abstract base classes (InstDecoder, BaseMMU, BaseISA, BaseTLB), and each ISA directory provides concrete implementations. This allows the CPU models to remain ISA-agnostic while still accurately modeling architecture-specific behavior.

graph TB
    subgraph "Generic Base Classes"
      InstDecoder["InstDecoder\n(instruction fetch/decode)"]
      BaseMMU["BaseMMU\n(memory management)"]
      BaseISA["BaseISA\n(ISA state)"]
      BaseTLB["BaseTLB\n(TLB interface)"]
      PCStateBase["PCStateBase\n(program counter)"]
    end

    subgraph "x86"
      X86Dec["X86::Decoder"]
      X86MMU["X86::MMU"]
      X86ISA["X86::ISA"]
      X86TLB["X86::TLB"]
    end

    subgraph "ARM"
      ArmDec["ArmISA::Decoder"]
      ArmMMU["ArmISA::MMU"]
      ArmISAc["ArmISA::ISA"]
      ArmTLB["ArmISA::TLB"]
    end

    subgraph "RISC-V"
      RiscvDec["RiscvISA::Decoder"]
      RiscvMMU["RiscvISA::MMU"]
      RiscvISAc["RiscvISA::ISA"]
      RiscvTLB["RiscvISA::TLB"]
    end

    InstDecoder --> X86Dec
    InstDecoder --> ArmDec
    InstDecoder --> RiscvDec
    BaseMMU --> X86MMU
    BaseMMU --> ArmMMU
    BaseMMU --> RiscvMMU
    BaseISA --> X86ISA
    BaseISA --> ArmISAc
    BaseISA --> RiscvISAc
    BaseTLB --> X86TLB
    BaseTLB --> ArmTLB
    BaseTLB --> RiscvTLB
    

ISA Plugin Pattern

gem5's ISA abstraction uses a combination of C++ virtual interfaces and build-system-level selection. At compile time, one or more ISAs are enabled via the build configuration. The CPU model calls generic methods on InstDecoder, BaseISA, and BaseMMU, which dispatch to the ISA-specific implementation.

Generic Base Classes

// arch/generic/decoder.hh
class InstDecoder : public SimObject
{
  protected:
    void *machInst;  // ISA-specific machine instruction

  public:
    // Feed bytes from instruction fetch
    virtual void moreBytes(const PCStateBase &pc, Addr fetchPC) = 0;

    // Check if a complete instruction is available
    virtual bool instReady() const = 0;

    // Decode and return a StaticInst
    virtual StaticInstPtr decode(PCStateBase &nextPC) = 0;

    // Reset decoder state (e.g., on branch)
    virtual void reset() {}
};
// arch/generic/mmu.hh
class BaseMMU : public SimObject
{
  public:
    enum Mode { Read, Write, Execute };

    BaseTLB *dtb;  // Data TLB
    BaseTLB *itb;  // Instruction TLB

    // Address translation
    virtual Fault translateAtomic(const RequestPtr &req,
        ThreadContext *tc, Mode mode) = 0;

    virtual void translateTiming(const RequestPtr &req,
        ThreadContext *tc, Translation *translation,
        Mode mode) = 0;

    // TLB maintenance
    virtual void flushAll() = 0;
    virtual void demapPage(Addr vaddr, uint64_t asn) = 0;
};

PC State Abstraction

Each ISA has a different program counter representation. x86 needs microcode PC tracking, ARM needs Thumb/ARM mode bits, and RISC-V needs compressed instruction awareness. PCStateBase provides the polymorphic interface.

class PCStateBase
{
  protected:
    Addr _pc = 0;
    Addr _npc = 0;
    MicroPC _upc = 0;
    MicroPC _nupc = 0;

  public:
    Addr pc() const { return _pc; }
    Addr npc() const { return _npc; }
    MicroPC upc() const { return _upc; }

    virtual PCStateBase *clone() const = 0;
    virtual void advance() = 0;
    virtual bool branching() const = 0;
};

Supported ISAs

ISADirectoryKey FeaturesModes
x86-64arch/x86/Microcode engine, CPUID, APIC, segmentationSE + FS
ARM/AArch64arch/arm/Security extensions (TrustZone), PMU, HTM, SVESE + FS
RISC-Varch/riscv/M/A/F/D/C/V extensions, PMP, PMA checkerSE + FS
MIPSarch/mips/MIPS32/64, CP0 coprocessorSE + FS
SPARCarch/sparc/SPARC V9, register windowsSE + FS
POWERarch/power/POWER ISASE
Nullarch/null/Stub ISA for testing infrastructureβ€”

Instruction Decode Pipeline

sequenceDiagram
    participant CPU as CPU Frontend
    participant Dec as InstDecoder
    participant Cache as StaticInst Cache
    participant Exec as Execution Unit

    CPU->>Dec: moreBytes(pc, fetchPC)
    Dec->>Dec: Buffer and parse bytes
    CPU->>Dec: instReady()?
    Dec-->>CPU: true
    CPU->>Dec: decode(nextPC)
    Dec->>Cache: lookup machInst
    alt Cache hit
      Cache-->>Dec: Return cached StaticInst
    else Cache miss
      Dec->>Dec: Create new StaticInst
      Dec->>Cache: Insert into cache
    end
    Dec-->>CPU: StaticInstPtr
    CPU->>Exec: execute(StaticInst, ThreadContext)
    

πŸ” Narrated Walkthrough: From Binary to Execution

  1. Fetch β€” The CPU frontend reads bytes from the instruction Cache Hierarchy | gem5 Wiki" href="../mem_doc/cache/index.html">cache at the current PC. For x86, this may be a variable number of bytes; for RISC-V, 2 or 4 bytes.
  2. Feed Decoder β€” Fetched bytes are passed to the ISA-specific InstDecoder::moreBytes(). The decoder accumulates bytes until a complete instruction is recognized.
  3. Decode β€” decode() converts the raw machine instruction into a StaticInst object. For x86, this may produce multiple microops. For ARM, it selects between ARM/Thumb/AArch64 decoding.
  4. Cache β€” Decoded instructions are cached to avoid redundant decoding. The cache is keyed by the machine instruction encoding.
  5. Execute β€” The StaticInst::execute() method is called with a ThreadContext, which provides access to registers, memory, and ISA state.
  6. Faults β€” If execution triggers an exception (page fault, illegal instruction), the ISA's fault class handles the trap, updating PC to the exception vector.

Fault Hierarchy

Each ISA defines its own fault classes inheriting from FaultBase. Faults represent architectural exceptions (page faults, interrupts, traps) and carry ISA-specific information for handler dispatch.

// Generic fault base
class FaultBase : public RefCounted
{
  public:
    virtual const char *name() const = 0;
    virtual void invoke(ThreadContext *tc,
                        const StaticInstPtr &inst) = 0;
};

typedef RefCountingPtr<FaultBase> Fault;
const Fault NoFault = nullptr;

Key Components Reference

ComponentLocationPurposeCategory
InstDecodergeneric/decoder.hhAbstract instruction decoder interfaceGeneric
BaseMMUgeneric/mmu.hhAbstract MMU with iTLB/dTLBGeneric
BaseISAgeneric/isa.hhISA register state containerGeneric
BaseTLBgeneric/tlb.hhAbstract TLB interfaceGeneric
PCStateBasegeneric/pcstate.hhPolymorphic program counterGeneric
FaultBasesim/faults.hhBase class for all ISA faultsGeneric
X86::Decoderx86/decoder.hhx86 variable-length + microcode decoderx86
ArmISA::Decoderarm/decoder.hhARM/Thumb/AArch64 decoderARM
RiscvISA::Decoderriscv/decoder.hhRISC-V 16/32-bit decoderRISC-V
X86ISA::Interruptsx86/interrupts.hhLocal APIC interrupt controllerx86
ArmISA::PMUarm/ArmPMU.pyARM Performance Monitoring UnitARM
PMPriscv/PMP.pyRISC-V Physical Memory ProtectionRISC-V

Sub-Modules

πŸ–₯️ x86

Full x86-64 ISA with variable-length decoding, microcode engine, CPUID emulation, and APIC interrupt controller.

x86-64

πŸ“± arm

ARM and AArch64 ISA with TrustZone security extensions, SVE, PMU, and hardware transactional memory support.

ARMv8

πŸ”§ riscv

RISC-V ISA with modular extensions (M/A/F/D/C/V), PMP/PMA security, and compressed instruction support.

RV64GC

🧬 generic

ISA-independent abstract base classes defining the decoder, MMU, TLB, ISA state, and PC interfaces.

Base

Cross-Module Connections

graph LR
    arch["arch\n(ISA decoders, faults, MMU)"]
    sim["sim\n(SimObject, EventQueue)"]
    cpu["cpu\n(O3, Minor, KVM)"]
    mem["mem\n(cache, DRAM)"]
    base["base\n(BitUnion, types)"]

    base -->|"BitUnion, Addr"| arch
    sim -->|"SimObject base"| arch
    arch -->|"StaticInst, Faults"| cpu
    arch -->|"MMU, TLB"| mem
    cpu -->|"ThreadContext"| arch
    

Glossary

TermDefinition
ISAInstruction Set Architecture β€” the contract between hardware and software (x86, ARM, RISC-V)
StaticInstDecoded instruction object containing operand info, execute method, and disassembly
MachInstRaw machine instruction encoding (ISA-specific size and format)
ThreadContextPer-thread CPU state β€” registers, PC, ISA state β€” shared between arch and CPU models
MicroopMicro-operation β€” x86 decomposes complex CISC instructions into simpler microops
TLBTranslation Lookaside Buffer β€” caches virtual-to-physical address translations
PMPPhysical Memory Protection β€” RISC-V mechanism for memory access control
TrustZoneARM security extension partitioning system into Secure and Non-Secure worlds