PrimeTime Writes Wrong Conditional WIDTH in SDF? The Parallel Constraint Arcs Trap
When a pin carries two parallel min_pulse_width constraints with different sdf_cond — like an eFuse STROBE in read vs program mode — PrimeTime writes both COND WIDTH lines with the same merged (min::max) values. The fix is one variable, but it has to be set before link_design, which trips up everyone who relies on restore_session.
01Where This Comes From
An eFuse hard macro on a TSMC 28nm SoC. The vendor library defines two min_pulse_width constraints on the STROBE pin — one for read mode (~142 ns) and one for program mode (~11000 ns) — distinguished only by sdf_cond strings such as check_read_start and check_pgm_start. After full PrimeTime signoff, the SDF written for gate-level simulation contained two COND WIDTH lines on STROBE, and both reported the same (min::max) pair: 142.4570 :: 11000.0000.
That output looks plausible at first glance — the values are right. But it is silently wrong: the two values do not belong to the same condition. PrimeTime has merged the read-mode pulse-width value with the program-mode pulse-width value into a single (min::max) bounding pair, and then stamped that pair on every COND WIDTH line for the same pin.
When the gate-level simulator picks up that SDF, every WIDTH check on STROBE — whether the design is in read or program mode — will be evaluated against the wrong upper bound. False violations during functional simulation, real ones potentially masked. Either way, the SDF is no longer a faithful reflection of the library.
02The Symptom
Two parallel min_pulse_width entries in the lib become two COND WIDTH lines in the SDF, but the numeric values are mixed across conditions instead of staying per-condition.
03What Liberty Actually Encodes
Two parallel min_pulse_width constraints with mutually-exclusive when expressions — a standard pattern for IPs with mode pins.
- •Mode Pins Drive the Conditions
PD, CSB, PGENB, LOAD, PS — five mode pins on the eFuse. The when string of each min_pulse_width describes a unique functional state.
- •sdf_cond Is the Output Tag
Each min_pulse_width carries an sdf_cond string that the SDF writer is supposed to emit verbatim as the COND clause. It is the only handle the SDF has on which functional state the value belongs to.
- •Mutual Exclusivity Is a Lib Rule
Library Compiler will warn if the when conditions of parallel min_pulse_width entries are not mutually exclusive. If the lib is clean, only one constraint is ever active in any real silicon state.
- •constraint_high Is the High-Pulse Width
min_pulse_width () { constraint_high : N; } sets the minimum required width of the high pulse. The two constraints in this case differ by ~80x — read-mode 142 ns vs program-mode 11 us.
04Root Cause: Parallel Constraint Arcs Are Merged at Link Time
PrimeTime, by default, stores parallel constraint arcs in a bounding form. Two min_pulse_width values on the same endpoint do not survive link_design as two distinct values — they collapse into a single (min, max) pair stored on the bundled arc. write_sdf then emits the two COND lines from the same merged pair.
05The Variable: timing_parallel_constraint_arcs_compatibility
One application variable controls the entire behavior. Default value, false. To get per-condition SDF output, set it to true.
- 01Default Is falsePrimeTime ships with timing_parallel_constraint_arcs_compatibility set to false. Parallel constraint arc values are merged into bounding pairs at link time. This is the source of the SDF symptom.
- 02Set It to true to Disable Mergingset timing_parallel_constraint_arcs_compatibility true tells PrimeTime to keep all parallel constraint arc values intact. Each sdf_cond keeps its own constraint_high value through link, update_timing, and write_sdf.
- 03It Has to Be Set Before link_designThe Synopsys man page is explicit: 'This variable must be set before the link_design command is run.' link_design is when parallel arc storage is decided. Setting the variable later changes nothing.
- 04The Compatibility HintThe variable name and description both signal that the non-merged behavior used to be the default. If a legacy script wrote correct SDF without ever setting this variable, it almost certainly ran on an older PrimeTime where merge was off by default.
06The Timing Trap: restore_session Does Not Help
The single most common way teams burn an afternoon on this issue is setting the variable in the wrong place. PrimeTime sessions store the linked timing graph, not the application variable state, so any variable that influences linking has to be set in the session that originally ran link_design — not in a session that restores the result.
07PT vs Tempus: A Related Conditional Pulse-Width Difference
The same eFuse setup also produces a violation in PrimeTime that Cadence Tempus does not flag. Different issue, same root structure: how each tool treats conditional min_pulse_width constraints when no explicit case_analysis is given.
On the same STROBE pin, PrimeTime reports a min_pulse_width violation against the program-mode requirement of 11000 ns, even when the SoC is in functional read mode and the actual STROBE pulse is ~114 ns. Slack reports as -10886 ns. Tempus, on the same database, reports nothing.
PrimeTime does not symbolically evaluate the when expression of a conditional min_pulse_width. It cannot tell that PD, CSB, PGENB, LOAD, PS are constrained into a state that makes check_pgm_start unreachable. Without an explicit case_analysis on those mode pins, both conditional constraints stay active, and the worst one drives the violation.
Tempus appears to apply a different default for unresolved conditional pulse-width checks — closer to 'do not report unless the condition is reachable.' Neither behavior is incorrect; they are different defaults for the same ambiguous input. In PrimeTime, the fix is to lock the mode pins with set_case_analysis so the program-mode constraint is automatically deactivated, or to disable the program-mode arc directly with set_disable_timing on the corresponding timing arc.
08The Fix Recipe
A clean, repeatable PrimeTime flow that produces per-condition SDF and avoids the spurious mode-conditional violations. Treat this as a checklist for any IP that uses parallel conditional constraints — eFuse, OTP, custom analog wrappers, anything with mode-dependent min_pulse_width or min_period.
09How to Verify the Output Is Correct
Three checks confirm that the fix landed and the SDF is faithful.
- •1. Confirm the Variable Is Active Before link_design
printvar timing_parallel_constraint_arcs_compatibility right after set, and again immediately before link_design. Use report_app_var -only_non_default to spot-check the full set of overrides.
- •2. Verify sdf_cond Survived in the Library
After link, query: foreach_in_collection a [get_lib_timing_arcs -of [get_lib_pins '*/STROBE']] { echo "[get_attribute $a sdf_cond] [get_attribute $a when]" }. Empty sdf_cond fields mean the .db was compiled without preserving the strings — recompile from the original .lib.
- •3. Diff the SDF Per-Condition
After write_sdf, grep for the pin and confirm each COND WIDTH line carries (X::X) where X matches the constraint_high of that specific when. If two lines on the same pin still share an identical (min::max) pair, the merge happened — go back and check that the variable was set before link.
10What Else Can Affect This
The variable does not operate in isolation. A few neighboring settings either reinforce, mask, or override its effect.
11Why This Pattern Repeats Across Projects
Conditional min_pulse_width and min_period constraints appear in any IP with mode pins — eFuse, OTP, MTP, PLLs with mode controls, certain ADC sample clocks. The library encoding is standard. The signoff failure modes are also standard.
12Closing Note
Most of the engineering risk in modern signoff is no longer in the math; it is in what the tools assume by default and how those assumptions interact with library encoding. The conditional min_pulse_width / SDF case is a clean example: one variable, one ordering rule, one library convention — and a failure mode that survives full STA signoff and lands in gate-level simulation as silent corruption.
If your project uses eFuse, OTP, or any IP with mode-dependent pulse-width constraints, audit the SDF you hand off to gate-level simulation. Look for COND WIDTH lines on the same pin sharing identical (min::max) values — that is the fingerprint of this trap, and it is fixable in one line of TCL placed in the right file.
Hitting an SDF or signoff anomaly you cannot explain?
We have spent more time than we would like inside PrimeTime variables, lib compilation, and tool default differences. Send the symptom — we will tell you whether it is a setup issue, a tool bug, or something the lib is hiding.
References
- [1]
- [2]
- [3]Liberty Reference Manual — min_pulse_width and sdf_condSynopsys / OSCI Liberty
