Tcl · Module 21
Applying Constraints
A constraints file can run from top to bottom without error and leave the design completely unconstrained. The source command cannot tell you — so the script has to ask.
Intermediate16 min readtcledapart-iisynthesissdcverification
Part II · Module 21 · Chapter 21.6 · Applying Constraints
With the design elaborated, the constraints can be applied. Because a .sdc file is a Tcl script (Chapter 20.1), applying it is one command:
source [file join $here sdc constraints.sdc]That command succeeding feels like confirmation. It is not, and this chapter is about the difference.
1. Two files, the same return code
=== source succeeded. did anything land? ===
good.sdc source rc=0 clocks defined afterwards: 1
typo.sdc source rc=0 clocks defined afterwards: 0Both files sourced cleanly. One constrained the design; the other constrained nothing.
The difference is a single character — clock instead of clk in the port name — and source cannot see it.
2. Verify instead
The fix is to ask the design what it has, after the fact:
proc verify_constraints {expect_clocks} {
set n [llength $::sdc::clocks]
if {$n < $expect_clocks} {
error "expected at least $expect_clocks clock(s), the SDC defined $n" \
{} [list SDC UNDERAPPLIED $n]
}
return $n
}=== the verification that distinguishes them ===
good.sdc verify -> ok, 1 clock(s)
typo.sdc verify -> FAILED: expected at least 1 clock(s), the SDC defined 0The same two files, now distinguished. Four lines of checking turned an invisible failure into a stopped run with a message.
3. What to verify
An expected count is the minimum. Four checks worth making, in increasing order of value:
Clocks exist. Zero clocks after sourcing an SDC is a definite failure, whatever the design.
The count is right. You know how many clocks the block has. expect_clocks as a parameter the script states is better than "more than zero" — Chapter 19.5 §7's expectation idea.
Every port is timed. Exactly Chapter 20.8's review, run here against the live design rather than against a file.
The periods are what you expect. A clock defined with the wrong period is not caught by any count.
4. Where it goes in the flow
After elaboration (Chapter 21.5 §1) and before compile (Chapter 20.1 §2):
run_phase "constrain" {
source [file join $here sdc constraints.sdc]
verify_constraints $EXPECTED_CLOCKS
review_constraints
}The run_phase wrapper from Chapter 21.1 §4 catches a raise from either check and attributes it to this phase, so the failure message names the stage rather than arriving as a trace from inside a sourced file.
5. When the SDC itself fails
The other direction: the file raises partway through. Now Chapter 15.1 §4's partial-load applies — everything before the error was applied, everything after was not.
That is a worse state than nothing, because the design is partly constrained and the report will be partly meaningful.
So do not catch a constraint failure and continue:
# WRONG
catch {source $sdc} ;# half the constraints applied, run proceeds
# right
source $sdc ;# let it stop the phaseIf you must catch it — to add context — re-raise with return -options, per Chapter 14.5 §2, so the phase still fails.
6. Several constraint files
Blocks often have more than one: a shared interface budget, the block's own constraints, a mode-specific overlay. Order matters, because a later file can override an earlier one.
foreach f $SDC_FILES {
if {![file isfile $f]} {
error "constraint file missing: $f" {} [list SDC MISSING $f]
}
puts " sourcing [file tail $f]"
source $f
}
verify_constraints $EXPECTED_CLOCKSThree things: check each exists first (Chapter 21.2 §4); print each as it is sourced, so the log records what was applied in what order; and verify once at the end, because an intermediate state may legitimately be incomplete.
The printed list is the same argument as Chapter 17.4 §5's: when two runs disagree, the first question is which constraint files each one read.
7. Exercises
Exercise 1. Two SDC files both source with return code 0. What can differ?
Exercise 2. Trace the chain by which a one-character typo leaves a design unconstrained with no error.
Exercise 3. Why does the resulting timing report look clean?
Exercise 4. Name four things worth verifying after sourcing.
Exercise 5. How is this check different from Chapter 20.8's review?
Exercise 6. Why not catch a failing constraint file and continue?
Exercise 7. With three constraint files, what three things should the script do?
Where this fits
Part of the Tcl curriculum.
