《数字集成电路静态时序分析基础》笔记③
欢迎关注个人公众号摸鱼范式
网络课程《数字集成电路静态时序分析基础》的笔记
TCL的应用
Synopsys Tcl
例如,统计时钟数量,人数显然不合理,可以用脚本语言统计,但是可以更加简单,直接用Synopsys Tcl的拓展命令更加便捷
参考资料
TCL在EDA工具中的拓展与应用
通过对Design Object的分析,了解和学习DC获取电路并进行解析的方法
常见指令
get_ports
-
语法格式:get_ports portsName
-
指令功能:返回design中对应的port object
-
如何查看deign当中有没有一个叫做CLK的port?
get_ports CLK
{CLK}
- 如何查看deign当中有没有一个port叫做SPI?
get—_ports SPI
No object Found!
- 查看design当中所有的port(*可以统配任何字符)
get_port *
{A B C D CLK OUT[0] OUT[1]}
- 假设port名字交{CLKA CLKB OUTA OUT B INA INB},如何得到所有C开头的port?
get_ports C*
{CLKA CLKB}
get_cells
- 语法格式:get_cells cellsName
- 指令功能:返回design中对应的cell的instance name object
- 查看是否有一个叫U4的cell
get_cells U4
{U4}
- 查看所有cell
get_cells *
{U1 U2 U3 U4}
- 查看以3结尾的cells
get_cells *3
{U3}
get_nets
- 语法格式 :get_nets netsName
- 指令功能:返回design中net的object
- 查看INV开头的net
get_nets INV*
{INV0 INV1}
- 查看所有net
get_nets *
{A B C D CLK BUS0 BUS1 INV0 INV1 OUT[0 OUT[1]]}
- 查看有多少个net
llength [get_object_name [get_nets *]]
11
sizeof_collection [get_nets *]
11
get_pins
-
语法格式:get_pin pinsName
-
指令功能:返回design中pin的object
-
查看叫Z的pin
get_pins */Z
{INV0/Z INV1/Z}
- 查看Q开头的pin
get_pins */Q*
{ENCODER/Q0 ENCODER/Q1 REGFILE/Q[1] REGFILE/Q[0]}
数据类型
数据类型:”object(对象)“及其“属性”
说明:
- object使tcl的一个重要拓展
- 常见对象有四种cell、net、port、pin
- 每种object有他的属性
- 任何一个属性都可以用get_attribute得到
- list_attribute -class *可以得到object的属性
- 部分属性可以用set_attribute来设置
Cell object
- 属性ref_name:用来保存器map到reference cell名称
get_attribute[get_cell -h U3] ref_name
{INV}
Pin object
- 属性owner_net:用来保存与之相连的net的名称
get_attribute [get_pins U2/A] owner_net
{BUS0}
Port object
- 属性direction:用来保存port方向
get_attribute [get_ports A] direction
{in}
get_attribute [get_ports OUT[1]] direction
{out}
Net object
- 属性 full_name:用来保存net的名称
get_attribute [gets_nets INV0]
{INV0}
get_object_name [get_nets INV0]
{INV0}
get_attribute INV0 full_name
Error:No attribute found
理解属性以后,就可以完成更多的任务:
- get_* -f:-f这个option可以用来过滤属性,以得到我们想要的object
- 得到所有方向是input的port
get_ports * -f "direction==in"
{A B C D CLK}
- 得到所有方向是output的pin
get_pins * -f "direction==out"
{U1/Q0 U1/Q1 U2/Z U3/Z REGFILE/Q[0] REGFIEL/Q[1]}
- 得到所有ref_name是INV的cell
get_cells * -f "ref_name==INV"
{U2 U3}
- 如何的得到电路中所有的inverter,那么应该输入什么样的脚本?
1.直接使用Synopsys TCL指令
get_buffers -inverter
2.人工拓展TCL指令
get_inverters
使用TCL语言控制设计EDA工具
讲述一个简单的、入门级的Synopsys DesignComplier自动化方案,供初学者参考,感兴趣的同学可以对该方案进行优化升级
特点
- 全自动化
- 普适性与可重用性,修改参数即可应用到不同设计中
自动化电路综合平台只需要用户将待综合的设计与库文件放入一个文件加,修改与带综合设计对象有关的环境变量参数,在命令窗唤醒DC的指令,即自动化地完成综合过程,并得到综合后的网表文件和所需报告
运行流程:
- 运行run.csh脚本,启动DC
#!/bin/csh -f
# 清除之前的文档
\rm -rf *.log *svf alib* reports log work
# 新建文件夹
mkdir reports work
# 启动DC并运行top.tcl
dc_shell-xg-t -32bit -f ./top.tcl
- 建立reports与work两个文件夹。reports文件夹存放报告,work存放文档和脚本
- 启动顶层脚本top.tcl
- top.tcl按先后顺序启动子脚本,最总生成script.tcl
- DC读取script.tcl中的约束,最总完成综合,并将所有报告写入reports文件夹中
top.tcl脚本运行机制:
- set_library.tcl:生成设定库文件中的search path的约束
- read_design.tcl:生成读入设计文件的约束
- create_clock.tcl:生成时钟源相关的约束
- set_rst.tcl:生成复位端口的约束
- set_io.tcl:生成输入输出端口的约束
- set_cons.tcl:生成保存门级网表、各种reports文件的约束
注意:
- 以上所有约束都自动生成,无需人为干预
- 库文件、代码、时钟、复位、输入输出等均根据代码自动进行匹配,并生成相应的约束
- 最终所有约束都被写入到script.tcl中,供DC读取,完成最终的逻辑综合过程
代码读入约束生成
工作流程:
- 设计文件通常使用verilog文件,所以拓展名通常为v,所以先将变量extension设为v
- 调用filelist.tcl脚本,将所有拓展名为v的文件的文件路径输出到一个名为v_list的文档
- 打开v_list文档,根据文件的内容读入设计文件的指令输出道道script.tcl脚本
set extension v
source[file join $::script_path test/filelist.tcl]
#调用filelist.tcl脚本
set des[open[file join $::script_path test/work/v—list]r]
set design [gets $des] #打开vlist文档
for{}{$design!=""}{set design [gets $des]}{
puts $script [format "read_file -format verilog %s"$deslgn]
#输出读入设计文件指令
}
puts $scnpt[format "current_design %s" $top]
#输出设置顶层设计指令
代码filelist生成模块filelist.tcl
功能:便利目标文件下所有文件,并将拓展名(.v)符合要求的文件完成路径输出到指定的文档,最终形成DC读取verilog代码的约束,写入script.tcl中
工作流程:
- 将工作路径切换到指定的工作路径
- 判断当前目录下的文件拓展名是否与设置的变量extension一直,如果一致,就将该文件路径输出到指定的文件
- 如果有文件夹,则递归调用本程序,直至结束
proc FindFile{myDirresult}{
if([catch {cd $WDir} err]}{
puts $result $err
return}
foreach myfile [glob-nocomplam *]{
cd $myDir #切换到对应路径
if{[string equal $myfile ""]}{
return} #如果是空文件夹就返回
set fullfile [file join $myDir $myfile]
if{[file isdirectory $myfile]}{
FindFile $fullfile $result #如果有下一级路径则递归调用本函数
}elseif{[string equal [file extension $fullfile] [format ".%s" $::extension]]){#判断扩展名是否与要求一致
puts $result $fullfile}}}
时钟约束生成子模块
功能和流程:
- 首先调用parameter.tcl脚本,读取其中用户对时钟源指定的参数,如时钟周期 等;
- 调用find_clk.tcl脚本,该脚本会将搜索顶层设计中的所有的clk端口,并将所有搜索结果输出到一个名为clk_list的文档;
- 打开clk_list档,将对时钟端口施加约束的指令输出到script.tcl脚本。
source [file join $::script_path test/findclk.tcl]
#调用find_clk.tcl脚本
set a [open [file join $::script_path test/work/clk_list] r]
#打开v_list文档
set b [gets $a]
set result [open[file join $::script_path test/work/script.tcl]
#DC时钟约束
for {} {$b!=""}{set b [gets $a]}{
puts $result [format "create_clock -name \"clock\" -period %u -waveform {0 %d}{ %s }" $::clk_source[expr $::clk_source/2]$b]
#将生成时钟源的指令输出到scnpt.tcl脚本
puts $result [format "set_dont_touch_network \[get_ports%s\]"$b]
#对时钟网络设置don't touch
puts $result [format "set_drive 0 \[get_ports%s\]"$b]
#设置时钟端口驱动为无穷大
puts $result [format "set_ideal_network \[get_ports%s\]"$b]
#设置时钟端为理想网线
}
close $result
匹配时钟端口子模块
功能:搜索代码中所有的时钟端口,将结果输出到work文件夹下的clk_list文档
工作流程
- 打开v-list文档,在其中找到顶层设计的路径,并打开设计文件;
- 利正则表达式匹配其中的clk端口,
- 并将匹配到的时钟端口的端口名输出到work文件夹下的clk_list文档
for {} {[eof $designfile]==0}{set fdesign [gets $designfile]}{
if{[regexp{input.*} $fdesign a]}{
#利用正则表达式匹配到声明输入端口那一行
if{[regexp {[^,( ]*clk[^,;]*}$a rport]}{
#利用正则表达式在那一行匹配后缀为clk的端口
puts $fport $rport
#将匹配到的端囗名输出到clk_list文档
}
}
}
- 其余脚本工作机制类似。
- 最终,所有的约束都被写入了script.tcl中。
- script.tcl脚本完全由自动化电路综合平台生成,并非人工编写;
- 在自动化电路综合平台运行后,由顶层脚本调用各子模块脚本生成该脚本。生成该脚本后,由顶层脚本调用该脚本,由此实现对设计的综合。
子模块脚本生成该脚本。生成该脚本后,由顶层脚本调用该脚本,由此实现对设计的综合。