用python实现分模块按cell类型统计cell个数并降序排列

2022-12-06 16:38:58 浏览数 (1)

有同学想看看综合网表里某模块里and、or、inv等cell的个数,谁最多谁最少。虽然用dc的各种命令组合也可以实现,但今天我们用python来实现。

因为verilog网表非常有规律,很容易用正则来匹配,所以用python来做统计正合适。之前写过一篇文章:《用Python提取Verilog网表层次和实例化关系》,这篇文章已经实现了网表parser,基于这个脚本做统计就非常简单了。

网表parser

用三条正则'modules (w )','s*(w )s (w )s*(','endmodule'来解析和拆分module、识别模块名、读取cell的类型和例化名。

代码语言:javascript复制
# netlistparser.py
import sys
import json
import re


def read_vlog_netlist(vlog_file):
    """
    get insts by module
    """
    
    vlog_lines = open(vlog_file, 'r').readlines()    

    module_start = 0
    modules = {}
    for line in vlog_lines:
        module_start_m = re.search('modules (w )', line)
        inst_m         = re.search('s*(w )s (w )s*(', line)
        module_end_m   = re.search('endmodule', line)
        
        if module_start_m:
            module_start = 1
            module = {}
            
            module_name = module_start_m.group(1)
            module['module_name'] = module_name

            insts = {}
            module['insts'] = insts

            modules[module_name] = module            
            
        elif module_end_m:
            module_start = 0

        elif module_start and inst_m:
            module_name = inst_m.group(1)
            inst_name = inst_m.group(2)
            insts[inst_name] = module_name

    return modules

if __name__ == '__main__':
    modules = read_vlog_netlist(sys.argv[1])
    print(json.dumps(modules, indent=4))

解析完成后,我们把数据放到dict里,方便存储成json,和进一步处理。格式如下:

代码语言:javascript复制
{
"moduleA": {
    "module_name": "moduleA",
    "insts": {
        "u_AND2_01": "AND2X1",
        "u_AND2_02": "AND2X1",
        "u_OR2_01": "OR2X1",
        "u_INV_01": "INVX1"        
    }
},
"moduleB": {
    "module_name": "moduleB",
    "insts": {
        "u_AND2_01": "AND2X1",
        "u_AND2_02": "AND2X1",
        "u_OR2_01": "OR2X1",
        "u_INV_01": "INVX1"        
    }
},
}

统计cell类型和个数

从网表parser的数据dict里分模块取出module,遍历insts,在字典cell_count用cell类型做key存放cell的计数。

代码语言:javascript复制
# cellinfo.py
import sys
import netlistparser as nlparser
import re
import json

def count_cells(modules):
    cells_info = []
    
    module_names = modules.keys()
    for module_name in module_names:
        cell_count = {}
        insts = modules[module_name]['insts']
        for inst in insts:
            cell_inst = inst
            cell_type = insts[inst]
            if cell_type in cell_count:
                cell_count[cell_type] = cell_count[cell_type]   1
            else:
                cell_count[cell_type] = 1
        # sort by cell_type
        cell_count2 = dict_sort_by_val(cell_count)
        
        cells_info_module = {module_name : cell_count2}
        cells_info.append(cells_info_module)
        
    return cells_info

其中用了一个函数,按字典的value排序:dict_sort_by_val(),如下,先把dict转成list,用sorted对list排序,排序后再转为dict。

代码语言:javascript复制
def dict_sort_by_val(d):
    keys = d.keys()
    values = d.values()
    l = [(key, val) for key, val in zip(keys, values)]
    l2 = sorted(l, key=lambda x:x[1], reverse=True)
    d2 = {}
    for k,v in l2:
        d2[k] = v
        
    return d2

写顶层调用:

代码语言:javascript复制
if __name__ == '__main__':
    vlog_netlist_file = sys.argv[1]

    print('Read {} ...'.format(vlog_netlist_file))
    modules = nlparser.read_vlog_netlist(vlog_netlist_file)
    
    cells_info = count_cells(modules)
    print(json.dumps(cells_info, indent=4))

最终效果如下:

代码语言:javascript复制
[
    {
        "cv32e40p_clock_gate": {
            "CKLNQD12BWP": 1
        }
    },
    {
        "cv32e40p_sleep_unit_PULP_CLUSTER0": {
            "DFCNQD1BWP": 2,
            "OR2D1BWP": 1,
            "OR4D1BWP": 1,
            "OA21D1BWP": 1,
            "cv32e40p_clock_gate": 1,
            "INR3D0BWP": 1
        }
    },
    {
        "cv32e40p_prefetch_controller_PULP_OBI0_PULP_XPULP0_DEPTH2_DW01_add_1": {
            "CKND2D1BWP": 23,
            "NR2XD0BWP": 18,
            "INVD1BWP": 17,
            "XOR2D1BWP": 15,
            "XNR2D1BWP": 9,
            "HA1D0BWP": 4,
            "HICIND1BWP": 1
        }
    },
    {
        "cv32e40p_prefetch_controller_PULP_OBI0_PULP_XPULP0_DEPTH2": {
            "INVD1BWP": 38,
            "DEL100D1BWP": 24,
            "AO32D0BWP": 13,
            "AOI32D0BWP": 10,
            "CKND2BWP": 9,
            "ND3D3BWP": 9,
            "OAI221D1BWP": 8,
            "ND2D1BWP": 8,
            ...
    },
    ...
]

0 人点赞