虽然dc也有report_area -hier命令来报告各级模块的面积,本python方案看似有点造轮子,但还是有一定的便利性。一、不受网表类型的限制,综合网表、dft网表、apr都可以。二、可以过滤面积小于指定值的小模块,比如工具自动插入的icg模块。三、还可以根据面积占比做排序,方便分析面积的瓶颈。
一、读入网表
下面先读入网表,并分模块识别每个模块内部的stdcell和子模块。这部分与《用python实现分模块按cell类型统计cell个数并降序排列》的方法相同,所以这里直接导入netlistparser.py。
import netlistparser as nlparserimport sysvlog_netlist_file = sys.argv[2]modules = nlparser.read_vlog_netlist(vlog_netlist_file)
这样网表就读到了内部python字典里,结构如下:
{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 }},}
二、读入lib库
stdcell的面积信息存储在fab提供的lib文件里,所以我们需要从lib里读到每种cell的面积,方法如下:
# libparser.pyimport sysimport reimport jsondef read_library(file_name): cells = {} lib_lines = open(file_name, 'r').readlines() cell_start = 0 pin_start = 0 total_lines = len(lib_lines) print('') for i in range(total_lines): line = lib_lines[i] print('33[1f {}%'.format(round(100 * i / total_lines))) cell_s_m = re.search(r'cells*((w+))s+{', line) area_m = re.search(r'sareas+:s+(s+)s*;', line) pin_s_m = re.search(r'spin((w+))s+{', line) dir_m = re.search(r'sdirections+:s+(w+)', line) func_m = re.search(r'sfunctions+:s+(.*)', line) end_m = re.search(r'}', line) if cell_s_m: cell_start = 1 cell = {} cell_name = cell_s_m.group(1) cell['cell_name'] = cell_name pins = [] cell['pins'] = pins cells[cell_name] = cell if cell_start and area_m: area = area_m.group(1) cell['area'] = round(float(area), 4) if cell_start and pin_s_m: pin_start = 1 pin = {} pin_name = pin_s_m.group(1) pin['pin_name'] = pin_name if cell_start and dir_m: pin_dir = dir_m.group(1) pin['pin_dir'] = pin_dir if cell_start and func_m: pin_func = func_m.group(1) pin['pin_func'] = pin_func if cell_start and pin_start and end_m: pin_start = 0 pins.append(pin) return cellsdef get_cell_area(cells, cell_name): if cell_name in cells: return cells[cell_name]['area'] else: return 0def is_libcell(cells, cell_name): if cell_name in cells: return true else: return falsedef write_lib_info(lib_info, file_name): f = open(file_name, 'w') f.write(json.dumps(lib_info, indent=4)) f.close()
其中,read_library()函数实现了用正则读取lib文件里的cell名字、area、pin、pin方向、function等信息。今天只需要用到cell名字和面积。其它信息是为了后续扩展其它功能做准备。
get_cell_area()提供了读取指定cell面积的接口。is_libcell()实现了判断是libcell还是一般的设计上的子模块。
write_lib_info()可以将lib库的字典写到json文件里,方便调试。
接下来,用这个libparser读入lib库:
import libparserimport syslib_file = sys.argv[1]lib_info = libparser.read_library(lib_file)
三、面积递归统计
我们从top design开始,当遇到stdcell中的cell则累加,当遇到子模块则递归。直到子模块不再含有其它子模块(仅由stdcell组成)时,则返回。
area_info = {}def report_area(modules, lib_info, module_name): global area_info area = 0 insts = modules[module_name]['insts'] for inst in insts: cell_inst = inst cell_type = insts[inst] if cell_type in area_info: area = area + area_info[cell_type] elif libparser.is_libcell(lib_info, cell_type): area = area + libparser.get_cell_area(lib_info, cell_type) else: # 递归 report_area(modules, lib_info, cell_type) area = area + area_info[cell_type] area_info[module_name] = area
四、打印面积
打印的同时,可以做一些过滤或者排序。
for module in area_info: if not re.search(r'clock_gate', module): print(module, round(area_info[module], 4))
效果如下:
学会文件缓存回写的过程
AT&T正式公布了2020年边缘计算发展的三大策略
华为鸿蒙系统公测申请入口
校园安防是一直都是智能安防建设中不可忽视的一部分
如何使用Arduino中断
用python实现网表分模块统计面积
电感原理图与线圈的原理作用和磁芯的磁化和磁导率分析
采用模块化方法处理高精度、高电流电池测试设备
降低输出纹波与噪声常用办法介绍
自动驾驶在数据中心营维的实现
TI无线连接技术选择指南介绍
随着人们对网络信息系统依赖性增强 网络攻击事件的数量不断增多
笔记本维修资料
苹果 M1 Mac重新支持侧载 iPhone 和 iPad 应用
5G基站给电源设计者带来什么新挑战
ZLG致远电子推进ZigBee在智能LED灯具的应用
大朋VR更具沉浸式的真4K影音游戏体验
能自己发电的圆形发电机原理分析
基于3GPP的标准将会成为全球统一的5G标准
数据库编程大赛:一条SQL计算扑克牌24点