Debugging Unconstrained Timing Paths
A practical guide to unconstrained timing paths: why "no constrained paths found" is dangerous, the short list of causes (disabled arcs, set_clock_sense, case analysis, false paths, exclusive clock groups, missing library arcs, clock or delay on a data pin), and the commands to confirm and fix each.
An unconstrained timing path is one the tool refuses to check. You ask for it with report_timing and get back nothing, either a blunt 'no constrained paths found', or the path shows up only under an -unconstrained option. It is dangerous precisely because it is silent: an unchecked path looks perfectly clean in every summary while being wide open in silicon. Chasing these down until every real path is constrained is a core signoff skill, and the reasons fall into a short, learnable list.
Two symptoms, one goal
There are two things you can see. Either the path is reported as unconstrained (the tool found it but has no check to apply), or it is not reported at all (the tool cannot even trace from the start point to the end point). The first is usually a constraint that killed the check; the second is usually a break in the timing graph. The goal in both cases is the same: find the exact pin or arc where the check or the trace dies, then decide whether it is a real exception you meant or a mistake to remove.
When the path is reported as unconstrained
Ask the tool for the reason first (in Tempus, report_timing -debug unconstrained; in PrimeTime, check_timing -verbose flags unconstrained and unclocked endpoints). The reason it prints maps directly to a fix. These are the common ones.
| Why it is unconstrained | How to confirm | How to fix |
|---|---|---|
| A check arc is disabled (set_disable_timing) | The coverage report marks the endpoint untested; the inactive-arc report shows the CK to D arc disabled | Reset the disable on that arc |
| The clock is stopped by set_clock_sense | Clock-propagation report shows the clock stopping at a pin | Reset the clock sense on that pin |
| A constant from set_case_analysis disables the arc | Case-analysis report traces the constant back to its source pin | Reset the case analysis at the source |
| A false path covers it (set_false_path) | The applied-exceptions report names the false path | Remove the false path if it was not intended |
| Launch and capture clocks are exclusive (set_clock_groups) | The clock-groups report lists them as logically exclusive | Reset the group, or replace it with the right exception |
| An input port has no clock-referenced input delay | The reason reads unconstrained input port | set_input_delay -clock on the port |
| No clock reaches the launch flop CK | Clock-propagation report shows propagation stopped in the clock path | Fix the disabled arc or clock definition upstream |
When the path is not reported at all
If the tool will not report the path even as unconstrained, the timing graph itself is broken between the two points. Trace it: run report_fanin (or all_fanin from the endpoint and all_fanout from the start point) and watch where the trace stops. The pin where the start-to-end connection breaks is your suspect, and it usually points at one of these.
- A missing library arc: the cell at that pin has no timing arc, or is missing just its rise or fall arc, so the tool cannot propagate through it. Confirm with a cell-timing report that shows no arc, then fix the .lib.
- A clock or set_input_delay defined on a data pin: the pin reports is_clock_used_as_data as true. A stray create_clock or input delay on an internal data pin turns it into a start point and cuts the path behind it. Remove the stray constraint.
- A set_max_delay or set_min_delay across the path: an intermediate pin returns a delay_max_rise (or min) value. The max/min-delay exception re-groups the path so the original endpoint is never checked. Keep it only if you meant it.
To pin down where a broken path dies without reading a huge fanin dump, bisect it. Report timing point-to-point from the start point to a pin in the middle: if it reports, the break is downstream of that pin; if it does not, the break is upstream. Move the midpoint and repeat, and a few tries corner the exact offending instance.
Never clear a constraint just to make a path appear. Half of these reasons (false paths, clock groups, case analysis, disabled scan arcs) are correct constraints doing their job, and removing them creates fake violations or, worse, hides a real functional exception. Confirm the reason, then decide whether the constraint was intended before you reset anything.
The discipline behind this: run a constraint audit (check_timing in PrimeTime, the equivalent in Tempus) early and after every constraint change, so unconstrained and unclocked endpoints surface as a small list you clear deliberately, rather than a surprise at signoff. An empty check_timing report is one of the quiet signs a design is genuinely ready.