Skip to main content

dau core

Hardware contracts, golden semantics, and the core registry for the DAU accelerator stack

Build Status codecov License PyPI

Overview

dau-core holds the definitions the other DAU packages share:

  • The core registry. Every HDL building block (streaming operator tiles, AXI stream infrastructure, shell adapters, shared packages) is described by a CoreDefinition: its module, sources, dependencies, golden model, testbench, measured resources, module parameters, and stream-contract facts.
  • Golden models. Each operator has a pure-Python reference implementation. Hardware results are compared byte for byte against it, so the golden defines what the tile computes.
  • Wire contracts. Register maps, stream framing structs, DMA constraints, capability advertisement, and composition specs.

The package also ships the SystemVerilog for every registered core. Every operator tile has a golden, a cocotb bench under Verilator, and measured resource points. The stream infrastructure and shell adapters are tested inside the composed shells instead of one by one. Five tiles generate their source from their parameters when rendered.

Documentation

The full documentation is at dau-dev.github.io/dau-core.

The core registry

Cores are declared in a Hydra config tree, dau_core/config/dau-core/cores.yaml, with one CoreDefinition entry per core, and loaded into the ccflow ModelRegistry at /dau-core/<core-name>. The package adds the tree to the shared Hydra search path through a hydra.lernaplugins entry point, so an application that composes Hydra configs finds the cores without importing dau_core.

from dau_core.registry import loaded_cores, core, sources_for

cores = loaded_cores()                     # name -> CoreDefinition, registry order
tile = core("int32-predicate-filter")      # one core
print(tile.kind.value)                     # "operator"
print(tile.golden)                         # "dau_core.operators:filter_values"
print(tile.resources)                      # measured LUT/FF/BRAM/DSP envelope

sources_for("stream-aggregation")    # dependency-closed HDL paths, in order

The palette has 46 operator tiles (filters, maps, ordered and hash-mode aggregations, joins, membership, sorters, partitioners, dispatchers, temporal operators, top-k, fixed-point transcendentals, and the stateful group), 5 stream-infrastructure blocks (AXI burst reader, broadcast, record writer, write mux, row unpacker), 4 shell adapters, 3 shared SV packages, and 1 simulation model: 59 entries in all. loaded_cores() returns the current list. If an application has already composed the registry, with or without overrides, the accessors read that composition instead of loading the packaged defaults.

Golden models

Each operator tile's behavior is defined by a pure function or small model in dau_core.operators or dau_core.temporal. Tile configurations are frozen pydantic models that mirror the tile's config ports, and the same object drives the golden, the testbench, and design emission. Their mapping fields are read-only, replace() is a model_copy that validates the result, and check() validates a model again on demand, so a copy that skipped validation is rejected before anything hashes or prices it.

from dau_core.operators import (
    PredicateOp, RowField, RowPredicateConfig, RowPredicateTerm,
    filter_rows_by_predicate, streaming_top_k,
)

config = RowPredicateConfig(
    term0=RowPredicateTerm(field=RowField.VALUE, op=PredicateOp.GT, constant=10),
)
rows = [(1, 5, 0, 0), (2, 25, 0, 0), (3, 11, 0, 0)]
filter_rows_by_predicate(rows, config)   # -> [(2, 25, 0, 0), (3, 11, 0, 0)]

streaming_top_k(rows, k=2)               # ORDER BY key DESC LIMIT 2, ties by arrival

dau_core.temporal covers the time-series operators (backward as-of join, market features, time/volume/dollar/imbalance bars, rolling moments, EWMA) in an exact-integer domain: divisions are deferred to the host, so goldens and hardware agree bit-for-bit.

Composition specs

A shell datapath is described as data: ScanCompositionSpec names registry cores, their config-port bindings, and module-parameter overrides for a one-scan-N-lanes design. Construction validates everything against the registry (operator kinds, status-contract roles, declared parameter bounds) and raises CompositionError before any HDL is generated; estimated_resources prices a spec from the measured envelopes.

from dau_core.composition import LaneSpec, ScanCompositionSpec, TileSpec, estimated_resources

spec = ScanCompositionSpec(
    name="bar-noc-4",
    lanes=tuple(
        LaneSpec(
            tile=TileSpec(core="bar-aggregation", config={"cfg_mode": "2'd0"}),
            partition=TileSpec(core="pair-key-filter",
                               config={"cfg_key_mask": "32'd3", "cfg_key_match": f"32'd{lane}"}),
        )
        for lane in range(4)
    ),
)
print(estimated_resources(spec, part="xc7a200tfbg484-2", clock_ns=8.0))

Pricing needs a part and a clock. Each core is looked up at exactly that part, clock, and parameter set, and a combination that has not been measured raises UnmeasuredResourceError naming it. Nothing is interpolated.

Wide lanes

A quad-row operator core takes one row per beat at the rate its ingest contract declares (one row per cycle or per two cycles, depending on the tile). A wide-row-stream core takes the reader's whole beat, SLOTS = data_width / 128 quad rows every cycle, with no dispatcher and no fan-out. The three row operators have wide counterparts (wide-row-predicate-filter, wide-row-map-alu, wide-field-sum-aggregation) that take the same configs in the same order; only the core names change.

data_width must equal SLOTS * 128 or construction raises CompositionError. A wide lane cannot use the packed front unpacker, because packing saves DMA bytes at the cost of job time and a wide lane needs whole rows.

from dau_core.composition import LaneSpec, ScanCompositionSpec, TileSpec, estimated_resources

spec = ScanCompositionSpec(
    name="q6-wide",
    data_width=512,   # SLOTS=4: four quad rows per cycle
    lanes=(
        LaneSpec(
            tile=TileSpec(core="wide-field-sum-aggregation",
                          config={"cfg_field_mask": "4'b0010"}),
            chain=(
                # shipdate >= 8766 AND shipdate < 9131
                TileSpec(core="wide-row-predicate-filter", config={
                    "cfg_field0": "2'd0", "cfg_op0": "3'd6", "cfg_constant0": "32'd8766",
                    "cfg_combine01": "2'd1",
                    "cfg_field1": "2'd0", "cfg_op1": "3'd3", "cfg_constant1": "32'd9131",
                    "cfg_combine2": "2'd0",
                    "cfg_field2": "2'd0", "cfg_op2": "3'd0", "cfg_constant2": "32'd0"}),
                # value = value * aux0 >> 15
                TileSpec(core="wide-row-map-alu", config={
                    "cfg_op": "3'd4", "cfg_dst_field": "2'd1",
                    "cfg_src_a_field": "2'd1", "cfg_src_b_field": "2'd2",
                    "cfg_shift": "5'd15"}),
            ),
        ),
    ),
)
print(estimated_resources(spec, part="xc7k325tffg900-2", clock_ns=8.0))

The rate model predicts rows / SLOTS / clock. At SF1 that is 6,001,215 / 4 / 125 MHz = 12.0 ms, and the job measures 12.4 ms on hardware.

Workflows and typed results

Multi-stage reference workflows are ccflow CallableModels with typed ResultBase results, so they can be registered and composed with Hydra like the rest of the package. dau_core.workflows.HeroWorkflow runs the temporal pipeline (as-of align, feature map, time bars, rolling moments) over the goldens and records the row count at each stage and a per-stage materialization cost (dau_core.hero).

from ccflow import GenericContext
from dau_core.temporal import generate_market_stream
from dau_core.workflows import HeroWorkflow

stream = generate_market_stream(seed=7, num_symbols=3)
result = HeroWorkflow(bar_width=64, roll_window=3)(GenericContext(value=stream))
print(result.funnel)   # input -> matched -> bars -> rolling row counts

Wire contracts

  • dau_core.registers: the DAU magic word, register/protocol versions, register offsets, reset scopes, and the stream-job register contract (trigger/status/buffer addresses).
  • dau_core.stream: Arrow-lite framing (BatchHeader, ColumnDescriptor, OperationDescriptor), logical types, operation codes, record-batch limits, and shared error codes.
  • dau_core.capabilities: DMA constraints and device/operator capability models populated from a live device.
  • dau_core.capability_contract: the composed capability advertisement a built shell publishes, derived from its composition spec.
  • dau_core.design: the operator-unit inventory parsed back from a synthesized design's manifest.

HDL and verification

dau_core/hdl/ holds the SystemVerilog for every registered core, five of them generated at render time. Tiles share a 64-bit valid/ready stream and status contract: input_last ends a batch, a terminal tile closes out with a status word and count, and mid-lane stages stay silent on success. The tests run at three levels, all from pytest:

  • text-contract checks over the packaged sources;
  • standalone Verilator benches;
  • cocotb-on-Verilator benches, golden-equal against the registered reference for each tile.

Installation

Requires Python 3.11 or newer.

pip install dau-core

Metadata

Release files for dau-core 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for dau-core 0.2.0
File Size Uploaded Provenance Actions
dau_core-0.2.0.tar.gz 579.7 kB Without provenance Details for dau_core-0.2.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for dau-core 0.2.0
File Interpreter ABI Platform Actions
dau_core-0.2.0-py3-none-any.whl Python 3 none any Details for dau_core-0.2.0-py3-none-any.whl

Total release size: 1.3 MB

Release files / dau_core-0.2.0.tar.gz

Download URL dau_core-0.2.0.tar.gz
Size 579.7 kB
Tags Source
SHA-256 checksum
How to use checksums
262d9e33577d71582ab95eefabaacc21841492f57e95254f8510e8a3b12287f5
BLAKE2b-256 checksum
How to use checksums
8dfd4de0e92ccfafe68b70df295225d0b2959332bdcc6ecf883da187fe11c722
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.15

Release files / dau_core-0.2.0-py3-none-any.whl

Download URL dau_core-0.2.0-py3-none-any.whl
Size 713.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
60685208c315be8cbcd9f901d51e49c2e8970cb34539098f708645d96245e4d4
BLAKE2b-256 checksum
How to use checksums
1c4d110de96994c9936d1170b130134685e9e8acc707972f1c6790dd2c02b579
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.15

Security for dau-core 0.2.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page