tcl文本处理-根据用户定义的值重新排列行和列中的值

tcl文本处理-根据用户定义的值重新排列行和列中的值,tcl,text-processing,vlsi,Tcl,Text Processing,Vlsi,我是tcl的新手,希望在一个简单案例的文本处理中使用它。以下格式为Liberty(.lib文件),用于芯片设计。我真的很感激你在这方面的帮助 这是我的文件的一个片段(仅对“值”进行文本处理) 所以所有的“值”都是25行x5列的查找表格式,我想改成5行x5列的表格格式。为了实现这一点,我想询问用户,在映射之前,他/她想要索引_3中的5个值中的哪一个,如下所示(同时删除索引_3行): C是基于索引_3的用户定义列:(第1列表示0.084,第2列表示0.84,第3列表示3.36,第4列表示8.4,第5

我是tcl的新手,希望在一个简单案例的文本处理中使用它。以下格式为Liberty(.lib文件),用于芯片设计。我真的很感激你在这方面的帮助

这是我的文件的一个片段(仅对“值”进行文本处理)

所以所有的“值”都是25行x5列的查找表格式,我想改成5行x5列的表格格式。为了实现这一点,我想询问用户,在映射之前,他/她想要索引_3中的5个值中的哪一个,如下所示(同时删除索引_3行):

C是基于索引_3的用户定义列:(第1列表示0.084,第2列表示0.84,第3列表示3.36,第4列表示8.4,第5列表示13.44)*用户只能选择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列(索引_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", \  
  ); 
我的策略是:

  • 在整个文件中搜索“上升约束”为零的文本处理值

  • 注释掉“索引3(…)”;在重新打印的已处理文件的行首和行尾添加/*和*/(可选)

  • 根据所选索引_3值(“用户定义的列选择”)将“值”从25行x 5列表转换为5行x 5列表

  • 按原样重新打印其他行(包括文本处理的“值”)


  • 我尽力解释我的编码请求。你们中有谁能帮我想一个合适的方法在tcl我可以做这样的文本处理?非常感谢

    第一步是了解如何以最终形式表示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]"
    

    我终于对这件事产生了浓厚的兴趣,并根据我更好的判断编出了一个完整的答案。我不会以任何方式记录它。阅读它,阅读文档中你不懂的命令,然后过来问问题

    查看您的liberty文件,我发现它非常接近本机Tcl语法。因此,您可以创建几个名为“计时”、“上升约束”等的过程,基本上可以将其作为脚本运行

    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
    
    您确实丢失了所有漂亮的缩进,但得到了所需的值。

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

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

    虽然有很多解析器可用,但这里有一个适合您

    我建议使用解析器来处理[dot]lib,因为文件格式已损坏,无法通过黄金时段或其他lib工具读取


    还有一个C语言版本的。。google vlsicad ucsd edu+liberty parser

    你必须自己动手……文件有多大(好吧,数量级)?1kB?1MB?1GB?1TB?如果是对上一个问题的改进,你也应该在发布新问题之前编辑上一个问题。这真是太棒了!!简洁明了。非常感谢你。我现在运行了脚本,它返回了我确切要求的内容!你是救命恩人!我肯定要花一些时间来理解你的想法——“dict”和“regexp”命令对我来说是新的。dict的使用方式似乎与处理数组的方式相同。一个小问题,您建议我如何用变量“约束”返回的更新“值”覆盖原始的.lib文件“值”(在用户输入索引_3值后)?另外,一定要让我知道如何为我的项目推荐你。如果需要创建一个新的.lib文件,则需要升级上面的解析器来处理其余字段。一旦字典中有了所有需要的值,编写一个新的.lib文件就相当容易了。参考文献:。要写出一个文件,您可以使用open、close、dict、foreach、put。非常感谢您提供的参考资料和策略!我试着按照你的建议去做,但是没有办法用新的值替换这些值,包括“,”和“\”字符,并以5x5格式排列这些值(如我的问题所示)。这是我诚挚地请求你的最后一件帮助。我将在我的项目中引用你的名字。这帮了大忙!我正在努力删除{0 3.1 1 8.1 2 13.1 3 18.1 4 23.1}中值之间的索引,并将其更改为{3.1 8.1 13.1 18.1 23.1},然后在.lib文件中覆盖它。删除索引后,我必须在每行的末尾插入“,”和“\”(通过for循环迭代)。非常感谢您的意见。很抱歉打扰你这么多,但我想我从来没有遇到过像你这样的tcl大师,因此我会从你的投入中学到很多东西。谢谢@msb感谢您的澄清:)我昨天刚加入stackoverflow,所以我不知道绿色复选标记选项(直到现在才知道)。我已把它标记为正确的。如果我误解了你,我深表歉意。我将把Brad重定向到我的后续链接。很好的一天!对于您的阅读,Tcl语法可以在一页中完全描述:--读几遍,帮助您理解我的代码。哇!!!这绝对是令人震惊的事情。你是个魔术师!我想我得花上好几代的时间来编写这个。我更多的是一个硬件描述编码器(Verilog等)。无论如何,我必须仔细阅读这些命令——有些命令对我来说非常陌生。非常感谢你的时间和努力,我非常感激。我会继续提问。。我试着在activetcl中运行它,不知怎么的它崩溃了…嗯。
    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", \
    );
    }
    }