VIM插件 -- 自动生成verilog module的testbench
@(VIM)
1. 动机
软件语言都有各自好用的IDE,各种自动补全,高亮,语法检查。而苦逼的ICer大多还操着远古时期的VIM写着verilog。也是,硬件语言本身就小众,即使是xilinx, altera等大厂的vivado, quartus等大牌软件,自带的代码编辑器也不是很友好。好在号称编辑器之神的VIM提供了丰富的定制化功能,vimscript可以实现诸多媲美成熟IDE的功能。此外,vimscript还配备了很多语言的编程接口,perl,python的脚本都可以在vimscript里运行,这也使得开发插件的门槛降低了不少。
在某次写verilog的testbench时,觉得从写完一个模块,到验证其功能的路上花了大量时间在一些重复的coding上,testbench中大部分内容都是重复模块的端口定义,完全可以让脚本去干,于是花了半天尝试着用python写了一套自动生成verilog modual 的testbench的脚本,嵌入到vim中,通过简单的命令就可以实现繁琐的testbench的模板生成。顺便,,,也巩固一下python的正则表达式写法。话不多说,直接上代码。
2. 代码
"-------------------------------------------------------------------
" auto testbench (python)
"-------------------------------------------------------------------
:nnoremap tb :call Autotb()
function! Autotb()
python << EOF
import vim,re
# 清除所有注释内容
def clear_commonts(lines):
block_comment_index = [] # record block comment index
# remove // comment
for i in range(len(lines)):
lines[i] = re.sub('//.*$','',lines[i])
all_pairs = re.findall('/\*',lines[i])
if(all_pairs != []):
next_index = 0
new_line = lines[i]
for j in range(len(all_pairs)):
# print(new_line)
find_index = re.search('/\*',new_line).span()
next_index = find_index[1]
new_line = new_line[next_index:]
block_comment_index.append(i)
if(re.search('\*/',new_line)!=None): # find paired */
block_comment_index.append(i)
else:
if(re.search('\*/',lines[i])!=None): # find paired */
block_comment_index.append(i)
# print(block_comment_index)
if(len(block_comment_index)%2!=0):
raise('ERROR: /* and */ not paired')
else:
for i in range(int(len(block_comment_index)/2)):
left_index = block_comment_index[i*2]
right_index = block_comment_index[i*2+1]
if(left_index==right_index): # inline /* */
lines[left_index] = re.sub('/\*.*\*/','',lines[left_index])
else:
for j in range(left_index+1,right_index): # delet comment in block /* */
lines[j] = ''
lines[left_index] = re.sub('/\*.*$','',lines[left_index])
lines[right_index] = re.sub('^.*\*/','',lines[right_index])
return lines
# 找到模块名
def find_inst_name(line):
pattern = re.compile('(module)\s+(\w+)')
if(pattern.search(line)!=None):
return pattern.search(line).group(2)
else:
return ''
# 文本行转换为字符串
def lines