Friday, August 6, 2010

Tcl and EDA

Tcl/Tk for EDA

Every user of EDA tools, and hardware description languages such as VHDL and Verilog, needs to know about Tcl!

A good working knowledge of Tcl can help you gain greater productivity in using EDA tools for FPGA and ASIC design, but many Tcl courses and textbooks focus on using Tcl for general-purpose computing applications. At Doulos we understand the needs of EDA users, and our courses and example materials concentrate on those needs.

Xilinx ISE is one of the many EDA tools that can be controlled using Tcl. Why would you want to do that? Well, on our courses we often see delegates make an edit to their source code, then re-implement it only to find that the synthesis/layout doesn't do the same as it did before.

This is a constant danger if repeatability depends on remembering to click on the correct boxes and menus in the user interface. If you create a command file you can run that same file many times, thus guaranteeing that you are issuing the same commands to the tool each time.

There are two ways of running the script:
  1. Within the GUI there is a Tcl command window, in which you can source (i.e. call/run) a script.
  2. You can issue the command "xtclsh scriptname" in your DOS command window or *nix shell and avoid the overhead of a graphical interface completely.

With all this in mind, we are now going to explore some of the ways in which we can drive ISE from a Tcl script. We will synthesise a small design using XST and implement it in a Spartan3e device (chosen to match the boards used on our course VHDL for FPGA Design).

Input files

The first thing we need to do is to tell the tool which source files will be used. We want to do this in a maintainable way, and to this end all filenames are given at the top of the script.
We set some Tcl variables to contain the filenames we require:
# where all output will be created
set compile_directory     spartan3e
# the top-level of our HDL source:
set top_name              spartan3e_top
# input source files:
set hdl_files [ list \
  ../constants_spartan.vhd \
  ../components.vhd \
  ...Other files... \
# constraints with pin placements.
set constraints_file      ../spartan3e_fsm.ucf
A # denotes a comment; the comment is terminated by a newline and is ignored by the parser. Care is required, as other Tcl behaviour means a hash character will not always be interpreted as the beginning of a comment. Until you know this behaviour it's best to follow these rules about comments:
  • Each comment appears on a separate line where # is the first character on that line
  • In a comment, don't include mismatched round or square brackets and don't use curly brackets at all
The set command is used to apply a value to a variable:
set variable_name value
In the setting of the variable "hdl_files" we used the list command to create a Tcl list from the text strings that follow it. As a simpler alternative, we could have used braces to enclose a set of strings:
set hdl_files {
  ...Other files...
This approach has some drawbacks, especially when the list items have spaces or special characters. It's generally best to construct the list using the list command. This also allows you to use lappend and lindex commands to manipulate the list.

Setting a Compilation Directory

We now need somewhere to process our files. We can use the file command and its sub-command mkdir to create a directory:
if {![file isdirectory $compile_directory]} {
  file mkdir $compile_directory
This code asks if the directory exists; if not, it is created. You may also find file exists useful. Using $ in front of a variable name give you the content of that variable.

Project Creation and Settings

So, now we have a directory and we can do something there. Assuming no project exists in this directory we can go ahead and make one. Xilinx provide the project command, which includes sub-commands for the project settings and other related tasks. Let's try some:
project new $proj.ise
project set family Spartan3E
project set device xc3s500e
project set package fg320
project set speed -4
This is one of the strengths of Tcl; it is easy to add new commands by writing your own procedures. Doing that is outside the scope of this discussion but is covered fully in Essential Tcl/Tk.
Now we need to add some files to the project. Again, Xilinx provide a Tcl command for this: the xfile command is used to add or remove files and to get information on any source files in the current ISE project. We need to add some files, but we don't really want to type filenames again (maintainability, remember?) and we already have a list of source files. The solution is to loop through the list adding each file to the project:
foreach filename $hdl_files {
  xfile add $filename
  puts "Adding file $filename to the project."
The puts command is a simple way to write to STDOUT (which is usually the console/shell). Note: don't forget to add the constraints file; NGDBuild does not automatically detect .ucf files when run from Tcl. Use xfile add in the same way.

Running Processes

Before we run any processes, we can set process options using project set as above; see the provided script for examples and the Xilinx Development System Reference Guide for exhaustive detail.
Now we can run something. Just as with the ISE graphical interface, running any given process will run any required prior processes. In our example, I can issue this command:
process run "Generate Programming File"
and the design will be synthesised and implemented first before the bitfile is created. Again, just as in the graphical interface, source and intermediate file dependencies are checked and processes are run only if required. For example, to force a rerun:
process run "Implement Design" -force rerun_all

Programming the Device

Here we have to change our approach as Impact does not have a Tcl interface. However, this does allow us to explore another way of controlling applications. Impact has the ability to run a script file that consists of a series of commands. These are not Tcl commands, but we can use Tcl to construct this file. We can then run Impact from with the Tcl script. Let's see how.
First we need to open a file that will become the Impact script. We do this with the open command:
if {[catch {set f_id [open $impact_script_filename w]} msg]} {
  puts "Can't create $impact_script_filename"
  puts $msg
What's going on here? The open command returns a handle to the file which we put in the variable "f_id". If open fails it would stop the script; this is probably the best thing to do here, but in general you may want to trap errors and continue with other things. That's what catch can do; it will return a non-zero error code if the command it runs (in this case the open) fails, and it places any error message from that command in the variable that here we have called "msg". Hence, if the open fails $msg will contain the reason why.
How do we write text to the file? With the puts command. Earlier we used it to write text to the console, but here we see an addition:
puts $f_id "addDevice -position 1 -file $bit_filename"
Well, it's not really an addition: the default destination of a puts command is the standard output, so if we leave off the second argument then STOUT is where the output goes. The line above uses a second argument, so the text is written to the file given by $f_id instead. After we have written the required command to the Impact script we should close the file.
Now we have to start Impact. There are several ways of calling external programs from Tcl; the easiest is to use the exec command, which runs the external program, waits for it to finish and returns all its output. This is acceptable for quick programs but not for anything more complicated, as you cannot direct any input to the program or control it while it is running. More flexibility is provided by using open, but this time as a pipe from the program:
set impact_p [open "|impact -batch $impact_script_filename" r]
This line starts Impact with the script, and returns its output to the variable "impact_p". The benefit of using the pipe is that we can now watch the STDOUT of the tool from within our Tcl script:
while {![eof $impact_p]} { gets $impact_p line ; puts $line }
This code writes each line of Impact's output to the Tcl script's own standard output. The command eof returns true when the external program finishes. This approach will not work if the external program requires some interaction because that program will not tell you when it requires some input. In our case, however, this is fine, because we want the Impact script to run until completion.
source :


TCLspice build a TCL/TK shell onto ngspice.


Prior to year 2008 TCLspice was an independent project forked from ngspice. It is still hosted on sourceforge but it is not active anymore. The former maintainer of TCLspice, Stefan Jones, accepted to give me, Lionel Sainte Cluque, his chair as the project was no longer active. Paolo Nenzi, ngspice maintainer accepted to merge TCL functionality to ngspice source code as soon as it is stable.

Prior to 2008

A crude copy and paste from TCLspice website:

TclSpice is being actively developed and maintained by MultiGiG ltd (as a by-product of a Clock-verification tool) and we try to act in concert with the following independent Open-Source EDA efforts to achieve (eventually) a complete freely available but industrial quality tool-set which work together seamlessly.

•Magic VLSI editor [ tcl version ] (Tim Edwards).

•Xcircuit schematic capture package [ tcl version ] (Tim Edwards).

•Automatic Schematic Generation (Multigig, Stephan Frezza).

•FastHenry Inductance extractor (Jacob White).

•FastCap Capacitance field solver (Jacob White).

•OpenAccess VLSI database (

•Octtools, TimberWolf, place / router (Berkely (formerly)) (

•SpicePP preprocessor for berkeley spice3f5. It adds support for some structures commercial spice provide.

Some words from Stefan Jones:

The project was started around 2002 when I started working for Multigig. The then owner of Multigig, John Wood, was working on Tcl extensions for the magic vlsi program.

It was also considered a good thing to try to do the same for ngspice, bringing the same scripting benefits and a newer, easier to use GUI.

Also the old xspice simulator source code was found. It was also decided it would be a good idea to merge this also into ngspice.

Around 2003 the code was starting to diverse from ngspice with the two above features. I stopped producing diffs to ngspice as the ngspice people wanted the code to be kept separate. But I did make a cvs branch on the ngspice repository for the code so at least the two versions (ngspice and tclspice) could be merged easily.

Adrian Dawe was responsible for the TCL GUI code, also an employee at Multigig (which you said could not get to work I believe). He also setup the original tclspice website. I did the C-code bits.

Also around this time Stuart Brorson started working on spice. He finally fixed the remaining issues in the xspice to tclspice code merge and got it working properly.

I think soon after Dietmar Warning also became interested in tclspice and submitted a few patches.

But soon after that people seemed to switch to working on ngspice as it was the more active project (with Paolo Nenzi being more active)

Around 2004 Multigig switch to commercial spice tools. Thus work slowed/stopped on tclspice as it was no longer used much. Recently no-one uses tclspice anymore at Multigig so no work has been done other than to fix the occasion user submitted bug report.

Since 2008

In 2007 the function spicetoblt was released, enabling data to be passed easily from spice to TCL. This was the first indicator of TCLspice revival. In the early 2008th, TCL specific code have been copied and pasted into an ngspice CVS tarball, and the first set of TCLspice patches have been released. Then ngspice make process have been reviewed to handle libtool, required for generating libraries in a platform independent way.

Current status

TCLspice is not yet included into ngspice source tree, as both simulators are under heavy development. TCLspice can be downloaded as an independent tarball and the source code is taken from ngspice latest development snapshot.

Road map

■This is probably the more dificult point.
■I think there are a few bugs. :) Let's make sure.
•Documentation: This still needs to be corrected. Any remarks welcome. This documents can be enriched of your many contributions.
◦Correct what is wrong,
◦Send me the link of your reference pages to populate the bibliography of the user manual,
◦Document the code of your most brilliant scripts to include them in the "learn by example" section.
■Looking for a good TCL developer to develop a good TCL front-end: intuitive, proficient, easy to use, and so on. This is intended to be an independent project, but TCLspice and NGspice relies on it.
■The front-end will be independent from the simulator but both tclspice and ngspice will relies on it.
■A simulator engine like ngspice is very flexible. As a counterpart it is not frendly. There is a need for a front-end software that enables new users to understand and proficiently use it and, in the same time, is appealing to the professional who is skilled and doesn't want to spend time wandering through menus and icons and prefers to write batch recipes. A good front-end is necessary for the end user.
◦Windows port:
■Port to the most popular operating system.
◦While ngspice and tclspice are quite known to the free eda community, there have not been much "networking" activity. As a result very few ngspice package exists and each distribution has its own compiled with the personal preferences of the package maintainer. We should contact package maintainer and plan with them the integration of ngspice in an organized way.
◦Contact the people from the many OS distributions to plan integration of TCLspice in their packages.
◦Contact the people TCLspice initiators were working with (list above) to restart development.

TCLspice now is distributed in the core ngspice sources. Downloading the latest version of cvs sources is the best way to get it.

TCLspice was (older versions still are) distributed in a separate tarball available here. (with some bugs) For install and usage information, please refer to the user manual.

No comments: