tcl scripting(vlsi) (1)
tcl scripting(vlsi) (1)
of
• Format
— Real-world VLSI TCL scripting examples
Why TCL?
• Productivity
• Portability
— Ms Windows, UNIX variants, Macintosh, OpenVMS, BeOS, …
• Availability
— Download, use, modify and re-distribute without royalties
• Embeddable My
TCL
application
expect My
extension
• Extendible
. ..
TK
TCL
• Flexible integration
Application A Application B
TC
• Easy to learn (e.g. Solaris) (e.g. WinNT)
L
TCL was adopted by the SoC Design industrial community as a “standard” scripting
language for SoC Design tool scripting. Availability of a common language eases
design tool integration, reduces training costs, but also accelerates SoC Design tool
development as a common standardized TCL support may be implemented using
freely downloadable sources.
TCL shell (tclsh)
• Command-line interface
— Interactive incremental testing (try & see)
You may also come across tools which use TCL versions 7.6, 8.2 and beyond.
There are significant differences between these versions (new commands and
new command options) and therefore it is advisable to consult tool documentation
for any incompatibilities.
tclsh syntax
tclsh ?fileName arg arg ...?
Working with TCL scripts (UNIX)
• Interactive & iterative process
1. EDIT
2. TEST
From a TCL
From a UNIX shell: interpreter:
$$ tclsh
tclsh
tclsh my_script.tcl
$$ tclsh my_script.tcl %% source
source my_script.tcl
my_script.tcl
Hello
Hello world!
world! Hello
Hello world!
world!
$$ !!
!! %% !!
Repeat Hello !!
last UNIX
Hello world!
world! Repeat Hello
Hello world!
world!
...
... last TCL ...
command ...
command %% exit
exit
Writing a TCL script typically involves an iterative process of editing and testing
TCL script files. This process is identical for all platforms supported by TCL.
Working with TCL scripts (Ms Windows)
• Interactive & iterative process
1. EDIT
2. TEST
From a TCL
From Command/MSDOS Prompt: interpreter:
C:\>
C:\> tclsh
tclsh
C:\> tclsh my_script.tcl
C:\> tclsh my_script.tcl %% source
source my_script.tcl
my_script.tcl
Press Hello
Hello world!
world! Repeat Hello
Hello world!
world!
↑ C:\> tclsh my_script.tcl
C:\> tclsh my_script.tcl last TCL
%% !!
!!
Hello command
to repeat Hello world!
world! Hello
Hello world!
world!
last ...
... Or use ...
...
command %% exit
↑ exit
Debugger
controls
Command Variable
stack traces
TCL
script
display
Breakpoints
Commandreturn
value and error
code
TCL Interpreter in SoC Design Tools
• TCL interpreter is typically embedded in your SoC
Design tool command console (GUI or command line)
— Try invoking info commands in your favorite SoC Design
tool!
HERE
HERE
HERE
HERE
HERE
HERE
TCL-enabled SoC Design tools will be discussed in more detail later in this
Workshop.
Help!
• Command hints and manual pages
%% info
info
wrong
wrong ## args:
args: should
should be
be "info
"info option
option
?arg
?arg arg
arg ...?"
...?"
%% info
info xyzzy
xyzzy
bad
bad option
option "xyzzy":
"xyzzy": should
should bebe args,
args,
body,
body, cmdcount,
cmdcount, commands,
commands, complete,
complete,
default,
default, exists,
exists, globals,
globals, level,
level,
library,
library, locals, patchlevel, procs,
locals, patchlevel, procs,
script,
script, tclversion,
tclversion, oror vars
vars
%% info
info commands
commands
tell
tell socket
socket subst
subst open
open eof
eof pwd
pwd glob
glob
list
list exec pid auto_load_index time
exec pid auto_load_index time
unknown
unknown eval
eval lrange
lrange fblocked
fblocked lsearch
lsearch
auto_import
auto_import
...
...
%% man
man info
info
UNIX only!
Command-line hints provide quick feedback on the command syntax and available
options. Manual pages are the best source of information for each TCL command.
They are well written and updated with each release of TCL distribution.
Manual page browsing using man command works only on UNIX platforms (TCL
interpreter actually invokes man command from the native UNIX environment). On
UNIX, TCL manual pages are typically located in section n of the on-line UNIX
manual. You may use -S option to select this section in case of command name
conflict with another UNIX application, for example
man -S n file
will retrieve manual page for TCL file command and not for the UNIX file
command.
Microsoft Windows users may use Windows help file provided with the Windows
TCL distribution. The help file contains manual pages identical to those in the
UNIX distribution.
Furthermore, manual pages may be downloaded from
http://dev.scriptics.com/ in HTML format for both platforms.
EDA vendors distribute proprietary documentation for additional TCL
commands provided by their SoC Design tools.
Quiz 1
• What categories of SoC Design tools
support TCL?
(a) high-level synthesis
(b) HDL simulation
(c) automatic placement & routing
(d) prototyping & testing tools
(e) all of the above
Answer
TCL Scripting for SoC Design
TCL Basics 1
Aims and Topics
• Aim
— To familiarixe with TCL syntax and operation of a TCL
interpreter
• Topics
— TCL syntax
— Variables
— Substitution
— Command evaluation
TCL Commands
• TCL is CASE SENSITIVE
• TCL script is composed of “commands”
spaces or tabs newline terminates
TCL
separate command words the command
script
TCL
commands
info commands Enter ↵
info commands
Word Grouping
Substitution
Command Evaluation
Each line of a TCL script is processed in four steps indicated above. If you want
to be able to write effective TCL scripts you need to understand how this process
works.
The previous slide outlined command separation. In the following we will look at
the steps which follow next.
Word Grouping With "" and {}
• Use "" or {} to group words together
Note that there are other differences between grouping with "" and {}
(more later!).
puts
puts "Hello
"Hello {{ world!
world! }}
}} "" puts Hello { world! }}
puts
puts "Hello
"Hello "" world!
world! ""
"" ""
Syntax Error!
escape " with a backslash
puts "Hello \"
puts "Hello world! \"
\" world! \" "" puts Hello " world! "
puts
puts "Hello
"Hello "world!"
"world!" ""
Syntax Error!
puts
puts {Hello
{Hello {{ world!
world! }}
}}}} puts Hello { world! }}
puts
puts {Hello
{Hello "" world!
world! ""
""}}
puts Hello " world! ""
puts
puts {Hello
{Hello }world!{
}world!{ }}
Syntax Error!
## This
This is
is aa comment
comment
cmdName
cmdName arg
arg arg
arg arg
arg ...
...
cmdName
cmdName arg
arg arg
arg arg
arg ...;
...; cmdName
cmdName arg
arg arg
arg arg
arg ...
... command must be
terminated before
an in-line comment
cmdName arg
cmdName arg arg
arg arg ...; ## This
arg ...; This is
is an
an inline
inline comment
comment
escape a newline to
cmdName arg \\
cmdName arg continue on subsequent
arg arg ...
arg arg ... lines \ Enter ↵
## Even
Even aa comment
comment can
can be
be split
split across multiple \\
across multiple
lines!
lines!
Variables
• No need to declare variables
— Use set to create a variable and assign/retrieve its value
— Use unset to delete one or more variables
%% set
set aa "Hello
"Hello world!"
world!"
Hello assigns Hello world! to variable a and returns this new value
Hello world!
world!
%% set
set aa with no value, set returns the value of the named variable
Hello
Hello world!
world!
%% set
set bb reading variable which wasn’t previously defined is an error
can’t
can’t read
read "b":
"b": no
no such
such variable
variable
%% set
set bb 123
123 value 123 is a string containing characters 1, 2 and 3
123
123
%% unset
unset aa bb deletes variables a and b from the TCL interpreter
%% (deleting variable which wasn’t previously defined is an error)
Word Grouping
variable
Substitutiom backslash
command
Command Evaluation
Substitution
• All command words are searched for special constructs which
trigger substitution
— Words are examined from left to right, character by character
$
start
%% set
set dd 10;
10; set
set pp 22
22
%% puts "Time == $d
puts "Time $d ns"
ns" puts Time = $d ns
Time == 10
Time 10 ns
ns
$d is replaced by its
value (10)
puts Time = 10 ns
%% puts
puts "Flag\t\"rst\"
"Flag\t\"rst\" on"
on" puts Flag\t\"rst\" on
Flag
Flag "rst"
"rst" on
on
tab quotes quotes
%% puts
puts "Synthesis done. \a\a\a"
"Synthesis done. \a\a\a" beeps 3 times
Synthesis
Synthesis done.
done.
%% puts "ABC == \x41\102\x43"
puts "ABC \x41\102\x43" inserting binary values into a TCL
ABC == ABC
ABC ABC string
%% puts
puts "Some specials: \$\"\\"
"Some specials: \$\"\\" escaping special characters $, “ and \
Some specials: $"\
Some specials: $"\
Everyone’s Favourite: The Newline
• Inserting newlines
%% puts
puts "Line
"Line 11 %% puts
puts "Line
"Line 1\nLine
1\nLine 2"
2"
newlines within "" Line
Line 2"
Line 2" Line 11
or {} are reserved Line
Line
Line 11 Line 22
insert a newline with \n
Line
Line 22 %%
2nd newline inserted
%% by puts
• Avoiding newlines
%% puts
puts "Line
"Line 1\
1\ escaped newline + zero or more spaces or tabs are
replaced with a space!
Line
Line 2"
2"
Line
Line 11 Line
Line 22
%%
%% puts
puts "No\
"No\
— If you don’t want the space, use \b
\bSpace"
\bSpace"
delete the substituted NoSpace
NoSpace
space with a backspace %%
Newlines are very useful for improving readability of user messages, simulation
data, serial bitstream, formatting raw data strings, etc. The above examples
demonstrate some of the typical uses of newlines in TCL scripts.
Command Substitution ([])
• Each occurrence of [<commands>] is replaced with the value
returned from the last command executed in <commands>
— Except where [] are escaped (\[ and \])
%% set
set dd 10
10 puts Time = [set d]ns
10
10
%% puts "Time == [set
puts "Time [set d]ns"
d]ns" set d
Time == 10ns
Time 10ns Command Separation
Word Grouping
Substitution
Command Evaluation
10
set b [set a]
set b eggs
eggs
eggs
puts Two nested eggs
Word Grouping with []
• [] can be used for word grouping too!
— Do not escape word separators and grouping quotes within []
puts [set
%% puts [set bb "No
"No [set
[set aa "escapes
"escapes here"]"]
here"]"]
No
No escapes
escapes here
here [] group the argument to puts
escapes here
No escapes here
Command Separation
Word Grouping
variable
Substitution backslash
command
Command Evaluation ?
Command Evaluation
• TCL interpreter searches for a matching TCL
command (command name is the 1st word) and then
passes all arguments to it
• Next the command will execute
— Can interpret arguments in any way (strings, numbers, etc.)
• Commands
— Built-in puts puts No escapes here
— User-defined
set
Quiz 2
file: examples/quiz2.tcl
set
set aa 10
10
set
set bb "{$a}\{
"{$a}\{ #[set
#[set cc 14]"
14]"
puts
puts "$b"
"$b"
Answer
TCL Scripting for SoC Design
TCL Basics 2
Aims and Topics
• Aim
— To learn about using TCL for arithmetic calculations, basics of
file manipulation and structured scripting
• Topics
— Mathematical operations
— Basic file manipulation
— Basic procedures
Mathematical Operations
• TCL supports all usual operators and
functions
• Mathematical
— Arithmetic
— Relational
— Logical
— Bit-wise
— Various functions
• But also
— String pattern matching
— List, array, string manipulation
— File I/O, inter-process, network
— ... (more later)
TCL as a Calculator
• Use expr command to evaluate mathematical expressions
10 - 20
%% expr
expr 11 ++ 11
22
%% set
set aa 10;
10; set
set bb 20
20 expr
20 substitution performed first by the
20 TCL interpreter and then by the
%% expr
expr $a
$a -- $b
$b expr command
-10
-10
%% expr
expr {$a
{$a -- $b}
$b} substitution performed only by the $a - $b
The improved speed of calculation when the expression is enclosed in braces can
be observed even on a simple example above.
expr {$a -$b} executes 7 times faster than expr $a - $b
bits 7 6 5 4 3 2 1 0
0000 0111 (7)
%% set
set aa 0x07
0x07 AND 0000 0100 (4) read bit 2
0x07
0x07 0000 0100 (4)
%% expr $a && 0x04
expr $a 0x04
44 0000 0111 (7)
set bit 3 to 1
%% set
set aa [expr $a || 0x08]
[expr $a 0x08] OR 0000 1000 (8)
15
15 0000 1111 (15)
%% set
set a_neg [expr ~$a
a_neg [expr ~$a ++ 1]
1]
-15 INV 0000 1111 (15)
-15 1111 0000 (-16) change the sign
+ 0000 0001 (1) (2's complement)
1111 0001 (-15) NB: equivalent to
set a_neg -$a
0000 1111 0
0001 1110 0 shift LEFT by 2 bits
%% expr $a <<
expr $a << 22 left shift always inserts 0
60 0011 1100 (60)
60
%% expr $a >>
expr $a >> 11
77 0000 1111 shift RIGHT by 1 bit
%% expr $a_neg >>
expr $a_neg >> 11 0000 0111 (7)
-8
-8 right shift always propagates
the sign bit!
1111 0001
1111 1000 (-8)
Mathematical Functions
• These functions can be used INSIDE math expressions
Examples:
π
trigonometric functions expect
expr sin(3.1415927
%% expr sin(3.1415927 // 2.0)
2.0) arguments in RADIANS
1.0
1.0
%% expr returns real number even when the
expr pow(2,
pow(2, 16)
16) arguments are integers...
65536.0
65536.0
%% expr ...but this can be easily converted back to
expr int(pow(2,
int(pow(2, 16))
16)) integer, if needed
65536
65536
%% expr
expr ceil(sqrt(2))
ceil(sqrt(2)) returns nearest integer GREATER than √2
2.0
2.0
%% expr
expr floor(sqrt(2))
floor(sqrt(2)) returns nearest integer LESS than √2
1.0
1.0
%% expr returns a FLOATING-POINT reminder
expr fmod(4.57,
fmod(4.57, 2.0)
2.0) after the division of 4.57 by 2.0
0.57
0.57
%% expr
expr int(rand()*10)
int(rand()*10) returns a random integer in the interval
0-9 (inclusive)
66
rand() returns a random real number in the interval
0 (inclusive) to 1 (exclusive)
Incrementing and Decrementing
• Can be done using expr command...
%% set
set aa 10
10
10
10
%% set
set aa [expr
[expr $a
$a ++ 1]
1]
11
11
%% set
set aa [expr
[expr $a
$a -- 5]
5]
66
%% proc
proc average
average {n1
{n1 n2
n2 n3
n3 n4}
n4} {{ proc
2.5
2.5 INSIDE the procedure, i.e
%% average
average -10
-10 10
10 -50
-50 33 they are local variables average
-11.75
-11.75
%% set
set appname
appname "My
"My script"
script"
My
My script
script variable appname is available globally - both
%% proc
proc print_error
print_error {msg}
{msg} {{ INSIDE and OUTSIDE the procedure.
global
global appname
appname This is a global variable.
puts
puts "$appname:
"$appname: $msg"
$msg"
}}
Command Separation
Word Grouping
variable
Substitution backslash
command
Command Evaluation
expr cd average
set
puts incr
pwd ...
glob proc
Grouping with {} and "" Revisited
• Quotes ("") enable substitution
– [], $, \ substitutions performed as usual
%% set
set aa xyz
xyz
xyz
xyz
all substitutions
%% puts
puts "Substituting
"Substituting as
as usual:
usual: \x41,
\x41, $a,\
$a,\ performed as usual
number
number == [set b 123]"
[set b 123]"
Substituting
Substituting as usual: A,
as usual: A, xyz, number == 123
xyz, number 123
substitutions disabled,
puts {Substitution
%% puts {Substitution disabled:
disabled: \x41,
\x41, $a,\
$a,\ BUT \<newline>
number
number == [set
[set bb 123]}
123]} substitution is allowed
Substitution
Substitution disabled:
disabled: \x41,
\x41, $a,
$a, number
number == [set
[set bb 123]
123]
When Do I Use "" and when Do I Use {}?
• Use "" for
— Quoting string values
— Immediate processing
• Substitutions performed BEFORE the command is executed
• Use {} for
— Avoiding substitution
— Deferred processing
store frequently-used expressions, which
• Delay substitutions until “LATER” will be used later
Note that in the last command, the $cost argument must not be enclosed in
braces! This is because two rounds of substitutions are required to be performed
on the argument to expr. First the TCL interpreter substitutes $cost for the
expression $a*0.1 + $b*0.6 $c*0.3 and then the expr command substitutes
values for $a, $b and $c.
Quiz 3
file: examples/quiz3.tcl
%% set
set aa 22
22
%% proc
proc print_q
print_q {a}
{a} "puts
"puts {Value
{Value == $a}"
$a}"
%% proc
proc print_b {a}
print_b {a} {puts
{puts "Value
"Value == $a"}
$a"}
%% print_q
print_q 33
Value == ???
Value ???
%% print_b
print_b 33
Value == ???
Value ???
Answer
LAB 1: Extracting Bits from Integers
• Using a TCL interpreter in an interactive mode,
extract 4 least significant bits from a positive integer
number between 0 to 15.
• Example:
LSB
... 1 0 0 1
%% set
set aa 99
99
%% set
set b0
b0 [[ ...
... ]]
11
...
... insert your code here
...
...
...
...
%% set
set bb "$b3$b2$b1$b0"
"$b3$b2$b1$b0"
1001
1001
LAB 1: Extracting Bits from Integers (2)
• Stage 1
— Use expr TCL command with the following arithmetic operators
$a >> 1 shift content of variable a right by 1 bit
$a & 1 apply bit-wise AND on the contents of variable a to
extract the least significant bit
— Use command substitution []to assign individual bits to four
variables, e.g. b0, b1, b2 and b3, and then store the result in b
— Do NOT use if or other control flow commands (not covered yet)!
• Stage 2
– Store the algorithm as a new TCL command to_bits (returns the result)
— Print b after the result to indicate binary format, e.g. 1010b
– Print a warning message if the input value is outside the valid 0-15 range
• use the a?b:c operator to test whether input falls within the valid range
TCL Scripting for SoC Design
Control Flow
Aims and Topics
• Aim
– To learn how to control command execution in
TCL
• Topics
– What is control flow?
– Conditional commands
– Looping commands
– Loop control
What is Control Flow?
• A collection of TCL commands which can be used to
control when and how many times commands are
executed
• Conditional command
execution
conditionally – if
execute or skip
commands – switch
• Looping commands
repeat – for
commands
– foreach
– while
• Loop control
– break
– continue
Conditional Execution: if
• Execute commands IF the condition is true
– Condition is evaluated in the same way as expr expression
– Enclose the condition and if command body in {} unless you require
substitution
if
if {$area $area_desired} then
{$area << $area_desired} then {{ if 1 (true) if
puts
puts "Desired area constraint met."
"Desired area constraint met." condition body
}}
0 (false)
if body
Use indentation
to improve readability!
Conditional Execution: if-else
• Execute if body commands IF the condition is true,
ELSE execute else body
if 1 (true) if
if condition
if {$area
{$area << $area_desired}
$area_desired} then
then {{ body
puts
puts "Desired area constraint met."
"Desired area constraint met." 0 (false)
}} else
else {{
puts
puts "Area
"Area constraint
constraint VIOLATED."
VIOLATED." else
else is
optional
}} body
else body
Conditional Execution: if-elseif-else
• Test for more than one condition with elseif
– Any number of elseif’s can be used
Complete if syntax
The above are trivial examples. Pattern bodies may contain more than one
command.
If default is not the last pattern, it will be matched as an ordinary string "default".
Matching Multiple Patterns with switch
• To match several different patterns use ‘-’ separator...
switch
switch --
-- $cellName
$cellName {{
AND2 -- AND3
AND2 AND3 {incr
{incr and_count}
and_count} incr and_count will be executed
OR2 - when $cellName is AND2 or AND3
OR2 -
OR3
OR3 {incr
{incr or_count}
or_count} Use one line for each pattern
INV
INV {incr inv_count}
{incr inv_count} to improve readability!
default
default {puts
{puts "Unrecognized
"Unrecognized cell."}
cell."}
}}
Always use -- to prevent
match patterns using switch from confusing
glob-style pattern matching strings with options.
newlines
must be
set hier_path
set hier_path "/DecoderModule/mp3/U*"
"/DecoderModule/mp3/U*" escaped
switch
switch -glob
-glob -- $cellName \\
-- $cellName
patterns defined ${hier_path}AND*
${hier_path}AND* {incr and_count} \\
{incr and_count}
during run-time ${hier_path}OR*
${hier_path}OR* {incr or_count} \\
{incr or_count}
using substitution
${hier_path}INV
${hier_path}INV {incr inv_count} \\
{incr inv_count}
default
default {puts "Unrecognized cell."}
{puts "Unrecognized cell."}
switch matching patterns can be changed during the run-time. For example, the
switch statement above allows to define the path for the cells to be searched for
by changing the value of the hier_path variable.
Patterns searched for in the above command are:
• /DecoderModule/mp3/U*AND*
• /DecoderModule/mp3/U*OR*
• /DecoderModule/mp3/U*INV
Looping: for
• Use for to execute commands specified number of times
– LAB 1 revisited
set execute
set aa 9;
9; set
set bb ""
"" start
start test next execute
next
for
for {set
{set ii 0}
0} {$i
{$i << 4}
4} {incr
{incr i}i} {{
set
set bit [expr ($a >> $i) & 0x1]
bit [expr ($a >> $i) & 0x1] evaluate
1 (true)
execute
set b "$bit$b"
set b "$bit$b" test body
}} body
0 (false)
%% set
set lib_cells
lib_cells "INV
"INV AND
AND OR"
OR"
INV
INV AND
AND OR
OR
foreach cell
%% foreach cell $lib_cells
$lib_cells {{ execute
puts "Found library cell: $cell" body
}– usingputs2"Foundloop valibraryriables cell:
$cell" next
Found library cell: INV 1 (true) assign next
} bod element
Found library cell: AND elements to the
y available
Found library cell: INV loop variables
Found library cell: OR ?
Found library cell: AND
%Found 0 (false)
library cell: OR
%
Multiple Loop Variables with foreach
• Useful for parsing results returned from other commands
%% set
set cell_counts
cell_counts "INV
"INV 55
55 AND
AND 10
10 OR
OR 20"
20"
INV
INV 55
55 AND
AND 10
10 OR
OR 20
20
foreach syntax
foreach varName list body
set
set number
number 20
20 test
set
set bits
bits 11 evaluate 1 (true) execute
while
while {(pow(2,
{(pow(2, $bits)
$bits) -- 1)
1) << $number}
$number} {{ test body
incr bits
incr bits
}} 0 (false)
bod
y
if {condition1} then
if {condition1} then {{ foreach
foreach varName
varName list
list {{
body1
body1 body
body
}} elseif
elseif {condition2}
{condition2} {{ }}
body2
body2
}} elseif
elseif {condition3}
{condition3} {{
body3
body3 Group conditions, while
while {test}
{test} {{
}} tests and bodies with body
body
{} unless you }}
require substitution.
switch
switch string
string {{
pattern1
pattern1 {body1}
{body1} break
break terminate the loop
pattern2 {body2}
pattern2 {body2}
skip the current
pattern3 --
pattern3 match pattern3 OR pattern4 continue
continue iteration
pattern4
pattern4 {body4}
{body4}
default if present,
default {default
{default body}
body} default must be the LAST pattern
}}
Braces & Spaces (Grouping Mistakes)
WRONG RIGHT
if
if {$a
{$a >> 0}
0} puts
puts "positive"
"positive" if
if {$a 0} {puts
{$a >> 0} {puts "positive"}
"positive"}
body NOT
grouped!
if
if {$a
{$a >> 0}{
0}{ if
if {$a
{$a >> 0}
0} {{
missing space
puts "positive" puts "positive"
puts "positive" between }{ ! puts "positive"
}} }}
Use braces and you
won't need to worry
condition NOT grouped!
about spaces!
if $a
if $a >> 00 {puts
{puts "positive"}
"positive"} if {$a >> 0}
if {$a 0} {puts
{puts "positive"}
"positive"}
if {$a
if {$a >> 0} {{
0} if {$a
if {$a >> 0} {{
0}
puts
puts "positive"
"positive" puts
puts "positive"
"positive"
}} TWO }} else
else {{
else commands! puts "negative"
else {{ puts "negative"
puts
puts "negative"
"negative" }}
}}
Quiz 4
set a 0 file:
while {$a < 150} { examples/quiz4.tcl
incr a
switch $a {
100 {continue}
140 {set a 300}
200 {break}
}
}
puts "Value of a = $a"
Answer
TCL Scripting for SoC Design
Strings
Aims and Topics
• Aim
— To learn about how to work with strings in
TCL
• Topics
— Constructing strings
— String operations
— Extracting information from strings
— Binary strings
What is a String?
• Any collection of characters
— Letters, digits, special characters, binary characters, etc.
o
Constructing Strings
• Strings in TCL can be constructed in a variety of
ways
— Typing the string characters
%% set
set aa "Hello";
"Hello"; set
set bb "world";
"world";
— Substitution and set world
world
— TCL append command %% set
set cc "$a
"$a $b!"
$b!"
Hello
Hello world!
world!
%% append
append dd $a
$a "" "" $b
$b "!"
"!"
Hello
Hello world!
world!
It might seem that there is no justification for having append, when the same effect
can be achieved using substitution. However, the append command is significantIy
faster when constructing Iong strings. In the above exampIe, if the body of the
foreach Ioop is repIaced with
set test_script "${test_script}source $f\n"
the Ioop wiII be 200 times slower!
• Return value:
O strings str1 and str2 are IDENTICAL
1 string str1 is lexicographically AFTER string str2
-1 string str1 is lexicographically BEFORE string str2
%% string
string match
match "*/mp3/*"
"*/mp3/*" "ƒDecoderModule/mp3/U4"
"ƒDecoderModule/mp3/U4"
11
%% string
string match
match "*/mp3/*"
"*/mp3/*" "/DecoderModule/mpeg2/U12"
"/DecoderModule/mpeg2/U12"
OO
• Return value:
O pattern does NOT match string
1 pattern matches string
Glob-style Match Patterns
• glob-style patterns are similar to UNIX shell wildchar
patterns
• glob-style patterns use the following special characters
? matches any SINGLE character
* matches any sequence of xero or more characters
\c matches the SINGLE (escaped) character c
[abc] matches any SINGLE character in abc
[a-b] matches any SINGLE character between a-b (inclusive)
{abc,xyz,...} matches any of the strings abc, xyz, etc.
string toupper
%% string toupper "Vhdl
"Vhdl Edif
Edif TCL"
TCL" convert Iowercase characters to
VHDL UPPERCASE
VHDL EDIF
EDIF TCL
TCL
string tolower
%% string tolower "DECODER.VHD"
"DECODER.VHD" convert UPPERCASE characters to Iowercase
decoder.vhd
decoder.vhd
string trim
%% string trim "" Area:
Area: 2345
2345 remove white spaces (spaces, tabs,
"" newIines, carriage returns) from the
beginning and the end of the string
Area:
Area: 2345
2345
string trim
%% string trim "((a+b)))"
"((a+b)))" ")("
")(" remove onIy the specified characters,
e.g. ) and ( in this case
a+b
a+b
string trimleft
%% string trimleft "..ƒmp3/"
"..ƒmp3/" "ƒ."
"ƒ." remove onIy the specified characters (/ and .)
mp3/
mp3/ and onIy from the BEGINNING of the string
string trimright
%% string trimright "../mp3ƒ"
"../mp3ƒ" "ƒ"
"ƒ" remove onIy the specified characters (/)
../mp3
../mp3 and onIy from the END of the string
• Typical examples
%% set
set add
add 65365;
65365; set
set dd 31;
31; set
set period
period .OOOOO462
.OOOOO462
.OOOOO462
.OOOOO462
%% format "Writing %d
format "Writing (%#x, %#o)
%d (%#x, %#o) to address %#x"
to address %#x" $d
$d $d
$d $d
$d $add
$add
Writing 31
Writing (0x1f, 037)
31 (0x1f, 037) to address 0xff55
to address 0xff55
%% format
format "Max
"Max period:%15.2e (%f) seconds"
period:%15.2e (%f) seconds" $period
$period $period
$period
Max
Max period:
period: 4.62e-006
4.62e-006 (0.000005)
(0.000005) seconds
seconds
format syntax
• Typical example
%% set
set report
report "Total
"Total size:
size: 12345
12345 cells;
cells; Clock:
Clock: 24
24 MHz"
MHz"
Total
Total size:
size: 12345
12345 cells;
cells; Clock:
Clock: 24
24 MHz
MHz
%% scan
scan $report
$report "%s%s%d"
"%s%s%d" w1 w2 cells
w1 w2 cells
returns the number 33
of matched strings %% set
set cells
cells
12345
12345
conversion specifiers: variabIes into which the matching strings
string, string, integer wiII be assigned
scan syntax
WhiIe scan is a usefuI command for scanning simpIe string patterns, reguIar
expressions offer more powerfuI method for scanning strings (Session 8).
Using Character Indices
• Individual characters can be manipulated using their index
values with the string command
H e I I o w o r I d !
the first character
has index 0
0 1 2 ..................... 11
string first
%% string first "FF2"
"FF2" $data
$data string index
%% string index $data
$data 13
13
77 11
string last
%% string last "FF2"
"FF2" $data
$data string range
%% string range $data
$data 1O
1O 21
21
22
22 OOO16OOB7914
OOO16OOB7914
string length
%% string length $data
$data string range
%% string range $data 25 end
$data 25 end
33
33 O3C899FE
O3C899FE
set i O
set j O
Answer
LAB 2: Working with a String Bitstream
• Write a procedure get_filename which will extract the
design file name from a Xilinx FPGA bitstream file (.bit).
• Example:
% source bitstream.tcl this wiII read the FPGA
bitstream and store it in the TcI
% get_filename $bitstream variabIe bitstream
file_ad.ncd
VariabIe bitstream contains
bitstream is string in
hexadecimaI format.
• Stage 2
– Extract the other fields from the bitstream header
• NOTE: the field data may also contain characters Ox61-Ox65 (a-e) !
— Check whether the file name field has the correct length
TCL Scripting for SoC Design
• Topics
— Lists
• building lists
• manipulating lists
— Arrays
• building arrays
• manipulating arrays
— Lists versus Arrays
What is a List?
• List is a collection of ORDERED elements
— List elements are strings
• Can represent anything (string values, other lists, other TCL
data structures, etc.)
— List elements are separated by whitespaces
• Spaces, tabs, newlines
list element
separator
• TCL list of 5 "lemon"
elements: %% set
set fruits
fruits "apple
"apple lemon
lemon banana
banana pear
pear grapes"
grapes"
apple
apple lemon
lemon banana
banana pear
pear grapes
grapes
Manipulating List Elements
• Use llength to count the number of elements in a list
%% llength
llength $fruits
$fruits
55
%% lindex
lindex $fruits
$fruits 11 %% lrange
lrange $fruits
$fruits 00 22
lemon
lemon apple
apple lemon
lemon banana
banana
%% lindex $fruits end
lindex $fruits end %% lrange $fruits 33 end
lrange $fruits end
grapes
grapes pear
pear grapes
grapes
llength list
%% set
set cells
cells "inv
"inv {and2
{and2 or2}
or2} {and3
{and3 or3}
or3} or4"
or4"
inv
inv {and2
{and2 or2}
or2} {and3
{and3 or3}
or3} or4
or4
TCL returns {}'s
to indicate list lists within the 2nd element of the cells list
grouping.
The {}'s are NOT
part of the list!
%% set
set cells
cells "inv
"inv {{and2
{{and2 nand2}
nand2} {or2
{or2 nor2}}"
nor2}}"
inv
inv {{and2
{{and2 nand2}
nand2} {or2
{or2 nor2}}
nor2}}
%% set
set library
library "ams.vhdl
"ams.vhdl {and
{and 22 100}
100} {or
{or 22 120}
120} {inv
{inv 11 20}"
20}"
ams.vhdl
ams.vhdl {and
{and 22 100}
100} {or
{or 22 120}
120} {inv
{inv 11 20}
20}
Building Lists (1)
• Use word grouping with "" (or {})
• Use list command all arguments become list elements
%% set
set fruits
fruits [list
[list apple
apple lemon
lemon banana
banana pear
pear grapes]
grapes]
apple
apple lemon
lemon banana
banana pear
pear grapes
grapes
%% lappend
lappend fruits
fruits strawberry
strawberry orange
orange
apple
apple lemon
lemon banana
banana pear
pear grapes
grapes strawberry
strawberry orange
orange
• Equivalent to
%% set
set fruits
fruits "$fruits
"$fruits strawberry
strawberry orange"
orange"
apple
apple lemon
lemon banana
banana pear
pear grapes
grapes strawberry
strawberry orange
orange
%% set
set fruits
fruits [lreplace
[lreplace $fruits
$fruits 11 11 orange]
orange] use IDENTICAL indices
pineapple if only ONE element is
pineapple orange
orange lemon
lemon
to be replaced
%% set
set fruits
fruits [lreplace
[lreplace $fruits
$fruits 00 0]
0] (or deleted)
orange
orange lemon
lemon
proc lreverse
proc lreverse {l}
{l} {{
set
set reversed_l
reversed_l """"
foreach
foreach element
element $l
$l {{
set
set reversed_l [linsert
reversed_l [linsert $reversed_l
$reversed_l 00 $element]
$element]
}}
return
return $reversed_l
$reversed_l
}}
• Typical uses
— Manipulate hierarchical paths (rename elements, change the
separator, determine the depth of hierarchy, etc.)
list element separator
— Extract useful information from strings, and more... characters (1 or more)
• Return value
-1 pattern does NOT match any elements in the list
0-end index of the first element matching the pattern
Examples: Searching Lists
• Glob-style pattern matching
%% set
set cell_list
cell_list "inv
"inv and2
and2 or2
or2 and3
and3 or3
or3 or4"
or4"
or2 inv
inv and2
and2 or2
or2 and3
and3 or3
or3 or4
or4
found at %% lsearch $cell_list or*
lsearch $cell_list or*
index 2 glob-style search patterns
22
%% lsearch
lsearch -glob $cell_list xor*
-glob $cell_list xor*
-1
-1
• Exact matching
%% lsearch
lsearch -exact $cell_list or4
-exact $cell_list or4
55 exact strings to be matched
%% lsearch
lsearch -exact $cell_list and
-exact $cell_list and
-1
-1
Sorting Lists
• Use lsort to sort list elements
returns the list of TCL commands
(UNSORTED)
%% set
set sorted_cmds
sorted_cmds [lsort
[lsort [info
[info commands]]
commands]]
after
after append
append array
array auto_execok
auto_execok auto_import
auto_import auto_load
auto_load
auto_load_index
auto_load_index auto_mkindex auto_mkindex_old auto_qualify
auto_mkindex auto_mkindex_old auto_qualify SORTED list
auto_reset
auto_reset binary
binary break
break case
case catch
catch cd
cd clock
clock close
close concat
concat of commands
...
...
• Assigning/reading the
value
value of an array element
array variable name key value
set IT_people(john)
%% set IT_people(john) memo
memo
memo
memo
set IT_people(john)
%% set IT_people(john)
memo
memo key
All keys in the array must be defined before the key is to be accessed. For
example, set IT_people(edward) will generate an error message.
Basic Array Operations
• Arrays and their elements can be manipulated as other
TCL variables
— Retrieve element’s value using variable substitution
%% puts
puts "John
"John received
received aa $IT_people(john)."
$IT_people(john)."
John
John received
received aa memo.
memo.
3D array %% set
set frame_set(10,100,2)
frame_set(10,100,2) 250
250 string!
250
250
%% set
set synthesis_results(smallest,23ns)
synthesis_results(smallest,23ns) 34mW
34mW
easy to combine 34mW
34mW
1D, 2D, 3D, ... %% set
elements in ONE array!
set image(filename)
image(filename) lena.rgb
lena.rgb
lena.rgb
lena.rgb
Examining Arrays
• Use array mega-command to obtain information about
array variables
— Check for the existence of the array variable
• Returns 0 if the variable is not an array or it does not exist
• Returns 1 otherwise
array exists
%% array exists IT_people
IT_people
11
(255,255)
Lists versus Arrays
LISTS ARRAYS
• Can store various elements • Can store various elements
• Order of elements is preserved • Order of elements if NOT
preserved
• Elements are retrieved using an • Elements are retrieved using
INTEGER index a STRING key
• Lists are manipulated using the • Arrays are manipulated using
list value the name of the array variable
%% set
set ll [list
[list rr gg b]
b] %% array
array set
set aa {{
rr gg bb order is NOT rr RED
preserved
RED gg GREEN
GREEN bb BLUE
BLUE }}
order is %% llength
llength $l
$l %% array
array names
names aa
preserved 33 list l is accessed by array a is accessed
bb rr gg
its value $l (not l) by the name of array
variable a (not $a)
Lists and arrays provide two ways of storing multiple data elements. When
deciding between the two, it is best to choose a data structure which is the most
natural representation of the data.
For example, a phone book is most naturally represented in an array as names
can be used as array keys. A list of files is usually represented using lists, as this
allows easy file browsing, sorting and manipulation.
Before TCL 8.0 lists access was much slower than array access. Since TCL 8.0
both lists and arrays are internally represented using similar data structures. TCL
then provides advantages of using linked lists, but with the performance of array
access.
Quiz 6
set a_list {apple lemon pear} file:
array set a_array {0 apple 1 lemon 2 pear} examples/quiz6.tcl
Answer
LAB 3: Sorting Design Blocks
• Write a procedure sort_by_area which will sort the design
blocks according to their area
– decoder is a global list which contains the list of design blocks
– block_area is a global array which stores areas of all leaf blocks
• For example $block_area(/Decoder/mp3/u1) is the area
of the /Decoder/mp3/u1 block
Decoder
mp3 GND
u1 u2 buffer
• Example: u1
%% source
source decoder.tcl
decoder.tcl
%% sort_by_area
sort_by_area $decoder
$decoder
/Decoder/GND
/Decoder/GND /Decoder/buffer/u1
/Decoder/buffer/u1 /Decoder/mp3/u1
/Decoder/mp3/u1 /Decoder/mp3/u2
/Decoder/mp3/u2
LAB 3: Sorting Design Blocks (2)
• Stage 1
— Sort the decoder list using a custom sorting command
• Use global block_area to allow access to the block_area global
variable from within the custom comparison command
• Stage 2
— Include both the sorted block names and their respective areas
in the returned result
• Each element is a list with 2 elements: block name & area
— Construct a sub-list containing only the leaf blocks extracted
from the list of all design cells available in the decoder_full variable
• Use lsearch [array names block_area] $block_name
to check whether an area figure can be obtained for the block
— Calculate the total area for all blocks in the decoder list,
including the hierarchical blocks (mp3 and Decoder)
TCL Scripting for SoC Design
• Topics
— Reading from and writing to files
— Invoking external programs
— Multi-process communication
File Manipulation Revisited
• Simple file manipulation with cd, pwd and glob
• file command provides many other operations, e.g.:
%% file
file mkdir
mkdir ~/project/daily_backup
~/project/daily_backup CREATE a directory
%% file
file copy
copy add_v2.vhdl
add_v2.vhdl ~/project/daily_backup
~/project/daily_backup COPY a file/directory
%% file
file rename
rename sub_v4.vhdl sub.vhd
sub_v4.vhdl sub.vhd RENAME a file/directory
%% file
file rename
rename sub.vhd
sub.vhd ~/project/archive
~/project/archive MOVE a file/directory
%% file
file delete
delete compile.log
compile.log DELETE a file/directory
file24 is the
channel identifier
close syntax
close channelId
Catching Command Errors
• Use the catch command to trap and handle errors from
specific commands/scripts
%% catch
catch {set
{set fid
fid [open
[open does_not_exist.txt r]} result
does_not_exist.txt r]} result
11
set result
%% set result
couldn’t
couldn’t open
open "does_not_exist.txt":
"does_not_exist.txt": no
no such
such file
file or
or directory
directory
• Beware !
– catch also suppresses syntax and programming errors
— Use catch at lowest possible level to catch only the errors you expect!
Writing to Files
• Use puts to write to files
— Returns an enpty stving on success, error message otherwise
write "Hello world!" + newline
%% puts
puts $fid
$fid "Hello
"Hello world!"
world!" into an open file with channel ID $fid
%%
%% puts -nonewline
puts -nonewline $fid
$fid "Hello
"Hello world!"
world!" write "Hello world!" only
%% (no newline)
puts stdout
%% puts stdout "Hello
"Hello world!"
world!" write "Hello world!" + newline
Hello
Hello world!
world! to standard terminal output
%% puts (stdout channel is the default)
puts "Hello
"Hello world!"
world!"
Hello
Hello world!
world!
write an error message to standard terminal
puts stderr
%% puts stderr "Error:
"Error: invalid
invalid input!"
input!" error output
Error:
Error: invalid
invalid input!
input!
Be warned that stdin/out and stderr exist only when there is a terminal window. On
NT stdout and stderr are identical.
File Pointer Position
• Files are accessed using an “invisible” file pointer
— Positioned at the beginning when the file is opened
— Moves forward with each file read
moves forward as the characters are read
test1.dat: T H I S I S L I N E 1 \n T H I S ...
0 1 2 ...
the file origin
has index 0
%% seek
seek $fid
$fid 55 start
start move the file pointer 5 positions AFTER the file origin
%% seek
seek $fid
$fid 88 current
current move the file pointer 8 positions AFTER the current position
%% seek
seek $fid
$fid -10 end
-10 end move the file pointer 10 positions BEFORE the end of the file
• Typical uses
— Processing files and communication channel data line-by-line
set
set fid
fid [open
[open "test1.dat"
"test1.dat" r]
r]
while
while {[gets $fid line] >= 0}
{[gets $fid line] >= 0} {{
puts "test1.dat: $line"
puts "test1.dat: $line" the while loop will terminate at the end
}} of file (gets will return -1)
close
close $fid
$fid
source to_bits.tcl
source to_bits.tcl source other scripts if required
• Typical uses
— Reading the content of an entire file for further processing
— Processing text or binary files character-by-character
— Reading characters from communication channels
proc correct_newlines
proc correct_newlines {src_file
{src_file dest_file}
dest_file} {{
set src [open $src_file
set src [open $src_file r]r]
set
set dest
dest [open
[open $dest_file
$dest_file w]
w] destination file will use end-
puts
puts $dest [read $src]
$dest [read $src] of-line characters
close of the host platform
close $src
$src
close $dest
close $dest
}}
TCL also supports the compatible subset of the native platform's file path
convention. However, this will only work on one native platform. It is advisable
avoid using this and use portable TCL file path handling instead.
Although the forward slash is the directory separator, one should use file split and
file join to analyze and construct the filenames.
Channel Buffering
S NO
T
... I H I
buffering
\n
1 T H
E
puts N
I L
THIS IS LINE 1\n
S
THIS IS LINE 2\n
I T
H
LINE
channel buffer buffering
There is an internal buffer associated with each I/O channel. For example, when
puts command puts characters into a channel, the characters are first buffered
and only then send to the channel.
There are three possible methods of channel buffering:
•NO buffering: the characters are not buffered at all. The characters are output
as they are received. This type of buffering is slow due to frequent I/O operations.
Try: source examples/buffering_none.tcl
•LINE buffering: the output is flushed after each end-of-line character. Line
buffering is the default type of buffering for terminal devices (such as stdout).
Try: source examples/buffering_line.tcl
•FULL buffering: the output is flushed after the internal buffer was filled with
characters. Full buffering is the default for file access as this provides a good
performance trade-off (I/O access occurs only after the internal buffer was filled).
Try: source examples/buffering_full.tcl
Configuring Channel Buffers
• fconfigure is used to configure the type of channel buffering
none no buffering
line line buffering
file: examples/buffering_none.tcl full full buffering
...
...
fconfigure stdout -buffering
fconfigure stdout -buffering none
none buffering mode
...
...
fconfigure syntax
fconfigure channelId
flush syntax
flush channelId
Invoking External Programs
• Use exec to invoke external programs
external program ...and its arguments
%% exec
exec zip
zip archive.zip
archive.zip test1.dat
test1.dat
adding:
adding: test1.dat
test1.dat (92
(92 bytes
bytes security)
security) (deflated
(deflated 72%)
72%)
%% eval
eval exec
exec rm
rm [glob
[glob *.log]
*.log]
%% exec
exec tar
tar -cvf archive.tar projectƒ*
-cvf archive.tar projectƒ* UNIX shell wildchars
! tar: don’t work in TCL!
tar: projects/*:
projects/*: Cannot
Cannot stat:
stat: No
No such
such file
file or
or directory
directory
...
...
%% eval
eval exec
exec tar
tar -cvf archive.tar [glob
-cvf archive.tar [glob projectƒ*]
projectƒ*] use glob instead
...
...
NOTE!
!
%% set
set dir_list [exec dir
dir_list [exec dir C:*.*]
C:*.*] dir is a built-in command
couldn’t
couldn’t execute
execute "dir":
"dir": no
no such
such file
file or
or directory
directory
%%
%% set
set dir_list [exec COMMAND.COM
dir_list [exec COMMAND.COM ƒC
ƒC dir
dir C:*.*]
C:*.*] invoke command.com
...
... with built-in command as
an argument instead
Similarly to Windows/DOS shell example above, you may also invoke commands
using a UNIX shell directly. For example, an alternative way
of executing the tar command above is
exec /bin/sh -c "tar -cvf archive.tar project/*"
This will execute correctly as the string given to the -c option is executed
by the UNIX shell (/bin/sh).
InputIOutput Redirection
• TCL implements a range of I/O redirection operators
— Redirection of standard input, output and error channels
to/from files (overwrite and append modes)
— Receive standard input from a TCL string
— Piping standard output to standard input between two commands
process ID
• ...or using open with a pipe and use the pid command
to retrieve the process ID
external program to invoke
pipe
the standard output from the ipconfig
%% set
set fid [open "|
fid [open ipconfig" r]
"| ipconfig" r] program can be accessed as a CHANNEL
file24
file24
%% pid
pid $fid
$fid
1164
1164
process ID
commands
HHDDLL H
Haarrddw
waarree
SSimmuulaatoorr results tteessttrrigg
external program
(can be another TCL read/write mode (bi-directional communication)
script!)
%% set
set fid [open "|
fid [open test_rig" r+]
"| test_rig" r+] IMPORTANT: set-up LINE buffering
file24 (FULL buffering is the default for files)
file24
%% fconfigure
fconfigure $fid -buffering line
$fid -buffering line
%% puts $fid "test1 100"
puts $fid "test1 100"
%% gets
gets $fid
$fid
test1:
test1: 1000
1000 H
Haarrddw
waarree
%% puts
puts $fid
$fid "test2
"test2 200"
200" tteessttrrigg
%% gets
gets $fid
$fid
test2:
test2: 400
400
%% close
close $fid
$fid
Answer
TCL Scripting for SoC Design
Regular Expressions
Aims and Topics
• Aim
– To gain proficiency in using regular expressions for advanced
string processing
• Topics
– Regular expressions (REs): what and why?
– Regular expression patterns
– RE-based string searching
– RE-based string replacement
Why Regular Expressions?
• String search capabilities already exist in TCL
– lsearch, string match, switch, etc.
– Inefficient for complex string search/replace operations
• Example
— RE for an output port declaration in a VHDL entity:
regular expression *[a-zA-Z][a-zA-ZO-9_]*
*[a-zA-Z][a-zA-ZO-9_]* *:
*: *out
*out [a-zA-Z][a-zA-ZO-9_]*
[a-zA-Z][a-zA-ZO-9_]*
entity add is
port (
cin : in std_logic;
a : in std_logic_vector(7 downto 0); string matching the regular expression
b : in std_logic_vector(7 downto 0);
y : out std_logic_vector(7 downto 0);
cout: out std_logic
);
end add; NOTE: RE string matching is based on context
(e.g. signal which is a 1-bit output port). Therefore
the matching will work for signals of any name or type.
Regular Expression Basics
• Alphabet and digit characters are matched as usual
a matches a SINGLE given character, i.e. character a
VHDL matches a SEQUENCE of given characters, i.e. string VHDL
%% regexp
regexp {[A-Z][A-Z]*}
{[A-Z][A-Z]*} "which
"which is
is better:
better: VHDL
VHDL or Verilog?" m_var
or Verilog?" m_var
11
%% set Enclose RE patterns within {} to protect
set m_var
m_var patterns from TCL substitution (unless
VHDL
VHDL the substitution is desired)
set
set fid
fid [open
[open "adder.vhdl"
"adder.vhdl" r]
r]
set
set add
add [read
[read $fid]
$fid]
close
close $fid
$fid
regexp
regexp -nocase
-nocase --
-- {{ *entity
*entity *[a-z][a-z0-9_]*
*[a-z][a-z0-9_]* *is
*is *} $add e_line
*} $add e_line
puts "$e_line"
puts "$e_line"
%% cd
cd examples
examples
source find_entity_line.tcl
%% source find_entity_line.tcl
entity
entity add
add is
is
file: examples/adder.vhdl
entity add is
port (
...
);
end add;
...
regexp syntax
• Alternatives
x|y matches ONE of the two possible atoms, e.g.
out|in string out OR string in
[a-z]|[0-9] lowercase letter OR a digit
file: examples/find_entity_name.tcl
...
...
regexp
regexp -nocase
-nocase --
-- {{ *entity
*entity +([a-z][a-z0-9_]*)
+([a-z][a-z0-9_]*) +is
+is *}
*} $add
$add \\
e_line e_name
e_line e_name
a sub-expression is
holds the entire holds the 1st matched enclosed within ()
matched string sub-string
puts
puts "$e_name"
"$e_name"
source find_entity_name.tcl
%% source find_entity_name.tcl
add
add
Example: Extracting VHDL Port Direction
file: examples/adder.vhdl
• More than one entity add is
port (
sub-pattern can be used cin : in std_logic;
a : in std_logic_vector(7 downto 0);
— Add additional sub-pattern b : in std_logic_vector(7 downto 0);
y : out std_logic_vector(7 downto 0);
variables as necessary cout: out std_logic
);
end add;
...
file: examples/find_port_dir.tcl
...
...
regexp
regexp -nocase
-nocase --
-- \\
{{ *([a-z][a-zO-9_]*)
*([a-z][a-zO-9_]*) +:
+: +([a-z]+)[^;]*;}
+([a-z]+)[^;]*;} $add
$add \\
p_line p_name p_dir
p_line p_name p_dir
puts
puts "$p_name
"$p_name ($p_dir)"
($p_dir)"
source find_port_dir.tcl
%% source find_port_dir.tcl
cin
cin (in)
(in)
Using Indices with regexp
• With -indices option regexp will extract string
index range instead of a string
regexp -indices
%% regexp -indices --
-- {[A-Z][a-z]+}
{[A-Z][a-z]+} "VHDL
"VHDL or Verilog?" idx
or Verilog?" idx
11
%% set
set idx
idx
88 14
14 indices or the first and the last character of the matched string
%% string
string range
range "VHDL
"VHDL or
or Verilog?
Verilog? [lindex
[lindex $idx
$idx 0]
0] [lindex
[lindex $idx
$idx 1]
1]
Verilog
Verilog
• Typical uses
– Searching for an insertion position
– Repetitive search
– Index-based string manipulation
Example: Searching for All Occurrences
• Find all entity port lines
– Use matched pattern indices to resize the search buffer
file: examples/find_all_port_lines.tcl
...
...
set { *[a-z][a-z0-9_]* *: *(in|out) +[a-z][a-z0-9_]*(\([^()]+\))?}
set buf
buf $add
$add
set llist ""
set llist ""
while
while {[regexp -nocase -indices
{[regexp -nocase -indices ---- <port_RE>
<port_RE> $buf
$buf idx]}
idx]} {{
## store
store matched
matched port
port line
line
lappend
lappend llist
llist [string
[string range
range $buf
$buf [lindex
[lindex $idx
$idx 0]
0] [lindex
[lindex $idx
$idx 1]]
1]]
## resize
resize the
the search
search buffer
buffer
set
set buf [string range
buf [string range $buf
$buf [expr
[expr [lindex
[lindex $idx
$idx 1]+1]
1]+1] end]
end]
}}
...
...
Note that since TCL version 8.3, regexp provides the -start option, which
allows to move the search pointer without the need to manipulate the search
buffer as above.
Example: Filtering Command Logs
• Extract warnings from a Simplicity .srr log file
file: examples/filtercore.srr
...
Synthesizing work.interface.rtl
@W:"c:\lab6\interface.vhd":82:39:82:43|Signal aver2 in the sensitivity list is not used in the process
Post processing for work.interface.rtl
...
file: examples/extract_warnings.tcl
proc extract_warnings
proc extract_warnings {f} {f} {{
set
set in_file
in_file [open
[open $f$f r]
r]
while
while {[gets $in_file line]
{[gets $in_file line] >= >= 0}
0} {{
if {[regexp @W $line]}
if {[regexp @W $line]} { {
regexp
regexp -nocase
-nocase -- -- \\ extracted output
{([a-z_]+\.vhd)[0-9:"|]+([a-z_\.
{([a-z_]+\.vhd)[0-9:"|]+([a-z_\. 0-9]+)}
0-9]+)} \\
$line
$line buf
buf filename
filename msgmsg
puts
puts "$filename\t\t$msg"
"$filename\t\t$msg"
}}
}}
close
close $f
$f
}}
String Substitution
• Use regsub for RE-based string substitution
replace the matched variable which will store the
RE pattern to search for input string pattern with this result
%% regsub
regsub --
-- {[a-z]+}
{[a-z]+} "cin std_logic;" "carry_in"
"cin :: std_logic;" "carry_in" new_str
new_str
11
%% set
set new_str
new_str
carry_in
carry_in :: std_logic;
std_logic;
• Useful options
– Use -nocase for case-insensitive search
– Use -all to replace ALL matched patterns (global substitution)
regsub syntax
%% regsub
regsub --
-- {[0-9]+
{[0-9]+ +([a-z]+)
+([a-z]+) +([0-9]+)} "vector(7 downto
+([0-9]+)} "vector(7 downto 0)"
0)" \\
{(n-1) \1 \2} new_str
{(n-1) \1 \2} new_str
11
%% set
set new_str
new_str
vector((n-1) downto
vector((n-1) downto 0)
0)
Using REs for Complex Substitutions
• Two-pass processing (collect & substitute)
– regexp to collect the information
– regsub to substitute
puts $new_line
Answer
LAB 4: VHDL Netlist Hacking
• Write a procedure find_vector_port which will identify the
FIRST bus port in the VHDL design entity
– An example of a VHDL design file is in adder.vhdl
entity add is
port (
cin : in std_logic;
a : in std_logic_vector(7 downto 0); Stage 2: modify the port names
b : in std_logic_vector(7 do wnto 0);
entity add is
cout: out std_logic;
sum : out port (
std_logic_vector(7 do wnto 0);
cin : in std_logic;
)
a_bus : in std_logic_vector(7 downto 0);
end add;
b_bus : in std_logic_vector(7 downto 0);
cout : out std_logic;
sum_bus : out std_logic_vector(7 downto 0);
)
end add;
• Example:
%% find_vector_port
find_vector_port adder.vhdl
adder.vhdl
First
First bus
bus port is aa
port is
%%
LAB 4: VHDL Netlist Hacking (2)
• Stage 1
– Open and read in the entire adder.vhdl file into a variable
– Use regexp to extract the first entity port name, which is a vector
• Construct a regular expression to identify the port name with the
std_logic_vector type
– Print the port name on the terminal
• Stage 2
– Replace regexp with regsub to append _bus string to ALL vector port
names and save the new adder entity into a new file
– Include port indices into the port names, e.g. ain_bus_7_0
– Replace the port bus signals with a number of single-bit signals
labelled with their respective indices, e.g. ain_7, ain_6, etc.
– Replace ALL design bus signals (in entity and architecture)
with single-bit signals (use adder_full.vhdl)
TCL Scripting for SoC Design
• Topics
— Where you can find TCL interpreters in SoC Design tools
— Typical uses of TCL with various SoC Design tools
Where is My TCL Interpreter?
• TCL interpreter is typically embedded in your SoC
Design tool command console (GUI or command line)
HERE
HERE
HERE
HERE
HERE
HERE
Finding out More about your SoC Design Tool
• Check the version of the TCL interpreter
info tclversion
%% info tclversion
8.0
8.0
info patchlevel
%% info patchlevel
8.0.5
8.0.5
Tool
Next Steps
What this Course Covered...
• Main topics
— TCL scripting basics
— TCL data structures (strings, lists and arrays)
— File I/O, multi-process communication and simple networking
— Regular expressions
— Building TCL applications
— EDA TCL scripting
— Appendix:
• Using expect for interacting with command-line programs
— UNIX
— Windows 95/98/NT/2000
— Macintosh
• Try this:
Windows 2000
$$ wish
wish
%% button
button .b
.b -text
-text "Hello
"Hello World!"
World!" -command
-command exit
exit
.b
.b
%% pack
pack .b
.b -padx
-padx 44 -pady
-pady 66
%%
• Books
– tcl.activestate.com/resource/doc/books
There are many resources available to TCL application developers. Some of the popular
websites are listed here. Feel free to use your favourite Internet search engine to discover
more.
comp.lang.tcl is an on-line discussion forum for TCL scripting related issues. If your
company does not provide a news server access, you might want to use one of the public
news services, e.g. try Google at
http://groups.google.com/groups?group=comp.lang.tcl
TCL Scripting for SoC Design
Appendix A:
From Scripts to Applications
Aims and Topics
• Aim
– Expand the knowledge of TCL to enable building complex,
robust and portable scripting applications
• Topics
– TCL scripts versus applications
– Command-line arguments & environment variables
– Advanced procedures
– Variable scope
– Error handling
– Date & time in TCL
– Scheduling and delaying command execution
– Script profiling
– Distributing TCL scripts
TCL Script versus TCL Application
• TCL script is simply a collection of TCL commands, which
do something more or less useful
– ...or for better portability use the UNIX shell to search the $PATH
IMPORTATNT!
full path to the UNIX shell (escaped newline)
which will invoke the
#!/bin/sh
#!/bin/sh
TCL interpreter on this ## DO
DO NOT REMOVE: \\
NOT REMOVE:
script exec
exec tclsh "$0"
tclsh "$0" "$@"
"$@"
TCL script starts puts
puts "Hello World!"
"Hello World!"
here
On Windows all .tcl files are associated with a TCL/TK interpreter called wish. If
you want to use only the plain TCL interpreter, you may re-define this file
association using the Windows Explorer (File Manager) application.
Command-Line Arguments
• Very useful for customizing TCL script behavior
from a command-line
• Command-line arguments passed to TCL scripts are
stored in the following special global variables
argv TCL list of all command-line arguments
argc number of command-line arguments (= llength $argv)
argv0 script name
tclsh examples/cmd_line_args
%% tclsh examples/cmd_line_args -file
-file mp3.vhdl
mp3.vhdl -dir
-dir synth_run.12
synth_run.12
argv
argv == -file
-file mp3.vhdl
mp3.vhdl -dir
-dir synth_run.12
synth_run.12
argc =
argc = 44
argv0
argv0 == examples/cmd_line_args
examples/cmd_line_args
%%
Dealing with Platform-Specific Code
• Use the global tcl_platform array to obtain information
about the host platform
file: examples/platform_details.tcl
proc platform_details
proc platform_details {}
{} {{
global tcl_platform
global tcl_platform
puts "Machine:\t $tcl_platform(machine)"
puts "Machine:\t $tcl_platform(machine)"
puts "Platform:\t $tcl_platform(platform)"
puts "Platform:\t $tcl_platform(platform)"
puts "OS:\t\t $tcl_platform(os)
puts "OS:\t\t $tcl_platform(os) $tcl_platform(osVersion)"
$tcl_platform(osVersion)"
puts
puts "Byte order:\t $tcl_platform(byteOrder)"
"Byte order:\t $tcl_platform(byteOrder)"
}}
file: examples/edit.tcl
• Typical proc edit
proc edit {filename}
{filename} {{
global
global tcl_platform
example tcl_platform
switch $tcl_platform(platform)
switch $tcl_platform(platform) {{
windows
windows {exec
{exec notepad.exe
notepad.exe $filename
$filename &}
&}
unix
unix - linux {exec nedit $filename &}
- linux {exec nedit $filename &}
}}
}}
Accessing Environment Variables
• Use global env array to access system environment variables
set env(PATH)
%% set env(PATH)
/usr/bin:/bin/:/usr/local/bin
/usr/bin:/bin/:/usr/local/bin
set env(LM_LICENSE_FILE)
%% set env(LM_LICENSE_FILE)
/nfs/cad/mentor/licenses/license.dat
/nfs/cad/mentor/licenses/license.dat
%% info
info exists
exists env(EDITOR)
env(EDITOR) check for existence of an environment variable
00
%% set
set env(EDITOR)
env(EDITOR) "nedit"
"nedit" modify the value of an environment variable
nedit
nedit
proc print_log
proc {{fid stdout}
print_log {{fid {prefix LOG:}}
stdout} {prefix LOG:}} {{
global log
global log
foreach
foreach line
line $log
$log {{
puts
puts $fid
$fid "$prefix
"$prefix $line"
$line"
}}
}}
proc print_log_args
proc print_log_args {fid{fid args}
args} {{
global
global log
log
set
set prefix
prefix "LOG:";
"LOG:"; set
set header
header "";
""; default option values
foreach
foreach {option value} $args {{
{option value} $args parsing command options stored in the args list
switch -- $option
switch -- $option { {
-prefix
-prefix {set
{set prefix
prefix $value}
$value}
-header
-header {set
{set header
header $value}
$value}
default
default {puts
{puts "ERROR:
"ERROR: Unknown
Unknown option
option \"$option\".";
\"$option\"."; return;}
return;}
}}
}}
if
if {$header
{$header !=!= ""}
""} {puts
{puts $fid
$fid $header}
$header}
foreach
foreach line
line $log
$log {puts
{puts $fid
$fid "$prefix
"$prefix $line"}
$line"}
}}
Variable Number of Arguments (2)
• Using print_log with variable arguments
%% print_log_args
print_log_args stdout
stdout
LOG:
LOG: ...
... args (2 elements)
...
...
%% print_log_args
print_log_args stdout
stdout -prefix
-prefix "PLACE
"PLACE && ROUTE:"
ROUTE:"
PLACE
PLACE && ROUTE:
ROUTE: ...
... args (4 elements)
...
...
%% print_log_args
print_log_args stdout
stdout -prefix
-prefix "PLACE
"PLACE && ROUTE:"
ROUTE:" -header
-header "Design
"Design P&R
P&R Log"
Log"
Design
Design P&R
P&R Log
Log
PLACE
PLACE && ROUTE:
ROUTE: ...
...
... args (1 element)
...
%% print_log_args
print_log_args stdout
stdout -bad_option
-bad_option
Unknown
Unknown option
option "-bad_option"
"-bad_option"
Variable Scope
• global command provides access to variables at global
level only
• upvar command allows accessing variables at ANY level
– typically used for passing variables by reference
file: examples/print_log_upvar.tcl
proc print_log_upvar
proc print_log_upvar {fid
{fid log_var
log_var args}
args} {{
upvar
upvar 11 $log_var
$log_var log
log variable $log_var becomes visible via a local variable log
%% print_log_upvar
print_log_upvar stdout
stdout sim_log
sim_log
LOG:
LOG: ...
...
...
...
Generating Application Errors
• Error messages can be generated with puts
• TCL also provides a robust error reporting mechanism
using the error TCL command
errorInfo global variable which stores the stack trace
after an error occurred
errorCode global variable which holds the error code
of the last error
file: examples/print_log_error.tcl
proc print_log_error
proc print_log_error {fid log_var args}
{fid log_var args} {{
...
...
switch
switch --
-- $option
$option {{
-prefix
-prefix {set
{set prefix
prefix $value}
$value}
-header
-header {set
{set header
header $value}
$value}
default
default {error
{error "ERROR:
"ERROR: Unknown
Unknown option
option \"$option\".";}
\"$option\".";}
}}
}} terminates immediately and returns the error message.
errorInfo and errorCode variables are set appropriately
...
...
}
Handling Date and Time
• Query the current time
%% clock
clock seconds
seconds
1004945376
1004945376 time measured as seconds from fixed starting time
(usually January 1, 1970)
• Examples
%% after
after 1000
1000 sleep for 1000 milliseconds, then return
%% after
after 5000
5000 {puts
{puts "Job
"Job done."}
done."} returns immediately, but schedules execution of
after#1
after#1 a TCL script 5000 milliseconds from now
%% vwait
vwait event-loop
event-loop
Job tclsh must enter the EVENT LOOP in order to
Job done.
done. execute all pending scripts
Script Performance Profiling
• Use time command to evaluate the average execution time
over 1 or more iterations
• Typical uses
– Performance profiling
– Collecting timing statistics
• Examples
%% time
time {my_command}
{my_command} time command execution over 1 iteration (default)
180000
180000 microseconds
microseconds per
per iteration
iteration
%% time {my_command} 100
time {my_command} 100 time command execution over 100 iterations
256310
256310 microseconds
microseconds per
per iteration
iteration
TCL Application Distribution
• TCL application includes the following elements
– TCL script files
– Any other files (data, setup, etc.)
– TCL interpreter (?)
• Defining packages
— Insert package provide tool 1.0 in each TCL script to
become part of the tool package
— Run pkg_mkIndex . *.tcl in the package directory to create the
package index file (pkgIndex.tcl)
— Update auto_path global variable to include the package directory
All TCL scripts in the examples directory, which define procedures were included in
the tool TCL package.
For an example of the package index file, look in examples/pkglndex.tcl
Quiz 9
file: examples/quiz9.tcl
proc cell_count {args} {
return [llength $args]
}
Answer
TCL Scripting for SoC Design
Appendix B:
Binary Files and Strings
Aims and Topics
• Aim
— Learn about handling binary data using
TCL
• Topics
— Reading and writing binary files
— Binary strings
Reading and Writing Binary Files
• When accessing binary files, the automatic end-of-line
conversion must be switched off!
file: examples/bitstream.tcl
set
set fid
fid [open
[open "bitstream.bit"
"bitstream.bit" r]
r] change the translation
fconfigure
fconfigure $fid
$fid -translation
-translation binary
binary mode for $fid channel to
BINARY (i.e. no newline
set
set bitstream
bitstream [read
[read $fid]
$fid] conversion)
binary
binary scan $bitstream H*
scan $bitstream H* bitstream
bitstream
close
close $fid
$fid
• Use fconfigure to change properties 10 1 1 0
of an open channel 1 0 1
1 1 10
— Automatic end-of-line conversion 1 0
0
— End-of-file character 1
0
— Channel blocking and buffering
⇒ Channel properties can be changed
at ANY TIME during channel access
remember me?
%% set
set binary_data
binary_data "\x03\x04\x05"
"\x03\x04\x05"
♥♦♣
ε φχ
output will vary depending on the terminal & platform
Binary strings can be manipulated in the same way as “usual” text strings, i.e. they
can be constructed using substitution or using the append command and
compared using ==.
However, only the following string commands are guaranteed to work with binary
strings:
string index, string range, string length
It is therefore sometimes desirable to convert binary strings into normal
TCL strings.
Converting Binary Strings
• ... use the binary TCL command to convert binary
values to/from their equivalent string representation
binary command can be used to convert binary strings into a variety of text
strings.
binary format syntax:
proc
proc to_bits
to_bits {num}
{num} {{
binary scan [binary format
binary scan [binary format II $num]
$num] B*
B* bits
bits
return
return [string
[string trimleft
trimleft $bits
$bits 0]
0]
}}
trims away unnecessary leading bit conversion specifier
O’s (high-to-low order)
Appendix C:
Client-Server Applications
and Networking
Aims and Topics
• Aim
— Expand the knowledge of TCL multi-process communication to
include client-server and networking applications
• Topics
— Client-server applications
— Safe interpreters
— Simple networking
Multi-Process Communication
CLIENT SERVER
commands
HHDDLL H
Haarrddw
waarree
SSimmuulaatoorr results tteessttrrigg
external program
(can be another TCL read/write mode (bi-directional communication)
script!)
%% set
set fid [open "|
fid [open test_rig" r+]
"| test_rig" r+] IMPORTANT: set-up LINE buffering
file24 (FULL buffering is the default for files)
file24
%% fconfigure
fconfigure $fid -buffering line
$fid -buffering line
%% puts $fid "test1 100"
puts $fid "test1 100"
%% gets
gets $fid
$fid
test1:
test1: 1000
1000 H
Haarrddw
waarree
%% puts
puts $fid
$fid "test2
"test2 200"
200" tteessttrrigg
%% gets
gets $fid
$fid
test2:
test2: 400
400
%% close
close $fid
$fid
Notice that in the above example a considerable amount of TCL code is used to
parse server commands. In order to improve efficiency, it would be better to define
all server commands as TCL commands and then use TCL parsing and error
checking capabilities.
Using TCL as a Command Parser
file: examples/test_rig2.tcl
proc test1
proc test1 {data}
{data} {{
## perform Use TCL interpreter to parse
perform test1
test1 commands to improve efficiency
set
set result [expr
result [expr $data
$data ** 10]
10]
return "test1: $result"
return "test1: $result"
}}
proc test2
proc test2 {data}
{data} {{
## perform
perform test2
test2
set
set result
result [expr
[expr $data
$data ** 2]
2] catch will evaluate the
return
return "test2:
"test2: $result"
$result" TCL script in $line and
}} store its
result in result. Returns 0 on
success, 1 otherwise.
while
while {[gets
{[gets stdin
stdin line]
line] >=
>= 0}
0} {{
if
if {[catch $line result] !=
{[catch $line result] != 0}
0} {{
puts "Error: $result"
puts "Error: $result"
}} else
else {{
puts
puts $result
$result there is no need to change the
}} server's parsing code when new
commands are added
}}
C
CLLIIEEN
NTT SSEERRVVEERR
%% interp mmaainin
interp create
create -safe
-safe safe_parser
safe_parser TTcclininteerrpprreeteerr
safe_parser
safe_parser $script
%% safe_parser
safe_parser eval
eval $script
$script
...
... safe_parser
TTcclininteerrpprreeteerr
hides all “dangerous” commands
When attempting to invoke a “dangerous” TCL command (e.g. exec, file, open)
in a safe interpreter, the command is simply not recognized and the interpreter
will return an error.
It is always a good idea to examine TCL scripts you receive from your friends
and colleagues by running them in a safe TCL interpreter. You can use
check_script command from examples/check_script.tcl to do this for you.
%% source
source examples/check_script.tcl
examples/check_script.tcl
%% check_script
check_script unknown_script.tcl
unknown_script.tcl
invalid
invalid command
command name
name "file"
"file"
Safe Server Command Parser
file: examples/test_rig_safe.tcl
proc
proc test1
test1 {data}
{data} {{
... When receiving TCL commands
... from another process or machine,
}} always use SAFE interpreters
proc
proc test2
test2 {data}
{data} {{
...
...
}}
interp
interp create
create -safe
-safe safe_parser
safe_parser
safe_parser
safe_parser alias test1
alias test1 test1
test1
safe_parser alias test2 test2
safe_parser alias test2 test2
while
while {[gets
{[gets stdin
stdin line]
line] >=
>= 0}
0} {{
if {[catch {safe_parser
if {[catch {safe_parser eval
eval $line}
$line} result]
result] !=
!= 0}
0} {{
puts "Error: $result"
puts "Error: $result"
}} else
else {{
puts
puts $result
$result
}}
}}
129.14.234.2 10.140.131.21
ports
80
33
80
8111
33 8111
unique
port number
More on Networking
• Port numbers
— < 1024 are reserved
— Other ports are available, but could be used by other applications
(e.g. SoC Design license servers)
— Port numbers between 8100-9999 are usually OK
SERVER: socket
socket -server server_accept 8111
-server server_accept 8111 port numbers
CLIENT: set
set ch_id
ch_id [socket $host 8111]
[socket $host 8111]
hostname or IP address of the destination server
vwait varName
Example: A Networked Server
file: examples/test_rig_net.tcl
...
...
interp
interp create
create -safe
-safe safe_parser
safe_parser
...
...
Appendix D:
Interacting with
Command-Line Programs
Aims and Topics
• Aim
– To learn about using Expect for as a tool for communicating between
interactive command-line programs and a TCL interpreter
• Topics
– What is Expect?
– Simple communication with an interactive program
– Handling errors and loops
– Regular expressions with Expect
– Expect in SoC Design scripting
What is the Problem?
• Some useful tools exists only as interactive
command-line programs
– Limited command set (e.g. no loops or conditionals)
– Require user input
– Difficult to use for repetitive jobs
EExxppeecct
Example: FTP session
if
if {[llength
{[llength $argv]
$argv] << 1}
1} {{
puts
puts stderr
stderr "Usage:
"Usage: expect
expect any_ftp.tcl
any_ftp.tcl <hostname>"
<hostname>"
}}
set
set host
host [lindex
[lindex $argv
$argv 0]
0]
exp_spawn
exp_spawn ftp
ftp $host
$host start an ftp client, but redirect its
I/O through expect
expect
expect "Name"
"Name"
exp_send
exp_send "anonymous\r"
"anonymous\r"
use \r to simulate a raw carriage
return
expect
expect "Password:"
"Password:"
exp_send
exp_send "secret
"secret password\r"
password\r"
expect "ftp>"
expect "ftp>"
exp_send "cd pub\r"
exp_send "cd pub\r"
expect "ftp>"
expect "ftp>"
exp_interact let user interact with the ftp client
exp_interact at this point
Handling Errors
file: examples/any_ftp2.tcl
...
...
set
set host
host [lindex
[lindex $argv
$argv 0]
0]
set timeout 10
set timeout 10 controls how long expect waits for
a match (in seconds)
exp_spawn
exp_spawn ftp
ftp $host
$host
expect
expect {{
"Name"
"Name" {exp_send
{exp_send "anonymous\r"}
"anonymous\r"}
if matches this... ...then do this
"unknown host"
"unknown host" {return
{return 0}
0}
if matches this... ...then do this
timeout {return
timeout {return 0}
0}
no match ...then do this
after 10 seconds?
}
}
...
...
Example: Changing Password Remotely
expect
expect {{ $
-re $prompt {exp_send "passwd\r"} start up UNIX
-re $prompt {exp_send "passwd\r"}
#
passwd program
timeout {return 0}
timeout {return 0}
}
}
expect {
expect {
"assword:" {exp_send "$old_pass\r"} type in the old password
"assword:" {exp_send "$old_pass\r"}
timeout {return 0}
timeout {return 0}
}
}
...
...
Looping in Expect
file: examples/rpasswd.tcl
proc
proc change_remote_passwd
change_remote_passwd {machine
{machine user
user old_pass
old_pass new_pass}
new_pass} {{
...
...
set
set times
times 00
expect
expect {{
"new
"new \[Pp\]assword:"
\[Pp\]assword:" {{
glob-style search pattern
incr
incr times
times
if {$times >> 2}
if {$times 2} {{
return
return 00
}}
exp_send
exp_send "$new_pass\r"
"$new_pass\r" type in new password TWICE
exp_continue
exp_continue repeat the pattern search
}}
"tokens
"tokens updated
updated successfully\r\n"
successfully\r\n" {return
{return 1}
1} success!
timeout {return 0}
timeout {return 0}
}}
}}
Expect in SoC Design Scripting
• Many SoC Design tools and utilities are command-line
driven
– HDL simulation
– HDL synthesis
– Placement & routing
– Generation & customization of IP cores
– File format conversion, back-annotation, etc.
– Programs for driving test beds, prototyping boards, etc.
• Stage 1
– Choose an FTP server on your local network to which you have access
(localhost will do) and:
• Create directories ~/incoming and ~/results
• Start examples/synth_server on this server
– Test the operation of the FTP client first by hand
• Upload the design files using
ftp> put design_*
• Collect any useful messages you EXPECT
– Write an Expect TCL script for this job
LAB 6: Interaction with a Synth. Server (2)
• Stage 2
— Check in 60-second intervals whether the ~/results directory contains
design_results.log. Once present, download all design_* files from
the /results directory.
• Check for design_results.log using
ftp> get design_results.log
• Use after 60000 to delay script execution for 60 seconds
— After the files were received, start-up an editor with received
design_results.log
— Send user an e-mail message that the job was completed
Index
Note: the course is structured such that information on a particular construct is usually
spread over several consecutive pages. Where this occurs, only the first page of the set is
listed in this index
F J
fconfigure, 7-l4, 7-2O, l2-3, l3-3 join, 6 - ll
file
binary, l2-3 L
command, 7-3 lappend, 6-7
descriptor, 7-4 lindex, 6-4
id, 7-4 linsert, 6-9
pointer, 7-7 list, 6-3, 6-6
portability, 7-l2 nested, 6-5
read, 7-8, 7-lO reversal, 6-lO
translation, l2-3 summary, 6-l6
write, 7-6 versus array, 6-23
fileevent, l3-lO
llength, 6-4 read, 7-lO
logical real numbers, 3-4
operators, 3-5 redirection, 7-l8
lrange, 6-4 regexp, 8-6, 8-l7
lreplace, 6-9 indices, 8-l2
lsearch, 6-l2, 6-l3 lsearch, 6-l2, 6-l3
lsort, 6-l4, 6-l5 nocase, 8-6
switch, 4-8
M regsub, 8-l5, 8-l7
regular expression, 8-3
mathematical
sub-expression, 8-lO
functions, 3-7
regular expressions
operators, 3-3, 3-5
expect, l4-9
N require
package, ll- l 7
networking, l3-8 resources, lO-5
newline, 2-l4, 7-l2 result, 7-5
nonewline, 7-6
S
O
safe interpreter, l3-6
open, 7-4, 7-l9, 7-2O,l3-3 scan
operators, 3-5 clock, ll- l 3
bit-wise, 3-5 string, 5 - ll
comparison, 3-5 script, l-8, l-9
logical, 3-5 scripts, ll- 3
mathematical, 3-3 seconds, l l - l 3
Seek, 7-7
P set, 2-7, 5-4
package, ll- l 7 shift
pid, 7-l9 operators, 3-5
pipe, 7-l8 socket, l3-lO
pipe |, 7-l9 split, 6 - ll
precision, 3-9 stderr, 7-6
procedure, ll- 8 stdin, 7-6
arguments, ll-9 , ll- lO stdout, 7-6
procedures, 3-lO string, 5-3
process, 7-l9 binary, l2-4
communication, 7-2O, l3-3 formatting, 5-lO
provide scanning, 5 - ll
package, ll- l 7 string compare, 5-5, 5-9
puts, 2-5 string first, 5-l2
write to file, 7-6 string index, 5-l2
pwd, 3-l2 string last, 5-l2
string length, 5-l2
R string match, 5-6, 5-9
string range, 5-l2
random numbers, 3-8
string tolower, 5-8 U
string toupper, 5-8
unset, 2-7
string trim, 5-8
upvar, l l - l l
substitution, 2-9, 2-lO, 2-l2, 2-l7
backslash, 2-l3 V
command, 2-l6
variable, 2 - ll variable, 2-7
switch, 4-9 environmental, ll- 7
switch, 4-3, 4-7, 4-l5 global, 3-ll, l l - l l
multiple pattern match, 4-8 name, 2-8
options, 4-8 substitution, 2 - ll
variable substitution, 4-9 switch, 4-9
upvar, l l - l l
T value, 2-8
vwait, ll- l4 , l3-lO
tcl_platform, ll- 6
tcl_precision, 3-9 W
tcp/ip, l3-8
time, l l - l 5 while, 4-3, 4-l3, 4-l5
TK, lO-4
TCL Scripting for SoC Design
These lab exercises are designed to make you more familiar with TCL scripting
by using it in some typical SoC Design scripting situations. They are organixed
in a way that takes you step by step through what to do first, and then let you
alter the code to achieve the desired functionality.
Gertain conventions are followed in the exercises, that are worth mentioning
before you start.
Icoms
Each exercise starts on a new page and is divided into separate clear sections
using icons:
The labs are not in any specific sequence. Choose a specific lab according to
your requirements. If time permits, you are welcomed to experiment with any
of the other labs presented in this lab book.
The labs will involve, understanding of the supplied code and the addition of
new functionalities to the existing code. The data structure as well as the
subprograms’ functionality will be explained inside the ‘background info’ and
‘recommendation’ sections of each individual lab.
Lab Summary
Lab 1 : 5emeric TCL, synthesis report file parsimg - an example of the use
of TCL to parse a simple report file and log the error, warning and note
messages.
Goals
The goals of the lab exercise are to familiarixe yourself with a typical example
file parsing and information gathering. This example uses a Synplify ‘.srr’ file
however this example can be extended to any synthesis tool with a limited
amount of alterations.
Scenario
Commonly, SoC Design tools generate lengthy ASCII report files summarixing
their activity. Although the created reports are very thorough, the amount of
information available is often overwhelming for the human eye. As a result, the
user at times overlooks important messages.
The proposed lab example consists in creating a procedure that will be used to
extract specific information from a report file and display them on the screen.
message_type
standard output
get_message
file_name
Data types:
- message_type : (string) notes, warnings, errors
- file_name : (string) filtercore.srr
- standard output : (string)
Action
Workstation Users:
<install_path>/tclscript/labs/generictcl
PC Users:
<install_path>\tclscript\labs\generictcl
Your trainer will tell you the location of the lab files installation
<install_path>
❏We will work on the file warnings_errors.tcl. Take a look at the file's
contents using a text editor. Check with your instructor to see which text
editors are available, or use your favorite editor.
❏Add to the ‘get_message’ procedure a routine that will prevent the same
message to be printed more than once.
Lab 2 – Generic TCL, test karmess builder
Goals
The goal of this exercise is to become familiar with how to create complex
parsing patterns for language processing. This example uses a VHDL design as
a source. Once the principles of language processing are understood, the same
techniques can be used for a variety of other languages such as Verilog, EDIF,
and HTML.
Scenario
The proposed lab example consists in improving an existing script to extend its
semantics coverage and the creation of a procedure used to find the ports of a
given design. The general structure of the script is as follows:
(ports)
findPorts
(line)
(entity)
status vhdlDesign
createTb
(entity)
(line)
(ports)
(line)
findEntity buildTestBench
filtercore.vhd
Procedure call :
Data transfer :
t_filtercore.vhd
The ‘createTb’ procedure is the top-level procedure. It implements a state
machine that directs the text line ($line) read from the input file to ether the
procedure ‘findEntity’ or the procedure ‘findPorts’ according to the state, the
state machine is in. The variable ‘status’ is the state variable. The values held
in the variable ‘status’ can be : ‘entity’ ‘ports’ ‘finish’.
The procedure ‘findEntity’, searches the ‘line’ variable for the entity name of the
design. Once the name has been found, it is stored in the variable
‘vhdlDesign(entity)’.
The procedure ‘findPorts’ searches the line variable for ports patterns. Once
ports have been identified, the procedure append the variable list
‘vhdlDesign(ports)’ with the following information: name, direction and type of
the port . For more information, see the ‘Data structure’ topic in the
‘Recommendations’ section.
The procedure ‘buildTestBench’ simply creates the output file from the
information gathered inside the ‘vhdlDesign’ variable. You are welcomed to look
at this procedure although, you will not be asked to do any work on it.
Recommemdatioms
Data structures:
The main data structure used in this script is called: ‘vhdlDesign’. This variable
is used to hold the name of the entity declared in the original design file
(filtercore.vhd) as well as the port details. The following diagram represents
how the design information is stored inside the vhdlDesign variable.
# Variable declaration
global vhdlDesign
set vhdlDesign(entity) {}
set vhdlDesign(ports) {}
# Variable assignment
set vhdlDesign(entity) “decoder”
lappend vhdlDesign(ports) “a in integer”
lappend vhdlDesign(ports) “b out bit”
vhdlDesign
(entity) decoder
entity decoder is
port (a : in integer;
(ports) a in integer
b : out bit);
end decoder;
b out bit
VHDL Tokems:
Tokens are commonly used in scanners/parsers to facilitate the building of
complex regular expressions. Here are the tokens defined for this TCL script:
set separator {\s}
set nameIdentifier {[a-z][_a-z0-9]*}
set typeIdentifier {[a-z][a-z0-9_ ]*(\([a-z0-9_ ]*\))*}
set portMode "in|out|inout|buffer"
VHDL 5rammar:
The grammar part of a scanner/parser is used to define a valid set of token
sequences. This is used in regular expressions to extract specific information
from code. Here are the grammar rules defined in the TCL script.
set portPattern
"($nameIdentifier)$separator*:$separator*
($portMode)+$separator+($typeIdentifier)"
Other patterns used in this script are used to detect entity declarations such as:
set entityHead
"^$separator*entity$separator+
($nameIdentifier)$separator+is"
entityHead
entityEnd
Actiom
Workstation Users:
<install_path>/tclscript/labs/generictcl
PC Users:
<install_path>\tclscript\labs\generictcl
Your trainer will tell you the location of the lab files installation
<install_path>
❏We will work on the file testbench.tcl. Take a look at the file's
contents using a text editor. Check with your instructor to see which text
editors are available, or use your favorite editor.
❏Familiarixe yourself with the script. Before modifying the script, you can
execute it to see what it does (look at the generated ‘t_filtercore.vhd’).
❏The first part of this lab consists in adding a procedure called ‘findPorts’
that will be used to store the ports information inside the variable
‘vhdlDesign’. The following diagram represents the data flow for that
function:
(line) (ports)
findPorts vhdlDesign
status
The ‘line’ variable is passed from the procedure ‘createTb’. Its value is a
text line (ASCII) extracted from input file currently processed
(filtercore.vhd).
In this procedure you will have to process the ‘line’ to define if it is a port
declaration or not. If so, you will have to store the ports information inside
the variable ‘vhdlDesign’. The processing information has been described
in the recommendation section.
...
ls : IN STD_LOGIC; portPattern
reset : IN STD_LOGIC;
);
entityEnd
END filtercore;
By setting the value of ‘status’ to ‘finish’, this will force the state machine
implemented inside the procedure ‘createTb’ to stop.
❏One you have made the modifications, run the script and observe the
differences in the resut file ‘t_filtercore.vhd’.
❏Although the current ‘entityEnd’ pattern works with the current example,
this grammar can only match two type of entity ending:
The VHDL language reference manual defines that an entity ending can
also be of the following form:
❏ Modify the ‘entityEnd’ pattern to include those two extra kinds of endings.
❏Modify the ‘filtercore’ entity ending inside the ‘filtercore.vhd’ file to be:
‘END ENTITY;’ or END ENTITY filtercore;’ and validate your new
script.
... ...
ls : IN STD_LOGIC; ls : IN STD_LOGIC;
reset : IN STD_LOGIC; reset : IN STD_LOGIC;
); );
END filtercore; END ENTITY filtercore;
Lab 3 – ModelSim Dymamic Power Estimatiom
Goals
The goal of this exercise is to become familiar with some of the features of
ModelSim’s API. This example is based on a VHDL simulation; this script will
be used to log signal activity during a simulation and report the results of its
analysis.
Scenario
The proposed lab example consists in creating a procedure that will be used to
monitor signals activity at a given hierarchical level of the design during a
simulation. Once the simulation is over the script will display the results using
a graph.
monitorSignals
(signal)
signalList signalType
(hierarchy)
find describe
when
expendedList
(maxValue)
(mostLeast)
reportSignals
result.txt graph.tcl
Procedure call :
Data transfer :
API Procedure :
API
Recommemdatioms
ModelSim’s API:
ModelSim features a large amount of TCL API commands described in
detail in the simulator’s documentation. This script will only feature a few
of those to give you a feel for what you can achieve with scripting.
Enum: ('U','X','0','1','Z','W','L','H','-')
Array(15 downto 0) of
Enum: ('U','X','0','1','Z','W','L','H','-')
Data types:
- signalList : (list of strings) signal names.
- signalType : (string) type information of a signal (see previous
section ‘describe’ command).
- expendedList : (array) Signal names are used as indexes whilst
the toggle amount is the value.
- resultList: (list of ‘toggle value/ signal’ name pair) a list version of
the values contained in the variable ‘expendedList’.
- sortedList : numerically sorted version of the variable ‘resultList’.
ExpendedList()
(a) 0
signal a : integer := 0;
signal b : std_logic := ‘0'; (b) 0
signal c : Boolean := false;
(c) 0
counter
ExpendedList()
(c) 0
Actiom
Workstation Users:
<install_path>/tclscript/labs/modelsimtcl
PC Users:
<install_path>\tclscript\labs\modelsimtcl
Your trainer will tell you the location of the lab files installation
<install_path>
❏We will work on the file signalcount.tcl. Take a look at the file's
contents using a text editor. Check with your instructor to see which text
editors are available, or use your favorite editor.
Adding the ‘momitorSigmals’ procedure
❏ Add to the get_message procedure a routine that will prevent the same
message to be printed more than once.
Optiomal
❏If you have some time left, try to improve the ‘monitorSignals’ procedure by
checking if a signal (inside the ‘signalList’ variable) is of an array type; if
so, expend the signal into individual values so that you can create
individual counters for each of the bits of a vector. The following diagram
explains the procedure.
signalList
Array(3 downto 0) of
dataio Enum:
('U','X','0','1','Z','W','L','H','-')
clk
ExpendedList()
(sig_a) 0
(dataio(0)) 0
(dataio(1)) 0
Added
(dataio(2)) 0
(dataio(3)) 0
(dataio) 0
(clk) 0
Lab 3 – Leomardo Multi-pass Synthesis
5oals
The goal of this exercise is to become familiar with some of the features of
Leonardo’s API. This example is based on a VHDL synthesis; this script will be
used to perform a multi-pass synthesis and report the results of its analysis.
Scemario
The proposed lab example consists in creating a procedure that will be used to
initiate synthesis runs over a range of constraint variations. This type of script
would typically run overnight since they are inherently long. Once the multi-
pass synthesis is complete, the script will display the results using a graph. The
following diagram illustrates the script’s architecture:
vhdlFileList
maxFreq
read
args compile
load_library
config Leonardo’s
variables pre_optimixe
optimixe
optimixe_timing
newRun
report_delay report_area
synResult
Procedure call :
Data transfer :
API Procedure :
API
The ‘compile’ procedure is the top-level procedure. This procedure reads all the
files located inside the current directory and initiate successive synthesis runs
on each of those files. When calling the procedure, the user has to specify a
required frequency value in MHx. Optionally, if the VHDL files require
packages to be analyxed prior to synthesis, the user will specify the required
files as part of the procedure’s arguments.
Recommemdatioms
This is the list of Leonardo Spectrum’s global variables used in this lab:
- part : This variable indicates the part name in the chosen target
family.
o ‘set part EPF10K30RC208' will set the part to the
specified value.
If you require more information about specific variables, you can type the
command ‘help –v’ inside the Leonardo Spectrum’s console window.
Data types:
- config : (array) Constraint names are used as indexes.
config()
nano seconds
(register2register) 100
(input2register) 100
(output2register) 100
(resource_sharing)
TRUE
(encoding) Binary
Actiom
Workstation Users:
<install_path>/tclscript/labs/leonardotcl
PC Users:
<install_path>\tclscript\labs\leonardotcl
Your trainer will tell you the location of the lab files installation
<install_path>
❏We will work on the file complile.tcl. Take a look at the file's contents using a
text editor. Check with your instructor to see which text editors are available, or
use your favorite editor.
❏ Complete the procedures using the comments found inside the script file.
❏Test the resulting script on the vhdl files found in the lab directory. This can be
achieved by typing the following commands in Leonardo Spectrum.
cd <install_path>/tclscript/labs/leonardotcl
source compile.tcl
compile 40 mask_types.vhd
Lab 4 – Symplify Multi-pass Synthesis
5oals
The goal of this exercise is to become familiar with some of the features of
Synplify’s API. This example is based on a VHDL synthesis; this script will be
used to perform a multi-pass synthesis and report the results of its analysis.
Scemario
The proposed lab example consists in creating a procedure that will be used to
initiate synthesis runs over a range of constraint variations. This type of script
would typically run overnight since they are inherently long. Once the multi-
pass synthesis is complete, the script will display the results using a graph. The
following diagram illustrates the script’s architecture:
vhdlFileList
maxFreq
add_file
args compile
set_option
newRun config
project
<name>.srr result.txt
Procedure call :
Data transfer :
API Procedure :
API
The ‘compile’ procedure is the top-level procedure. This procedure reads all the
files located inside the current directory and initiate successive synthesis runs
on each of those files. When calling the procedure, the user has to specify a
required frequency value in MHx. Optionally, if the VHDL files require
packages to be analyxed prior to synthesis, the user will specify the required
files as part of the procedure’s arguments.
Recommemdatioms
Symplify’s API:
Synplify features a large amount of TCL API commands described in
detail in the synthesis tool’s documentation. This script will only feature a
few of those to give you a feel for what you can achieve with scripting.
Data types:
- config : (array) Constraint names are used as indexes.
config()
sequential
(default_enum_encoding)
0
(symbolic_fsm_compiler)
0
(resource_sharing)
0
(frequency)
Actiom
Workstation Users:
<install_path>/tclscript/labs/Synplifytcl
PC Users:
<install_path>\tclscript\labs\Synplifytcl
Your trainer will tell you the location of the lab files installation
<install_path>
❏We will work on the file complile.tcl. Take a look at the file's contents
using a text editor. Check with your instructor to see which text editors
are available, or use your favorite editor.
Completing the procedures
❏ Complete the procedures using the comments found inside the script file.
❏ Test the resulting script on the vhdl files found in the lab directory. This
can be achieved by performing the following steps.