API Reference
Every public name of odatix.workspace and odatix.run, what it does
and what it takes. The Python API overview is the place to
start; this page is the one to come back to.
Both modules re-export everything worth using, so nothing below needs to be imported from a submodule:
from odatix.workspace import Workspace, NotFoundError
from odatix.run import Run, RunError
Every path is resolved against the workspace, never against the current
directory, so an object obtained from a Workspace reads and writes the same
files as the commands run from inside it.
odatix.workspace
Workspace
The entry point of the configuration API. Everything a user can configure hangs off it.
| Constructor | |
|---|---|
Workspace(root=".", settings=None) |
Build a workspace on a directory, optionally with settings already in hand. |
Workspace.open(root=".", required=False) |
Open the workspace held by a directory. With required=True, raises NotAWorkspaceError when the directory holds no odatix.yml; without it, the Odatix defaults apply — which is what a directory about to be initialized looks like. |
Workspace.from_dict(settings, root=".") |
Open a workspace from settings already read, without reading the file again. |
Workspace.init(root=".", examples=False) |
Create the configuration files of a workspace and open it, as odatix init does. An existing configuration is overwritten. examples=True also copies the example designs. |
| Attribute | Type | What it is |
|---|---|---|
root |
str |
The workspace directory. |
settings_file |
str |
Path of odatix.yml. |
exists |
bool |
Whether the directory actually holds a workspace. |
settings |
dict |
The settings file, as plain values. Missing keys are not filled in: paths is what applies the defaults. |
paths |
WorkspacePaths |
Where each part of the workspace is. |
architectures |
ArchitectureCollection |
The architectures. |
simulations |
SimulationCollection |
The simulations. |
workflows |
WorkflowCollection |
The workflows. |
tools |
ToolCollection |
The EDA tools, built-in ones included. |
targets |
TargetFileCollection |
The target files, one per tool. |
jobs |
JobConfigCollection |
The run settings files, one per command. |
derived_metrics |
DerivedMetricsFile |
The derived metrics of the workspace. |
| Method | What it does |
|---|---|
reload() |
Read the settings file again, and forget the resolved paths. |
save_settings(values=None, **kwargs) |
Write odatix.yml. Only the settings actually set are written: an empty file means “use the Odatix defaults”. |
odatix_settings() |
The settings as an OdatixSettings object, for the parts of Odatix that take one. |
Workspace.SETTINGS_FILENAME is the name of the settings file (odatix.yml).
from odatix.workspace import Workspace
ws = Workspace.open() # the workspace of the current directory
ws = Workspace.open("~/designs") # another one
ws = Workspace.init("new_dir") # create it, then open it
ws.save_settings(work_path="build", result_path="out")
WorkspacePaths
Where each part of a workspace is, the Odatix defaults applied. Every attribute is a path resolved against the workspace directory.
| Group | Attributes |
|---|---|
| What is configured | arch_path, sim_path, workflow_path, tools_path, target_path |
| Where jobs run | work_path, and under it simulation_work_path, fmax_synthesis_work_path, custom_freq_synthesis_work_path, pnr_work_path, analysis_work_path, workflow_work_path |
| What runs produce | result_path, benchmark_file, derived_metrics_file |
| Run settings files | fmax_synthesis_settings_file, custom_freq_synthesis_settings_file, pnr_settings_file, simulation_settings_file, workflow_settings_file, analysis_settings_file, clean_settings_file |
| Method | What it does |
|---|---|
under_work_path(name) |
The work directory of one kind of job, e.g. under_work_path("pnr_work_path"). Those settings name a sub-directory of the work directory, so they are joined to it rather than resolved against the workspace. |
resolve(path) |
A workspace path as a path usable from anywhere. |
to_dict() |
Every path, by name. |
Entry
One directory of a workspace, holding the definition of an architecture, a
simulation, a workflow or a tool. Base class of Architecture, Simulation,
Workflow and Tool.
| Member | What it is |
|---|---|
kind |
What this entry is called to a user ("architecture", "tool", …). |
name |
Its name, which is also its directory name. |
path |
Path of its directory. |
exists |
Whether it is on disk. |
require() |
Raise NotFoundError unless it exists. Returns the entry, to be chained. |
create() |
Create its directory. Does nothing when it is already there. |
delete() |
Delete it and everything in its directory. |
rename(new_name) |
Rename it. The object keeps pointing at it under its new name. |
duplicate(new_name) |
Copy it under another name, and return the copy. |
Collection
The entries of one kind held by a workspace. Base class of
ArchitectureCollection, SimulationCollection, WorkflowCollection and
ToolCollection.
Collections behave like the mappings they are: len(c), "name" in c,
c["name"] (raising NotFoundError, which is also a KeyError), and iteration
— which yields entry objects, not names.
| Member | What it does |
|---|---|
path |
Directory holding the entries. |
kind |
What one entry is called. |
names() |
Names of the entries, in natural order. |
get(name, default=None) |
The entry, or default when there is none. |
entry(name) |
The entry of that name, whether or not it exists yet. Its settings are then the defaults, and saving it is what creates it — this is what an editor works on while a new entry is being filled in. |
exists(name) |
Whether there is such an entry. |
create(name, **kwargs) |
Create an entry and return it. Raises AlreadyExistsError when the name is taken, so a creation never silently lands on someone else’s directory. kwargs are settings applied to it. |
delete(name) |
Delete an entry. Raises when there is none. |
rename(name, new_name) |
Rename an entry, and return it. |
duplicate(name, new_name) |
Copy an entry under another name, and return the copy. |
"MyCPU" in ws.architectures
ws.architectures["MyCPU"] # NotFoundError if there is none
ws.architectures.get("MyCPU") # None instead
ws.architectures.entry("MyCPU") # whether or not it exists yet
for architecture in ws.architectures:
print(architecture.name, architecture.settings.top_level_module)
Settings
Base class of every settings object. Instances behave both as objects
(settings.rtl_path) and as mappings (settings["rtl_path"],
dict(settings.items())), so they can be handed to code expecting either.
Values are read as their declared type whatever they come as: "Yes", true
and True all mean the same thing, and "50" is stored as 50.
| Member | What it does |
|---|---|
Settings(**values) |
Build a settings object, the unset keys taking their defaults. |
specs() (classmethod) |
The declared settings, in file order, as {name: Setting}. |
spec(name) (classmethod) |
One declaration. |
from_dict(data) (classmethod) |
Build from a plain mapping, keeping unknown keys in extra. |
get(key, default=None), keys(), values(), items() |
The mapping interface. |
update(values=None, **kwargs) |
Set several settings at once. |
to_dict(include_extra=True, skip_disabled=False) |
A plain mapping. skip_disabled=True leaves out the keys whose when condition does not hold, i.e. the ones that would not be written. |
copy() |
An independent copy. |
extra |
Everything the file holds that the class does not declare. Never lost, never rewritten. |
Setting
One declared key of a settings file. Reading the declarations is how a generic editor — the graphical interface, a form generator — knows what a settings file holds.
Setting(default=None, type="any", key=None, section=None, comment=None, style=None, when=None, skip_if_empty=False, doc=None, factory=None, alt_key=None, alt_comment=None, stored=True)
| Argument | What it says |
|---|---|
default / factory |
The value used when the file does not define the key. factory for mutable defaults, so two settings objects never share one. |
type |
How the value is read and written: "any", "str", "int", "optional_int", "bool", "list", "str_list", "int_list", "dict", or a Settings subclass for a nested block. |
key |
Name of the key in the file, when it differs from the attribute name. |
section |
Title of the block this key opens, rendered as a comment above it in a generated file. |
comment |
End-of-line comment, rendered the same way. |
style |
"yesno" to write booleans as Yes/No, "flow" to write a list inline as [a, b]. |
when |
Name of another (boolean) setting this key depends on, optionally prefixed with ! to negate it. The key is only written while the condition holds, and is removed when it stops holding, so mutually exclusive settings never coexist in a file. |
alt_key / alt_comment |
Key the value is written under when when does not hold, instead of being removed. This is how a file remembers a value that is currently switched off. |
stored |
False for a setting that only exists in memory (a switch whose state is read back from which key the file uses). It is never written, but it is part of the settings. |
skip_if_empty |
Do not write the key at all when its value is empty. |
doc |
What the setting means, used by this documentation and by the command line help. |
| Method | What it does |
|---|---|
make_default() |
A fresh default value. |
coerce(value) |
Read a value of any origin (file, form field, user code) as this setting’s type. |
dump(value) |
Turn a value into what is written in the file. |
is_empty(value) |
Whether skip_if_empty would drop it. |
Saving a settings file keeps what you put in it: its comments, its key order, its quoting and every key Odatix does not know about. Only what actually changed is rewritten. A file that does not exist yet is generated with the section comments that make it readable.
Architectures
Architecture
One architecture of a workspace. Its settings are those of its main parameter
domain, so arch.settings and arch.domains.main.settings are the same
object, and arch.configs are the configurations of that main domain.
Everything of Entry, plus:
| Member | What it is |
|---|---|
settings |
ArchitectureSettings, read from file on first access. Assignable. |
settings_path |
Path of its _settings.yml. |
settings_class |
ArchitectureSettings. |
main_domain |
The ParameterDomain the architecture carries itself. |
domains |
ParameterDomainCollection — the main domain first, then the named ones. |
configs |
ConfigurationCollection of the main domain. |
reload() |
Forget the settings held in memory and read them again. |
save(regenerate=False) |
Write the settings back. regenerate=True rewrites the whole file from scratch, section comments included. |
update(values=None, **kwargs) |
Change some settings and write them back, in one call. |
parameter_domains() |
{domain: [configuration, …]} for every domain that actually uses parameters. Domains that substitute nothing, and domains without configurations, are left out: they add no axis to the sweep. |
combinations() |
Every configuration combination, written the way a job selection names it. |
count_combinations() |
How many that amounts to. |
frequencies(target="", configuration="", mode="fmax", fallback=None) |
The frequencies this architecture is run at — see resolve_frequencies. |
generate_configurations(overwrite=False, clear=False, domains=None) |
Generate the configurations of the domains set to generate them, returning {domain: [name, …]}. overwrite replaces existing ones, clear deletes them first, domains restricts which are generated. |
ArchitectureCollection
The architectures of a workspace (ws.architectures). A Collection
of Architecture.
ArchitectureSettings
Settings of an architecture — <architecture>/_settings.yml, which are also the
settings of its main parameter domain.
| Setting | Type | Default | What it says |
|---|---|---|---|
generate_rtl |
bool | False |
Whether the RTL is generated by a command instead of read from a directory. |
design_path |
str | "" |
Directory of the design sources the generation runs on. (when generate_rtl) |
design_path_whitelist |
list | [] |
What to copy from it. Everything, when empty. (when generate_rtl) |
design_path_blacklist |
list | [] |
What not to copy from it. (when generate_rtl) |
generate_command |
str | "" |
Command that generates the RTL. (when generate_rtl) |
generate_output |
str | "" |
Directory the command writes the RTL to. (when generate_rtl) |
rtl_path |
str | "" |
Directory holding the RTL of the design. (when not generate_rtl) |
top_level_file |
str | "" |
File holding the top level module. |
top_level_module |
str | "" |
Name of the top level module. |
clock_signal |
str | "" |
Name of the clock signal of the top level. |
reset_signal |
str | "" |
Name of the reset signal of the top level. |
use_parameters |
bool | False |
Whether the configurations of the main domain are substituted into a file. |
param_target_file |
str | "" |
File the parameters are written into. The top level file, when empty. |
start_delimiter |
str | "" |
Text after which the parameters are written. |
stop_delimiter |
str | "" |
Text before which the parameters are written. |
file_copy_enable |
bool | False |
Whether an extra file is copied into each work directory. |
file_copy_source |
str | "" |
File to copy. (when file_copy_enable) |
file_copy_dest |
str | "" |
Where to copy it, in the work directory. (when file_copy_enable) |
fmax_synthesis |
FrequencyBounds |
Bounds of the fmax binary search for this architecture. | |
custom_freq_synthesis |
CustomFrequencies |
Frequencies a custom frequency synthesis runs it at. | |
generate_configurations |
bool | False |
Whether the configurations of the main domain are generated from a template. |
generate_configurations_settings |
ConfigGeneration |
Template, name and variables they are generated from. |
Method: frequencies(target="", configuration="", mode="fmax", fallback=None).
Frequency settings given per target — a mapping named after the target,
holding its own fmax_synthesis and custom_freq_synthesis blocks — are not
declared here, but they are preserved: like any other key Odatix does not
know about, they stay in the file and in settings.extra.
FrequencyBounds
The frequency range an fmax binary search runs in, in MHz. A bound left unset falls back to the workspace default, so only the bounds actually set are written.
| Setting | Type | Default |
|---|---|---|
lower_bound |
optional int | None |
upper_bound |
optional int | None |
CustomFrequencies
The frequencies a custom frequency synthesis runs at, in MHz. They come as a list, as a range, or as both — a range is expanded and appended to the list.
| Setting | Type | Default | What it says |
|---|---|---|---|
frequencies |
int list (key list) |
[] |
Frequencies to synthesize at. |
list_append |
bool | False |
Whether this list adds to the one of the level above instead of replacing it. |
lower_bound |
optional int | None |
First frequency of the range. |
upper_bound |
optional int | None |
Last frequency of the range. |
step |
any | None |
Step between two frequencies. A step that is missing, zero or No switches the range off, which is how a block keeps a range it does not currently use. |
resolve_frequencies
resolve_frequencies(settings, target="", configuration="", mode="fmax", fallback=None)
The frequencies a run uses for one configuration of an architecture, once every
level of its settings file has had its say — global, then per target, then per
configuration. mode is "fmax" or "custom_freq". Returns a
ResolvedFrequencies:
| Attribute | What it is |
|---|---|
lower_bound / upper_bound |
The bounds the fmax binary search tries. |
frequencies |
The frequencies a custom frequency synthesis runs at, the range expanded. |
deprecated_bounds |
The file still spells its bounds the old way (fmax_lower_bound instead of an fmax_synthesis block). |
messages |
What the file has that a user should know about, as Message objects. |
check_bounds
check_bounds(lower_bound, upper_bound, step=0, kind="fmax synthesis")
What is wrong with a frequency range, as a list of Message — empty
when it can be run.
Parameter domains and configurations
ParameterDomain
One parameter domain of an architecture or of a workflow.
| Member | What it is |
|---|---|
name |
Its name. MAIN_DOMAIN for the main one. |
is_main |
Whether it is the domain the instance carries itself. |
label |
How it is named to a user: the instance’s name, for the main one. |
path / settings_path |
Its directory, and its _settings.yml. |
exists / require() |
Whether it is on disk. |
settings_class |
The instance’s own settings class for the main domain (an architecture’s main file holds much more than a domain’s), DomainSettings for the others. |
settings |
Read from file on first access, kept until save() or reload(). Assignable. |
use_parameters |
Whether this domain substitutes parameters into the design. A domain without a settings file substitutes nothing: there is nowhere for it to say where its parameters go. |
configs |
ConfigurationCollection of this domain. |
save(regenerate=False) |
Write the settings back, keeping the comments and the unknown keys. |
update(values=None, **kwargs) |
Change some settings and write them back. |
reload() |
Read them from file again. |
preview_configurations() |
{name: content} the generation settings would produce, writing nothing. Empty when the domain does not generate its configurations, or when its generation settings are incomplete. |
generate_configurations(overwrite=False, clear=False) |
Generate the configuration files, and return the names written. |
create() / delete() / rename(new_name) |
The main domain can be neither deleted nor renamed. |
duplicate(new_name, instance=None) |
Copy this domain, under instance when given — so a domain can be copied from one architecture to another. Copying the main domain keeps only what a domain is made of: its configuration files and the settings a domain declares. |
ParameterDomainCollection
The parameter domains of an architecture or of a workflow (arch.domains).
Iterating yields the main domain first, then the named ones in natural order.
| Member | What it does |
|---|---|
main |
The domain the instance carries itself. |
names() |
Every domain, the main one first. |
sub_names() |
Only the domains stored in a subdirectory. |
get(name, default=None) / exists(name) |
|
entry(name) |
The domain of that name, whether or not it exists yet. |
create(name, **settings) |
Create a named parameter domain, and return it. |
delete(name) / rename(name, new_name) |
|
duplicate(name, new_name, instance=None) |
|
configs() |
The configurations of every domain, as {domain: [name, …]}. |
MAIN_DOMAIN is the name Odatix gives the main domain.
DomainSettings
Settings of a named parameter domain — <instance>/<domain>/_settings.yml.
| Setting | Type | Default | What it says |
|---|---|---|---|
use_parameters |
bool | True |
Whether the configurations of this domain are substituted into a file at all. |
param_target_file |
str | "" |
File the parameters are written into, relative to the design directory. |
start_delimiter |
str | "" |
Text after which the parameters are written. |
stop_delimiter |
str | "" |
Text before which the parameters are written. |
generate_configurations |
bool | False |
Whether the configurations are generated from a template. |
generate_configurations_settings |
ConfigGeneration |
Template, name and variables they are generated from. |
Configuration
One configuration file of a parameter domain. The name never carries the .txt
extension: that is a detail of how it is stored, and every other part of Odatix
(job selections, result files, work directories) names a configuration without
it.
| Member | What it does |
|---|---|
name / filename / path |
|
exists / require() |
|
read() |
The parameters it holds, as text ("" when it does not exist). |
write(content) |
Replace its content, creating it if needed. |
content |
The same, as a property. Assignable. |
delete() / rename(new_name) / duplicate(new_name) |
ConfigurationCollection
The configurations of one parameter domain (arch.configs,
domain.configs).
| Member | What it does |
|---|---|
path |
The directory holding them. |
names() |
Configuration names, without extension, in natural order. |
filenames() |
Their file names, extension included. |
get(name, default=None) / exists(name) |
|
create(name, content="") |
Create a configuration. Raises when one of that name exists. |
write(name, content="") |
Create or replace one. |
delete(name) / rename(name, new_name) / duplicate(name, new_name) |
|
clear() |
Delete every configuration file of the domain. |
CONFIG_EXTENSION is ".txt"; configuration_names(path) lists the
configurations held by a directory.
ConfigGeneration
How the configurations of a domain are generated.
| Setting | Type | What it says |
|---|---|---|
name |
str | Name given to each generated configuration, e.g. "${width}bits". |
template |
any | Text written in each generated configuration file. |
variables |
dict | Former location of the variables, read for backward compatibility. |
The values themselves are the variables of the architecture, of the workflow or of the domain, declared at the root of its settings file rather than here.
Variables
Every settings class that can be swept — ArchitectureSettings,
WorkflowSettings and DomainSettings — carries the variables mapping and the
methods to edit it.
| Setting / Method | What it does |
|---|---|
variables |
dict — definition of each variable, by name. |
set_variable(name, type, settings, format=None, group=None) |
Declare a variable, replacing any declaration of the same name. type is "range", "list", "function"… ; settings is what that type needs, e.g. {"from": 1, "to": 8} or {"list": [1, 2, 4]}. format is applied to the values; variables sharing a group are zipped together value by value instead of being crossed. |
remove_variable(name) |
|
variable_names() |
variable_definition(name, type, settings, format=None, group=None) builds a
single {name: definition} mapping, for callers assembling a variables block
themselves.
Reading settings written before variables moved to the root of the file still
works: they are read from generate_configurations_settings, and written back at
the root the next time the file is saved.
combinations, count_combinations
combinations(domains_configs, arch_name)— expand a{domain: [configuration, …]}mapping into the list of combinations it stands for, each written the way a job selection names it (<domain>/<configuration>, the main domain being named after the architecture itself).count_combinations(domains_configs)— how many that amounts to, i.e. the size of the cross product.
architecture.configs.write("08bits", "\n parameter WIDTH = 8;\n")
width = architecture.domains.create("width", param_target_file="rtl/cpu.sv")
width.settings.start_delimiter = "#("
width.settings.stop_delimiter = ")"
width.settings.generate_configurations = True
width.settings.generate_configurations_settings.name = "${width}bits"
width.settings.generate_configurations_settings.template = "WIDTH = ${width}"
width.settings.set_variable("width", "range", {"from": 8, "to": 64, "step": 8})
width.save()
width.preview_configurations() # {name: content}, writes nothing
width.generate_configurations(overwrite=True)
Simulations
Simulation
One simulation of a workspace. Everything of Entry, plus:
| Member | What it is |
|---|---|
settings |
SimulationSettings. Assignable. |
settings_path |
Its _settings.yml. |
metrics_path / metrics |
The MetricsFile it extracts from its runs. |
save(regenerate=False) / update(values=None, **kwargs) / reload() |
SimulationCollection
The simulations of a workspace (ws.simulations). A Collection
of Simulation.
SimulationSettings
| Setting | Type | Default | What it says |
|---|---|---|---|
architectures |
list | [] |
The architectures this simulation runs on, and what it changes for each of them (param_domains, metrics_file). Read and written with odatix.workspace.sim_architectures. |
use_parameters |
bool | True |
Whether the parameters of the architecture are substituted into the testbench. |
param_target_file |
str | "" |
File they are written into. |
start_delimiter |
str | "" |
Text after which they are written. |
stop_delimiter |
str | "" |
Text before which they are written. |
override_parameters |
bool | False |
Whether this simulation substitutes parameters of its own on top of the architecture’s. |
override_param_file |
str | "" |
File holding the overriding parameters. (when override_parameters) |
override_param_target_file |
str | "" |
File they are written into. (when override_parameters) |
override_start_delimiter |
str | "" |
Text after which they are written. (when override_parameters) |
override_stop_delimiter |
str | "" |
Text before which they are written. (when override_parameters) |
invariant_domains |
any | None |
Parameter domains this simulation’s result does not depend on. A list of domain names, or a mapping giving the value to run for each. |
progress |
ProgressSettings |
How the run reports its progress to the monitor. | |
tasks |
list | [] |
What the simulation runs, as a task graph. Without it, make sim is run. |
ProgressSettings
| Setting | Type | What it says |
|---|---|---|
file |
str | Log file the progress is read from. |
regex |
str | Pattern the percentage is read with. |
Workflows
Workflow
One workflow of a workspace. A workflow is swept exactly like an architecture —
same parameter domains, same configurations, same generation — so it is an
Architecture here too; what differs is its settings and the
metrics file it carries.
| Member | What it is |
|---|---|
everything of Architecture |
domains, configs, combinations(), generate_configurations(), … |
settings |
WorkflowSettings. |
metrics_path / metrics |
The MetricsFile it extracts from its runs. |
tasks |
Its task graph, as it is stored. Assignable. |
WorkflowCollection
The workflows of a workspace (ws.workflows).
WorkflowSettings
| Setting | Type | Default | What it says |
|---|---|---|---|
sources |
SourcesSettings |
Where the files the workflow runs on come from. | |
use_parameters |
bool | True |
Whether the configurations of the main domain are substituted into a file. |
param_target_file |
str | "" |
File they are written into. |
start_delimiter |
str | "" |
Text after which they are written. |
stop_delimiter |
str | "" |
Text before which they are written. |
progress |
ProgressSettings |
How the run reports its progress to the monitor. | |
tasks |
list | [] |
What the workflow runs, as a task graph. Execution starts at the task named main. |
generate_configurations |
bool | False |
Whether the configurations of the main domain are generated from a template. |
generate_configurations_settings |
ConfigGeneration |
Template, name and variables. |
SourcesSettings
| Setting | Type | What it says |
|---|---|---|
path |
str | Directory copied into each work directory. |
whitelist |
list | What to copy from it. |
blacklist |
list | What not to copy from it. |
EDA tools
Tool
One EDA tool usable by a workspace. A tool is either defined by the workspace, or shipped with Odatix. For a built-in one, what the workspace holds is an overlay.
Everything of Entry, plus:
| Member | What it is |
|---|---|
exists |
A tool exists once it has a tool.yml; an empty directory is not one. |
is_builtin |
Whether Odatix ships a tool of this name. Whatever the workspace holds for it is then an overlay, never a tool of its own. |
has_overlay |
Whether the workspace holds something for this built-in tool. |
builtin_dir |
Directory of the built-in tool of that name, or None. |
settings_path / metrics_path |
Its tool.yml and its metrics.yml. |
settings |
ToolSettings as they apply: its own for a workspace tool, the built-in definition with the workspace overlay on top for a built-in one. These are the settings to edit. Assignable. |
builtin_settings |
What Odatix ships, or empty settings. |
effective_settings |
What actually runs. |
document |
The workspace tool.yml, as plain values. |
builtin_document |
The tool.yml Odatix ships. |
effective_document |
What actually runs, as plain values: the built-in definition with the overlay applied on top, the way Odatix resolves it at run time. What an overlay says about the built-in flows is dropped, so this is what runs, not what was asked for. |
metrics |
The ToolMetrics it reads from its reports. |
targets |
The TargetFile it runs on. |
save(as_overlay=None) |
Write the tool’s file. A workspace tool is written whole; a built-in one gets an overlay holding only the flows added to it and the settings that differ from the built-in definition. An overlay left with nothing to say is removed rather than kept empty. as_overlay forces one of the two. |
save_overlay(overrides, flows) |
Write the overlay of a built-in tool from what it overrides and the flows it adds, without going through settings. |
update(values=None, **kwargs) |
Change some settings and write them back. |
delete() |
Delete the workspace directory. A built-in tool stays available. |
reload() |
Saving a built-in tool writes only what differs from the built-in definition, so putting a setting back to what Odatix says drops it from the workspace file instead of freezing it there.
ToolCollection
The EDA tools of a workspace (ws.tools). Only the tools the workspace
defines are listed by names(): what it holds for a built-in tool is an
overlay on it, not a tool of its own.
| Member | What it does |
|---|---|
names() |
Tools defined by this workspace. |
builtin_names() |
Tools shipped with Odatix. |
all_names() |
Every tool usable by this workspace. |
exists(name) |
Whether the workspace defines it (built-in tools excluded). |
get(name, default=None) |
|
create(name, **settings) |
Create a workspace tool with a minimal tool.yml, and return it. |
import_builtin(name, new_name) |
Copy a built-in tool into the workspace under another name, so it can be edited as a tool of its own. |
ToolSettings
The settings of a tool, as its tool.yml describes them. The file spreads the
flows over three places — the default flow’s commands sit at the top level,
default_flow names it, and flows holds the rest. This object holds them as
one list, the default flow first, and puts them back where they belong on
save.
ToolSettings(label="", description="", icon="", process_group=True, report_path="", target_file="", default_metrics_file="", flows=None, format=None, extra=None)
| Member | What it is |
|---|---|
label, description, icon |
How the tool is presented. |
process_group |
Whether the jobs of this tool run in a process group of their own. |
report_path |
Where the tool writes the reports the metrics are read from. |
target_file |
Name of its target file. |
default_metrics_file |
Metrics file used when a flow names none. |
format |
A ToolFormat. |
extra |
Everything the file holds that the class does not own. |
default_flow |
The Flow that runs when no other is asked for. |
flow_names() / flow(name) |
|
add_flow(name, label="", description="", icon="", metrics_file="", is_default=False) |
Add a flow, and return it. |
remove_flow(name) / set_default_flow(name) |
|
from_dict(data) (classmethod) |
Read a tool, either as its tool.yml spells it out or as to_dict() hands it back. Both are accepted, so settings can be passed around without being pinned to the file layout. |
to_dict() |
The settings as plain values, in the canonical shape used by the editors. |
to_document(header=None) |
Build the full tool.yml of a workspace tool. |
overlay_overrides(builtin) |
Only the values that differ from a built-in definition. The flows are not part of it: the built-in ones belong to Odatix, and the added ones are written on their own. |
OVERRIDABLE_KEYS lists what an overlay may override; PLATFORMS is
("unix", "windows").
overlay_document(name, overrides, flows, header=None) builds the workspace
overlay of a built-in tool: the flows it adds and the settings it overrides,
nothing of the built-in flows.
Flow
One way of running a tool: a set of commands, per platform and job type.
Flow(name, label="", description="", icon="", metrics_file="", is_default=False, platforms=None)
| Method | What it does |
|---|---|
execution(job_type, platform="unix") |
The JobExecution of a job type. |
command(job_type, platform="unix") |
Its command, or an empty list when it is not a plain command. |
steps(job_type, platform="unix") |
Its steps, or an empty list when it is not run in steps. |
set_command(job_type, command, platform="unix") |
Make a job type run one command. |
session(job_type, platform="unix") |
How it opens the tool, as a Session. |
set_steps(job_type, steps, platform="unix", session=None) |
Make it run a sequence of resumable steps. Each step is a {"name", "command", "default"} mapping or a Step; steps declaring args are fragments of session. |
inherit(job_type, platform="unix") |
Declare nothing, so the default flow’s commands apply. |
from_dict(data) / to_dict() |
|
declares_nothing() |
True when the flow says nothing of its own — no metadata, and not a single command or step on any platform. Such a flow is what reading an empty file yields, and writing it back would only add noise. |
JOB_TYPES is ("tool_test", "fmax_synthesis", "custom_freq_synthesis", "pnr", "analysis"); STEPPED_JOB_TYPES are the ones that can be split into steps
(every one but tool_test).
JobExecution
What one flow runs for one job type on one platform. Three modes:
| Mode | Meaning |
|---|---|
"inherit" |
Nothing declared: the tool’s default flow applies. |
"command" |
A single command. |
"steps" |
A sequence of resumable steps. |
JobExecution(mode="inherit", command=None, steps=None, session=None), with
from_dict() and to_dict().
Step
One resumable step of a job type: Step(name, command=None, default=False, args=None), with from_dict() and to_dict().
A step declares either the whole command it runs — it is then a process of its
own — or the args it adds to the job type’s session, in which case
in_session is true and the steps of a run share a single process of the tool.
Session
How a job type opens the tool, once for all the steps of a run:
Session(command=None, begin=None, end=None), with declares_nothing(),
from_dict() and to_dict(). What the steps add is run between begin and
end.
ToolFormat
How the output of a tool is read: which markers make a line an error or a warning, which ones carry a tag, and what to rewrite in it.
ToolFormat(logs=None, tags=None, replace=None), with is_empty(),
from_dict(), to_dict() and to_document(only_non_empty=False).
ToolMetrics
The metrics of a tool (metrics.yml), one mapping per job type plus the common
ones. For a built-in tool, the file holds only what the workspace says about
them: the metrics it adds, the built-in ones it overrides, and — as entries
mapped to nothing — the built-in ones it removes.
| Member | What it does |
|---|---|
exists |
|
sections |
The metric definitions, by section key. Assignable. |
section(section_key) |
One section. |
set(name, definition, section_key="metrics") |
Add or replace one metric. |
remove(name, section_key="metrics") |
|
to_dict() / reload() |
|
save() |
Write the file back, keeping its comments and the keys it does not own. |
Section keys are fmax_synthesis_metrics, custom_freq_synthesis_metrics,
pnr_metrics and metrics (the common ones), listed by METRIC_SECTIONS.
tool = ws.tools["vivado"]
tool.is_builtin # True
tool.settings.flow_names() # ["standard", "power_opt"]
tool.settings.default_flow.command("fmax_synthesis")
tool.settings.label = "Vivado 2024.1"
tool.save() # writes only what differs
own = ws.tools.create("my_tool", label="My Tool")
own.settings.default_flow.set_command("fmax_synthesis", ["make fmax"])
own.save()
Targets
Target
One synthesis target of a tool. A target that is not enabled is remembered but not run.
Target(name, enabled=True, script_copy_enable=False, script_copy_source="", original_name=None), with enable(), disable(), from_dict() and
to_dict().
TargetFile
The target file of one EDA tool (ws.targets["vivado"], tool.targets).
Changes are held in memory until save(), which rewrites the target list while
leaving the rest of the file — its comments, its constraint file, its install
path — as it was.
| Member | What it does |
|---|---|
path |
Path of the target file, as Odatix resolves it: the name comes from the tool (target_file in its tool.yml), and an existing file found at the old default location next to the workspace settings is edited where it is rather than moved. |
target_path / fallback_path |
The two places it is looked up in. |
exists |
|
targets |
The targets, in file order. Assignable. |
names() |
Every target name. |
enabled_names() |
The ones the jobs of this tool actually run on. |
get(name, default=None) / exists_target(name) |
|
add(name, enabled=True, script_copy_enable=False, script_copy_source="", save=True) |
Add a target and, unless told otherwise, write the file back. |
remove(name, save=True) |
Remove a target and its per-target settings. |
rename(name, new_name, save=True) |
Rename it, carrying its per-target settings over. |
duplicate(name, new_name, save=True) |
Copy it, per-target settings included. |
enable(name, save=True) / disable(name, save=True) |
|
save() |
Write the target list back. Disabled targets are written as commented-out entries. |
settings() |
Everything the file holds, as plain values — useful to read the keys that belong to the tool rather than to the target list. |
reload() |
TargetFileCollection
The target files of a workspace, one per EDA tool (ws.targets). Supports
ws.targets["vivado"], get(tool, default=None) and names() — the tools this
workspace has a target file for.
Metrics
MetricsFile
The metrics definition file (_metrics.yml) of a workflow or of a simulation.
metrics and metadata are read on first access and written back by save(),
which keeps the comments and the keys the API does not own.
| Member | What it does |
|---|---|
exists |
|
metrics |
The metric definitions, by name. Assignable. |
metadata |
The extra result dimensions declared by the file, by name. Assignable. |
set(name, definition) / remove(name) |
|
to_dict() / reload() / save() / delete() |
DerivedMetricsFile
The derived metrics file of a workspace
(ws.derived_metrics).
| Member | What it does |
|---|---|
exists |
|
metrics |
The derived metric definitions, by name. Assignable. |
groups |
The groups they are computed over, by name. Assignable. |
set(name, definition) / remove(name) |
|
set_group(name, definition) / remove_group(name) |
|
to_dict() / reload() / save() |
Run settings files
JobConfigCollection
The run settings files of a workspace, one per command (ws.jobs). Reachable by
attribute (ws.jobs.fmax_synthesis) or by key (ws.jobs["simulation"]), and
iterable.
| Member | What it does |
|---|---|
names() |
The run modes. |
get(mode, default=None) |
JobConfig
The settings file of one run command.
| Member | What it is |
|---|---|
mode |
The run mode this file belongs to. |
label |
How this run is named to a user. |
command |
The Odatix command that reads this file (fmax, sim, …). |
settings_class |
The JobSettings subclass of this mode. |
selection_key |
The key holding what this run targets (architectures, simulations, workflows, sources). |
path / exists |
|
settings |
Read from file on first access, the way the graphical interface edits it: what it leaves out falls back on a default, and a file that does not exist yet is simply an empty configuration. Assignable. |
selection |
What this run targets, whatever the run calls it. Assignable. |
raw_selection |
What the file holds under its selection key, exactly as written. Reading it this way keeps the difference between “no entry” (an empty list) and “the key is there but says nothing” (None), which is what the run flows report as an empty run settings file. |
load() |
Read the file the way a run needs it, and keep it. The file must exist, hold a mapping, spell out every key of REQUIRED_KEYS plus the one saying what to run, and give them values of the right kind. Returns the settings; raises InvalidSettingsError when the file cannot be run from. |
save(regenerate=False) / update(values=None, **kwargs) / reload() |
REQUIRED_KEYS is ("overwrite", "ask_continue", "nb_jobs").
job_config(path, mode="fmax_synthesis") builds a run settings file worked on
by path, outside of a workspace — a temporary file a run is started from,
for instance.
JOB_MODES
The run modes, each with its label, its settings class, the workspace setting naming its file, and the command that reads it.
| Mode | Command | Settings class |
|---|---|---|
fmax_synthesis |
odatix fmax |
FmaxSynthesisJobSettings |
custom_freq_synthesis |
odatix synth |
CustomFreqSynthesisJobSettings |
pnr |
odatix pnr |
PnrJobSettings |
analysis |
odatix analyze |
AnalysisJobSettings |
simulation |
odatix sim |
SimulationJobSettings |
workflow |
odatix workflow |
WorkflowJobSettings |
The short names of the commands (fmax, synth, sim, analyze, …) are
accepted wherever a mode is: resolve_mode(mode) gives the canonical one.
JobSettings
What every run command reads, whatever it runs. Base class of all the settings below.
| Setting | Type | Default | What it says |
|---|---|---|---|
overwrite |
bool | False |
Whether results that already exist are run again. (-o) |
ask_continue |
bool | False |
Whether the run stops for a confirmation once it knows what it will do. (-y) |
exit_when_done |
bool | False |
Whether the monitor closes by itself once every job is done. (-E) |
log_size_limit |
int | 300 |
How many log lines the monitor keeps per job. (--logsize) |
nb_jobs |
any | 8 |
How many jobs run in parallel — an integer, or "auto" (the number of CPUs minus one). (-j) |
force_single_thread |
bool | False |
Whether each job is asked to use a single thread, to avoid overloading the CPU when many run in parallel. |
FmaxSynthesisJobSettings
JobSettings, plus:
| Setting | Type | What it says |
|---|---|---|
architectures |
list | The architecture configurations to synthesize. |
fmax_synthesis |
FmaxBoundsSettings |
Bounds the binary search runs in. |
FmaxBoundsSettings — override (bool, False: when false, these values
are only used where no architecture-specific bounds are defined), lower_bound
and upper_bound (optional ints, in MHz, overridden by --from / --to).
CustomFreqSynthesisJobSettings
JobSettings, plus:
| Setting | Type | What it says |
|---|---|---|
architectures |
list | The architecture configurations to synthesize. |
frequencies |
FrequenciesSettings |
The frequencies they are synthesized at. |
FrequenciesSettings — a list and a range can both be kept in the file, each
switched on or off: the one that is off is written under disabled_list /
disabled_range, so its values are remembered without being run.
| Setting | Type | Default | What it says |
|---|---|---|---|
override |
bool | False |
Whether these frequencies replace the architecture-specific ones. |
use_custom_freq_list |
bool (not stored) | True |
Whether the list is used. |
frequencies |
int list (key list) |
Odatix default | Frequencies to synthesize at, in MHz. (--at) |
use_custom_freq_range |
bool (not stored) | True |
Whether the range is used. |
range |
FrequencyRange |
The range to synthesize at. |
FrequencyRange — start (key from, default 50), stop (key to,
default 100) and step (default 10), in MHz, overridden by --from,
--to and --step.
PnrJobSettings
JobSettings, plus sources (list): the completed synthesis jobs to start
from, written
<source_type>/<source_tool>[@<source_flow>]/<target>/<architecture>/<configuration>[@<frequency>MHz]
with * accepted at every level.
AnalysisJobSettings
JobSettings, plus architectures (list) and tools (string list): the EDA
tools the RTL analysis runs with. (-t)
SimulationJobSettings
JobSettings, plus simulations: the simulations to run, each with the
architecture configurations it runs on. Held as a
{simulation: [configuration, …]} mapping, written to file as the list of
single-key mappings odatix sim expects.
simulation_selection_list(selection) builds that file value from the mapping.
WorkflowJobSettings
JobSettings, plus workflows: the workflow configurations to run, as
"<workflow>/<configuration>".
run = ws.jobs.fmax_synthesis
run.settings.architectures = ["MyCPU/08bits", "MyCPU/16bits"]
run.settings.nb_jobs = "auto"
run.settings.fmax_synthesis.lower_bound = 50
run.save()
ws.jobs.simulation.settings.simulations = {"TB_Counter": ["MyCPU/08bits"]}
ws.jobs.simulation.save()
settings = ws.jobs.fmax_synthesis.load() # checked the way a run needs it
Reading a selection
JobRequest
One entry of a run selection, read.
| Attribute | What it is |
|---|---|
text |
The entry as written, without its spaces. |
entry |
What holds the configurations, i.e. the architecture or the workflow ("counter"). |
configuration |
The configuration selected ("08bits"). An entry that selects none names the entry itself, which is how “the design with its parameters left alone” has always been written. |
path |
"<entry>/<configuration>", the configuration file without its extension. |
domains |
The other parameter domains selected, each written "<domain>/<configuration>". |
has_configuration |
Whether a configuration was actually selected. |
notes |
What reading this entry has to tell the user, as Message objects. |
work_dirname |
The directory this entry runs in, under the one named after its entry. The other domains are part of it: two runs of the same configuration with different domains are two different results. |
| Method | What it does |
|---|---|
display_name(target="", only_one_target=True) |
How this entry is named in what a run prints: the other domains between brackets, and the target too when a run has several. |
with_domains(domains) |
The same entry, targeting these parameter domains instead. |
parse_request
parse_request(text, keep_extension_note=True) — read one entry of a selection
into a JobRequest.
expand_selection
expand_selection(requests, root, messages=None) — turn a selection into the
entries it stands for, resolving its wildcards against what root holds.
messages collects what a user should be told; domain_names(root, entry)
lists the parameter domains an entry holds.
Message
Something a user should be told about. Message(level, text, hints=None), where
level is one of "error", "warning", "note" or "tip" — which is how
Odatix already names what it prints — and hints are the lines that follow it.
Errors
| Exception | Also a | Raised when |
|---|---|---|
WorkspaceError |
Exception |
Base class of every error of this API. |
NotFoundError |
KeyError |
There is no such architecture, simulation, workflow, tool, domain, target… |
AlreadyExistsError |
ValueError |
The name asked for is already taken. |
InvalidNameError |
ValueError |
The name cannot be used on disk (empty, holds a path separator…). |
NotAWorkspaceError |
ValueError |
The directory holds no Odatix settings file, and one was required. |
InvalidSettingsError |
ValueError |
A settings file cannot be used as it is: missing, not valid YAML, or holding a value of the wrong kind. |
InvalidSettingsError(message, path=None, key=None, hints=None) carries path
(the file it is wrong in), key (the key it is wrong at, when it is about one)
and hints (what a user can do about it).
InvalidSettingsError is what reading a file for a run raises. Reading one
to edit it never does: a file being written is allowed to be incomplete.
YAML helpers
odatix.workspace.yaml_io holds what the API reads and writes files with. It is
worth reaching for when a script has to touch a file the API does not model.
| Function | What it does |
|---|---|
read_yaml(path, default=None) |
Read a YAML file into plain Python values. |
read_mapping(path) |
Read a YAML file that has to hold a mapping, reporting what is wrong with it instead of falling back on a default. |
read_document(path) |
Read into a round-trip mapping, keeping comments and formatting. A missing or empty file yields an empty mapping. |
write_document(path, data, yaml_obj=None) |
Write a mapping, creating the parent directories. |
new_document(header=None) |
An empty round-trip mapping, optionally with a header comment. |
file_header(title, generator="Odatix") |
The banner Odatix puts at the top of the files it generates. |
flow_seq(values) / block_seq(values) |
A sequence rendered inline ([a, b, c]) or one item per line. |
parse_bool(value, default=False) |
Read a boolean the way the workspace files write them: YAML booleans, but also the Yes/No spelling Odatix generates. |
parse_int(value, default=None) |
Read an integer, default for anything that is not one. |
parse_int_list(value) |
Read a list of integers, accepting a real list or the free text a form field holds ("50, 100; 200"). |
yes_no(value) |
Render a boolean the way the generated files spell it. |
odatix.workspace.settings holds the rendering primitives underneath:
load_settings(settings_class, path), save_settings(settings, path, header=None, regenerate=False), render(settings, header=None) — a complete
YAML document with its section comments — and apply(settings, data) — writing
a settings object into an existing document, leaving everything it holds that
the class does not declare untouched.
odatix.run
odatix.workspace says what a workspace is configured to do; odatix.run gets
it done. Nothing here exits the interpreter and nothing asks a question: what a
run cannot do raises RunError.
Run
A run of one of the commands of a workspace.
Run(workspace, mode, options=None, reporter=None, cancel_event=None, **overrides)
| Argument | What it is |
|---|---|
workspace |
The Workspace the run belongs to. |
mode |
What to run, one of JOB_MODES. |
options |
A RunOptions: what this run does differently from what its settings file says. Built from the keyword arguments when not given. |
reporter |
A Reporter: where what the run says is collected. |
cancel_event |
A threading.Event asking the run to stop. Checking and preparing look at it between jobs and raise RunCancelled. |
**overrides |
Any RunOptions setting, e.g. overwrite=True. |
| Member | What it is |
|---|---|
config |
The JobConfig of this run. |
settings_file |
The run settings file it reads. |
work_path |
Where its jobs live. |
result_path |
Where the results go. Nothing is exported when there is none, which is what a run working outside of a workspace does. |
use_benchmark / benchmark_file |
What the results are compared against. |
path(name) |
Where one part of the workspace is, letting this run replace it: a run started from a script works on the workspace as it is configured, while the command line lets a user point one of its parts elsewhere for a single run (--archpath, --work). |
reporter |
Everything the run said along the way. |
| Step | What it does |
|---|---|
check() |
Read everything the run needs and work out what it would do with each of its jobs, without touching anything. Returns a JobPlan. Raises RunError when the run cannot be started at all, RunCancelled when it was asked to stop. |
prepare() |
Write the work directory of every job — its sources, its parameters and the script that runs it. Nothing is started. Returns the jobs, ready to be run. |
start(detach=None, session=None) |
Hand the prepared jobs over to the daemon. detach returns as soon as they are enqueued instead of attaching the monitor — which is what a run started from a script does, unless told otherwise. session is the daemon session to enqueue into. |
execute() |
Check, prepare and start, in one call. |
Each step does the ones before it when they have not been done, so start()
alone runs everything.
| Member | What it is |
|---|---|
was_checked |
Whether checking has been done and its plan is in hand. |
plan |
What the run would do. |
jobs |
The jobs it would run, as the objects its flow builds. |
checked() |
What checking produced, checking first when it has not been done. |
run_job
run_job(mode, workspace=None, **overrides) — run one of the commands of a
workspace from beginning to end. The whole of Run in one call.
from odatix.workspace import Workspace
from odatix.run import Run, RunError
run = Run(Workspace.open(), "fmax_synthesis", tool="vivado", overwrite=True)
try:
plan = run.check() # what would be run, having touched nothing
print(plan.counts()) # {'new': 12, 'cached': 3, 'error': 0, ...}
run.prepare() # every work directory written
run.start() # handed over to the daemon
except RunError as error:
print(error, error.errors())
RunOptions
What one run does differently from what its settings file says — the command line flags, by name. Built the same way as the settings of a workspace, so a value given as text is read the same way here as it is there.
What runs
| Setting | Type | Default | What it says |
|---|---|---|---|
tool |
any | "" |
EDA tool the jobs run with, or the tools an analysis runs. |
flow |
any | None |
Flow of that tool. Its default flow when unset. |
until |
any | None |
Last step of the flow to run, inclusive. |
rerun_from |
any | None |
Step to run again, with the ones after it. |
overwrite |
bool | False |
Run again what is already done. |
keep |
bool | False |
Keep previous results, by timestamping the new ones. |
resume |
bool | False |
Pick a stopped run up where it left off. |
continue_on_error |
bool | False |
Keep going when a job fails. |
check_eda_tool |
bool | True |
Check the EDA tool actually runs before using it. |
How it runs
| Setting | Type | Default | What it says |
|---|---|---|---|
nb_jobs |
any | None |
How many jobs run at once. The settings file’s own value when unset. |
force_single_thread |
bool | False |
Ask each job to use a single thread. |
log_size_limit |
optional int | None |
How many log lines the monitor keeps per job. |
noask |
bool | True |
Do not stop for the “Continue?” confirmation. |
exit_when_done |
bool | False |
Close the monitor once every job is done. |
detach |
bool | True |
Hand the jobs over to the daemon without attaching a monitor. |
session |
any | None |
Daemon session to enqueue into. |
debug |
bool | False |
Report what reading the settings files finds. |
Frequencies
| Setting | Type | Default | What it says |
|---|---|---|---|
lower_bound |
optional int | None |
Lowest frequency of an fmax search, in MHz. |
upper_bound |
optional int | None |
Highest frequency of an fmax search, in MHz. |
frequencies |
int list | [] |
Frequencies a custom frequency synthesis runs at. The settings file’s own when empty. |
Where a place & route starts from
| Setting | Type | What it says |
|---|---|---|
source_result_types |
any | Result types a place & route starts from. |
from_type |
any | Result type the sources come from. |
from_tool |
any | EDA tool they come from. |
from_flow |
any | Flow they come from. |
source_work_root |
any | Work directory the sources are read from. |
Paths
| Setting | Type | What it says |
|---|---|---|
settings_file |
any | Run settings file to read, instead of the workspace’s own. |
work_path |
any | Where the jobs run. |
result_path |
any | Where the results are written. Nothing is exported when empty. |
arch_path, sim_path, workflow_path, target_path |
any | Where the architectures, simulations, workflows and target files are. |
use_benchmark / benchmark_file |
any | Whether the results are compared against a benchmark, and which. |
custom_metrics_file |
any | Extra metrics to read from the reports. |
output_filename |
any | Name of the result file, when the run writes one. |
JobPlan
What checking found: every job, with its category. Returned by Run.check(),
and also what the command line prints its checklist from.
| Member | What it does |
|---|---|
add(name, category, **details) |
Record one job. details holds extra facts to display (tasks, target, …). |
merge(other, suffix="") |
Append the entries of another plan, optionally suffixing their names — one plan per EDA tool, one checklist for the user. |
names(category, colored=True) |
Names of the jobs of one category, in insertion order. colored=False strips the terminal color codes. |
counts() |
How many jobs per category. |
run_count() |
How many are actually going to be launched. |
sorted_entries() |
Entries by category severity, then by name. |
to_list() |
A JSON-serializable form. |
print_summary(noun="architectures") |
The CLI checklist: one section per non-empty category. |
Categories, from odatix.lib.run_report.Category:
| Category | Runs | What it means |
|---|---|---|
new |
yes | A job with no result yet. |
overwrite |
yes | Existing results, which will be overwritten. |
incomplete |
yes | Incomplete results, which will be overwritten. |
resume |
yes | Partially done: the run resumes at the first missing step. |
cached |
no | Existing results, skipped — use overwrite to run them again. |
daemon |
no | Already managed in a daemon session, skipped. |
error |
no | Invalid settings, skipped. |
JobPlanner
What a run decides to do with each of its job directories, and the plan it builds from those decisions. A run builds its own; this is the class to reach for when writing a front-end that has to reproduce the same verdicts.
JobPlanner(work_path="", work_log_path="", status_filename="", valid_status="", overwrite=False, requested_steps=None, rerun_step_index=None)
| Method | What it does |
|---|---|
classify_job(tmp_dir, subject, job_noun="synthesis") |
Decide what to do with a job directory. Returns (state, daemon_entry), the state being one of "cached", "daemon", "overwrite", "incomplete", "resume" or "new". The verdict comes from three sources, in that order of precedence: the step state of the directory, its status file, then the daemon sessions. |
steps_decision(tmp_dir) |
The step-level verdict for a flow split into steps, or None when the flow is not stepped. "cached" when the directory holds every step this run asks for, "resume" when it holds some of them, "new" otherwise. This takes precedence over the status file: a directory left by a run that stopped at an earlier step holds a perfectly valid status file, and must not be mistaken for a complete result. |
daemon_decision(tmp_dir, steps_decision=None) |
Whether a job is already handled by a daemon session ("skip"), can be re-enqueued over a failed one ("replace"), or is unknown to every session ("none"). |
refresh_daemon_jobs() |
Read what the daemon sessions are working on. |
record(name, state, daemon_entry=None) |
Add a job to the plan under the category its state calls for, returning whether it is one this run will actually work on. |
reset() |
Forget every decision taken so far. |
Reporter
Collects what a run reports, keeping it printed as it always was. Everything
Odatix reports goes through odatix.lib.printc, so a reporter listens there
rather than asking the run flows to report differently.
| Class | What it does |
|---|---|
Reporter |
The base: collects inside listening(). |
TerminalReporter |
What the command line uses: printed as it happens, and kept. |
CollectingReporter |
Kept and not printed: what a script or a server wants, so a run does not write to a standard output nobody is reading. |
| Member | What it does |
|---|---|
listening() |
A context manager collecting everything reported inside it. |
messages |
Everything reported, as (level, text) pairs. |
of_level(level) |
Only what was reported at that level. |
errors / warnings |
|
last_error() |
|
clear() |
RunError, RunCancelled
RunError(message, messages=None, code=-1)— the run cannot go on: its settings are unusable, its EDA tool is missing, there is nothing left to run.messagesholds what it reported before stopping, as(level, text)pairs, the last error being the exception’s own message;errors()gives only what was reported as an error;codeis the exit code the command line uses.RunCancelled— the run was asked to stop while it was checking or preparing its jobs.
See also
- Python API overview — the same API, told as a story.
- Configuration file reference — every file, every key.
- Commands reference — every command and its options.