The TCL Scripting Language
Most software tools require a scripting/batch/macro language. In the past this meant that the user had to learn a new language for each software package. This is clearly inefficient, both for the user but also for the company. They shouldn't really spend their time creating languages.
This is where TCL comes into play. It is a scripting language that can readily be used in any application. As a result, essentially all modern EDA tools now use TCL (e.g. Cadence Encounter, RTL Compiler and Synopsys Design Compiler). It just makes sense.
Another plus for TCL is that there is also a graphical toolkit to build GUIs. That is called Tk. So the combination of both is known as "TCL/Tk", pronounced "tickle T-K".
TCL is an interpreted language, no compiled binaries. So it is system independent. Unix systems usually come pre-installed with a TCL interpreter installed. Windows user can download the Activestate TCL release. But most likely you want to write a script for a particular tool. In that case no external interpreter is needed.
The original TCL shell can usually be started with "tcl", and the graphical TCL/TK shell is called "wish". Start either one and just type away TCL commands. Since we are mostly interested in EDA we will use Cadence Encounter for this tutorial. Start it with the command "encounter".
TCL has a very simple structure. Each command is of the form
command param1 param2 ...
No parenthesis, nothing at the end of the line. Just a command and a number of parameters. There are no variable types either, they are derived from the context.
Let's begin with a quick "Hello World" example:
We can conclude the following items:
At first sight TCL code looks fairly different from C code, but its structure is very simple and intuitive.
As with any language there are the usual "if-then" and "for" structures. Here is a for-loop where $a is counted from 1 to 9. The sequence of parameters is similar to C, begin - check - next - command:
We can readily add an if-command to only print odd numbers:
The if statement in the previous example works like this: The modulo of 2 for an even number is zero. And "zero" means "false" in TCL. To summarize, Boolean false values in TCL are "0", "false" and "no". Everything else is Boolean true.
A very powerful feature of TCL is the built in list handling. You may recall the pain of building a linked list in C, pointers everywhere. TCL has a built in list data-type and all the typical command to handle list elements. Consider this example:
We see that a list is really just a string with all list elements separated by white spaces. We can use "lappend" to add elements, "llength" to query the number of elements and "lindex" to obtain a specific element. To sort a list we can use "lsort".
The next question is, once you built a list, what do you do with it? This is where the "foreach" command comes in handy. It provides a simple way to traverse all list elements. In the next example we use it to simply output each element:
In this last example we use "foreach" to loop over all elements in our list. At each iteration, the current value is stored in $word. Then we can act upon that value, in our case with "puts".
Just like any other programming language TCL supports procedures. Usually the code is put into a separate file and then loaded at run time. After that the new procedures can be used just like TCL commands.
For the next example, create a file called "myproc.tcl" with this contents:
This is a very simple procedure called "sum". It takes two parameters and returns the sum. Note there is no "return" command. TCL simply uses the last result as the return value.
To actually use this code we use the "source" command to read in our "myproc.tcl" file. This will not actually execute any code, only make "sum" available for use to use. After the "source" command we can use our new procedure just like any TCL command:
Local and Global Variables
Variables that are defined in the main section of a TCL file or on the command line are called "global variables". On the other hand, variables inside a procedure are "local variables". That makes sense because a procedure should be universal and should be able to use any variable name, regardless of which global variables are used.
But sometimes it is necessary to access a global variable. Especially in EDA software there are many switches that engineers typically use to control the implementation run. We will run an example to illustrate the problem, followed by a second example with the solution.
Let's go back to our file "myproc.tcl" and edit it like this:
We see that the new variable $c has been introduced. It has no assigned value, since it is not declared as a parameter of the procedure. We want to use whatever value $c has at the time "sum" is called. So in our example $c is a global variable.
However, when we run this example, it does not work like this:
We can certainly assign a value to $c on the command line, but as we can see $c is not visible in our procedure.
The solution is the "global" keyword. It tells TCL that a certain variable should get the global value. So we can modify "myproc.tcl" as follows:
We add the "global" command to make $c a global variable. Now it will actually get the global value that is set when "sum" is run:
We see the correct result is produced, 31=21+9+1. The 21 and 9 are given to the procedure as parameters and the "1" is the current value of $c. Using this method we can readily access all global variables in a TCL session.
TCL is a great programming language with powerful built in features and a very easy to understand syntax. In EDA tools in particular we can collect our code in ".tcl" files and then use "source" to read it in at run time.