【快速断言体系】一步步搭建一个高效的快速断言体系 1

前言

【快速断言体系】一步步搭建一个高效的快速断言体系 0

阶段性成果诞生啦,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,阶段性工作完成,我得缓缓!!!!!

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

尼德兰的喵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值