Tcl · Module 20
Why SDC Exists, and Why It Is Tcl
Without constraints a timing tool has no idea what fast means. SDC is how you tell it — and because SDC is Tcl, everything from Part I is available while you do.
Foundation17 min readtcledapart-iisdcconstraintstiming
Part II · Module 20 · Chapter 20.1 · Why SDC Exists, and Why It Is Tcl
A timing tool can measure how long a path takes. It cannot know whether that is acceptable, because "acceptable" is not a property of the netlist — it depends on how fast the clock runs, what arrives when, and which paths matter.
SDC is how you supply that. It is the contract between the design and the silicon it has to become, and it is the single most consequential text in the flow: every timing number downstream is computed against it.
It is also, as this chapter's second half shows, an ordinary Tcl script.
1. What a timing tool knows without constraints
Nothing useful. Given only a netlist it can compute delays, and has no requirement to compare them against — so there are no violations, and a report that looks clean.
That is Chapter 18.8's silent failure at the largest possible scale: a design with no clock defined reports no timing problems, because there is nothing to fail.
Constraints are what make the question meaningful. There are four kinds, and Module 20 covers each:
| Constraint | Answers |
|---|---|
| Clocks (20.2) | how fast is this supposed to run? |
| Input delays (20.3) | when does data arrive at the boundary? |
| Output delays (20.4) | when must data leave it? |
| Exceptions (20.5–20.7) | which paths are not real, or have longer than one cycle? |
2. The contract
The contract framing matters because it explains who SDC is for. It is read by synthesis, by place and route, and by signoff timing — often from different vendors. It travels with the block, and a block handed over without its constraints is unusable.
That is why SDC is the portable part, as Chapter 16.2 §2 noted: the constraint commands are a shared standard, unlike most tool scripting.
3. It is not a file format
Here is the misconception the registry purpose asks to settle. A .sdc file looks like a configuration file:
create_clock -name core_clk -period 2.0 [get_ports clk]
set_input_delay 0.4 -clock core_clk [get_ports {d_in[0]}]
set_output_delay 0.3 -clock core_clk [get_ports {d_out[0]}]It is not. It is a Tcl script. create_clock is a command; -name, core_clk, -period and 2.0 are its arguments; [get_ports clk] is command substitution, exactly as Chapter 2.5 described.
Sourced, it does what you would expect:
=== good.sdc, sourced ===
clocks:
core_clk 2.0 on clk (primary)
input delays: 1
d_in[0] clock core_clk 0.4
output delays: 1
d_out[0] clock core_clk 0.3
false paths: 0
multicycle: 0
clock groups: 04. What that buys you
If it is Tcl, then Part I is available. This is not a theoretical point:
# smart.sdc — an ordinary Tcl script that happens to call constraint commands.
# A variable, used in three places instead of three literals.
set PERIOD 2.0
set IN_FRAC 0.20
set OUT_FRAC 0.15
create_clock -name core_clk -period $PERIOD [get_ports clk]
# A loop over every bit of the bus, instead of four copied lines.
foreach_in_collection p [get_ports {d_in[*]}] {
set_input_delay [expr {$PERIOD * $IN_FRAC}] -clock core_clk $p
}
foreach_in_collection p [get_ports {d_out[*]}] {
set_output_delay [expr {$PERIOD * $OUT_FRAC}] -clock core_clk $p
} clocks:
core_clk 2.0 on clk (primary)
input delays: 4
d_in[0] clock core_clk 0.4
d_in[1] clock core_clk 0.4
d_in[2] clock core_clk 0.4
d_in[3] clock core_clk 0.4
output delays: 2
d_out[0] clock core_clk 0.3
d_out[1] clock core_clk 0.3Four input delays and two output delays, from three lines. And look at the numbers: 0.4 is 2.0 × 0.20, computed by expr while the file was sourced.
Three things that gives you, and each one is a real defect avoided:
- One place to change the period. Writing
2.0in fourteen places guarantees that one day thirteen of them get updated.$PERIODcannot drift. - Delays expressed as a fraction of the cycle. When the period changes, the I/O budget follows automatically — which is what you meant, and what a literal
0.4does not do. - A loop instead of copied lines. A thirty-two-bit bus is one loop, and adding a bit changes nothing.
5. The Tcl rules apply, including the painful ones
Because it is Tcl, Tcl's parsing rules apply — including the one that bites immediately with bus names:
=== an .sdc file is a Tcl script: sourcing one ===
invalid command name "0"
while executing
"0"
invoked from within
"get_ports d_in[0]"
invoked from within
"set_input_delay 0.4 -clock core_clk [get_ports d_in[0]]"d_in[0] unbraced is command substitution — Tcl tried to run a command called 0. This is Chapter 18.3 §3 arriving in the file where you will meet it most, because buses are everywhere in constraints.
Brace every object name containing brackets: [get_ports {d_in[0]}].
Two more Part I rules worth keeping in mind here:
exprgoes in braces —[expr {$PERIOD * 0.2}], per Chapter 14.8 §5.- A comment is a command, so
#must be at the start of a command, not after one on the same line without a semicolon (Chapter 1.8).
6. Where SDC comes from and where it goes
Worth knowing so the file makes sense as an artefact:
Written by whoever knows the timing intent — usually the block owner, sometimes generated from a spec. It is a design document as much as an input file.
Read by synthesis, by place and route, and by signoff timing. The same file, several tools, often several vendors.
Reviewed, which is the subject of Chapter 20.8 — because a constraint set that is wrong produces a confident, meaningless result rather than an error.
Version-controlled, like source. A timing result is only meaningful alongside the constraints that produced it.
7. What makes a constraint set wrong
Three failure modes, in rough order of how often they occur, and each is a later chapter:
Missing. A port with no delay, a clock never declared. The paths involved are unconstrained, so they produce no violations and no mention — the quietest failure, and Chapter 20.8 is the check for it.
Wrong. A period that does not match the spec, a delay budget nobody agreed. Produces a confident number that is simply false.
Over-relaxed. An exception that excuses a path which is actually real. A false path on something genuinely timed is how a chip comes back failing at speed — which is why Chapter 20.5 treats every exception as a claim that needs a reason recorded next to it.
8. Exercises
Exercise 1. What does a timing tool report on a design with no clock defined, and why?
Exercise 2. Name the four kinds of constraint this module covers.
Exercise 3. Is a .sdc file a configuration format? What is it?
Exercise 4. Give three things you can do in a .sdc file because it is Tcl.
Exercise 5. Why express an input delay as a fraction of the period rather than as a literal?
Exercise 6. [get_ports d_in[0]] gives invalid command name "0". Why, and what is the fix?
Exercise 7. Why is an over-relaxed constraint more dangerous than a missing one in silicon?
Where this fits
Part of the Tcl curriculum.
