Verilog_perl,perl解析Verilog的利器

Verilog_perl是Perl解析和处理Verilog文件的工具。

详细细节见:https://www.veripool.org/verilog-perl

官网的示例晦涩难懂,这里主要介绍典型的使用方式。

下面是一个verilog代码的示例,是后面的测试需要的verilog代码源文件。

module test#(
    parameter END_OF_LIST = 0
)(
    input i_clk ,
    input i_rest_n ,

    output reg[3:0]sum ,
    input [2:0] a,b
);

logic [2:0] a_ff,b_ff;

always@(posedge i_clk)begin
    if(i_rest_n == 1'b0)begin
        sum <= '0 ;
    end
    else begin
        sum <= a_ff+b_ff;
    end
end

sync_cell U_A_SYNC_CELL[2:0](
    .clk   ( i_clk    ) ,
    .rst_n ( i_rest_n ) ,
    .in    ( a        ) ,
    .out   ( a_ff     )
);
sync_cell U_B_SYNC_CELL[2:0](
    .clk   ( i_clk    ) ,
    .rst_n ( i_rest_n ) ,
    .in    ( b        ) ,
    .out   ( b_ff     )
);

endmodule

一、Verilog::Getopt

 提供了标准化的选项处理方式,类似于 Verilog/VCS 和 cc/GCC。

use Verilog::Getopt ;
my $opt= new Verilog::Getopt ;
my @Opts = $opt->parameter("+incdri+verilog","-F","test.lst","+define+MEM_CTRL_BUS_WIDTH=96") ;
for my $i(@Opts){
    print($i);
}

如上的例子,Getopt模块会帮助解析输入的参数,值得注意的是,不同的参数的影响是不同的。

例如+incdir+定义的目录可以存储在内部的变量中,用于后面解析文件确定查找文件目录,-F则会被当做filelist解析,然后递归返回filelist中的文件,文件列表作为返回值返回,上面的例子中会存储与$Opts中,还有一些Getopt不识别的参数,也会被原样的座位返回值返回存储与$Opts中。

二、Verilog::Parser

package MyParser;
use Verilog::Parser;
@ISA = qw(Verilog::Parser);
 
# parse, parse_file, etc are inherited from Verilog::Parser
sub new {
    my $class = shift;
    #print "Class $class\n";
    my $self = $class->SUPER::new();
    bless $self, $class;
    return $self;
}
 
sub symbol {
    my $self = shift;
    my $token = shift;
 
    $self->{symbols}{$token}++;
}
 
sub report {
    my $self = shift;
 
    foreach my $sym (sort keys %{$self->{symbols}}) {
       printf "Symbol %-30s occurs %4d times\n",
       $sym, $self->{symbols}{$sym};
    }
}
 
package main;
 
my $parser = MyParser->new();
$parser->parse_file("test.v");
$parser->report();

上面是官网的例子,在文件中检索非关键字的单词,并统计每个词出现的次数,结果如下所示。

Verilog::Parser中有个方法,lineno()可以帮助我们定位具体元素的位置,例如每当遇到symbols,打印出具体的行号,如下面的示例:

package MyParser;
use Verilog::Parser;
@ISA = qw(Verilog::Parser);
 
# parse, parse_file, etc are inherited from Verilog::Parser
sub new {
    my $class = shift;
    #print "Class $class\n";
    my $self = $class->SUPER::new();
    bless $self, $class;
    return $self;
}
 
sub symbol {
    my $self = shift;
    my $token = shift;
 
    $self->{symbols}{$token}++;
    printf("%-14s occurs at line:%d",$token,$self->lineno()) ;
    print("\n") ;
}
 
 
package main;
 
my $parser = MyParser->new();
$parser->parse_file("test.v");

运行后输出结果如下所示:

三、Verilog::SigParser

当Verilog中具体类型匹配时,会调用对应的回调函数。

$\="\n" ;
package Myparser ;
use Verilog::SigParser ;
@ISA=qw(Verilog::SigParser) ;

sub new{
    my $class=shift ;
    my $self=$class->SUPER::new() ;
    bless $self,$class ;
    return $self ;
}

sub port{
    my $self=shift ;
    my ($name, $objof, $direction, $data_type, $array, $pinnum)=@_ ;
    print($name.":".$direction) ;
}


package main;

my $parse=Myparser->new();
$parse->parse_file("test.v") ;

这个例子是解析代码中的port信息,然后放回port名和对应的端口方向。

运行上面的程序输出:

同样的,如果想获得instant信息,程序如下:

$\="\n" ;
package Myparser ;
use Verilog::SigParser ;
@ISA=qw(Verilog::SigParser) ;

sub new{
    my $class=shift ;
    my $self=$class->SUPER::new() ;
    bless $self,$class ;
    return $self ;
}


sub instant{
    my $self=shift ;
    print(shift,shift,shift) ;
}

package main;

my $parse=Myparser->new();
$parse->parse_file("test.v") ;

运行后获取如下输出:

四、Verilog::Preproc

SigParser无法处理含有宏的或者预处理命令(如`ifdef ... `else ... `endif)的代码,将源文件通过Preproc处理后在传递给SigParser处理就可以正确的处理了。

在下面的例子中,假设要处理的verilog源文件如下所示:

module test#(
    parameter END_OF_LIST=0
)(
    input  logic            i_clk    ,
    input  logic            i_rest_n ,
    output logic [`WIDTH:0] sum      ,
    input [`WIDTH-1:0] a,b
);
logic [`WIDTH-1:0] a_ff,b_ff;
 `ifdef REGOUT
always@(posedge i_clk)begin
    if(i_rest_n == 1'b0)begin
        sum <= '0 ;
    end
    else begin
        sum <= a_ff+b_ff;
    end
end
`else
always@*begin
        sum = a_ff + b_ff ;
end
`endif
sync_cell U_A_SYNC_CELL[2:0](
    .clk   ( i_clk    ) ,
    .rst_n ( i_rest_n ) ,
    .in    ( a        ) ,
    .out   ( a_ff     )
);
sync_cell U_B_SYNC_CELL[2:0](
    .clk   ( i_clk    ) ,
    .rst_n ( i_rest_n ) ,
    .in    ( b        ) ,
    .out   ( b_ff     )
);
endmodule

如果直接用SigParser解析会报如下错误:

下面的例子,相关的参数(如宏的定义,include文件的查找目录等)通过Getopt模块处理,传递给Preproc,Preproc模块对源代码处理后再通过SigParser处理就可以了。

先通过下面的程序看一下Preproc处理后的文件是什么样的。

use Verilog::Preproc ;
use Verilog::Getopt ;

my $opt=new Verilog::Getopt ;
$opt->parameter(qw/+define+WIDTH=3/) ;

my $vp=Verilog::Preproc-> new(options=>$opt,keep_whitespace=>0,line_directives=>0) ;
$vp->open("test.v") ;
while(my $line=$vp->getline()){
    print($line) ;
}

运行后结果如下所示,可以看到`WIDTH被替换为定义的3了,由于REGOUT没有定义,所以`ifdef中的内容也不在了。


 

下面是一个完整的解析代码的例子:

$\="\n" ;
package Myparser ;
use Verilog::SigParser ;
@ISA=qw(Verilog::SigParser) ;

sub new{
    my $class=shift ;
    my $self=$class->SUPER::new() ;
    bless $self,$class ;
    return $self ;
}

sub instant{
    my $self=shift ;
    print(shift,shift,shift) ;
}

package main;
use Verilog::Getopt ;
use Verilog::Preproc ;

my $opt=new Verilog::Getopt ;
$opt->parameter(@ARGV);

my $parse=Myparser->new();
my $vp=Verilog::PReproc->new(optinons=>$opt);
$vp->open("test.v");
while(my $line=$vp->getline()){
    $parser->parse($line);
}

$parser->eof ;

上面的例子,Preproc根据输入的参数对源文件进行处理,然后将处理后的文件传递给SigParser,当传递完所有字符后,使用$parser->eof对字符进行解析。

五、Verilog::Netlist

Verilog::Netlist 用于读取和存储整个设计数据库中的互连信息。

该模块可以解析Verilog代码,获取模块的例化与连接关系。

use Verilog::Netlist;
 
# Setup options so files can be found
use Verilog::Getopt;
my $opt = new Verilog::Getopt;
$opt->parameter( "+incdir+verilog",
                 "-y","verilog",
                 "-f","test.lst"
                 );
 
# Prepare netlist
my $nl = new Verilog::Netlist(options => $opt,link_read_nonfatal=>1);
$nl->read_file(filename=>"test.v");
my $top=$nl->find_module("test");
$top->is_top(1);
# Read in any sub-modules
$nl->link();
#$nl->lint();  # Optional, see docs; probably not wanted
$nl->exit_if_error();
 
foreach my $mod ($nl->top_modules_sorted) {
    show_hier($mod, "  ", "", "");
}
 
sub show_hier {
    my $mod = shift;
    my $indent = shift;
    my $hier = shift;
    my $cellname = shift;
    if (!$cellname) {$hier = $mod->name;} #top modules get the design name
    else {$hier .= ".$cellname";} #append the cellname
    printf("%-45s %s\n", $indent."Module ".$mod->name,$hier);
    foreach my $sig ($mod->ports_sorted) {
        printf($indent."      %sput %s\n", $sig->direction, $sig->name);
    }
    foreach my $cell ($mod->cells_sorted) {
        printf($indent. "    Cell %s\n", $cell->name);
        foreach my $pin ($cell->pins_sorted) {
            printf($indent."     .%s(%s)\n", $pin->name, $pin->netname);
        }
        show_hier($cell->submod, $indent."   ", $hier, $cell->name) if $cell->submod;
    }
}

上面的例子递归打印了模块的例化关系,以及模块的端口信息。

顶层的模块需要通过read_file读取的,如果下层有例化的模块,只需要加在filelist(上例中为test.lst)中即可。

iscas2spice spice netlist generation tool -- version 2.2 by Jingye Xu @ VLSI Group, Dept. of ECE, UIC, June, 2008 This tool reads the ISCAS85 benchmark circuit "*.bench" file and translate the file into SPICE netlist using the given technology and the standard cell library. platform: linux x86 sytem Input: ISCAS85 benchmark circuit: *.bench; standard cell library: stdcells.sclb; standard cell models: stdcells.lib; interconnect paramaters: *.int; Output: SPICE netlist: out.sp The whole procedure of the tools can be divided into several steps: 1. Gate replacement: replace the gates that can't be found in the with the gates in the standard cell lib. (break.pl) Output: *.bench, *.bench.bak 2. Generate the GSRC files: generate the GSRC files for the fengshui placer. (gsrcgen.pl) Output: gsrcfile/iscas.* 3. Placement: using the fengshui placement tool to perform the component placement. (fs50) Output: gsrcfile/iscas_fs50.pl 4. Generate ISPD file: tanslate the placement results into ISPD98 format file that can be used as the input of the global router. (gsrc2ispd.pl) Output: gsrcfile/iscas.laby.txt 5. Perform the routing: use the labyrinth global router to perform the routing. (mazeRoute) Output: gsrcfile/output 6. Generate the SPICE netlist: use all the available information to generate the final SPICE netlist. (spicegen.pl) Output: out.sp Usage: iscas2spice.pl Iscas85BenchmarkFile [-C/L/N] options: -C :default value, use the RC model for interconnect -L :use the RLC model for interconnect -N :treat interconnect as short circuit wire This package used the fengshui placement tools and labyrinth global routing tools, for information regarding these two free tools, please vist: http://www.ece.ucsb.edu/~kastner/labyrinth/ http://vlsicad.cs.binghamton.edu/software.html For information regarding this software itself please visit: http://wave.ece.uic.edu/~iscas2spice Many thanks to my advisor Masud H. Chowdhury for his support!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值