0

私は tcl を初めて使用し、単純なケースのテキスト処理で使用したいと考えています。以下のフォーマットは、チップ設計で使用される Liberty (.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");  
      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", \  
      );  
    } 

したがって、すべての「値」は 25 行 x 5 列のルックアップ テーブル形式であり、5 行 x 5 列のテーブル形式に変更したいと考えています。これを達成するために、次のようにマッピングを行う前に、index_3 の 5 つの値のどれが必要かをユーザーに尋ねたいと思います (index_3 行も削除します)。

C は index_3 に基づくユーザー定義の列です: (0.084 の場合は列 1、0.84 の場合は列 2、3.36 の場合は列 3、8.4 の場合は列 4、13.44 の場合は列 5)。*ユーザーが選択できる値は 1 つだけです

マッピング スキーム:

   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

など..

例として、ユーザーが列 1 (index_3 からの値 0.084) を選択するとします --> これにより、「値」内のデータの最初の列全体がテキスト処理/配置されるように「選択」されます。

したがって、マッピング スキームに基づいて tcl によって実行される結果のテキスト処理は次のようになります。

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", \  
  ); 

私の戦略はこれです:

  1. 「rise_constraint」を検索して、ファイル全体でテキスト処理する値をゼロにします

  2. 行 "index_3 (...)" をコメントアウトします。転載処理ファイルの行頭と行末に /* と */ を追加 (オプション)

  3. 選択した Index_3 値に基づいて、25 行 x 5 列のテーブルから 5 行 x 5 列のテーブルに「値」を変換します (「ユーザー定義の列の選択」)

  4. 他の行をそのまま再印刷します (テキスト処理された「値」を含む)

コーディングのリクエストを説明するために最善を尽くしました。このようなテキスト処理を行うことができるtclでの適切な方法を考えるのを手伝ってください。どうもありがとう!!

4

3 に答える 3

1

最初のステップは、最終的な形式で tcl のデータを表現する方法を知ることです。これは考えられる解決策の 1 つにすぎません。

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 に答える
1

私はついにこれに本当に興味を持ち、より良い判断に反して完全な答えをコード化しました. 私は決してそれを文書化するつもりはありません。それを読んで、理解できないコマンドのドキュメントを読んでから、質問に来てください。

liberty ファイルを見ると、ネイティブの 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 に答える