write_path_spice: match side input values to the path arc's transitions (#475)

* write_path_spice: match side input values to the path arc's transitions

gatePortValues() chose side input values from the first CUDD cube of the
Boolean difference d(f)/d(input), which sensitizes the gate but ignores
the transition directions of the arc the path used:

- For non-unate gates whose Boolean difference is a tautology (xor2,
  xnor2) every side variable came back don't-care, and the unknown value
  fell through to tie-low in writeSubcktInstVoltSrcs() -- wrong whenever
  the path used the when-condition requiring the side high.
- For mux select arcs the cube was an arbitrary data assignment,
  unrelated to the output edge the path reported.

Either way the written deck's gate drives the opposite direction from
the reported path: the simulated chain switches with inverted polarity
from that gate onward, edge-qualified arrival measurements fail, and
the deck sums delays from the wrong rise/fall tables.

Constrain the side input condition to the cofactor pair matching this
arc -- f1 & !f0 when the input and driver edges agree (non-inverting),
f0 & !f1 when they differ (inverting) -- threading the gate input
RiseFall from the path stage into gatePortValues().  Also release the
CUDD nodes that were previously leaked (the old code Cudd_Ref'd the
Boolean difference after the generator was freed and never deref'd it).

Fixes #474

Co-Authored-By: Claude Fable 5 <[email protected]>

* test: write_path_spice
  arc-sense regression for #474, and outlined in #475

---------

Co-authored-by: Brian Degnan <[email protected]>
Co-authored-by: Claude Fable 5 <[email protected]>
This commit is contained in:
Brian Degnan
2026-07-27 10:23:15 -07:00
committed by GitHub
co-authored by Claude Fable 5 Brian Degnan
parent f476e269b9
commit 87ce5680df
10 changed files with 177 additions and 26 deletions
+3 -1
View File
@@ -514,11 +514,13 @@ WritePathSpice::writeGateStage(Stage stage)
const Path *drvr_path = stageDrvrPath(stage);
const RiseFall *drvr_rf = drvr_path->transition(this);
const Path *gate_input_path = stageGateInputPath(stage);
const RiseFall *input_rf = gate_input_path->transition(this);
const Edge *gate_edge = stageGateEdge(stage);
LibertyPortLogicValues port_values;
bool is_clked;
gatePortValues(input_pin, drvr_pin, drvr_rf, gate_edge,
gatePortValues(input_pin, drvr_pin, input_rf, drvr_rf, gate_edge,
port_values, is_clked);
PinSet inputs(network_);