test_cores

Attributes

OWN_PACKAGE

HDL_SUFFIXES

WIDTH_NAMED_TILES

CANONICAL_PALETTE_VERSION

CANONICAL_PALETTE

Functions

own_cores() → tuple

committed_hdl(hdl_dir) → set[str] | None

The HDL git CARRIES under hdl_dir, as paths relative to it, or

test_every_hdl_file_belongs_to_exactly_one_core() → None

Checked-in HDL and registry entries match exactly, in both directions.

test_all_source_paths_exist() → None

test_goldens_resolve_to_callables() → None

test_benches_are_importable_modules() → None

test_every_operator_has_a_golden() → None

test_every_selectable_operator_declares_its_ingest_rate() → None

Ingest rate is core PUBLIC INTERFACE (the scheduler rate-matches

test_wide_combinational_tiles_declare_pipeline_depth_without_changing_ingest() → None

test_every_selectable_operator_declares_its_contract_kind() → None

A new core declares its stream contract in the registry — contract

test_every_selectable_operator_declares_its_record_words() → None

test_parameterized_record_words_resolve_from_defaults_and_overrides() → None

test_only_combinational_per_beat_cores_support_pipeline_depth() → None

test_sources_for_closes_dependencies_in_order() → None

test_lookup_errors_are_typed() → None

test_synthesizable_cores_carry_measured_envelopes() → None

Recorded operator/stream-infra envelopes are measured OOC values.

test_the_width_named_tiles_are_exactly_the_declared_ones() → None

The naming rule is that a width is a parameter, not an identity; this

test_the_canonical_palette_is_exactly_the_registered_names() → None

THE GUARD a rename has to pass. A name that leaves this set takes

test_the_canonical_palette_is_pinned_to_the_canonical_form_it_spells() → None

The other direction of the same coupling: a canonical-form bump that

_measured(**overrides)

A core carrying one measurement point, built here rather than read from

test_exact_resource_measurement_resolves_with_parameter_defaults() → None

test_resource_measurement_refuses_an_unmeasured_part() → None

test_an_unclocked_measurement_answers_for_any_clock_and_records_no_timing() → None

A combinational core (identity-registers is one: a parameter ROM with

test_every_registered_core_with_resources_carries_measurement_points() → None

There is one shape for a resource record. A scalar count with no

test_normalize_follows_the_same_rule_as_violation() → None

A type spelling is only for a parameter declared element_type; a plain

test_violated_measurement_is_retrievable_but_not_a_usable_envelope() → None

test_registry_is_hydra_composition_not_a_python_literal() → None

Composition IS the registry: cores load from dau-core's hydra config

test_accessors_defer_to_a_composed_registry() → None

The composed registry is the source of truth: accessors read through

test_silent_on_success_operator_set_is_pinned() → None

The status contract's two classes are registry truth: silent-on-success

test_dispatcher_rate_still_needs_record_aware_modeling() → None

The dispatcher's framing-shaped rate describes a 2-word record. Its

test_authoritative_models_reject_impossible_values() → None

test_parameter_spec_rejects_incoherent_constraints() → None

test_parameter_spec_violation_is_the_single_constraint_source() → None

test_an_element_type_parameter_accepts_a_width_or_a_spelling() → None

The two forms are the same declaration where they overlap, and the

test_an_element_type_parameter_bounds_the_width_not_the_encoding() → None

A registry bound mirrors an RTL guard about BITS. q16.16 encodes as

test_an_element_type_spelling_is_refused_where_no_type_is_declared() → None

A size parameter takes a size. Silently reading "int32" as 32 on a

test_an_element_type_default_must_name_a_type_the_spec_admits() → None

test_a_measurement_coordinate_may_name_the_type_it_was_measured_at() → None

The same point, written either way, is one point -- so migrating a

test_storage_intent_prices_against_declared_parameters() → None

test_storage_intent_refuses_an_undeclared_scale_parameter() → None

test_storage_intent_without_scale_is_a_fixed_cost() → None

test_storage_bytes_refuses_illegal_scale_overrides() → None

test_a_core_resolves_hdl_from_the_package_that_declares_it(...) → None

A tile contributed by another distribution finds its own HDL.

test_a_well_formed_vendor_tile_does_not_trip_our_palette_guards(...) → None

Installing a third-party tile must not fail THIS suite.

test_a_core_naming_an_uninstalled_hdl_package_refuses_clearly() → None

The failure names the missing distribution rather than surfacing an

test_a_measured_point_matches_a_derived_clock_period() → None

A clock period is DERIVED (1000 / job_clock_mhz), so exact float

test_an_unresolvable_hdl_source_says_so() → None

A declared source that does not resolve is a DECLARATION error.

Module Contents

test_cores.OWN_PACKAGE = 'dau_core.hdl'
test_cores.HDL_SUFFIXES = ('.sv', '.v')
test_cores.own_cores() → tuple
test_cores.committed_hdl(hdl_dir: pathlib.Path) → set[str] | None

The HDL git CARRIES under hdl_dir, as paths relative to it, or None when there is no repository to ask.

Committedness is a git fact, and only git can answer it. A directory listing cannot: the suite renders every generated core into the render root on each run (conftest._render_generated_cores), so a rendered file being PRESENT there is the normal state and says nothing about whether someone checked it in. Absent a repository – an installed distribution – nothing is committed and there is nothing to check.

test_cores.test_every_hdl_file_belongs_to_exactly_one_core() → None

Checked-in HDL and registry entries match exactly, in both directions.

A GENERATED core is excluded because it has no checked-in file by definition – and asserted to have none, which is the same guard from the other side: a generated core with a file beside the entry means someone committed rendered output, and whichever of the two is stale will be the one that gets synthesized.

The reach is the whole package, not one directory listing. Listing hdl/ alone left the render root – a SUBDIRECTORY of it – outside this guard entirely, and three rendered tiles sat committed there until a rename made their filenames disagree with their contents. So the walk descends, and the committed set comes from git: a rendered file being present in the render root is the normal working state (the suite renders there on every run), and what distinguishes that from the mistake is whether it was checked in.

test_cores.test_all_source_paths_exist() → None
test_cores.test_goldens_resolve_to_callables() → None
test_cores.test_benches_are_importable_modules() → None
test_cores.test_every_operator_has_a_golden() → None
test_cores.test_every_selectable_operator_declares_its_ingest_rate() → None

Ingest rate is core PUBLIC INTERFACE (the scheduler rate-matches opaque cores from the registry declaration alone): every stream operator declares it. The floor is the composed 1-row/2-cycle lane rate; only silicon-proven faster cores declare 1/1.

test_cores.test_wide_combinational_tiles_declare_pipeline_depth_without_changing_ingest() → None
test_cores.test_every_selectable_operator_declares_its_contract_kind() → None

A new core declares its stream contract in the registry — contract tests select validators from this tag, never from test-local exemption sets.

test_cores.test_every_selectable_operator_declares_its_record_words() → None
test_cores.test_parameterized_record_words_resolve_from_defaults_and_overrides() → None
test_cores.test_only_combinational_per_beat_cores_support_pipeline_depth() → None
test_cores.test_sources_for_closes_dependencies_in_order() → None
test_cores.test_lookup_errors_are_typed() → None
test_cores.test_synthesizable_cores_carry_measured_envelopes() → None

Recorded operator/stream-infra envelopes are measured OOC values.

EMPTY as of 2026-08-16: the stride distributor was the last operator carrying no envelope at all, and no design containing it could be priced. Asserted exactly, so a tile shipped without a measurement fails here rather than surfacing as an unpriceable design later.

test_cores.WIDTH_NAMED_TILES: frozenset[str]
test_cores.test_the_width_named_tiles_are_exactly_the_declared_ones() → None

The naming rule is that a width is a parameter, not an identity; this pins how much of the palette still contradicts it.

Scoped to own_cores() for the same reason every exact-set guard here is: an installed third-party tile with a width in its name is that vendor’s business, not drift in our palette.

test_cores.CANONICAL_PALETTE_VERSION = '7'
test_cores.CANONICAL_PALETTE: frozenset[str]
test_cores.test_the_canonical_palette_is_exactly_the_registered_names() → None

THE GUARD a rename has to pass. A name that leaves this set takes every recorded canonical spec that spells it with it.

Scoped to own_cores() like every exact set here: a vendor’s installed tile is not in our canonical alphabet’s history and cannot depart from it.

There are exactly two honest ways past a DEPARTURE failure:

  1. Keep the name. A rename that buys nothing is not worth an identity boundary.

  2. Bump SPEC_CANONICAL_VERSION and CANONICAL_PALETTE_VERSION in the same change, so every text recorded under the old palette is refused by version instead of read against a registry that cannot resolve it. Designs already on silicon do not re-enter the design cache across that boundary – their hash is stamped in a bitstream and the manifest recording it must not be rewritten – so they are rebuilt once, deliberately, rather than mis-recognized forever.

test_cores.test_the_canonical_palette_is_pinned_to_the_canonical_form_it_spells() → None

The other direction of the same coupling: a canonical-form bump that leaves this set alone has not said which palette the new version reads, and the departure message above would then name the wrong version.

test_cores._measured(**overrides)

A core carrying one measurement point, built here rather than read from the registry: which cores are migrated is a migration detail, and a test of the lookup should not move when that changes.

test_cores.test_exact_resource_measurement_resolves_with_parameter_defaults() → None
test_cores.test_resource_measurement_refuses_an_unmeasured_part() → None
test_cores.test_an_unclocked_measurement_answers_for_any_clock_and_records_no_timing() → None

A combinational core (identity-registers is one: a parameter ROM with no clock) has no timing to meet, so its point carries no timing status and prices a build at every clock.

test_cores.test_every_registered_core_with_resources_carries_measurement_points() → None

There is one shape for a resource record. A scalar count with no part, clock or parameters cannot say which board it was measured on and no longer parses.

test_cores.test_normalize_follows_the_same_rule_as_violation() → None

A type spelling is only for a parameter declared element_type; a plain parameter takes an int and refuses a string the way violation() does.

test_cores.test_violated_measurement_is_retrievable_but_not_a_usable_envelope() → None
test_cores.test_registry_is_hydra_composition_not_a_python_literal() → None

Composition IS the registry: cores load from dau-core’s hydra config tree into the ccflow ModelRegistry at /dau-core/<name>. A parallel Python-literal core list is the anti-pattern this guards against.

test_cores.test_accessors_defer_to_a_composed_registry() → None

The composed registry is the source of truth: accessors read through to /dau-core (no snapshot cache), so a consumer’s hydra overrides are visible and never clobbered by a default reload.

test_cores.test_silent_on_success_operator_set_is_pinned() → None

The status contract’s two classes are registry truth: silent-on-success cores (chain-stage/partition legal) versus per-batch success close-out cores (terminal-tile legal). Changing a core’s class changes lane status semantics — confirm intent here.

test_cores.test_dispatcher_rate_still_needs_record_aware_modeling() → None

The dispatcher’s framing-shaped rate describes a 2-word record. Its 64-bit front ingests one WORD per cycle, so an N-word record costs N cycles, while a wide framing delivers a whole record per beat-slot — two rules the current rate shapes cannot express together. Record shape is now declared for detection, but this pins the remaining rate-model gap so RECORD_WORDS != 2 is not silently treated as resolved.

test_cores.test_authoritative_models_reject_impossible_values() → None
test_cores.test_parameter_spec_rejects_incoherent_constraints() → None
test_cores.test_parameter_spec_violation_is_the_single_constraint_source() → None
test_cores.test_an_element_type_parameter_accepts_a_width_or_a_spelling() → None

The two forms are the same declaration where they overlap, and the spelling reaches types a width never could.

test_cores.test_an_element_type_parameter_bounds_the_width_not_the_encoding() → None

A registry bound mirrors an RTL guard about BITS. q16.16 encodes as 4128 and is a 32-bit type; bounding the encoding would reject it for being a large number, which is a statement about nothing.

test_cores.test_an_element_type_spelling_is_refused_where_no_type_is_declared() → None

A size parameter takes a size. Silently reading “int32” as 32 on a capacity is the misreading the whole mechanism exists to prevent.

test_cores.test_an_element_type_default_must_name_a_type_the_spec_admits() → None
test_cores.test_a_measurement_coordinate_may_name_the_type_it_was_measured_at() → None

The same point, written either way, is one point – so migrating a registry entry to spellings cannot orphan an envelope that was measured before types existed.

test_cores.test_storage_intent_prices_against_declared_parameters() → None
test_cores.test_storage_intent_refuses_an_undeclared_scale_parameter() → None
test_cores.test_storage_intent_without_scale_is_a_fixed_cost() → None
test_cores.test_storage_bytes_refuses_illegal_scale_overrides() → None
test_cores.test_a_core_resolves_hdl_from_the_package_that_declares_it(tmp_path, monkeypatch) → None

A tile contributed by another distribution finds its own HDL.

The registry is a hydra search path, so any package joining it through the hydra.lernaplugins entry point can contribute cores. Their HDL used to be resolved under dau_core.hdl regardless, so a third-party tile could be registered from anywhere but had to vendor its Verilog into this package. source_package is the seam.

test_cores.test_a_well_formed_vendor_tile_does_not_trip_our_palette_guards(monkeypatch) → None

Installing a third-party tile must not fail THIS suite.

Four guards here assert an exact set over the whole registry – the HDL directory listing, the descriptor-tagged operators, the envelope-free tiles, and the scalar-envelope holdouts. Each is a statement about dau-core’s own palette, and each read loaded_cores(), so a vendor tile registered through the entry point showed up as drift in all four. A contributor’s first experience of the platform was our test suite failing on their correct tile.

The line drawn is between those four and the universal-property guards (every operator has a golden, a contract kind, record words, a measured envelope). Those are contract requirements a well-formed tile satisfies, so they stay registry-wide on purpose – which is why the tile below is built well-formed rather than minimal. It is the exact-set guards that fail even a perfect vendor tile, and only those are scoped.

test_cores.test_a_core_naming_an_uninstalled_hdl_package_refuses_clearly() → None

The failure names the missing distribution rather than surfacing an ImportError from inside a path resolution.

test_cores.test_a_measured_point_matches_a_derived_clock_period() → None

A clock period is DERIVED (1000 / job_clock_mhz), so exact float equality is the wrong test.

150 MHz gives 6.666666666666667 while a registry writes 6.66667: the same physical clock, and the lookup refused it as unmeasured while printing the point it had just rejected. Real clock tiers differ by more than a nanosecond, so a picosecond tolerance keeps the “never a neighboring point” guarantee intact while tolerating representation.

test_cores.test_an_unresolvable_hdl_source_says_so() → None

A declared source that does not resolve is a DECLARATION error.

An out-of-tree tile whose HDL directory is not an importable package resolves to a MultiplexedPath that prints the right path and does not exist, so the first symptom used to be a synthesis run against a missing file. The requirement – an __init__.py beside the .sv files, so importlib can traverse the directory – is stated in the error rather than left to be discovered.