0

I am new to tcl and would like to use it in text processing of a simple case. The following format is in Liberty (.lib file) which is used in chip design. I would be truly indebted for any help on this.

Here is a snippet of my file (text processing to be done only on the "values")

timing () {  
    related_pin : "clk";  
    timing_type : setup_rising;  
    rise_constraint (constraint_template_5X5) {  
      index_1 ("0.01, 0.05, 0.12, 0.2, 0.4");  
      index_2 ("0.005, 0.025, 0.06, 0.1, 0.3");  
      index_3 ("0.084, 0.84, 3.36, 8.4, 13.44") ;  
      values ( \  
        "1.1, 1.2, 1.3, 1.4, 1.5", \        
        "2.1, 2.2, 2.3, 2.4, 2.5", \  
        "3.1, 3.2, 3.3, 3.4, 3.5", \  
        "4.1, 4.2, 4.3, 4.4, 4.5", \  
        "5.1, 5.2, 5.3, 5.4, 5.5", \  
        "6.1, 6.2, 6.3, 6.4, 6.5", \  
        "7.1 ,7.2, 7.3, 7.4, 7.5", \  
        "8.1, 8.2, 8.3, 8.4, 8.5", \  
        "9.1, 9.2, 9.3, 9.4, 9.5", \  
        "10.1,10.2,10.3,10.4,10.5", \  
        "11.1,11.2,11.3,11.4,11.5", \  
        "12.1,12.2,12.3,12.4,12.5", \  
        "13.1,13.2,13.3,13.4,13.5", \  
        "14.1,14.2,14.3,14.4,14.5", \  
        "15.1,15.2,15.3,15.4,15.5", \  
        "16.1,16.2,16.3,16.4,16.5", \  
        "17.1,17.2,17.3,17.4,17.5", \  
        "18.1,18.2,18.3,18.4,18.5", \  
        "19.1,19.2,19.3,19.4,19.5", \  
        "20.1,20.2,20.3,20.4,20.5", \  
        "21.1,21.2,21.3,21.4,21.5", \  
        "22.1,22.2,22.3,22.4,22.5", \  
        "23.1,23.2,23.3,23.4,23.5", \  
        "24.1,24.2,24.3,24.4,24.5", \  
        "25.1,25.2,25.3,25.4,25.5", \  
      );  
    } 

So all the "values" are in a 25 rows x 5 columns lookup table format which I wish to change to a 5 rows x 5 columns table format. To accomplish this, I would like to ask the user which of the 5 values in index_3 he/she wants before mapping is done as follows (while also removing the index_3 line):

C is the user defined column based on index_3: (column 1 for 0.084, column 2 for 0.84, column 3 for 3.36, column 4 for 8.4, column 5 for 13.44). *Only 1 value can be chosen by user

Mapping scheme:

   1,C -> row 1 column 1  
   2,C -> row 2 column 1  
   3,C -> row 3 column 1  
   4,C -> row 4 column 1  
   5,C -> row 5 column 1  
   6,C -> row 1 column 2  
   7,C -> row 2 column 2  
   8,C -> row 3 column 2

etc ..

For EXAMPLE, say a user chooses column 1 (value 0.084 from index_3) --> which 'chooses' entire 1st column of the data in 'values' to be text processed/arranged

Hence, resulting text processing done by tcl based on the mapping scheme should be:

index_1 ("0.01, 0.05, 0.12, 0.2, 0.4");  
index_2 ("0.005, 0.025, 0.06, 0.1, 0.3");

 values ( \  
        "1.1, 6.1, 11.1, 16.1, 21.1", \  
        "2.1, 7.1, 12.1, 17.1, 22.1", \  
        "3.1, 8.1, 13.1, 18.1, 23.1", \  
        "4.1, 9.1, 14.1, 19.1, 24.1", \  
        "5.1, 10.1,15.1, 20.1, 25.1", \  
  ); 

My strategy is this:

  1. search for "rise_constraint" to zero in on which values to text process in the entire file

  2. comment out line "index_3 (...)"; add /* and */ at beginning and end of line in reprinted processed file (optional)

  3. convert 'values' from 25 rows x 5 columns table to 5 rows x 5 columns table BASED on Index_3 value chosen ("user defined column choice")

  4. re-print other lines as is (including the text processed 'values')

I tried my very best to explain my coding request. Can any of you meastros please help me think of a proper way in tcl I can do such text processing? Many thanks!!

4

3 回答 3

1

我终于对此产生了浓厚的兴趣,并根据我更好的判断编写了一个完整的答案。我不会以任何方式记录它。阅读它,阅读文档以了解您不理解的命令,然后来提问。

查看您的自由文件,我发现它非常接近本机 Tcl 语法。因此,您可以创建一些名为“timing”、“rise_constraint”等的程序,基本上可以将其作为脚本运行。

package require struct::list

######################################################################
proc main {libfile} {
    global lines idx3 vals
    set lines [list]
    set idx3 [list]
    set vals [list]

    evaluate_liberty $libfile

    set idx [get_choice "select an index_3 value: " $idx3]
    set column [struct::list mapfor elem $vals {lindex $elem $idx}]

    set newvalues [list]
    for {set i 0} {$i < 5} {incr i} {
        lappend newvalues [lrange $column [expr {5*$i}] [expr {5*($i+1)-1}]]
    }

    print_liberty $newvalues
}

######################################################################
proc evaluate_liberty {libfile} {
    set fh [open $libfile r]
    # handle known syntax error in liberty file
    set contents [string map {\", \"} [read -nonewline $fh]]
    regsub -all -line {\s+$} $contents {} contents
    close $fh

    uplevel #0 $contents
}

proc get_choice {prompt values} {
    while {1} {
        for {set i 0} {$i < [llength $values]} {incr i} {
            puts stderr [format "%2d. %s" $i [lindex $values $i]]
        }
        puts -nonewline stderr $prompt
        gets stdin answer
        if {[string is integer -strict $answer]} {
            if {0 <= $answer && $answer < [llength $values]} {
                return $answer
            }
        }
    }
}

proc print_liberty {newvalues} {
    global lines close_braces
    puts [join $lines \n]

    puts "values ( \\"
    foreach elem $newvalues {
        puts [format "\"%s\", \\" [join $elem {, }]]
    }
    puts ");"

    for {set i 1} {$i <= $close_braces} {incr i} {
        puts [format %c 125]
    }
}

######################################################################
# define DSL
proc timing {label script} {
    lappend ::lines [format "timing %s %c" $label 123]
    incr ::close_braces
    uplevel 1 $script
}

proc rise_constraint {label script} {
    lappend ::lines [format "rise_constraint %s %c" $label 123]
    incr ::close_braces
    uplevel 1 $script
}

proc index_3 {args} {
    global idx3
    foreach item $args {
        lappend idx3 [string map {( "" \" "" , "" ) ""} $item]
    }
}

proc values {args} {
    global vals
    foreach set [lrange $args 1 end-1] {
        lappend vals [split [regsub -all {\s*,\s*} $set { }]]
    }
}

rename unknown system_unknown

proc unknown args {
    lappend ::lines "[join $args];"
}

######################################################################
if {$argc == 0} {
    puts "usage: $argv0 filename.lib"
    exit
}

set libfile [lindex $argv 0]
if {![file exists $libfile]} {
    error "no such file: $libfile"
}

main $libfile

运行它:

$ tclsh liberty.tcl test.lib  > newlib.lib
 0. 0.084
 1. 0.84
 2. 3.36
 3. 8.4
 4. 13.44
select an index_3 value: 0

$ cat newlib.lib 
timing () {
related_pin : clk;
timing_type : setup_rising;
rise_constraint (constraint_template_5X5) {
index_1 ("0.01, 0.05, 0.12, 0.2, 0.4");
index_2 ("0.005, 0.025, 0.06, 0.1, 0.3");
values ( \
"1.1, 2.1, 3.1, 4.1, 5.1", \
"6.1, 7.1, 8.1, 9.1, 10.1", \
"11.1, 12.1, 13.1, 14.1, 15.1", \
"16.1, 17.1, 18.1, 19.1, 20.1", \
"21.1, 22.1, 23.1, 24.1, 25.1", \
);
}
}

你确实失去了所有漂亮的缩进,但你得到了你想要的值。

于 2014-04-16T22:05:21.507 回答
1

第一步是知道如何以最终形式表示 tcl 中的数据。这只是一种可能的解决方案。

dict set risedata constraints { 
  constraint {
    0.084 { 0 { 0 1.1 1  6.1 2 11.1 3 16.1 4 21.1 }
            1 { 0 2.1 1  7.1 2 12.1 3 17.1 4 22.1 }
            2 { 0 3.1 1  8.1 2 13.1 3 18.1 4 23.1 }
            3 { 0 4.1 1  9.1 2 14.1 3 19.1 4 24.1 }
            4 { 0 5.1 1 10.1 2 15.1 3 20.1 4 25.1 }
    }
  }
  indexes { 1 { 0.01 0.05 0.12 0.2 0.4 }
            2 { 0.005 0.025 0.06 0.1 0.3 }
            3 { 0.084 0.84 3.36 8.4 13.44 } }
}

set c 0.084
puts "$c 2 3: [dict get $risedata constraints constraint $c 2 3]"
puts "idx1 3: [lindex [dict get $risedata constraints indexes 1] 3]"
puts "idx2 3: [lindex [dict get $risedata constraints indexes 2] 3]"

然后知道你需要在哪里,加载 .lib 只是一个简单的解析问题:

set fh [open z.lib r]
set inval false
while { [gets $fh line] >= 0 } {
  if { [regexp {\);} $line] } {
    set inval false
  }
  if { [regexp {index_(\d+)} $line all idx] } {
    regsub {^[^"]*"} $line {} d
    regsub {".*} $d {} d
    regsub -all {,} $d {} d
    dict set risedata constraints indexes $idx $d
  }
  if { $inval } {
    regsub {^[^"]*"} $line {} d
    regsub {".*} $d {} d
    regsub -all {[ ,]+} $d { } d
    set row [expr {$rcount % 5}]
    set column [expr {$rcount / 5}]
    set i 0
    foreach {v} [split $d { }] {
      set c [lindex [dict get $risedata constraints indexes 3] $i]
      dict set risedata constraints constraint $c $row $column $v
      incr i
    }
    incr rcount
  }
  if { [regexp {values} $line] } {
    set inval true
    set row 0
    set rcount 0
  }
}
close $fh

puts $risedata
set c 0.084
puts "$c 2 3: [dict get $risedata constraints constraint $c 2 3]"
puts "idx1 3: [lindex [dict get $risedata constraints indexes 1] 3]"
puts "idx2 3: [lindex [dict get $risedata constraints indexes 2] 3]"
于 2014-04-14T22:42:51.627 回答
0

这是 STF(Synopsys 技术文件)或简单称为[dot]lib liberty

我确实在 TCL 平台上处理了这些文件,但使用了一些解析器。

尽管这里有许多解析器可用,但它适合您。

我建议使用解析器来处理[dot]lib,因为文件格式多次损坏并且无法被 primetime 或其他 lib 工具读取。

自由解析器

还有另一种 C 语言可用.. google vlsicad ucsd edu + liberty parser

于 2014-11-28T13:36:52.717 回答