热度 1| |||
library file 是 IC 设计中一种重要的数据文件,用于记录标准单元(及 memory)的 timing /power/noise等 信息。
library file 遵循 liberty format,对于有 K 库需求的公司而言,K 库质量是芯片 qualify 的重要保证,因此有一些额外的手段对 library file 进行充分的分析和验证十分必要,这样的工作都依赖于一个健壮的 liberty parser。
现在可以公开检索到的 liberty parse 不多,利用 python 语言编写的更少,(为什么特别提到 python,因为 python 现在是 IC 公司自动化流程及 inhouse-tool 开发的主流语言),因为在实际工作中有这样的需求,因此本文利用 python3 开发了一个 liberty parser,并将之用到了公司一系列工具之中,效果不错,本着开放互助的原则在此分享给大家。
工具github 地址为 https://github.com/liyanqing1987/libertyParser。
可以采用git clone的方式下载源代码。
[liyanqing@cmp1 tools]$ git clone https://github.com/liyanqing1987/libertyParser.git Cloning into 'libertyParser'... remote: Enumerating objects: 39, done. remote: Counting objects: 100% (3/3), done. remote: Compressing objects: 100% (3/3), done. remote: Total 39 (delta 0), reused 1 (delta 0), pack-reused 36 Unpacking objects: 100% (39/39), done.
也可以采用Download ZIP的方式下载源码压缩包。
libertyParser 下载下来以后包括以下内容。
[liyanqing.1987@n212-206-207 libertyParser]$ ls examples libertyParser.py LICENSE README
其中examples 是示例目录,其中包含一个 library 文件范例 example.lib 和一个使用脚本范例 example.py。
libertyParser.py 包含了核心代码,包括 parser 和一些实用的 function。
LICENSE文件是许可证授权文件。
README 文件中则对 liberty parser 的基本原理和代码结构做了详细说明。
下面看一下example目录中的内容。
example.py
#!/usr/bin/env python3import osimport reimport sys os.environ["PYTHONUNBUFFERED"]="1"cwd = os.getcwd() upperLevelPath = os.path.dirname(cwd) sys.path.append(upperLevelPath)import libertyParser################# Main Process #################def main(): libFile = './example.lib' print('') print('>>> Input file: ' + str(libFile)) myLibertyParser = libertyParser.libertyParser(libFile) unitDic = myLibertyParser.getUnit() print('') print('>>> Unit:') print(unitDic) cellList = myLibertyParser.getCellList() print('') print('>>> Cell list:') print(cellList) cellAreaDic = myLibertyParser.getCellArea() print('') print('>>> Cell area:') print(cellAreaDic) cellLeakagePowerDic = myLibertyParser.getCellLeakagePower() print('') print('>>> Cell leakage_power') print(cellLeakagePowerDic) libPinDic = myLibertyParser.getLibPinInfo(cellList=['DFFX1'], pinList=['Q']) print('') print('>>> Lib pin info (cell="DFFX1", pin="Q"):') print(libPinDic)if __name__ == '__main__': main()
通过example.py可以看出libertyParser的使用方式。
example.py中,首先将 libertyParser.py 中的类 libertyParser 实例化,实例化的时候同时传入 library file (s),此时 liberty parser 会逐行解析 library file (s),报告不规范行和非法行,同时将 library file (s) 的数据记录到 python dict(字典)的数据结构之中。(数据结构请参阅 README)
myLibertyParser = libertyParser.libertyParser(libFile)
对于 myLibertyParser,其使用有两种方式。
1. 直接获取数据结构 myLibertyParser.libDic,自己逐层拨开 libDic 取出所需数据。
2. 如果对 libDic 的结构了解不充分,也可以使用 libertyParser 内置的一些函数来获取基本数据,内置函数有以下几种。
* getUnit () : 返回字典 unitDic,里面包含 library file 中所有关于 unit 的定义。
* getCellList () : 返回列表 cellList,里面包含 library file 中所有 cell。
* getCellArea () : 返回字典 cellAreaDic,里面包含 library file 中所有 cell 的 area 信息。
* getCellLeakagePower () :返回字典 cellLeakagePowerDic,里面包含 library file 中所有 cell 的 leakage_power 信息,因为一个 cell 会包含多个 leakage_power,所以每个 leakage_power 的数据结构中会同时包含 when/related_pg_pin/values 这三个数据以示区分。
* getLibPinInfo () : 返回字典 libPinDic,里面包含 library file 中所有 pin 层级的 timing 和 internal_power 信息,最小单位是 timing table 和 internal_power table 中所包含的 index 及 values 数据。
那么我们用范例 lib(非常简单的一个 lib,包含了三个简单 cell)来运行一下范例脚本。
[liyanqing@lavaHost1 examples]$ ./example.py >>> Input file: ./example.lib >>> Unit:OrderedDict([('time_unit', '"1ns"'), ('capacitive_load_unit', '(1,pf)'), ('leakage_power_unit', '"1nW"'), ('current_unit', '"1mA"'), ('voltage_unit', '"1V"'), ('pulling_resistance_unit', '"1kohm"')])>>> Cell list:['DFFX1', 'INVX1', 'NOR2X1']>>> Cell area:OrderedDict([('DFFX1', '0'), ('INVX1', '0'), ('NOR2X1', '0')]) >>> Cell leakage_power OrderedDict([('DFFX1', [{'value': '5.07033', 'when': '"(CK * D * !(Q) * QN)"'}, {'value': '6.17743', 'when': '"(CK * D * Q * !(QN))"'}, ... ...])]) >>> Lib pin info (cell="DFFX1", pin="Q"): OrderedDict([('cell', OrderedDict([('DFFX1', OrderedDict([('pin', OrderedDict([('Q', OrderedDict([('timing', [OrderedDict([('related_pin', '"CK"'), ('timing_sense', 'non_unate'), ('timing_type', 'rising_edge'), ('table_type', OrderedDict([('cell_rise', OrderedDict([('template_name', 'delay_template_5x5'), ('index_1', '("0.25, 0.5, 0.75, 1.25, 1.5")'), ('index_2', '("0.015, 0.05, 0.15, 0.3, 0.6")'), ('values', '( "0.517821, 0.652322, 1.02595, 1.58443, 2.70065", "0.549747, 0.684235, 1.05788, 1.61636, 2.73261", ... ... )')]))]))])])]))]))]))]))])
四、总结
这个 parser 具有简单高效的特点。
由于采用了基于结构分析(不包含任何关键词),所以它能普遍适用于不同纳米制程的 library file(实测过 28nm - 7nm)。
尽管 python 属于一种执行低效的语言,但是经过代码调优,实测 parser 700 万行的 library file(有 700MB 这么大),用时仅仅 28s 左右。