Tcl · Module 16
Standard Tcl vs Tool Commands: The Boundary
Every line in a flow script is one of two things, and they have completely different rules about where they will run. Telling them apart is the first skill of Part II.
Foundation18 min readtcledapart-iiportabilityinfo-commandstool-commands
Part II · Module 16 · Chapter 16.4 · Standard Tcl vs Tool Commands: The Boundary
Open any flow script and every line is one of two kinds:
foreach cell [get_cells -hierarchical *fifo*] {
puts "found $cell"
}foreach and puts are Tcl. They work in tclsh, in every EDA tool, and in every other program that embeds Tcl. get_cells is a tool command — one vendor added it to one interpreter, and it exists nowhere else.
The two look identical, because Chapter 2.1 was right that everything is a command. Telling them apart anyway is the first real skill of Part II, because it decides what you can reuse, what you must document, and what will break when somebody runs your script somewhere else.
1. The boundary
2. Part I never used one
Worth stating, because it is the evidence you already have.
Across the whole of Part I — fifteen modules — not a single example used get_cells, get_ports, report_timing, create_clock or any other vendor command. Every example ran in a plain tclsh.
That was deliberate, and it means the language you learned is the portable half. Everything from Part I will work inside any tool. Everything you learn from here on is an addition that may not.
3. The standard set is small enough to know
There are about ninety standard commands. Not thousands — ninety. A plain tclsh reports:
total: 93And they are the names you already recognise:
append apply array binary break
catch cd chan clock close
concat continue dict encoding eof
error eval exec exit expr
file for foreach format gets
glob global if incr info
join lappend lassign lindex linsert
list llength lrange lsearch lset
lsort namespace open package proc
puts pwd read regexp regsub
rename return scan set source
split string subst switch trace
unset uplevel upvar variable whileThat is the set, with Tcl's internal auto_* helpers and the event/channel plumbing a flow script never types left out. It is learnable. And it is the whole trick: if a command is not in that set, it came from somewhere else.
4. The quick heuristic, and where it fails
Vendor commands are overwhelmingly verb_noun with an underscore: get_cells, report_timing, create_clock, set_input_delay, write_verilog. Standard Tcl commands are nearly always a single lowercase word: foreach, lsort, string, expr.
The numbers back it up on this interpreter:
standard commands containing an underscore: 5 of 93
auto_execok auto_import auto_load auto_load_index auto_qualify
single-word commands: 88So the heuristic is: an underscore means it is probably a tool command. Tested:
foreach looks like a tool command: no actually in plain Tcl: yes
lsort looks like a tool command: no actually in plain Tcl: yes
string looks like a tool command: no actually in plain Tcl: yes
expr looks like a tool command: no actually in plain Tcl: yes
get_cells looks like a tool command: yes actually in plain Tcl: no
report_timing looks like a tool command: yes actually in plain Tcl: no
create_clock looks like a tool command: yes actually in plain Tcl: no
current_design looks like a tool command: yes actually in plain Tcl: no
auto_load looks like a tool command: yes actually in plain Tcl: yes5. The definitive test: ask the interpreter
info commands tells you what exists here — the introspection from Chapter 14.10 doing its most valuable job.
In a plain tclsh, the vendor commands are simply absent:
info commands get_cells : ''
info commands get_ports : ''
info commands get_pins : ''
info commands get_nets : ''
info commands get_clocks : ''
info commands report_timing : ''
info commands create_clock : ''
info commands current_design : ''
info commands link_design : ''
info commands read_verilog : ''Empty every time. These are not Tcl.
But "does it exist here" alone cannot tell you which kind it is, because inside a tool both kinds exist. For that, compare against a baseline captured from a plain interpreter:
# Capture once, from a plain tclsh:
# foreach c [lsort [info commands]] { puts $c } > baseline.txt
set baseline {}
set fp [open baseline.txt r]
while {[gets $fp line] >= 0} { lappend baseline [string trim $line] }
close $fp
foreach c {foreach get_cells report_timing} {
set known [expr {[lsearch -exact $baseline $c] >= 0}]
set here [expr {[llength [info commands $c]] > 0}]
puts [format " %-14s in plain Tcl: %-3s available here: %-3s -> %s" \
$c [expr {$known?"yes":"no"}] [expr {$here?"yes":"no"}] \
[expr {$known ? "standard Tcl, portable" : ($here ? "a tool command, NOT portable" : "not available at all")}]]
}Run inside a shell that has tool commands added:
foreach in plain Tcl: yes available here: yes -> standard Tcl, portable
get_cells in plain Tcl: no available here: yes -> a tool command, NOT portable
report_timing in plain Tcl: no available here: no -> not available at allThree outcomes, correctly distinguished. And the same comparison lists everything a shell adds:
commands this shell adds: current_design get_cells get_ports read_design6. Why it matters
Four practical consequences, in rough order of how soon they will bite you.
Portability. A script using only standard Tcl runs in any tool. One using get_cells runs only where get_cells is defined — and not necessarily in every tool from the same vendor, as Chapter 17.5 shows.
Documentation. A script that uses tool commands has an unstated requirement. Say it at the top, where Chapter 15.9 put the usage line:
# Requires: a tool providing get_cells, get_ports and report_timing.
# Developed against <tool> <version>.Testability. This is the one people miss. A procedure that takes a list of names can be tested in tclsh; one that calls get_cells itself cannot be tested without a tool licence and a design.
# hard to test: reaches for the tool itself
proc count_fifos {} {
return [llength [get_cells -hierarchical *fifo*]]
}
# easy to test: the caller supplies the data
proc count_matching {names pattern} {
set n 0
foreach c $names { if {[string match $pattern $c]} { incr n } }
return $n
}The second runs in tclsh against a list you wrote by hand. Pushing the tool calls to the edges and keeping the logic in standard Tcl is the same separation Chapter 15.7 made between bin/ and lib/ — and here it also buys you a test suite that needs no licence.
Checking before you run. A long flow should not fail at minute forty because a command is missing. The preflight from Chapter 14.10 §8 applies directly:
proc require_commands {args} {
set missing {}
foreach c $args {
if {![llength [info commands $c]]} { lappend missing $c }
}
if {[llength $missing]} {
error "this tool does not provide: [join $missing {, }]" {} \
[list TOOL MISSING $missing]
}
}
require_commands get_cells get_ports report_timing7. Reading someone else's script
Open an unfamiliar flow script and sort every command into three piles:
- Standard Tcl —
foreach,set,if,lsort,regexp. You already know these; they are not where the difficulty is. - Tool commands you recognise —
get_cells,create_clock. Look them up in that tool's reference, not on the internet, because the options differ between vendors (Chapter 17.6). - Commands that are neither — usually procedures the team wrote, sourced from a site library.
info procs <name>andinfo body <name>will show you the source, which is Chapter 14.10 §4.
That third pile is where the surprises live, and it is the one people forget to check.
8. The honest summary
Part II is going to teach you a lot of commands that are not Tcl. That is the deal, and it is worth being clear-eyed about it:
- The language you learned in Part I is permanent and portable.
- The commands you learn from here are specific to tools, and some of them will be obsolete in ten years.
- The skill that lasts is knowing which is which, and structuring scripts so the portable part is the large part.
A flow script where the tool calls are concentrated in a few procedures at the edge, and the logic is standard Tcl in the middle, survives a tool change. One where the two are interleaved on every line does not.
9. Exercises
Exercise 1. foreach cell [get_cells *] { ... } — which parts are Tcl and which are not?
Exercise 2. Roughly how many standard Tcl commands are there, and why does that number matter?
Exercise 3. State the underscore heuristic and give the counterexample from this chapter.
Exercise 4. Why is info procs the wrong way to identify tool commands? Give both reasons.
Exercise 5. What is the definitive test, and what does it need that info commands alone does not?
Exercise 6. Rewrite proc count_fifos {} { llength [get_cells -hierarchical *fifo*] } so it can be tested in tclsh.
Exercise 7. A flow fails after forty minutes with invalid command name "report_qor". What should have happened instead, and how?
Where this fits
Part of the Tcl curriculum.
