Tcl · Module 21
Elaboration and Linking
Elaboration is where the tool finds out what it actually has. Anything it cannot resolve becomes an empty box with no timing and no area — which improves every number in the report.
Intermediate15 min readtcledapart-iisynthesiselaborationblack-box
Part II · Module 21 · Chapter 21.5 · Elaboration and Linking
Reading the sources gives the tool a collection of module definitions. Elaboration turns that into an actual design: it picks the top, works out what it instantiates, resolves each reference to a definition, and builds the hierarchy.
Linking is the resolution part — connecting each instantiated name to something real, whether a module from the sources or a cell from a library.
It is the first phase where the tool finds out what it genuinely has, which makes it the first phase that can tell you something is missing.
1. Where it sits
Elaboration comes after reading and before constraining, and the order is forced:
- The ports and instances a constraint refers to do not exist until elaboration created them.
get_ports clkbefore elaboration finds nothing, which — per Chapter 18.8 — applies the constraint to nothing and says so quietly. - Equally, elaboration needs everything read first, or references cannot resolve.
So the sequence is not negotiable: read, elaborate, then constrain.
2. The black box
Here is what makes this phase dangerous.
When the tool meets an instantiation it cannot resolve — a module whose source was not in the file list, a macro whose library was not read — it has two options. Stop, or carry on with an empty placeholder.
Most tools, by default or by common setting, carry on. The unresolved reference becomes a black box: a cell with a name, some pins, and nothing else.
3. Read what the tool says
The registry purpose's instruction, and it is the whole mitigation on the tool side.
Elaboration produces messages, and the ones about unresolved references are usually warnings rather than errors. In a log of several thousand lines, after a run that reported success, a warning is something nobody reads.
Two habits:
Capture the log. Elaboration messages go to the session log, so the run must write one and keep it — Chapter 21.8.
Grep it deliberately. Not "read the log", which nobody does, but a check in the script that looks for the specific thing:
proc check_log_for {logfile patterns} {
set hits {}
set fp [open $logfile r]
set n 0
while {[gets $fp line] >= 0} {
incr n
foreach p $patterns {
if {[string match $p $line]} { lappend hits [list $n $line] ; break }
}
}
close $fp
return $hits
}Pure Part I — Chapter 12.2 and string match. The patterns are tool-specific and worth finding once; what matters is that the check is in the script, so it runs whether or not anybody feels like reading the log.
4. Catching it before elaboration
Better still: the sources already contain the answer, and Chapter 21.3 built the extraction.
If a module is instantiated but never defined in the sources, and it is not a library cell, it will not resolve:
defined : alu, cpu_top, fifo, fifo_ctrl
instantiated : alu, fifo
candidates for top (defined but never instantiated): cpu_top, fifo_ctrlEvery instantiated module here — alu and fifo — also appears in the defined list. Nothing is missing.
Turn that into a check:
proc check_references {defined instantiated {known_cells {}}} {
set unresolved {}
foreach m $instantiated {
if {[lsearch -exact $defined $m] >= 0} { continue }
if {[lsearch -exact $known_cells $m] >= 0} { continue }
lappend unresolved $m
}
if {[llength $unresolved]} {
error "[llength $unresolved] module(s) instantiated but not defined: [join $unresolved {, }]" \
{} [list ELAB UNRESOLVED $unresolved]
}
return [llength $instantiated]
}5. Then verify what you got
After elaboration, the design exists, so you can ask it questions — which is Module 19 doing real work:
set cells [get_cells -hierarchical *]
if {[sizeof_collection $cells] == 0} {
error "elaboration produced no instances" {} {ELAB EMPTY}
}
puts " elaborated: [sizeof_collection $cells] instance(s)"
puts " top : [current_design]"Three checks worth making every run:
- The instance count is not zero — the most basic proof that something happened.
- The count is roughly what you expect. An order of magnitude too small is a black box swallowing a block.
- The top is the one you asked for — Chapter 21.3 §5's check, confirmed after the fact.
Printing the count every run is what makes a regression visible: elaborated: 9142 instances dropping to elaborated: 412 next week is obvious in a diff of two logs and invisible in either one alone.
6. Exercises
Exercise 1. What does elaboration do that reading the sources does not?
Exercise 2. Why must elaboration come before constraining?
Exercise 3. What is a black box, and what does it contain?
Exercise 4. Why does a missing module make a design look better rather than broken?
Exercise 5. Why is "read the elaboration log" insufficient as a mitigation?
Exercise 6. How can an unresolvable reference be caught before elaboration, and what are the limits?
Exercise 7. Name three things to check immediately after elaboration.
Where this fits
Part of the Tcl curriculum.
