Configuration API

ChampSim uses an initial configuration step, written in Python, to parse the JSON configuration file into C++ files for building. The configuration mechanism can be used programmatically, as a Python module.

Parsing API

config.parse.parse_config(*configs, module_dir=None, branch_dir=None, btb_dir=None, pref_dir=None, repl_dir=None, compile_all_modules=False, verbose=False)

This is the main parsing dispatch function. Programmatic use of the configuration system should use this as an entry point.

Parameters:
  • configs – The configurations given here will be joined into a single configuration, then parsed. These configurations may be simply the result of parsing a JSON file, although the root should be a JSON object.

  • module_dir – A directory to search for all modules. The structure is assumed to follow the same as the ChampSim repository: branch direction predictors are under branch/, replacement policies under replacement/, etc.

  • branch_dir – A directory to search for branch direction predictors

  • btb_dir – A directory to search for branch target predictors

  • pref_dir – A directory to search for prefetchers

  • repl_dir – A directory to search for replacement policies

  • compile_all_modules – If true, all modules in the given directories will be compiled. If false, only the module in the configuration will be compiled.

  • verbose – Print extra verbose output

File Generation API

The file generation API contains two interfaces: a high-level interface with config.filewrite.FileWriter, and a low-level interface with config.filewrite.Fragment. Users should prefer the high-level interface where possible. The low-level interface may provide greater flexibility when needed, for example a more parallel application.

class config.filewrite.FileWriter(bindir_name=None, objdir_name=None, makedir_name=None, verbose=False)

This class maintains the state of one or more configurations to be written.

This class provides a context manager interface over a set of Fragments, and is more convenient for general use.

Parameters:
  • bindir_name – The default directory for binaries if none is given to write_files().

  • objdir_name – The default directory for object files if none is given to write_files().

__enter__()

This function forms one half of the context manager interface

__exit__(exc_type, exc_value, traceback)

This function terminates the context manager and calls finish().

finish()

Write all accumulated configurations to their files.

write_files(parsed_config, bindir_name=None, srcdir_names=None, objdir_name=None, makedir_name=None)

Accumulate the results of parsing a configuration into the File Writer. Parameters passed here will override parameters given in the constructor

Parameters:
  • parsed_config – the result of parsing a configuration file

  • bindir_name – the directory in which to place the binaries

  • srcdir_name – the directory to search for source files

  • objdir_name – the directory to place object files

static write_fragments(*fragments)

Write out a set of prepared fragments.

class config.filewrite.Fragment(fileparts=None)

Examines the given config and prepares to write the needed files.

Programs may use this class for fine-grained control of when and how files are written.

static from_config(parsed_config, bindir_name=None, srcdir_names=None, objdir_name=None, makedir_name=None, verbose=False)

Produce a sequence of Fragments from the result of parse.parse_config().

Parameters:
  • parsed_config – the result of parsing a configuration file

  • bindir_name – the directory in which to place the binaries

  • srcdir_name – the directory to search for source files

  • objdir_name – the directory to place object files

  • makedir_name – the directory to place makefiles

static join(*frags)

Merge multiple Fragments into one.

write(verbose=False)

Write the internal series of fragments to file.

Utility Functions

System operations

ChampSim’s configuration makes frequent use of sequences of dictionaries. The following functions operate on a system, a dictionary whose values are dictionaries.

config.util.iter_system(system, name, key='lower_level')

Iterate through a dictionary system.

The system is organized as a dictionary of { c[‘name’]: c } for all c. Starting at the given name, generate a path through the system, traversing by the given key. Loops are not allowed, each element may be visited at most once.

Parameters:
  • system – the system to be iterated through

  • name – the key to start at

  • key – the key that points to the next element

config.util.combine_named(*iterables)

Collect a sequence of sequences of dictionaries by their ‘name’ parameter. Earlier parameters have priority over later parameters.

config.util.upper_levels_for(system, name, key='lower_level')

List all elements of the system who have the given element name under the given key.

Parameters:
  • system – the system to be iterated through

  • name – the key to start at

  • key – the key that points to the next element

config.util.propogate_down(path, key)

Propogate the value of a key down a path of dictionaries. Later elements inherit the value from earlier elements, unless they have one themselves.

Parameters:
  • path – an iterable of dictionary values

  • key – they dictionary key to propogate

Itertools extentions

The following functions are extentions of the itertools package.

config.util.collect(iterable, key_func, join_func)

Perform the “sort->groupby” idiom on an iterable, grouping according to the join_func.

config.util.batch(it, n)

A backport of itertools.batch().

config.util.sliding(iterable, n)

A backport of itertools.sliding()

config.util.cut(iterable, n=-1)

Split an iterable into a head and a tail. The head should be completely consumed before the tail is accesssed.

Parameters:
  • iterable – An iterable

  • n – The length of the head or, if the value is negative, the length of the tail.

config.util.do_for_first(func, iterable)

Evaluate the function for the first element in the iterable and yield it. Then yield the rest of the iterable.

config.util.append_except_last(iterable, suffix)

Concatenate a suffix to each element of the iterable except the last one.

config.util.multiline(long_line, length=1, indent=0, line_end=None)

Split a long string into lines with n words

config.util.yield_from_star(gen, args, n=2)

Python generators can return values when they are finished. This adaptor yields the values from the generators and collects the returned values into a list.

Dictionary Operations

ChampSim frequently operates on dictionaries, so these functions are provided as convenience functions.

config.util.chain(*dicts)

Combine two or more dictionaries. Values that are dictionaries are merged recursively. Values that are lists are joined.

Dictionaries given earlier in the parameter list have priority.

>>> chain({ 'a': 1 }, { 'b': 2 })
{ 'a': 1, 'b': 2 }
>>> chain({ 'a': 1 }, { 'a': 2 })
{ 'a': 1 }
>>> chain({ 'd': { 'a': 1 } }, { 'd': { 'b': 2 } })
{ 'd': { 'a': 1, 'b': 2 } }
Parameters:

dicts – the sequence to be chained

config.util.subdict(whole_dict, keys, invert=False)

Extract only the given keys from a dictionary. If they keys are not present, they are not defaulted.

config.util.extend_each(lhs, rhs)

For two dictionaries whose values are lists, join the values that have the same key.

config.util.explode(value, in_key, out_key=None)

Convert a dictionary with a list member to a list with dictionary members. :param value: the dictionary to be extracted :param in_key: the key holding the list :param out_key: the key to distinguish the resulting list elements

config.parse.duplicate_to_length(elements, count)

Duplicate an array of elements, truncating if the sequence is longer than the count

>>> duplicate_to_length([1,2,3], 6)
[1,1,2,2,3,3]
>>> duplicate_to_length([1,2], 5)
[1,1,1,2,2]
>>> duplicate_to_length([1,2,3,4], 3)
[1,2,3]
Parameters:
  • elements – the sequence of elements to be duplicated

  • count – the final length

config.parse.extract_element(key, *parents)

Extract a certain key from the series of parents, returning the merged keys. Keys whose values are not dictionaries are ignored.

>>> a = { 'key': { 'internal': 1 } }
>>> b = { 'key': { 'internal': 2 } }
>>> extract_element('key', a, b)
{ 'internal': 1 }
>>> c = { 'key': { 'other': 1 } }
>>> extract_element('key', a, c)
{ 'internal': 1, 'other': 1 }
>>> d = { 'key': 'foo' }
>>> extract_element('key', a, c, d)
{ 'internal': 1, 'other': 1 }

If one or more of the parents contains a ‘name’ key, the result will contain a ‘name’ key with value ‘{parent[“name”]}_{key}’.

Parameters:
  • key – the key to extract

  • parents – the dictionaries to extract from