.. _Explicit_Config: ================================================ Explicit Configuration Format ================================================ The explicit configuration format gives full control over every module in the ChampSim hierarchy. Unlike the :ref:`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: ``name`` A unique identifier for this module instance (e.g. ``"cpu0_L1D"``). ``module`` The interface type this module implements (e.g. ``"cache"``, ``"core"``, ``"memory_controller"``, ``"channel"``, ``"prefetcher"``, ``"replacement"``, ``"branch_predictor"``, ``"btb"``, ``"vmem"``, ``"page_table_walker"``). ``model`` The 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``, ``Gi`` for 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()``. .. _Explicit_Submodule_Params: 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: .. code-block:: cpp int degree = builder.get_parameter("degree", true, 3); // returns 6 auto sets = builder.get_parameter("tracker_sets", true, 256); // returns 512 **Parameter types** — JSON values are mapped to C++ types as follows: * JSON integers → ``int64_t`` (use ``numeric_any_cast`` for ``int``, ``std::size_t``, etc.) * JSON floats → ``double`` * JSON booleans → ``bool`` * JSON strings → ``std::string`` The ``get_parameter()`` 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.