搜档网
当前位置:搜档网 › Tcl在Vivado中的应用

Tcl在Vivado中的应用

Tcl 在Vivado 中的应用

Xilinx?的新一代设计套件Vivado 相比上一代产品ISE ,在运行速度、算法优化和功能整合等很多方面都有了显著地改进。但是对初学者来说,新的约束语言XDC 以及脚本语言Tcl 的引入则成为了快速掌握Vivado 使用技巧的最大障碍,以至于两年多后的今天,仍有很多用户缺乏升级到Vivado 的信心。

本文介绍了Tcl 在Vivado 中的基础应用,希望起到抛砖引玉的作用,指引使用者在短时间内快速掌握相关技巧,更好地发挥Vivado 在FPGA 设计中的优势。

Tcl 的背景介绍和基础语法

Tcl (读作tickle )诞生于80年代的加州大学伯克利分校,作为一种简单高效可移植性好的脚本语言,目前已经广泛应用在几乎所有的EDA 工具中。Tcl 的最大特点就是其语法格式极其简单甚至可以说僵化,采用纯粹的 [命令 选项 参数] 形式,是名副其实的“工具命令语言”( 即Tcl 的全称Tool Command Language )。

实际上Tcl 的功能可以很强大,用其编写的程序也可以很复杂,但要在Vivado 或大部分其它EDA 工具中使用,则只需掌握其中最基本的几个部分。

注: 在以下示例中,% 表示Tcl 的命令提示符,执行回车后,Tcl 会在下一行输出命令执行结果。 // 后是作者所加注释,并不是例子的一部分。

设置变量

打印

打印主要通过puts 语句来执行,配合特殊符号,直接决定最终输出内容。

% set myVar “Hello World!” //设置一个名为myVar 的变量,其值为Hello World!

% puts $myVar Hello World! % puts “Hello World!” Hello World!

% puts myVar myVar % puts {$myVar} $myVar

% puts “\$myVar ” $myVar

文件I/O

写文件

读文件

可以看到Tcl 对文件的操作也是通过设置变量,改变属性以及打印命令来进行的。上述写文件的例子中通过puts 命令在my_file.txt 文件中写入两行文字,分别为“Hello World!” 和myVar 变量的值,然后在读文件操作中逐行读取同一文件的内容。

控制流和循环命令

Tcl 语言中用于控制流程和循环的命令与C 语言及其它高级语言中相似,包括if 、while 、for 和foreach 等等。

具体使用可以参考如下示例,

%set wfp [open “my_file.txt” w] file1073b243 %puts $wfp “Hello World!” %puts $wfp $myVar %close $wfp

%set rfp [open “my_file.txt” r] file10 %set file_data [read $rfp] Hello World! Hello World! %close $rfp

% if {$myVar != 1} {puts “Sweet!”} //判断myVar 变量的值,若不等于1就打印Sweet ! Sweet!

% if {$myVar == 1} { puts “$myVar is = 1” } else { puts “$myVar is != 1”} //多条件判断 Hello World is != 1

% foreach x $myVar {puts $x} //循环读取myVar 变量的值并打印 Hello World!

% set x 1 //设置变量x 1

% while {$x < 5} { puts “x is $x ”; set x [expr {$x + 1}] } //判断变量的值, 打印,变量再赋值。 x is 1

子程序/过程

Tcl 中的子程序也叫做过程(Procedures ),Tcl 正是通过创建新的过程来增强其内建命令的能力,提供更强的扩展性。具体到Vivado 的使用中,用户经常可以通过对一个个子程序/过程的创建来扩展或个性化Vivado 的使用流程。

一些特殊符号

% proc myProc {var} { //创建一个新的子程序(过程)myProc ,用来打印输入变量的值。 puts $var }

% myProc “Yay!” //调用子程序(过程) Yay!

% set flop_name “flop1” //字符串 flop1

% set myVar “flop_name” //没有置换变量 flop_name % set myVar “$flop_name” //变量置换 flop1

% set myVar {$flop_name} //$代表其本身 $flop_name

% set myVar “\$flop_name” //反斜杠置换 $flop_name

%set myVar \ //反斜杠允许命令出现在多行 “$flop_name” flop1

Tcl语言的基本语法相对简单,但要熟练掌握仍需日常不断练习。Xilinx网站上有很

多相关资料,这里推荐两个跟Tcl相关的文档UG835和UG894,希望对大家学习Vivado

和Tcl有所帮助。

在Vivado中使用Tcl定位目标

在Vivado中使用Tcl最基本的场景就是对网表上的目标进行遍历、查找和定位,这

也是对网表上的目标进行约束的基础。要掌握这些则首先需要理解Vivado对目标的分类。目标的定义和定位

如上图所示,设计顶层的I/O称作ports,其余底层模块或是门级网表上的元件端口

都称作pins。而包括顶层在内的各级模块,blackbox以及门级元件,都称作cells。连线称

作nets,加上XDC中定义的clocks,在Vivado中一共将网表文件中的目标定义为五类。

要选取这五类目标,则需用相应的get_*命令,例如get_pins等等。

get_ports

ports仅指顶层端口,所以get_ports的使用相对简单,可以配合通配符“* ”以及Tcl

语言中处理list的命令一起使用。如下所示,

get_ports A // 仅列出叫做A的顶层端口

get_ports * //列出所有顶层端口

get_ports *data*//列出所有名字中含有“data” 的顶层端口

get_cells/get_nets

不同于ports 仅指顶层端口,要定位cells 和nets 则相对复杂,首先需要面对层次的问题。这里有个大背景需要明确:Vivado 中Tcl/XDC 对网表中目标的搜索是层次化的,也就是一次仅搜索一个指定的层次current_instance ,缺省值为顶层。

以右图所示设计来举例,若要搜索A (不含a1,a2)层次内的所有cells 和名字中含有nt 的nets , 有两种方法:

若要将搜索层次改为A+B+b1,则可以写一个循环,逐一用current_instance 将搜索层次指向A ,B 和b1,再将搜索到的cells 或nets 合成一个list 输出即可。

若要将搜索层次改为当前层次以及其下所有子层次,可以使用 -hierarchical (在Tcl 中可以简写为-hier )

llength [get_ports *] // 列出设计中所有顶层端口的数量

lindex [get_ports *data*] 0 // 列出名字中含有 “data” 的顶层端口中的第一个 foreach x [get_ports *] {puts $x} // 逐一打印出所有顶层端口

get_cells -hierarchical * //搜索Top 层以及其下所有子层次内的所有cells

get_nets -hier *nt* //搜索Top 层以及其下所有子层次内的名字中含有nt 的nets current_instance A //修改搜索层次到A

get_cells -hier * //搜索A 以及其下所有子层次内的所有cells

get_nets -hierarchical *nt* //搜索A 以及其下所有子层次内的名字中含有nt 的nets current_instance //修改搜索层次到缺省值Top

在使用-hierarchical 时有一点需要特别留意,即后面所跟的搜索条件仅指目标对象的名字,不能含有代表层次的“/” 。 下面列出的写法便是一种常见的使用误区,并不能以此搜索到A 及其下子层次内所有的cells 。

get_pins

pins 在Vivado 数据库中有个独特的存在形式,即 / 。这里的“/”不表示层次,而是其名字的一部分,表示这个pin 所属的实体。也就是说,在使用get_pins 配合-hier 来查找pins 时,“/”可以作为名字的一部分,出现在搜索条件内(注意与上述get_cells 和get_nets 的使用区别)。

目标之间的关系

Tcl 在搜索网表中的目标时,除了上述根据名字条件直接搜索的方式,还可以利用目标间的关系,使用-of_objects (在Tcl 中可以简写为-of )来间接搜索特定目标。

Vivado 中定义的五类目标间的关系如下页左图所示。

以上示右图的设计来举例,

下图是一个更复杂的示例,涉及跨层次搜索。可以看到在get_pins 时,要加上-leaf 才能准确定位到门级元件(或blackbox )的端口q 。另外,在实际操作中,使用get_nets 和get_pins 时,需要视情况而加上其它条件(-filter )才能准确找到下述例子中的cells (i2)。

高级查找功能

在使用get_*命令查找网表中的目标时,除了名字这一直接条件,往往还需要辅以其它更复杂的条件判断,这就需要用到高级查找功能:-filter结合Tcl支持的各种关系和逻辑运算符(==, !=, =~, !~, <=, >=, >, <, &&, ||)甚至是正则表达式来操作。

在创建子程序时也常常用到-filter,例如下述get_p的子程序/过程就可以用来返回指定管脚的方向属性,告诉用户这是一个输入管脚还是一个输出管脚。

Tcl在Vivado中的延伸应用

Tcl在Vivado中的应用还远不止上述所列,其它常用的功能包括使用预先写好的Tcl 脚本来跑设计实现流程,创建高级约束(XDC不支持循环等高级Tcl语法)以及实现复杂的个性化设计流程等等。Tcl所带来的强大的可扩展性决定了其在版本控制、设计自动化流程等方面具有图形化界面不能比拟的优势。

Vivado在不断发展更新的过程中,还有很多新的功能,包括ECO、PR、HD Flow等等都是从Tcl脚本方式开始支持,然后再逐步放入图形化界面中实现。这也解释了为何高端FPGA用户和熟练的Vivado用户都更偏爱Tcl脚本。

篇幅所限,不能一一展开。关于以上Tcl在Vivado中的延伸应用,敬请关注Xilinx 官方网站和中文论坛上的更多技术文章。

Ally Zhou2014-9-12 于Xilinx上海Office

相关主题