The ChampSim Module System¶
ChampSim provides a runtime module system that allows you to swap implementations of key simulator components without recompilation. Each component type has an interface (a C++ abstract base class with pure virtual methods) and one or more implementations (concrete classes that override every method). ChampSim ships default implementations for all interfaces; you can replace any of them with your own.
Modules are implemented as C++ classes that inherit from an interface base class in the
champsim::modules namespace. Every module:
Inherits from one of the interface base classes listed below.
Implements every pure virtual method declared by that interface (use empty stubs
override {}for methods where no behavior is needed).Accepts a
champsim::modules::ModuleBuilderin its constructor to receive configuration parameters and access its parent module.Registers itself with a static registration line so the simulator can instantiate it by name at runtime.
Interfaces and Implementations¶
ChampSim distinguishes between interfaces and implementations:
An interface is an abstract base class that defines the contract a module must fulfill. Interfaces live in
champsim::modulesand have names likeprefetcher,replacement,branch_predictor,btb,cache_module,core_module, etc.An implementation is a concrete class that inherits from an interface and provides the actual behavior. ChampSim ships default implementations (e.g.
DEFAULT_CACHE,DEFAULT_CORE,lru,hashed_perceptron,ip_stride, etc.).
When writing a new module, you implement an existing interface. The four user-facing module interfaces are:
champsim::modules::branch_predictor— attached to a corechampsim::modules::btb— attached to a corechampsim::modules::prefetcher— attached to a cachechampsim::modules::replacement— attached to a cache
Higher-level interfaces (cache_module, core_module, memory_controller_module,
etc.) define the contracts that caches, cores, and DRAM controllers fulfill. The default
implementations DEFAULT_CACHE (CACHE class) and DEFAULT_CORE (O3_CPU class)
implement these interfaces. See Cache Model and Core Model for details.
Module Construction and ModuleBuilder¶
All modules receive a champsim::modules::ModuleBuilder in their constructor. The
ModuleBuilder provides:
Configuration parameters from the JSON config file via
get_parameter<T>().Access to the parent module via
get_parent<T>(). For example, a prefetcher can obtain a pointer to its parent cache.The module’s name and model via
get_name()andget_model().
Example constructor:
struct my_pref : champsim::modules::prefetcher {
champsim::modules::cache_module* cache_ = nullptr;
int degree = 3;
my_pref(champsim::modules::ModuleBuilder builder)
: cache_(builder.get_parent<champsim::modules::cache_module>()),
degree(builder.get_parameter<int>("degree", true, 3))
{}
};
-
struct ModuleBuilder¶
Provides configuration parameters and parent access to modules during construction.
Every module constructor receives a ModuleBuilder. Use it to:
Retrieve parameters from the JSON config via get_parameter().
Access the parent module (e.g. the cache a prefetcher is attached to) via get_parent().
Query the module’s name and model via get_name() and get_model().
Public Functions
-
template<typename T>
inline T get_parameter(std::string name, bool optional = false, T default_value = T{}) const¶ Retrieve a configuration parameter by name.
Parameters are set in the JSON configuration file. For example, if the config contains
{"model": "my_pref", "degree": 4}, thenget_parameter<int>("degree")returns 4.- Template Parameters:
T – The expected type of the parameter.
- Parameters:
name – The parameter name as it appears in the JSON config.
optional – If true, returns default_value when the parameter is absent. If false (the default), the simulator exits with an error.
default_value – The value to return when the parameter is absent and optional is true.
- Returns:
The parameter value, or default_value if absent and optional.
-
inline std::string get_model() const¶
Return the model name of this module (e.g.
"ip_stride").
-
inline std::string get_name() const¶
Return the instance name of this module (e.g.
"cpu0_L2C.ip_stride").
-
template<typename T>
inline T *get_parent() const¶ Return a typed pointer to this module’s parent.
For prefetchers and replacement policies the parent is a cache_module. For branch predictors and BTBs the parent is a core_module.
- Template Parameters:
T – The parent module type (e.g.
cache_moduleorcore_module).- Returns:
A pointer to the parent module.
Module Registration¶
After defining your module class, register it with a static registration line in the
.cc file:
#include "my_pref.h"
#include "cache.h"
champsim::modules::prefetcher::register_module<my_pref> my_pref_register("my_pref");
The string "my_pref" is the model name — this is the value you use in the JSON
configuration file to select your module:
{ "L2C": { "prefetcher": "my_pref" } }
Or in the explicit config format:
{ "name": "L2C_prefetcher", "module": "prefetcher", "model": "my_pref", "degree": 4 }
By convention, the model name matches the directory name under prefetcher/,
replacement/, branch/, or btb/.
Branch Predictors¶
A branch predictor module inherits from champsim::modules::branch_predictor and must
implement three functions.
-
struct branch_predictor : public champsim::modules::module_base<branch_predictor, core_module>¶
Interface for branch predictor modules.
Branch predictors are attached to a core (core_module). Implement the three virtual methods below and register with register_module to create a custom branch predictor.
Public Functions
-
virtual void initialize_branch_predictor() = 0¶
Called when the core is initialized. Use this to set up dynamic data structures.
-
virtual void last_branch_result(champsim::address ip, champsim::address target, bool taken, uint8_t branch_type) = 0¶
Called when a branch is resolved. All parameters are guaranteed correct.
- Parameters:
ip – The instruction pointer of the branch.
target – The correct target of the branch.
taken – True if the branch was taken.
branch_type – One of BRANCH_DIRECT_JUMP, BRANCH_INDIRECT, BRANCH_CONDITIONAL, BRANCH_DIRECT_CALL, BRANCH_INDIRECT_CALL, BRANCH_RETURN, or BRANCH_OTHER.
-
virtual bool predict_branch(champsim::address ip, champsim::address predicted_target, bool always_taken, uint8_t branch_type) = 0¶
Called when a branch direction prediction is needed.
- Parameters:
ip – The instruction pointer of the branch.
predicted_target – The predicted target from the BTB (may be incorrect).
always_taken – True if the BTB determines the branch is always taken.
branch_type – One of BRANCH_DIRECT_JUMP, BRANCH_INDIRECT, BRANCH_CONDITIONAL, BRANCH_DIRECT_CALL, BRANCH_INDIRECT_CALL, BRANCH_RETURN, or BRANCH_OTHER.
- Returns:
True if the branch is predicted taken, false otherwise.
-
virtual void initialize_branch_predictor() = 0¶
Branch Target Buffers¶
A BTB module inherits from champsim::modules::btb and must implement three functions.
-
struct btb : public champsim::modules::module_base<btb, core_module>¶
Interface for branch target buffer (BTB) modules.
BTBs are attached to a core (core_module). Implement the three virtual methods below and register with register_module to create a custom BTB.
Public Functions
-
virtual void initialize_btb() = 0¶
Called when the core is initialized. Use this to set up dynamic data structures.
-
virtual void update_btb(champsim::address ip, champsim::address predicted_target, bool taken, uint8_t branch_type) = 0¶
Called when a branch is resolved.
- Parameters:
ip – The instruction pointer of the branch.
predicted_target – The correct target of the branch.
taken – True if the branch was taken.
branch_type – One of BRANCH_DIRECT_JUMP, BRANCH_INDIRECT, BRANCH_CONDITIONAL, BRANCH_DIRECT_CALL, BRANCH_INDIRECT_CALL, BRANCH_RETURN, or BRANCH_OTHER.
-
virtual std::pair<champsim::address, bool> btb_prediction(champsim::address ip, uint8_t branch_type) = 0¶
Called when a branch target prediction is needed.
- Parameters:
ip – The instruction pointer of the branch.
branch_type – One of the branch type constants.
- Returns:
A pair of (predicted target address, always-taken flag). Return
{champsim::address{}, false}if prediction fails.
-
virtual void initialize_btb() = 0¶
Memory Prefetchers¶
A prefetcher module inherits from champsim::modules::prefetcher and must implement six
functions. The prefetch_line() helper is provided by the base class for issuing
prefetch requests into the parent cache.
-
struct prefetcher : public champsim::modules::module_base<prefetcher, cache_module>¶
Interface for memory prefetcher modules.
Prefetchers are attached to a cache (cache_module). Implement the six virtual methods below and register with register_module to create a custom prefetcher. Use prefetch_line() to issue prefetch requests.
Public Functions
-
virtual void prefetcher_initialize() = 0¶
Called when the cache is initialized. Use this to set up dynamic data structures.
-
virtual uint32_t prefetcher_cache_operate(champsim::address addr, champsim::address ip, bool cache_hit, bool useful_prefetch, access_type type, uint32_t metadata_in) = 0¶
Called when a tag check is performed in the cache.
- Parameters:
addr – The address of the packet. Includes offset bits for L1 caches; zero offset otherwise. If
virtual_prefetchis true, this is a virtual address.ip – The instruction pointer that initiated the demand. Zero for prefetches from other levels.
cache_hit – True if this tag check is a hit.
useful_prefetch – True if this tag check hit a prior prefetch.
type – The access type (LOAD, RFO, PREFETCH, WRITE, or TRANSLATION).
metadata_in – Metadata carried by the packet.
- Returns:
Metadata to store alongside the block.
-
virtual uint32_t prefetcher_cache_fill(champsim::address addr, long set, long way, bool prefetch, champsim::address evicted_addr, uint32_t metadata_in) = 0¶
Called when a miss is filled in the cache.
- Parameters:
addr – The address of the filled block (same addressing rules as prefetcher_cache_operate).
set – The cache set that the fill occurred in.
way – The cache way that the fill occurred in.
prefetch – True if the filled block was a prefetch.
evicted_addr – The address of the evicted block (default-constructed if bypass).
metadata_in – Metadata carried by the packet.
- Returns:
Metadata to store alongside the block.
-
virtual void prefetcher_cycle_operate() = 0¶
Called each cycle after all other cache operations have completed.
-
virtual void prefetcher_final_stats() = 0¶
Called at the end of the simulation. Can be used to print statistics.
-
virtual void prefetcher_branch_operate(champsim::address ip, uint8_t branch_type, champsim::address branch_target) = 0¶
Called on branch operations. Useful for instruction prefetchers.
- Parameters:
ip – The instruction pointer of the branch.
branch_type – One of BRANCH_DIRECT_JUMP, BRANCH_INDIRECT, BRANCH_CONDITIONAL, BRANCH_DIRECT_CALL, BRANCH_INDIRECT_CALL, BRANCH_RETURN, or BRANCH_OTHER.
branch_target – The target address of the branch.
-
bool prefetch_line(champsim::address pf_addr, bool fill_this_level, uint32_t prefetch_metadata) const¶
Issue a prefetch request into the parent cache.
This delegates to the parent cache’s prefetch mechanism. You do not need to store your own parent pointer to use this method.
- Parameters:
pf_addr – The address to prefetch.
fill_this_level – If true, fill this cache level; otherwise fill the next level down.
prefetch_metadata – Metadata to associate with the prefetch.
- Returns:
True if the prefetch was successfully enqueued.
-
bool prefetch_line(uint64_t pf_addr, bool fill_this_level, uint32_t prefetch_metadata) const¶
This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.
-
virtual void prefetcher_initialize() = 0¶
Replacement Policies¶
A replacement policy module inherits from champsim::modules::replacement and must
implement five functions.
-
struct replacement : public champsim::modules::module_base<replacement, cache_module>¶
Interface for cache replacement policy modules.
Replacement policies are attached to a cache (cache_module). Implement the five virtual methods below and register with register_module to create a custom replacement policy.
Public Functions
-
virtual void initialize_replacement() = 0¶
Called when the cache is initialized. Use this to set up dynamic data structures.
-
virtual long find_victim(uint32_t triggering_cpu, uint64_t instr_id, long set, const champsim::cache_block *current_set, champsim::address ip, champsim::address full_addr, access_type type) = 0¶
Called when a cache miss requires eviction.
- Parameters:
triggering_cpu – The core index that initiated this access.
instr_id – Instruction count for examining program order of requests.
set – The cache set being accessed.
current_set – A pointer to the beginning of the set being accessed.
ip – The instruction that initiated the demand. Zero for prefetches from other levels.
full_addr – The address of the packet.
type – The access type (LOAD, RFO, PREFETCH, WRITE, or TRANSLATION).
- Returns:
The way index to evict, or the total number of ways to bypass.
-
virtual void update_replacement_state(uint32_t triggering_cpu, long set, long way, champsim::address full_addr, champsim::address ip, champsim::address victim_addr, access_type type, bool hit) = 0¶
Called when a tag check completes (on both hits and misses).
- Parameters:
triggering_cpu – The core index that initiated this access.
set – The cache set.
way – The cache way.
full_addr – The address of the packet.
ip – The instruction that initiated the demand.
victim_addr – The address of the evicted block (zero on hits).
type – The access type.
hit – True if the packet hit the cache.
-
virtual void replacement_cache_fill(uint32_t triggering_cpu, long set, long way, champsim::address full_addr, champsim::address ip, champsim::address victim_addr, access_type type) = 0¶
Called when a block is filled in the cache.
This is called with the same timing as find_victim(), and is additionally called when filling an invalid way.
- Parameters:
triggering_cpu – The core index that initiated this fill.
set – The cache set.
way – The cache way.
full_addr – The address of the filled block.
ip – The instruction that initiated the demand.
victim_addr – The address of the evicted block (zero on hits).
type – The access type.
-
virtual void replacement_final_stats() = 0¶
Called at the end of the simulation. Can be used to print statistics.
-
virtual void initialize_replacement() = 0¶
Cache Module Interface¶
The cache_module interface defines the contract that caches fulfill. Prefetchers
and replacement policies can query their parent cache through this interface, for
example to read queue occupancy or cache geometry.
-
struct cache_module : public champsim::modules::module_base<cache_module, environment_module>, public champsim::operable¶
Interface for cache modules.
The default implementation is CACHE. Prefetchers and replacement policies are attached to a cache_module. Module authors can query cache geometry and queue occupancy through this interface.
Subclassed by CACHE
Public Types
-
using stats_type = cache_stats¶
The stats type returned by get_sim_stats() and get_roi_stats().
Public Functions
-
virtual stats_type get_sim_stats() const = 0¶
Return simulation-wide statistics for this cache.
-
virtual stats_type get_roi_stats() const = 0¶
Return region-of-interest statistics for this cache.
-
virtual bool is_virtual_prefetch() const = 0¶
Return true if this cache uses virtual addresses for prefetching.
-
virtual bool prefetch_line(champsim::address pf_addr, bool fill_this_level, uint32_t prefetch_metadata) = 0¶
Issue a prefetch into this cache.
- Parameters:
pf_addr – The address to prefetch.
fill_this_level – If true, fill this cache level; otherwise fill the next level.
prefetch_metadata – Metadata to associate with the prefetch.
- Returns:
True if the prefetch was successfully enqueued.
-
virtual long invalidate_entry(champsim::address inval_addr) = 0¶
Invalidate the cache line at the given address. Returns the way index, or -1.
-
virtual std::size_t get_mshr_occupancy() const = 0¶
Return the current number of occupied MSHR entries.
-
virtual std::size_t get_mshr_size() const = 0¶
Return the total MSHR capacity.
-
virtual double get_mshr_occupancy_ratio() const = 0¶
Return the MSHR occupancy as a ratio in [0, 1].
-
virtual std::vector<std::size_t> get_rq_occupancy() const = 0¶
Return per-channel read queue occupancy.
-
virtual std::vector<std::size_t> get_rq_size() const = 0¶
Return per-channel read queue capacity.
-
virtual std::vector<double> get_rq_occupancy_ratio() const = 0¶
Return per-channel read queue occupancy as a ratio in [0, 1].
-
virtual std::vector<std::size_t> get_wq_occupancy() const = 0¶
Return per-channel write queue occupancy.
-
virtual std::vector<std::size_t> get_wq_size() const = 0¶
Return per-channel write queue capacity.
-
virtual std::vector<double> get_wq_occupancy_ratio() const = 0¶
Return per-channel write queue occupancy as a ratio in [0, 1].
-
virtual std::vector<std::size_t> get_pq_occupancy() const = 0¶
Return per-channel prefetch queue occupancy.
-
virtual std::vector<std::size_t> get_pq_size() const = 0¶
Return per-channel prefetch queue capacity.
-
virtual std::vector<double> get_pq_occupancy_ratio() const = 0¶
Return per-channel prefetch queue occupancy as a ratio in [0, 1].
-
virtual std::size_t num_sets() const = 0¶
Return the number of sets in this cache.
-
virtual std::size_t num_ways() const = 0¶
Return the number of ways in this cache.
-
using stats_type = cache_stats¶
Core Module Interface¶
The core_module interface defines the contract that CPU cores fulfill. Branch
predictors and BTBs are attached to a core_module.
-
struct core_module : public champsim::modules::module_base<core_module, environment_module>, public champsim::operable¶
Interface for CPU core modules.
The default implementation is O3_CPU. Branch predictors and BTBs are attached to a core_module.
Subclassed by O3_CPU
Public Types
-
using stats_type = cpu_stats¶
The stats type returned by get_sim_stats() and get_roi_stats().
Public Functions
-
virtual uint64_t sim_instr() const = 0¶
Return the number of instructions simulated so far.
-
virtual uint8_t get_cpu_num() const = 0¶
Return this core’s CPU index.
-
virtual uint64_t sim_cycle() const = 0¶
Return the number of cycles simulated so far.
-
virtual stats_type get_sim_stats() const = 0¶
Return simulation-wide statistics for this core.
-
virtual stats_type get_roi_stats() const = 0¶
Return region-of-interest statistics for this core.
-
using stats_type = cpu_stats¶
Memory Controller Interface¶
The memory_controller_module interface defines the contract that DRAM controllers
fulfill. Stats can be retrieved per channel.
-
struct memory_controller_module : public champsim::modules::module_base<memory_controller_module, environment_module>, public champsim::operable¶
Interface for DRAM memory controller modules.
The default implementation is MEMORY_CONTROLLER. Stats can be retrieved per channel.
Subclassed by MEMORY_CONTROLLER
Public Types
-
using stats_type = dram_stats¶
The stats type returned by get_sim_stats() and get_roi_stats().
Public Functions
-
virtual std::size_t get_num_channels() const = 0¶
Return the number of DRAM channels.
-
virtual stats_type get_sim_stats(std::size_t channel_no) const = 0¶
Return simulation-wide statistics for the given channel.
-
virtual stats_type get_roi_stats(std::size_t channel_no) const = 0¶
Return region-of-interest statistics for the given channel.
-
using stats_type = dram_stats¶