关键字:Verdi EDA 自动化 TCL 驱动 脚本 NPI
目录
- 前言
- 什么是NPI?
- 应该使用哪个NPI?
- 示例
-
- Verilog
- TCL
- 运行
-
- 调试
- 常态化运行
- 总结
-
- 关于示例
- 关于NPI
- 其他
前言
不知道大家是否遇到过,至少我经常有这样的需求:想要自动抓出某个信号的所有驱动,利用命名规则之类的做一些过滤之后做一些自动化处理;
网上到处搜索却没有查到方法,只能考虑如何自己做;但是这种事用脚本做起来并不容易,verilog语法如此复杂,没办法使用python/perl之类的通过一些正则表达式就可以抓到自己想要的结果,就算抓出来了一些,也无法确保真的完备,甚至有明显的遗漏;而针对自己的coding style就算抓全了,也无法确保以后长期可以使用。
我甚至想过利用python写一个简单的verilog编译器,后来了解到一些开源内容的复杂度后放弃了。但这个想法也给了我一个思路,我们不就有一个现成的编译器吗?VCS/Verdi一定有这样的功能,否则我们也不可能在RTL界面双击信号就可以看到它的驱动有哪些。
那么就只剩一个问题了,Synopsys有没有对外开放这些接口呢?
很幸运,有的。
通过四处查阅Verdi的文档,我找到了Verdi提供的有这样功能的接口,Synopsys称之为”NPI”,也就是Native Programming Interface.。
什么是NPI?
可以简单地认为是Synopsys官方提供的一套功能接口,可以让用户调用实现特定的自动化功能;例如上面提到的trace driver/load,还有抓取parameter、port信息等等,内容非常庞杂;同时支持C接口和TCL接口,整个文档高达2459页(Verdi2016版本),包含了Language model,Netlist Model,Text Model,Power Model,FSDB Model,Coverage Model等等非常多的功能。
更多的时候,我是将其当作一个工具书来查找自己需要的功能。如有需要,各位可以在给"老王谈谈芯"公众号发消息“Verdi NPI文档”来获取完整的内容。
我们今天就以trace driver为例,来讲解一下TCL接口的使用。
应该使用哪个NPI?
在Verdi官方的NPI手册中,我们可以查阅到,有一个名为npi_trace_driver的NPI,其简介是这样描述的:
图1. npi_trace_driver功能简介
也就是可以给这个API输入一个信号的完整路径,获得其所有的driver;其输出的driver在TCL中会以一个list的形式返回。 显然我们需要的就是这样的接口。
关于函数简介和参数说明如下:
图2. npi_trace_driver TCL API函数说明
即,我们在TCL中调用这个函数,输入一个信号的完整路径,和一个空的list,调用这个函数之后,这个空的list里面就会被填充所有该信号driver的句柄/handle。
注意,这里list中得到的是句柄,而非人能直接读取的信息,因此还需要通过另一个NPI:npi_ut_get_hdl_info来获取这个句柄的详细信息,这个API的功能简介和参数说明如下:
图3. npi_ut_get_hdl_info 功能简介
图4. npi_ut_get_hdl_info接口参数说明
通过这个NPI,我们可以把一个句柄,转化为人能读取的具体信息,这个信息会包含变量类型、变量完整路径、文件名和行号;按照以下格式给出:
图5. npi_ut_get_hdl_info返回结果示例
好了,到此为止,我们已经有了需要的所有信息,接下来,让我们搭建一个示例看看效果。
示例
Verilog
先写一个简单的verilog module,就是对两个输入a和b,a敲2T,b敲1T,与起来送到输出端口c上,代码如下:
图6. 示例verilog代码
TCL
再根据上面的内容写出TCL代码,因为我们并不只需要输入信号的一层驱动,而是不断往上追溯,得到驱动的驱动、驱动的驱动的驱动……因此需要一个递归来不断trace driver,所以我写了一个get_driver的函数;
图7. trace driver TCL脚本示例
具体的代码功能在注释中都有写出,如果有问题欢迎在评论区提出。
上面只是一个非常简单的示例,但是已经展示了重点的信息,在此基础上,如果有任何定制化的需求,都可以通过加入一些字符串处理或者判断等方式实现;
例如,追踪到module port结束、DFF结束、常数结束,或者根据驱动层级格式化输出等等。
运行
代码都有了之后,接下来就是运行了;我们把运行分为两类,调试和常态化执行;
- 调试,即需要即时根据结果修改脚本,这种时候,我们是需要一个即时运行、显示结果和调试的窗口的;
- 常态化执行,则需要一个可以静默运行,固定输出的方式,自动化执行过程中一般不需要打开Verdi的GUI。
调试
调试的时候,首先要做的,是打开Verdi的TCL输入窗口,毕竟我们不想每运行一次都需要等待一次Verdi的license和启动时间。
依次到 Tool -> Preferences -> General下,勾选Enable TCL Command Entry Form即可,如下图所示
图8. 打开Verdi TCL调式窗口流程
之后会打开下面这样一个窗口(基于Ubuntu 16.04系统Verdi2016,不同版本可能长的不太一样)
图9. Verdi TCL调试窗口
在这个窗口中,输入source ./trace_driver.tcl回车,即可执行我们的TCL脚本。
我们执行上面的脚本,可以在Terminal中得到下面的结果
图10. trace driver TCL脚本输出结果
可以对于每个信号,可以追到所有的driver(例如in_a_d2,同时追到了reset为0和in_a_d1);同时最顶层的port是没有驱动的(如in_a)
实际调试中,报错会显示在TCL Command Entry窗口中,puts的输出结果会显示在Terminal窗口中(同上,基于Ubuntu 16.04系统Verdi2016,不同版本可能不一样)。
常态化运行
verdi可以通过启动时的选项直接执行TCL脚本的,可以使用如下的命令:
verdi xxx.v -play trace_driver.tcl -nogui
即可静默执行所需的TCL了;其中**-nogui**目的就是不弹出Verdi的窗口。
不过有一点需要注意,因为之前的TCL脚本最终没有exit,verdi执行完之后会停住但不退出,因此在常态化运行时,需要在TCL脚本最后补上一句exit。
执行效果如下图所示:
图11. Verdi常态化运行TCL脚本效果示意图
总结
以上,便是如何使用Verdi来trace特定信号driver的方法和简单的示例。在此再次说明一下:
关于示例
以上实例只是简单的功能演示,但是关键方法已经有了,在此基础上,各位可以通过TCL实现自己需要的各种格式化输出或过滤,甚至可以直接输出到txt后由Python等更友好的脚本语言实现更酷炫的展示效果,在此就不进一步展开了。
关于NPI
NPI是一个非常强大的功能,Verdi在其中提供了一个非常庞大的功能库,trace driver只是一个出于我自己最开始的需求出发的简单示例,除此之外,trace load也是类似的方法;还可以有port、module,甚至netlist、fsdb、coverage等等层面的处理,大家可以根据自己的需要查询Verdi的NPI手册。 可以在微信公众号"老王谈谈芯"聊天窗口发送消息“Verdi NPI手册”来获取Verdi2016的NPI手册下载链接,希望对大家有所帮助。
其他
本文只是我个人的经验分享,如果您发现了任何问题或者有任何建议,欢迎随时通过任何方式和我说明
最后,欢迎大家分享实际遇到的,可以用NPI解决的问题;你之前了解过这个工具吗?有实际使用过吗?
以及,是否还有其它常遇到的痛点问题?






