From b0f4954774569ae3f72e1b5ca612861533897a15 Mon Sep 17 00:00:00 2001 From: dsengupta0628 Date: Tue, 11 Aug 2026 20:42:47 +0000 Subject: [PATCH] add bug reproducer Signed-off-by: dsengupta0628 --- dcalc/test/CMakeLists.txt | 1 + dcalc/test/dcalc_case_analysis_leak.ok | 10 +++++ dcalc/test/dcalc_case_analysis_leak.tcl | 59 +++++++++++++++++++++++++ dcalc/test/dcalc_case_analysis_leak.v | 12 +++++ 4 files changed, 82 insertions(+) create mode 100644 dcalc/test/dcalc_case_analysis_leak.ok create mode 100644 dcalc/test/dcalc_case_analysis_leak.tcl create mode 100644 dcalc/test/dcalc_case_analysis_leak.v diff --git a/dcalc/test/CMakeLists.txt b/dcalc/test/CMakeLists.txt index 6caa2a23..b572e07c 100644 --- a/dcalc/test/CMakeLists.txt +++ b/dcalc/test/CMakeLists.txt @@ -1,5 +1,6 @@ sta_module_tests("dcalc" TESTS + case_analysis_leak prima_report ) diff --git a/dcalc/test/dcalc_case_analysis_leak.ok b/dcalc/test/dcalc_case_analysis_leak.ok new file mode 100644 index 00000000..efb775b2 --- /dev/null +++ b/dcalc/test/dcalc_case_analysis_leak.ok @@ -0,0 +1,10 @@ + +load on constant net cn (ff) arrival at z (ps) +0 159.19 +50 159.71 +200 167.60 +500 181.63 +1000 205.57 + +arrival spread across the sweep: 46.38 ps (expected 0.00) + diff --git a/dcalc/test/dcalc_case_analysis_leak.tcl b/dcalc/test/dcalc_case_analysis_leak.tcl new file mode 100644 index 00000000..47cd4dca --- /dev/null +++ b/dcalc/test/dcalc_case_analysis_leak.tcl @@ -0,0 +1,59 @@ +# Delay calculation ignores set_case_analysis constants. +# +# GraphDelayCalc uses DcalcPred (dcalc/GraphDelayCalc.cc), whose searchFrom +# stops only at power/ground nets: +# +# return !(sdc->isDisabledConstraint(from_pin) +# || (net && (network->isPower(net) || network->isGround(net)))); +# +# SearchPred0::searchFrom (search/SearchPred.cc) instead stops at +# sim->isConstant(from_vertex). DcalcPred::searchTo returns true +# unconditionally where SearchPred0::searchTo returns !sim->isConstant, and +# DcalcPred::searchThru omits sim->isDisabledCond and the +# simTimingSense == none test. GraphDelayCalc.cc never references Sim at all. +# +# Consequence: in findDriverEdgeDelays (GraphDelayCalc.cc:1011) an arc whose +# source pin is an SDC constant still passes searchFrom/searchThru, so its +# delay and slew are computed and merged into the driver vertex -- including +# when that driver is a live, non-constant pin. +# +# Circuit (dcalc_case_analysis_leak.v): +# +# c --BUF u0--> cn ---A2\ +# AND2 u1 --> n1 --BUF u2--> z +# a -------------------A1/ +# +# set_case_analysis 1 c makes net cn constant. 1 is non-controlling for an +# AND, so n1 and z stay live and the A2->ZN arc is dead. The reported path is +# a -> u1 -> u2 -> z, which never traverses cn. +# +# Sweeping the wire load on cn must not change anything on that path. It +# does: cn's slew rides the dead A2->ZN arc into n1, and n1's slew sets u2's +# delay. The arrival column below should be flat and is not. + +read_liberty ../../examples/nangate45_slow.lib.gz +read_verilog dcalc_case_analysis_leak.v +link_design top + +create_clock -name clk -period 10 +set_input_delay 0 -clock clk [get_ports {a c}] +set_output_delay 0 -clock clk [get_ports z] +set_input_transition 0.010 [get_ports {a c}] + +set_case_analysis 1 [get_ports c] + +puts "" +puts "load on constant net cn (ff) arrival at z (ps)" +set arrivals {} +foreach load {0 50 200 500 1000} { + set_load $load [get_nets cn] + set path [lindex [find_timing_paths -path_delay max] 0] + set arrival [format %.2f [expr [$path data_arrival_time] * 1e12]] + lappend arrivals $arrival + puts [format "%-32s%s" $load $arrival] +} + +set delta [expr [lindex $arrivals end] - [lindex $arrivals 0]] +puts "" +puts "arrival spread across the sweep: [format %.2f $delta] ps (expected 0.00)" +puts "" diff --git a/dcalc/test/dcalc_case_analysis_leak.v b/dcalc/test/dcalc_case_analysis_leak.v new file mode 100644 index 00000000..a55c2dc2 --- /dev/null +++ b/dcalc/test/dcalc_case_analysis_leak.v @@ -0,0 +1,12 @@ +module top (a, c, z); + input a, c; + output z; + wire cn, n1; + + // set_case_analysis 1 on port c makes net cn constant. + BUF_X1 u0 (.A(c), .Z(cn)); + // 1 is non-controlling for AND2, so n1 is NOT constant. + AND2_X1 u1 (.A1(a), .A2(cn), .ZN(n1)); + // Consumes n1's slew, so slew corruption becomes a delay change. + BUF_X1 u2 (.A(n1), .Z(z)); +endmodule