base β Core Utility Library
Foundational types, data structures, debugging infrastructure, and utility classes used across the entire gem5 simulator.
The base module is like a well-stocked workshop toolbox. Before you can build a house (simulate a processor), you need reliable measuring tapes (Addr, Tick types), screwdrivers (BitUnion for bit manipulation), logbooks (trace/debug), and quality meters (stats). Every other gem5 module reaches into this toolbox daily.
Architecture Overview
The base module provides the shared infrastructure that every gem5 component relies upon. It encompasses fundamental type definitions, address range management, statistics collection, binary loading, debug tracing, and generic data structures. Unlike sim (which manages simulation control) or arch (which defines ISAs), base is entirely ISA-agnostic and simulation-model-agnostic.
graph TB
subgraph "Types & Primitives"
types["types.hh\nAddr, Tick, MicroPC"]
bitunion["bitunion.hh\nBitUnion templates"]
flags["flags.hh\nFlags<T>"]
end
subgraph "Debug & Trace"
debug["debug.hh\nSimpleFlag, CompoundFlag"]
trace["trace.hh\nDPRINTF, OstreamLogger"]
end
subgraph "Data Structures"
addrrange["addr_range.hh\nAddrRange"]
circq["circular_queue.hh\nCircularQueue"]
satcnt["sat_counter.hh\nSatCounter"]
refcnt["refcnt.hh\nRefCountingPtr"]
trie["trie.hh\nTrie"]
end
subgraph "I/O & Config"
inifile["inifile.hh\nINI parser"]
cprintf["cprintf.hh\nFormatted output"]
str["str.hh\nString utilities"]
end
subgraph "Sub-Modules"
loader["loader/\nBinary loading"]
stats["stats/\nStatistics framework"]
end
types --> addrrange
types --> bitunion
debug --> trace
Fundamental Types
The types.hh header defines the core numeric types used throughout gem5. These provide a consistent, portable foundation for address representation, time tracking, and microarchitectural indexing.
namespace gem5 {
// Address type β typically 64-bit unsigned
typedef uint64_t Addr;
const Addr MaxAddr = (Addr)-1;
// Simulation time unit (1 Tick = 1 ps by default)
typedef uint64_t Tick;
const Tick MaxTick = (Tick)-1;
const Tick curTick(); // Current simulation time
// Microcode program counter
typedef uint16_t MicroPC;
const MicroPC MicroPCRomBit = 1 << 15;
// RegIndex for register file access
typedef uint16_t RegIndex;
} // namespace gem5
Address Range Management
AddrRange is a versatile class representing contiguous or interleaved address ranges. It supports hashed interleaving for multi-channel memory controllers and provides efficient containment testing.
class AddrRange
{
Addr _start;
Addr _end;
std::vector<Addr> masks; // Interleaving masks
uint8_t intlvMatch; // Interleave match value
public:
AddrRange(Addr start, Addr end);
AddrRange(Addr start, Addr end, const std::vector<Addr> &masks,
uint8_t intlv_match);
Addr start() const { return _start; }
Addr end() const { return _end; }
Addr size() const;
bool contains(Addr a) const;
bool intersects(const AddrRange &r) const;
bool isSubset(const AddrRange &r) const;
// Remove interleaving bits to get offset
Addr removeIntlvBits(Addr a) const;
Addr addIntlvBits(Addr a) const;
// Merge contiguous/overlapping ranges
bool mergesWith(const AddrRange &r) const;
};
Debug and Tracing
gem5's debug system uses compile-time flags and the DPRINTF macro family for conditional tracing. Debug flags are organized into SimpleFlag (individual) and CompoundFlag (groups) categories, controllable at runtime via command-line options.
Debug Flags
namespace debug {
class Flag
{
public:
Flag(const char *name, const char *desc);
const char *name() const;
virtual void enable() = 0;
virtual void disable() = 0;
virtual bool tracing() const = 0;
};
class SimpleFlag : public Flag
{
bool _tracing = false;
public:
void enable() override { _tracing = true; }
void disable() override { _tracing = false; }
bool tracing() const override { return _tracing; }
};
class CompoundFlag : public Flag
{
std::vector<Flag *> _kids;
public:
void enable() override; // Enables all children
void disable() override; // Disables all children
};
} // namespace debug
Trace System
// Usage pattern in gem5 source code:
DPRINTF(CacheTags, "Looking up addr %#x in set %d\n", addr, set);
DPRINTFR(Fetch, "Fetching instruction at PC %s\n", pc);
// Trace output logger
namespace trace {
class OstreamLogger : public Logger
{
public:
OstreamLogger(std::ostream &os);
void logMessage(Tick when, const std::string &name,
const std::string &flag,
const std::string &message) override;
};
} // namespace trace
Bit Manipulation
The BitUnion template system provides type-safe access to bit fields within machine words. It's essential for decoding instruction encodings, register fields, and hardware status registers.
// Define a bit union for an x86 page table entry
BitUnion64(PageTableEntry)
Bitfield<63> nx; // No-execute
Bitfield<51, 12> ppn; // Physical page number
Bitfield<7> ps; // Page size
Bitfield<5> accessed;
Bitfield<2> user;
Bitfield<1> write;
Bitfield<0> present;
EndBitUnion(PageTableEntry)
// Usage
PageTableEntry pte = readMemory(addr);
if (pte.present && pte.user) {
Addr physAddr = pte.ppn << 12;
}
Data Structures
CircularQueue
A fixed-size circular buffer used in CPU pipeline implementations (e.g., reorder buffers, load/store queues). Supports random access with automatic wrap-around and iterator-based traversal.
template<typename T>
class CircularQueue
{
std::vector<T> data;
uint32_t head, tail, capacity;
public:
CircularQueue(uint32_t size);
T& front();
T& back();
void push_back(const T &val);
void pop_front();
bool empty() const;
bool full() const;
uint32_t size() const;
T& operator[](uint32_t idx); // Wrapping access
};
Saturating Counter
Used extensively in branch predictors. A counter that clamps at min/max instead of wrapping around.
class SatCounter8
{
uint8_t counter;
uint8_t maxVal;
uint8_t initialVal;
public:
SatCounter8(unsigned bits, uint8_t initial = 0);
void increment() { if(counter < maxVal) ++counter; }
void decrement() { if(counter > 0) --counter; }
operator uint8_t() const { return counter; }
void reset() { counter = initialVal; }
};
Reference Counting Pointer
RefCountingPtr provides intrusive reference counting for objects inheriting from RefCounted. Used for managing shared ownership of fault objects, requests, and packets.
class RefCounted
{
mutable int count = 0;
friend class RefCountingPtr;
public:
virtual ~RefCounted() {}
};
template<class T>
class RefCountingPtr
{
T *data;
public:
RefCountingPtr(T *p = nullptr);
RefCountingPtr(const RefCountingPtr &r);
~RefCountingPtr();
T *operator->() const { return data; }
T &operator*() const { return *data; }
operator bool() const { return data != nullptr; }
};
I/O and Configuration
INI File Parser
Parses the config.ini file generated by System and Standard Library β the control plane of gem5" href="../python/index.html">Python configuration scripts. Each section maps to a SimObject, with key-value pairs defining parameter values.
class IniFile
{
public:
bool load(const std::string &file);
bool find(const std::string §ion, const std::string &entry,
std::string &value) const;
bool sectionExists(const std::string §ion) const;
void getSectionNames(std::vector<std::string> &list) const;
bool printUnreferenced() const; // Warn about unused params
};
Formatted Output (cprintf)
Type-safe printf-style formatting that works with C++ streams. Used throughout gem5 for consistent output formatting.
// cprintf β print to stdout
cprintf("Address: %#x, Size: %d bytes\n", addr, size);
// csprintf β return as string
std::string msg = csprintf("CPU%d: PC=%#x", cpuId, pc);
// ccprintf β print to arbitrary stream
ccprintf(std::cerr, "Error at tick %d: %s\n", curTick(), err);
Key Components Reference
| Component | Header | Purpose | Category |
|---|---|---|---|
Addr, Tick | types.hh | Fundamental address and time types | Core |
AddrRange | addr_range.hh | Address range with interleaving support | Core |
BitUnion | bitunion.hh | Type-safe bit field access templates | Core |
Flags<T> | flags.hh | Typesafe flags/bitmask container | Core |
SimpleFlag | debug.hh | Individual debug trace flag | Debug |
CompoundFlag | debug.hh | Group of debug flags | Debug |
OstreamLogger | trace.hh | Trace output to streams | Debug |
CircularQueue | circular_queue.hh | Fixed-size circular buffer | Data |
SatCounter8 | sat_counter.hh | Saturating counter for predictors | Data |
RefCountingPtr | refcnt.hh | Intrusive reference counting | Data |
Trie | trie.hh | Trie for fast address lookup | Data |
IniFile | inifile.hh | Configuration file parser | Config |
cprintf | cprintf.hh | Type-safe formatted printing | I/O |
Callback | callback.hh | Callback list management | Util |
Coroutine | coroutine.hh | Cooperative coroutine support | Util |
Sub-Modules
π¦ loader
Binary file loading subsystem β reads ELF, a.out, and raw image files, constructs memory images, and manages symbol tables for simulated workloads.
6 classesπ stats
Statistics collection framework β scalar counters, vectors, distributions, histograms, and formulas for performance analysis and validation.
12+ classesCross-Module Connections
graph LR
base["base\n(types, debug, data structures)"]
sim["sim\n(SimObject, Event)"]
cpu["cpu\n(BaseCPU, pipelines)"]
mem["mem\n(packets, ports)"]
arch["arch\n(ISA decoders)"]
base -->|"Addr, Tick, Flags"| sim
base -->|"BitUnion, CircularQueue"| cpu
base -->|"AddrRange, RefCntPtr"| mem
base -->|"BitUnion, types"| arch
base -->|"stats, trace"| sim
π Narrated Walkthrough: How Debug Tracing Works
- Flag Definition β Each module declares debug flags in its SConscript (e.g.,
DebugFlag('CacheTags')). The build system generates flag registration code. - DPRINTF Macro β Source code uses
DPRINTF(CacheTags, "msg %x", val). At compile time, this checks if the flag is enabled before formatting the string. - Runtime Activation β User passes
--debug-flags=CacheTagson the command line. TheSimpleFlag::enable()method sets the tracing boolean. - Output Routing β When tracing is active,
OstreamLogger::logMessage()formats the output with timestamp, object name, and flag name, then writes to the trace file. - Compound Flags β Flags like
MemoryAccessare compound flags that enable multiple Atomic and Timing Simple CPUs β gem5 Wiki" href="../cpu_doc/simple/index.html">simple flags (e.g.,CachePort,Bus,DRAM) simultaneously.
Glossary
| Term | Definition |
|---|---|
| Addr | 64-bit unsigned integer representing a physical or virtual memory address |
| Tick | Fundamental simulation time unit, default resolution is 1 picosecond |
| BitUnion | Template system for type-safe access to individual bits and bit ranges within integers |
| DPRINTF | Debug printf macro β conditionally prints trace output when the specified flag is enabled |
| AddrRange | Represents a memory address range, possibly with interleaving for multi-channel memory |
| SatCounter | Counter that clamps at maximum/minimum instead of wrapping β used in branch predictors |
| RefCountingPtr | Smart pointer using intrusive reference counting for shared object ownership |