作者陈锋,本文转载自:ExASIC
本文写了三个示例,展示了三种综合脚本的写法,供大家可以参考。
一:直接f.write()
第一种写法,在文件开头定义常修改的综合配置,然后直接用write函数,写到syn.tcl里。最后调用os.system("dc_shell -f syn.tcl")来执行综合。
import os
# config
#prj_root = '/home/xxx/prj/e100'
prj_root = '.'
lib_path = prj_root + '/syn'
lib_max = 'slow.db'
rtl_path = prj_root + '/rtl'
rtl_flist = rtl_path + '/rtl.flist'
# write syn script
print('Generate syn.tcl ...')
tcl = open('syn.tcl', 'w')
tcl.write('set lib_path ' + lib_path + '\n')
tcl.write('set ss_lib ' + lib_max + '\n')
tcl.write('set search_path [concat $search_path $lib_path]\n')
tcl.write('set target_library [list $ss_lib]\n')
tcl.write('set synthetic_library [list dw_foundation.sldb]\n')
tcl.write('set link_library [list * $ss_lib $synthetic_library]\n')
rtls = open(rtl_flist, 'r').readlines()
for rtl in rtls:
tcl.write('analyze -format verilog ' + rtl.rstrip() + '\n')
tcl.write('elaborate top\n')
tcl.write('link\n')
tcl.write('check_design\n')
# ... other syn script
print('Done')
# Do synthesis
print('Run Command: dc_shell -f syn.tcl')
#os.system('dc_shell -f syn.tcl')
# ...
二、把综合配置写在配置文件里
第一种方法里,综合配置写死在脚本里,每换一个项目都必须要修改脚本,不够通用。所以在第二个示例里,我们把配置写到json里。
配置文件如下:
{
"prj_root": ".",
"lib_path": "./syn",
"lib_max": "slow.db",
"rtl_path": "./rtl",
"rtl_flist": "./rtl/rtl.flist"
}
在脚本开头,把json配置文件读进来(json.loads()),转换成python的字典类型。后续跟示例一相同。
import os
import json
# config
jsonfile = open('syn.json').read()
cfg = json.loads(jsonfile)
print(cfg)
#prj_root = '/home/xxx/prj/e100'
prj_root = cfg["prj_root"]
lib_path = cfg["lib_path"]
lib_max = cfg["lib_max"]
rtl_path = cfg["rtl_path"]
rtl_flist = cfg["rtl_flist"]
三、把综合命令提炼成模板
对于综合来说,总是按照一定的flow,一步步执行和调试。所以其中的命令大部分是不变的,变的只是少量参数。
下面是一个Mako模板示例(Mako这一种模板语言,详见https://www.makotemplates.org):
set lib_path ${lib_path}
set ss_lib ${lib_max}
set search_path [concat $search_path $lib_path]
set target_library [list $ss_lib]
set synthetic_library [list dw_foundation.sldb]
set link_library [list * $ss_lib $synthetic_library]
% for rtl in rtls:
analyze -format verilog ${rtl}
% endfor
elaborate top
link
check_design
可以看出变化的部分用${xxx}来表示,比如,${lib_path}、${rtl}。还可以嵌入for循环,以提高效率。
在脚本里,根据json配置文件里定义的参数,来代替模板里的变化部分。这个替换的过程也叫做渲染(Render),下面是具体实现:
import os
import json
from mako.template import Template
# read config file
jsonfile = open('syn.json').read()
cfg = json.loads(jsonfile)
print(cfg)
prj_root = cfg["prj_root"]
lib_path = cfg["lib_path"]
lib_max = cfg["lib_max"]
rtl_path = cfg["rtl_path"]
rtl_flist = cfg["rtl_flist"]
rtls = open(rtl_flist, 'r').read().splitlines()
print(rtls)
# define a template
t = """
set lib_path ${lib_path}
set ss_lib ${lib_max}
set search_path [concat $search_path $lib_path]
set target_library [list $ss_lib]
set synthetic_library [list dw_foundation.sldb]
set link_library [list * $ss_lib $synthetic_library]
% for rtl in rtls:
analyze -format verilog ${rtl}
% endfor
elaborate top
link
check_design
"""
# write syn script
print('Generate syn.tcl ...')
mytemplate = Template(t)
scr = mytemplate.render(lib_path=lib_path,
lib_max=lib_max,
rtls=rtls)
tcl = open('syn.tcl', 'w')
tcl.write(scr)
print('Done')
# Do synthesis
print('Run Command: dc_shell -f syn.tcl')
#os.system('dc_shell -f syn.tcl')
# ...
补充几点
读带注释的json文件可以用json5
Mako模板支持对文件夹渲染,这样大项目也不怕。
其它模板语言:jinjia2、jade、ejs等
总结
文中的示例代码可以这里下载:https://github.com/chenfengrugao/pythontutorial/tree/master/day21