Skip to content

Publish integrated RustEDA 0.4.3 timing progress and shared documentation - #2

Draft
gaochangw wants to merge 24 commits into
mainfrom
codex/unified-brand
Draft

gaochangw wants to merge 24 commits into
mainfrom
codex/unified-brand

Conversation

@gaochangw

@gaochangw gaochangw commented Oct 25, 2026 •

Copy link
Copy Markdown
Member

The RustEDA integration branch documents the 0.4.3 timing scope: propagated primary clocks, bounded SPEF import, effective-capacitance waveforms and non-tree RC networks. The homepage now describes the implemented SPEF and propagated-clock support. Checker limits and pulse-width residuals remain explicit; mixed-library SRAM and derate work stays experimental.

The README and documentation use Signal Forge artwork: a 256×256 mark, a 760×176 wordmark displayed at 360px, and a 1200×400 84-frame banner. The timing illustration includes SPEF. Responsive images omit fixed HTML heights.

Validation: source links, strict MkDocs builds and rendered links pass for the integration and standalone documentation. The unified RustEDA site passes publication and repository-boundary checks. This documentation update introduces no algorithm or new EDA performance claim. The branch retains the existing integration changes; standalone main receives a separate documentation-only update and is not merged here.

gaochangw and others added 24 commits October 23, 2026 13:25
Add the pin limit checks that block-level signoff needs next to setup and
hold (docs/specs/sta/limits.md, STA-REQ-0800 to STA-REQ-0832):

- min_pulse_width and minimum_period groups become pulse checks of their
  pin instead of unanalyzed arcs: widths on the ideal or propagated clock
  waveform with the latest opening and earliest closing arrival, required
  widths at the opening transition time, the worst conditional group, and
  an unchecked count for pins no clock reaches (T0133).
- max_transition, max_capacitance and max_fanout from library pin limits
  and defaults and from set_max_transition, set_max_capacitance,
  set_max_fanout (design, port and clock-domain slots, last command per
  slot wins, tightest source applies) and set_fanout_load; inapplicable
  options and objects are reported (T0130, T0131) and the analyzed
  commands no longer carry D0021.
- Rows are kept in a bounded heap per corner and kind (--max-limit-rows,
  T0134) and written to a new limits table (limits.rbin, LIMITS v1) with
  the timing table; update --verify-full and session verification compare
  it bit for bit. Counts go to the SCOPE of sta.rbin, the run/update/query
  and whatif metrics, and the sta summary and status (drv_status,
  pulse_width_status); rusteda show reports a summary without drv_status
  as unchecked with null counts, and the shared builder writes it so.
- Report sections limits, pulse_width, min_period, drv, max_transition,
  max_capacitance, max_fanout and hold_fix (per-corner hold violators with
  needed delay, driving net and the worst hold path with nets and pin
  slack windows, plus a merged list).
- rusteda import takes repeatable --spef/--spef-corner pairs into a
  PARASIT v2 table that keeps and replaces corners (RCLI-REQ-0075); every
  analyzed corner uses its own extraction and a corner without one fails
  with T0070. --require-wire-model on run, update and whatif rejects a
  revision timed with another wire model (T0135).
- inspect, its instance pins and the pins section reported the hold-side
  required time as required_ns and the setup one as required_hold_ns; they
  now give required_setup_ns and required_hold_ns at the worst slack's
  transition. report --kind now applies to the endpoints section.

Tests derive every value by hand on synthetic constant-table libraries
(engine tests/limits.rs, CLI tests/signoff_cli.rs, shared import_spef.rs
and show_drv.rs).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Bump the workspace version to 0.4.0 and record the pin limit checks,
per-corner parasitics, wire-model requirement, hold-fix report and the
inspect and report fixes in the changelog.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The hold_fix section listed every endpoint of every corner with its
names before filtering; it now takes the shown endpoints from the hold
order of each corner and counts and merges from the slack table, naming
only the rows it prints (STA-REQ-0830 to STA-REQ-0832, AGENTS rule 3.4).

The rows kept by the limit checks (at most the row budget or the node
count per kind) now enter the per-corner state budget checked before
propagation (STA-REQ-0810, T0023).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…rner in paths

Fixes from the independent verification of the 0.4.0 signoff checks
(docs/specs/sta/limits.md):

- One status rule for the revision summary and every envelope
  (STA-REQ-0813, engine::limits::status): met, violated, partial,
  unconstrained or unchecked. Unclocked pulse pins make the pulse status
  unchecked (nothing evaluated) or partial, never met; a count without a
  checked row is null. Each design rule gets its own status
  (max_transition_status, max_capacitance_status, max_fanout_status); a
  rule without any limit is unconstrained with a null count and makes
  drv_status partial. Checks whose value, limit or slack is not finite
  are counted as unevaluated (T0137, completeness
  unevaluated_limit_checks, limits.rbin KINDS now 56 bytes) instead of
  being dropped silently.
- The shared Liberty reader consumes min_pulse_width_high,
  min_pulse_width_low and min_period as unconditional scalar pulse arcs
  of their pin (LIBERTY-REQ-0049) instead of ignoring them (Rule 7), so a
  library that states only the attributes is checked; with groups, the
  largest constraint applies (STA-REQ-0801).
- Pulse widths on an ideal clock are the declared waveform with the clock
  latencies; the analysis notes T0139 per corner and the measured
  difference to the reference tool is documented (STA-REQ-0815).
- path --to (and pin/port targets) gives the worst path in --corner, or
  over all corners without it, scanning the ranked paths; a requested
  family without a path warns T0138 (STA-REQ-0814).
- Row sections report the checked count as total, with stored, truncated
  and unevaluated (STA-REQ-0811).
- The per-corner state estimate counts the parsed SPEF of every analyzed
  corner, and one import holds at most eight per-file budgets of decoded
  SPEF (T0072, RCLI-REQ-0075).
- The changed arc classification gets the new ID STA-REQ-0017; the old
  STA-REQ-0013 text moves to legacy.md.
- cancel_at_every_point cancels at every event before the last phase
  ends: the notes of a finished run follow its last checkpoint, and the
  synthetic pulse arcs add notes for the wt_full flops.

Shared files changed (verification/shared.sha256): rusteda-formats
liberty/build.rs, liberty/classify.rs, tests/liberty_cells_and_pins.rs;
rusteda-cli import_spef.rs and tests/import_spef.rs; docs/specs/core,
docs/specs/liberty, docs/specs/rusteda-cli/spef.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…identity

Fix round 2 of the 0.4.0 signoff checks.

- Keep the Liberty pin attributes min_pulse_width_high/low and min_period
  as Pin fields (LIBERTY-REQ-0049) instead of synthetic timing arcs; the
  compiled library format LIBERTY v4 carries them (WS-REQ-0117) and a
  cached v3 .rlib is compiled again. The frozen legacy test
  sta_view_model.rs is restored unchanged.
- Add --pulse-groups worst|last and --pulse-pins all|clock-ends to run and
  update (STA-REQ-0816, STA-REQ-0817): the last listed group per
  transition and checks only where a clock ends, as observed black-box on
  the reference; pass-through pins are counted (T0141) and make the pulse
  status partial. Record the rules in scope.pulse_rules, the sta.rbin
  scope and the limits table.
- inspect of an endpoint reports the required times of its worst setup
  and hold path, consistent with its endpoint slacks (latch data pins).
- report --section endpoints --kind hold orders by hold slack by default.
- Lower a corner through one function for the analysis and the store's
  backward pass, so update and run commit identical sta.rbin with SPEF.
- A design rule limited on some pins only is partial, not met.
- Warn T0140 when an import drops the parasitics table (RCLI-REQ-0076).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ected pins

Design rules on tie cells and constant nets now follow the observed reference
behaviour: drivers of constant nets are not checked for max_capacitance and
max_fanout (counted, note T0143), and pins without a propagated transition are
checked for max_transition with a static transition from the corner's delay
calculation (STA-REQ-0809); pins that still have none are counted as untimed
(T0145) and their limited checks are unevaluated, never silently skipped.
Pins of an ideal clock network are left out and counted (STA-REQ-0818, T0146).

`--clock-limits paths|domain` selects how a clock's -clock_path/-data_path
limits map to pins (STA-REQ-0808): `paths` (default) follows the constraint
definitions, `domain` reproduces the reference (data-path limit on the whole
domain, -clock_path alone not applied, T0144). The clock network pins on which
the scopes differ are counted under either scope (T0147).

Library pins that the netlist leaves unconnected are not pins of the design;
unconnected outputs are counted with their names (STA-REQ-0819, T0148).

The limits table CORNERS record grows to 80 bytes (unreleased LIMITS v1); the
envelope gains scope.drv_rules and completeness drv_* counts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s with a constant enable

The delay calculation of a pin's transition now ignores logic values (STA-REQ-0116): arcs that
constants, case analysis or false `when` conditions disable, the transitions a sense refinement
removes, and the clock-to-output arcs of sequential cells that a constant disables or no clock
reaches enter the transition merge as CSR arcs with an empty tag map (no arrival, no required
time). Tie outputs start at transition 0, constant ports keep their input transition, and the
propagated clock model seeds the other ports and tie cells. Levels order every arc that carries
a transition; a loop among them is cut with warning T0149.

- STA-REQ-0159 (replaces 0152): a unate arc whose sense the residual function contradicts is
  disabled (xor2 next to a tie timed both senses).
- STA-REQ-0161 (replaces 0154): a latch whose enable a constant holds active is transparent for
  late arrivals in their own tags; held inactive it is opaque.
- STA-REQ-0229 (replaces 0211): setup and recovery checks take the early, hold and removal
  checks the late transition of the capture clock pin.
- STA-REQ-0230: latch D -> Q keeps its library sense; note T0150 names cells whose latch group
  stores the inverted data pin.
- The independent checker follows the same rules; the const_mux_select derivation gains the
  transition at the multiplexer output.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ant pins, merge launched clock enables

The reference timing tool (black box, both default libraries) differs from 0.4.0 on five
structures next to constants; each now follows the reference:

- A flop or latch whose asynchronous clear or preset is held active is no longer a constant
  (STA-REQ-0162 replaces 0151): its clock-to-output arc launches and the cone below is timed
  and checked for capacitance and fanout. With the reset of a synthesized core under case
  analysis the old rule missed max_transition violators and was optimistic by up to 1 ns.
- A clock gate output (clock_gate_out_pin) is the conjunction of its clock_gate_clock_pin and
  clock_gate_enable_pin inputs: an enable or clock held at 0 makes it constant 0 whatever the
  test enable, state function or statetable say (STA-REQ-0162).
- A pin at a constant passes no arrival: wires of constant nets, wires into case-analysis load
  pins and cell arcs into pins held constant carry only their transitions (STA-REQ-0164). Checks
  that a false when disables are no longer timed where arrivals reach them; such endpoints are
  counted as disabled (STA-REQ-0163 replaces 0161).
- The propagated clock merges the transition of a launched signal that enters the clock network
  (a flop output into an AND clock gate or a clock-mux select), by repeating the clock
  propagation with the launch transitions as seeds until they no longer change, bounded and
  budgeted (STA-REQ-0714; STA-REQ-0117 replaces 0116).
- With ideal clocks, the pins that a clock reaches through arcs that constants disable belong to
  the ideal clock network for the design rules, and a flop clocked there launches its output
  transition at the ideal clock transition (STA-REQ-0822 replaces 0818).

The independent checker evaluates clock gate outputs the same way. New hand-derived tests in
tests/held_sequential.rs; superseded texts in docs/specs/sta/legacy.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Both tool repositories now vendor the same 209 shared files with the same
verification/shared.sha256; `cargo xtask shared diff` finds no difference.

From the synthesis tool's side the shared crates gain: the BLIF and AIGER
readers and `rusteda import --rtl` of .blif/.aag/.aig (RCLI-REQ-0021/0022),
diagnostic letters B and G (WS-REQ-0190), the streaming export from frozen
netlist tables with the frozen writer and the parallel Verilog writer, the
lexer fix for a colon followed by a comment, its fast flat netlist reader and
a 64 MiB budget on the full-reader fallback, and the blif/aiger specification
directories in `cargo xtask shared`. The show-DRV requirement is renumbered
RCLI-REQ-0023 because RCLI-REQ-0021 is the published BLIF/AIGER import. The
external-simulator oracle tests read RUSTEDA_* variables instead of names of
this repository.

The timing engine is unchanged. Against the pinned 78ea7cc binaries, the
sixteen-netlist corpus commits byte-identical netlist, constraints, sta and
limits tables and exports identical netlists; a private copy of the routed
dual-library signoff harness gives the same 710 gate results, and all 1922
command receipts and 186 workspace files are identical apart from version,
time stamps and program path. Gates: all-feature workspace tests 772 passed,
clippy, fmt, layout, coverage 587/0, fixtures check, verify all, verify pdk
--profile pr --require, deny, reuse and strict docs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… fF, stop launches into held outputs

RC driver of extracted pi loads (STA-REQ-0726 replaces STA-REQ-0721, new STA-REQ-0727):
- the Thevenin resistance is the forward NLDM delay sensitivity over 1 fF above the total
  load times -ln(1 - output threshold), at the total load (was the central sensitivity over
  1 % of the total load);
- a pi whose resistance is below 1/1000 of that resistance is lumped: delay and transition are
  the table values at the total capacitance. The fitted two-point waveform lies 3 to 5 % below
  the table transition of a nearly lumped load; the external transient shows the pi and its
  lumped total coincide there (new engine Ngspice case rc_driver_spice).
- Both rules were measured black box on synthetic linear Liberty tables and both PDKs. They
  close the GF180 ss + max reference-extracted parity failure (6.8 ps setup / 5.3 ps hold at a
  clock buffer with a 16.9 Ohm pi) and the sky130 clock-gater transition difference (V2-F6).
- Shared rusteda-compute rc.rs: additive gate_detail_with_resistance (gate_detail unchanged
  bit for bit, test added); manifest updated.

Sequential launches (STA-REQ-0164, STA-REQ-0156): a disabled clock-to-output launch launches
no arrival also where a clock reaches its clock pin, so an output pin held by case analysis is
not in the clock's domain (verifier failure V4-F1), and a launch that set_disable_timing
disables carries nothing. Hand-derived test in held_sequential.rs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…in the changelog

Documentation only; the pinned binaries of ebc7037 are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…et an option

The shared netlist import test named a third-party program in its doc comment,
function and temporary directory; it now describes the netlist it imports
(concatenations, part-selects in both directions, sized constants), and the doc
comment of the unresolved-cell test is attached to that test again. Two shared
comments that named this repository refer to the timing tool by its role.

The full Verilog reader's budget for a netlist that the streaming reader
declines is the option `rusteda import --max-netlist-ast-mib` (default 64 MiB,
requires --netlist, RCLI-REQ-0024); its V0300 error names the budget and the
option. 0.4.0 read such a netlist without a bound; the 0.4.1 changelog now says
so and how to read one as before, and that a part-select against the declared
direction or a decimal constant of more than 32 digits takes the full reader.
Measured: the full reader peaks at about 42 times the file size (1.07 GiB for a
26 MiB netlist, 95 MiB with the streaming reader), noted in the spec.

Results are unchanged against the 78ea7cc binaries (ruststa c407c742, rusteda
c8f71b63): the routed sky130/gf180 fixtures (final hold-closed designs on native
and external-extractor 3-corner SPEF, and the signoff fixture) give 228/228 identical
command outputs and 198/198 identical workspace files (108 rbin); the 16-netlist
corpus gives identical rev1/rev2 tables and identical `rusteda export` 16/16; a
netlist the streaming reader declines imports to the same table. Gates:
all-feature workspace tests 773/0/30, all-feature clippy, fmt, layout, coverage
588/0, fixtures check, shared check/diff (209 files, identical manifest in both
tool repositories), verify all 214/0, verify pdk --profile pr --require, deny,
reuse, markdown/strict docs/site checks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Brings feat/shared-convergence (25b0201, 6af9936) onto the sta3 stream (ebc7037, 268ad9a).
The only textual conflict was the generated requirement matrix: it is regenerated with
`cargo xtask coverage` (590 requirements, 0 gaps: the convergence's 588 plus STA-REQ-0726 and
STA-REQ-0727 from sta3).

Shared files: the convergence did not touch rusteda-compute rc.rs, so the merge keeps sta3's
additive gate_detail_with_resistance. `cargo xtask shared update` leaves the merged
verification/shared.sha256 unchanged (209 files), and the synthesis tool's copy now carries the
same rc.rs, so `cargo xtask shared diff` is clean both ways.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ires with the driver waveform (0.4.2)

STA-REQ-0728 (replaces 0726): the Thevenin driver's effective capacitance is one
Newton-Raphson correction of the driver system from the total load instead of the
converged end-of-ramp charge solution; resistance proxy and lumped regime unchanged.
STA-REQ-0729 (replaces 0722): the sinks of a net whose driver transition comes from a
resistive pi follow that driver's own waveform through one pole of their first moment.

Against transistor-level transients of both default PDKs' cells the converged charge
solution over-shields resistive loads; the new rules lower the mean driver delay error
from 3.1 to 1.8 ps (pi loads) and the sink arrival error on RC trees from 6.5 to 0.64 ps.
On the routed design set (32 cases x 3 corners, native and reference-extracted SPEF) the
largest endpoint difference against the reference timing tool falls from 5.21 to 0.97 ps.

Shared crate change is additive: rc::gate_one_step, rc::wire_from_driver.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…cted parts (0.4.3)

STA-REQ-0730: a net whose RC network has resistor loops after zero-resistance
contraction (two parallel resistors included) is solved on its nodal conductance
system instead of being rejected: breadth-first spanning tree passes, the Woodbury
identity and a Cholesky factor of the k x k loop resistance matrix give the exact
first moments in f64, checked against Kirchhoff's current law with refinement; the
pi takes sum C, sum C*tau, sum C*tau^2. Scratch and work are bounded by the state
budget. Note T0152 counts loops per corner. Tree nets keep the old passes bit for bit.

STA-REQ-0731: a component without a resistor path to the driver is joined to it
with zero resistance; its capacitance stays on the net, its sinks get no wire delay
(a lower bound) and warning T0151 names the first net and its members.
STA-REQ-0732 replaces STA-REQ-0703 (no rejection of cycles/disconnected nodes).

Evidence: external nodal simulator on five planted networks (moments 3e-15, sink
arrivals 0.08 ps); transistor-level buf_1 of both PDKs: wire delays within 0.2 ps
where the reference timing tool is 4-29 ps off on loops. The two reference-extracted
designs refused by 0.4.2 now pass the 1 ps endpoint gate (0.62/0.67 ps) and agree
per sink to 0.0001 ps; 44 tree-only routed cases are byte-identical to 0.4.2.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…inuous

The remaining pulse-width differences at sky130 slow-corner clock pins (1.28 to
1.86 ps on three final layouts) are steps of the reference timing tool's driver
transition as a function of the clock net's resistance (0.7 to 1.2 ps between
resistances 1 % apart); across a step the tools agree within 0.1 ps, and
transistor-level transients of the same cell and loads are continuous and
closer to the unchanged model beyond the step. The specification of
STA-REQ-0728 states it, and a unit test keeps the driver transition continuous
and non-decreasing in the pi resistance. Release code is unchanged (allocated
sections of the release binary identical; only the build id differs).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Chang Gao <gaochangw@outlook.com>
Signed-off-by: Chang Gao <gaochangw@outlook.com>
@gaochangw gaochangw changed the title Publish the integrated RustEDA revision and shared documentation Publish integrated RustEDA 0.4.3 timing progress and shared documentation Oct 28, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant