我们写代码时,常常会写一个TODO的注释来表明这里还需要添加或完善功能(先集中精力完成重要的功能)。或者用FIXME来表明这里有一些小BUG(但现在不影响主要功能)。也可能会用XXX来表明这里还有改进的空间(但现在还不是时候)。这些额外注释的确是写code的小助手。但如果在Tapeout前忘了(或者漏掉)要完善或改进一些细节,倒有些可惜。代码太多、太长,谁记得有没有加过FIXME?!
今天我们来用Python写一段脚本检查代码中是不是有被遗忘的特殊注释。
需求分析
可以指定要检查代码的目录
只检查目录里的.v和.sv的文件,忽略其它文件
支持TODO,FIXME,XXX三种特殊注释
报错时显示文件与行号,方便后续修改
实现过程
通过命令行参数指定代码目录,如下:
import argparse
if __name__ == '__main__':
cmdline_parser = argparse.ArgumentParser()
cmdline_parser.add_argument('-y', help='specify rtl dirs')
args = cmdline_parser.parse_args()
if args.y:
rtl = args.y
else:
rtl = 'rtl'
通过depth确定项目根目录,再拼接上指定的代码目录。用os.listdir()来获取代码目录中的所有有文件和子目录,再用for循环逐个判断是文件(os.path.isfile)还是子目录,如果是文件,再判断文件后缀是否是.sv或.v。
import os
dep = os.popen('depth').readlines()[0]
print('project root: {}\n'.format(dep))
rtlbasedir = dep + os.sep + rtl
rtlfiles = os.listdir(rtlbasedir)
for f in rtlfiles:
absf = rtlbasedir + os.sep + f
if os.path.isfile(absf):
if re.search(r'\.s?v$', f):
把文件路径传递给检查函数,打开文件,逐行检查有无TODO、FIXME、XXX等特殊注释。如果有,则报错Error: +lineno file,并打印出错行。
def check(f):
print('Checking file: {}'.format(f))
with open(f, 'r') as lines:
lineno = 0
for l in lines:
lineno += 1
if re.search(r'(TODO|FIXME|XXX)', l):
print('Error: +{} {}'.format(lineno, f))
print('\t{}'.format(l))
最终效果
最终效果如下:
[bill@server script]$ ./rtl_check.py
TODO/FIXME/XXX Checker 1.0
Usage: python3 rtl_check.py -y rtl_dir_name
For example:
python3 rtl_check.py -y rtl
project root: ./../..
Checking file: ./../../rtl/ctrl.v
Checking file: ./../../rtl/process.v
Error: +83 ./../../rtl/process.v
// TODO: may have no relationship with rim, need to confirm
Checking file: ./../../rtl/seq.v
Checking file: ./../../rtl/merge.v
Checking file: ./../../rtl/fifo.v
Checking file: ./../../rtl/wrapper.v
Error: +136 ./../../rtl/bist.v
assign wr_clk = clk; //TODO: add clk gate
Error: +137 ./../../rtl/bist.v
assign rd_clk = clk; //TODO: add clk gate