Explicit Configuration Format¶
The explicit configuration format gives full control over every module in the ChampSim hierarchy. Unlike the legacy format, which uses shorthand keys and auto-generates modules, the explicit format requires you to define every module (channels, caches, cores, DRAM, etc.) individually.
To use the explicit format, set "environment": "ENVIRONMENT" at the root of
your JSON configuration file. All modules are defined in a flat "children" array.
Basic Structure¶
An explicit configuration file has the following top-level structure:
{
"environment": "ENVIRONMENT",
"block_size": 64,
"page_size": 4096,
"num_cores": 1,
"children": [
{ ... module definitions ... }
]
}
Each entry in the "children" array defines one module instance. Every module has at
minimum three keys:
nameA unique identifier for this module instance (e.g.
"cpu0_L1D").moduleThe interface type this module implements (e.g.
"cache","core","memory_controller","channel","prefetcher","replacement","branch_predictor","btb","vmem","page_table_walker").modelThe registered model name of the implementation to use (e.g.
"DEFAULT_CACHE","DEFAULT_CORE","lru","ip_stride").
Additional keys are module-specific parameters.
Module References¶
Modules refer to each other using the @name syntax. For example, a cache connects to
its lower-level channel via:
"lower_level": "@cpu0_L1D_cpu0_L2C_channel"
This tells the simulator to look up the module named cpu0_L1D_cpu0_L2C_channel and
connect it as the lower-level channel for this cache.
References are resolved after all modules have been constructed, so definition order in
the "children" array does not matter.
Typed Parameter Objects¶
Some parameters use typed wrapper objects instead of plain values:
{"time": "250p"}A time duration. Suffixes:
p(picoseconds),n(nanoseconds),u(microseconds).{"frequency": "4G"}A frequency value. Suffixes:
G(GHz),M(MHz).{"bits": "6"}A bit-width value.
{"bytes": "8"}or{"bytes": "4Ki"}A byte size.
Ki,Mi,Gifor binary prefixes.{"bandwidth": 2}A bandwidth value (operations per cycle).
{"access_types": ["LOAD", "PREFETCH"]}A bitmask of access types.
{"null": "channel"}A null reference for an optional module connection.
{"optional_uint64": 1}An optional 64-bit unsigned integer.
Submodules (Children)¶
Modules like caches and cores can have submodules defined inline using a nested
"children" array. This is how prefetchers, replacement policies, branch predictors,
and BTBs are attached to their parent:
{
"name": "cpu0_L2C",
"module": "cache",
"model": "DEFAULT_CACHE",
"num_sets": 1024,
"num_ways": 8,
...
"children": [
{"name": "cpu0_L2C_prefetcher", "module": "prefetcher", "model": "ip_stride", "degree": 4},
{"name": "cpu0_L2C_replacement", "module": "replacement", "model": "lru"}
]
}
Custom parameters (like "degree": 4 above) are passed to the module’s constructor
via ModuleBuilder::get_parameter<T>().
Passing Parameters to Submodules¶
In the explicit format, submodule parameters are inline keys in the child’s JSON
object. Any key that is not one of the three reserved keys ("name", "module",
"model") is treated as a parameter and forwarded to the ModuleBuilder.
For example, the following gives the prefetcher two custom parameters:
{
"name": "cpu0_L2C_pref",
"module": "prefetcher",
"model": "ip_stride",
"degree": 6,
"tracker_sets": 512
}
Inside the module’s constructor, these are read as:
int degree = builder.get_parameter<int>("degree", true, 3); // returns 6
auto sets = builder.get_parameter<std::size_t>("tracker_sets", true, 256); // returns 512
Parameter types — JSON values are mapped to C++ types as follows:
JSON integers →
int64_t(usenumeric_any_castforint,std::size_t, etc.)JSON floats →
doubleJSON booleans →
boolJSON strings →
std::string
The get_parameter<T>() method handles type conversion automatically via
numeric_any_cast for all arithmetic types, so requesting int from a value stored
as int64_t works seamlessly.
Debugging parameters — use --dump to verify that your parameters were set
correctly. Values read from JSON show as (set); default values show as (default).
Channels¶
Channels connect modules together. A channel definition looks like:
{
"name": "cpu0_L1D_cpu0_L2C_channel",
"module": "channel",
"model": "DEFAULT_CHANNEL",
"rq_size": 32,
"wq_size": 32,
"pq_size": 16,
"offset_bits": {"bits": "6"},
"match_offset_bits": false
}
A Minimal Example¶
The following is a stripped-down explicit config showing the essential structure. See
champsim_config_explicit.json in the repository root for a complete example with
all default modules:
{
"environment": "ENVIRONMENT",
"block_size": 64,
"page_size": 4096,
"num_cores": 1,
"children": [
{
"name": "LLC_DRAM_channel",
"module": "channel",
"model": "DEFAULT_CHANNEL",
"rq_size": 64, "wq_size": 64, "pq_size": 64,
"offset_bits": {"bits": "6"},
"match_offset_bits": false
},
{
"name": "DRAM",
"module": "memory_controller",
"model": "DEFAULT_MEMORY_CONTROLLER",
"channels": 1,
"ul_channels": ["@LLC_DRAM_channel"],
...
},
{
"name": "LLC",
"module": "cache",
"model": "DEFAULT_CACHE",
"num_sets": 2048, "num_ways": 16,
"lower_level": "@LLC_DRAM_channel",
"children": [
{"name": "LLC_pref", "module": "prefetcher", "model": "no"},
{"name": "LLC_repl", "module": "replacement", "model": "lru"}
]
},
...
]
}
Debugging with –dump¶
Use --dump to see the fully-resolved module hierarchy that ChampSim constructs from
your config. This is useful for verifying that modules are connected correctly:
bin/champsim --config my_config.json --dump
This prints every module, its parameters, and its connections to stderr.