Thursday, November 15, 2018

TCL Practice Task 2 (Scripting Language)

TCL is very important from automation point of view in VLSI Industry but students are lacking bigtime. Even if they learn, they face problem to understand the uses of TCL in VLSI Industry. In these series of articles, I am listing down few of the small projects or say programs or say exercise which can help anyone to understand the use-model of TCL in Industry. As a fresher, if you try at least once, it will boost your confidence. If you are able to automate below few task, more then 50% of work (based on TCL) can be done easily.
This is second part. If you have missed first part, please visit it (TCL Practice Task 1). Because to understand this Task, you should have Task 1 program handy. :)

If you have completed previous task (task 1), I am sure now you are good in file handling.

Task 2:- Mapping Two Files

Step 1: Create 2 Input files ("file_input1.txt" and "file_input2.txt")
Content of "file_input1.txt" is same as in the previous Task. So, you can copy file from last program. Snapshot of both the files are present below.

Input File: “file_input1.txt”

    Name        Delay    Trans    Load
    ---------------------------------------------
    AND1_2X      1.50ns    0.1    1.25ff
    AND1_3X      1.75ns    0.2    1.98ff
    AND2_3X      2.37ns    0.3    2.27ff
    AND2_4X      1.82ns    0.5    2.54ff
    NAND1_2X    2.14ns    0.2    1.69ff
    NAND2_3X    2.48ns    0.3    2.11ff

Input File: “file_input2.txt”

    CELL_1:    AND1_2X
    CELL_2:    AND2_3X
    CELL_3:    AND2_4X
    CELL_4:    NAND2_3X

Step 2: Reuse TCL Program of Task 1 and convert into procedure or procedures.

Step 3: Write a TCL program, where you will read both input files "file_input1.txt" & "file_input2.txt" and as per the CELL name present in second file (e.g. AND1_2X ...), you have to extract below data and display it in the below format.

    Name        Trans    Load    Delay    Total_Delay
    ----------------------------------------------------------------------------
    AND1_2X      0.1    1.25ff    1.50ns      1.50ns
    AND2_3X      0.3    2.27ff    2.37ns      3.87ns
    AND2_4X      0.5    2.54ff    1.82ns      5.69ns
    NAND2_3X    0.3    2.11ff    2.48ns      8.17ns

Total Delay = Delay of Cell + Delay of Previous stage
So, in our case,
    Delay of AND1_2X = 1.50ns + 0ns = 1.50ns
    Delay of AND2_3X = 2.37ns + 1.50ns = 3.87ns
    Delay of AND2_4X = 1.82ns + 3.87ns = 5.69ns
    Delay of NAND2_3X = 2.48ns + 5.69ns = 8.17ns

Note:
  • All the above calculations, you have to do with in TCL Program.
  • You have to reuse TCL program of Task 1.
    • Reading of File "file_input1.txt" should be with the help of previous program only.
    • Rearranging the data should be using previous program.
    • Writing data should be as per previous program.

Step 4: Print the above formated data onto the terminal & in output file "file_output2.txt"

Learning after this Program:
  • How to Open & Close 2 Input files simultaneously
  • How to Read or Write from/in a file
  • How to save data in List and do different operation on that
  • How to do Matching or say comparison of Data
  • How to select only a specific data
  • How to do mathematical calculations
  • Different commands use-model
    • list, lindex, lappend
    • Foreach loop, While loop, If-else loop
    • gets and puts
    • split
    • expr
    • incr
  • How to manage single space, multiple space
  • Regular expression concepts
  • Procedure concepts (proc in tcl)
    • How to write a Procedure
    • How to pass a value to Procedure
    • How to call a Procedure
    • How to get return from a Procedure (return command)

Industrial Use of this Task:
Most of the time, we work on automation of data in Industry.This data present in the form of report file (.rpt file) or output file or may be logfile. After reading data, we have to do a lot of operation (mathematically) and has to represent the data as per our requirement.
For example,
  1. Timing Report have a lot of information about several Timing paths. You may have to create a automation to find out only slack of specific paths mentioned in other file.
  2. SPEF file has C (cap) information of Nets. You want to compare 2 SPEF files of same design generated after making certain changes in design. This type of automation create a final report of Delta Cap for all Nets present in either SPEF file. Analysis of this final report (created after automation) may help you to fix design issues.
There are lot of such examples. I will try to list those sometime later. :)

I am sure this article will help you. In the Next article, we will discuss about a task where you have to take inputs from user in runtime (means during the execution of Program).


-By Rajat Bansal
(Btech-EC:- 2019 Passout)
(ABES Engineering College)


-Supervised By Puneet Mittal
(Founder & Director)
(VLSI Expert Private Limited)

7 comments:

  1. Mail me at 14294.abhishek@gmail.com for the script. Was not able to post it here!

    ReplyDelete
  2. PART1



    proc read_file {file_name} {
    set fp_infile [open "$file_name" r]
    set file_data [read $fp_infile]
    close $fp_infile
    return $file_data
    }

    proc read_cell {cell_index file2_data_split} {
    while {$cell_index != 4} {
    #
    #read the ith cell from file_input2
    #
    set cell [lindex $file2_data_split $cell_index]
    #puts $cell
    regexp {([A-Z0-9_:]+) ([A-Z0-9_]+)} $cell match_var sub_cell sub_gate
    return $sub_gate

    } ;# while
    } ;# proc

    proc get_data_from_fileinput1 {array_to_list x} {
    #find_in_fileinput1 $cell_index $array_to_list
    #while {$cell_index != 4} {
    #
    #find the cell name in file_input1
    #
    #set file_input1_data [array get row]
    #puts $array_to_list
    set match_cell [lsearch -all -inline -regexp $array_to_list "^$x"]
    set split_match_cell [split $match_cell " "]
    #puts $split_match_cell
    regexp {[NAND]+} $split_match_cell found
    if {$found == "NAND"} {
    set col1 [lindex $split_match_cell 5]
    set col2 [lindex $split_match_cell 11]
    set col3 [lindex $split_match_cell 15]
    set mylist [list $col1 $col2 $col3]
    #puts $mylist
    } else {
    set col1 [lindex $split_match_cell 6]
    set col2 [lindex $split_match_cell 12]
    set col3 [lindex $split_match_cell 16]
    set mylist [list $col1 $col2 $col3]
    #puts $mylist
    }
    #set arrange [lsort -ascii $mylist]
    #puts $arrange
    #set trans_value [lindex $arrange 0]
    #set load_value [lindex $arrange 1]
    #set delay_value [lindex $arrange 2]
    set delay_value [lsearch -all -inline -regexp $mylist "ns*"]
    set trans_value 0
    regexp {[0-9.]*} $mylist trans_value
    set load_value [lsearch -all -inline -regexp $mylist "ff*"]
    #puts [format "%-12s" "%-9s" "%-9s" "%-9s" $x $trans_value $load_value $delay_value]
    set arranged_cell_values [list $x $trans_value $load_value $delay_value]
    #puts $arranged_cell_values
    return $arranged_cell_values

    #} ;#findinfileinput1 while
    } ;#proc


    ReplyDelete
  3. PART2



    proc total_delay_calc {got_data_from_fileinput1 old_delay} {
    #upvar $old_delay ref_old_delay
    #global old_delay
    set convert_to_list [split $got_data_from_fileinput1 " "]
    #puts $convert_to_list
    #puts "hello $old_delay"
    set match_and [lsearch $convert_to_list "D"]
    #puts $match_and
    set current_delayns [lindex $convert_to_list 3]
    set current_delay 0
    regexp {[0-9.]+} $current_delayns current_delay
    #puts $current_delay
    set total_delay [expr ($current_delay + $old_delay)]
    set old_delay $total_delay
    set delays [list $total_delay $old_delay]
    #puts $delays
    return $delays
    }

    #
    #displays the info in modified way
    #
    proc add_total_delay_to_row {array_to_list tot_delay_1 got_data_from_fileinput1
    } {
    #puts $array_to_list
    #puts $got_data_from_fileinput1
    #puts $tot_delay_1

    set new_row [split $got_data_from_fileinput1 " "]
    #puts $new_row
    #set dummy [lindex $new_row 13]
    #puts $dummy
    #puts $new_row

    regexp {[NAND]+} $new_row found
    if {$found == "NAND"} {
    #puts "hello $new_row"
    set row_list_dummy [lindex $new_row 0]
    regexp {[A-Z0-9_]+} $row_list_dummy row_list(0)
    set row_list(1) [lindex $new_row 1]
    set row_list(2) [lindex $new_row 2]
    set row_list(3) [lindex $new_row 3]
    set ns ns
    set tot_delay_1 "$tot_delay_1 $ns"
    set tot_delay_1_ns [join $tot_delay_1 ""]

    } else {
    set row_list_dummy [lindex $new_row 0]
    regexp {[A-Z0-9_]+} $row_list_dummy row_list(0)
    set row_list(1) [lindex $new_row 1]
    set row_list(2) [lindex $new_row 2]
    set row_list(3) [lindex $new_row 3]
    set ns ns
    set tot_delay_1 "$tot_delay_1 $ns"
    set tot_delay_1_ns [join $tot_delay_1 ""]

    }

    set formatted_row [format "%-12s %-9s %-9s %-9s %-9s" $row_list(0) $row_list(1) $row_list(2) $row_list(3) $tot_delay_1_ns]
    return $formatted_row
    }

    proc write_in_out {fp_outfile row_cell} {
    puts $fp_outfile
    puts $fp_outfile $row_cell
    }



    if {[catch {open "file_input1.txt"} file_input1_id] && [catch {open "file_input2.txt"} file_input2_id]} {
    puts "error1: $file_input1_id"
    puts "error2: $file_input2_id"

    } else {
    #read from file_input1.txt and sort/modify
    source "/nfs/iind/disks/pds.tfm.disk_0001/Abhishek/file_handling_1.tcl"
    set cell_index 0
    #read from file_input2.txt
    set file_name "file_input2.txt"
    set file2_data [read_file $file_name]
    puts $file2_data

    set file2_data_split [split $file2_data "\n"]
    #
    #puts $name
    puts [format "%-12s %-9s %-9s %-9s %-5s" $name $Trans $Load $Delay {Total Delay}]
    #puts $ohye
    puts "---------------------------------------------------------"

    #
    #in file_out2.txt
    #
    set fp_outfile [open "file_out2.txt" w+]
    set m [format "%-12s %-9s %-9s %-9s %-5s" $name $Trans $Load $Delay {Total Delay}]
    puts $fp_outfile $m
    puts $fp_outfile "---------------------------------------------------------"
    #
    #puts $file2_data_split
    #

    ReplyDelete
  4. PART3


    proc total_delay_calc {got_data_from_fileinput1 old_delay} {
    #upvar $old_delay ref_old_delay
    #global old_delay
    set convert_to_list [split $got_data_from_fileinput1 " "]
    #puts $convert_to_list
    #puts "hello $old_delay"
    set match_and [lsearch $convert_to_list "D"]
    #puts $match_and
    set current_delayns [lindex $convert_to_list 3]
    set current_delay 0
    regexp {[0-9.]+} $current_delayns current_delay
    #puts $current_delay
    set total_delay [expr ($current_delay + $old_delay)]
    set old_delay $total_delay
    set delays [list $total_delay $old_delay]
    #puts $delays
    return $delays
    }

    #
    #displays the info in modified way
    #
    proc add_total_delay_to_row {array_to_list tot_delay_1 got_data_from_fileinput1
    } {
    #puts $array_to_list
    #puts $got_data_from_fileinput1
    #puts $tot_delay_1

    set new_row [split $got_data_from_fileinput1 " "]
    #puts $new_row
    #set dummy [lindex $new_row 13]
    #puts $dummy
    #puts $new_row

    regexp {[NAND]+} $new_row found
    if {$found == "NAND"} {
    #puts "hello $new_row"
    set row_list_dummy [lindex $new_row 0]
    regexp {[A-Z0-9_]+} $row_list_dummy row_list(0)
    set row_list(1) [lindex $new_row 1]
    set row_list(2) [lindex $new_row 2]
    set row_list(3) [lindex $new_row 3]
    set ns ns
    set tot_delay_1 "$tot_delay_1 $ns"
    set tot_delay_1_ns [join $tot_delay_1 ""]

    } else {
    set row_list_dummy [lindex $new_row 0]
    regexp {[A-Z0-9_]+} $row_list_dummy row_list(0)
    set row_list(1) [lindex $new_row 1]
    set row_list(2) [lindex $new_row 2]
    set row_list(3) [lindex $new_row 3]
    set ns ns
    set tot_delay_1 "$tot_delay_1 $ns"
    set tot_delay_1_ns [join $tot_delay_1 ""]

    }

    set formatted_row [format "%-12s %-9s %-9s %-9s %-9s" $row_list(0) $row_list(1) $row_list(2) $row_list(3) $tot_delay_1_ns]
    return $formatted_row
    }

    proc write_in_out {fp_outfile row_cell} {
    puts $fp_outfile
    puts $fp_outfile $row_cell
    }



    if {[catch {open "file_input1.txt"} file_input1_id] && [catch {open "file_input2.txt"} file_input2_id]} {
    puts "error1: $file_input1_id"
    puts "error2: $file_input2_id"

    } else {
    #read from file_input1.txt and sort/modify
    source "/nfs/iind/disks/pds.tfm.disk_0001/Abhishek/file_handling_1.tcl"
    set cell_index 0
    #read from file_input2.txt
    set file_name "file_input2.txt"
    set file2_data [read_file $file_name]
    puts $file2_data

    set file2_data_split [split $file2_data "\n"]
    #
    #puts $name
    puts [format "%-12s %-9s %-9s %-9s %-5s" $name $Trans $Load $Delay {Total Delay}]
    #puts $ohye
    puts "---------------------------------------------------------"

    #
    #in file_out2.txt
    #
    set fp_outfile [open "file_out2.txt" w+]
    set m [format "%-12s %-9s %-9s %-9s %-5s" $name $Trans $Load $Delay {Total Delay}]
    puts $fp_outfile $m
    puts $fp_outfile "---------------------------------------------------------"
    #
    #puts $file2_data_split
    #

    ReplyDelete
  5. PART3 (Please ignore the older one)
    #Cell 1
    set x [read_cell $cell_index $file2_data_split] ;#cell_index=0
    set array_to_list [array get row]
    #puts $array_to_list
    #puts $x
    set got_data_from_fileinput1 [get_data_from_fileinput1 $array_to_list $x]
    set old_delay 0
    #puts "1 $got_data_from_fileinput1"
    #puts "2 $old_delay"
    set delay_list1 [total_delay_calc $got_data_from_fileinput1 $old_delay]
    set old_delay [lindex $delay_list1 1]
    set tot_delay_1 [lindex $delay_list1 0]
    set row_cell_1 [add_total_delay_to_row $array_to_list $tot_delay_1 $got_data_from_fileinput1]
    puts $row_cell_1
    write_in_out $fp_outfile $row_cell_1

    #
    #Cell 2
    set cell_index [expr $cell_index+1]
    set x [read_cell $cell_index $file2_data_split]
    set array_to_list [array get row]
    set got_data_from_fileinput1 [get_data_from_fileinput1 $array_to_list $x]
    set delay_list2 [total_delay_calc $got_data_from_fileinput1 $old_delay]
    set old_delay [lindex $delay_list2 1]
    set tot_delay_2 [lindex $delay_list2 0]
    set row_cell_2 [add_total_delay_to_row $array_to_list $tot_delay_2 $got_data_from_fileinput1]
    puts $row_cell_2
    write_in_out $fp_outfile $row_cell_2

    #
    #Cell 3
    set cell_index [expr $cell_index+1]
    set x [read_cell $cell_index $file2_data_split]
    #puts "hey $x"
    set array_to_list [array get row]
    set got_data_from_fileinput1 [get_data_from_fileinput1 $array_to_list $x]
    #puts $got_data_from_fileinput1
    set delay_list3 [total_delay_calc $got_data_from_fileinput1 $old_delay]
    set old_delay [lindex $delay_list3 1]
    set tot_delay_3 [lindex $delay_list3 0]
    set row_cell_3 [add_total_delay_to_row $array_to_list $tot_delay_3 $got_data_from_fileinput1]
    puts $row_cell_3
    write_in_out $fp_outfile $row_cell_3

    #
    # Cell 4
    set cell_index [expr $cell_index+1]
    set x [read_cell $cell_index $file2_data_split]
    set array_to_list [array get row]
    set got_data_from_fileinput1 [get_data_from_fileinput1 $array_to_list $x]
    #puts $got_data_from_fileinput1
    set delay_list4 [total_delay_calc $got_data_from_fileinput1 $old_delay]
    set old_delay [lindex $delay_list4 1]
    set tot_delay_4 [lindex $delay_list4 0]
    #puts "$array_to_list $tot_delay_4 $got_data_from_fileinput1"
    set row_cell_4 [add_total_delay_to_row $array_to_list $tot_delay_4 $got_data_from_fileinput1]
    puts $row_cell_4
    write_in_out $fp_outfile $row_cell_4
    close $fp_outfile
    };#if

    ReplyDelete
  6. #!/usr/bin/tclsh

    set input_file1 [open "file_input1.txt" r]
    set input_file2 [open "file_input2.txt" r]
    set output_file [open "C:/ActiveTcl/bin/training/output_file1.txt" w]

    set obj_cell_name ""
    set sum_delay 0


    while {[gets $input_file1 line]>=0} {
    lappend obj_cell_name [lindex $line 1]
    }
    close $input_file2

    set line_num 1
    while {[gets $input_file2 line]>=0} {
    if {$line_num == 1} {
    puts $output_file "$line\tdelay"
    set line_num [expr $line_num+1]
    } else {
    if {[string match "*[lindex $line 0]*" $obj_cell_name]==1} {
    #regexp {([0-9].*)ns} [lindex $line 1]] delay_unit delay
    set delay [string trimright [lindex $line 1] "ns"]
    set sum_delay [expr $sum_delay+$delay]
    puts $output_file "$line\t[expr $sum_delay]ns"
    set line_num [expr $line_num+1]
    continue
    }
    }
    }
    close $input_file1
    close $output_file

    ReplyDelete