Skip to content
VLSI Mentor

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:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
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

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
=== source succeeded. did anything land? ===
    good.sdc   source rc=0   clocks defined afterwards: 1
    typo.sdc   source rc=0   clocks defined afterwards: 0

Both 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:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
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
}
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
=== 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 0

The 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):

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
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:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
# WRONG
catch {source $sdc}          ;# half the constraints applied, run proceeds

# right
source $sdc                  ;# let it stop the phase

If 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.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
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_CLOCKS

Three 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.