我们知道dc里,命令read_file
的输入参数相当灵活,有yes/no型的(如-autoread、-rtl),也有指定类别传参数的(如-format、-define、-top),还有直接传的(如file_list)。
dc_shell> read_file -help
Usage: read_file
[-autoread]
[-format format_name]
[-define macro_names]
[-rtl]
[-top top]
...
[file_list]
那么我们tcl里怎么定义一个函数支持同样的参数输入呢?要实现这个功能,就要说到一个特殊参数args
,这个args
是把所有的参数拼成一个列表传入。
下面是一个仿写的例子,定义了特殊参数args
,用for
循环把这个参数列表逐个打印出来。
proc read_file {args} {
set num [llength $args]
for {set i 0} {$i < $num} {incr i} {
set arg [lindex $args $i]
puts "$i: $arg"
}
}
read_file -autoread -format verilog -define A=1 -rtl -top digital_top {../rtl/a.v ../rtl/b.v ../rtl/c.v}
# 输出log
0: -autoread
1: -format
2: verilog
3: -define
4: A=1
5: -rtl
6: -top
7: digital_top
8: ../rtl/a.v ../rtl/b.v ../rtl/c.v
虽然打印出来了,但还是显得有些乱,并没有按含义进行处理。所以我们需要在函数里进一步解析参数,最终存放到一个字典里。解析过程如下:
proc read_file {args} {
set options {}
set file_list ""
set num [llength $args]
for {set i 0} {$i < $num} {incr i} {
set arg [lindex $args $i]
if {$arg == "-autoread"} {
dict append options "autoread" true
} elseif {$arg == "-format"} {
dict append options "format" [lindex $args [expr $i + 1]]
incr i
} elseif {$arg == "-define"} {
dict append options "define" [lindex $args [expr $i + 1]]
incr i
} elseif {$arg == "-rtl"} {
dict append options "rtl" true
} elseif {$arg == "-top"} {
dict append options "top" [lindex $args [expr $i + 1]]
incr i
} else {
lappend file_list $arg
}
}
foreach key [dict keys $options] {
set val [dict get $options $key]
puts "$key: $val"
}
puts $file_list
}
read_file -autoread -format verilog -define A=1 -rtl -top digital_top {../rtl/a.v ../rtl/b.v ../rtl/c.v}
# 输出log
autoread: true
format: verilog
define: A=1
rtl: true
top: digital_top
{../rtl/a.v ../rtl/b.v ../rtl/c.v}
这样模仿的read_file
参数定义就实现了。在使用时,可以用dict exists $dictname keyname
判断参数是否存在,再做进一步处理。这种定义函数参数的方法比较灵活,也不用太关注参数的顺序。