Tcl · Module 20
Reviewing a Constraint Set
A wrong constraint set does not produce an error. It produces a confident timing report that means nothing — so the review has to be a program, not a reading.
Advanced18 min readtcledapart-iisdcreviewchecklistquality
Part II · Module 20 · Chapter 20.8 · Reviewing a Constraint Set
Everything in this module shares one failure mode: a wrong constraint set does not produce an error. It produces a clean, confident timing report that happens to mean nothing.
So the review cannot be somebody reading the file and feeling satisfied. It has to be a script that proves it — and because a .sdc file is Tcl (Chapter 20.1), you can write one.
1. What the review must establish
Four things, from the registry's own list:
- Every clock declared — and the right kind, primary or generated.
- Every input and output timed — no port left on the optimistic default.
- Every exception justified — a recorded reason, not a bare constraint.
- Multicycle paths complete — both setup and hold stated.
Each is mechanically checkable. §6 is about the things that are not.
2. An incomplete set
Here is a constraint set that looks reasonable:
create_clock -name core_clk -period 2.0 [get_ports clk]
set_input_delay 0.4 -clock core_clk [get_ports {d_in[*]}]
set_false_path -from [get_ports reset_n] -to [get_cells u_core]
set_multicycle_path 2 -from [get_cells u_cfg] -to [get_cells u_core] -setupA clock, input delays on the data bus, an exception, a multicycle. Run the review against it:
=== an incomplete constraint set ===
ok 1 clock(s) defined
ERROR 3 input port(s) with no input delay: ref_clk, reset_n, cfg_mode
ERROR 2 output port(s) with no output delay: d_out[0], d_out[1]
ERROR 1 false path(s) with no recorded reason
ERROR a multicycle -setup was declared with no matching -hold
---
4 problem(s)3. The review script
proc review_constraints {} {
set problems 0
# 1. is there a clock at all?
if {[llength $::sdc::clocks] == 0} {
puts stderr " ERROR no clock is defined"
incr problems
} else {
puts " ok [llength $::sdc::clocks] clock(s) defined"
}
# 2. every input port timed (except the clocks themselves)
set clk_ports {}
foreach c $::sdc::clocks { lappend clk_ports [lindex $c 2] }
set timed {}
foreach d $::sdc::idelays { lappend timed [lindex $d 0] }
set untimed {}
foreach_in_collection p [get_ports *] {
if {[get_attribute $p direction] ne "in"} { continue }
if {[lsearch -exact $clk_ports $p] >= 0} { continue }
if {[lsearch -exact $timed $p] < 0} { lappend untimed $p }
}
if {[llength $untimed]} {
puts stderr " ERROR [llength $untimed] input port(s) with no input delay: [join $untimed {, }]"
incr problems
} else {
puts " ok every input port has an input delay"
}
# 3. every exception justified
set unjustified 0
foreach f $::sdc::falsepath { if {[lindex $f 2] eq ""} { incr unjustified } }
if {$unjustified} {
puts stderr " ERROR $unjustified false path(s) with no recorded reason"
incr problems
} else {
puts " ok every false path has a reason"
}
# 4. multicycle paths state both sides
set sides {}
foreach m $::sdc::mcp { lappend sides [lindex $m 3] }
if {[lsearch -exact $sides "setup"] >= 0 && [lsearch -exact $sides "hold"] < 0} {
puts stderr " ERROR a multicycle -setup was declared with no matching -hold"
incr problems
} elseif {[llength $::sdc::mcp]} {
puts " ok multicycle paths state both setup and hold"
}
puts " ---"
puts " $problems problem(s)"
return $problems
}The output-port check is the input check with out substituted, and is omitted above for length.
Four Part I decisions in that procedure, and each is from Chapter 15.9:
- Problems go to
stderr, the summary tostdout— so the check runs in a pipeline and the diagnostics still reach a human (Chapter 14.9 §2). - It reports the
okcases too. A check that only speaks when unhappy leaves you unsure whether it ran. Fiveoklines is evidence. - It names the offenders, not just the count —
ref_clk, reset_n, cfg_modeis actionable where "3 ports" is not. - It returns a count, and the caller decides the exit status. The procedure never calls
exit(Chapter 15.4 §3).
4. A complete set
The same review against a constraint set that does the job:
set PERIOD 2.0
create_clock -name core_clk -period $PERIOD [get_ports clk]
create_clock -name ref_clk -period 10.0 [get_ports ref_clk]
foreach_in_collection p [get_ports {d_in[*]}] {
set_input_delay [expr {$PERIOD * 0.20}] -clock core_clk $p
}
set_input_delay [expr {$PERIOD * 0.20}] -clock core_clk [get_ports reset_n]
set_input_delay [expr {$PERIOD * 0.20}] -clock core_clk [get_ports cfg_mode]
foreach_in_collection p [get_ports {d_out[*]}] {
set_output_delay [expr {$PERIOD * 0.15}] -clock core_clk $p
}
false_path [get_ports cfg_mode] [get_cells u_core] \
{cfg_mode is static after reset; software sets it before the core runs}
set_multicycle_path 2 -from [get_cells u_cfg] -to [get_cells u_core] -setup
set_multicycle_path 1 -from [get_cells u_cfg] -to [get_cells u_core] -hold
set_clock_groups -asynchronous -group {core_clk} -group {ref_clk}=== a complete constraint set ===
ok 2 clock(s) defined
ok every input port has an input delay
ok every output port has an output delay
ok every false path has a reason
ok multicycle paths state both setup and hold
---
0 problem(s)Four problems to zero. And notice what the complete file is made of: a variable for the period, loops over the buses, the false_path wrapper from Chapter 20.5 §4, and a paired multicycle — all of which are Part I applied to constraints.
5. Running it
As part of the flow, not on request:
source constraints.sdc
if {[review_constraints] > 0} {
puts stderr "constraint review failed — not proceeding"
exit 1
}Three properties worth insisting on:
- It runs every time, immediately after the constraints are read. A check somebody has to remember is run after the problem is expensive.
- It fails the build. A non-zero exit so the surrounding automation stops rather than spending four hours on a run that cannot mean anything.
- Its output is in the log, so two runs can be compared and a regression is visible.
6. What a script cannot check
The honest half, and it matters as much as the script.
Mechanical — the script handles these:
- Is there a clock? Are all ports timed? Does every false path have a reason? Is every multicycle paired? Is every clock in exactly one group?
Not mechanical — a human must:
- Is the period right? The script sees 2.0; only the specification says whether that is correct.
- Is the budget right? 20% input and 15% output is a decision, not a fact — Chapter 20.4 §5.
- Is a false path's claim true? The reason is recorded; whether it is still correct needs somebody who knows the design.
- Is there a synchroniser behind each clock group? Chapter 20.7 §5 — the constraint cannot tell you, and neither can simulation.
- Is an exception covering a design problem? The hardest one, and the most consequential.
7. The review as a document
The constraint set is a design document, and the review has a human half worth running at every milestone:
- Read every exception and ask whether its reason still holds. Designs change; claims do not update themselves.
- Count the exceptions. A handful is normal; a long list usually means something structural is being papered over.
- Check the clock periods against the specification, not against memory.
- Check the I/O budget adds up, and that the far side of each interface agrees — Chapter 20.4 §6.
- Ask what changed since last time. A diff of the constraint set between milestones is one of the highest-value reviews available, and it costs nothing because the file is in version control.
8. Exercises
Exercise 1. Why can a constraint-set review not be "somebody reads the file"?
Exercise 2. Name the four mechanically checkable properties.
Exercise 3. The incomplete set had four problems and no syntax errors. What would the timing report have looked like?
Exercise 4. Why does the review report the ok cases as well as the failures?
Exercise 5. Why does review_constraints return a count instead of calling exit?
Exercise 6. The review reports no problems on a design that was never loaded. What is missing?
Exercise 7. Name three things the script cannot check.
Where this fits
Part of the Tcl curriculum.
