verilog/sv预处理perl工具EP3使用说明

EP3是一个perl5的程序,它可以预处理STDIN或者输入文件,并产生一个输出文件。EP3是为了对verilog硬件描述语言进行灵活预处理而开发出来的。如果你需要预处理数组或类似高级数据结构,你应该直接用perl写脚本。

安装

标准的ep3在cpan上可以找到:https://metacpan.org/pod/Text::EP3

但是该版本不支持@for,要想使用该功能,需要下载这个版本:https://github.com/weiqi7777/ep3

该版本是卢骏开发,来源:http://www.lujun.org.cn/?p=4470

  1. 从github下载支持@for的ep3。

  2. 修改ep3-master/lib/Text/EP3.pm中2152行。因为我安装之后会报这个数组未初始化,可能是perl的版本不同的原因吧。

    1
    $self->{For_Exe} = ()

    ==>

    1
    $self->{For_Exe} = [()]
  3. 在ep3-master目录下执行如下命令,会将ep3安装到/home/fzheng/perl5目录下。

    1
    2
    3
    perl Makefile.PL INSTALL_BASE=/home/fzheng/perl5
    make
    make install
  4. 添加环境变量

    1
    2
    export PERL5LIB="/home/fzheng/perl5/lib/perl5:$PERL5LIB";
    export PATH="/home/fzheng/perl5/bin:$PATH";

简单的小例子

命令的分隔符默认是“@”,这是为了避免和其他分隔符产生冲突,verilog中有使用$, &等。你也可以在命令行通过参数修改该分隔符。

EP3会对每行进行解析,遇到命令分隔符,则调用相应的函数。

先创建一个src文件,里面有@for命令

1
% gvim src
1
2
3
@for i=0 to 1
hello world @i@
@endfor

然后调用ep3进行处理

1
% ep3 src

在STDOUT得到输出结果

1
2
hello world 0
hello world 1

可以看到,EP3进行了一个循环,得到了2行代码。这在处理verilog/system verilog代码时非常有用。

EP3 option

[-no]protect

默认是protect,表示注释代码中的宏不会被替换。

noprotect,表示注释代码中的宏会被替换。

例:

src:

1
2
@define VAR 100
// @VAR

执行如下命令:

1
% ep3 src

输出是:

1
// @VAR

而执行如下命令:

1
% ep3 src -noprotect

输出是:

1
// 100

[-no]comment

默认是comment,表示注释也会输出

nocomment,注释不会输出

例:

src:

1
2
// this is comment
this is content

执行如下命令:

1
% ep3 src

输出是:

1
2
//this is comment
this is content

而执行如下命令:

1
% ep3 src –nocomment

输出是:

1
this is content

-delimeter string

默认是@,可以修改命令的分隔符。

例:

src:

1
2
3
#for i=0 to 1
test
#endfor

命令:

1
% ep3 src –delimeter

输出是:

1
2
test
test

-define string1=string2

宏定义,和一般语言一样,不举例了。

-include directory

头文件查找目录,和一般语言一样,不举例了。

-output_filename

输出文件名,默认是STDOUT

-module filename

加载module,需要在@INC里找到module.pm。没试过。

-line_comment string

单行注释标识,默认是//

-start_comment string

多行注释起始标识,默认是/*

-end_comment string

多行注释结束标识,默认是*/

例:

src:

1
2
3
4
## this is one line comment
this is content
#* this is
multi line comment*#

命令:

1
% ep3 src –line_comment ## -nocomment –start_comment “#*” –end_comment “*#”

输出是:

1
this is content

文本嵌入命令

@define key definition

宏定义,key是一个单独的word,definition可以包含任意字符(甚至空白字符)直到本行结束。

@replace key definition

和define几乎完全一样,除了,key在任何位置都可以被替换,不光是word边界。

@macro key(value[,value]*) definition

和上面两个类似,不同的是,可以支持参数传递。

例:

src:

1
2
3
4
5
6
@define DEF hello
this is @DEF
@replace REP bye
this is xxREPxx
@macro MAC(v1,v2) def v1 v2
this is @MAC(xxx, yyy)

命令:

1
%ep3 src

输出是:

1
2
3
this is hello
this is xxbyexx
this is @def xxx yyy

这里发现macro的输出多了个@,也许是个bug。

@eval key expr

支持一个有效的perl表达式

例:

src:

1
2
@eval EVAL 1.2+2.3
this is @EVAL

命令:

1
% ep3 src

输出是

1
this is 3.5

@include < file> or “file” [condition]

该命令包含文件,“file”在当前目录查找,< file>在所有的include path查找。

还支持使用@mark condition_BEGIN和@mark condition_END指定包含部分内容。

例:

inc:

1
2
3
4
5
1 stuff before
@mark PORT_BEGIN
2 stuff middle
@mark PORT_END
3 stuff after

src:

1
@include “inc”

命令:

1
%ep3 src

输出:

1
2 stuff middle

@enum a,b,c,d…

枚举类型,abcd会被替换成数字,默认从0开始。如果其中有一个是数字,后面的会从这个数字开始。

例:

src:

1
2
@enum a,b,c,d,6,e,f
this is @a @b @c @d @e @f

命令:

1
%ep3 src

输出是

1
this is 0 1 2 3 6 7

@ifdef @ifndef key

条件编译,包括define和replace定义的。

例:

1
2
3
4
5
6
7
8
@define DA 1
@replace RP 2
@ifdef DA
this is DA
@endif
@ifdef RP
this is RP
@endif

输出是

1
2
this is DA
this is 2

@if expr

@[elif|elsif] key | expr

@else

@endif

这些和大部分语言类似,不举例了。

@for iter = expr0 to expr1 [delta expr2]

@endfor

循环输出中间的字符,并支持修改步距。

例:

1
2
3
4
5
@for k=45.2 to 31.1 delta -3.1
@for i=1 to 2
(@k,@i)
@endfor
@endfor

输出是

1
2
3
4
5
6
7
8
9
10
(45.2, 1)
(45.2, 2)
(42.1, 1)
(42.1, 2)
(39, 1)
(39, 2)
(35.9, 1)
(35.9, 2)
(32.8, 1)
(32.8, 2)

@comment on|off|default|previous

on:开

off:关

default:修改为命令行的配置

previous:修改为上次的配置

例:

1
2
3
4
5
6
7
8
@comment off
// comment 1
@comment on
// comment 2
@comment previous
// comment 3
@comment default
// comment 4

输出是

1
2
// comment 2
// comment 4

@protect on|off|default|previous

设置protect配置

@ep3 on|off

设置ep3开关

例:

1
2
3
4
@ep3 off
@if 1
test
@endif

输出是

1
2
3
@if 1
test
@endif

@perl_begin和@perl_end

@perl_begin和@perl_end支持内嵌脚本,它们之间的code会被当作perl代码来执行,并且可以在普通文本中调用。

1
2
3
4
5
6
7
8
9
10
11
@perl_begin
{
sub myroutine
{
my $x = shift;
my $y = shift;
return “x=$x and y=$y, where x+y=”.($x+$y);
}
}
@perl_end
To be sure, @myroutine(3.14,5+1)

输出是:

1
To be sure, x=3.14 and y=6, where x+y=9.14

@debug on|off|value

增加debug信息到输出文件。每bit代表一个含义,可以只开相应bit

0x01 1 - primary message
0x02 2 - ep3_process engine
0x04 4 - define(replace, macro, eval, enum)
0x08 8 - include
0x10 16 - if(else, ifdef, etc.)
0x20 32 - perl_begin/end

扩展

EP3是个perl程序,一般放在perl的bin目录下,要直接调用到ep3,需要设好perl的环境变量

bin/ep3也只是例化了下Text::EP3而已,真正的代码在lib/site_perl/5.12.5/Text/EP3.pm里面。

如果我就想输出@for i=0 to 2这行怎么办?

可以用

1
@ep3 off

也可以用

1
2
3
@perl_begin
@> \@for i=0 to 2
@perl_end