tcl文本处理-根据用户定义的值重新排列行和列中的值
我是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个值 制图方案: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
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", \
);
我的策略是:
我尽力解释我的编码请求。你们中有谁能帮我想一个合适的方法在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", \
);
}
}