generic β ISA-Independent Base Classes
Abstract interfaces that define the contract between CPU models and ISA implementations, enabling gem5's architecture-agnostic simulation framework.
📚 What is this & why does it exist?
π‘ Think of it likeβ¦The generic module is like the standard electrical outlets in a building. It doesn't matter whether you plug in an American appliance (x86), a European one (AArch32, AArch64, TrustZone security extensions, SVE/SVE2 vector processing, PMU, and hardware transactional memory." href="../arm/index.html">ARM), or an Asian one (RISC-V) β as long as they follow the socket specification (generic base classes), they'll work with any building's wiring (CPU model). The generic module defines those socket specifications: how to decode instructions, translate addresses, manage ISA state, and handle faults.
Architecture Overview
The generic directory contains abstract base classes that every ISA must implement. These classes form the bridge between gem5's ISA-agnostic CPU models (O3, Minor, TimingSimple, KVM) and the ISA-specific behavior (instruction decoding, register layout, fault handling, address translation).
graph TB
subgraph "Generic Interfaces"
InstDecoder["InstDecoder\n(instruction fetch/decode)"]
BaseMMU["BaseMMU\n(memory management)"]
BaseISA["BaseISA\n(ISA state container)"]
BaseTLB["BaseTLB\n(TLB interface)"]
PCStateBase["PCStateBase\n(program counter)"]
end
subgraph "CPU Models (consumers)"
O3["O3CPU"]
Minor["MinorCPU"]
Simple["TimingSimpleCPU"]
KVM["KvmCPU"]
end
subgraph "ISA Implementations (providers)"
X86["X86ISA::*"]
ARM["ArmISA::*"]
RISCV["RiscvISA::*"]
end
O3 --> InstDecoder
O3 --> BaseMMU
O3 --> BaseISA
Minor --> InstDecoder
Minor --> BaseMMU
Simple --> InstDecoder
Simple --> BaseMMU
KVM --> BaseISA
X86 -.->|"implements"| InstDecoder
ARM -.->|"implements"| InstDecoder
RISCV -.->|"implements"| InstDecoder
X86 -.->|"implements"| BaseMMU
ARM -.->|"implements"| BaseMMU
RISCV -.->|"implements"| BaseMMU
InstDecoder β Instruction Decoder Interface
The abstract instruction decoder defines how CPU models feed fetched bytes to the ISA-specific decoder and retrieve decoded StaticInst objects.
class InstDecoder : public SimObject
{
protected:
void *machInst; // ISA-specific machine instruction buffer
public:
InstDecoder(const Params &p);
// Feed fetched bytes from the instruction cache
virtual void moreBytes(const PCStateBase &pc,
Addr fetchPC) = 0;
// Is a complete instruction available for decoding?
virtual bool instReady() const = 0;
// Decode the buffered instruction, advance PC
virtual StaticInstPtr decode(PCStateBase &nextPC) = 0;
// Reset decoder state (e.g., after branch, exception)
virtual void reset() {}
// Get moreBytesSize: how many bytes to fetch per cycle
virtual Addr moreBytesSize() const { return sizeof(MachInst); }
};
Decoder Contract
CPU models interact with the decoder through a Atomic and Timing Simple CPUs β gem5 Wiki" href="../../cpu_doc/simple/index.html">simple protocol:
- Call
moreBytes()with fetched Cache Hierarchy | gem5 Wiki" href="../../mem_doc/cache/index.html">cache line data - Check
instReady()β returns true when enough bytes for a complete instruction - Call
decode()to get theStaticInstand advance the PC - Repeat. Call
reset()on branch misprediction or exception.
BaseMMU β Memory Management Unit Interface
Defines the abstract interface for address translation. Each ISA provides its own MMU implementation with ISA-specific page table formats and TLB organizations.
class BaseMMU : public SimObject
{
public:
enum Mode { Read, Write, Execute };
// Separate TLBs for instructions and data
BaseTLB *itb;
BaseTLB *dtb;
BaseMMU(const Params &p);
// Atomic translation (blocks until complete)
virtual Fault translateAtomic(
const RequestPtr &req,
ThreadContext *tc,
Mode mode) = 0;
// Timing translation (non-blocking, callback)
virtual void translateTiming(
const RequestPtr &req,
ThreadContext *tc,
Translation *translation,
Mode mode) = 0;
// Functional translation (for debug/initialization)
virtual Fault translateFunctional(
const RequestPtr &req,
ThreadContext *tc,
Mode mode);
// TLB management
virtual void flushAll() = 0;
virtual void demapPage(Addr vaddr, uint64_t asn) = 0;
virtual void takeOverFrom(BaseMMU *old) {}
// Get TLBs
BaseTLB *getITB() const { return itb; }
BaseTLB *getDTB() const { return dtb; }
};
Translation Callback
// Used by timing mode for asynchronous translation
class BaseMMU::Translation
{
public:
virtual ~Translation() {}
// Called when translation completes
virtual void finish(const Fault &fault,
const RequestPtr &req,
ThreadContext *tc,
Mode mode) = 0;
// Called if squashed before completion
virtual void markDelayed() {}
};
BaseISA β ISA State Container
Holds all ISA-specific register state that isn't part of the standard integer/float register files. This includes control registers, status registers, and ISA configuration state.
class BaseISA : public SimObject
{
public:
BaseISA(const Params &p);
// Read/write miscellaneous (system) registers
virtual RegVal readMiscRegNoEffect(RegIndex idx) const = 0;
virtual RegVal readMiscReg(RegIndex idx) = 0;
virtual void setMiscRegNoEffect(RegIndex idx, RegVal val) = 0;
virtual void setMiscReg(RegIndex idx, RegVal val) = 0;
// Number of misc registers
virtual int numMiscRegs() const = 0;
// Clear all ISA state
virtual void clear() = 0;
// Initialize for thread context
virtual void setThreadContext(ThreadContext *tc);
// Serialize for checkpointing
virtual void serialize(CheckpointOut &cp) const override;
virtual void unserialize(CheckpointIn &cp) override;
};
BaseTLB β Translation Lookaside Buffer
class BaseTLB : public SimObject
{
public:
BaseTLB(const Params &p);
// Flush all TLB entries
virtual void flushAll() = 0;
// Invalidate entries for a specific page
virtual void demapPage(Addr vaddr, uint64_t asn) = 0;
// Take over state from another TLB (CPU switching)
virtual void takeOverFrom(BaseTLB *otlb) = 0;
// Statistics
virtual void regStats() override;
};
PCStateBase β Program Counter Abstraction
Different ISAs have different PC representations. x86 needs microcode PCs, ARM needs mode bits, RISC-V needs compressed instruction awareness. PCStateBase provides the polymorphic interface.
class PCStateBase
{
protected:
Addr _pc = 0; // Current instruction address
Addr _npc = 0; // Next instruction address
MicroPC _upc = 0; // Micro-operation PC
MicroPC _nupc = 0; // Next micro-operation PC
public:
Addr pc() const { return _pc; }
void pc(Addr val) { _pc = val; }
Addr npc() const { return _npc; }
void npc(Addr val) { _npc = val; }
MicroPC upc() const { return _upc; }
MicroPC nupc() const { return _nupc; }
// Advance PC to next instruction
virtual void advance() = 0;
// Check if branching (npc != sequential)
virtual bool branching() const = 0;
// Clone for speculative execution
virtual PCStateBase *clone() const = 0;
// Comparison for branch prediction validation
virtual bool equals(const PCStateBase &other) const;
// Size of current instruction (for NPC calculation)
virtual Addr instSize() const { return sizeof(MachInst); }
};
How ISAs Implement These Interfaces
graph TB
subgraph "InstDecoder"
ID["InstDecoder (generic)"]
X86D["X86::Decoder\n- Variable length (1-15 bytes)\n- State machine parser\n- Microcode ROM"]
ArmD["ArmISA::Decoder\n- ARM/Thumb/AArch64 modes\n- Conditional execution\n- Fixed-width per mode"]
RvD["RiscvISA::Decoder\n- 16 or 32-bit\n- Simple 2-bit length check\n- C-extension expansion"]
end
subgraph "BaseMMU"
MMU["BaseMMU (generic)"]
X86M["X86::MMU\n- 4-level page tables\n- CR3 page table base\n- Segmentation layer"]
ArmM["ArmISA::MMU\n- Sv39/Sv48 tables (AArch64)\n- Secure/Non-Secure worlds\n- TTBR0/TTBR1"]
RvM["RiscvISA::MMU\n- Sv39/Sv48 tables\n- PMP enforcement\n- SATP register"]
end
ID --> X86D
ID --> ArmD
ID --> RvD
MMU --> X86M
MMU --> ArmM
MMU --> RvM
π Narrated Walkthrough: Adding a New ISA to gem5
- Create Directory β Add
src/arch/myisa/with SConscript and Kconfig files. - Implement InstDecoder β Subclass
InstDecoderand implementmoreBytes(),instReady(), anddecode()for your instruction encoding. - Implement BaseISA β Subclass
BaseISAto define your ISA's system registers (CSRs, control registers, etc.). - Implement BaseMMU β Subclass
BaseMMUandBaseTLBwith your page table format and translation logic. - Define PCState β Subclass
PCStateBasewith your ISA's PC representation (instruction size, modes, etc.). - Define Faults β Create fault classes inheriting from
FaultBasefor each exception type. - Define StaticInst β Implement instruction classes with
execute()methods for each opcode. - System and Standard Library β the control plane of gem5" href="../../python/index.html">Python Wrappers β Create SimObject Python classes (MyISACPU.py, MyISAMMU.py, etc.) for configuration.
Key Components Reference
| Component | Header | Key Methods | Implemented By |
|---|---|---|---|
InstDecoder | decoder.hh | moreBytes(), decode(), instReady() | x86, ARM, RISC-V, MIPS, SPARC, POWER |
BaseMMU | mmu.hh | translateAtomic(), translateTiming(), flushAll() | x86, ARM, RISC-V, MIPS, SPARC |
BaseISA | isa.hh | readMiscReg(), setMiscReg(), clear() | x86, ARM, RISC-V, MIPS, SPARC |
BaseTLB | tlb.hh | flushAll(), demapPage(), takeOverFrom() | x86, ARM, RISC-V, MIPS, SPARC |
PCStateBase | pcstate.hh | pc(), npc(), advance(), branching() | x86, ARM, RISC-V, MIPS, SPARC |
Design Patterns
- Strategy Pattern β CPU models use the generic interface; concrete ISA implementations are injected at configuration time.
- Template Method β Base classes define the algorithm skeleton (e.g., translation workflow), ISA implementations fill in the ISA-specific steps.
- Polymorphism β
PCStateBase*pointers allow CPU models to handle any ISA's PC representation uniformly. - Separation of Concerns β CPU pipeline logic is completely separate from instruction semantics and address translation.
Glossary
| Term | Definition |
|---|---|
| StaticInst | Decoded instruction object containing operands, execute method, and flags |
| ThreadContext | Per-thread CPU state providing access to registers, PC, and ISA state |
| MachInst | Raw machine instruction encoding β ISA-specific size and format |
| MiscReg | Miscellaneous register β ISA-specific system/control registers not in the standard regfile |
| Functional Translation | Instant address translation for debug or initialization (no timing modeled) |
| Atomic Translation | Blocking address translation that completes immediately in atomic CPU mode |
| Timing Translation | Non-blocking translation with callback β models real TLB miss latency |