RTL cosim timing verification

The fifth and final group closes the cycle-approximate-Python loop: it reads the cycle count the RTL co-simulator measured for one transaction and compares it against the cycle count the Python golden predicted in Group 1. When the two agree within tolerance, the SimPy timing model has been experimentally validated against the RTL — the strongest claim Waveflow can make about its sim.

Step Produces What it does
extract_cosim_timing cosim_timing Runs waveflow.utils.cosimparse.CosimReportParser on the solution dir; serializes the kernel’s measured transaction-cycle count to results/cosim_timing.json
validate_timing timing_verdict Compares py_timing.transaction_cycles (Group 1) against cosim_timing.transaction_cycles; raises if the absolute delta exceeds tolerance_cycles (default 20)

The structured timing pair

Both timing-side steps deliberately emit structured JSON with named cycle counts — not pass/fail bits. This shape is what the future model-training workflow (per project-cycle-model-training) will consume to fit HwComponent timing parameters from a corpus of cosim runs.

results/py_timing.json (from Group 1):

{
    "transaction_cycles": 140,
    "transaction_seconds": 1.4e-06,
    "clk_freq": 100000000.0,
    "source": "py_sim",
    "events": { "samp_read_begin": ..., "samp_out_write_end": ... }
}

results/cosim_timing.json (this group):

{
    "transaction_cycles": 144,
    "report_path": ".../sim/report/poly_cosim.rpt",
    "vitis_version": "2025.1+",
    "source": "cosim",
    "top": "poly"
}

The parser handles both Vitis 2025.1+ (<top>_cosim.rpt table) and the legacy cosim.log shape — picked transparently per file presence.

The verdict

ValidateTimingStep produces results/timing_verdict.json regardless of pass/fail:

{
    "pass": true,
    "py_cycles": 140,
    "cosim_cycles": 144,
    "delta": 4,
    "tolerance": 20,
    "py_timing_path": "...",
    "cosim_timing_path": "..."
}

If delta > tolerance the build fails with RuntimeError. Either way the verdict file is written first — downstream tools can read the actual numbers without re-running the build.

The tolerance is a constructor parameter on the step (defaulted to 20). Tightening it is a one-line change once the model is refined.

How the model was calibrated

The first cosim run reported 144 cycles for nsamp=100, unroll_factor=1, in_bw=32. The Python sim with the default proc_latency=10 reported 110 — delta=34, over tolerance.

The fix was to bump PolyAccelComponent.proc_latency from 10 to 40 to absorb the RTL pipeline fill/drain and stream handshake overhead that the simpler “compute-latency” model didn’t capture. With that calibration:

  • py_cycles = 140
  • cosim_cycles = 144
  • delta = 4

This is the manual v1 of the model-training workflow described next.

What’s next

The structured timing artifacts emitted here are the input format for a future parameter-fitting step that will fit HwComponent.proc_latency / proc_ii / similar from a corpus of cosim runs across param_supports variants. Once that lands, calibration stops being a manual one-line edit and starts being a build-DAG step in its own right.

Run the whole pipeline

python -m examples.stream_inband.poly_build --through validate_timing --force --live-output

Requires Vitis HLS on PATH. Produces results/timing_verdict.json with a green pass=true when the model and the RTL agree.


Back to: Polynomial Accelerator overview


This site uses Just the Docs, a documentation theme for Jekyll.