前言
阶段性成果诞生啦,chk_xz搞好了!然后我就一直在思考,如果csdn哪天闭站了可咋整,我这优秀的成果啊,那都是得保存好啊!
阶段性成果展示
你看这里有一个其貌不扬的小RTL代码,当然了,没用的代码都被我干掉了:
里面信号声明的地方被我加了各种符合前文说明的注释,用以生成断言;
然后在vim内键入 :F,就是这个效果:
当当当当~~~~,断言生成完成:
那么继续添加一些,把其他信号也加上检查吧:
还是在这个文件中 :F 一下,断言自动刷新:
看起来何止还行,简直是有点完美啊!
关键实现
脚本的实现在auto_assert.py中实现,主函数分为以下几步:
def main():
rtl_file = sys.argv[1]
signal_info = sys_rtl_file(rtl_file)
assert_list = gen_assert_code(signal_info)
write_rtl(rtl_file, assert_list)
if __name__ == '__main__':
main()
signal_info用来获取RTL中的信号信息:
def sys_rtl_file(file):
signal_info = {}
with open (file, "r") as rtl:
handle = rtl.readlines()
for line in handle:
result = re.search(r"^\s*(input|output|wire|reg)\s*(wire|reg)?\s*(\[[\s\-\:\w]+\])?\s*(\w+)[\;\,\s]+(//.*)?", line)
if result:
info = {}
signal_name = result.group(4)
if result.group(2):
info['type'] = result.group(2)
info['port'] = result.group(1)
else:
info['type'] = result.group(1)
info['port'] = "none"
if result.group(3):
signal_width = result.group(3).replace(r"]", "").replace(r"[", "")
if re.match(r"(\w+)\s*\:0", signal_width):
#print(re.match(r"(\w+)\s*\:0", signal_width).group(1))
signal_width = int(re.match(r"(\w+)\s*\:0", signal_width).group(1)) + 1
elif re.match(r"(\w+)\s*\-1\:0", signal_width):
signal_width = re.match(r"(\w+)\s*\-1\:0", signal_width).group(1)
else:
print("ERROR!!!!!")
info['width'] = signal_width
else:
info['width'] = 1
if result.group(5):
info['note'] = result.group(5).replace(r"//", "")
gen_assert_code用来生成断言,之后继续完善这个体系的话,就是往这里面添加东西:
def gen_assert_code(info):
assert_list = ["`ifdef ASSERT_ON // AUTO ADD",
"",
"wire assert_clk = clk;",
"wire assert_rst_n = rst_n;",
"",
"reg after_rst = 1'b0;",
"always @(posedge assert_clk) if(assert_rst_n == 1'b0) ##10; after_rst <= 1'b1;",
"",
"property chk_xz(info);",
" @(posedge assert_clk) disable iff(~after_rst)",
" ~$isunkown(info);",
"endproperty",
"",
"property chk_xz_valid(valid, info);",
" @(posedge assert_clk) disable iff(~after_rst)",
" valid |-> ~$isunkown(info);",
"endproperty",
""
]
for signal in info:
sig_info = info[signal]
if 'note' in sig_info.keys():
result = re.search(r"ASSERT: ([^\/]+)", sig_info['note'])
if result:
assert_note_list = result.group(1).split(r";")
for note in assert_note_list:
assert_note = note.strip()
if add_chk_xz(signal, assert_note) != -1:
assert_list.append(add_chk_xz(signal, assert_note))
assert_list.append("")
assert_list.append("`endif //AUTO ADD ASSERT_ON")
return assert_list
显然,现在这个函数里面只添加了一个add_chk_xz:
def add_chk_xz(signal, note):
if not re.match(r"chk_xz", note):
return -1
if re.match(r"chk_xz while (.*)", note):
str = "assert property chk_xz_valid(%s, %s) else $error(\"%s has xz error\", %s);" % (signal, re.match(r"chk_xz while (.*)", note).group(1), r"%s", signal)
else:
str = "assert property chk_xz(%s) else $error(\"%s has xz error\", %s);" % (signal, r"%s", signal)
return str
之后肯定还会写add_chk_value和add_end_chk的!!!
最后的函数write_rtl就是重新写一下RTL代码,把生成的断言添加进去:
def write_rtl(file, assert_list):
new_rtl = []
ignore_flag = 0
ignore_chg = 0
add_flag = 0
has_add = 0
with open (file, "r") as rtl:
handle = rtl.readlines()
for line in handle:
if ignore_chg == 1:
ignore_flag = 0
if re.match(r"`ifdef ASSERT_ON ", line):
ignore_flag = 1
add_flag = 1
if re.match(r"endmodule", line) and has_add == 0:
add_flag = 1
if re.match(r"`endif //AUTO ADD ASSERT_ON", line):
ignore_chg = 1
if add_flag == 1:
new_rtl.extend(assert_list)
add_flag = 0
has_add = 1
if ignore_flag == 0:
new_rtl.append(line.rstrip())
for line in new_rtl:
print(line)
鉴于有人说过:好的代码本身就是注释,因此我一行注释都没写~~~~~~
脚本完成后,在~/.vimrc中添加这句话:
command! F :execute '%! /home/xiaotu/my_work/auto_assert/auto_assert.py %'
OK,阶段性工作完成,我得缓缓!!!!!