DC Tcl tutorial
Tcl 的全称是 Tool Command Language,它是当今 EDA 软件系统中普遍采用的一种脚本
语言 ,如 Synopsys DC 中的 dc_shell-t>和 Synopsys PrimeTime 中的 pt_shell>就是基于这种脚
本的,实际上它已经成为了一种工业标准。
Design compiler 的后续版本已经不支持 dc shell (dcsh),而大规模 asic 的综合都采取 batch
mode,因此我们必须掌握 DC Tcl。最新的 dc_shell 与 dc_shell-t 都只支持 DC Tcl。
以 DC 为例,使用 Tcl 比 dc_shell 具有以下一些优点:
有更多的在线帮助;
支持 lists 和 arrays;
用户可以定义 procedures;
case 结构、string 的操纵与比较、文件操纵;等等。
Synopsys 中使用 Tcl 的工具有:Design Compiler, Formality, PrimeTime, Physical Compiler,
Chip Architect 等等。
一)Tcl 语法
Tcl 是基于字符串的命令语言。每一个 Tcl 脚本被看作是一系列命令的组合,用换行符
或分号来分隔。每一条命令语句由一个命令和一系列参数组成。
注释:
用#表示这一行后面的内容为注释,例如:
# Same line comment.
使用新版的 DC,若读入 dcsh script,会发现注释符“/*” “*/”已经不再被支持,
如该注释方法已不支持:/* clock setting */
通配符:
?表示一个字符(PrimeTime only)
* 表示任意多个(包括 0 个)字符
特殊字符:
$ 获得变量的值,比如$sum 返回变量 sum 的值
[ ] 执行其内包含的命令,并返回命令执行的值
“” 内容作为一个整体,其内支持$与[ ]符号的作用,如支持变量替代
{} 内容作为一个整体,但其内不支持$、[ ]以及转义字符\的作用
\ 转义符
( )用于访问 array 的元素,e.g., $env(HOME)
; 命令行结束,可有可无
变量:
Tcl 的变量数据类型实际上只有一种,即:字符串。其所有的数值计算都只包含在
expr 中。
建立一个变量并赋值的 set 命令,例如:
set x 27
(在 dcsh 中相应的赋值命令则是 $x=27, 在最新的 dc_shell 中不再支持该赋值方式)
删除一个变量的 unset 命令,例如:
unset x (注意在 tcl 命令中,有些命令的第一个变量是不带$符号的;不要错误地认
为因 x 已经用 set x 定义,而将该命令写为 unset $x)
用$符号对一个变量取值,例如:
set x 27
set y $x
用“\”引用一些特殊符号,例如:
set x 7
set y \$x
注:这里 y 的值是$x,而不是 7。
命令嵌套和引用:
“ ”表示弱引用,其内包含的嵌套命令和变量替代仍旧有效,例如:
set a 5
set s “temp = data[$a]”
注:s 的值为 temp = data[5]
{ }表示强制引用,其内的所有字符包括$符号都作为字符付给变量,例如:
set a 5
set s {temp = data[$a]}
注:s 的值为 temp = data[$a]
用 expr 进行算术运算,将运算式包含在[]内。符号对[]的意思是执行里面的命令,并返
回结果,有点类似 C 语言中的函数调用。例如:
dc_shell-t> set period 10.0
10.0
dc_shell-t> set freq [expr (1 / $period)]
0.1
dc_shell-t> echo “freq = [expr $f req* 1000] MHz”
freq = 100.0 MHz
dc_shell-t> set_load [expr [load_of cba_core/and2a0/A] * 5] \
[all_output]
注:这里的“\”表示续行。
其他一些有用的对变量进行操作的命令。
append 命令
Example:
set a engine_top
set b “_gate.v”
set x [append a $b] ; # x 被赋值为 engine_top_gate.v;append 的第一个分量无需带$符
puts $x ;#显示 subname; puts 命令的变量要带$符
二)Lists 和 Array 的用法
2.1 list 的用法
Lists 是 Tcl 的一个重要部分。Lists 用来表示不同对象的分组。Lists 元素可以包含 strings
或其它 lists。
创建一个 list 的三种方法:双引号,{}以及 list 命令。如下例所示。
下面表格列出了相关的对 list 的操作命令:
现举例说明:
dc_shell-t> set L1 {el1 el2 el3}
el1 el2 el3
dc_shell-t>echo $L1
el1 el2 el3
dc_shell-t>set Num_of_List_Elements [llength $L1]
3
还可以这样用:
dc_shell-t> set a 5
5
dc_shell-t> set b {c d $a [list $a z]}
c d $a [list $a z]
dc_shell-t> set b [list c d $a [list $a z]]
c d 5 {5 z}
dc_shell-t> lindex $b 0 ; #注意 list 的元素不能用( )来引用,比如$b(0)是错误的
c
在 DC 中可以这样配置 link_library:
dc_shell-t> set link_library {*}
*
dc_shell-t> lappend link_library tc6a.db opcon.db
* tc6a.db opcon.db
dc_shell-t> echo $link_library
* tc6a.db opcon.db
2.2 Array 的用法
Array 的元素可以用()来访问。每一个元素有自己独立的 name 和 value,name 类似 index
但可以为任意值。
示例:
dc_shell > echo $vio_rpt_ext(curr) ; #注意 echo 命令的变量需要$符
.volt
三)控制流(Control Flow)命令的使用:
if 语句,例如:
if {$x ==0} {
echo “Equal”
} elseif {$x > 0} {
echo “Greater”
} else {
echo “Less”
}
while 语句,例如:
set p 0
while {$p <= 10} {
echo “$p squared is: [expr $p*$p]” incr p
}
循环语句,例如:
for {set p 0} {$p <= 10} {incr p} {
echo “$p squared is: [expr $p * $p]”
}
foreach 语句,例如:
set i 1
foreach value {1 3 5 2} {
set i [expr $i * $value]
}
echo $i
30
四)过程(Procedures)
用户通过过程可以扩充 Tcl 的命令,并且可以有不同的参数。
语法为:
proc name arguments body
name:过程名
arguments:过程的参数,可以为空
body:过程的脚本
例如:
dc_shell-t> proc plus {a b} { return [expr $a + $b]}
dc_shell-t> plus 5 6
11
六)DC 中的一些 Tcl 说明
在 UNIX 提示符下启动 DC 的 Tcl 模式:
UNIX% dc_shell –tcl_mode
在较新的 DC 版本如 2011 SP2 版本中,只支持 Tcl 模式,因此直接使用命令 dc_shell
即启动 Tcl 模式。
每个设计中都有以下一些目标对象(objects):
designs, cells, references, ports, pins, clocks, nets
其中每个目标对象都有其相应的属性,例如:
ports 拥有的属性有:direction, driving_cell, max_capacitance, others…
designs 拥有的属性有:area, operating_conditions_max, max_area, others…
在标准的 Tcl 中则没有这些内容。
集合(Collection):
以下是在 DC-Tcl 中生成集合的一部分命令:
get_cells
get_clocks
get_designs
get_libs
get_nets
get_pins
get_ports
all_clocks
all_designs
all_inputs
all_outputs
all_registers
举例说明:
# Constrain a design for timing, using a time budget
set CLK_PER 10.0; # clock period (ns)
set time_budget 40.0; # percentage of clock period allowed for input/output logic
# calculate intermediate variables
set IO_DELAY [expr ( (1-$time_budget/100.0) * $CLK_PER)]
set all_except_clk [remove_from_collection [all_inputs] [get_ports Clk] ]
# constrain the design for timing
create_clock –period $CLK_PER –name MY_CLOCK [get_ports Clk]
set_input_delay $IO_DELAY –max –clock MY_CLOCK $all_except_clk
set_output_delay $IO_DELAY –max clock MY_CLOCK [all_outputs]
集合过滤(Filtering Collections):
用 filter_collection 命令,例如:
filter_collection [get_cells] “ref_name == AN2”;
注:从 cell 集合中去除名字为 AN2 的 cell
source 命令
加载执行一个 tcl 脚本,e.g., source clkdef.tcl
(注意 dcsh 的 include 命令不可以用在 tcl 中,会报错)
read_verilog
读取 verilog 文件。dcsh 命令 read -format verilog 不支持。
file
file option arg
例如 option 为 extension 时,该命令获得文件后缀名。
如:
set f top.current;
file extension $f; #返回值为“.current”
File command and option Description
file dirname fname Returns the directory name part of a file name.
file exists fname Returns 1 if the file name exists, 0 otherwise.
file extension fname Returns the extension part of a file name.
file isdirectory fname Returns 1 if the file name is a directory, 0 otherwise.
file isfile fname Returns 1 if the file name is a file, 0 otherwise.
file readable fname Returns 1 if the file is readable, 0 otherwise.
file rootname fname Returns the name part of a file name.
file size fname Returns the size, in bytes, of a file.
file tail fname Returns the file name from a file path string.
file writable fname Returns 1 if the file is writable, 0 otherwise
glob
产生与 pattern 匹配的所有文件的 list。
e.g., set flist [glob *.em *.volt]
open,close 及 flush
open 命令获得文件的 ID,可有 r,w 等选项。
e.g., set f [open aa.em w+] ; # 获得文件 aa.em 的 ID (比如返回值可能是 file15)
gets ,puts
gets 从文件中读取一行。
实例
set f [open aa.em r]
gets $f line; #cong 文件 aa.em 中读取一行
Design compiler 综合脚本示例
set DESIGN_NAME top
set SUB_MODULE [list sub1.v sub2.v sub3.v]
set CLK_NAME Sysclk
set CLK_PERIOD 10
set INPUT_DELAY 2
set OUTPUT_DELAY 3
##5 步综合步骤
read_verilog [list $SUB_MODULE $DESIGN_NAME.v] ;# 1)读取 verilog 文件
current_design $DESIGN_NAME ;#2)设置 current_design
link ;#3)link
# 4)约束条件设定
create_clock -p $CLK_PERIOD -n $CLK_NAME [get_ports $CLK_NAME]
set_input_delay $INPUT_DELAY -clock $CLK_NAME [list [all_inputs]]
set_output_delay $OUTPUT_DELAY -clock $CLK_NAME [list [all_outputs]]
compile ;# 5)综合
六、RISC_CORE 的 Tcl 脚本
runit.tcl 文件:
#
set_min_library core_slow.db -min_version core_fast.db
# Directory Structure
set source_dir unmapped
set script_dir scripts
set mapped_dir mapped
set reports_dir reports
# List of designs to be compiled
set designs_to_build {RISC_CORE}
foreach module $designs_to_build {
set fname $source_dir/$module.db
read_db $fname
set current_design $module
link
source scripts/top_level.tcl
uniquify
compile
set fname $mapped_dir/$module.db
write -hierarchy -output $fname
set fname $reports_dir/$module.rpt
report_constraint -all_violators > $fname
report_timing > reports/default_timing.rpt
report_timing -input_pins > reports/pins_timing.rpt
report_timing -nets > reports/nets_timing.rpt
report_timing -delay min > reports/min_timng.rpt
}