Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion dau_core/capability_contract.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,9 @@ def opcode_bitmap(opcodes: tuple[OperationCode, ...]) -> int:

class TileCapability(CheckedModel):
"""One operator tile instance as the contract describes it: registry
identity, stream contract, HDL opcode truth, and instance config."""
identity, stream contract, HDL opcode truth, instance config, and the
module parameters it was built with (each declared parameter, at its
override or its default)."""

core: str
module: str
Expand All @@ -58,6 +60,7 @@ class TileCapability(CheckedModel):
unit_kind: UnitKind | None = None
row_capacity: int | None = None
config: tuple[tuple[str, str], ...] = ()
params: tuple[tuple[str, int], ...] = ()

@property
def host_opcodes(self) -> tuple[OperationCode, ...]:
Expand All @@ -79,6 +82,7 @@ def to_mapping(self) -> dict[str, Any]:
"unit_kind": self.unit_kind.value if self.unit_kind is not None else None,
"row_capacity": self.row_capacity,
"config": dict(self.config),
"params": dict(self.params),
}

@classmethod
Expand All @@ -93,6 +97,9 @@ def from_mapping(cls, mapping: Mapping[str, Any]) -> TileCapability:
unit_kind=UnitKind(mapping["unit_kind"]) if mapping.get("unit_kind") else None,
row_capacity=mapping.get("row_capacity"),
config=tuple(sorted((str(key), str(value)) for key, value in dict(mapping.get("config", {})).items())),
# absent in manifests written before the fact was advertised; a
# reader that needs a parameter treats it as unknown
params=tuple(sorted((str(key), int(value)) for key, value in dict(mapping.get("params", {})).items())),
)


Expand Down Expand Up @@ -247,6 +254,7 @@ def tile_capability(tile: TileSpec | str) -> TileCapability:
unit_kind=definition.unit_kind,
row_capacity=definition.row_capacity,
config=tuple(sorted((str(key), str(value)) for key, value in spec.config.items())),
params=tuple(sorted((name, spec.params.get(name, parameter.default)) for name, parameter in definition.parameters.items())),
)


Expand Down
24 changes: 24 additions & 0 deletions dau_core/tests/test_capability_contract.py
Original file line number Diff line number Diff line change
Expand Up @@ -233,3 +233,27 @@ def test_reconfigurable_is_a_manifest_fact() -> None:
legacy = baked.to_mapping()
del legacy["reconfigurable"]
assert CapabilityContract.from_mapping(legacy).reconfigurable is False


def test_a_tile_capability_carries_the_parameters_it_was_built_with() -> None:
from dau_core.operators import DispatchMode

dispatcher = TileSpec(core="key-mask-dispatcher", params={"NUM_PARTITIONS": 4, "MODE": int(DispatchMode.EXACT_BRANCH)})
lane = LaneSpec(tile=TileSpec(core="field-sum-aggregation", config={"cfg_field_mask": "4'b0010"}))
contract = capability_contract(ScanCompositionSpec(name="t", lanes=(lane,) * 4, partitioner=dispatcher))

assert contract.partitioner is not None
params = dict(contract.partitioner.params)
# overrides as given, every other declared parameter at its default
assert params["MODE"] == DispatchMode.EXACT_BRANCH
assert params["NUM_PARTITIONS"] == 4
assert params["IN_WIDTH"] == 64
assert set(params) == set(dispatcher.definition().parameters)
assert CapabilityContract.from_mapping(json.loads(json.dumps(contract.to_mapping()))) == contract

# a manifest written before the parameters were advertised reads as unknown
mapping = contract.to_mapping()
del mapping["partitioner"]["params"]
restored = CapabilityContract.from_mapping(mapping).partitioner
assert restored is not None
assert restored.params == ()