Skip to content
VLSI Mentor

Tcl · Module 17

Tcl Embedded in an EDA Tool

You are dropped at an unfamiliar tool prompt. Three commands tell you what interpreter you are in and what it can do — and one property of tool commands explains most of the confusion that follows.

Intermediate17 min readtcledapart-iitool-shellsinfo-commandsstate

Part II · Module 17 · Chapter 17.1 · Tcl Embedded in an EDA Tool

Chapter 16.1 argued why vendors embed Tcl. This chapter is the practical consequence: you are sitting at a tool prompt you have not used before. What do you type to find out what you have?

And once you know, there is one property of tool commands that is not true of anything in Part I, and getting it wrong is the source of most "but it worked yesterday" confusion.

1. The definition, precisely

A tool shell is a standard Tcl interpreter, plus extra commands, plus extra state.

All three parts matter, and the third is the one people skip.

Three stages left to right, with a second row. A standard Tcl interpreter parses and evaluates your script exactly as tclsh would. The tool registers extra commands into it. Those commands read and change a design database, which is the extra state, so the same command answers differently at different points in a flow.Standard interpreterthe language, unchangedExtra commandsregistered by the toolExtra statethe design databaseSame rules applyparsing, substitution,scopeFound with infocommandsask, do not assumeAnswers changenot a pure function12
Figure 1 — the three parts of a tool shell. The interpreter and the language are standard and unchanged. The tool contributes a command set and a design database; the commands are the only way to reach the database, and their answers depend on what is in it.

2. What does not change

Everything from Part I. The parsing rules from Module 2, substitution happening once, foreach and lsort and catch and regexp, procedures, namespaces, exit and its status.

Chapter 16.1 §5 demonstrated this directly: the same standard-Tcl work produced byte-identical output with and without tool commands present. You do not relearn the language. You learn a command set.

3. Finding out what you have

Three questions, three commands. This is the introspection from Chapter 14.10, and it is the single most useful thing to know at an unfamiliar prompt.

Everything below is real output from a teaching mock — toolshell.tcl, a few dozen lines of ordinary Tcl that registers some design-query commands into a plain interpreter. It is not a real tool. The technique is what transfers.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
puts "  info tclversion        : [info tclversion]"
puts "  info patchlevel        : [info patchlevel]"
puts "  info commands set*     : [lsort [info commands set*]]"
puts "  info commands report_* : [lsort [info commands report_*]]"
puts "  info commands get_*    : [lsort [info commands get_*]]"
puts "  info commands *design* : [lsort [info commands *design*]]"
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
  info tclversion        : 8.5
  info patchlevel        : 8.5.9
  info commands set*     : set
  info commands report_* : report_area report_design report_ports
  info commands get_*    : get_cells get_ports
  info commands *design* : current_design read_design report_design

Read those six lines as a procedure you can follow anywhere:

  • info tclversion tells you which language features you have. This matters: try, lmap and dict map need 8.6, and plenty of tools ship an 8.5-era interpreter, exactly as Chapter 14.5 §4 warned. Check before you rely on one.
  • info patchlevel is the full version, for a bug report.
  • info commands <pattern> is the discovery tool. A glob over the command set answers "what can this thing do" far faster than any manual.

4. The part that is genuinely different: state

Here is the property no Part I command has.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
puts "  before loading:"
puts "    current_design -> [catch {current_design} e] / $e"
puts "    get_cells *    -> [catch {get_cells *} e] / $e"
read_design cpu.design
puts "  after read_design cpu.design:"
puts "    current_design -> [current_design]"
puts "    get_cells *    -> [get_cells *]"
puts "    report_area    -> [report_area]"
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
  before loading:
    current_design -> 1 / no design loaded
    get_cells *    -> 1 / no design loaded
  after read_design cpu.design:
    current_design -> cpu_top
    get_cells *    -> u_fifo u_alu u_ctrl u_decode
    report_area    -> cells: 4

The same command, with the same arguments, raised at one moment and answered at another. Nothing about the command changed; the state behind it did.

Contrast an ordinary Tcl command:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
    llength $l     -> 3
    llength $l     -> 3   (same input, same answer, always)

5. Reading the error when state is wrong

no design loaded is the shape of message you will meet constantly, in many wordings. It is worth recognising as a category rather than as individual errors, because the fix is always the same kind of thing: something earlier in the flow did not happen.

Because these arrive as ordinary Tcl errors, everything from Module 14 applies — they unwind, they can be caught, and they carry a stack trace. So a flow script can check its preconditions rather than discovering them:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
proc require_design {} {
    if {[catch {current_design} d]} {
        error "no design is loaded — did an earlier stage fail?" {} {FLOW NODESIGN}
    }
    return $d
}

That is Chapter 14.11's boundary check, applied to tool state instead of to data.

6. The session is long-lived

One more difference from tclsh. A script you run with tclsh script.tcl starts an interpreter, runs, and exits — the state dies with it.

A tool session typically stays alive across many commands: you load a design once and then work on it for an hour, or a batch run executes a long sequence of stages in one interpreter. The state accumulates.

That has a consequence worth internalising early: in a long session, a variable or a procedure you defined an hour ago is still there. So is a setting you changed and forgot. "It works in my session but not in a fresh batch run" is almost always something defined earlier in the session that the script never defines for itself.

Chapter 17.2 is about exactly that gap, and Chapter 17.4 about the files that widen it.

7. A short orientation routine

What to type at an unfamiliar prompt, in order:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
info tclversion                    ;# which language features exist
info commands get_*                ;# what can I query
info commands report_*             ;# what can it tell me
current_design                     ;# is anything loaded yet
info commands                      ;# the full list, if you dare

Then, before relying on anything in a script, check it is there — the preflight from Chapter 14.10 §8:

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

Five lines of typing replaces an afternoon of assuming.

8. Exercises

Exercise 1. Give the three-part definition of a tool shell.

Exercise 2. Which command tells you whether try and lmap are available, and why would they not be?

Exercise 3. You are at an unfamiliar prompt. How do you find every command that reports something?

Exercise 4. get_cells * worked an hour ago and now raises no design loaded. What changed?

Exercise 5. Why can a tool command not be tested in isolation, and what does that imply about how you structure a flow script?

Exercise 6. get_cells * returns a different set before and after optimisation. Is that a bug?

Exercise 7. A script works in your interactive session and fails in a fresh batch run. What is the most likely cause?

Where this fits

Part of the Tcl curriculum.