在模拟芯片开发的最后集成后的检视中,大部分是人工检视模块之间的连线是否正确。
但是在EDA工具中进行检视,往往比较费时费力——需要大量的鼠标操作。而且检视结束,没有办法输出检视的交付件。
为了解决这个问题,制作了一个cdl网表的解析工具,能输出模块于模块间连线的报表。
表格中1列放置起点模块的引脚,另外一列放置相连的终点模块的终点。
本文所处理的cdl网表来自于模拟EDA工具导出。
cdl文件定义了所有模块的定义。模块之间的例化关系,也都在模块内的例化模块表述。
.SUBCKT my_module input1 input2 output
R1 input1 net1 / 10k
R2 net1 input2 net2 / 20k
C1 net2 output / 1nF
.ENDS my_module
cdl网表中使用.SUBCKT和.ENDS定义一个module。
示例中my_module就是定义的模块名。它内部例化了R1、R2、C1三个模块。R1为例化名,对应的module名为10k。
试着从input1看一下,它是如何连接到内部的例化模块:my_module的input1连接到了R1的第一个引脚,R1的第二个引脚连接net1的连线;顺着net1搜索,可以看到R2的第一个引脚连接到net1。cdl网表中就是这样表述模块之间的连接。每一个连线都是单bit的(这比分析verilog代码变的容易很多)。
这样我们就可以遵照这种追踪的方法,搜索起点到终点的连线(先从简单的直接连接的来分析,文章最后再说一下,穿透部分模块的思路)
解析的代码可以使用IA辅助生成,然后修改。
AI的提示词如下:
写一个脚本,读取cdl网表文件,并能提取里面模块名,以及模块之间的嵌套关系。脚本使用argparse,输入cdl文件路径。代码注释都用英文。cdl文件中每个例化模块的定义以“.SUBCKT "为开头,以”.ENDS"结束,“.SUBCKT "和”.ENDS"可能在不同的行。在“.SUBCKT "加空格之后的第一个词就是例化名,例化名之后就是连线wire的名称,这些词都用空格隔开;提取模块名子需要匹配“.SUBCKT "后面的第一个词即可;wire名换行之后行头都有字符"+";例化定义中行头为"*.PININFO "的模块端口的定义,端口定义形式为“端口名:端口方向”,多个端口用空格隔开。在例化模块定义内,行头为+,表示这一行是上一行的连续内容。在例化模块定义内,二级例化模块的行头首个字符为字母,后续紧跟的二级例化模块的连线名,行尾巴包含“/"的就是二级模块的模块名;如果行尾没有”/",但是在行中包含"=",则在包含=的前一个词,即为模块名。二级模块的内容也可能是多行的。
备注:生成出来的代码还是有些小问题,还需要人工修改。有些细节的需求,我也不知道如何写才能让AI按照我的想法写脚本。
提取后的数据以python的字典存储,示例如下。
{ "my_module":{
"pins":{
"input1":"I",
"input2":"I",
"output":"O"},
"instances": {
"R1":{"wires":["input1", "net1"], "module_name":"10k"},
"R2":{"wires":["net1","input2","net2"], "module_name":"20k"},
"C1":{"wires":["net2","output"], "module_name":"1nF"}
}
},
"10k": {
"pins":{ "min":"B", "plus":"B" }
},
"20k": {
"pins":{ "min":"B", "adj":"B", "plus":"B" }
},
"1nF": {
"pins":{ "node1":"I", "node2":"O" }
}
}
在第1部分已经简单的描述了抽取一个模块内的连接关系。但是提取不同例化层级之间的模块连线,就还需要一些额外的信息:起点和终点的例化层级。
代码层级
例如,我们要抽取从U1到U4的连线关系。
那就需要知道U1的例化层级:TOP.U0.U1,以及其module name;U2的例化层级:TOP.U0.U1.U2.U3.U4,以及其module name。
知道了U1和U4在系统的位置,那就可以推断出从U1查看与U2的关系,然后再U2中查看与U3的连线关系,U3再向下查看与U4的连线关系。就像剥洋葱一样,一层一层的分析。以此方法遍历U1的每个pin,最终就能知道U1和U4的哪些端口是直连的(中间没有过其他模块)。
还有另外一种分叉路径关系,处理就要复杂一点:
从U1到U4,就需要在U0下面平级查找到U2,然后再检查U4。
对于这种情况,就需要知道U1和U4在整个层级上是在U0汇合。
对于一些简单的电阻或者反相器、buffer驱动,这种一进一出的模块,可以简单的穿透。
穿透的方法,就是找到此类模块的一个pin,然后从另一个pin再继续查看。
对于需要透传的模块,还需要额外建立一个字典类存储。
对于生成报告,还需要做一些合并显示。例如总线会在cdl中打散为单bit的信号,这些需要尽可能的合并显示,减少检视的工作量。
有了这种表格的报告方式,还可以增加一些自动判断的脚本,筛选一些高风险的连线关系,例如不同命,或者属性不匹配的连接,提高检视的效率。
对于普通的信号路径遍历,还是很快,但是对于模拟电路中的电源和地信号,因为涉及的范围很广,遍历效率就会比较低。可以通过预置一些开关——当开关打开时,可以跳过电源和地信号,快速分析业务信号。