SPDM v0.1 (Synarius Parameter Data Model)

Status: Draft mini-specification

Scope

SPDM v0.1 defines a canonical, XML-based parameter model for Synarius that is:

  • strongly typed

  • semantically rich

  • suitable for simulation and code generation

  • variant-capable

  • designed for loss-minimizing import/export with DCM2, CDFX, and PAR

1. Conceptual Model

Parameter

A uniquely identified configuration/calibration item.

  • Required: id, typeRef

  • Optional: path, unitRef, quantity, defaultValue, constraints, metadata

ParameterSet

A versionable container of concrete parameter values.

  • Supports inheritance via baseSetRef

  • Contains values for parameter IDs

  • May carry variant-specific overrides

ParameterValue

Typed assignment for one parameter in a set.

  • BaseValue: unconditional

  • Override: conditional via variant condition

  • Can carry coded and physical form where needed

Type system

  • Scalar: int, float, bool, string

  • Enum: named literals, optional coded representation

  • Array: 1D..nD values

  • Curve/Table/Map: axis-based values

  • Struct: named fields with typed values

Units and quantities

  • Unit is referenced via unitRef

  • Physical quantity is optional metadata (example: torque)

  • Conversion/coding metadata can be carried in metadata or extensions

Constraints

  • Numeric ranges (min/max; hard/soft semantics)

  • Validity ranges

  • Enum domain restrictions

  • Recursive constraints for arrays/structs

Variants

  • Conditions are named expressions in VariantModel

  • Override entries reference condition IDs

  • Resolution is deterministic by priority

  • Priority ties among active overrides are invalid

Defaults vs actual values

  • defaultValue lives in ParameterDefinition

  • actual values live in ParameterSet

  • if no actual value exists, fallback is defaultValue

Metadata

Namespaced metadata may appear on package, parameter, set, and value levels. Typical content:

  • source origin descriptors

  • author/timestamp/comment

  • release/process flags

2. Design Principles

  1. Canonical model first: SPDM is normative internally.

  2. Semantics/storage separation: model semantics are independent from XML carrier details.

  3. Import information preservation: unmapped source details must be retained in metadata/extensions.

  4. Explicit representation: coded and physical values may coexist.

  5. Safe extensibility: versioned schema + namespace extensions + round-trip of unknown extensions.

3. XML Representation

Root

  • Element: spdm:ParameterPackage

  • Namespace: urn:synarius:spdm:0.1

  • Required attributes: schemaVersion, packageId, createdAt

Normative top-level order

  1. TypeDefinitions

  2. UnitDefinitions

  3. ParameterDefinitions

  4. VariantModel

  5. ParameterSets

  6. Extensions (optional)

ParameterDefinition shape

  • Required attributes: id, typeRef

  • Optional attributes: unitRef, quantity, path

  • Optional children: DisplayName, Description, DefaultValue, Constraints, Metadata

Value encoding

  • ScalarValue(kind,value)

  • EnumValue(literal,coded?)

  • ArrayValue(dimensions) with Item*

  • CurveValue with AxisX + Values

  • MapValue with AxisX + AxisY + Values

  • StructValue with recursive FieldValue(name, Value)

Variant handling

  • VariantModel/Condition(id, expression)

  • Override(conditionRef, priority)

  • Resolve by descending priority, tie -> validation error

4. XSD (reference)

The following XSD is a structural baseline for SPDM v0.1. Semantic checks (cross-reference validity, dimensional consistency, override conflict checks) are implemented by application validators in addition to XSD.

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    targetNamespace="urn:synarius:spdm:0.1"
    xmlns:spdm="urn:synarius:spdm:0.1"
    elementFormDefault="qualified"
    attributeFormDefault="unqualified">

  <xs:simpleType name="ScalarKind">
    <xs:restriction base="xs:string">
      <xs:enumeration value="int"/>
      <xs:enumeration value="float"/>
      <xs:enumeration value="bool"/>
      <xs:enumeration value="string"/>
    </xs:restriction>
  </xs:simpleType>

  <xs:complexType name="RangeType">
    <xs:attribute name="min" type="xs:double" use="optional"/>
    <xs:attribute name="max" type="xs:double" use="optional"/>
    <xs:attribute name="hard" type="xs:boolean" use="optional"/>
  </xs:complexType>

  <xs:complexType name="ScalarValueType">
    <xs:attribute name="kind" type="spdm:ScalarKind" use="required"/>
    <xs:attribute name="value" type="xs:string" use="required"/>
  </xs:complexType>

  <xs:complexType name="EnumValueType">
    <xs:attribute name="literal" type="xs:string" use="required"/>
    <xs:attribute name="coded" type="xs:string" use="optional"/>
  </xs:complexType>

  <xs:complexType name="ArrayValueType">
    <xs:sequence>
      <xs:element name="Item" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
    </xs:sequence>
    <xs:attribute name="dimensions" type="xs:string" use="required"/>
  </xs:complexType>

  <xs:complexType name="AxisType">
    <xs:sequence>
      <xs:element name="V" type="xs:double" minOccurs="0" maxOccurs="unbounded"/>
    </xs:sequence>
    <xs:attribute name="unitRef" type="xs:string" use="optional"/>
  </xs:complexType>

  <xs:complexType name="CurveValueType">
    <xs:sequence>
      <xs:element name="AxisX" type="spdm:AxisType"/>
      <xs:element name="Values">
        <xs:complexType>
          <xs:sequence>
            <xs:element name="V" type="xs:double" minOccurs="0" maxOccurs="unbounded"/>
          </xs:sequence>
        </xs:complexType>
      </xs:element>
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="MapValueType">
    <xs:sequence>
      <xs:element name="AxisX" type="spdm:AxisType"/>
      <xs:element name="AxisY" type="spdm:AxisType"/>
      <xs:element name="Values">
        <xs:complexType>
          <xs:sequence>
            <xs:element name="V" type="xs:double" minOccurs="0" maxOccurs="unbounded"/>
          </xs:sequence>
        </xs:complexType>
      </xs:element>
    </xs:sequence>
    <xs:attribute name="xSize" type="xs:positiveInteger" use="required"/>
    <xs:attribute name="ySize" type="xs:positiveInteger" use="required"/>
    <xs:attribute name="storage" type="xs:string" use="optional" default="row-major"/>
  </xs:complexType>

  <xs:complexType name="StructValueType">
    <xs:sequence>
      <xs:element name="FieldValue" minOccurs="0" maxOccurs="unbounded">
        <xs:complexType>
          <xs:sequence>
            <xs:element ref="spdm:Value"/>
          </xs:sequence>
          <xs:attribute name="name" type="xs:string" use="required"/>
        </xs:complexType>
      </xs:element>
    </xs:sequence>
  </xs:complexType>

  <xs:element name="Value">
    <xs:complexType>
      <xs:choice>
        <xs:element name="ScalarValue" type="spdm:ScalarValueType"/>
        <xs:element name="EnumValue" type="spdm:EnumValueType"/>
        <xs:element name="ArrayValue" type="spdm:ArrayValueType"/>
        <xs:element name="CurveValue" type="spdm:CurveValueType"/>
        <xs:element name="MapValue" type="spdm:MapValueType"/>
        <xs:element name="StructValue" type="spdm:StructValueType"/>
      </xs:choice>
    </xs:complexType>
  </xs:element>

  <xs:complexType name="MetadataType">
    <xs:sequence>
      <xs:element name="Entry" minOccurs="0" maxOccurs="unbounded">
        <xs:complexType mixed="true">
          <xs:attribute name="key" type="xs:string" use="required"/>
          <xs:attribute name="ns" type="xs:string" use="optional"/>
        </xs:complexType>
      </xs:element>
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="ConstraintsType">
    <xs:sequence>
      <xs:element name="Range" type="spdm:RangeType" minOccurs="0" maxOccurs="unbounded"/>
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="TypeDefinitionsType">
    <xs:sequence>
      <xs:element name="EnumType" minOccurs="0" maxOccurs="unbounded">
        <xs:complexType>
          <xs:sequence>
            <xs:element name="Literal" minOccurs="1" maxOccurs="unbounded">
              <xs:complexType>
                <xs:attribute name="name" type="xs:string" use="required"/>
                <xs:attribute name="coded" type="xs:string" use="optional"/>
              </xs:complexType>
            </xs:element>
          </xs:sequence>
          <xs:attribute name="id" type="xs:string" use="required"/>
        </xs:complexType>
      </xs:element>
      <xs:element name="ArrayType" minOccurs="0" maxOccurs="unbounded">
        <xs:complexType>
          <xs:attribute name="id" type="xs:string" use="required"/>
          <xs:attribute name="elementType" type="xs:string" use="required"/>
          <xs:attribute name="dimensions" type="xs:string" use="required"/>
        </xs:complexType>
      </xs:element>
      <xs:element name="MapType" minOccurs="0" maxOccurs="unbounded">
        <xs:complexType>
          <xs:attribute name="id" type="xs:string" use="required"/>
          <xs:attribute name="xType" type="xs:string" use="required"/>
          <xs:attribute name="yType" type="xs:string" use="required"/>
          <xs:attribute name="valueType" type="xs:string" use="required"/>
          <xs:attribute name="xSize" type="xs:positiveInteger" use="required"/>
          <xs:attribute name="ySize" type="xs:positiveInteger" use="required"/>
        </xs:complexType>
      </xs:element>
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="UnitDefinitionsType">
    <xs:sequence>
      <xs:element name="Unit" minOccurs="0" maxOccurs="unbounded">
        <xs:complexType>
          <xs:attribute name="id" type="xs:string" use="required"/>
          <xs:attribute name="symbol" type="xs:string" use="optional"/>
          <xs:attribute name="quantity" type="xs:string" use="optional"/>
        </xs:complexType>
      </xs:element>
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="ParameterDefinitionType">
    <xs:sequence>
      <xs:element name="DisplayName" type="xs:string" minOccurs="0"/>
      <xs:element name="Description" type="xs:string" minOccurs="0"/>
      <xs:element name="DefaultValue" minOccurs="0">
        <xs:complexType>
          <xs:sequence>
            <xs:element ref="spdm:Value"/>
          </xs:sequence>
        </xs:complexType>
      </xs:element>
      <xs:element name="Constraints" type="spdm:ConstraintsType" minOccurs="0"/>
      <xs:element name="Metadata" type="spdm:MetadataType" minOccurs="0"/>
    </xs:sequence>
    <xs:attribute name="id" type="xs:string" use="required"/>
    <xs:attribute name="typeRef" type="xs:string" use="required"/>
    <xs:attribute name="unitRef" type="xs:string" use="optional"/>
    <xs:attribute name="quantity" type="xs:string" use="optional"/>
    <xs:attribute name="path" type="xs:string" use="optional"/>
  </xs:complexType>

  <xs:complexType name="ParameterDefinitionsType">
    <xs:sequence>
      <xs:element name="ParameterDefinition" type="spdm:ParameterDefinitionType" minOccurs="0" maxOccurs="unbounded"/>
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="VariantModelType">
    <xs:sequence>
      <xs:element name="Condition" minOccurs="0" maxOccurs="unbounded">
        <xs:complexType>
          <xs:attribute name="id" type="xs:string" use="required"/>
          <xs:attribute name="expression" type="xs:string" use="required"/>
        </xs:complexType>
      </xs:element>
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="OverrideType">
    <xs:sequence>
      <xs:element ref="spdm:Value"/>
    </xs:sequence>
    <xs:attribute name="conditionRef" type="xs:string" use="required"/>
    <xs:attribute name="priority" type="xs:integer" use="optional"/>
  </xs:complexType>

  <xs:complexType name="ParameterValueRefType">
    <xs:sequence>
      <xs:element name="BaseValue" minOccurs="0">
        <xs:complexType>
          <xs:sequence>
            <xs:element ref="spdm:Value"/>
          </xs:sequence>
        </xs:complexType>
      </xs:element>
      <xs:element name="Override" type="spdm:OverrideType" minOccurs="0" maxOccurs="unbounded"/>
      <xs:element name="Metadata" type="spdm:MetadataType" minOccurs="0"/>
    </xs:sequence>
    <xs:attribute name="parameterId" type="xs:string" use="required"/>
  </xs:complexType>

  <xs:complexType name="ValuesType">
    <xs:sequence>
      <xs:element name="ParameterValueRef" type="spdm:ParameterValueRefType" minOccurs="0" maxOccurs="unbounded"/>
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="ParameterSetType">
    <xs:sequence>
      <xs:element name="Metadata" type="spdm:MetadataType" minOccurs="0"/>
      <xs:element name="Values" type="spdm:ValuesType"/>
    </xs:sequence>
    <xs:attribute name="id" type="xs:string" use="required"/>
    <xs:attribute name="baseSetRef" type="xs:string" use="optional"/>
    <xs:attribute name="priority" type="xs:integer" use="optional"/>
  </xs:complexType>

  <xs:complexType name="ParameterSetsType">
    <xs:sequence>
      <xs:element name="ParameterSet" type="spdm:ParameterSetType" minOccurs="1" maxOccurs="unbounded"/>
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="ExtensionsType">
    <xs:sequence>
      <xs:any processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
    </xs:sequence>
  </xs:complexType>

  <xs:element name="ParameterPackage">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="TypeDefinitions" type="spdm:TypeDefinitionsType"/>
        <xs:element name="UnitDefinitions" type="spdm:UnitDefinitionsType"/>
        <xs:element name="ParameterDefinitions" type="spdm:ParameterDefinitionsType"/>
        <xs:element name="VariantModel" type="spdm:VariantModelType"/>
        <xs:element name="ParameterSets" type="spdm:ParameterSetsType"/>
        <xs:element name="Extensions" type="spdm:ExtensionsType" minOccurs="0"/>
      </xs:sequence>
      <xs:attribute name="schemaVersion" type="xs:string" use="required"/>
      <xs:attribute name="packageId" type="xs:string" use="required"/>
      <xs:attribute name="createdAt" type="xs:dateTime" use="required"/>
    </xs:complexType>
  </xs:element>

</xs:schema>

5. Example SPDM file

<?xml version="1.0" encoding="UTF-8"?>
<spdm:ParameterPackage
    xmlns:spdm="urn:synarius:spdm:0.1"
    schemaVersion="0.1"
    packageId="Powertrain.Calib"
    createdAt="2026-04-02T10:30:00Z">

  <spdm:TypeDefinitions>
    <spdm:EnumType id="FuelMode_t">
      <spdm:Literal name="Eco" coded="0"/>
      <spdm:Literal name="Normal" coded="1"/>
      <spdm:Literal name="Sport" coded="2"/>
    </spdm:EnumType>
    <spdm:ArrayType id="IgnAngleCorrVec_t" elementType="float" dimensions="8"/>
    <spdm:MapType id="TorqueMap_t" xType="float" yType="float" valueType="float" xSize="4" ySize="3"/>
  </spdm:TypeDefinitions>

  <spdm:UnitDefinitions>
    <spdm:Unit id="deg" symbol="deg" quantity="Angle"/>
    <spdm:Unit id="Nm" symbol="N*m" quantity="Torque"/>
    <spdm:Unit id="rpm" symbol="1/min" quantity="RotationalSpeed"/>
    <spdm:Unit id="pct" symbol="%" quantity="Ratio"/>
  </spdm:UnitDefinitions>

  <spdm:ParameterDefinitions>
    <spdm:ParameterDefinition id="Engine.MaxTorque" typeRef="float" unitRef="Nm" quantity="Torque">
      <spdm:DefaultValue>
        <spdm:Value>
          <spdm:ScalarValue kind="float" value="300.0"/>
        </spdm:Value>
      </spdm:DefaultValue>
      <spdm:Constraints>
        <spdm:Range min="0.0" max="800.0" hard="true"/>
      </spdm:Constraints>
    </spdm:ParameterDefinition>

    <spdm:ParameterDefinition id="Ignition.CorrVector" typeRef="IgnAngleCorrVec_t" unitRef="deg"/>
    <spdm:ParameterDefinition id="Engine.TorqueMap" typeRef="TorqueMap_t" unitRef="Nm"/>
    <spdm:ParameterDefinition id="Vehicle.FuelMode" typeRef="FuelMode_t"/>
  </spdm:ParameterDefinitions>

  <spdm:VariantModel>
    <spdm:Condition id="isEU" expression="Market == 'EU'"/>
  </spdm:VariantModel>

  <spdm:ParameterSets>
    <spdm:ParameterSet id="Base" priority="0">
      <spdm:Values>
        <spdm:ParameterValueRef parameterId="Engine.MaxTorque">
          <spdm:BaseValue>
            <spdm:Value>
              <spdm:ScalarValue kind="float" value="320.0"/>
            </spdm:Value>
          </spdm:BaseValue>
        </spdm:ParameterValueRef>

        <spdm:ParameterValueRef parameterId="Ignition.CorrVector">
          <spdm:BaseValue>
            <spdm:Value>
              <spdm:ArrayValue dimensions="8">
                <spdm:Item>0.0</spdm:Item><spdm:Item>0.2</spdm:Item><spdm:Item>0.4</spdm:Item><spdm:Item>0.5</spdm:Item>
                <spdm:Item>0.5</spdm:Item><spdm:Item>0.4</spdm:Item><spdm:Item>0.2</spdm:Item><spdm:Item>0.0</spdm:Item>
              </spdm:ArrayValue>
            </spdm:Value>
          </spdm:BaseValue>
        </spdm:ParameterValueRef>

        <spdm:ParameterValueRef parameterId="Engine.TorqueMap">
          <spdm:BaseValue>
            <spdm:Value>
              <spdm:MapValue xSize="4" ySize="3" storage="row-major">
                <spdm:AxisX unitRef="rpm">
                  <spdm:V>1000</spdm:V><spdm:V>2000</spdm:V><spdm:V>3000</spdm:V><spdm:V>4000</spdm:V>
                </spdm:AxisX>
                <spdm:AxisY unitRef="pct">
                  <spdm:V>20</spdm:V><spdm:V>50</spdm:V><spdm:V>100</spdm:V>
                </spdm:AxisY>
                <spdm:Values>
                  <spdm:V>80</spdm:V><spdm:V>140</spdm:V><spdm:V>190</spdm:V><spdm:V>210</spdm:V>
                  <spdm:V>100</spdm:V><spdm:V>180</spdm:V><spdm:V>250</spdm:V><spdm:V>280</spdm:V>
                  <spdm:V>120</spdm:V><spdm:V>220</spdm:V><spdm:V>300</spdm:V><spdm:V>320</spdm:V>
                </spdm:Values>
              </spdm:MapValue>
            </spdm:Value>
          </spdm:BaseValue>
        </spdm:ParameterValueRef>

        <spdm:ParameterValueRef parameterId="Vehicle.FuelMode">
          <spdm:BaseValue>
            <spdm:Value>
              <spdm:EnumValue literal="Normal" coded="1"/>
            </spdm:Value>
          </spdm:BaseValue>
          <spdm:Override conditionRef="isEU" priority="10">
            <spdm:Value>
              <spdm:EnumValue literal="Eco" coded="0"/>
            </spdm:Value>
          </spdm:Override>
        </spdm:ParameterValueRef>
      </spdm:Values>
    </spdm:ParameterSet>
  </spdm:ParameterSets>

</spdm:ParameterPackage>

6. Mapping Considerations

DCM2 -> SPDM

Easy:

  • FESTWERT/FESTWERTE -> scalar/array

  • KENNLINIE -> curve

  • KENNFELD -> map/table

Ambiguous/loss-prone:

  • implicit typing

  • limited explicit unit/quantity information

  • tool-specific flags/comments

CDFX -> SPDM

Easy:

  • rich typed XML, including coded/physical forms

  • direct mapping for arrays/curves/maps/structures

Ambiguous/loss-prone:

  • process/QM metadata outside SPDM core

PAR -> SPDM

Easy:

  • straightforward key/value import for common scalar/vector cases

Ambiguous/loss-prone:

  • tool-dependent dialect differences

  • often incomplete units/constraints/variant semantics

Import policy:

  • preserve source identifiers, comments, checksums in origin metadata for round-trip traceability

7. Implementation Notes

Parsing strategy

  1. XML parse stage

  2. Typed IR construction

  3. Semantic validation + normalization

Suggested internal structures

  • Package, TypeDef, UnitDef, ParameterDef, ParameterSet, Condition

  • ValueNode tagged union (Scalar/Enum/Array/Curve/Map/Struct)

  • parsed condition AST for deterministic evaluation

Versioning

  • schemaVersion follows semantic versioning

  • minor = backward compatible

  • major = potentially breaking

Validation

  • XSD for structure and primitive constraints

  • semantic validator for: - unresolved references - dimension mismatch - enum/code mismatch - active override priority conflicts

8. Minimum Compliance Profile (v0.1)

An implementation is SPDM v0.1 compliant if it can:

  1. parse all core value forms (scalar/enum/array/curve/map/struct)

  2. resolve defaults and set values deterministically

  3. evaluate variant overrides with deterministic conflict handling

  4. preserve origin metadata needed for round-trip conversion

  5. reject structurally invalid XML and semantically invalid references