TCL : Tool command language Linux OS : TCL packages are installed Windows OS : tclsh packages has to installed : We can use Cygwin along with tclsh packages Interpreter path : which tclsh /usr/bin/tclsh Tcl/perl/phython dont need compilation , It has direct execution To use in files first line of file type #!/usr/bin/tclsh Basic : set b “This is “tool” command language class $a” puts $b set a {This is "tool" command language class $a} puts $a Topic Covered • Special variable • Proc • File operations • String • Lists • Decision making statements • Loops • arrays • Operators • regexpressions • Dictionary • Packages Special Variables argc, argv , argv0 argc – gives the argument count argv – printing argument values argv0 – prints name of the script Ex 1 : Type puts $argc, Puts $argv, Puts $argv0 Ex 1: output ./sample.txt -x1 10 -x2 20 -y1 3 -y2 4 8 -x1 10 -x2 20 -y1 3 -y2 4 ./sample.txt Ex 2 : #!/usr/bin/tclsh puts $argc puts $argv puts $argv0 if {$argc != 8} { puts "Error : Not passed enough arguments" puts "arguments passed $argc and expected is 8" exit } set fields [split $argv " "] lassign $fields a b c d e f g h puts $a puts $b puts $c puts $d puts $e puts $f puts $g puts $h if {$a == "-x1"} { set x1 $b} if {$a == "-x2"} { set x2 $b} if {$a == "-y1"} { set y1 $b} if {$a == "-y2"} { set y2 $b} if {$c == "-x1"} { set x1 $d} if {$c == "-x2"} { set x2 $d} if {$c == "-y1"} { set y1 $d} if {$c == "-y2"} { set y2 $d} if {$e == "-x1"} { set x1 $f} if {$e == "-x2"} { set x2 $f} if {$e == "-y1"} { set y1 $f} if {$e == "-y2"} { set y2 $f} if {$g == "-x1"} { set x1 $h} if {$g == "-x2"} { set x2 $h} if {$g == "-y1"} { set y1 $h} if {$g == "-y2"} { set y2 $h} set area [expr ($x2 - $x1) * ($y2 - $y1)] puts $area Ex2 : Output1 ./sample.tcl -y2 20 -x2 20 -y1 3 -x1 10 8 -y2 20 -x2 20 -y1 3 -x1 10 ./sample.tcl -y2 20 -x2 20 -y1 3 -x1 10 170 Ex2 : Output2 ./sample.tcl -y2 20 -x2 20 -y1 3 6 -y2 20 -x2 20 -y1 3 ./sample.tcl Error : Not passed enough arguments arguments passed 6 and expected is 8 expr operator set a 10; set b 20 set c [expr $a + $b] set d [expr $a - $b] set e [expr $a * $b] puts " The results are $c $d $e " The results are 30 -10 200 Procedure (Proc) Ex 1: proc add {a b} { expr $a + $b } puts [add 10 30] # calling Proc Ex 2: set Name "SRAM256K" proc macroarea {x1 x2 y1 y2} { expr {($x2-$x1) * ($y2 -$y1)} } set area [macroarea 10 20 10 30] puts "Area of $Name Macro is $area" File management • Open file • Read content • Write file content • Append file content File handler While we use puts message used to display the message only on the screen File handler • Read content of file • Write content to the file • Append to the file. (Existing lines will not change only we write to the end of the file) Different IO modes • Read mode • Write mode • Append mode Examples Write co-ordinates in one file Read file Ex: To print only one line set fh_read [open "macro.txt" r] gets $fh_read line puts $line Ex: To print every line #!/usr/bin/tclsh set fh_read [open "fileop.tcl" r] while {[gets $fh_read long]>=0} { puts $long } Example : ICC2 has given the co-ordinates of macros in file We have to calculate overall area Flow : • Open text file • Read line one by one • Calculate area • Add to overall area • Print the final area Example2: #!/usr/bin/tclsh set fh_read [open "macro.txt" r] set wrifile [open "new.txt" w] set totalarea 0 while {[gets $fh_read line]>=0} { #puts $line set fields [split $line " "] lassign $fields macroname a b c d e f g h if {$a == "-x1"} { set x1 $b} if {$a == "-x2"} { set x2 $b} if {$a == "-y1"} { set y1 $b} if {$a == "-y2"} { set y2 $b} if {$c == "-x1"} { set x1 $d} if {$c == "-x2"} { set x2 $d} if {$c == "-y1"} { set y1 $d} if {$c == "-y2"} { set y2 $d} if {$e == "-x1"} { set x1 $f} if {$e == "-x2"} { set x2 $f} if {$e == "-y1"} { set y1 $f} if {$e == "-y2"} { set y2 $f} if {$g == "-x1"} { set x1 $h} if {$g == "-x2"} { set x2 $h} if {$g == "-y1"} { set y1 $h} if {$g == "-y2"} { set y2 $h} set area [expr ($x2 - $x1) * ($y2 - $y1)] puts $wrifile " area of $macroname is $area" set totalarea [expr $totalarea + $area] } puts $wrifile "toltal area is $totalarea" close $wrifile Conditional/Ternary Set a 100 set b [expr $a == 100 ? true : false] puts $b Mathematical Operation set a 2; set b 2; set c 3; set x 2; set y 3 set result [expr ($a * $x * $y) + ($b * $x) + $c] string Operations Special characters \’ to print with single code \” to print with double codes \\ to print \ back slash \? To print question mark \a alert bell \n new line \t horizontal tab \v vertical tab Ex: \” to print with double codes set b "\"hello world\"" puts $b Ex:\? To print question mark set b "What is your name \?" puts $b Ex: for new line and horizontal tab set b "What \n\tis \n\t\tyour \n\t\t\tname" puts $b #Example to vertical tab set b "What \vis \v\v\your \v\v\vname" puts $b a) Compare set a hello set b hello string compare $a $b result 0 set a abc set b hello string compare $a $b result -1 Here S1 comes before S2 alphabetically set a hello set b abc string compare $a $b S1 comes after S2 alphabetically result 1 b) string first set a “TCL: hello world I am in TCL class” set b TCL set d [string first $b $a] puts $d If string b is in a then it returns the index(char index) of first occurrence Else it returns -1 c) string last set a “TCL: hello world I am in TCL class” set b TCL set d [string last $b $a] puts $d If string b is in a then it returns the index (char index) of last occurrence d) Reverse – reverse the string set a hello hello string reverse $a set b [string reverse $a] puts $b e) String Match—If both strings(completely) are same then it returns 1 else 0. set a "TCL: hello world I am in TCL class" set d [string match $a "TCL: hello world I am in TCL class"] puts $d f) index set a tcl set b [string index $a 0] set b [string index $a 1] Returns character at index. g) length, toupper , tolower length -- gives length of a string [charecter count including spaces] toupper-- coverts all lower cases to upper cases tolower -- converts all upper cases to lower cases set a "TCL ScriPt For CLass" set d [string length $a] puts $d set e [string toupper $a] puts $e set f [string tolower $a] puts $f h) Range – Gives the characters in the index range set a “This is a new TCL class after Unix class” set sub_string [string range $a 14 39] output: TCL class after Unix class i) append -- appends the new sting after old string set a hello append a " world" puts $a g) Trim string -- Trims characters at both end default trim is white spaces Ex : to remove spaces set a " This is a new TCL class after Unix class " puts $a set sub_string [string trim $a] puts $sub_string Ex: set a "ssThis is a new TCL class after Unix class" puts $a set sub_string [string trim $a ?s?] puts $sub_string Output: ssThis is a new TCL class after Unix class This is a new TCL class after Unix cla h) Trim right – Only right side is trimmed. Default trimming is white spaces set a "ssThis is a new TCL class after Unix class" puts $a set sub_string [string trimright $a ?s?] puts $sub_string Output: ssThis is a new TCL class after Unix class ssThis is a new TCL class after Unix cla i) Left trim -- Only right side is trimmed. Default trimming is white spaces Ex: set a "ssThis is a new TCL class after Unix class" puts $a set sub_string [string trimleft $a ?s?] puts $sub_string Output: ssThis is a new TCL class after Unix class This is a new TCL class after Unix class j) String wordend – returns index after the end of a word. (word index has to be specified) string wordend string index set a "This is tool command language class" set s [string wordend $a 13] puts $s Ans : 20 k) wordstart : Gives index of beginning of a word that is located at the value passed in index string wordstart string index set a "This is tool command language class" set s [string wordstart $a 2] puts $s Ans: 0 Lists Lists are similar to arrays Lists is a collections of items Items can be string integers or real values special characters • List — Defining a list set a [list this is a class] this is a class puts $a this is a class • Split -- splits in to elements of a list based on reference charecter-- (no change in parent varilable) Set a RED_GREEN_YELLOW Set b [split $a “_”] puts $b • lappend -- appends element at last -- (changes in parent varilable) set a [list this is a class] this is a class lappend a first this is a class first • llength -- Gives length of a list set d [llength $a] puts $d • llindex -- Gives element at particular index set e [llindex $a 2] puts $e • lrange --Return one or more adjacent elements from a list specified in index range. set a "Orange blue red green black white yellow" set b [lrange $a 2 5] puts $b • lsort- arrange the terms in ascending/descending order -(no change in parent varilable) ex : set a "this is tcl class PD" this is tcl class PD set b [lsort $a] PD class is tcl this set c [lsort -decreasing $a] this tcl is class PD • lsort -dictionary -- Ignores cases while sorting set a "basic_of_CMOS tcl unix PD_Basics PD_main custom_layout synthesis STA" set b [lsort -dictionary $a] DFT puts $b • lsort -integer-- sorts based on integer #!/usr/bin/tclsh set a "1264 129 132" set b [lsort -integer $a] puts $b • lsort -real $a-- sorts based on real values • lsort -unique $a-- sorts by removig duplicate elements in the list • lset – set particular index with new value- (changes in parent varilable) ex: set a "this is tcl class in vlsi" this is tcl class in vlsi lset a 3 session this is tcl session in vlsi puts $a this is tcl session in vlsi • linsert -- inserts elements (more than one) at particular index -- (no changes in parent variable ) #!/usr/bin/tclsh set a "Orang blue red green" puts $a set b [linsert $a 3 white yellow] puts $b • lreplace -- Replaces elements in index range with new elements (No changes to parent variable) ex: set a "Orange blue red green black white yellow" puts $a set b [lreplace $a 1 3 a b c] puts $b • concat -- merges two list into one list set a "PAD1 PAD2 PAD3 PAD4 PAD5 PAD6 PAD7 PAD8" set b "PAD9 PAD10 PAD11 PAD12 PAD3 PAD14 PAD15 " set c [concat $a $b] puts $c • lassign -- assings successive elements of a list to specified variables set a "Orange blue red green black white yellow" puts $a lassign $a c0 c1 c2 c3 c4 c5 c6 puts "colour 0 is $c1" puts "colour 1 is $c2" puts "colour 2 is $c3" puts "colour 3 is $c4" puts "colour 4 is $c5" puts "colour 5 is $c6" puts "colour 6 is $c7" Ex: Perfom above example using for loop #!/usr/bin/tclsh set a "black white blue yellow greeen" set b [llength $a] for {set i 1} {$i <= $b} {incr i} { set d [lindex $a [expr $i-1]] puts "Colour $i is $d" } Ex: Create list for courses in alphabetical order and print all courses as "course 1 ...." "course 2 ...." #!/usr/bin/tclsh set a "basic_of_CMOS tcl unix PD_Basics PD_main DFT custom_layout synthesis STA" puts $a set i 1 foreach courses $a { puts " course $i at vlsigiru is $courses" set i [expr $i+1] } RESULT : course 1 at vlsigiru is basic_of_CMOS course 2 at vlsigiru is tcl course 3 at vlsigiru is unix course 4 at vlsigiru is pd course 5 at vlsigiru is dft course 6 at vlsigiru is custom_layout Ex : List using alphabetical order #!/usr/bin/tclsh set a "basic_of_CMOS tcl unix PD_Basics PD_main DFT custom_layout synthesis STA" set b [lsort -dictionary $a] set i 1 foreach courses $b { puts " course $i at vlsigiru is $courses" set i [expr $i+1] } RESULT : course 1 at vlsigiru is basic_of_CMOS course 2 at vlsigiru is custom_layout course 3 at vlsigiru is dft course 4 at vlsigiru is pd_basics course 5 at vlsigiru is pd_main course 6 at vlsigiru is sta course 7 at vlsigiru is synthesis course 8 at vlsigiru is tcl course 9 at vlsigiru is unix Ex : There are 2 lists of PADS availible . Group that in to 4 equls groups of PADS to place at four sides of Core area set a "PAD1 PAD2 PAD3 PAD4 PAD5 PAD6 PAD7 PAD8 ...." set b "PAD9 PAD10 PAD11 PAD12 PIN13 PIN14 PIN15 PIN16 ......" #!/usr/bin/tclsh set a "PAD1 PAD2 PAD3 PAD4 PAD5 PAD6 PAD7 PAD8" set b "PAD9 PAD10 PAD11 PAD12 PAD3 PAD14 PAD15 PAD16" set c [concat $a $b] puts $c set d [expr [llength $c]/4] set PG0 [lrange $c 0 $d-1] puts $PG0 set PG1 [lrange $c $d [expr (2 * $d)-1]] puts $PG1 set PG2 [lrange $c [expr (2 * $d)] [expr (3 * $d)-1]] puts $PG2 set PG3 [lrange $c [expr (3 * $d)] [expr (4 * $d)-1]] puts $PG3 Ex: In above example if we have add number of PADS Then write tcl program to create 3 equall; groups and last group with less PADCELLs #!/usr/bin/tclsh set a "PAD1 PAD2 PAD3 PAD4 PAD5 PAD6 PAD7 PAD8" set b "PAD9 PAD10 PAD11 PAD12 PAD3 PAD14 PAD15" set c [concat $a $b] puts $c set e [expr [llength $c]/4.0] set f [expr {ceil($e)}] set d [expr {int ($f)}] set PG0 [lrange $c 0 $d-1] puts $PG0 set PG0 [lrange $c 0 $d-1] puts " elements in PG0 is $PG0" set PG1 [lrange $c $d [expr (2 * $d)-1] puts "elements in PG1 is $PG1" set PG2 [lrange $c [expr (2 * $d)] [expr (3 * $d)-1]] puts "elements in PG2 is $PG2" set PG3 [lrange $c [expr (3 * $d)] [expr (4 * $d)-1]] puts "elements in PG2 is $PG2" Ex: By using loop and for elements not integer multiple of 4 set a {PAD0 PAD1 PAD2 PAD3 PAD4 PAD5 PAD6 PAD7} set b {PAD8 PAD9 PAD10 PAD11 PAD12 PAD13 PAD14 PAD15 PAD16 PAD17 PAD18 PAD19 PAD20 PAD21 PAD22} set PG {PG0 PG1 PG2 PG3} set c [concat $a $b] set d [expr [llength $c] / 4.0] set e [expr {ceil ($d)}] set f [expr {int ($e)}] puts $c puts $d puts $e puts $f set i 0 foreach group $PG { set group [lrange $c [expr $i * $f] [expr (($i+1) * $f) - 1]] puts $group incr i } LOOPS IN TCL a) For loop Syntax : for {initialization} {condition} {increment} { statement(s); } b) while loop syntax : while {conditio} { } Note: Ex : While loop #!/usr/bin/tclsh set x 1 while {$x < 5} { puts "x is $x" set x [expr {$x + 1}] } break statement : The break statement in Tcl language is used for terminating a loop. When the break statement is encountered inside a loop, the loop is immediately terminated and program control resumes at the next statement following the loop. set a 10 # while loop execution while {$a < 20 } { puts "value of a: $a" incr a if { $a > 15} { # terminate the loop using break statement break } The continue statement in Tcl language works somewhat like the break statement. Instead of forcing termination, however, continue forces the next iteration of the loop to take place, skipping any code in between. set a 10 while { $a < 20 } { if { $a == 15} { #skip the iteration incr a continue } puts "value of a: $a" incr a } To add all the numbers from 1 to x and to skip 6 set x 10 set i 1 set sum 0 while {$i <= $x} { if {$i == 6} {continue} set sum [expr $i + $sum] incr i } Conditional Statements Syntax : if {condition 1} { # Executes when the condition1 is true } elseif {condition 2} { # Executes when the condition2 is true } elseif {condition 3} { # Executes when the condition3 is true } else { # executes when the none of the above condition is true } Ex : set a 100 #check the boolean condition if { $a == 10 } { # if condition is true then print the following puts "Value of a is 10" } elseif { $a == 20 } { # if else if condition is true puts "Value of a is 20" } elseif { $a == 30 } { # if else if condition is true puts "Value of a is 30" } else { # if none of the conditions is true puts "None of the values is matching" } Ex : To get the numbers range given in arguments divisible by 3 and 7 #!/usr/bin/tclsh puts $argv if {$argc != 4} { "not enough arguments passed" exit } lassign $argv a b c d if {$a == "-lr"} {set e $b} if {$a == "-ur"} {set f $b} if {$c == "-lr"} {set e $d} only if {$c == "-ur"} {set f $d} set flag 0 for {set j $e} {$j <= $f} {incr j} { if {(($j % 3) == 0) && (($j % 7) == 0) } { puts " The number is $j" set flag 1 } } if {$flag == 0} { puts "There is no number in range divisible by 3 and 7" } Ex: To print prime numbers till given number in argument to the file and if any number is in 60s then stop printing #!/usr/bin/tclsh for {set j 0} {$j <= 100} {incr j} { if { (($j % 3) == 0) && (($j % 7) == 0 ) } { if { $j/10 == 6 } { break } puts "the number divisible by 3 and 7 is $j" } } Ex : To get the prime numbers mentioned in argument -pnum 100 i) 1st for loop -- 2 to 100--i 2 3 4 5 6 .... 50. .72..63..64 ii) 2nd for loop --2 to i/2-- j 2 3 4 5 6. 25 iii) i % j == 0 then it is a prime number iv) i % j != 0 then it a prime number #!/usr/bin/tclsh puts $argv if {$argc != 2} { "not enough arguments passed" exit } lassign $argv a b if {$a == "-pnumb"} {set e $b} for {set i 2} {$i <= $e} {incr i} { set flag 1 for {set j 2} {$j <= $i/2} {incr j} { if { ($i % $j) == 0 } { set flag 0 } } if {$flag == 1} { puts "The prime number is $i" } } Prime number example Using only whie loop #!/usr/bin/tclsh puts $argv if {$argc != 2} { "not enough arguments passed" exit } lassign $argv a b if {$a == "-pnumb"} {set e $b} set i 2 while {$i <= $e} { set flag 1 set j 2 while {$j <= $i/2} { if { ($i % $j) == 0 } { set flag 0 } incr j } if {$flag == 1} { puts "The prime number is $i" } incr i } Arrays : A Tcl array is a collection of variables. Each variable may hold any value and the array is indexed by arbitrary values. The key-value pairs are unordered. A Tcl array is an associative array. Noramal array Creating a array set color(0) {orange purple set color(1) {red blue green} set color(2) {pink white} puts $color(1) Printing a array puts "$color(1) ---- prints red blue green Ex: To print all values of array #!/usr/bin/tclsh set student(1) {10 20 40 50} set student(2) {10 50 40 60} set student(3) {30 20 60 70} set student(4) {50 80 70 20} set student(5) {60 90 90 45} set student(6) {70 20 50 55} set student(7) {10 50 30 65} set student(8) {80 60 20 30} for {set i 1} {$i <= [array size student]} {incr i} { puts "The marks of student($i) is $student($i)" } Associative Array In Tcl, you integers set can use anything color(myHouse) as array index, not just purple set color(myCar) red set color(myChair) red puts $color(myhouse) Size of array array size ARRAY-NAME array size color --- Here it is 3 To get indices of array array names array_name The returns a list of the indices of an array: Ex: #!/usr/bin/tclsh set student(1) {10 20 40} set student(s1) {10 50 40} set student(s12) {30 20 60} set student(s13) {50 80 70} set student(slow) {60 90 90} set student(fast) {70 20 50} set student(modearte) {10 50 30} set s [array names student] puts $s Output : s1 modearte slow 1 fast s12 s13 Ex: To get particular argument like marks of particular student ./filename.txt -stu 4 -sub 2 -- prit sub 2 marks of student 4 #!/usr/bin/tclsh if {$argc != 4} {Puts "argument count error"} lassign $argv a b c d if {$a == "-stu"} {set e $b} if {$c == "-sub"} {set f $d} if {$e > 8} { puts "no student with that number" exit } if {$f > 4} { puts "no subject with that number" exit } set student(1) {10 20 40 50} set student(2) {10 50 40 60} set student(3) {30 20 60 70} set student(4) {50 80 70 20} set student(5) {60 90 90 45} set student(6) {70 20 50 55} set student(7) {10 50 30 65} set student(8) {80 60 20 30} foreach a [array names student] { for if {$a == $e} { set g $student($a) set h [lindex $g $f-1] puts "The marks is $h } } input: ./filename.txt -stu 4 -sub 2 Ans : 80 Ex: Calculating number of lines in a file #!/usr/bin/tclsh set fh_read [open "dummy_file.txt" r] set i 0 while {[gets $fh_read long]>=0} { puts $long incr i } puts "The no of lines in file is $i" Ex: Calculating number of total number of words in a file #!/usr/bin/tclsh set fh_read [open "dummy_file.txt" r] set i 0 set b 0 while {[gets $fh_read long]>=0} { puts $long set lword_cnt [llength $long] incr i # puts "Number of words in line $i is $lword_cnt" set b [expr $b + $lword_cnt] } puts "The no of lines in file is $i" puts "The no words in file is $b" Assignment: Assigment 1: Get the number of from a particular line specified in argument like -line 4: Get no of words in line 4 If line number is more than the number of lines in file display error meassge Assigment 2 " Get of no charecter including spaces in entire file " #!/usr/bin/tclsh set fh_read [open "dummy_file.txt" r] set i 0 set word_count 0 set char_count 0 while {[gets $fh_read long]>=0} { foreach word [split $long " "] { incr word_count # puts $word foreach char [split $word ""] { puts $char incr char_count } } } puts "total word count is $word_count" puts " total char count is $char_count" Assignment 3 : The program for array to get studen marks in proc proc student_marks {e f} { if {$e > 8} { puts "no student with that number" exit } if {$f > 4} { puts "no subject with that number" exit } set student(1) {10 20 40 50} set student(2) {10 50 40 60} set student(3) {30 20 60 70} set student(4) {50 80 70 20} set student(5) {60 90 90 45} set student(6) {70 20 50 55} set student(7) {10 50 30 65} set student(8) {80 60 20 30} foreach a [array names student] { if {$a == $e} { set g $student($a) set h [lindex $g $f-1] puts $h } } } set j [student_marks 9 2] puts $j Assignment 4: Write a proc to find factorial of a numbers Assignment 5 : Write a proc to find average of n numbers Operators: Boolean Operators Relational operators Bitwise operators Arithmetic Operators Ternary Operator Regexpression The "regexp" command is used to match a regular expression in Tcl. A regular expression is a sequence of characters that contains a search pattern. It consists of multiple rules and the following table explains these rules and corresponding use. Ex 1: #!/usr/bin/tclsh set c "This is a TCL class in morning" if {[regexp -nocase {^this.*morning} $c]} { puts "search match" } Ex 2 : #!/usr/bin/tclsh set c "aThis is a TCL class in morning" if {[regexp -nocase {^[b-z]this} $c]} { puts "search match" } else { puts "no match" } EX 3: VHDL entity Example #!/usr/bin/tclsh set c " entity add is" if { [regexp -nocase {^ +entity +([a-z][a-z0-9_]*) +(is)} $c line 1 2]} { puts "correct syntax continue" puts $line puts $1 puts $2 } Ex 4: To extract the entity name in entity declaration from a VHDL file Note: Create one VHDL file with many enity declarations and with different entity names #!/usr/bin/tclsh set fh_read [open "dummy_file.txt" r] set i 0 while {[gets $fh_read long]>=0} { if {[regexp -nocase { *entity +([a-z][a-z0-9_]*) +is} $long a b]} { incr i puts "The entity name is $b" #puts "correct syntax" } } puts "no of entity lines in file is $i" Ex 5 : To extract the ports and direction #!/usr/bin/tclsh set c " sum_out : out std_logic" if { [regexp -nocase {^ +([a-z][a-z0-9_]*) *: *(in|out) +std_logic} $c line 1 2 3]} { puts "correct syntax continue" puts $line puts $1 puts $2 puts $3 } #!/usr/bin/tclsh set c " sum_out : out std_logic_vector(50 downto 4)" if { [regexp -nocase {^ +([a-z][a-z0-9_]*) *: *(in|out) +std_logic_vector *\( *([0-9]*) +downto +([0-9]*)\)} $c line 1 2 lsb msb]} { puts "correct syntax continue" puts $line puts $1 puts $2 puts $lsb puts $msb }