def compile_model(model: ControlModel) -> GDSSpec:
"""Compile a ControlModel into a GDSSpec.
Registers: types, spaces, entities, blocks, wirings, and parameters.
"""
spec = GDSSpec(name=model.name, description=model.description)
# 1. Register types
spec.collect(StateType, ReferenceType, MeasurementType, ControlType)
# 2. Register spaces
spec.collect(StateSpace, ReferenceSpace, MeasurementSpace, ControlSpace)
# 3. Register entities (one per state)
for state in model.states:
spec.register_entity(_build_state_entity(state))
# 4. Register blocks
for inp in model.inputs:
spec.register_block(_build_input_block(inp))
for sensor in model.sensors:
spec.register_block(_build_sensor_block(sensor))
for ctrl in model.controllers:
spec.register_block(_build_controller_block(ctrl, model))
for state in model.states:
spec.register_block(_build_state_mechanism(state, model))
# 5. Register spec wirings
all_block_names = [b for b in spec.blocks]
wires: list[Wire] = []
# Controller → State dynamics wirings
for ctrl in model.controllers:
for drive in ctrl.drives:
wires.append(
Wire(
source=ctrl.name,
target=_dynamics_block_name(drive),
space="ControlSpace",
)
)
spec.register_wiring(
SpecWiring(
name=f"{model.name} Wiring",
block_names=all_block_names,
wires=wires,
description=(f"Auto-generated wiring for control model {model.name!r}"),
)
)
# 6. Register inputs as parameters
for inp in model.inputs:
spec.register_parameter(
ParameterDef(
name=inp.name,
typedef=ReferenceType,
description=f"Exogenous input: {inp.name}",
)
)
# 7. Register transition signatures (mechanism read dependencies)
from gds.constraints import TransitionSignature
for state in model.states:
driving_controllers = [
ctrl.name for ctrl in model.controllers if state.name in ctrl.drives
]
spec.register_transition_signature(
TransitionSignature(
mechanism=_dynamics_block_name(state.name),
reads=[(state.name, "value")],
depends_on_blocks=driving_controllers,
)
)
# 8. Declare execution contract — control systems are discrete/synchronous/Moore
spec.execution_contract = ExecutionContract(time_domain="discrete")
return spec