Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
e6a21d8
yaml config: reject user params that shadow compiler-derived PARAMS keys
caitlinross Jul 11, 2026
08a8122
tests: add compiled-tree equality check of each .conf/.yaml twin
caitlinross Jul 11, 2026
fc8b778
yaml config: opt-in dump of the fully-resolved config tree
caitlinross Jul 11, 2026
121d024
yaml config: convert unit-bearing values in model params
caitlinross Jul 11, 2026
bd633bc
yaml config: add a top-level simulation: block
caitlinross Jul 11, 2026
e4dce69
codes_mapping: apply a config-provided simulation end time
caitlinross Jul 11, 2026
a7f6e08
yaml config: compile inline workload: and jobs: blocks
caitlinross Jul 11, 2026
855d781
workloads: apply synthetic params from config with CLI precedence
caitlinross Jul 13, 2026
cf9e3d3
workloads: guard synthetic mains against unexecutable multi-job configs
caitlinross Jul 13, 2026
3b94e99
docs: document the workload: shortcut and jobs: block
caitlinross Jul 13, 2026
7534c12
tests: cover the multi-job guard with an aborting integration test
caitlinross Jul 15, 2026
c480d2c
workloads: make payload_size configurable in the synthetic and fattre…
caitlinross Jul 15, 2026
4883039
workloads: move the config helper to C++ and drop the unused present()
caitlinross Jul 15, 2026
4f3a48e
modelconfig: use std::size, note the strtod locale assumption, doxyge…
caitlinross Jul 15, 2026
a04e04b
tests: split the config-compiler unit tests into per-area files
caitlinross Jul 15, 2026
1ecde5d
docs: document the config-tree helper and expected-abort test pattern
caitlinross Jul 15, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 94 additions & 0 deletions codes/codes-workload-config.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/*
* Copyright (C) 2013 University of Chicago.
* See COPYRIGHT notice in top-level directory.
*
*/

#ifndef CODES_WORKLOAD_CONFIG_H
#define CODES_WORKLOAD_CONFIG_H

/**
* @file codes-workload-config.h
*
* Apply synthetic-workload parameters from a loaded config to a model main's
* option globals, with command-line precedence.
*
* The YAML front-end compiles a `workload:` shortcut or a single all-nodes
* `jobs:` entry into a WORKLOAD section (see the config compiler). A synthetic
* main calls the helpers below once, after configuration_load()/
* codes_mapping_setup(), passing each of the ROSS options it registered
* (`traffic`, `num_messages`, `arrival_time`, `payload_size`) together with that
* option's compiled-in default. For each knob the precedence is:
*
* command line > config (WORKLOAD section) > the model's built-in default
*
* Command-line detection follows the same pattern codes_mapping uses for the
* simulation end time: ROSS records no "was this option set" flag, so the helper
* compares the current global against the registered default. An unchanged value
* means the command line did not set it, so a configured value may take over; any
* other value is treated as a command-line override and left untouched. The edge
* case is the same as end_time's: passing a value equal to the default on the
* command line is indistinguishable from omitting it, so the config wins there.
*
* A legacy `.conf` run carries no WORKLOAD section, so every apply is a no-op and
* the model keeps its command-line/default behavior exactly as before.
*/

#ifdef __cplusplus
extern "C" {
#endif

/**
* Maps a friendly traffic-pattern name (as written in a YAML `workload:` block)
* to the value of a model main's own traffic enum. Each main supplies its own
* table because the pattern set and the enum values differ per model (only
* "uniform" is universally 1).
*/
struct codes_workload_traffic_name {
const char* name; /**< friendly name, e.g. "uniform" (NULL terminates a table) */
int value; /**< the main's traffic enum value for that pattern */
};

/**
* Abort (via tw_error) if the loaded config carries a JOBS section -- an explicit
* multi-job placement (see the config compiler). The synthetic mains generate a
* single global traffic pattern and cannot yet execute per-job placement, so
* running such a config would silently ignore it. The config still compiles and
* validates; this makes a main that cannot honor it fail loudly with guidance
* rather than misrun. A no-op for a single-workload (WORKLOAD-section) or legacy
* config. @p model_name names the model in the diagnostic.
*/
void codes_workload_config_check_unsupported_jobs(const char* model_name);

/**
* Apply an integer WORKLOAD key to @p val unless the command line already set it.
*
* @param key the WORKLOAD key name (e.g. "num_messages", "payload_size").
* @param val the option global; overwritten only when it still equals
* @p cli_default and the config provides @p key.
* @param cli_default the option's registered default (the command-line sentinel).
*/
void codes_workload_config_apply_int(const char* key, int* val, int cli_default);

/**
* Apply a floating-point WORKLOAD key to @p val unless the command line already
* set it. Semantics match codes_workload_config_apply_int (used for
* `arrival_time`, resolved to nanoseconds by the compiler).
*/
void codes_workload_config_apply_double(const char* key, double* val, double cli_default);

/**
* Apply WORKLOAD/traffic (a friendly pattern name) to @p val unless the command
* line already set it, mapping the name through @p names (a table terminated by a
* `{NULL, 0}` entry). A no-op if @p val already differs from @p cli_default or no
* traffic is configured. Aborts via tw_error if the configured name is not in
* @p names, naming the offending value.
*/
void codes_workload_config_apply_traffic(int* val, int cli_default,
const struct codes_workload_traffic_name* names);

#ifdef __cplusplus
}
#endif

#endif /* CODES_WORKLOAD_CONFIG_H */
38 changes: 37 additions & 1 deletion codes/configfile.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,18 @@
#ifndef SRC_COMMON_MODELCONFIG_CONFIGFILE_H
#define SRC_COMMON_MODELCONFIG_CONFIGFILE_H

/**
* @file configfile.h
*
* The C API for the in-memory config store: a tree of (possibly nested)
* sections holding keys and multikeys, with operations to look them up, iterate
* a section's entries, dump the store, and compare two stores structurally
* (cf_equal/cf_equal_report). Both config front-ends (legacy `.conf` and the
* YAML compiler) populate this same representation.
*/

#include <stddef.h> /* size_t */
#include <stdio.h> /* FILE (cf_equal_report) */
#include <stdlib.h>

#ifdef __cplusplus
Expand Down Expand Up @@ -94,9 +105,34 @@ struct ConfigVTable {
* */
int cf_dump(struct ConfigVTable* cf, SectionHandle h, char** err);

/* Compare two config trees: return true if equal, false if not */
/**
* Compare two config trees for equality.
*
* Equality is structural and **order-insensitive**: the two trees are equal when
* they hold the same named sections and keys with the same values, regardless of
* the order entries were written -- because the config store keys every lookup by
* name (sections case-insensitively, keys case-sensitively) and never by
* position. The value *list* of a key is compared as an ordered tuple, so a
* list-valued key such as `modelnet_order` must match value-for-value in order.
*
* @return 1 if the trees are equal, 0 otherwise.
*/
int cf_equal(struct ConfigVTable* h1, struct ConfigVTable* h2);

/**
* Like cf_equal(), but on inequality writes a human-readable description of every
* divergence -- each under its `section/key` path, saying whether an entry is
* missing from one side, is a key on one side and a section on the other, or has
* differing values -- to @p report. Pass a NULL @p report for the same result
* with no output (identical to cf_equal). Intended for tests and diagnostics, so
* a failed comparison points at the exact section/key that diverged rather than
* only reporting that the trees differ.
*
* @param report stream to write the divergence report to, or NULL for none.
* @return 1 if the trees are equal, 0 otherwise.
*/
int cf_equal_report(struct ConfigVTable* h1, struct ConfigVTable* h2, FILE* report);

static inline int cf_free(struct ConfigVTable* cf) {
if (!cf)
return 1;
Expand Down
Loading
Loading