Tcl · Module 25
The Simulator Command Set
A simulation is three phases, and each reports failure through a different channel. Knowing which commands belong to the simulator and which to Tcl is what makes a script portable.
Intermediate20 min readtcledapart-iisimulationverification
Part II · Module 25 · Chapter 25.1 · The Simulator Command Set
Modules 21 to 24 were synthesis, timing and implementation. A simulator is a different kind of tool with the same Tcl relationship: a command set layered on a Tcl interpreter, which means a simulation run is a program.
1. What runs here, and what does not
Being specific up front, because this module's subject is a tool and honesty about tools matters more than convenience.
There is no Questa, ModelSim, VCS or Xcelium on the machine these chapters were verified on. So the vlib / vlog / vsim command names — the ones the curriculum's own samples use, and the ones you will meet in industry — are not executed anywhere in this module. Where they appear, they are the industry vocabulary with a small teaching mock behind them, and each chapter says so.
What is real is Icarus Verilog 13.0. It is an open-source Verilog simulator, it is installed here, and every phase, exit status and log line attributed to it in this chapter came out of an actual run on an actual design — a 4-deep 8-bit synchronous FIFO with a self-checking testbench.
That split matters because the two halves of this chapter need different treatment. The phases are universal and are demonstrated for real. The command names are vendor-specific and are labelled.
2. The phases
Every simulator does the same three things under different names:
| Phase | What it does | Questa family | Icarus |
|---|---|---|---|
| Compile | parse each source file, check its syntax | vlog / vcom | iverilog |
| Elaborate | build the design hierarchy, resolve instances and parameters | vopt / vsim | iverilog (same step) |
| Run | advance simulation time | vsim then run | vvp |
Two differences worth noticing rather than memorising.
Icarus fuses compile and elaborate. iverilog reads the sources and writes one executable artefact; there is no separate elaboration command and no library directory. The Questa family separates them, which is why it needs vlib to create a library first and vopt to optimise an elaborated design.
In the Questa family, vsim is itself the Tcl interpreter. It loads the design and then gives you a prompt where run, add wave and every Tcl command coexist. That is the premise of Chapter 25.2. Icarus has no such shell — vvp runs a program to completion — which is precisely why the do-file chapter needs a mock.
3. The phases, run for real
=== phase 1: compile and elaborate (Icarus) ===
iverilog exit status : 0
produced : sim/fifo_tb.vvp (17790 bytes)
=== phase 2: run ===
test=fill_drain seed=7
fill_drain: 9 checks, 0 errors
TEST PASSED
tb/fifo_tb.v:68: $finish called at 170 (1s)
vvp exit status : 0Now a source file with a missing semicolon:
=== a compile error stops at phase 1, and nothing runs ===
tb/broken.v:4: syntax error
I give up.
iverilog exit status : 2
binary exists : noI give up. is Icarus's own wording, quoted because it is worth knowing that a tool's failure message is not always greppable for the word "error" — a run script matching on error would miss this line entirely and see only the exit status.
4. Which commands are the simulator's?
This is the registry's question for the chapter, and it matters practically: a script built on Tcl's own commands runs in any interpreter, and one built on the tool's commands runs only in that tool. Knowing which is which tells you what is portable.
The temptation is to ask the interpreter directly. Do not use info procs for this.
The reliable method is to diff the tool's command set against a baseline plain tclsh:
# capture once, from a bare tclsh: puts [join [lsort [info commands]] "\n"]
set baseline {}
set fh [open sim/tclsh-baseline.txt r]
while {[gets $fh l] >= 0} { if {[string trim $l] ne ""} { lappend baseline [string trim $l] } }
close $fh
set here [lsort [info commands]]
set added {}
foreach c $here { if {[lsearch -exact $baseline $c] < 0} { lappend added $c } }=== commands in a bare tclsh : 92 ===
=== commands in this shell : 105 ===
=== the difference is the tool's command set ===
add
assert_loaded
declare_signal
examine
force
now
quit
report_waves
run
vlib
vlog
vsim
wave_count92 against 105, and the 13-command difference is everything this shell adds. Point the same script at a real vsim and the list is that tool's genuine command set, which no manual will give you as exhaustively.
Two honest notes on that output. The list includes assert_loaded, declare_signal, report_waves and wave_count, which are the mock's internal helpers rather than commands a user would type — a real diff against a real tool includes its internals too, and distinguishing a tool's public interface from its plumbing needs the documentation, not the interpreter. And quit and run are real simulator commands that happen to read like ordinary words, which is exactly why the diff is more trustworthy than intuition.
5. Why info procs is the wrong classifier
=== the wrong classifier, and why ===
info procs vlog -> 'vlog'
info procs puts -> ''
info commands vlog -> 'vlog'
info commands puts -> 'puts'In the mock shell info procs vlog returns vlog, and info procs puts returns nothing — which looks like a perfect classifier. Tool command: yes. Tcl built-in: no.
6. Reading a command set you have never seen
Once the diff gives you a list of names, the ensemble trick from Chapter 14.10 works on simulator commands too: pass a deliberately invalid subcommand and let the tool enumerate the valid ones.
catch {add bogus} msg
puts $msgIn the mock that raises add: unknown object 'bogus'; a real tool typically lists what it accepts. Combined with the diff, that is enough to map an unfamiliar tool's interface without documentation — which is Chapter 17.6's subject, and the fastest way into a vendor shell nobody has written notes for.
Two habits make the mapping durable:
Record the version alongside the command list. A command set is a property of a release, not of a tool, and Chapter 24.2 §6's provenance argument applies to interfaces as much as to numbers.
Write the list to a file in the repository. A diff of this release's command set against last release's is how you find out that an option was removed — before a nightly regression finds out for you.
7. Exercises
Exercise 1. Name the three phases and what each one does.
Exercise 2. Why does Icarus need no vlib, and why does the Questa family?
Exercise 3. Which simulator phase does vsim occupy in the Questa family, and what else is it?
Exercise 4. A compile error gave exit 2 and no artefact. A failing test gives exit 0 and a full log. What must a run script therefore check?
Exercise 5. Why would a run script grepping for the word error miss Icarus's compile failure?
Exercise 6. How do you establish a tool's own command set?
Exercise 7. Why is info procs a false positive in the mock and a false negative in a real simulator?
Exercise 8. Why record the tool version next to the command list?
Where this fits
Part of the Tcl curriculum.
