JSON graph format
Tomii executes graphs defined in JSON. The
Python API generates this format for you
(Graph.to_json), but you can also write it by hand. The source of truth for
the format is the serde structs in tomii-core/src/json_structs.rs; this
page documents every field they define. python -m tomii --schema prints a
machine-readable schema for graph construction.
Top-level structure
{
"initializations": [ ... ],
"nodes": [ ... ],
"post_nodes": [ ... ],
"network_config": { ... }
}
| Field | Required | Description |
|---|---|---|
initializations | no (defaults to empty) | Objects computed once before execution |
nodes | yes | Computation nodes |
post_nodes | no | Nodes run in the post-computation phase |
network_config | no | Network receiver configuration |
Initializations
Each entry in initializations defines a named object that exists before any
node runs. Nodes reference these objects by name with $ref arguments, and
factor fields can reference them as counts.
| Field | Required | Type | Description |
|---|---|---|---|
name | yes | string | Unique name |
factor | no | factor | Number of instances |
args | yes | array | Typed values: {"type": ..., "value": ...} (both fields required) |
function | no | string | Plugin function that computes the object from args |
Without function, the single arg is parsed as a literal typed value.
With function, the plugin function is called at init time with args:
{
"name": "buf_size",
"args": [ { "type": "usize", "value": "100" } ]
},
{
"name": "fft_planner",
"function": "fft_planner",
"args": [ { "type": "$ref", "value": "buf_size" } ]
}
(from examples/matrix-compute/graph.json)
Two names are reserved and resolved at runtime rather than defined by you:
$index (the instance index of the consuming node) and $workers (the
worker count). Use them as $ref values, e.g.
{"type": "$ref", "value": "$index"}.
Nodes
Each entry in nodes (and post_nodes) defines a task.
| Field | Required | Type | Description |
|---|---|---|---|
name | yes | string | Unique name |
function | yes | string | Plugin function to execute |
args | yes | array | Arguments passed to the function |
factor | no | factor | Number of parallel instances |
loop | no | object | {"name": string, "factor": factor?} — loop configuration |
loop_args | no | array | Arguments for the loop |
group_size | no | factor | Instances grouped into one task |
condition | no | object | Node-level condition |
priority | no | string | "high", "normal" (default), or "low" |
use_workers | no | string | Worker index range "start-end", inclusive on both ends ("0-7" = workers 0 through 7) |
A node with factor creates that many parallel instances of the task, each
with its own instance index. See
nodes and vars.
Arguments
Each element of args is an object with a type and, depending on the
type, a value or a predecessor:
| Field | Required | Description |
|---|---|---|
type | yes | Type string (see below) |
value | no | Literal value or referenced name |
predecessor | no | Predecessor object for dependency types |
condition | no | Arg-level guard: {"operation", "value", "value_type"} |
Argument types
type | Uses | Meaning |
|---|---|---|
$ref | value | Reference to an initialization object |
$res | predecessor | Data dependency: consume a predecessor's result |
$dep | predecessor | Ordering-only dependency: wait, but do not fetch the result |
$barrier | predecessor | Wait for the selected predecessor instances to complete |
| literal type | value | Constant parsed from the string, e.g. {"type": "usize", "value": "100"} |
Literal types accepted: bool, char, i8–i128, u8–u128, usize,
isize, f32, f64, String, Complex32, Complex64, and Vec<T>
where T is any of the scalar types (the value is a comma-separated list).
Complex values accept "3.5+2.5i", "3.5,2.5", or
"{\"re\":3.5,\"im\":2.5}". The full runtime type system is described in
types.
Network input is consumed by naming the virtual node $network as a
predecessor, not by a distinct argument type:
{
"type": "$res",
"predecessor": { "name": "$network", "indexes": "0" }
}
(from the MIMO benchmark graph generated by bench/mimo-bench/tomii/build_graph.py;
the $network node exists when network_config is present)
Predecessor objects
| Field | Required | Type | Description |
|---|---|---|---|
name | yes | string | Predecessor node name (or $network) |
indexes | yes | string | Instance selection (see below) |
group_by | no | factor | Group this many predecessor completions before firing one successor |
indexes selects which predecessor instances the consuming instance depends
on, as relative instance offsets: 0 means the same index, -1 the
previous. Three syntaxes are accepted:
| Syntax | Example | Meaning |
|---|---|---|
| single | "0" | One offset; also accepts an init name that resolves to a number |
| comma list | "0,1,2" | Exact list of offsets |
| range | "0-5", "0-num_nodes" | Contiguous range of offsets |
In a range, each endpoint may be a number or an init name. A numeric end is
inclusive: "0-5" selects offsets 0 through 5. A named end resolves to the
variable's value and is exclusive: "0-num_nodes" with num_nodes = 200
selects offsets 0 through 199. This matters for barriers that fan in over
all instances of a factor node:
{
"name": "write_res",
"function": "write_to_file",
"args": [
{ "type": "$ref", "value": "result_file" },
{
"type": "$res",
"predecessor": { "name": "mat_mul", "indexes": "0-num_nodes" }
}
]
}
(from examples/matrix-compute/graph.json)
With group_by, a barrier over N predecessor instances fires the successor
once per group of group_by completions instead of once for all N. See
control flow.
Factor
A factor is either a literal integer or a string naming an initialization object that holds a number:
"factor": 200
"factor": "num_nodes"
The reserved name "$workers" resolves to the worker count. Factors appear
on nodes, initializations, loops, group_size, group_by, and several
network_config fields.
Conditions
A node-level condition gates execution: the node's function runs only if
the condition holds, evaluated by calling a plugin function.
| Field | Required | Description |
|---|---|---|
operation | yes | Comparison, e.g. "Eq", "Neq" |
value | yes | Comparison value as a string |
value_type | yes | Rust type of value, e.g. "bool" |
function | yes | Plugin function returning the value to compare |
args | yes | Arguments passed to function |
"condition": {
"operation": "Eq",
"value": "false",
"value_type": "bool",
"function": "is_pilot",
"args": [
{ "type": "$res", "predecessor": { "name": "$network", "indexes": "0" } },
{ "type": "$ref", "value": "framestats" },
{ "type": "$ref", "value": "$index" }
]
}
(from the MIMO benchmark graph generated by bench/mimo-bench/tomii/build_graph.py)
The arg-level condition (inside an argument object) is a guard with only
operation, value, and value_type — the argument is used only if the
guard holds.
network_config
Present only for graphs that ingest packets from the network. Dedicated
receiver threads (--receiver-threads) own the sockets and inject data as
the virtual $network node's results. See
network sources.
| Field | Required | Type | Description |
|---|---|---|---|
socket_type | yes | string | Only "udp" is currently supported |
num_sockets | yes | factor | Number of receive sockets |
packet_length | yes | factor | Packet size in bytes |
frame_packets | yes | factor | Packets per frame (legacy spelling stream_packets still accepted) |
buffer_depth | no (default 128) | integer | Receive buffer depth |
address | yes | string | Bind address, literal or the name of a String init object |
start_port | yes | factor | First port; socket i binds start_port + i |
extract_packet_func | yes | string | Plugin function that extracts payload from a packet |
id_function | yes | string | Plugin function that maps a packet to its frame id |
index_function | yes | object | {"function": string, "args": [...]} — maps a packet to a $network instance index |
"network_config": {
"socket_type": "udp",
"num_sockets": "antennas",
"packet_length": "packet_length",
"frame_packets": "packets_per_frame",
"buffer_depth": 2000,
"address": "server_address",
"start_port": "base_port",
"extract_packet_func": "process_packet",
"id_function": "get_frame_id"
}
(from the MIMO benchmark graph generated by bench/mimo-bench/tomii/build_graph.py;
index_function is required by
the current json_structs.rs and must be added to graphs written against
older versions)
Complete example
examples/matrix-compute/graph.json, trimmed to two nodes:
{
"initializations": [
{ "name": "buf_size", "args": [ { "type": "usize", "value": "100" } ] },
{ "name": "num_nodes", "args": [ { "type": "usize", "value": "200" } ] },
{
"name": "fft_planner",
"function": "fft_planner",
"args": [ { "type": "$ref", "value": "buf_size" } ]
}
],
"nodes": [
{
"name": "gen_vec",
"factor": "num_nodes",
"function": "generate_vector",
"args": [ { "type": "$ref", "value": "buf_size" } ]
},
{
"name": "compute_fft",
"factor": "num_nodes",
"function": "compute_fft",
"args": [
{ "type": "$ref", "value": "fft_planner" },
{
"type": "$res",
"predecessor": { "name": "gen_vec", "indexes": "0" }
}
]
}
]
}
Each of the 200 compute_fft instances depends on the gen_vec instance at
offset 0 from its own index — a 1:1 edge. More examples are collected in
examples.