用python实现一个verilog网表Parser(一)
专栏:ExASIC Nov. 10, 2024, 1:36 p.m. 302 阅读
做一个Verilog网表Parser

在工作中经常需要对网表进行分析、统计、修改,而现有的EDA工具却往往不够灵活。其实我们自己也可以用python来实现这个功能。今天我们来实现第一步,先做一个Verilog网表Parser。

分析网表的结构和组成

下面是一个简化的网表,但是却包括完整的语法结构。

module xor4 (a , b , c);
input  [3:0] a ;
input  [3:0] b ;
output  [3:0] c ;


XOR U0 (.A2 ( b[0] ) , .A1 ( a[0] ) , .Y ( c[0] ) ) ;
XOR U1 (.A2 ( b[1] ) , .A1 ( a[1] ) , .Y ( c[1] ) ) ;
XOR U2 (.A2 ( b[2] ) , .A1 ( a[2] ) , .Y ( c[2] ) ) ;
XOR U3 (.A2 ( b[3] ) , .A1 ( a[3] ) , .Y ( c[3] ) ) ;
  
endmodule


module xor8 (a, b, c);
input [7:0] a ;
input [7:0] b ;
output [7:0] c ;

xor4 U0 (.a(a[3:0]), .b(b[3:0]), .c(c[3:0]));
xor4 U0 (.a(b[7:4]), .b(b[7:4]), .c(c[7:4]));

endmodule

可以看到:

  1. Verilog网表总是由若干个module组成

  2. 每个module由模块名字、端口、内部wire定义(可选)、实例化(其它设计模块或者标准单元库模块)等几部分组成

  3. 端口由端口列表、位宽、方向等信息组成

  4. 实例化由模块名、例化名、端口连接组成

定义网表数据结构

端口

端口的数据结构:端口名字、方向、类型、最高位、最低位。具体如下:

class t_port:

    def __init__(self):
        self.name = "default"
        self.direction = "input"
        self.wire_type = "wire"
        self.msb = 0
        self.lsb = 0

连线

连线的数据结构:连线的名字、连接关系。具体如下:

class t_wire:

    def __init__(self, name):
        self.name = name
        self.conn = []

一根连线可以连接到多个pin或port,所以用列表来存储。

实例化

实例化的数据结构:实例化名字、模块名、端口映射关系。具体如下:

class t_inst:

    def __inst__(self, name):
        self.name = name
        self.module_name = "default"
        self.port_map = []

端口映射关系是多组"端口<->连线"对,因而也用列表存储。

模块

模块的数据结构:模块名、端口列表、连线列表、实例化列表。具体如下:

class t_module:

    def __init__(self, name):
        self.name = name
        self.ports = []
        self.wires = []
        self.insts = []

顶层模块与普通的模块并无差异,只是没有被实例化而已。这个角度看,如果没有冗余模块时,就可以自动分析出顶层模块。否则就需要额外指定顶层模块名字。

感谢阅读,更多文章点击这里:【专栏:ExASIC】
最新20篇 开设专栏