python抽取cdl网表的连线关系

在模拟芯片开发的最后集成后的检视中,大部分是人工检视模块之间的连线是否正确。

但是在EDA工具中进行检视,往往比较费时费力——需要大量的鼠标操作。而且检视结束,没有办法输出检视的交付件。

为了解决这个问题,制作了一个cdl网表的解析工具,能输出模块于模块间连线的报表。

表格中1列放置起点模块的引脚,另外一列放置相连的终点模块的终点。

1、谈一下对cdl网表的理解

本文所处理的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代码变的容易很多)。

这样我们就可以遵照这种追踪的方法,搜索起点到终点的连线(先从简单的直接连接的来分析,文章最后再说一下,穿透部分模块的思路)

 

2、解析cdl网表

解析的代码可以使用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" }
   }   
}

 

 

3、提取路径

在第1部分已经简单的描述了抽取一个模块内的连接关系。但是提取不同例化层级之间的模块连线,就还需要一些额外的信息:起点和终点的例化层级。

 

python抽取cdl网表的连线关系_第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的哪些端口是直连的(中间没有过其他模块)。

还有另外一种分叉路径关系,处理就要复杂一点:

python抽取cdl网表的连线关系_第2张图片

 

从U1到U4,就需要在U0下面平级查找到U2,然后再检查U4。

对于这种情况,就需要知道U1和U4在整个层级上是在U0汇合。

4、模块的透传

对于一些简单的电阻或者反相器、buffer驱动,这种一进一出的模块,可以简单的穿透。

穿透的方法,就是找到此类模块的一个pin,然后从另一个pin再继续查看。

对于需要透传的模块,还需要额外建立一个字典类存储。

5、报告的样式

对于生成报告,还需要做一些合并显示。例如总线会在cdl中打散为单bit的信号,这些需要尽可能的合并显示,减少检视的工作量。

有了这种表格的报告方式,还可以增加一些自动判断的脚本,筛选一些高风险的连线关系,例如不同命,或者属性不匹配的连接,提高检视的效率。

6、遍历效率

对于普通的信号路径遍历,还是很快,但是对于模拟电路中的电源和地信号,因为涉及的范围很广,遍历效率就会比较低。可以通过预置一些开关——当开关打开时,可以跳过电源和地信号,快速分析业务信号。

 

你可能感兴趣的:(芯片开发随笔,python,数据结构,开发语言,嵌入式硬件)