一款基于vimscript的自动化verilog脚本。由automatic for Verilog & RtlTree修改而来,原作者zhangguo。

原脚本参考

automatic for Verilog & RtlTree

vim auto script for verilog & RtlTree

最新脚本GitHub地址请点击 automatic-verilog

使用手册(Handbook)

部分功能与插件相关联,请参考终篇效果。本使用说明只介绍脚本automatic.vim修改或新增的部分功能。


AutoInst

自动生成例化模块连接。

操作步骤

  1. 写标志/*autoinst*/

    写标志

    将要例化的模块写为如下格式:module_name inst_name(/*autoinst*/);

    ⚠️注意

    • 格式末尾必须要有分号;
    • 注意格式可不在同一行,只要(/*autoinst*/)包含在括号内,括号外为module_name inst_name即可;支持端口处带parameter的写法。

    e.g.

    1
    fetch fetch_inst ( /*autoinst*/ );
    1
    2
    mem     u_mem(
    /*autoinst*/);
    1
    2
    3
    4
    5
    6
    7
    8
    9
      writeback 
    #(
    // Parameters
    .BMAN (BMAN),
    )writeback_inst
    (
    .write_data (write_data[31:0]),
    /*autoinst*/
    );
  2. 自动例化

    自动例化
    • 使用菜单栏点击AutoInst(0)或在命令行输入:call AutoInst(0)确认,进行/*autoinst*/当前模块自动例化,注意例化时光标必须置于/*autoinst*/所在行之前的位置(即在当前行或上一行,若在当前行则必须在/*autoinst*/所在列之前);
    • 使用菜单栏点击AutoInst(1)或在命令行输入:call AutoInst(1)确认,进行/*autoinst*/所有模块自动例化;
    • 默认键盘快捷键为<S-F3>,可在脚本automatic.vim中如下位置配置快捷键
    1
    2
    3
    4
    5
    6
    7
    8
       "Auto 自动化 {{{3
    map <S-F3> :call AutoInst(0)<ESC>
    map <S-F4> :call AutoPara(0)<ESC>
    map <S-F5> :call AutoParaValue(0)<ESC>
    map <S-F6> :call AutoReg()<ESC>
    map <S-F7> :call AutoWire()<ESC>
    map <S-F8> :call AutoDef()<ESC>
    "}}}3

    AutoInst

特性

特性

在代码中添加如下格式的内容声明文件夹即可:

1
2
3
4
//Local Variables:
//verilog-library-directories:("." "./aaa/bbb/ccc")
//verilog-library-directories-recursive:0
//End:
  • verilog-library-directories为要选择的文件夹,文件夹之间以空格隔开;

  • verilog-library-directories-recursive为是否进行文件夹递归搜索,即搜索所有选择文件夹及其子文件夹;

    假设需要选择当前文件夹以及其下所有子文件夹作为例化搜索的对象,则配置为:

    //verilog-library-directories:(".")
    //verilog-library-directories-recursive:1

    ⚠️注意

    如果使用递归搜索,请勿采用重叠的文件夹,否则递归会报错;例如上述例子中,"." 当前文件夹递归搜索包含"./aaa/bbb/ccc"子文件夹,若此时使用递归搜索则重复调用时会报错。

    CrossDir

添加//INST_NEW//INST_DELio_dir、注释//以及宏定义`ifedf

  • 例化时默认自动在尾部添加io_dir,即端口类型input/output/inout
  • 例化时默认若有端口更新,自动在该端口尾部添加//INST_NEW
  • 例化时默认若有端口被删除,自动在所有端口例化之后添加//INST_DEL
  • 例化时默认添加//类型注释
  • 例化时默认添加`ifdef类型的宏定义,包括ifdef/elsif/else/endif

可在脚本automatic.vim中如下位置配置相关参数选择不添加以上内容

1
2
3
4
5
6
7
8
9
10
11
"AutoInst 自动例化配置{{{2
let s:ati_io_dir = get(g:,'ati_io_dir',1) "add //input or //output in the end of instance
let s:ati_inst_new = get(g:,'ati_inst_new',1) "add //INST_NEW if port has been newly added to the module
let s:ati_inst_del = get(g:,'ati_inst_del',1) "add //INST_DEL if port has been deleted from the module
let s:ati_keep_chg = get(g:,'ati_keep_chg',1) "keep changed inst io
let s:ati_incl_cmnt = get(g:,'ati_incl_cmnt',1) "include comment line of // (/*...*/ will always be ignored)
let s:ati_incl_ifdef = get(g:,'ati_incl_ifdef',1) "include ifdef like `ifdef `endif
let s:ati_95_support = get(g:,'ati_95_support',0) "Support Verilog-1995
let s:ati_tail_not_align = get(g:,'ati_tail_not_align',0) "don't do alignment in tail when autoinst
let s:ati_add_dir = get(g:,'ati_add_dir',0) "add //Instance ...directory...
"}}}2

也可通过在.vimrc(or _vimrc)中配置相关global参数实现配置(以io_dir为例)

1
let g:ati_io_dir = 0
  1. 自动保留/*autoinst*/上方的例化端口,只对其余端口进行自动例化。

  2. 同时,若配置ati_keep_chg=1,若端口连线更改,则不进行重刷,只进行端口对齐操作。

例化时默认ati_keep_chg=1let s:ati_keep_chg = get(g:,'ati_keep_chg',1)),即若更改过端口连线,则不进行重刷

name&reinst

reinst_with_conn_change

⚠️注意事项

注意事项
  1. AutoInst支持verilog-1995以及verilog-2001的不同写法,但使用verilog-1995写法时需在脚本automatic.vim中如下位置配置选择兼容verilog-1995,否则默认不兼容

    1
    2
    3
    4
    5
    "AutoInst 自动例化配置{{{2
    ......
    let s:AUTOINST_95_SUPPORT= 0 "Support Verilog-1995
    ......
    "}}}2

    注意,若采用verilog-1995写法,则AutoInstifdef以及注释//的支持存在问题,建议此时配置关闭这些选项

  2. 输入输出端口的格式不支持连续多个的特殊写法,例如input [7:0] a,b,c;,只支持单行写法


AutoPara

自动生成例化参数连接。

操作逻辑基本同AutoInst一致,分为两种。

  • AutoParaValue例化parameter,标志为/*autoinstparam_value*/

  • AutoPara例化parameter,标志为/*autoinstparam*/

操作步骤

  1. 写标志/*autoinstparam*//*autoinstparam_value*/

    写标志

    整体操作与AutoInst一致,参考AutoInst

  2. 自动例化参数

    自动例化

    整体操作与AutoInst一致,参考AutoInst

    • AutoPara默认键盘快捷键为<S-F4>,可在脚本automatic.vim中如下位置配置快捷键
    • AutoParaValue默认键盘快捷键为<S-F5>,可在脚本automatic.vim中如下位置配置快捷键
    1
    2
    3
    4
    5
    6
    7
    8
    "Auto 自动化 {{{3
    map <S-F3> :call AutoInst(0)<ESC>
    map <S-F4> :call AutoPara(0)<ESC>
    map <S-F5> :call AutoParaValue(0)<ESC>
    map <S-F6> :call AutoReg()<ESC>
    map <S-F7> :call AutoWire()<ESC>
    map <S-F8> :call AutoDef()<ESC>
    "}}}3

    autopara_normal

    autopara_value

特性

特性

AutoInst一致,参考AutoInst

添加//PARA_NEW //PARA_DEL,注释//以及宏定义ifedf,并支持配置使用端口参数例化或使用所有参数进行例化。

在脚本automatic.vim中如下位置配置相关参数选择不添加//PARA_NEW //PARA_DEL,并可通过配置ONLY_PORT确定使用哪种参数进行例化。

当前添加注释//以及宏定义ifedfAutoPara中只支持使用端口参数例化,使用所有参数进行例化的会添加无用的注释//以及宏定义ifedf,请使用者注意。

另外,注释//以及宏定义ifedf只针对AutoPara,不论如何配置,AutoParaValue均不添加注释//以及宏定义ifedf

1
2
3
4
5
6
7
8
9
"AutoPara 自动参数配置{{{2
let s:atp_only_port = get(g:,'atp_only_port',0) "add only port parameter definition,ignore parameter = value; definition
let s:atp_para_new = get(g:,'atp_para_new',1) "add //PARA_NEW if parameter has been newly added to the module
let s:atp_para_del = get(g:,'atp_para_del',1) "add //PARA_DEL if parameter has been deleted from the module
let s:atp_keep_chg = get(g:,'atp_keep_chg',1) "keep changed parameter
let s:atp_incl_cmnt = get(g:,'atp_incl_cmnt',0) "include comment line of // (/*...*/ will always be ignored)
let s:atp_incl_ifdef = get(g:,'atp_incl_ifdef',0) "include ifdef like `ifdef `endif
let s:atp_tail_not_align = get(g:,'atp_tail_not_align',0) "don't do alignment in tail when autopara
"}}}2

也可通过在.vimrc(or _vimrc)中配置相关global参数实现配置(以only_port为例)

1
let g:atp_only_port = 1

例化端口参数(ONLY_PORT=1)的例子:

1
2
3
4
5
6
7
module writeback
#(
parameter BMAN=3,
parameter AMAN=45 ,
parameter WIDTH = 16 ,
parameter TIME_INTERVAL = 4'd11
)

例化所有参数(ONLY_PORT=0)的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
module writeback
#(
parameter BMAN=3,
parameter AMAN=45 ,
parameter WIDTH = 16 ,
parameter TIME_INTERVAL = 4'd11
)
(
......
);

parameter CNT0 = 16'h55, CNT1 = 16'h55;
parameter CNT2 = 256 ;
parameter CNT3 = 16'h55 ;

AutoInst一致,参考AutoInst

支持特殊的parameter连续多个的写法,例如parameter A = 1, B = 5, C = 6

⚠️注意事项

注意事项
  1. AutoParaifdef以及注释//的支持存在问题,建议配置关闭(默认为关闭)

AutoReg

自动定义寄存器列表。

操作步骤

  1. 写标志/*autoreg*/

    写标志

    在一个空白行内写入:/*autoreg*/

    ⚠️注意

    同一行内:

    • /*autoreg*/前端可以存在空格
    • /*autoreg*/后端可以存在任意字符,操作时会忽略

    e.g.

    1
    /*autoreg*/
    1
    2
    //multiple spaces
    /*autoreg*/
  2. 自动生成reg

    自动生成reg
    • 使用菜单栏点击AutoReg()或在命令行输入:call AutoReg()确认,在当前文本/*autoreg*/下方自动生成reg,例化时光标位置随意,只要保证当前文本含有包含/*autoreg*/的行即可;
    • 默认键盘快捷键为<S-F6>,可在脚本automatic.vim中如下位置配置快捷键
    1
    2
    3
    4
    5
    6
    7
    8
       "Auto 自动化 {{{3
    map <S-F3> :call AutoInst(0)<ESC>
    map <S-F4> :call AutoPara(0)<ESC>
    map <S-F5> :call AutoParaValue(0)<ESC>
    map <S-F6> :call AutoReg()<ESC>
    map <S-F7> :call AutoWire()<ESC>
    map <S-F8> :call AutoDef()<ESC>
    "}}}3

    autoreg

特性

特性

添加//REG_NEW //REG_DEL

AutoInst以及AutoPara一致,参考AutoInst

可在脚本automatic.vim中如下位置配置相关参数选择不添加以上内容

1
2
3
4
5
"AutoReg 自动寄存器配置{{{2
let s:atr_reg_new = get(g:,'atr_reg_new',1) "add //REG_NEW if register has been newly added to the module
let s:atr_reg_del = get(g:,'atr_reg_del',1) "add //REG_DEL if register has been deleted from the module
...
"}}}2

自动保留/*autoreg*/范围外的reg。即,在//Start of automatic reg以及//End of automatic reg行之外)不重刷,只对其余端口进行自动生成reg。不支持修改后的reg不重刷的功能。

rereg

如果解析出当前变量为reg型,但解析其位宽等信息失败时,可在尾部添加标志位,即//unresolved,代表解析变量失败。

可在脚本automatic.vim中如下位置配置相关参数选择不添加以上内容

1
2
3
4
"AutoReg 自动寄存器配置{{{2
...
let s:atr_unresolved_flag = get(g:,'atr_unresolved_flag',0) "add //unresolved if reg is unresolved
"}}}2

⚠️注意事项

注意事项
  1. AutoReg自动生成的//Start of automatic reg以及//End of automatic reg行会被用于定位所有/*autoreg*/的内容,不能随意对其进行删除(例如只删除其中一个而保留另一个),否则再次进行自动生成时会出现错误
  2. 请勿在文本中写多个标志/*autoreg*/,否则可能出现错误
  3. 重刷特性会检查现有的reg,但数组格式的reg的检查会出现异常,例如reg [7:0] ram_data[127:0]

AutoWire

自动定义线网列表。

操作步骤

  1. 写标志/*autowire*/

    写标志

    AutoReg一致,参考AutoReg

  2. 自动生成wire

    自动生成wire
    • 使用菜单栏点击AutoWire()或在命令行输入:call AutoWire()确认,在当前文本/*autowire*/下方自动生成wire,例化时光标位置随意,只要保证当前文本含有包含/*autowire*/的行即可;
    • 默认键盘快捷键为<S-F7>,可在脚本automatic.vim中如下位置配置快捷键
    1
    2
    3
    4
    5
    6
    7
    8
    "Auto 自动化 {{{3
    map <S-F3> :call AutoInst(0)<ESC>
    map <S-F4> :call AutoPara(0)<ESC>
    map <S-F5> :call AutoParaValue(0)<ESC>
    map <S-F6> :call AutoReg()<ESC>
    map <S-F7> :call AutoWire()<ESC>
    map <S-F8> :call AutoDef()<ESC>
    "}}}3

    autowire

特性

特性

添加//WIRE_NEW //WIRE_DEL

AutoInst以及AutoPara一致,参考AutoInst

可在脚本automatic.vim中如下位置配置相关参数选择不添加以上内容

1
2
3
4
5
"AutoWire 自动线网配置{{{2
let s:atw_wire_new = get(g:,'atw_wire_new',1) "add //WIRE_NEW if wire has been newly added to the module
let s:atw_wire_del = get(g:,'atw_wire_del',1) "add //WIRE_DEL if wire has been deleted from the module
...
"}}}2

自动保留/*autowire*/范围外的wire。即,在//Start of automatic wire以及//End of automatic wire行之外)不重刷,只对其余端口进行自动生成wire。不支持修改后的wire不重刷的功能。

AutoReg一致,参考AutoReg

如果解析出当前变量为wire型,但解析其位宽等信息失败,解析信号例化模块失败,获取例化模块相关信号失败等情况时,可在尾部添加标志位,即//unresolved,代表解析变量失败。

可在脚本automatic.vim中如下位置配置相关参数选择不添加以上内容

1
2
3
4
"AutoWire 自动线网配置{{{2
...
let s:atw_unresolved_flag = get(g:,'atw_unresolved_flag',0) "add //unresolved if wire is unresolved
"}}}2

支持单行例化的检索,举例:

1
module_name u_inst_name ( .test( a ), .test1( b ), .test2( c ));

⚠️注意事项

注意事项
  1. AutoWire自动生成的//Start of automatic wire以及//End of automatic wire行会被用于定位所有/*autowire*/的内容,不能随意对其进行删除(例如只删除其中一个而保留另一个),否则再次进行自动生成时会出现错误

  2. 由于AutoWire会搜索例化模块的wire,因此会按路径进行例化模块搜索,此时可按照AutoInst中的跨文件夹相关的内容配置文件路径,保证例化模块可以被搜索到

  3. 请勿在文本中写多个标志/*autowire*/,否则可能出现错误

  4. 暂不支持例化端口的复杂写法,只支持单信号的简单写法,复杂写法举例如下:

    1
    2
    3
    4
    5
    module_name u_inst_name (
    .test ( {a,b[7:0],c} ),
    .test1 ( ~d ),
    .test2 ( &e )
    );

AutoDef

自动定义所有信号列表

可参考AutoRegAutoWireAutoDef功能上等于AutoReg+AutoWire。写标志为/*autodef*/

autodef

autodef

⚠️注意事项

注意事项
  1. AutoRegAutoWire自动生成的//Start of automatic reg//Start of automatic wire以及//End of automatic reg//End of automatic wire行会被用于定位所有/*autodef*/的内容,不能随意对其进行删除(例如只删除其中一个而保留另一个),否则再次进行自动生成时会出现错误
  2. 由于AutoDef会搜索例化模块的wire,因此会按路径进行例化模块搜索,此时可按照AutoInst中的跨文件夹相关的内容配置文件路径,保证例化模块可以被搜索到
  3. 请勿在文本中写多个标志/*autodef*/,否则可能出现错误

RtlTree

通过Rtl树观察代码结构

此功能完全参考zhangguo的脚本automatic for Verilog & RtlTree,只进行tags生成的vimscript集成以及文件名跨文件夹的重构。同时,此功能开启后由于自动生成tags,因此可以通过<C-]>进行模块的快速跳转。

操作步骤

  1. 打开Rtl

    打开

    命令行输入RtlTree(或直接使用缩略的Rtl)确认即可

    1
    :RtlTree

    callout_rtl

  2. 跳转

    跳转
    • 鼠标操作

      单击跳转至例化位置,双击跳转至模块内部

      mouse

    • 键盘操作

      单击~-+位置跳转至模块内部,单击同一行其他位置跳转至例化位置

      fastkey

⚠️注意事项

注意事项
  1. RtlTree会自动生成tags文件,若一般正常操作则会自动删除此文件,但出现异常时此文件可能会留存,若不需要请自行删除
  2. RtlTree以当前模块为顶层模块开始进行树图生成(默认,不可改)

注意事项(Note)

⚠️除了使用手册之外的其他注意事项

Align

位置对齐的相关配置

  1. 对齐位置

    对齐位置

    可在脚本automatic.vim中如下位置配置相关参数选择使用自动函数时的对齐位置:

    1
    2
    3
    4
    5
    6
    "Position 确定信号对齐位置{{{2
    let s:name_pos_max = 32
    let s:symbol_pos_max = 64
    let s:start_pos = 4
    let s:start_prefix = repeat(' ',s:start_pos)
    "}}}2

    name_pos_max:信号名对齐位置

    symbol_pos_max:第二个括号对齐位置

    start_pos:起始位置

    如果信号长度过长(长于设定的对齐位置),则会按照最长信号长度+4为新的对齐位置进行对齐。

    autopara

  2. 行尾对齐

    行尾对齐

    可在脚本automatic.vim中如下位置配置相关参数选择进行行尾对齐/不对齐(默认0,进行行尾对齐):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    "AutoInst 自动例化配置{{{2
    ......
    let s:ati_tail_not_align = get(g:,'ati_tail_not_align',0) "don't do alignment in tail when autoinst
    "}}}2
    "AutoPara 自动参数配置{{{2
    ......
    let s:atp_tail_not_align = get(g:,'atp_tail_not_align',0) "don't do alignment in tail when autopara
    "}}}2
    "AutoReg 自动寄存器配置{{{2
    ......
    let s:atr_tail_not_align = get(g:,'atr_tail_not_align',0) "don't do alignment in tail when autoreg
    "}}}2
    "AutoWire 自动线网配置{{{2
    ......
    let s:atw_tail_not_align = get(g:,'atw_tail_not_align',0) "don't do alignment in tail when autowire
    "}}}2
    • AutoInst行尾对齐

      image-20210612222934861

    • AutoInst行尾不对齐

      image-20210612222827132

    • AutoPara的行尾对齐

      image-20210612223220307

    • AutoPara的行尾不对齐

      image-20210612223427942

    • AutoRegAutoWireAutoDef的行尾对齐

      AutoInst以及AutoPara类似

Others

其他相关注意事项

其他注意事项
  1. 通过修改脚本的对应位置可以修改相应的配置信息,配置信息包括很多内容,在每个函数的操作手册中有提及

    如果在vim运行过程中需要更新配置,直接在vimsource脚本文件automatic.vim即可

  2. AutoWireAutoDef运行时会获取相关的所有例化模块,其运行速度可能较慢。为有效显示其运行状态,可以打开如下配置,实现获取例化模块的状态栏进度条显示

    需要注意的是,打开进度条显示后,由于进度条会刷新状态栏,若出现错误,则在状态栏的相关函数的错误信息会消失。

    1
    2
    3
    "Progressbar 进度条支持{{{2
    let s:atv_pb_en = 0
    "}}}2

    progressbar

  3. AutoInst只支持获取单行声明的写法,不支持获取端口跨行声明的写法;AutoPara支持连续的跨行声明,但不支持不连续的跨行声明

    • inst跨行,不支持:

      1
      2
      input [1:0]
      a,
    • parameter跨行,支持:

      1
      2
      parameter BMAN=3, 
      AMAN=45 ,WIDTH = 16,
    • parameter声明跨行,不支持:

      1
      2
      parameter BMAN
      =3,
  4. 最后一行为注释//时,脚本有概率会报异常,但不影响其执行

计划(Plan)

计划

梳理automatic脚本相关函数,包括autoinstautoparaautowireautoregautodef等自动化函数。

考虑结合原脚本vim automatic-verilog部分自动化优势以及emacs verilog-mode的部分特点,重构自动化脚本部分代码。

autodef实现merge属性。

编写格式校正脚本,自动校正所有代码格式。

  • 原型开发,支持校正部分端口、always块、assign

  • 全量开发,支持校正几乎所有端口、块函数(IO/always/parameter/comment/inst line