Data dictionary
The data dictionary is the resolved form of a project: every data object with its owner, its users, its shape, its limits and its scaling already worked out. It is the contract between the checking front end of DDD and its output backends, and it is the only thing they share. Everything before it - loading the description files, resolving the declarations, running the consistency checks - produces a dictionary; everything after it - the c backend, the a2l backend, whatever is added next - consumes one and nothing else. A backend therefore never reaches into the loader or into the analysis, and if it needs to know something, that something is a field of the dictionary rather than a second calculation performed in a template.
That arrangement is worth having for two reasons. The first is that two backends cannot
disagree about what a project contains: the shape a c array is declared with and the
MATRIX_DIM written into the a2l are read from one field, so they cannot drift apart -
each backend only has to order the indices the way its own format wants them, c with the
last index running fastest and ASAP2 with the first. The second is that the work of
resolving a project is done once, in a place that reports findings, instead of once per
output format in a place that can only crash.
DDD publishes the dictionary rather than keeping it to itself. ddd dump writes it out as
json, and ddd schema dictionary prints its json schema, so a generator DDD does not ship
- a report, a database importer, a header for a language DDD knows nothing about - can
consume a checked project without importing python and without depending on any of the
implementation:
ddd dump examples/demo/demo.ddd.json > dictionary.json
ddd schema dictionary > dictionary.schema.json
$ ddd dump examples/demo/demo.ddd.json
{
"format": 9,
"name": "DemoDevice",
"description": "Demonstration project showing every kind of data object",
"source": "demo.ddd.json",
"components": [
{
"name": "Controller",
"description": "Consumes the raw values and produces the derived ones",
"source": "controller.ddd.json",
"declarations": [
{
"name": "ValueA",
"scope": "input",
"condition": null
},
...
ddd dump is the one command whose standard output is the payload, so its findings go
to standard error and the redirection above works whether or not the project has any. A
script writes the file with -o dictionary.json instead: the same text, as the same bytes
on every platform, and a file whose content would not change is left untouched, so that what
reads it does not run again for nothing - a redirection leaves the bytes to the shell, and
empties the file before the tool has even started. A run that generates anyway writes it
beside the artefacts with ddd generate --dictionary, in the same write as them, which is
what the cmake integration does. The
same file is what comparing two deliveries needs: archive the
dictionary of a delivery next to its binary, and a later ddd compare can answer whether
the next delivery may replace it, long after the sources of the first one have moved on.
What is already resolved
The value of the dictionary is what a backend no longer has to work out. By the time a backend sees it:
The limits are filled in. limits is never absent. A declaration that states its
physical limits keeps them; one that does not gets the full range its datatype and
conversion imply, computed once. A backend writing LOWER_LIMIT and UPPER_LIMIT into
an a2l therefore never has to decide what a missing limit means, and cannot decide it
differently from anybody else.
The shape is a tuple of dimensions, empty for a scalar, and it is complete even when the
description file never stated it. A measurement or a value block declares its dimensions
and an axis its size, but a curve and a map deliberately do not repeat the size of their
tables: they name the axes they are interpolated over, and the shape follows from those. The
demo project declares CurveA like this - no limits, no dimensions:
{
"scope": "local",
"definition": {
"kind": "curve",
"name": "CurveA",
"id": "6ywadt4ekhj3",
"description": "Calibratable curve over AxisA",
"datatype": "uint16",
"unit": "ms",
"conversion": { "factor": 0.01 },
"axis": "AxisA",
"init": [1200, 900, 800, 750, 700, 650],
"volatile": false
}
}
and the dictionary hands the backends this:
{
"name": "CurveA",
"id": "6ywadt4ekhj3",
"extensions": {},
"kind": "curve",
"datatype": "uint16",
"description": "Calibratable curve over AxisA",
"unit": "ms",
"conversion": { "kind": "linear", "factor": 0.01, "offset": 0.0 },
"limits": { "min": 0.0, "max": 655.35 },
"shape": [6],
"dimensions": [6],
"init": [1200, 900, 800, 750, 700, 650],
"section": null,
"raster": null,
"point_counts": "none",
"volatile": false,
"condition": null,
"references": { "axis": "AxisA" },
"owner": "Controller",
"consumers": [],
"local": true,
"a2l": { "export": true, "format": null, "display_identifier": null }
}
The six points come from AxisA, and the limits from the full uint16 range through
the linear conversion: 65535 raw counts of 0.01 ms are 655.35 ms. dimensions is the same
shape again, spelled the way the project spells it: here the number, and for an array
dimensioned by a declared constant the constant’s name, so a
generator can declare the array by the name while sizing it by the number. The kind of the
conversion, left out of the description because a block carrying a factor can only be
linear, is spelled out. Both blocks above are folded onto fewer lines than the files
themselves use; the values are exactly the ones in examples/demo and in the dump of it.
The owner and the consumers are worked out. owner names the component whose
declaration was taken as the authoritative one, consumers lists the components that
declared the object as an input, and local says whether the owner keeps it to itself.
This is what lets the c backend group the definitions by owning component and emit a header
per component that contains that component’s interface and nothing else, and what lets the
a2l backend build one GROUP per component with something to export - without either of
them knowing anything
about scopes, ownership rules or how a disagreement between two components is settled.
Where components disagreed, the producing component’s declaration is the one that
survives: the analysis reports the disagreement against the deviating consumer and puts
the producer’s definition into the dictionary, so a backend never sees two versions of one
object.
The condition is the producing declaration’s. A variable that only exists when a
preprocessor symbol is defined carries that expression here, which is what the c backend
wraps in #if and what the a2l backend notes in a comment, a2l having no notion of
conditional compilation.
The objects are sorted by name and the enumerations are collected, de-duplicated and sorted by name as well, so that a generated file depends on the content of a project and not on the order in which its files happened to be read. Together with the include patterns being expanded in sorted order and the generated files carrying no time stamp, that is what makes a regeneration without an input change produce a byte identical result - and therefore what lets a build system skip the recompilation. The components, by contrast, keep the order in which the project included them, and the declarations of a component keep the order the author wrote them in, because that order is information: it is how the interface of a component reads in its own file, and it is how it reads in its generated header.
The plugin blocks are resolved too. Every object, every structured instance and the
dictionary itself carry extensions, validated and dumped back with each plugin’s own
defaults filled in, and the dictionary names the plugins in play under plugins. That is
what keeps a plugin’s questions answerable from the dictionary alone, long after the project
that named the plugin has moved on: the archived dump is what ddd compare --plugin reads
back a plugin’s comparison rules against, and what ddd generate <name> hands to a
plugin’s own backend. See Plugins for what a plugin does with them.
Note
owner is null for an input that no component produces, which reaches the
dictionary whenever missing-producer is relaxed - a component checked or dumped on its
own, or an inconsistent project generated with ddd generate --force; the c backend
files such an object under <unresolved>. Every other field is always present.
Point counts ahead of a table
Some firmware stores the number of axis points inside every curve, map and axis, ahead of
its data, in the object’s own type - a 16 by 16 uint32 map begins with its two counts:
8093841c 10000000 10000000 00000000 ... a 16 x 16 map of uint32
nx = 16 ny = 16 then the 256 values
point_counts says whether an object is stored that way. It takes "none", the
ordinary layout, or "leading". It may be stated once, on the project, as the default for
every curve, map and axis; a component may state it again to override that default for the
curves, maps and axes it defines - the producing declaration, exactly as a component’s
raster does. A reader of the object never influences it. A
component read on its own - a standalone ddd dump, list or generate of a
component file - has no project to take a default from, so its tables resolve to
"none" unless the component states the key itself.
A table resolved to "leading" is declared flat, counts first, in its own datatype:
const uint32_t M[2 + (16) * (16)] = { 16U, 16U, ... };
and the a2l describes it with a record layout of its own, the counts ahead of the values it governs:
/begin RECORD_LAYOUT RL_MAP_COUNTED_ULONG
NO_AXIS_PTS_X 1 ULONG
NO_AXIS_PTS_Y 2 ULONG
FNC_VALUES 3 ULONG ROW_DIR DIRECT
/end RECORD_LAYOUT
Two consistency checks come with the setting:
point-counts-unrepresentable refuses a table whose datatype cannot hold one of its
counts, and point-counts-mismatch warns when a curve or a map resolves to one convention
and one of its axes to the other. From format 9 on, every resolved object carries the
point_counts it was given, "none" for every kind but a curve, a map or an axis.
The format field
A dumped dictionary is meant to be archived next to a delivery and read back by a later
version of DDD, possibly years later. The format field stamps the shape of the document
- currently 9 - and changes only when that shape changes, not with every release of the
tool.
It exists so that a later reader can say this file is newer than I understand rather than misread it. DDD accepts a dictionary whose format is the one it knows or older, and refuses one that is newer:
$ ddd compare baseline.json demo.ddd.json
baseline.json#format: error[schema]: in the baseline: this dictionary is in format 10, and this DDD understands up to 9; use a newer DDD to read it
1 error
Refusing is the only safe answer: reading the file anyway would compare a delivery against fields this version does not know about, and quietly report every one of them as unchanged - which is precisely the verdict that would let a broken delivery out of the door. The rule is one-directional on purpose, so that a new DDD keeps reading the dictionaries archived by older ones.
That is also why a field of the dictionary may keep a default the description files no longer
allow. volatile has to be stated by every definition an author writes, but the dictionary
still defaults it to false, so a dictionary dumped by an older DDD still reads back and can
still be compared against, instead of a required field turning every archived document into a
file this version refuses.
Warning
A dictionary is a snapshot of a project, not a description of it. ddd generate and
ddd check read description files; the dictionary is what ddd compare reads back
and what a foreign generator consumes. Treat it as an artefact of a build - archive it,
do not edit it, and do not maintain a project in it.
Consuming it from another tool
The document is plain json, described by a published schema, and it round-trips: a
dictionary written by ddd dump and read back is the same dictionary, and a backend fed
the reloaded document produces byte identical output. Both properties are asserted by the
test suite (tests/test_backends.py), because they are the whole point of publishing the
contract - a third party generating from a dumped dictionary has to get what DDD would have
got.
One field asks something of its reader: init is carried as the declaration wrote it, so a
list is nested one level per dimension and a scalar written for an array is still a scalar -
"init": 0 beside "shape": [4] means four zeros. It is not expanded here because
expanding it would write one literal per element for a value the description states once, and
an array of ten thousand elements would carry ten thousand of them. A generator broadcasts the
scalar over shape, which is what the c backend does before rendering the initialiser.
ddd schema dictionary prints the whole thing, definitions included; its top level, which
is where a consumer starts, is this (the per field documentation the schema also carries is
elided here for space):
{
"additionalProperties": false,
"description": "The resolved data of one project.",
"properties": {
"format": {
"default": 9,
"minimum": 1,
"title": "Format",
"type": "integer"
},
"name": {
"maxLength": 128,
"minLength": 1,
"pattern": "^[A-Za-z_][A-Za-z0-9_]*$",
"title": "Name",
"type": "string"
},
"description": {
"default": "",
"title": "Description",
"type": "string"
},
"source": {
"default": "",
"title": "Source",
"type": "string"
},
"components": {
"default": [],
"items": {
"$ref": "#/$defs/ResolvedComponent"
},
"title": "Components",
"type": "array"
},
"objects": {
"default": [],
"items": {
"$ref": "#/$defs/ResolvedObject"
},
"title": "Objects",
"type": "array"
},
"enums": {
"default": [],
"items": {
"$ref": "#/$defs/EnumConversion"
},
"title": "Enums",
"type": "array"
},
"constants": {
"default": [],
"items": {
"$ref": "#/$defs/ConstantDeclaration"
},
"title": "Constants",
"type": "array"
},
"rasters": {
"default": [],
"items": {
"$ref": "#/$defs/ResolvedRaster"
},
"title": "Rasters",
"type": "array"
},
"types": {
"default": [],
"items": {
"$ref": "#/$defs/ResolvedStruct"
},
"title": "Types",
"type": "array"
},
"instances": {
"default": [],
"items": {
"$ref": "#/$defs/ResolvedInstance"
},
"title": "Instances",
"type": "array"
},
"leaves": {
"default": [],
"items": {
"$ref": "#/$defs/ResolvedLeaf"
},
"title": "Leaves",
"type": "array"
},
"plugins": {
"default": [],
"items": {
"type": "string"
},
"title": "Plugins",
"type": "array"
},
"extensions": {
"additionalProperties": {
"additionalProperties": true,
"type": "object"
},
"title": "Extensions",
"type": "object"
}
},
"required": [
"name"
],
"title": "DDD data dictionary",
"type": "object"
}
additionalProperties is false here, as it is on every object DDD describes - the one
open door is extensions, whose blocks belong to the plugins that own them - so a consumer
validating against the schema finds a key it was not expecting instead of skipping it.
enums carries the distinct enumerations the objects use, so a consumer that wants to
emit a type per enumeration - which is what the c backend offers its templates as
model.enums - does not have to walk every object and de-duplicate them itself.
constants records the declared constants whole - name,
value and description - so a dimension an object spells by name stays resolvable from the
document alone. rasters records the
declared measurement rasters the same way - name, event
channel, period and description - so that a generator can write the XCP event list itself
instead of reconstructing it from the events the objects happen to name. The
conversions themselves are the same models the description files use, and they are documented
with the other data contracts. types, instances and
leaves describe the structured variables: the declared structures, the variables
instantiating one, and the member objects each instance flattens into.
Reference
The dictionary is a pydantic model like every other contract, which means it is validated when the analysis hands it over: a bug in the front end surfaces at that boundary rather than half way through a jinja template.
- pydantic model DataDictionary[source]
The resolved data of one project.
What
ddd dumpwrites and every backend reads. Unlike the description files, this one is produced rather than authored: every derived property is already worked out, so a consumer never has to repeat the resolution and two consumers can never disagree about it.![digraph "Entity Relationship Diagram created by erdantic" {
graph [fontcolor=gray66,
fontname="Times New Roman,Times,Liberation Serif,serif",
fontsize=9,
nodesep=0.5,
rankdir=LR,
ranksep=1.5
];
node [fontname="Times New Roman,Times,Liberation Serif,serif",
fontsize=14,
label="\N",
shape=plain
];
edge [dir=both];
"ddd.ir.ComponentDeclaration" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>ComponentDeclaration</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>scope</td><td port="scope">Scope</td></tr><tr><td>condition</td><td port="condition">str | None</td></tr></table>>,
tooltip="ddd.ir.ComponentDeclaration

One entry of a component interface, in the order the component declared it.

A reference \
to an object rather than the object itself: the definition lives once, under
``objects``, and is the one the producing component \
gave. Two components declaring the
same name appear here twice and in ``objects`` once.
"];
"ddd.ir.DataDictionary" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>DataDictionary</b></td></tr><tr><td>format</td><td port="format">int</td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>description</td><td port="description">str</td></tr><tr><td>source</td><td port="source">str</td></tr><tr><td>components</td><td port="components">tuple[ResolvedComponent, ...]</td></tr><tr><td>objects</td><td port="objects">tuple[ResolvedObject, ...]</td></tr><tr><td>enums</td><td port="enums">tuple[EnumConversion, ...]</td></tr><tr><td>constants</td><td port="constants">tuple[ConstantDeclaration, ...]</td></tr><tr><td>rasters</td><td port="rasters">tuple[ResolvedRaster, ...]</td></tr><tr><td>types</td><td port="types">tuple[ResolvedStruct, ...]</td></tr><tr><td>instances</td><td port="instances">tuple[ResolvedInstance, ...]</td></tr><tr><td>leaves</td><td port="leaves">tuple[ResolvedLeaf, ...]</td></tr><tr><td>plugins</td><td port="plugins">tuple[str, ...]</td></tr><tr><td>extensions</td><td port="extensions">dict[str, dict[str, Any]]</td></tr></table>>,
tooltip="ddd.ir.DataDictionary

The resolved data of one project.

What ``ddd dump`` writes and every backend reads. Unlike \
the description files, this one
is produced rather than authored: every derived property is already worked out, so a
consumer \
never has to repeat the resolution and two consumers can never disagree about it.
"];
"ddd.ir.ResolvedComponent" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>ResolvedComponent</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>description</td><td port="description">str</td></tr><tr><td>source</td><td port="source">str</td></tr><tr><td>declarations</td><td port="declarations">tuple[ComponentDeclaration, ...]</td></tr></table>>,
tooltip="ddd.ir.ResolvedComponent

A component and the objects it declares.
"];
"ddd.ir.DataDictionary":components:e -> "ddd.ir.ResolvedComponent":_root:w [arrowhead=crownone,
arrowtail=nonenone];
"ddd.ir.ResolvedInstance" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>ResolvedInstance</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>id</td><td port="id">str | None</td></tr><tr><td>extensions</td><td port="extensions">dict[str, dict[str, Any]]</td></tr><tr><td>type</td><td port="type">str</td></tr><tr><td>kind</td><td port="kind">ObjectKind</td></tr><tr><td>description</td><td port="description">str</td></tr><tr><td>shape</td><td port="shape">tuple[int, ...]</td></tr><tr><td>dimensions</td><td port="dimensions">tuple[Union[int, str], ...]</td></tr><tr><td>volatile</td><td port="volatile">bool</td></tr><tr><td>section</td><td port="section">str | None</td></tr><tr><td>raster</td><td port="raster">str | None</td></tr><tr><td>condition</td><td port="condition">str | None</td></tr><tr><td>owner</td><td port="owner">str | None</td></tr><tr><td>consumers</td><td port="consumers">tuple[str, ...]</td></tr><tr><td>local</td><td port="local">bool</td></tr><tr><td>a2l</td><td port="a2l">A2lObjectOptions</td></tr></table>>,
tooltip="ddd.ir.ResolvedInstance

One variable whose datatype is a structure.

Kept apart from :class:`ResolvedObject` rather \
than widening it: an object with no datatype
and no limits would turn every reader of those two fields into a branch, and they \
are read
unconditionally in a dozen places on the strength of always being there.
"];
"ddd.ir.DataDictionary":instances:e -> "ddd.ir.ResolvedInstance":_root:w [arrowhead=crownone,
arrowtail=nonenone];
"ddd.ir.ResolvedLeaf" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>ResolvedLeaf</b></td></tr><tr><td>path</td><td port="path">str</td></tr><tr><td>instance</td><td port="instance">str</td></tr><tr><td>instance_id</td><td port="instance_id">str | None</td></tr><tr><td>kind</td><td port="kind">ObjectKind</td></tr><tr><td>datatype</td><td port="datatype">Datatype</td></tr><tr><td>description</td><td port="description">str</td></tr><tr><td>unit</td><td port="unit">str</td></tr><tr><td>conversion</td><td port="conversion">IdentityConversion | LinearConversion | EnumConversion | StringConversion</td></tr><tr><td>limits</td><td port="limits">Limits</td></tr><tr><td>shape</td><td port="shape">tuple[int, ...]</td></tr><tr><td>dimensions</td><td port="dimensions">tuple[Union[int, str], ...]</td></tr><tr><td>bits</td><td port="bits">int | None</td></tr><tr><td>volatile</td><td port="volatile">bool</td></tr><tr><td>section</td><td port="section">str | None</td></tr><tr><td>raster</td><td port="raster">str | None</td></tr><tr><td>condition</td><td port="condition">str | None</td></tr><tr><td>owner</td><td port="owner">str | None</td></tr><tr><td>consumers</td><td port="consumers">tuple[str, ...]</td></tr><tr><td>local</td><td port="local">bool</td></tr><tr><td>a2l</td><td port="a2l">A2lObjectOptions</td></tr></table>>,
tooltip="ddd.ir.ResolvedLeaf

One member of one structured variable, at the end of one access path.

The flattening. A structure \
reaches the a2l as an object per member rather than as an a2l
structure, so this is the form that backend consumes - an ordinary \
object in every respect
but its name, which is a path rather than an identifier.
"];
"ddd.ir.DataDictionary":leaves:e -> "ddd.ir.ResolvedLeaf":_root:w [arrowhead=crownone,
arrowtail=nonenone];
"ddd.ir.ResolvedObject" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>ResolvedObject</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>id</td><td port="id">str | None</td></tr><tr><td>extensions</td><td port="extensions">dict[str, dict[str, Any]]</td></tr><tr><td>kind</td><td port="kind">ObjectKind</td></tr><tr><td>datatype</td><td port="datatype">Datatype</td></tr><tr><td>description</td><td port="description">str</td></tr><tr><td>unit</td><td port="unit">str</td></tr><tr><td>conversion</td><td port="conversion">IdentityConversion | LinearConversion | EnumConversion | StringConversion</td></tr><tr><td>limits</td><td port="limits">Limits</td></tr><tr><td>shape</td><td port="shape">tuple[int, ...]</td></tr><tr><td>dimensions</td><td port="dimensions">tuple[Union[int, str], ...]</td></tr><tr><td>init</td><td port="init">InitValue | None</td></tr><tr><td>section</td><td port="section">str | None</td></tr><tr><td>raster</td><td port="raster">str | None</td></tr><tr><td>point_counts</td><td port="point_counts">PointCounts</td></tr><tr><td>volatile</td><td port="volatile">bool</td></tr><tr><td>condition</td><td port="condition">str | None</td></tr><tr><td>references</td><td port="references">dict[str, str]</td></tr><tr><td>owner</td><td port="owner">str | None</td></tr><tr><td>consumers</td><td port="consumers">tuple[str, ...]</td></tr><tr><td>local</td><td port="local">bool</td></tr><tr><td>a2l</td><td port="a2l">A2lObjectOptions</td></tr></table>>,
tooltip="ddd.ir.ResolvedObject

One data object, with every derived property already worked out.
"];
"ddd.ir.DataDictionary":objects:e -> "ddd.ir.ResolvedObject":_root:w [arrowhead=crownone,
arrowtail=nonenone];
"ddd.ir.ResolvedRaster" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>ResolvedRaster</b></td></tr><tr><td>raster</td><td port="raster">str</td></tr><tr><td>event</td><td port="event">int</td></tr><tr><td>cycle</td><td port="cycle">str | None</td></tr><tr><td>cycle_ns</td><td port="cycle_ns">int | None</td></tr><tr><td>description</td><td port="description">str</td></tr></table>>,
tooltip="ddd.ir.ResolvedRaster

One declared daq event, as the dictionary publishes it.
"];
"ddd.ir.DataDictionary":rasters:e -> "ddd.ir.ResolvedRaster":_root:w [arrowhead=crownone,
arrowtail=nonenone];
"ddd.ir.ResolvedStruct" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>ResolvedStruct</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>description</td><td port="description">str</td></tr><tr><td>members</td><td port="members">tuple[ResolvedMember, ...]</td></tr></table>>,
tooltip="ddd.ir.ResolvedStruct

One structure, in an order a c file can be written out in.

The order of :attr:`DataDictionary.types` \
matters and is not alphabetical: a structure
appears after every structure it nests, because a c compiler needs the nested one \
to be
complete first. The members keep the order the author wrote them in, which is the order the
compiler lays them out.&#\
xA;"];
"ddd.ir.DataDictionary":types:e -> "ddd.ir.ResolvedStruct":_root:w [arrowhead=crownone,
arrowtail=nonenone];
"ddd.models.constants.ConstantDeclaration" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>ConstantDeclaration</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>value</td><td port="value">Union[int, float]</td></tr><tr><td>description</td><td port="description">str</td></tr></table>>,
tooltip="ddd.models.constants.ConstantDeclaration

One named number, declared once and named wherever the project needs it.
"];
"ddd.ir.DataDictionary":constants:e -> "ddd.models.constants.ConstantDeclaration":_root:w [arrowhead=crownone,
arrowtail=nonenone];
"ddd.models.conversion.EnumConversion" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>EnumConversion</b></td></tr><tr><td>kind</td><td port="kind">Literal['enum']</td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>enumerators</td><td port="enumerators">tuple[Enumerator, ...]</td></tr></table>>,
tooltip="ddd.models.conversion.EnumConversion

A verbal conversion table; the raw value *is* the physical value.

Accepts \
both the explicit form::

 {\"kind\": \"enum\", \"name\": \"StateA\",
 \"enumerators\": [{\"name\": \"STATE_OFF\", \"value\": \
0}]}

and the mapping shorthand::

 {\"kind\": \"enum\", \"name\": \"StateA\", \"enumerators\": {\"STATE_OFF\": 0}}
"];
"ddd.ir.DataDictionary":enums:e -> "ddd.models.conversion.EnumConversion":_root:w [arrowhead=crownone,
arrowtail=nonenone];
"ddd.ir.ResolvedComponent":declarations:e -> "ddd.ir.ComponentDeclaration":_root:w [arrowhead=crownone,
arrowtail=nonenone];
"ddd.models.objects.A2lObjectOptions" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>A2lObjectOptions</b></td></tr><tr><td>export</td><td port="export">bool | None</td></tr><tr><td>format</td><td port="format">Optional[str]</td></tr><tr><td>display_identifier</td><td port="display_identifier">Optional[str]</td></tr></table>>,
tooltip="ddd.models.objects.A2lObjectOptions

What a declaration asks of the a2l backend. Only that backend interprets it.
&#\
xA;Nothing here changes the generated c or the meaning of the object; a project that
generates no a2l can leave the whole block \
out.
"];
"ddd.ir.ResolvedInstance":a2l:e -> "ddd.models.objects.A2lObjectOptions":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.ir.ResolvedLeaf":conversion:e -> "ddd.models.conversion.EnumConversion":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.conversion.IdentityConversion" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>IdentityConversion</b></td></tr><tr><td>kind</td><td port="kind">Literal['identity']</td></tr></table>>,
tooltip="ddd.models.conversion.IdentityConversion

``physical == raw``; stated like any other conversion, ``{}`` its shortest spelling.&#\
xA;
Not a default: a definition naming storage by ``datatype`` states this one where raw and
physical are the same number, \
so that the claim is written down rather than left to
silence.
"];
"ddd.ir.ResolvedLeaf":conversion:e -> "ddd.models.conversion.IdentityConversion":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.conversion.LinearConversion" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>LinearConversion</b></td></tr><tr><td>kind</td><td port="kind">Literal['linear']</td></tr><tr><td>factor</td><td port="factor">float</td></tr><tr><td>offset</td><td port="offset">float</td></tr></table>>,
tooltip="ddd.models.conversion.LinearConversion

``physical = raw * factor + offset``, the scaling of a fixed point value.
"];
"ddd.ir.ResolvedLeaf":conversion:e -> "ddd.models.conversion.LinearConversion":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.conversion.StringConversion" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>StringConversion</b></td></tr><tr><td>kind</td><td port="kind">Literal['string']</td></tr></table>>,
tooltip="ddd.models.conversion.StringConversion

Bytes read as text: each element of the array holds one character code.

\
Stated on a ``uint8`` or ``sint8`` array of one dimension; the rules sit beside the
datatype because the same pair is written \
in three places. ``kind`` is required here,
unlike on the other three kinds: a string has no key of its own to be inferred from,&#\
xA;and ``{}`` is the identity.

The two mappings are the identity on one byte, so that the derived limits of a string
\
are the raw range of its datatype - which is what the a2l record states - and nothing
that ranges a conversion has to know that \
a string exists. A byte has no reading of its
own, so no reading is produced for it, as for the identity.
"];
"ddd.ir.ResolvedLeaf":conversion:e -> "ddd.models.conversion.StringConversion":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.ir.ResolvedLeaf":a2l:e -> "ddd.models.objects.A2lObjectOptions":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.objects.Limits" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>Limits</b></td></tr><tr><td>min</td><td port="min">Union[int, float]</td></tr><tr><td>max</td><td port="max">Union[int, float]</td></tr></table>>,
tooltip="ddd.models.objects.Limits

Physical lower/upper limit of a data object.
"];
"ddd.ir.ResolvedLeaf":limits:e -> "ddd.models.objects.Limits":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.ir.ResolvedMember" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>ResolvedMember</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>description</td><td port="description">str</td></tr><tr><td>datatype</td><td port="datatype">Datatype | None</td></tr><tr><td>type</td><td port="type">str | None</td></tr><tr><td>external</td><td port="external">str | None</td></tr><tr><td>header</td><td port="header">str | None</td></tr><tr><td>dimensions</td><td port="dimensions">tuple[Union[int, str], ...]</td></tr><tr><td>bits</td><td port="bits">int | None</td></tr></table>>,
tooltip="ddd.ir.ResolvedMember

One member of a structure, as the c templates need it to declare the member.

Only what a \
declaration takes. The meaning of the member - its unit, its conversion, its
limits - travels with the *leaf* instead, because \
that is the form the a2l consumes and
there is no second place a reader should have to look.

Exactly one of ``datatype``, ``\
type`` and ``external`` is stated: a member holds a value
of a base datatype, is a structure, or is storage of a type DDD does \
not describe. A
member stating none of them would be storage with no size, no meaning and no name, which
a consumer of this \
document has nothing to do with.
"];
"ddd.ir.ResolvedObject":conversion:e -> "ddd.models.conversion.EnumConversion":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.ir.ResolvedObject":conversion:e -> "ddd.models.conversion.IdentityConversion":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.ir.ResolvedObject":conversion:e -> "ddd.models.conversion.LinearConversion":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.ir.ResolvedObject":conversion:e -> "ddd.models.conversion.StringConversion":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.ir.ResolvedObject":a2l:e -> "ddd.models.objects.A2lObjectOptions":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.ir.ResolvedObject":limits:e -> "ddd.models.objects.Limits":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.ir.ResolvedStruct":members:e -> "ddd.ir.ResolvedMember":_root:w [arrowhead=crownone,
arrowtail=nonenone];
"ddd.models.conversion.Enumerator" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>Enumerator</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>value</td><td port="value">int</td></tr><tr><td>description</td><td port="description">str</td></tr></table>>,
tooltip="ddd.models.conversion.Enumerator

One named value of an enum conversion, and what that value means.
"];
"ddd.models.conversion.EnumConversion":enumerators:e -> "ddd.models.conversion.Enumerator":_root:w [arrowhead=crownone,
arrowtail=nonenone];
}](_images/graphviz-1bae40a9ddabe0a63100e211c63b78afd3bfad7a.png)
Show JSON schema
{ "title": "DDD data dictionary", "description": "The resolved data of one project.\n\nWhat ``ddd dump`` writes and every backend reads. Unlike the description files, this one\nis produced rather than authored: every derived property is already worked out, so a\nconsumer never has to repeat the resolution and two consumers can never disagree about it.", "type": "object", "properties": { "format": { "default": 9, "description": "Version of this document format, raised only when the shape of the document changes.\n\nStamped so that a dictionary archived next to a delivery can be read back years later by\na version of DDD that can say \"this file is newer than I understand\" rather than misread\nit. It does not follow the version of the tool.\n\nA whole number of at least 1, and strictly that: ``\"9\"``, ``9.0`` and ``0`` are not\nversions any DDD ever wrote, and the check that refuses a dictionary from a newer DDD has\nno version to compare them with.", "minimum": 1, "title": "Format", "type": "integer" }, "name": { "description": "Name of the project, from the root project description.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "description": { "default": "", "description": "Free text from the root project description.", "title": "Description", "type": "string" }, "source": { "default": "", "description": "Name of the root description file, for reference in generated comments.", "title": "Source", "type": "string" }, "components": { "default": [], "description": "Every component of the project, including those of its sub-projects.", "items": { "$ref": "#/$defs/ResolvedComponent" }, "title": "Components", "type": "array" }, "objects": { "default": [], "description": "Sorted by name, so that every backend produces a stable output.", "items": { "$ref": "#/$defs/ResolvedObject" }, "title": "Objects", "type": "array" }, "enums": { "default": [], "description": "Distinct enumerations used by the objects, sorted by name.", "items": { "$ref": "#/$defs/EnumConversion" }, "title": "Enums", "type": "array" }, "constants": { "default": [], "description": "The named constants the project declares, sorted by name.\n\nRecorded whole - name, value and description - so that a generator consuming the\ndictionary can emit them the way the shipped templates do, and so that a dimension\nspelled by name stays resolvable after the description files have moved on.", "items": { "$ref": "#/$defs/ConstantDeclaration" }, "title": "Constants", "type": "array" }, "rasters": { "default": [], "description": "The measurement rasters the project declares, sorted by name.\n\nRecorded whole - name, event, period and description - so that a generator consuming the\ndictionary can write the event list itself rather than repeat the resolution. Empty in a\ndictionary from format 4 or older.", "items": { "$ref": "#/$defs/ResolvedRaster" }, "title": "Rasters", "type": "array" }, "types": { "default": [], "description": "The structures the project declares, each after every structure it nests.\n\nDependency order rather than alphabetical, because a template that simply loops over them\nhas to be able to write them out as they come: c needs a nested structure to be complete\nbefore the one that contains it.", "items": { "$ref": "#/$defs/ResolvedStruct" }, "title": "Types", "type": "array" }, "instances": { "default": [], "description": "Variables whose datatype is a structure, sorted by name.", "items": { "$ref": "#/$defs/ResolvedInstance" }, "title": "Instances", "type": "array" }, "leaves": { "default": [], "description": "Every member of every structured variable, flattened, sorted by path.\n\nBy path with every ``[n]`` in it read as the number it is, so the elements of an array of\nstructures are in the order they are stored in rather than in the order their spellings\nhappen to sort in: ``[2]`` before ``[10]``.\n\nWritten out rather than worked out on demand, because the dictionary is a produced\ndocument: a generator DDD does not ship reads it without importing python, and no backend\nshould repeat resolution the analysis has already done.", "items": { "$ref": "#/$defs/ResolvedLeaf" }, "title": "Leaves", "type": "array" }, "plugins": { "default": [], "description": "The names of the plugins that interpreted this dictionary, sorted.\n\nNames rather than module spellings: a path is relative to a project file the dump no\nlonger has, and the name is what the blocks are keyed by. Empty in a dictionary from\nformat 6 or older, and what ``missing-plugin`` reads when a comparison runs without one\nof them.", "items": { "type": "string" }, "title": "Plugins", "type": "array" }, "extensions": { "additionalProperties": { "additionalProperties": true, "type": "object" }, "description": "The settings of each plugin, in resolved form, keyed by plugin name.\n\nRecorded so that a comparison over an archived dump can rebuild what the plugin's hooks\nwere given, without the project file that stated them.", "title": "Extensions", "type": "object" } }, "$defs": { "A2lObjectOptions": { "additionalProperties": false, "description": "What a declaration asks of the a2l backend. Only that backend interprets it.\n\nNothing here changes the generated c or the meaning of the object; a project that\ngenerates no a2l can leave the whole block out.", "properties": { "export": { "anyOf": [ { "type": "boolean" }, { "type": "null" } ], "default": null, "description": "Whether the object belongs in the a2l file; omitted, it does.\n\nThe one a2l option any component may state, not only the producer. Which signals a\ncalibration engineer needs to see is not a property of whoever happens to write the\nvariable: a component reading a value from a library it does not own has as good a claim\nto measuring it.\n\nStated by several, the answer is yes if any of them says so, and an object nobody\nmentions is exported: see \"Who asks for an export\" on the definition page.", "title": "Export" }, "format": { "anyOf": [ { "pattern": "^%[0-9]*\\.[0-9]+$", "type": "string" }, { "type": "null" } ], "default": null, "description": "a2l ``FORMAT`` string, e.g. ``\"%8.3\"``: total width, then decimal places.\n\nRefused beside a ``string`` conversion, which has no decimals to display.", "title": "Format" }, "display_identifier": { "anyOf": [ { "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "type": "string" }, { "type": "null" } ], "default": null, "description": "Alternative name shown by the calibration tool.", "title": "Display Identifier" } }, "title": "A2lObjectOptions", "type": "object" }, "ComponentDeclaration": { "additionalProperties": false, "description": "One entry of a component interface, in the order the component declared it.\n\nA reference to an object rather than the object itself: the definition lives once, under\n``objects``, and is the one the producing component gave. Two components declaring the\nsame name appear here twice and in ``objects`` once.", "properties": { "name": { "description": "Name of the declared object; a key into the ``objects`` list of the dictionary.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "scope": { "$ref": "#/$defs/Scope", "description": "How this component uses the object: ``input``, ``output`` or ``local``." }, "condition": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Preprocessor expression this component guarded the declaration with, if any.", "title": "Condition" } }, "required": [ "name", "scope" ], "title": "ComponentDeclaration", "type": "object" }, "ConstantDeclaration": { "additionalProperties": false, "description": "One named number, declared once and named wherever the project needs it.", "properties": { "name": { "description": "The name a shape writes where it would state a number: ``PRESSURE_CELLS``.\n\nAn identifier, because the name reaches the generated code as an identifier of its own;\nthe templates receive every declared constant to emit.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "value": { "anyOf": [ { "maximum": 18446744073709551615, "minimum": -9223372036854775808, "type": "integer" }, { "type": "number" } ], "description": "The value, a number: a whole number of either sign, or one written with a point.\n\nA literal only: an expression would put a parser and an evaluation order into a\ndescription format, and a constant cannot name another constant, so what cannot be\nwritten cannot cycle. How it is written settles what it is - ``2`` is a whole number,\nand anything carrying a point or an exponent is fractional, so ``2.0`` and ``1e3`` both\nare - because that is what the author is picking: the type, not the format. The\noutputs carry the number in its shortest spelling that reads back as the same number, a\nwhole number without a point and any other with a point or an exponent, so ``2.50``\nreaches the generated code as ``2.5`` and ``1e3`` as ``1000.0``.\nA whole number is bounded by what a 64 bit target can express, signed or unsigned, and\na fractional one must be finite: ``inf`` and ``nan`` name nothing a description can\nstate, and would reach a template as those words.\n\nNothing here requires the value to be a size. A constant that a shape names has to be\na whole number of at least 1, the same rule a dimension written as a literal obeys, but\nthat is checked where the shape names it - the declaration is not the place, because a\nconstant may be declared to be emitted and never dimension anything.", "title": "Value" }, "description": { "default": "", "description": "What the constant stands for, e.g. ``cells of the pressure manifold``.\n\nThis is where the meaning of a number is written down once, instead of being implied by\nevery object that happens to use it.", "title": "Description", "type": "string" } }, "required": [ "name", "value" ], "title": "ConstantDeclaration", "type": "object" }, "Datatype": { "description": "The base datatypes DDD can allocate storage for.", "enum": [ "boolean", "uint8", "sint8", "uint16", "sint16", "uint32", "sint32", "uint64", "sint64", "float32", "float64" ], "title": "Datatype", "type": "string" }, "EnumConversion": { "additionalProperties": false, "description": "A verbal conversion table; the raw value *is* the physical value.\n\nAccepts both the explicit form::\n\n {\"kind\": \"enum\", \"name\": \"StateA\",\n \"enumerators\": [{\"name\": \"STATE_OFF\", \"value\": 0}]}\n\nand the mapping shorthand::\n\n {\"kind\": \"enum\", \"name\": \"StateA\", \"enumerators\": {\"STATE_OFF\": 0}}", "properties": { "kind": { "const": "enum", "default": "enum", "description": "The tag of this kind, which may be left out: a block stating ``enumerators`` or a\n``name`` is an enum.", "title": "Kind", "type": "string" }, "name": { "description": "C identifier of the generated ``typedef enum``; shared enums must agree everywhere.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "enumerators": { "anyOf": [ { "items": { "$ref": "#/$defs/Enumerator" }, "minItems": 1, "type": "array" }, { "additionalProperties": { "maximum": 18446744073709551615, "minimum": -9223372036854775808, "type": "integer" }, "description": "The enumerators as a ``{\"NAME\": value}`` mapping.", "minProperties": 1, "propertyNames": { "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$" }, "type": "object" } ], "description": "The named values, either as objects or as a ``{\"NAME\": value}`` mapping.\n\nTwo of them may not carry the same name, which the mapping form cannot express twice and\nthe list form can: the generated enumeration would not compile, and a calibration tool\nreading the generated table of labels would have two answers for one. Two names sharing a\n*value* is a different matter - it is the C idiom for an alias, reported as\n``enum-duplicate-value`` rather than refused.", "title": "Enumerators" } }, "required": [ "name", "enumerators" ], "title": "EnumConversion", "type": "object" }, "Enumerator": { "additionalProperties": false, "description": "One named value of an enum conversion, and what that value means.", "properties": { "name": { "description": "C identifier of the enumerator; enumerators of all enums share one c namespace.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "value": { "description": "The raw value; two enumerators of one enum sharing one is reported as a warning.\n\n``enum-duplicate-value``, a warning rather than a refusal, because it is legal c and\noccasionally meant as an alias - but the a2l table then offers a calibration tool two\nnames for one reading.\n\nBounded to what 64 bits can hold - no datatype DDD offers stores more - so a value no\nstorage could ever represent is refused here rather than overflowing a comparison once\nit is checked against the c ``int`` every enumerator has to fit, or against the\ndatatype carrying it.\n\nA whole number written without a decimal point: ``4``, not ``4.0``, which the published\nschema accepts and the loader refuses.", "maximum": 18446744073709551615, "minimum": -9223372036854775808, "title": "Value", "type": "integer" }, "description": { "default": "", "description": "What the value means; documentation, not interface.", "title": "Description", "type": "string" } }, "required": [ "name", "value" ], "title": "Enumerator", "type": "object" }, "IdentityConversion": { "additionalProperties": false, "description": "``physical == raw``; stated like any other conversion, ``{}`` its shortest spelling.\n\nNot a default: a definition naming storage by ``datatype`` states this one where raw and\nphysical are the same number, so that the claim is written down rather than left to\nsilence.", "properties": { "kind": { "const": "identity", "default": "identity", "description": "The tag of this kind, which may be left out: an empty block is the identity.", "title": "Kind", "type": "string" } }, "title": "IdentityConversion", "type": "object" }, "InitElement": { "anyOf": [ { "$ref": "#/$defs/InitScalar" }, { "items": { "$ref": "#/$defs/InitElement" }, "type": "array" } ] }, "InitScalar": { "anyOf": [ { "maximum": 18446744073709551615, "minimum": -9223372036854775808, "type": "integer" }, { "type": "boolean" }, { "type": "number" } ] }, "InitValue": { "anyOf": [ { "$ref": "#/$defs/InitScalar" }, { "type": "string" }, { "items": { "$ref": "#/$defs/InitElement" }, "type": "array" } ] }, "Limits": { "additionalProperties": false, "description": "Physical lower/upper limit of a data object.", "properties": { "min": { "anyOf": [ { "maximum": 18446744073709551615, "minimum": -9223372036854775808, "type": "integer" }, { "type": "number" } ], "description": "Smallest physical value the object may take.", "title": "Min" }, "max": { "anyOf": [ { "maximum": 18446744073709551615, "minimum": -9223372036854775808, "type": "integer" }, { "type": "number" } ], "description": "Largest physical value the object may take; at least ``min``.", "title": "Max" } }, "required": [ "min", "max" ], "title": "Limits", "type": "object" }, "LinearConversion": { "additionalProperties": false, "description": "``physical = raw * factor + offset``, the scaling of a fixed point value.", "properties": { "kind": { "const": "linear", "default": "linear", "description": "The tag of this kind, which may be left out: a block stating ``factor`` or ``offset``\nis linear.", "title": "Kind", "type": "string" }, "factor": { "default": 1.0, "description": "Scaling; must not be zero, or nothing could be converted back.", "title": "Factor", "type": "number" }, "offset": { "default": 0.0, "description": "What raw zero stands for, in the physical unit.", "title": "Offset", "type": "number" } }, "title": "LinearConversion", "type": "object" }, "ObjectKind": { "description": "What sort of data object a definition describes.", "enum": [ "measurement", "parameter", "value_block", "curve", "map", "axis" ], "title": "ObjectKind", "type": "string" }, "PointCounts": { "description": "Where an interpolation object stores its number of axis points, if anywhere.", "enum": [ "none", "leading" ], "title": "PointCounts", "type": "string" }, "ResolvedComponent": { "additionalProperties": false, "description": "A component and the objects it declares.", "properties": { "name": { "description": "Name of the component, unique within the project.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "description": { "default": "", "description": "Free text from the component description, offered to the templates.", "title": "Description", "type": "string" }, "source": { "default": "", "description": "File name of the description file, for reference in generated comments.\n\nThe name alone, without the directories above it: a dictionary dumped from two checkouts\nof one project is otherwise two different documents, and the banner of a generated file\nwould carry the path of whoever's machine generated it.", "title": "Source", "type": "string" }, "declarations": { "default": [], "description": "The interface of the component, in the order it declared it.", "items": { "$ref": "#/$defs/ComponentDeclaration" }, "title": "Declarations", "type": "array" } }, "required": [ "name" ], "title": "ResolvedComponent", "type": "object" }, "ResolvedInstance": { "additionalProperties": false, "description": "One variable whose datatype is a structure.\n\nKept apart from :class:`ResolvedObject` rather than widening it: an object with no datatype\nand no limits would turn every reader of those two fields into a branch, and they are read\nunconditionally in a dozen places on the strength of always being there.", "properties": { "name": { "description": "Name of the variable; its c identifier and the root of every leaf path.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "id": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Identity the producer gave this object, which survives a rename of it.\n\nEmpty in a dictionary from format 5 or older, which recorded none: an object that pairs\non nothing pairs on its name, exactly as it did then.", "title": "Id" }, "extensions": { "additionalProperties": { "additionalProperties": true, "type": "object" }, "description": "The blocks of the project's plugins, keyed by plugin name, in resolved form.\n\nEach validated against its plugin's model and dumped back, defaults filled in, so two\ndumps compare on one shape. Empty in a dictionary from format 6 or older, which recorded\nnone, and empty for an object nothing stamped.", "title": "Extensions", "type": "object" }, "type": { "description": "Name of the structure it is, which is the c type of the declaration.", "title": "Type", "type": "string" }, "kind": { "$ref": "#/$defs/ObjectKind", "description": "``measurement`` or ``parameter``: what the whole object is, and so how it is qualified." }, "description": { "default": "", "description": "What the object is; the comment in the generated c.", "title": "Description", "type": "string" }, "shape": { "default": [], "description": "Array dimensions of the variable itself, empty for a single structure.\n\nAn array of structures reaches the a2l as its elements: there is no one address that\ndescribes ``cell[0].raw`` and ``cell[1].raw`` at once, so each element contributes its own\nleaves at its own path. Every dimension is a resolved number; the spelling is in\n``dimensions``.", "items": { "exclusiveMinimum": 0, "type": "integer" }, "title": "Shape", "type": "array" }, "dimensions": { "default": [], "description": "The shape again, each dimension spelled the way the declaration spells it.\n\nParallel to ``shape`` exactly as on a plain object: the number, or the name of the\ndeclared constant the generated code declares the array by. Empty in a dictionary from\nformat 3 or older.", "items": { "anyOf": [ { "maximum": 18446744073709551615, "minimum": 1, "type": "integer" }, { "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "type": "string" } ] }, "title": "Dimensions", "type": "array" }, "volatile": { "default": false, "description": "Whether the declaration carries ``volatile``, which qualifies the whole object.", "title": "Volatile", "type": "boolean" }, "section": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Linker section the whole structure is placed in; its members have no placement\nof their own.", "title": "Section" }, "raster": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Measurement raster the producing component updates the object in; ``null`` when the\nproject named none. Empty in a dictionary from format 4 or older.", "title": "Raster" }, "condition": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Preprocessor condition of the producing declaration, if any.", "title": "Condition" }, "owner": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Component owning the object; ``null`` only when the project is inconsistent.", "title": "Owner" }, "consumers": { "default": [], "description": "Components declaring the object as an input, sorted.", "items": { "type": "string" }, "title": "Consumers", "type": "array" }, "local": { "default": false, "description": "Owned exclusively by ``owner``; no other component may declare it.", "title": "Local", "type": "boolean" }, "a2l": { "$ref": "#/$defs/A2lObjectOptions", "default": { "export": null, "format": null, "display_identifier": null }, "description": "What the whole object asks of the a2l; a member may ask for more of its own." } }, "required": [ "name", "type", "kind" ], "title": "ResolvedInstance", "type": "object" }, "ResolvedLeaf": { "additionalProperties": false, "description": "One member of one structured variable, at the end of one access path.\n\nThe flattening. A structure reaches the a2l as an object per member rather than as an a2l\nstructure, so this is the form that backend consumes - an ordinary object in every respect\nbut its name, which is a path rather than an identifier.", "properties": { "path": { "description": "The c expression that reads this member: ``Inlet.latest.value``, ``Inlet.cell[2].raw``.\n\nBoth the name the a2l gives the object and the symbol it links it to. Written the way it\nwould be written in c, so that a reader of the a2l, of the generated c and of a map file is\nlooking at one string rather than at three spellings of one thing.", "title": "Path", "type": "string" }, "instance": { "description": "Name of the variable this leaf belongs to, which is the root of :attr:`path`.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Instance", "type": "string" }, "instance_id": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Identity of the variable this leaf belongs to; a member has none of its own.\n\nA leaf is identified by this together with the part of :attr:`path` below the instance,\nso renaming the instance is tracked and renaming a *member of the type* is not - the\npath is half of the identity. Empty in a dictionary from format 5 or older.", "title": "Instance Id" }, "kind": { "$ref": "#/$defs/ObjectKind", "description": "Taken from the variable: every leaf of one object has the storage class of the whole." }, "datatype": { "$ref": "#/$defs/Datatype", "description": "Storage of one element." }, "description": { "default": "", "description": "What this member is; the a2l long identifier.", "title": "Description", "type": "string" }, "unit": { "default": "", "description": "Physical unit, from the member or from the type it names.", "title": "Unit", "type": "string" }, "conversion": { "description": "Always present: the member's conversion, or the identity when none was given.", "discriminator": { "mapping": { "enum": "#/$defs/EnumConversion", "identity": "#/$defs/IdentityConversion", "linear": "#/$defs/LinearConversion", "string": "#/$defs/StringConversion" }, "propertyName": "kind" }, "oneOf": [ { "$ref": "#/$defs/IdentityConversion" }, { "$ref": "#/$defs/LinearConversion" }, { "$ref": "#/$defs/EnumConversion" }, { "$ref": "#/$defs/StringConversion" } ], "title": "Conversion" }, "limits": { "$ref": "#/$defs/Limits", "description": "Always present: stated, or derived from the storage - a bitfield's from its width." }, "shape": { "default": [], "description": "Array dimensions of this member; empty for a scalar.\n\nEvery dimension is a resolved number, because this is the form the a2l consumes; a\ndimension the member spells as a constant name carries that name in ``dimensions``.", "items": { "exclusiveMinimum": 0, "type": "integer" }, "title": "Shape", "type": "array" }, "dimensions": { "default": [], "description": "The shape again, each dimension spelled the way the member spells it.\n\nParallel to ``shape`` exactly as on a plain object. Empty in a dictionary from format 3\nor older.", "items": { "anyOf": [ { "maximum": 18446744073709551615, "minimum": 1, "type": "integer" }, { "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "type": "string" } ] }, "title": "Dimensions", "type": "array" }, "bits": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "default": null, "description": "Width in bits when the member is a c bitfield.\n\nSuch a leaf has no address of its own - ``&s.ready`` does not compile - so it reaches no\na2l until a build tells DDD both where the word is and which bits inside it to read.", "title": "Bits" }, "volatile": { "default": false, "description": "From the variable, which carries the qualifier for all of its members at once.", "title": "Volatile", "type": "boolean" }, "section": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Linker section of the structure this member belongs to; a member has no placement\nof its own.", "title": "Section" }, "raster": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Raster of the variable this member belongs to; a member has none of its own.", "title": "Raster" }, "condition": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Preprocessor condition of the producing declaration, if any.", "title": "Condition" }, "owner": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Component owning the variable this leaf belongs to.", "title": "Owner" }, "consumers": { "default": [], "description": "Components declaring the variable as an input, sorted.", "items": { "type": "string" }, "title": "Consumers", "type": "array" }, "local": { "default": false, "description": "Owned exclusively by ``owner``.", "title": "Local", "type": "boolean" }, "a2l": { "$ref": "#/$defs/A2lObjectOptions", "default": { "export": null, "format": null, "display_identifier": null }, "description": "The member's own a2l options; a member may be kept out of the file on its own." } }, "required": [ "path", "instance", "kind", "datatype", "conversion", "limits" ], "title": "ResolvedLeaf", "type": "object" }, "ResolvedMember": { "additionalProperties": false, "description": "One member of a structure, as the c templates need it to declare the member.\n\nOnly what a declaration takes. The meaning of the member - its unit, its conversion, its\nlimits - travels with the *leaf* instead, because that is the form the a2l consumes and\nthere is no second place a reader should have to look.\n\nExactly one of ``datatype``, ``type`` and ``external`` is stated: a member holds a value\nof a base datatype, is a structure, or is storage of a type DDD does not describe. A\nmember stating none of them would be storage with no size, no meaning and no name, which\na consumer of this document has nothing to do with.", "properties": { "name": { "description": "Name of the member, as it is written in the c struct.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "description": { "default": "", "description": "What the member is, for a comment beside its declaration.", "title": "Description", "type": "string" }, "datatype": { "anyOf": [ { "$ref": "#/$defs/Datatype" }, { "type": "null" } ], "default": null, "description": "Storage of the member when it is a base one; ``null`` when it names a declared type." }, "type": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Name of the structure this member is, when it is one; ``null`` when it is a datatype.\n\nThe name as the types file spells it, which in a dictionary carrying an ``unknown-type``\nerror may be a name no ``types`` entry answers: the member says what it was declared as,\nand the finding says that nothing declares it.", "title": "Type" }, "external": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Name of the external type this member is, when it is one; ``null`` otherwise.\n\nAn external type is one DDD does not declare - a hand written header defines it - so the\nmember is opaque storage: it appears in the generated structure verbatim, spelled with\nthis name, and contributes no leaf, because DDD knows neither its layout nor its meaning.", "title": "External" }, "header": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "The header defining the external type, spelled the way the generated inclusion writes\nit: ``my_driver.h`` for the quoted form, ``<os_types.h>`` for the angle form. Stated\nexactly when ``external`` is, and carried on the member so a consumer of the dictionary\nnever has to resolve the type name a second time.", "title": "Header" }, "dimensions": { "default": [], "description": "Array dimensions, empty for a scalar, each spelled the way the member spells it.\n\nA number, or the name of a declared constant, exactly as ``dimensions`` is spelled on\nan object or an instance. A member carries no numeric ``shape`` beside it: it is the\ndeclaration side of the answer, and the resolved numbers live on the leaves of every\ninstantiated structure, with the value of a named dimension in the dictionary's\n``constants``.", "items": { "anyOf": [ { "maximum": 18446744073709551615, "minimum": 1, "type": "integer" }, { "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "type": "string" } ] }, "title": "Dimensions", "type": "array" }, "bits": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "default": null, "description": "Width in bits when the member is a c bitfield; ``null`` when it is not.", "title": "Bits" } }, "required": [ "name" ], "title": "ResolvedMember", "type": "object" }, "ResolvedObject": { "additionalProperties": false, "description": "One data object, with every derived property already worked out.", "properties": { "name": { "description": "Name of the object, unique across the whole project; its c and a2l identifier.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "id": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Identity the producer gave this object, which survives a rename of it.\n\nEmpty in a dictionary from format 5 or older, which recorded none: an object that pairs\non nothing pairs on its name, exactly as it did then.", "title": "Id" }, "extensions": { "additionalProperties": { "additionalProperties": true, "type": "object" }, "description": "The blocks of the project's plugins, keyed by plugin name, in resolved form.\n\nEach validated against its plugin's model and dumped back, defaults filled in, so two\ndumps compare on one shape. Empty in a dictionary from format 6 or older, which recorded\nnone, and empty for an object nothing stamped.", "title": "Extensions", "type": "object" }, "kind": { "$ref": "#/$defs/ObjectKind", "description": "Which sort of object this is, taken from the definition that produced it." }, "datatype": { "$ref": "#/$defs/Datatype", "description": "Storage type of one element." }, "description": { "default": "", "description": "What the object is; the a2l long identifier and the comment in the generated c.", "title": "Description", "type": "string" }, "unit": { "default": "", "description": "Physical unit, as the declaring components agreed on it.", "title": "Unit", "type": "string" }, "conversion": { "description": "Always present: the declared conversion, or the identity when none was given.", "discriminator": { "mapping": { "enum": "#/$defs/EnumConversion", "identity": "#/$defs/IdentityConversion", "linear": "#/$defs/LinearConversion", "string": "#/$defs/StringConversion" }, "propertyName": "kind" }, "oneOf": [ { "$ref": "#/$defs/IdentityConversion" }, { "$ref": "#/$defs/LinearConversion" }, { "$ref": "#/$defs/EnumConversion" }, { "$ref": "#/$defs/StringConversion" } ], "title": "Conversion" }, "limits": { "$ref": "#/$defs/Limits", "description": "Always present: the explicit limits, or the range the datatype and conversion imply." }, "shape": { "default": [], "description": "Storage shape, empty for a scalar; for a curve or a map it comes from its axes.\n\nEvery dimension is at least one, like the ``dimensions`` and ``size`` it derives from,\nand every dimension is a resolved number: a dimension stated as the name of a declared\nconstant carries its value here and its name in ``dimensions``.", "items": { "exclusiveMinimum": 0, "type": "integer" }, "title": "Shape", "type": "array" }, "dimensions": { "default": [], "description": "The shape again, each dimension spelled the way the project spells it.\n\nParallel to ``shape``: the same dimensions in the same order, each the number itself or\nthe name of the declared constant that states it - the name under which the generated\ncode declares the array. Empty in a dictionary from format 3 or older, which recorded\nno spellings.", "items": { "anyOf": [ { "maximum": 18446744073709551615, "minimum": 1, "type": "integer" }, { "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "type": "string" } ] }, "title": "Dimensions", "type": "array" }, "init": { "anyOf": [ { "$ref": "#/$defs/InitValue" }, { "type": "null" } ], "default": null, "description": "Raw initial value as the description wrote it, or the text of a string object;\n``null`` means zero initialised.\n\nA list is nested to match ``shape``, one level per dimension. A scalar written for an\narray is carried as the scalar: it initialises every element, and expanding it here\nwould write one literal per element into the dumped dictionary for a value the\ndescription states once. A consumer that needs the elements broadcasts the scalar over\n``shape``, which is what the c backend does to render the initialiser." }, "section": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Linker section the producing declaration placed the object in; ``null`` for the\ntoolchain's defaults.", "title": "Section" }, "raster": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Measurement raster the producing component updates the object in; ``null`` when the\nproject named none. Empty in a dictionary from format 4 or older.", "title": "Raster" }, "point_counts": { "$ref": "#/$defs/PointCounts", "default": "none", "description": "Whether this curve, map or axis stores its point counts ahead of its data: its\nproducing component's ``point_counts``, else the project's. ``none`` for every other kind,\nand in a dictionary from format 8 or older, which never stored any." }, "volatile": { "default": false, "description": "Generate the object ``volatile``: stated by every declaration, on every kind.\n\nCalibration data carries it as ``const volatile``, which is what a value the calibration\ntool changes in a running ecu needs - see the field of the same name on the authored\ndefinition. The default is kept although a definition may no longer omit it, so that a\ndictionary dumped by an older DDD still reads back: an older document is read with the\ndefaults of the format it states, which is what the ``format`` key of this document is\nfor.", "title": "Volatile", "type": "boolean" }, "condition": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Preprocessor condition of the producing declaration, if any.", "title": "Condition" }, "references": { "additionalProperties": { "type": "string" }, "description": "Other objects this one refers to, keyed by field name (``axis``, ``x_axis``, ...).", "title": "References", "type": "object" }, "owner": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Component owning the object; ``null`` only when the project is inconsistent.", "title": "Owner" }, "consumers": { "default": [], "description": "Components declaring the object as an input, sorted; empty when nothing reads it.", "items": { "type": "string" }, "title": "Consumers", "type": "array" }, "local": { "default": false, "description": "Owned exclusively by ``owner``; no other component may declare it.", "title": "Local", "type": "boolean" }, "a2l": { "$ref": "#/$defs/A2lObjectOptions", "default": { "export": null, "format": null, "display_identifier": null }, "description": "What the author asked for in the ``a2l`` block. Only the a2l backend interprets it." } }, "required": [ "name", "kind", "datatype", "conversion", "limits" ], "title": "ResolvedObject", "type": "object" }, "ResolvedRaster": { "additionalProperties": false, "description": "One declared daq event, as the dictionary publishes it.", "properties": { "raster": { "description": "Name the objects refer to, and the short name of the xcp event.", "title": "Raster", "type": "string" }, "event": { "description": "The xcp event channel number.", "title": "Event", "type": "integer" }, "cycle": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "The period as the project wrote it: ``10ms``. Absent when the event is not cyclic.", "title": "Cycle" }, "cycle_ns": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "default": null, "description": "The same period in nanoseconds, resolved so that a consumer never parses the spelling.\n\nBoth are kept for the reason ``shape`` and ``dimensions`` both are: the authored form is\nwhat a reader recognises, and the number is what a consumer computes with.", "title": "Cycle Ns" }, "description": { "default": "", "description": "Free text from the declaration; the long name of the eventual ``EVENT``.", "title": "Description", "type": "string" } }, "required": [ "raster", "event" ], "title": "ResolvedRaster", "type": "object" }, "ResolvedStruct": { "additionalProperties": false, "description": "One structure, in an order a c file can be written out in.\n\nThe order of :attr:`DataDictionary.types` matters and is not alphabetical: a structure\nappears after every structure it nests, because a c compiler needs the nested one to be\ncomplete first. The members keep the order the author wrote them in, which is the order the\ncompiler lays them out.", "properties": { "name": { "description": "Name of the structure, which is the name of the generated typedef.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "description": { "default": "", "description": "What the structure is, for a comment above it.", "title": "Description", "type": "string" }, "members": { "default": [], "description": "The members, in declaration order.", "items": { "$ref": "#/$defs/ResolvedMember" }, "title": "Members", "type": "array" } }, "required": [ "name" ], "title": "ResolvedStruct", "type": "object" }, "Scope": { "description": "Direction of a variable with respect to the declaring component.", "enum": [ "input", "output", "local" ], "title": "Scope", "type": "string" }, "StringConversion": { "additionalProperties": false, "description": "Bytes read as text: each element of the array holds one character code.\n\nStated on a ``uint8`` or ``sint8`` array of one dimension; the rules sit beside the\ndatatype because the same pair is written in three places. ``kind`` is required here,\nunlike on the other three kinds: a string has no key of its own to be inferred from,\nand ``{}`` is the identity.\n\nThe two mappings are the identity on one byte, so that the derived limits of a string\nare the raw range of its datatype - which is what the a2l record states - and nothing\nthat ranges a conversion has to know that a string exists. A byte has no reading of its\nown, so no reading is produced for it, as for the identity.", "properties": { "kind": { "const": "string", "description": "The tag of this kind, which is required: a string has no key of its own to be\nrecognised by, so nothing else would tell it from the identity.", "title": "Kind", "type": "string" } }, "required": [ "kind" ], "title": "StringConversion", "type": "object" } }, "additionalProperties": false, "required": [ "name" ] }
- field format: Annotated[int, Field(ge=1, strict=True)] = 9
Version of this document format, raised only when the shape of the document changes.
Stamped so that a dictionary archived next to a delivery can be read back years later by a version of DDD that can say “this file is newer than I understand” rather than misread it. It does not follow the version of the tool.
A whole number of at least 1, and strictly that:
"9",9.0and0are not versions any DDD ever wrote, and the check that refuses a dictionary from a newer DDD has no version to compare them with.Version of this document format, raised only when the shape of the document changes.
Stamped so that a dictionary archived next to a delivery can be read back years later by a version of DDD that can say “this file is newer than I understand” rather than misread it. It does not follow the version of the tool.
A whole number of at least 1, and strictly that:
"9",9.0and0are not versions any DDD ever wrote, and the check that refuses a dictionary from a newer DDD has no version to compare them with.
- field name: Identifier [Required]
Name of the project, from the root project description.
- field description: str = ''
Free text from the root project description.
- field source: str = ''
Name of the root description file, for reference in generated comments.
- field components: tuple[ResolvedComponent, ...] = ()
Every component of the project, including those of its sub-projects.
- field objects: tuple[ResolvedObject, ...] = ()
Sorted by name, so that every backend produces a stable output.
- field enums: tuple[EnumConversion, ...] = ()
Distinct enumerations used by the objects, sorted by name.
- field constants: tuple[ConstantDeclaration, ...] = ()
The named constants the project declares, sorted by name.
Recorded whole - name, value and description - so that a generator consuming the dictionary can emit them the way the shipped templates do, and so that a dimension spelled by name stays resolvable after the description files have moved on.
The named constants the project declares, sorted by name.
Recorded whole - name, value and description - so that a generator consuming the dictionary can emit them the way the shipped templates do, and so that a dimension spelled by name stays resolvable after the description files have moved on.
- field rasters: tuple[ResolvedRaster, ...] = ()
The measurement rasters the project declares, sorted by name.
Recorded whole - name, event, period and description - so that a generator consuming the dictionary can write the event list itself rather than repeat the resolution. Empty in a dictionary from format 4 or older.
The measurement rasters the project declares, sorted by name.
Recorded whole - name, event, period and description - so that a generator consuming the dictionary can write the event list itself rather than repeat the resolution. Empty in a dictionary from format 4 or older.
- field types: tuple[ResolvedStruct, ...] = ()
The structures the project declares, each after every structure it nests.
Dependency order rather than alphabetical, because a template that simply loops over them has to be able to write them out as they come: c needs a nested structure to be complete before the one that contains it.
The structures the project declares, each after every structure it nests.
Dependency order rather than alphabetical, because a template that simply loops over them has to be able to write them out as they come: c needs a nested structure to be complete before the one that contains it.
- field instances: tuple[ResolvedInstance, ...] = ()
Variables whose datatype is a structure, sorted by name.
- field leaves: tuple[ResolvedLeaf, ...] = ()
Every member of every structured variable, flattened, sorted by path.
By path with every
[n]in it read as the number it is, so the elements of an array of structures are in the order they are stored in rather than in the order their spellings happen to sort in:[2]before[10].Written out rather than worked out on demand, because the dictionary is a produced document: a generator DDD does not ship reads it without importing python, and no backend should repeat resolution the analysis has already done.
Every member of every structured variable, flattened, sorted by path.
By path with every
[n]in it read as the number it is, so the elements of an array of structures are in the order they are stored in rather than in the order their spellings happen to sort in:[2]before[10].Written out rather than worked out on demand, because the dictionary is a produced document: a generator DDD does not ship reads it without importing python, and no backend should repeat resolution the analysis has already done.
- field plugins: tuple[str, ...] = ()
The names of the plugins that interpreted this dictionary, sorted.
Names rather than module spellings: a path is relative to a project file the dump no longer has, and the name is what the blocks are keyed by. Empty in a dictionary from format 6 or older, and what
missing-pluginreads when a comparison runs without one of them.The names of the plugins that interpreted this dictionary, sorted.
Names rather than module spellings: a path is relative to a project file the dump no longer has, and the name is what the blocks are keyed by. Empty in a dictionary from format 6 or older, and what
missing-pluginreads when a comparison runs without one of them.
- field extensions: dict[str, dict[str, Any]] [Optional]
The settings of each plugin, in resolved form, keyed by plugin name.
Recorded so that a comparison over an archived dump can rebuild what the plugin’s hooks were given, without the project file that stated them.
The settings of each plugin, in resolved form, keyed by plugin name.
Recorded so that a comparison over an archived dump can rebuild what the plugin’s hooks were given, without the project file that stated them.
- pydantic model ResolvedObject[source]
One data object, with every derived property already worked out.
![digraph "Entity Relationship Diagram created by erdantic" {
graph [fontcolor=gray66,
fontname="Times New Roman,Times,Liberation Serif,serif",
fontsize=9,
nodesep=0.5,
rankdir=LR,
ranksep=1.5
];
node [fontname="Times New Roman,Times,Liberation Serif,serif",
fontsize=14,
label="\N",
shape=plain
];
edge [dir=both];
"ddd.ir.ResolvedObject" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>ResolvedObject</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>id</td><td port="id">str | None</td></tr><tr><td>extensions</td><td port="extensions">dict[str, dict[str, Any]]</td></tr><tr><td>kind</td><td port="kind">ObjectKind</td></tr><tr><td>datatype</td><td port="datatype">Datatype</td></tr><tr><td>description</td><td port="description">str</td></tr><tr><td>unit</td><td port="unit">str</td></tr><tr><td>conversion</td><td port="conversion">IdentityConversion | LinearConversion | EnumConversion | StringConversion</td></tr><tr><td>limits</td><td port="limits">Limits</td></tr><tr><td>shape</td><td port="shape">tuple[int, ...]</td></tr><tr><td>dimensions</td><td port="dimensions">tuple[Union[int, str], ...]</td></tr><tr><td>init</td><td port="init">InitValue | None</td></tr><tr><td>section</td><td port="section">str | None</td></tr><tr><td>raster</td><td port="raster">str | None</td></tr><tr><td>point_counts</td><td port="point_counts">PointCounts</td></tr><tr><td>volatile</td><td port="volatile">bool</td></tr><tr><td>condition</td><td port="condition">str | None</td></tr><tr><td>references</td><td port="references">dict[str, str]</td></tr><tr><td>owner</td><td port="owner">str | None</td></tr><tr><td>consumers</td><td port="consumers">tuple[str, ...]</td></tr><tr><td>local</td><td port="local">bool</td></tr><tr><td>a2l</td><td port="a2l">A2lObjectOptions</td></tr></table>>,
tooltip="ddd.ir.ResolvedObject

One data object, with every derived property already worked out.
"];
"ddd.models.conversion.EnumConversion" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>EnumConversion</b></td></tr><tr><td>kind</td><td port="kind">Literal['enum']</td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>enumerators</td><td port="enumerators">tuple[Enumerator, ...]</td></tr></table>>,
tooltip="ddd.models.conversion.EnumConversion

A verbal conversion table; the raw value *is* the physical value.

Accepts \
both the explicit form::

 {\"kind\": \"enum\", \"name\": \"StateA\",
 \"enumerators\": [{\"name\": \"STATE_OFF\", \"value\": \
0}]}

and the mapping shorthand::

 {\"kind\": \"enum\", \"name\": \"StateA\", \"enumerators\": {\"STATE_OFF\": 0}}
"];
"ddd.ir.ResolvedObject":conversion:e -> "ddd.models.conversion.EnumConversion":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.conversion.IdentityConversion" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>IdentityConversion</b></td></tr><tr><td>kind</td><td port="kind">Literal['identity']</td></tr></table>>,
tooltip="ddd.models.conversion.IdentityConversion

``physical == raw``; stated like any other conversion, ``{}`` its shortest spelling.&#\
xA;
Not a default: a definition naming storage by ``datatype`` states this one where raw and
physical are the same number, \
so that the claim is written down rather than left to
silence.
"];
"ddd.ir.ResolvedObject":conversion:e -> "ddd.models.conversion.IdentityConversion":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.conversion.LinearConversion" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>LinearConversion</b></td></tr><tr><td>kind</td><td port="kind">Literal['linear']</td></tr><tr><td>factor</td><td port="factor">float</td></tr><tr><td>offset</td><td port="offset">float</td></tr></table>>,
tooltip="ddd.models.conversion.LinearConversion

``physical = raw * factor + offset``, the scaling of a fixed point value.
"];
"ddd.ir.ResolvedObject":conversion:e -> "ddd.models.conversion.LinearConversion":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.conversion.StringConversion" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>StringConversion</b></td></tr><tr><td>kind</td><td port="kind">Literal['string']</td></tr></table>>,
tooltip="ddd.models.conversion.StringConversion

Bytes read as text: each element of the array holds one character code.

\
Stated on a ``uint8`` or ``sint8`` array of one dimension; the rules sit beside the
datatype because the same pair is written \
in three places. ``kind`` is required here,
unlike on the other three kinds: a string has no key of its own to be inferred from,&#\
xA;and ``{}`` is the identity.

The two mappings are the identity on one byte, so that the derived limits of a string
\
are the raw range of its datatype - which is what the a2l record states - and nothing
that ranges a conversion has to know that \
a string exists. A byte has no reading of its
own, so no reading is produced for it, as for the identity.
"];
"ddd.ir.ResolvedObject":conversion:e -> "ddd.models.conversion.StringConversion":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.objects.A2lObjectOptions" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>A2lObjectOptions</b></td></tr><tr><td>export</td><td port="export">bool | None</td></tr><tr><td>format</td><td port="format">Optional[str]</td></tr><tr><td>display_identifier</td><td port="display_identifier">Optional[str]</td></tr></table>>,
tooltip="ddd.models.objects.A2lObjectOptions

What a declaration asks of the a2l backend. Only that backend interprets it.
&#\
xA;Nothing here changes the generated c or the meaning of the object; a project that
generates no a2l can leave the whole block \
out.
"];
"ddd.ir.ResolvedObject":a2l:e -> "ddd.models.objects.A2lObjectOptions":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.objects.Limits" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>Limits</b></td></tr><tr><td>min</td><td port="min">Union[int, float]</td></tr><tr><td>max</td><td port="max">Union[int, float]</td></tr></table>>,
tooltip="ddd.models.objects.Limits

Physical lower/upper limit of a data object.
"];
"ddd.ir.ResolvedObject":limits:e -> "ddd.models.objects.Limits":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.conversion.Enumerator" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>Enumerator</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>value</td><td port="value">int</td></tr><tr><td>description</td><td port="description">str</td></tr></table>>,
tooltip="ddd.models.conversion.Enumerator

One named value of an enum conversion, and what that value means.
"];
"ddd.models.conversion.EnumConversion":enumerators:e -> "ddd.models.conversion.Enumerator":_root:w [arrowhead=crownone,
arrowtail=nonenone];
}](_images/graphviz-13485eb99304bcd3704f964d7305ce61d2d4d6e0.png)
Show JSON schema
{ "title": "ResolvedObject", "description": "One data object, with every derived property already worked out.", "type": "object", "properties": { "name": { "description": "Name of the object, unique across the whole project; its c and a2l identifier.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "id": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Identity the producer gave this object, which survives a rename of it.\n\nEmpty in a dictionary from format 5 or older, which recorded none: an object that pairs\non nothing pairs on its name, exactly as it did then.", "title": "Id" }, "extensions": { "additionalProperties": { "additionalProperties": true, "type": "object" }, "description": "The blocks of the project's plugins, keyed by plugin name, in resolved form.\n\nEach validated against its plugin's model and dumped back, defaults filled in, so two\ndumps compare on one shape. Empty in a dictionary from format 6 or older, which recorded\nnone, and empty for an object nothing stamped.", "title": "Extensions", "type": "object" }, "kind": { "$ref": "#/$defs/ObjectKind", "description": "Which sort of object this is, taken from the definition that produced it." }, "datatype": { "$ref": "#/$defs/Datatype", "description": "Storage type of one element." }, "description": { "default": "", "description": "What the object is; the a2l long identifier and the comment in the generated c.", "title": "Description", "type": "string" }, "unit": { "default": "", "description": "Physical unit, as the declaring components agreed on it.", "title": "Unit", "type": "string" }, "conversion": { "description": "Always present: the declared conversion, or the identity when none was given.", "discriminator": { "mapping": { "enum": "#/$defs/EnumConversion", "identity": "#/$defs/IdentityConversion", "linear": "#/$defs/LinearConversion", "string": "#/$defs/StringConversion" }, "propertyName": "kind" }, "oneOf": [ { "$ref": "#/$defs/IdentityConversion" }, { "$ref": "#/$defs/LinearConversion" }, { "$ref": "#/$defs/EnumConversion" }, { "$ref": "#/$defs/StringConversion" } ], "title": "Conversion" }, "limits": { "$ref": "#/$defs/Limits", "description": "Always present: the explicit limits, or the range the datatype and conversion imply." }, "shape": { "default": [], "description": "Storage shape, empty for a scalar; for a curve or a map it comes from its axes.\n\nEvery dimension is at least one, like the ``dimensions`` and ``size`` it derives from,\nand every dimension is a resolved number: a dimension stated as the name of a declared\nconstant carries its value here and its name in ``dimensions``.", "items": { "exclusiveMinimum": 0, "type": "integer" }, "title": "Shape", "type": "array" }, "dimensions": { "default": [], "description": "The shape again, each dimension spelled the way the project spells it.\n\nParallel to ``shape``: the same dimensions in the same order, each the number itself or\nthe name of the declared constant that states it - the name under which the generated\ncode declares the array. Empty in a dictionary from format 3 or older, which recorded\nno spellings.", "items": { "anyOf": [ { "maximum": 18446744073709551615, "minimum": 1, "type": "integer" }, { "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "type": "string" } ] }, "title": "Dimensions", "type": "array" }, "init": { "anyOf": [ { "$ref": "#/$defs/InitValue" }, { "type": "null" } ], "default": null, "description": "Raw initial value as the description wrote it, or the text of a string object;\n``null`` means zero initialised.\n\nA list is nested to match ``shape``, one level per dimension. A scalar written for an\narray is carried as the scalar: it initialises every element, and expanding it here\nwould write one literal per element into the dumped dictionary for a value the\ndescription states once. A consumer that needs the elements broadcasts the scalar over\n``shape``, which is what the c backend does to render the initialiser." }, "section": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Linker section the producing declaration placed the object in; ``null`` for the\ntoolchain's defaults.", "title": "Section" }, "raster": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Measurement raster the producing component updates the object in; ``null`` when the\nproject named none. Empty in a dictionary from format 4 or older.", "title": "Raster" }, "point_counts": { "$ref": "#/$defs/PointCounts", "default": "none", "description": "Whether this curve, map or axis stores its point counts ahead of its data: its\nproducing component's ``point_counts``, else the project's. ``none`` for every other kind,\nand in a dictionary from format 8 or older, which never stored any." }, "volatile": { "default": false, "description": "Generate the object ``volatile``: stated by every declaration, on every kind.\n\nCalibration data carries it as ``const volatile``, which is what a value the calibration\ntool changes in a running ecu needs - see the field of the same name on the authored\ndefinition. The default is kept although a definition may no longer omit it, so that a\ndictionary dumped by an older DDD still reads back: an older document is read with the\ndefaults of the format it states, which is what the ``format`` key of this document is\nfor.", "title": "Volatile", "type": "boolean" }, "condition": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Preprocessor condition of the producing declaration, if any.", "title": "Condition" }, "references": { "additionalProperties": { "type": "string" }, "description": "Other objects this one refers to, keyed by field name (``axis``, ``x_axis``, ...).", "title": "References", "type": "object" }, "owner": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Component owning the object; ``null`` only when the project is inconsistent.", "title": "Owner" }, "consumers": { "default": [], "description": "Components declaring the object as an input, sorted; empty when nothing reads it.", "items": { "type": "string" }, "title": "Consumers", "type": "array" }, "local": { "default": false, "description": "Owned exclusively by ``owner``; no other component may declare it.", "title": "Local", "type": "boolean" }, "a2l": { "$ref": "#/$defs/A2lObjectOptions", "default": { "export": null, "format": null, "display_identifier": null }, "description": "What the author asked for in the ``a2l`` block. Only the a2l backend interprets it." } }, "$defs": { "A2lObjectOptions": { "additionalProperties": false, "description": "What a declaration asks of the a2l backend. Only that backend interprets it.\n\nNothing here changes the generated c or the meaning of the object; a project that\ngenerates no a2l can leave the whole block out.", "properties": { "export": { "anyOf": [ { "type": "boolean" }, { "type": "null" } ], "default": null, "description": "Whether the object belongs in the a2l file; omitted, it does.\n\nThe one a2l option any component may state, not only the producer. Which signals a\ncalibration engineer needs to see is not a property of whoever happens to write the\nvariable: a component reading a value from a library it does not own has as good a claim\nto measuring it.\n\nStated by several, the answer is yes if any of them says so, and an object nobody\nmentions is exported: see \"Who asks for an export\" on the definition page.", "title": "Export" }, "format": { "anyOf": [ { "pattern": "^%[0-9]*\\.[0-9]+$", "type": "string" }, { "type": "null" } ], "default": null, "description": "a2l ``FORMAT`` string, e.g. ``\"%8.3\"``: total width, then decimal places.\n\nRefused beside a ``string`` conversion, which has no decimals to display.", "title": "Format" }, "display_identifier": { "anyOf": [ { "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "type": "string" }, { "type": "null" } ], "default": null, "description": "Alternative name shown by the calibration tool.", "title": "Display Identifier" } }, "title": "A2lObjectOptions", "type": "object" }, "Datatype": { "description": "The base datatypes DDD can allocate storage for.", "enum": [ "boolean", "uint8", "sint8", "uint16", "sint16", "uint32", "sint32", "uint64", "sint64", "float32", "float64" ], "title": "Datatype", "type": "string" }, "EnumConversion": { "additionalProperties": false, "description": "A verbal conversion table; the raw value *is* the physical value.\n\nAccepts both the explicit form::\n\n {\"kind\": \"enum\", \"name\": \"StateA\",\n \"enumerators\": [{\"name\": \"STATE_OFF\", \"value\": 0}]}\n\nand the mapping shorthand::\n\n {\"kind\": \"enum\", \"name\": \"StateA\", \"enumerators\": {\"STATE_OFF\": 0}}", "properties": { "kind": { "const": "enum", "default": "enum", "description": "The tag of this kind, which may be left out: a block stating ``enumerators`` or a\n``name`` is an enum.", "title": "Kind", "type": "string" }, "name": { "description": "C identifier of the generated ``typedef enum``; shared enums must agree everywhere.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "enumerators": { "anyOf": [ { "items": { "$ref": "#/$defs/Enumerator" }, "minItems": 1, "type": "array" }, { "additionalProperties": { "maximum": 18446744073709551615, "minimum": -9223372036854775808, "type": "integer" }, "description": "The enumerators as a ``{\"NAME\": value}`` mapping.", "minProperties": 1, "propertyNames": { "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$" }, "type": "object" } ], "description": "The named values, either as objects or as a ``{\"NAME\": value}`` mapping.\n\nTwo of them may not carry the same name, which the mapping form cannot express twice and\nthe list form can: the generated enumeration would not compile, and a calibration tool\nreading the generated table of labels would have two answers for one. Two names sharing a\n*value* is a different matter - it is the C idiom for an alias, reported as\n``enum-duplicate-value`` rather than refused.", "title": "Enumerators" } }, "required": [ "name", "enumerators" ], "title": "EnumConversion", "type": "object" }, "Enumerator": { "additionalProperties": false, "description": "One named value of an enum conversion, and what that value means.", "properties": { "name": { "description": "C identifier of the enumerator; enumerators of all enums share one c namespace.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "value": { "description": "The raw value; two enumerators of one enum sharing one is reported as a warning.\n\n``enum-duplicate-value``, a warning rather than a refusal, because it is legal c and\noccasionally meant as an alias - but the a2l table then offers a calibration tool two\nnames for one reading.\n\nBounded to what 64 bits can hold - no datatype DDD offers stores more - so a value no\nstorage could ever represent is refused here rather than overflowing a comparison once\nit is checked against the c ``int`` every enumerator has to fit, or against the\ndatatype carrying it.\n\nA whole number written without a decimal point: ``4``, not ``4.0``, which the published\nschema accepts and the loader refuses.", "maximum": 18446744073709551615, "minimum": -9223372036854775808, "title": "Value", "type": "integer" }, "description": { "default": "", "description": "What the value means; documentation, not interface.", "title": "Description", "type": "string" } }, "required": [ "name", "value" ], "title": "Enumerator", "type": "object" }, "IdentityConversion": { "additionalProperties": false, "description": "``physical == raw``; stated like any other conversion, ``{}`` its shortest spelling.\n\nNot a default: a definition naming storage by ``datatype`` states this one where raw and\nphysical are the same number, so that the claim is written down rather than left to\nsilence.", "properties": { "kind": { "const": "identity", "default": "identity", "description": "The tag of this kind, which may be left out: an empty block is the identity.", "title": "Kind", "type": "string" } }, "title": "IdentityConversion", "type": "object" }, "InitElement": { "anyOf": [ { "$ref": "#/$defs/InitScalar" }, { "items": { "$ref": "#/$defs/InitElement" }, "type": "array" } ] }, "InitScalar": { "anyOf": [ { "maximum": 18446744073709551615, "minimum": -9223372036854775808, "type": "integer" }, { "type": "boolean" }, { "type": "number" } ] }, "InitValue": { "anyOf": [ { "$ref": "#/$defs/InitScalar" }, { "type": "string" }, { "items": { "$ref": "#/$defs/InitElement" }, "type": "array" } ] }, "Limits": { "additionalProperties": false, "description": "Physical lower/upper limit of a data object.", "properties": { "min": { "anyOf": [ { "maximum": 18446744073709551615, "minimum": -9223372036854775808, "type": "integer" }, { "type": "number" } ], "description": "Smallest physical value the object may take.", "title": "Min" }, "max": { "anyOf": [ { "maximum": 18446744073709551615, "minimum": -9223372036854775808, "type": "integer" }, { "type": "number" } ], "description": "Largest physical value the object may take; at least ``min``.", "title": "Max" } }, "required": [ "min", "max" ], "title": "Limits", "type": "object" }, "LinearConversion": { "additionalProperties": false, "description": "``physical = raw * factor + offset``, the scaling of a fixed point value.", "properties": { "kind": { "const": "linear", "default": "linear", "description": "The tag of this kind, which may be left out: a block stating ``factor`` or ``offset``\nis linear.", "title": "Kind", "type": "string" }, "factor": { "default": 1.0, "description": "Scaling; must not be zero, or nothing could be converted back.", "title": "Factor", "type": "number" }, "offset": { "default": 0.0, "description": "What raw zero stands for, in the physical unit.", "title": "Offset", "type": "number" } }, "title": "LinearConversion", "type": "object" }, "ObjectKind": { "description": "What sort of data object a definition describes.", "enum": [ "measurement", "parameter", "value_block", "curve", "map", "axis" ], "title": "ObjectKind", "type": "string" }, "PointCounts": { "description": "Where an interpolation object stores its number of axis points, if anywhere.", "enum": [ "none", "leading" ], "title": "PointCounts", "type": "string" }, "StringConversion": { "additionalProperties": false, "description": "Bytes read as text: each element of the array holds one character code.\n\nStated on a ``uint8`` or ``sint8`` array of one dimension; the rules sit beside the\ndatatype because the same pair is written in three places. ``kind`` is required here,\nunlike on the other three kinds: a string has no key of its own to be inferred from,\nand ``{}`` is the identity.\n\nThe two mappings are the identity on one byte, so that the derived limits of a string\nare the raw range of its datatype - which is what the a2l record states - and nothing\nthat ranges a conversion has to know that a string exists. A byte has no reading of its\nown, so no reading is produced for it, as for the identity.", "properties": { "kind": { "const": "string", "description": "The tag of this kind, which is required: a string has no key of its own to be\nrecognised by, so nothing else would tell it from the identity.", "title": "Kind", "type": "string" } }, "required": [ "kind" ], "title": "StringConversion", "type": "object" } }, "additionalProperties": false, "required": [ "name", "kind", "datatype", "conversion", "limits" ] }
- Fields:
- field name: Identifier [Required]
Name of the object, unique across the whole project; its c and a2l identifier.
- field id: str | None = None
Identity the producer gave this object, which survives a rename of it.
Empty in a dictionary from format 5 or older, which recorded none: an object that pairs on nothing pairs on its name, exactly as it did then.
Identity the producer gave this object, which survives a rename of it.
Empty in a dictionary from format 5 or older, which recorded none: an object that pairs on nothing pairs on its name, exactly as it did then.
- field extensions: dict[str, dict[str, Any]] [Optional]
The blocks of the project’s plugins, keyed by plugin name, in resolved form.
Each validated against its plugin’s model and dumped back, defaults filled in, so two dumps compare on one shape. Empty in a dictionary from format 6 or older, which recorded none, and empty for an object nothing stamped.
The blocks of the project’s plugins, keyed by plugin name, in resolved form.
Each validated against its plugin’s model and dumped back, defaults filled in, so two dumps compare on one shape. Empty in a dictionary from format 6 or older, which recorded none, and empty for an object nothing stamped.
- field kind: ObjectKind [Required]
Which sort of object this is, taken from the definition that produced it.
- field datatype: Datatype [Required]
Storage type of one element.
- field description: str = ''
What the object is; the a2l long identifier and the comment in the generated c.
- field unit: str = ''
Physical unit, as the declaring components agreed on it.
- field conversion: Conversion [Required]
Always present: the declared conversion, or the identity when none was given.
- field limits: Limits [Required]
Always present: the explicit limits, or the range the datatype and conversion imply.
- field shape: tuple[PositiveInt, ...] = ()
Storage shape, empty for a scalar; for a curve or a map it comes from its axes.
Every dimension is at least one, like the
dimensionsandsizeit derives from, and every dimension is a resolved number: a dimension stated as the name of a declared constant carries its value here and its name indimensions.Storage shape, empty for a scalar; for a curve or a map it comes from its axes.
Every dimension is at least one, like the
dimensionsandsizeit derives from, and every dimension is a resolved number: a dimension stated as the name of a declared constant carries its value here and its name indimensions.
- field dimensions: tuple[Dimension, ...] = ()
The shape again, each dimension spelled the way the project spells it.
Parallel to
shape: the same dimensions in the same order, each the number itself or the name of the declared constant that states it - the name under which the generated code declares the array. Empty in a dictionary from format 3 or older, which recorded no spellings.The shape again, each dimension spelled the way the project spells it.
Parallel to
shape: the same dimensions in the same order, each the number itself or the name of the declared constant that states it - the name under which the generated code declares the array. Empty in a dictionary from format 3 or older, which recorded no spellings.
- field init: InitValue | None = None
Raw initial value as the description wrote it, or the text of a string object;
nullmeans zero initialised.A list is nested to match
shape, one level per dimension. A scalar written for an array is carried as the scalar: it initialises every element, and expanding it here would write one literal per element into the dumped dictionary for a value the description states once. A consumer that needs the elements broadcasts the scalar overshape, which is what the c backend does to render the initialiser.Raw initial value as the description wrote it, or the text of a string object;
nullmeans zero initialised.A list is nested to match
shape, one level per dimension. A scalar written for an array is carried as the scalar: it initialises every element, and expanding it here would write one literal per element into the dumped dictionary for a value the description states once. A consumer that needs the elements broadcasts the scalar overshape, which is what the c backend does to render the initialiser.
- field section: str | None = None
Linker section the producing declaration placed the object in;
nullfor the toolchain’s defaults.Linker section the producing declaration placed the object in;
nullfor the toolchain’s defaults.
- field raster: str | None = None
Measurement raster the producing component updates the object in;
nullwhen the project named none. Empty in a dictionary from format 4 or older.Measurement raster the producing component updates the object in;
nullwhen the project named none. Empty in a dictionary from format 4 or older.
- field point_counts: PointCounts = PointCounts.NONE
Whether this curve, map or axis stores its point counts ahead of its data: its producing component’s
point_counts, else the project’s.nonefor every other kind, and in a dictionary from format 8 or older, which never stored any.Whether this curve, map or axis stores its point counts ahead of its data: its producing component’s
point_counts, else the project’s.nonefor every other kind, and in a dictionary from format 8 or older, which never stored any.
- field volatile: bool = False
Generate the object
volatile: stated by every declaration, on every kind.Calibration data carries it as
const volatile, which is what a value the calibration tool changes in a running ecu needs - see the field of the same name on the authored definition. The default is kept although a definition may no longer omit it, so that a dictionary dumped by an older DDD still reads back: an older document is read with the defaults of the format it states, which is what theformatkey of this document is for.Generate the object
volatile: stated by every declaration, on every kind.Calibration data carries it as
const volatile, which is what a value the calibration tool changes in a running ecu needs - see the field of the same name on the authored definition. The default is kept although a definition may no longer omit it, so that a dictionary dumped by an older DDD still reads back: an older document is read with the defaults of the format it states, which is what theformatkey of this document is for.
- field condition: str | None = None
Preprocessor condition of the producing declaration, if any.
- field references: dict[str, str] [Optional]
Other objects this one refers to, keyed by field name (
axis,x_axis, …).
- field owner: str | None = None
Component owning the object;
nullonly when the project is inconsistent.
- field consumers: tuple[str, ...] = ()
Components declaring the object as an input, sorted; empty when nothing reads it.
- field local: bool = False
Owned exclusively by
owner; no other component may declare it.
- field a2l: A2lObjectOptions = A2lObjectOptions(export=None, format=None, display_identifier=None)
What the author asked for in the
a2lblock. Only the a2l backend interprets it.
- pydantic model ResolvedComponent[source]
A component and the objects it declares.
![digraph "Entity Relationship Diagram created by erdantic" {
graph [fontcolor=gray66,
fontname="Times New Roman,Times,Liberation Serif,serif",
fontsize=9,
nodesep=0.5,
rankdir=LR,
ranksep=1.5
];
node [fontname="Times New Roman,Times,Liberation Serif,serif",
fontsize=14,
label="\N",
shape=plain
];
edge [dir=both];
"ddd.ir.ComponentDeclaration" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>ComponentDeclaration</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>scope</td><td port="scope">Scope</td></tr><tr><td>condition</td><td port="condition">str | None</td></tr></table>>,
tooltip="ddd.ir.ComponentDeclaration

One entry of a component interface, in the order the component declared it.

A reference \
to an object rather than the object itself: the definition lives once, under
``objects``, and is the one the producing component \
gave. Two components declaring the
same name appear here twice and in ``objects`` once.
"];
"ddd.ir.ResolvedComponent" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>ResolvedComponent</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>description</td><td port="description">str</td></tr><tr><td>source</td><td port="source">str</td></tr><tr><td>declarations</td><td port="declarations">tuple[ComponentDeclaration, ...]</td></tr></table>>,
tooltip="ddd.ir.ResolvedComponent

A component and the objects it declares.
"];
"ddd.ir.ResolvedComponent":declarations:e -> "ddd.ir.ComponentDeclaration":_root:w [arrowhead=crownone,
arrowtail=nonenone];
}](_images/graphviz-af15c370f270848132627844b1d23f49c90d5c48.png)
Show JSON schema
{ "title": "ResolvedComponent", "description": "A component and the objects it declares.", "type": "object", "properties": { "name": { "description": "Name of the component, unique within the project.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "description": { "default": "", "description": "Free text from the component description, offered to the templates.", "title": "Description", "type": "string" }, "source": { "default": "", "description": "File name of the description file, for reference in generated comments.\n\nThe name alone, without the directories above it: a dictionary dumped from two checkouts\nof one project is otherwise two different documents, and the banner of a generated file\nwould carry the path of whoever's machine generated it.", "title": "Source", "type": "string" }, "declarations": { "default": [], "description": "The interface of the component, in the order it declared it.", "items": { "$ref": "#/$defs/ComponentDeclaration" }, "title": "Declarations", "type": "array" } }, "$defs": { "ComponentDeclaration": { "additionalProperties": false, "description": "One entry of a component interface, in the order the component declared it.\n\nA reference to an object rather than the object itself: the definition lives once, under\n``objects``, and is the one the producing component gave. Two components declaring the\nsame name appear here twice and in ``objects`` once.", "properties": { "name": { "description": "Name of the declared object; a key into the ``objects`` list of the dictionary.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "scope": { "$ref": "#/$defs/Scope", "description": "How this component uses the object: ``input``, ``output`` or ``local``." }, "condition": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Preprocessor expression this component guarded the declaration with, if any.", "title": "Condition" } }, "required": [ "name", "scope" ], "title": "ComponentDeclaration", "type": "object" }, "Scope": { "description": "Direction of a variable with respect to the declaring component.", "enum": [ "input", "output", "local" ], "title": "Scope", "type": "string" } }, "additionalProperties": false, "required": [ "name" ] }
- Fields:
- field name: Identifier [Required]
Name of the component, unique within the project.
- field description: str = ''
Free text from the component description, offered to the templates.
- field source: str = ''
File name of the description file, for reference in generated comments.
The name alone, without the directories above it: a dictionary dumped from two checkouts of one project is otherwise two different documents, and the banner of a generated file would carry the path of whoever’s machine generated it.
File name of the description file, for reference in generated comments.
The name alone, without the directories above it: a dictionary dumped from two checkouts of one project is otherwise two different documents, and the banner of a generated file would carry the path of whoever’s machine generated it.
- field declarations: tuple[ComponentDeclaration, ...] = ()
The interface of the component, in the order it declared it.
- pydantic model ComponentDeclaration[source]
One entry of a component interface, in the order the component declared it.
A reference to an object rather than the object itself: the definition lives once, under
objects, and is the one the producing component gave. Two components declaring the same name appear here twice and inobjectsonce.![digraph "Entity Relationship Diagram created by erdantic" {
graph [fontcolor=gray66,
fontname="Times New Roman,Times,Liberation Serif,serif",
fontsize=9,
nodesep=0.5,
rankdir=LR,
ranksep=1.5
];
node [fontname="Times New Roman,Times,Liberation Serif,serif",
fontsize=14,
label="\N",
shape=plain
];
edge [dir=both];
"ddd.ir.ComponentDeclaration" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>ComponentDeclaration</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>scope</td><td port="scope">Scope</td></tr><tr><td>condition</td><td port="condition">str | None</td></tr></table>>,
tooltip="ddd.ir.ComponentDeclaration

One entry of a component interface, in the order the component declared it.

A reference \
to an object rather than the object itself: the definition lives once, under
``objects``, and is the one the producing component \
gave. Two components declaring the
same name appear here twice and in ``objects`` once.
"];
}](_images/graphviz-8edead6011e89bd06e5b266bc785496f43b1dba6.png)
Show JSON schema
{ "title": "ComponentDeclaration", "description": "One entry of a component interface, in the order the component declared it.\n\nA reference to an object rather than the object itself: the definition lives once, under\n``objects``, and is the one the producing component gave. Two components declaring the\nsame name appear here twice and in ``objects`` once.", "type": "object", "properties": { "name": { "description": "Name of the declared object; a key into the ``objects`` list of the dictionary.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "scope": { "$ref": "#/$defs/Scope", "description": "How this component uses the object: ``input``, ``output`` or ``local``." }, "condition": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Preprocessor expression this component guarded the declaration with, if any.", "title": "Condition" } }, "$defs": { "Scope": { "description": "Direction of a variable with respect to the declaring component.", "enum": [ "input", "output", "local" ], "title": "Scope", "type": "string" } }, "additionalProperties": false, "required": [ "name", "scope" ] }
- field name: Identifier [Required]
Name of the declared object; a key into the
objectslist of the dictionary.
- field scope: Scope [Required]
How this component uses the object:
input,outputorlocal.
- field condition: str | None = None
Preprocessor expression this component guarded the declaration with, if any.
- pydantic model ResolvedRaster[source]
One declared daq event, as the dictionary publishes it.
![digraph "Entity Relationship Diagram created by erdantic" {
graph [fontcolor=gray66,
fontname="Times New Roman,Times,Liberation Serif,serif",
fontsize=9,
nodesep=0.5,
rankdir=LR,
ranksep=1.5
];
node [fontname="Times New Roman,Times,Liberation Serif,serif",
fontsize=14,
label="\N",
shape=plain
];
edge [dir=both];
"ddd.ir.ResolvedRaster" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>ResolvedRaster</b></td></tr><tr><td>raster</td><td port="raster">str</td></tr><tr><td>event</td><td port="event">int</td></tr><tr><td>cycle</td><td port="cycle">str | None</td></tr><tr><td>cycle_ns</td><td port="cycle_ns">int | None</td></tr><tr><td>description</td><td port="description">str</td></tr></table>>,
tooltip="ddd.ir.ResolvedRaster

One declared daq event, as the dictionary publishes it.
"];
}](_images/graphviz-5439111976247f13bc9c2447eaba366bd687c39e.png)
Show JSON schema
{ "title": "ResolvedRaster", "description": "One declared daq event, as the dictionary publishes it.", "type": "object", "properties": { "raster": { "description": "Name the objects refer to, and the short name of the xcp event.", "title": "Raster", "type": "string" }, "event": { "description": "The xcp event channel number.", "title": "Event", "type": "integer" }, "cycle": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "The period as the project wrote it: ``10ms``. Absent when the event is not cyclic.", "title": "Cycle" }, "cycle_ns": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "default": null, "description": "The same period in nanoseconds, resolved so that a consumer never parses the spelling.\n\nBoth are kept for the reason ``shape`` and ``dimensions`` both are: the authored form is\nwhat a reader recognises, and the number is what a consumer computes with.", "title": "Cycle Ns" }, "description": { "default": "", "description": "Free text from the declaration; the long name of the eventual ``EVENT``.", "title": "Description", "type": "string" } }, "additionalProperties": false, "required": [ "raster", "event" ] }
- field raster: str [Required]
Name the objects refer to, and the short name of the xcp event.
- field event: int [Required]
The xcp event channel number.
- field cycle: str | None = None
The period as the project wrote it:
10ms. Absent when the event is not cyclic.
- field cycle_ns: int | None = None
The same period in nanoseconds, resolved so that a consumer never parses the spelling.
Both are kept for the reason
shapeanddimensionsboth are: the authored form is what a reader recognises, and the number is what a consumer computes with.The same period in nanoseconds, resolved so that a consumer never parses the spelling.
Both are kept for the reason
shapeanddimensionsboth are: the authored form is what a reader recognises, and the number is what a consumer computes with.
- field description: str = ''
Free text from the declaration; the long name of the eventual
EVENT.
- pydantic model ResolvedStruct[source]
One structure, in an order a c file can be written out in.
The order of
DataDictionary.typesmatters and is not alphabetical: a structure appears after every structure it nests, because a c compiler needs the nested one to be complete first. The members keep the order the author wrote them in, which is the order the compiler lays them out.![digraph "Entity Relationship Diagram created by erdantic" {
graph [fontcolor=gray66,
fontname="Times New Roman,Times,Liberation Serif,serif",
fontsize=9,
nodesep=0.5,
rankdir=LR,
ranksep=1.5
];
node [fontname="Times New Roman,Times,Liberation Serif,serif",
fontsize=14,
label="\N",
shape=plain
];
edge [dir=both];
"ddd.ir.ResolvedMember" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>ResolvedMember</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>description</td><td port="description">str</td></tr><tr><td>datatype</td><td port="datatype">Datatype | None</td></tr><tr><td>type</td><td port="type">str | None</td></tr><tr><td>external</td><td port="external">str | None</td></tr><tr><td>header</td><td port="header">str | None</td></tr><tr><td>dimensions</td><td port="dimensions">tuple[Union[int, str], ...]</td></tr><tr><td>bits</td><td port="bits">int | None</td></tr></table>>,
tooltip="ddd.ir.ResolvedMember

One member of a structure, as the c templates need it to declare the member.

Only what a \
declaration takes. The meaning of the member - its unit, its conversion, its
limits - travels with the *leaf* instead, because \
that is the form the a2l consumes and
there is no second place a reader should have to look.

Exactly one of ``datatype``, ``\
type`` and ``external`` is stated: a member holds a value
of a base datatype, is a structure, or is storage of a type DDD does \
not describe. A
member stating none of them would be storage with no size, no meaning and no name, which
a consumer of this \
document has nothing to do with.
"];
"ddd.ir.ResolvedStruct" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>ResolvedStruct</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>description</td><td port="description">str</td></tr><tr><td>members</td><td port="members">tuple[ResolvedMember, ...]</td></tr></table>>,
tooltip="ddd.ir.ResolvedStruct

One structure, in an order a c file can be written out in.

The order of :attr:`DataDictionary.types` \
matters and is not alphabetical: a structure
appears after every structure it nests, because a c compiler needs the nested one \
to be
complete first. The members keep the order the author wrote them in, which is the order the
compiler lays them out.&#\
xA;"];
"ddd.ir.ResolvedStruct":members:e -> "ddd.ir.ResolvedMember":_root:w [arrowhead=crownone,
arrowtail=nonenone];
}](_images/graphviz-1885264906ce8e92fc76b96e81b114523be59836.png)
Show JSON schema
{ "title": "ResolvedStruct", "description": "One structure, in an order a c file can be written out in.\n\nThe order of :attr:`DataDictionary.types` matters and is not alphabetical: a structure\nappears after every structure it nests, because a c compiler needs the nested one to be\ncomplete first. The members keep the order the author wrote them in, which is the order the\ncompiler lays them out.", "type": "object", "properties": { "name": { "description": "Name of the structure, which is the name of the generated typedef.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "description": { "default": "", "description": "What the structure is, for a comment above it.", "title": "Description", "type": "string" }, "members": { "default": [], "description": "The members, in declaration order.", "items": { "$ref": "#/$defs/ResolvedMember" }, "title": "Members", "type": "array" } }, "$defs": { "Datatype": { "description": "The base datatypes DDD can allocate storage for.", "enum": [ "boolean", "uint8", "sint8", "uint16", "sint16", "uint32", "sint32", "uint64", "sint64", "float32", "float64" ], "title": "Datatype", "type": "string" }, "ResolvedMember": { "additionalProperties": false, "description": "One member of a structure, as the c templates need it to declare the member.\n\nOnly what a declaration takes. The meaning of the member - its unit, its conversion, its\nlimits - travels with the *leaf* instead, because that is the form the a2l consumes and\nthere is no second place a reader should have to look.\n\nExactly one of ``datatype``, ``type`` and ``external`` is stated: a member holds a value\nof a base datatype, is a structure, or is storage of a type DDD does not describe. A\nmember stating none of them would be storage with no size, no meaning and no name, which\na consumer of this document has nothing to do with.", "properties": { "name": { "description": "Name of the member, as it is written in the c struct.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "description": { "default": "", "description": "What the member is, for a comment beside its declaration.", "title": "Description", "type": "string" }, "datatype": { "anyOf": [ { "$ref": "#/$defs/Datatype" }, { "type": "null" } ], "default": null, "description": "Storage of the member when it is a base one; ``null`` when it names a declared type." }, "type": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Name of the structure this member is, when it is one; ``null`` when it is a datatype.\n\nThe name as the types file spells it, which in a dictionary carrying an ``unknown-type``\nerror may be a name no ``types`` entry answers: the member says what it was declared as,\nand the finding says that nothing declares it.", "title": "Type" }, "external": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Name of the external type this member is, when it is one; ``null`` otherwise.\n\nAn external type is one DDD does not declare - a hand written header defines it - so the\nmember is opaque storage: it appears in the generated structure verbatim, spelled with\nthis name, and contributes no leaf, because DDD knows neither its layout nor its meaning.", "title": "External" }, "header": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "The header defining the external type, spelled the way the generated inclusion writes\nit: ``my_driver.h`` for the quoted form, ``<os_types.h>`` for the angle form. Stated\nexactly when ``external`` is, and carried on the member so a consumer of the dictionary\nnever has to resolve the type name a second time.", "title": "Header" }, "dimensions": { "default": [], "description": "Array dimensions, empty for a scalar, each spelled the way the member spells it.\n\nA number, or the name of a declared constant, exactly as ``dimensions`` is spelled on\nan object or an instance. A member carries no numeric ``shape`` beside it: it is the\ndeclaration side of the answer, and the resolved numbers live on the leaves of every\ninstantiated structure, with the value of a named dimension in the dictionary's\n``constants``.", "items": { "anyOf": [ { "maximum": 18446744073709551615, "minimum": 1, "type": "integer" }, { "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "type": "string" } ] }, "title": "Dimensions", "type": "array" }, "bits": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "default": null, "description": "Width in bits when the member is a c bitfield; ``null`` when it is not.", "title": "Bits" } }, "required": [ "name" ], "title": "ResolvedMember", "type": "object" } }, "additionalProperties": false, "required": [ "name" ] }
- field name: Identifier [Required]
Name of the structure, which is the name of the generated typedef.
- field description: str = ''
What the structure is, for a comment above it.
- field members: tuple[ResolvedMember, ...] = ()
The members, in declaration order.
- pydantic model ResolvedMember[source]
One member of a structure, as the c templates need it to declare the member.
Only what a declaration takes. The meaning of the member - its unit, its conversion, its limits - travels with the leaf instead, because that is the form the a2l consumes and there is no second place a reader should have to look.
Exactly one of
datatype,typeandexternalis stated: a member holds a value of a base datatype, is a structure, or is storage of a type DDD does not describe. A member stating none of them would be storage with no size, no meaning and no name, which a consumer of this document has nothing to do with.![digraph "Entity Relationship Diagram created by erdantic" {
graph [fontcolor=gray66,
fontname="Times New Roman,Times,Liberation Serif,serif",
fontsize=9,
nodesep=0.5,
rankdir=LR,
ranksep=1.5
];
node [fontname="Times New Roman,Times,Liberation Serif,serif",
fontsize=14,
label="\N",
shape=plain
];
edge [dir=both];
"ddd.ir.ResolvedMember" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>ResolvedMember</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>description</td><td port="description">str</td></tr><tr><td>datatype</td><td port="datatype">Datatype | None</td></tr><tr><td>type</td><td port="type">str | None</td></tr><tr><td>external</td><td port="external">str | None</td></tr><tr><td>header</td><td port="header">str | None</td></tr><tr><td>dimensions</td><td port="dimensions">tuple[Union[int, str], ...]</td></tr><tr><td>bits</td><td port="bits">int | None</td></tr></table>>,
tooltip="ddd.ir.ResolvedMember

One member of a structure, as the c templates need it to declare the member.

Only what a \
declaration takes. The meaning of the member - its unit, its conversion, its
limits - travels with the *leaf* instead, because \
that is the form the a2l consumes and
there is no second place a reader should have to look.

Exactly one of ``datatype``, ``\
type`` and ``external`` is stated: a member holds a value
of a base datatype, is a structure, or is storage of a type DDD does \
not describe. A
member stating none of them would be storage with no size, no meaning and no name, which
a consumer of this \
document has nothing to do with.
"];
}](_images/graphviz-64d179e526ac6f9ae914fda19cbd93d335dd49f0.png)
Show JSON schema
{ "title": "ResolvedMember", "description": "One member of a structure, as the c templates need it to declare the member.\n\nOnly what a declaration takes. The meaning of the member - its unit, its conversion, its\nlimits - travels with the *leaf* instead, because that is the form the a2l consumes and\nthere is no second place a reader should have to look.\n\nExactly one of ``datatype``, ``type`` and ``external`` is stated: a member holds a value\nof a base datatype, is a structure, or is storage of a type DDD does not describe. A\nmember stating none of them would be storage with no size, no meaning and no name, which\na consumer of this document has nothing to do with.", "type": "object", "properties": { "name": { "description": "Name of the member, as it is written in the c struct.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "description": { "default": "", "description": "What the member is, for a comment beside its declaration.", "title": "Description", "type": "string" }, "datatype": { "anyOf": [ { "$ref": "#/$defs/Datatype" }, { "type": "null" } ], "default": null, "description": "Storage of the member when it is a base one; ``null`` when it names a declared type." }, "type": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Name of the structure this member is, when it is one; ``null`` when it is a datatype.\n\nThe name as the types file spells it, which in a dictionary carrying an ``unknown-type``\nerror may be a name no ``types`` entry answers: the member says what it was declared as,\nand the finding says that nothing declares it.", "title": "Type" }, "external": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Name of the external type this member is, when it is one; ``null`` otherwise.\n\nAn external type is one DDD does not declare - a hand written header defines it - so the\nmember is opaque storage: it appears in the generated structure verbatim, spelled with\nthis name, and contributes no leaf, because DDD knows neither its layout nor its meaning.", "title": "External" }, "header": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "The header defining the external type, spelled the way the generated inclusion writes\nit: ``my_driver.h`` for the quoted form, ``<os_types.h>`` for the angle form. Stated\nexactly when ``external`` is, and carried on the member so a consumer of the dictionary\nnever has to resolve the type name a second time.", "title": "Header" }, "dimensions": { "default": [], "description": "Array dimensions, empty for a scalar, each spelled the way the member spells it.\n\nA number, or the name of a declared constant, exactly as ``dimensions`` is spelled on\nan object or an instance. A member carries no numeric ``shape`` beside it: it is the\ndeclaration side of the answer, and the resolved numbers live on the leaves of every\ninstantiated structure, with the value of a named dimension in the dictionary's\n``constants``.", "items": { "anyOf": [ { "maximum": 18446744073709551615, "minimum": 1, "type": "integer" }, { "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "type": "string" } ] }, "title": "Dimensions", "type": "array" }, "bits": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "default": null, "description": "Width in bits when the member is a c bitfield; ``null`` when it is not.", "title": "Bits" } }, "$defs": { "Datatype": { "description": "The base datatypes DDD can allocate storage for.", "enum": [ "boolean", "uint8", "sint8", "uint16", "sint16", "uint32", "sint32", "uint64", "sint64", "float32", "float64" ], "title": "Datatype", "type": "string" } }, "additionalProperties": false, "required": [ "name" ] }
- Fields:
- field name: Identifier [Required]
Name of the member, as it is written in the c struct.
- field description: str = ''
What the member is, for a comment beside its declaration.
- field datatype: Datatype | None = None
Storage of the member when it is a base one;
nullwhen it names a declared type.
- field type: str | None = None
Name of the structure this member is, when it is one;
nullwhen it is a datatype.The name as the types file spells it, which in a dictionary carrying an
unknown-typeerror may be a name notypesentry answers: the member says what it was declared as, and the finding says that nothing declares it.Name of the structure this member is, when it is one;
nullwhen it is a datatype.The name as the types file spells it, which in a dictionary carrying an
unknown-typeerror may be a name notypesentry answers: the member says what it was declared as, and the finding says that nothing declares it.
- field external: str | None = None
Name of the external type this member is, when it is one;
nullotherwise.An external type is one DDD does not declare - a hand written header defines it - so the member is opaque storage: it appears in the generated structure verbatim, spelled with this name, and contributes no leaf, because DDD knows neither its layout nor its meaning.
Name of the external type this member is, when it is one;
nullotherwise.An external type is one DDD does not declare - a hand written header defines it - so the member is opaque storage: it appears in the generated structure verbatim, spelled with this name, and contributes no leaf, because DDD knows neither its layout nor its meaning.
- field header: str | None = None
The header defining the external type, spelled the way the generated inclusion writes it:
my_driver.hfor the quoted form,<os_types.h>for the angle form. Stated exactly whenexternalis, and carried on the member so a consumer of the dictionary never has to resolve the type name a second time.The header defining the external type, spelled the way the generated inclusion writes it:
my_driver.hfor the quoted form,<os_types.h>for the angle form. Stated exactly whenexternalis, and carried on the member so a consumer of the dictionary never has to resolve the type name a second time.
- field dimensions: tuple[Dimension, ...] = ()
Array dimensions, empty for a scalar, each spelled the way the member spells it.
A number, or the name of a declared constant, exactly as
dimensionsis spelled on an object or an instance. A member carries no numericshapebeside it: it is the declaration side of the answer, and the resolved numbers live on the leaves of every instantiated structure, with the value of a named dimension in the dictionary’sconstants.Array dimensions, empty for a scalar, each spelled the way the member spells it.
A number, or the name of a declared constant, exactly as
dimensionsis spelled on an object or an instance. A member carries no numericshapebeside it: it is the declaration side of the answer, and the resolved numbers live on the leaves of every instantiated structure, with the value of a named dimension in the dictionary’sconstants.
- field bits: int | None = None
Width in bits when the member is a c bitfield;
nullwhen it is not.
- pydantic model ResolvedInstance[source]
One variable whose datatype is a structure.
Kept apart from
ResolvedObjectrather than widening it: an object with no datatype and no limits would turn every reader of those two fields into a branch, and they are read unconditionally in a dozen places on the strength of always being there.![digraph "Entity Relationship Diagram created by erdantic" {
graph [fontcolor=gray66,
fontname="Times New Roman,Times,Liberation Serif,serif",
fontsize=9,
nodesep=0.5,
rankdir=LR,
ranksep=1.5
];
node [fontname="Times New Roman,Times,Liberation Serif,serif",
fontsize=14,
label="\N",
shape=plain
];
edge [dir=both];
"ddd.ir.ResolvedInstance" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>ResolvedInstance</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>id</td><td port="id">str | None</td></tr><tr><td>extensions</td><td port="extensions">dict[str, dict[str, Any]]</td></tr><tr><td>type</td><td port="type">str</td></tr><tr><td>kind</td><td port="kind">ObjectKind</td></tr><tr><td>description</td><td port="description">str</td></tr><tr><td>shape</td><td port="shape">tuple[int, ...]</td></tr><tr><td>dimensions</td><td port="dimensions">tuple[Union[int, str], ...]</td></tr><tr><td>volatile</td><td port="volatile">bool</td></tr><tr><td>section</td><td port="section">str | None</td></tr><tr><td>raster</td><td port="raster">str | None</td></tr><tr><td>condition</td><td port="condition">str | None</td></tr><tr><td>owner</td><td port="owner">str | None</td></tr><tr><td>consumers</td><td port="consumers">tuple[str, ...]</td></tr><tr><td>local</td><td port="local">bool</td></tr><tr><td>a2l</td><td port="a2l">A2lObjectOptions</td></tr></table>>,
tooltip="ddd.ir.ResolvedInstance

One variable whose datatype is a structure.

Kept apart from :class:`ResolvedObject` rather \
than widening it: an object with no datatype
and no limits would turn every reader of those two fields into a branch, and they \
are read
unconditionally in a dozen places on the strength of always being there.
"];
"ddd.models.objects.A2lObjectOptions" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>A2lObjectOptions</b></td></tr><tr><td>export</td><td port="export">bool | None</td></tr><tr><td>format</td><td port="format">Optional[str]</td></tr><tr><td>display_identifier</td><td port="display_identifier">Optional[str]</td></tr></table>>,
tooltip="ddd.models.objects.A2lObjectOptions

What a declaration asks of the a2l backend. Only that backend interprets it.
&#\
xA;Nothing here changes the generated c or the meaning of the object; a project that
generates no a2l can leave the whole block \
out.
"];
"ddd.ir.ResolvedInstance":a2l:e -> "ddd.models.objects.A2lObjectOptions":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
}](_images/graphviz-c45487c93d07317536b36e68d1df9dc4ec0ee871.png)
Show JSON schema
{ "title": "ResolvedInstance", "description": "One variable whose datatype is a structure.\n\nKept apart from :class:`ResolvedObject` rather than widening it: an object with no datatype\nand no limits would turn every reader of those two fields into a branch, and they are read\nunconditionally in a dozen places on the strength of always being there.", "type": "object", "properties": { "name": { "description": "Name of the variable; its c identifier and the root of every leaf path.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "id": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Identity the producer gave this object, which survives a rename of it.\n\nEmpty in a dictionary from format 5 or older, which recorded none: an object that pairs\non nothing pairs on its name, exactly as it did then.", "title": "Id" }, "extensions": { "additionalProperties": { "additionalProperties": true, "type": "object" }, "description": "The blocks of the project's plugins, keyed by plugin name, in resolved form.\n\nEach validated against its plugin's model and dumped back, defaults filled in, so two\ndumps compare on one shape. Empty in a dictionary from format 6 or older, which recorded\nnone, and empty for an object nothing stamped.", "title": "Extensions", "type": "object" }, "type": { "description": "Name of the structure it is, which is the c type of the declaration.", "title": "Type", "type": "string" }, "kind": { "$ref": "#/$defs/ObjectKind", "description": "``measurement`` or ``parameter``: what the whole object is, and so how it is qualified." }, "description": { "default": "", "description": "What the object is; the comment in the generated c.", "title": "Description", "type": "string" }, "shape": { "default": [], "description": "Array dimensions of the variable itself, empty for a single structure.\n\nAn array of structures reaches the a2l as its elements: there is no one address that\ndescribes ``cell[0].raw`` and ``cell[1].raw`` at once, so each element contributes its own\nleaves at its own path. Every dimension is a resolved number; the spelling is in\n``dimensions``.", "items": { "exclusiveMinimum": 0, "type": "integer" }, "title": "Shape", "type": "array" }, "dimensions": { "default": [], "description": "The shape again, each dimension spelled the way the declaration spells it.\n\nParallel to ``shape`` exactly as on a plain object: the number, or the name of the\ndeclared constant the generated code declares the array by. Empty in a dictionary from\nformat 3 or older.", "items": { "anyOf": [ { "maximum": 18446744073709551615, "minimum": 1, "type": "integer" }, { "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "type": "string" } ] }, "title": "Dimensions", "type": "array" }, "volatile": { "default": false, "description": "Whether the declaration carries ``volatile``, which qualifies the whole object.", "title": "Volatile", "type": "boolean" }, "section": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Linker section the whole structure is placed in; its members have no placement\nof their own.", "title": "Section" }, "raster": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Measurement raster the producing component updates the object in; ``null`` when the\nproject named none. Empty in a dictionary from format 4 or older.", "title": "Raster" }, "condition": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Preprocessor condition of the producing declaration, if any.", "title": "Condition" }, "owner": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Component owning the object; ``null`` only when the project is inconsistent.", "title": "Owner" }, "consumers": { "default": [], "description": "Components declaring the object as an input, sorted.", "items": { "type": "string" }, "title": "Consumers", "type": "array" }, "local": { "default": false, "description": "Owned exclusively by ``owner``; no other component may declare it.", "title": "Local", "type": "boolean" }, "a2l": { "$ref": "#/$defs/A2lObjectOptions", "default": { "export": null, "format": null, "display_identifier": null }, "description": "What the whole object asks of the a2l; a member may ask for more of its own." } }, "$defs": { "A2lObjectOptions": { "additionalProperties": false, "description": "What a declaration asks of the a2l backend. Only that backend interprets it.\n\nNothing here changes the generated c or the meaning of the object; a project that\ngenerates no a2l can leave the whole block out.", "properties": { "export": { "anyOf": [ { "type": "boolean" }, { "type": "null" } ], "default": null, "description": "Whether the object belongs in the a2l file; omitted, it does.\n\nThe one a2l option any component may state, not only the producer. Which signals a\ncalibration engineer needs to see is not a property of whoever happens to write the\nvariable: a component reading a value from a library it does not own has as good a claim\nto measuring it.\n\nStated by several, the answer is yes if any of them says so, and an object nobody\nmentions is exported: see \"Who asks for an export\" on the definition page.", "title": "Export" }, "format": { "anyOf": [ { "pattern": "^%[0-9]*\\.[0-9]+$", "type": "string" }, { "type": "null" } ], "default": null, "description": "a2l ``FORMAT`` string, e.g. ``\"%8.3\"``: total width, then decimal places.\n\nRefused beside a ``string`` conversion, which has no decimals to display.", "title": "Format" }, "display_identifier": { "anyOf": [ { "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "type": "string" }, { "type": "null" } ], "default": null, "description": "Alternative name shown by the calibration tool.", "title": "Display Identifier" } }, "title": "A2lObjectOptions", "type": "object" }, "ObjectKind": { "description": "What sort of data object a definition describes.", "enum": [ "measurement", "parameter", "value_block", "curve", "map", "axis" ], "title": "ObjectKind", "type": "string" } }, "additionalProperties": false, "required": [ "name", "type", "kind" ] }
- Fields:
- field name: Identifier [Required]
Name of the variable; its c identifier and the root of every leaf path.
- field id: str | None = None
Identity the producer gave this object, which survives a rename of it.
Empty in a dictionary from format 5 or older, which recorded none: an object that pairs on nothing pairs on its name, exactly as it did then.
Identity the producer gave this object, which survives a rename of it.
Empty in a dictionary from format 5 or older, which recorded none: an object that pairs on nothing pairs on its name, exactly as it did then.
- field extensions: dict[str, dict[str, Any]] [Optional]
The blocks of the project’s plugins, keyed by plugin name, in resolved form.
Each validated against its plugin’s model and dumped back, defaults filled in, so two dumps compare on one shape. Empty in a dictionary from format 6 or older, which recorded none, and empty for an object nothing stamped.
The blocks of the project’s plugins, keyed by plugin name, in resolved form.
Each validated against its plugin’s model and dumped back, defaults filled in, so two dumps compare on one shape. Empty in a dictionary from format 6 or older, which recorded none, and empty for an object nothing stamped.
- field type: str [Required]
Name of the structure it is, which is the c type of the declaration.
- field kind: ObjectKind [Required]
measurementorparameter: what the whole object is, and so how it is qualified.
- field description: str = ''
What the object is; the comment in the generated c.
- field shape: tuple[PositiveInt, ...] = ()
Array dimensions of the variable itself, empty for a single structure.
An array of structures reaches the a2l as its elements: there is no one address that describes
cell[0].rawandcell[1].rawat once, so each element contributes its own leaves at its own path. Every dimension is a resolved number; the spelling is indimensions.Array dimensions of the variable itself, empty for a single structure.
An array of structures reaches the a2l as its elements: there is no one address that describes
cell[0].rawandcell[1].rawat once, so each element contributes its own leaves at its own path. Every dimension is a resolved number; the spelling is indimensions.
- field dimensions: tuple[Dimension, ...] = ()
The shape again, each dimension spelled the way the declaration spells it.
Parallel to
shapeexactly as on a plain object: the number, or the name of the declared constant the generated code declares the array by. Empty in a dictionary from format 3 or older.The shape again, each dimension spelled the way the declaration spells it.
Parallel to
shapeexactly as on a plain object: the number, or the name of the declared constant the generated code declares the array by. Empty in a dictionary from format 3 or older.
- field volatile: bool = False
Whether the declaration carries
volatile, which qualifies the whole object.
- field section: str | None = None
Linker section the whole structure is placed in; its members have no placement of their own.
Linker section the whole structure is placed in; its members have no placement of their own.
- field raster: str | None = None
Measurement raster the producing component updates the object in;
nullwhen the project named none. Empty in a dictionary from format 4 or older.Measurement raster the producing component updates the object in;
nullwhen the project named none. Empty in a dictionary from format 4 or older.
- field condition: str | None = None
Preprocessor condition of the producing declaration, if any.
- field owner: str | None = None
Component owning the object;
nullonly when the project is inconsistent.
- field consumers: tuple[str, ...] = ()
Components declaring the object as an input, sorted.
- field local: bool = False
Owned exclusively by
owner; no other component may declare it.
- field a2l: A2lObjectOptions = A2lObjectOptions(export=None, format=None, display_identifier=None)
What the whole object asks of the a2l; a member may ask for more of its own.
- pydantic model ResolvedLeaf[source]
One member of one structured variable, at the end of one access path.
The flattening. A structure reaches the a2l as an object per member rather than as an a2l structure, so this is the form that backend consumes - an ordinary object in every respect but its name, which is a path rather than an identifier.
![digraph "Entity Relationship Diagram created by erdantic" {
graph [fontcolor=gray66,
fontname="Times New Roman,Times,Liberation Serif,serif",
fontsize=9,
nodesep=0.5,
rankdir=LR,
ranksep=1.5
];
node [fontname="Times New Roman,Times,Liberation Serif,serif",
fontsize=14,
label="\N",
shape=plain
];
edge [dir=both];
"ddd.ir.ResolvedLeaf" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>ResolvedLeaf</b></td></tr><tr><td>path</td><td port="path">str</td></tr><tr><td>instance</td><td port="instance">str</td></tr><tr><td>instance_id</td><td port="instance_id">str | None</td></tr><tr><td>kind</td><td port="kind">ObjectKind</td></tr><tr><td>datatype</td><td port="datatype">Datatype</td></tr><tr><td>description</td><td port="description">str</td></tr><tr><td>unit</td><td port="unit">str</td></tr><tr><td>conversion</td><td port="conversion">IdentityConversion | LinearConversion | EnumConversion | StringConversion</td></tr><tr><td>limits</td><td port="limits">Limits</td></tr><tr><td>shape</td><td port="shape">tuple[int, ...]</td></tr><tr><td>dimensions</td><td port="dimensions">tuple[Union[int, str], ...]</td></tr><tr><td>bits</td><td port="bits">int | None</td></tr><tr><td>volatile</td><td port="volatile">bool</td></tr><tr><td>section</td><td port="section">str | None</td></tr><tr><td>raster</td><td port="raster">str | None</td></tr><tr><td>condition</td><td port="condition">str | None</td></tr><tr><td>owner</td><td port="owner">str | None</td></tr><tr><td>consumers</td><td port="consumers">tuple[str, ...]</td></tr><tr><td>local</td><td port="local">bool</td></tr><tr><td>a2l</td><td port="a2l">A2lObjectOptions</td></tr></table>>,
tooltip="ddd.ir.ResolvedLeaf

One member of one structured variable, at the end of one access path.

The flattening. A structure \
reaches the a2l as an object per member rather than as an a2l
structure, so this is the form that backend consumes - an ordinary \
object in every respect
but its name, which is a path rather than an identifier.
"];
"ddd.models.conversion.EnumConversion" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>EnumConversion</b></td></tr><tr><td>kind</td><td port="kind">Literal['enum']</td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>enumerators</td><td port="enumerators">tuple[Enumerator, ...]</td></tr></table>>,
tooltip="ddd.models.conversion.EnumConversion

A verbal conversion table; the raw value *is* the physical value.

Accepts \
both the explicit form::

 {\"kind\": \"enum\", \"name\": \"StateA\",
 \"enumerators\": [{\"name\": \"STATE_OFF\", \"value\": \
0}]}

and the mapping shorthand::

 {\"kind\": \"enum\", \"name\": \"StateA\", \"enumerators\": {\"STATE_OFF\": 0}}
"];
"ddd.ir.ResolvedLeaf":conversion:e -> "ddd.models.conversion.EnumConversion":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.conversion.IdentityConversion" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>IdentityConversion</b></td></tr><tr><td>kind</td><td port="kind">Literal['identity']</td></tr></table>>,
tooltip="ddd.models.conversion.IdentityConversion

``physical == raw``; stated like any other conversion, ``{}`` its shortest spelling.&#\
xA;
Not a default: a definition naming storage by ``datatype`` states this one where raw and
physical are the same number, \
so that the claim is written down rather than left to
silence.
"];
"ddd.ir.ResolvedLeaf":conversion:e -> "ddd.models.conversion.IdentityConversion":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.conversion.LinearConversion" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>LinearConversion</b></td></tr><tr><td>kind</td><td port="kind">Literal['linear']</td></tr><tr><td>factor</td><td port="factor">float</td></tr><tr><td>offset</td><td port="offset">float</td></tr></table>>,
tooltip="ddd.models.conversion.LinearConversion

``physical = raw * factor + offset``, the scaling of a fixed point value.
"];
"ddd.ir.ResolvedLeaf":conversion:e -> "ddd.models.conversion.LinearConversion":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.conversion.StringConversion" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>StringConversion</b></td></tr><tr><td>kind</td><td port="kind">Literal['string']</td></tr></table>>,
tooltip="ddd.models.conversion.StringConversion

Bytes read as text: each element of the array holds one character code.

\
Stated on a ``uint8`` or ``sint8`` array of one dimension; the rules sit beside the
datatype because the same pair is written \
in three places. ``kind`` is required here,
unlike on the other three kinds: a string has no key of its own to be inferred from,&#\
xA;and ``{}`` is the identity.

The two mappings are the identity on one byte, so that the derived limits of a string
\
are the raw range of its datatype - which is what the a2l record states - and nothing
that ranges a conversion has to know that \
a string exists. A byte has no reading of its
own, so no reading is produced for it, as for the identity.
"];
"ddd.ir.ResolvedLeaf":conversion:e -> "ddd.models.conversion.StringConversion":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.objects.A2lObjectOptions" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>A2lObjectOptions</b></td></tr><tr><td>export</td><td port="export">bool | None</td></tr><tr><td>format</td><td port="format">Optional[str]</td></tr><tr><td>display_identifier</td><td port="display_identifier">Optional[str]</td></tr></table>>,
tooltip="ddd.models.objects.A2lObjectOptions

What a declaration asks of the a2l backend. Only that backend interprets it.
&#\
xA;Nothing here changes the generated c or the meaning of the object; a project that
generates no a2l can leave the whole block \
out.
"];
"ddd.ir.ResolvedLeaf":a2l:e -> "ddd.models.objects.A2lObjectOptions":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.objects.Limits" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>Limits</b></td></tr><tr><td>min</td><td port="min">Union[int, float]</td></tr><tr><td>max</td><td port="max">Union[int, float]</td></tr></table>>,
tooltip="ddd.models.objects.Limits

Physical lower/upper limit of a data object.
"];
"ddd.ir.ResolvedLeaf":limits:e -> "ddd.models.objects.Limits":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.conversion.Enumerator" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>Enumerator</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>value</td><td port="value">int</td></tr><tr><td>description</td><td port="description">str</td></tr></table>>,
tooltip="ddd.models.conversion.Enumerator

One named value of an enum conversion, and what that value means.
"];
"ddd.models.conversion.EnumConversion":enumerators:e -> "ddd.models.conversion.Enumerator":_root:w [arrowhead=crownone,
arrowtail=nonenone];
}](_images/graphviz-76204de907594567baf5c84403cce1d0e2c35272.png)
Show JSON schema
{ "title": "ResolvedLeaf", "description": "One member of one structured variable, at the end of one access path.\n\nThe flattening. A structure reaches the a2l as an object per member rather than as an a2l\nstructure, so this is the form that backend consumes - an ordinary object in every respect\nbut its name, which is a path rather than an identifier.", "type": "object", "properties": { "path": { "description": "The c expression that reads this member: ``Inlet.latest.value``, ``Inlet.cell[2].raw``.\n\nBoth the name the a2l gives the object and the symbol it links it to. Written the way it\nwould be written in c, so that a reader of the a2l, of the generated c and of a map file is\nlooking at one string rather than at three spellings of one thing.", "title": "Path", "type": "string" }, "instance": { "description": "Name of the variable this leaf belongs to, which is the root of :attr:`path`.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Instance", "type": "string" }, "instance_id": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Identity of the variable this leaf belongs to; a member has none of its own.\n\nA leaf is identified by this together with the part of :attr:`path` below the instance,\nso renaming the instance is tracked and renaming a *member of the type* is not - the\npath is half of the identity. Empty in a dictionary from format 5 or older.", "title": "Instance Id" }, "kind": { "$ref": "#/$defs/ObjectKind", "description": "Taken from the variable: every leaf of one object has the storage class of the whole." }, "datatype": { "$ref": "#/$defs/Datatype", "description": "Storage of one element." }, "description": { "default": "", "description": "What this member is; the a2l long identifier.", "title": "Description", "type": "string" }, "unit": { "default": "", "description": "Physical unit, from the member or from the type it names.", "title": "Unit", "type": "string" }, "conversion": { "description": "Always present: the member's conversion, or the identity when none was given.", "discriminator": { "mapping": { "enum": "#/$defs/EnumConversion", "identity": "#/$defs/IdentityConversion", "linear": "#/$defs/LinearConversion", "string": "#/$defs/StringConversion" }, "propertyName": "kind" }, "oneOf": [ { "$ref": "#/$defs/IdentityConversion" }, { "$ref": "#/$defs/LinearConversion" }, { "$ref": "#/$defs/EnumConversion" }, { "$ref": "#/$defs/StringConversion" } ], "title": "Conversion" }, "limits": { "$ref": "#/$defs/Limits", "description": "Always present: stated, or derived from the storage - a bitfield's from its width." }, "shape": { "default": [], "description": "Array dimensions of this member; empty for a scalar.\n\nEvery dimension is a resolved number, because this is the form the a2l consumes; a\ndimension the member spells as a constant name carries that name in ``dimensions``.", "items": { "exclusiveMinimum": 0, "type": "integer" }, "title": "Shape", "type": "array" }, "dimensions": { "default": [], "description": "The shape again, each dimension spelled the way the member spells it.\n\nParallel to ``shape`` exactly as on a plain object. Empty in a dictionary from format 3\nor older.", "items": { "anyOf": [ { "maximum": 18446744073709551615, "minimum": 1, "type": "integer" }, { "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "type": "string" } ] }, "title": "Dimensions", "type": "array" }, "bits": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "default": null, "description": "Width in bits when the member is a c bitfield.\n\nSuch a leaf has no address of its own - ``&s.ready`` does not compile - so it reaches no\na2l until a build tells DDD both where the word is and which bits inside it to read.", "title": "Bits" }, "volatile": { "default": false, "description": "From the variable, which carries the qualifier for all of its members at once.", "title": "Volatile", "type": "boolean" }, "section": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Linker section of the structure this member belongs to; a member has no placement\nof its own.", "title": "Section" }, "raster": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Raster of the variable this member belongs to; a member has none of its own.", "title": "Raster" }, "condition": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Preprocessor condition of the producing declaration, if any.", "title": "Condition" }, "owner": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Component owning the variable this leaf belongs to.", "title": "Owner" }, "consumers": { "default": [], "description": "Components declaring the variable as an input, sorted.", "items": { "type": "string" }, "title": "Consumers", "type": "array" }, "local": { "default": false, "description": "Owned exclusively by ``owner``.", "title": "Local", "type": "boolean" }, "a2l": { "$ref": "#/$defs/A2lObjectOptions", "default": { "export": null, "format": null, "display_identifier": null }, "description": "The member's own a2l options; a member may be kept out of the file on its own." } }, "$defs": { "A2lObjectOptions": { "additionalProperties": false, "description": "What a declaration asks of the a2l backend. Only that backend interprets it.\n\nNothing here changes the generated c or the meaning of the object; a project that\ngenerates no a2l can leave the whole block out.", "properties": { "export": { "anyOf": [ { "type": "boolean" }, { "type": "null" } ], "default": null, "description": "Whether the object belongs in the a2l file; omitted, it does.\n\nThe one a2l option any component may state, not only the producer. Which signals a\ncalibration engineer needs to see is not a property of whoever happens to write the\nvariable: a component reading a value from a library it does not own has as good a claim\nto measuring it.\n\nStated by several, the answer is yes if any of them says so, and an object nobody\nmentions is exported: see \"Who asks for an export\" on the definition page.", "title": "Export" }, "format": { "anyOf": [ { "pattern": "^%[0-9]*\\.[0-9]+$", "type": "string" }, { "type": "null" } ], "default": null, "description": "a2l ``FORMAT`` string, e.g. ``\"%8.3\"``: total width, then decimal places.\n\nRefused beside a ``string`` conversion, which has no decimals to display.", "title": "Format" }, "display_identifier": { "anyOf": [ { "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "type": "string" }, { "type": "null" } ], "default": null, "description": "Alternative name shown by the calibration tool.", "title": "Display Identifier" } }, "title": "A2lObjectOptions", "type": "object" }, "Datatype": { "description": "The base datatypes DDD can allocate storage for.", "enum": [ "boolean", "uint8", "sint8", "uint16", "sint16", "uint32", "sint32", "uint64", "sint64", "float32", "float64" ], "title": "Datatype", "type": "string" }, "EnumConversion": { "additionalProperties": false, "description": "A verbal conversion table; the raw value *is* the physical value.\n\nAccepts both the explicit form::\n\n {\"kind\": \"enum\", \"name\": \"StateA\",\n \"enumerators\": [{\"name\": \"STATE_OFF\", \"value\": 0}]}\n\nand the mapping shorthand::\n\n {\"kind\": \"enum\", \"name\": \"StateA\", \"enumerators\": {\"STATE_OFF\": 0}}", "properties": { "kind": { "const": "enum", "default": "enum", "description": "The tag of this kind, which may be left out: a block stating ``enumerators`` or a\n``name`` is an enum.", "title": "Kind", "type": "string" }, "name": { "description": "C identifier of the generated ``typedef enum``; shared enums must agree everywhere.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "enumerators": { "anyOf": [ { "items": { "$ref": "#/$defs/Enumerator" }, "minItems": 1, "type": "array" }, { "additionalProperties": { "maximum": 18446744073709551615, "minimum": -9223372036854775808, "type": "integer" }, "description": "The enumerators as a ``{\"NAME\": value}`` mapping.", "minProperties": 1, "propertyNames": { "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$" }, "type": "object" } ], "description": "The named values, either as objects or as a ``{\"NAME\": value}`` mapping.\n\nTwo of them may not carry the same name, which the mapping form cannot express twice and\nthe list form can: the generated enumeration would not compile, and a calibration tool\nreading the generated table of labels would have two answers for one. Two names sharing a\n*value* is a different matter - it is the C idiom for an alias, reported as\n``enum-duplicate-value`` rather than refused.", "title": "Enumerators" } }, "required": [ "name", "enumerators" ], "title": "EnumConversion", "type": "object" }, "Enumerator": { "additionalProperties": false, "description": "One named value of an enum conversion, and what that value means.", "properties": { "name": { "description": "C identifier of the enumerator; enumerators of all enums share one c namespace.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "value": { "description": "The raw value; two enumerators of one enum sharing one is reported as a warning.\n\n``enum-duplicate-value``, a warning rather than a refusal, because it is legal c and\noccasionally meant as an alias - but the a2l table then offers a calibration tool two\nnames for one reading.\n\nBounded to what 64 bits can hold - no datatype DDD offers stores more - so a value no\nstorage could ever represent is refused here rather than overflowing a comparison once\nit is checked against the c ``int`` every enumerator has to fit, or against the\ndatatype carrying it.\n\nA whole number written without a decimal point: ``4``, not ``4.0``, which the published\nschema accepts and the loader refuses.", "maximum": 18446744073709551615, "minimum": -9223372036854775808, "title": "Value", "type": "integer" }, "description": { "default": "", "description": "What the value means; documentation, not interface.", "title": "Description", "type": "string" } }, "required": [ "name", "value" ], "title": "Enumerator", "type": "object" }, "IdentityConversion": { "additionalProperties": false, "description": "``physical == raw``; stated like any other conversion, ``{}`` its shortest spelling.\n\nNot a default: a definition naming storage by ``datatype`` states this one where raw and\nphysical are the same number, so that the claim is written down rather than left to\nsilence.", "properties": { "kind": { "const": "identity", "default": "identity", "description": "The tag of this kind, which may be left out: an empty block is the identity.", "title": "Kind", "type": "string" } }, "title": "IdentityConversion", "type": "object" }, "Limits": { "additionalProperties": false, "description": "Physical lower/upper limit of a data object.", "properties": { "min": { "anyOf": [ { "maximum": 18446744073709551615, "minimum": -9223372036854775808, "type": "integer" }, { "type": "number" } ], "description": "Smallest physical value the object may take.", "title": "Min" }, "max": { "anyOf": [ { "maximum": 18446744073709551615, "minimum": -9223372036854775808, "type": "integer" }, { "type": "number" } ], "description": "Largest physical value the object may take; at least ``min``.", "title": "Max" } }, "required": [ "min", "max" ], "title": "Limits", "type": "object" }, "LinearConversion": { "additionalProperties": false, "description": "``physical = raw * factor + offset``, the scaling of a fixed point value.", "properties": { "kind": { "const": "linear", "default": "linear", "description": "The tag of this kind, which may be left out: a block stating ``factor`` or ``offset``\nis linear.", "title": "Kind", "type": "string" }, "factor": { "default": 1.0, "description": "Scaling; must not be zero, or nothing could be converted back.", "title": "Factor", "type": "number" }, "offset": { "default": 0.0, "description": "What raw zero stands for, in the physical unit.", "title": "Offset", "type": "number" } }, "title": "LinearConversion", "type": "object" }, "ObjectKind": { "description": "What sort of data object a definition describes.", "enum": [ "measurement", "parameter", "value_block", "curve", "map", "axis" ], "title": "ObjectKind", "type": "string" }, "StringConversion": { "additionalProperties": false, "description": "Bytes read as text: each element of the array holds one character code.\n\nStated on a ``uint8`` or ``sint8`` array of one dimension; the rules sit beside the\ndatatype because the same pair is written in three places. ``kind`` is required here,\nunlike on the other three kinds: a string has no key of its own to be inferred from,\nand ``{}`` is the identity.\n\nThe two mappings are the identity on one byte, so that the derived limits of a string\nare the raw range of its datatype - which is what the a2l record states - and nothing\nthat ranges a conversion has to know that a string exists. A byte has no reading of its\nown, so no reading is produced for it, as for the identity.", "properties": { "kind": { "const": "string", "description": "The tag of this kind, which is required: a string has no key of its own to be\nrecognised by, so nothing else would tell it from the identity.", "title": "Kind", "type": "string" } }, "required": [ "kind" ], "title": "StringConversion", "type": "object" } }, "additionalProperties": false, "required": [ "path", "instance", "kind", "datatype", "conversion", "limits" ] }
- Fields:
- field path: str [Required]
The c expression that reads this member:
Inlet.latest.value,Inlet.cell[2].raw.Both the name the a2l gives the object and the symbol it links it to. Written the way it would be written in c, so that a reader of the a2l, of the generated c and of a map file is looking at one string rather than at three spellings of one thing.
The c expression that reads this member:
Inlet.latest.value,Inlet.cell[2].raw.Both the name the a2l gives the object and the symbol it links it to. Written the way it would be written in c, so that a reader of the a2l, of the generated c and of a map file is looking at one string rather than at three spellings of one thing.
- field instance: Identifier [Required]
Name of the variable this leaf belongs to, which is the root of
path.
- field instance_id: str | None = None
Identity of the variable this leaf belongs to; a member has none of its own.
A leaf is identified by this together with the part of
pathbelow the instance, so renaming the instance is tracked and renaming a member of the type is not - the path is half of the identity. Empty in a dictionary from format 5 or older.Identity of the variable this leaf belongs to; a member has none of its own.
A leaf is identified by this together with the part of
pathbelow the instance, so renaming the instance is tracked and renaming a member of the type is not - the path is half of the identity. Empty in a dictionary from format 5 or older.
- field kind: ObjectKind [Required]
Taken from the variable: every leaf of one object has the storage class of the whole.
- field datatype: Datatype [Required]
Storage of one element.
- field description: str = ''
What this member is; the a2l long identifier.
- field unit: str = ''
Physical unit, from the member or from the type it names.
- field conversion: Conversion [Required]
Always present: the member’s conversion, or the identity when none was given.
- field limits: Limits [Required]
Always present: stated, or derived from the storage - a bitfield’s from its width.
- field shape: tuple[PositiveInt, ...] = ()
Array dimensions of this member; empty for a scalar.
Every dimension is a resolved number, because this is the form the a2l consumes; a dimension the member spells as a constant name carries that name in
dimensions.Array dimensions of this member; empty for a scalar.
Every dimension is a resolved number, because this is the form the a2l consumes; a dimension the member spells as a constant name carries that name in
dimensions.
- field dimensions: tuple[Dimension, ...] = ()
The shape again, each dimension spelled the way the member spells it.
Parallel to
shapeexactly as on a plain object. Empty in a dictionary from format 3 or older.The shape again, each dimension spelled the way the member spells it.
Parallel to
shapeexactly as on a plain object. Empty in a dictionary from format 3 or older.
- field bits: int | None = None
Width in bits when the member is a c bitfield.
Such a leaf has no address of its own -
&s.readydoes not compile - so it reaches no a2l until a build tells DDD both where the word is and which bits inside it to read.Width in bits when the member is a c bitfield.
Such a leaf has no address of its own -
&s.readydoes not compile - so it reaches no a2l until a build tells DDD both where the word is and which bits inside it to read.
- field volatile: bool = False
From the variable, which carries the qualifier for all of its members at once.
- field section: str | None = None
Linker section of the structure this member belongs to; a member has no placement of its own.
Linker section of the structure this member belongs to; a member has no placement of its own.
- field raster: str | None = None
Raster of the variable this member belongs to; a member has none of its own.
- field condition: str | None = None
Preprocessor condition of the producing declaration, if any.
- field owner: str | None = None
Component owning the variable this leaf belongs to.
- field consumers: tuple[str, ...] = ()
Components declaring the variable as an input, sorted.
- field local: bool = False
Owned exclusively by
owner.
- field a2l: A2lObjectOptions = A2lObjectOptions(export=None, format=None, display_identifier=None)
The member’s own a2l options; a member may be kept out of the file on its own.