Perl在ASIC中的应用——实战篇:网表处理

Posted ExASIC

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Perl在ASIC中的应用——实战篇:网表处理相关的知识,希望对你有一定的参考价值。


今天开始讲Perl语言在网表处理中的一些应用。我们都听说Perl的优势是文本处理,而我们的网表正是有一定语法格式的文本。简单点说,就是用Perl对网表中的内容进行高级查找替换


我们看一些实际中遇到的需求:

  1. 在综合网表的开头插入一些注释,比如网表产生的时间日期。

  2. 用buffer替换网表中的assign语句。

  3. 把寄存器register file模块的DFF全部替换成同时带复位reset、置位set、输出Q和Q非的DFF。

  4. 把网表wire名称大小写敏感转成大小写不敏感。


插入注释

原理:用Perl先读入原网表到内部数组,利用数组的索引确定插入的位置。

例如

#读入原网表

my @netlist;

open(FH_I, "<digital.v");

@netlist = <FH_I>;

close(FH_I);

#定义待插入的内容

my $now = `date +%Y-%m-%d' '%H:%M:%S`;

my $insert = "//this netlist is generated on $now\n";

#插入并写出网表

my $len = $#netlist;

open(FH_O, ">digital_new.v");

my $num = 10; #指定插入的行号

my $i;

for($i=0; $i<$num - 1; $i++){  #先输出插入行之前的内容

    print FH_O shift(@netlist);

}

print FH_O "$insert";               #输出新插入的内容

for($i=$num - 1; $i<=$len; $i++){   #最后输出剩下的内容

    print FH_O shift(@netlist);

}

上面这段Perl代码实现了在指定行号位置插入文件。如果指定行号为0,就表示插在网表的开头。如果指定行号为$len+1,就表示插在网表末尾。这段代码是不是很简单?有人说“我可以用sed命令一行代码就实现了”。是的,sed命令的确很好用。Perl的优势是灵活、高效,适合较复杂的情形,并且对超大型网表速度也很快


处理assign语句

在综合或者PR网表里,偶尔会出现assign语句。当然在综合时应该首先尽量用DC或RC去处理through型连线,multiple port net,常量等。我们这里的办法只是没有办法的办法。对于一条assign语句格式通常如下:

    assign B = A;

而BUF的例化格式:

    BUF0 u_buf_fix_assign_0 (.Z(B), .I(A));

所以我们需要一个高级查找替换,帮我们做这个事情。如果网表中有多处assign,那么BUF0的例化名需要每次加1。

my $netlist = "";

open(FH_I, "<digital.v"); #读入网表

while(<FH_I>){

    $netlist .= $_;

}

close(FH_I);

#查找替换

local $i = 0; #子函数里可以修改

$netlist =~ s/^\s*assign\s+(\w+)\s*=\s*(\w+)\s*;/&replace_assign($1, $2)/ge;

open(FH_O, ">digital_new.v");

print FH_O "$netlist";

close(FH_O);


sub replace_assign {

    our $i;

    my $B = shift;

    my $A = shift;

    my $ret = "\tBUF0 u_buf_fix_assign_$i (.Z($B), .I($A));\n";

    $i++; #用全局变量

    return $ret;

}

上面利用正则s///e来调用子函数实现复杂的替换,而s///g用来做全局替换。


DFF换类型

为了方便做ECO把register file的DFF换成同时带复位reset、置位set、输出Q和Q非的DFF。比如有DFFR和DFFSRQ:

DFF u_dff (.Q(Q),

                    .CLK(CLK),

                    .R(R),

                    .D(D));

DFFSRQ u_dff (.Q(Q),

                    .QN(),

                    .CLK(CLK),

                    .R(R),

                    .S(tiehi_net),

                    .D(D));

我们就可以查找reg_file中的DFF替换成DFFSRQ。初一看和assign处理的情况有点类似,但又有点不一样。不一样在这里的install写成了多行。我这里就只写出替换部分的代码:

$netlist =~ s/^\s*DFF\s+(\w+)\s+\(    #取instance名

                             \.Q\(        (\w+)  \),   #取Q的wire

                             \.CLK\(   (\w+)  \),   #取CLK的wire

                             \.R\(        (\w+)  \),   #取R的wire

                             \.D\(        (\w+)  \)    #取D的wire

                             \);/&replace_dff($1, $2, $3, $4, $5)/xge;

sub replace_dff {

    my $inst = shift;

    my $Q = shift;

    ...

    my $ret =  "DFFSRQ u_dff (.Q($Q), \n";

    $ret .= "                .QN(), \n";

    $ret .= "                .CLK($CLK), \n";

    $ret .= "                .R($R), \n";

    $ret .= "                .S(tiehi_net),  \n";

    $ret .= "                .D($D)); \n";

}

有些童鞋可能已经注意到了s///x,这里的x是为了正则表达式可以换行、加空白字符,还可以加注释。是不是很方便?


大小写敏感变不敏感

在verilog里是大小写敏感的,仅大小写不同的变量,如ABC、abc、Abc是三个不同的变量。但模拟电路里通常不做区别,认为是同一个变量。所以在用calibre做chip层LVS时,需要大小写不敏感的数字电路。我们假设网表里有:

wire n1;

wire n2;

wire N1;

wire N2;

wire n3;

一个简单粗暴的方法是把所有大写的“N加数字”的变量后面加上下划线,即N1->N1_,N2->N2_,N3->N3_,虽然N3不需要转换。

s/^\s*wire\s+N(\d+)\s*;/\twire N$1_;/g

所有instance连线的地方也需要转换。

s/\.(\w+)\s*\(N(d+)\)/.$1(N$2_)/g;


我们接着寻找更好的解决方案:

把网表拆分成若干个单个模块,在每个模块内查找大小写敏感的变量,然后再逐个转换。这个就当作今天的练习题吧!


下一次,我们介绍Perl的图形界面编程在仿真和测试中的应用。


如果觉得本文对你有帮助请转发转载以帮助更多的人。如果有建议或问题也欢迎直接留言讨论。


广告

******************************************

数字后端网表ECO软件:Gates On the Fly(GOF) 5.3

http://www.nandigits.cn

******************************************

--------------------

欢迎关注ExASIC. 分享芯片数字集成电路设计中的经验和方法。Sharing makes work smoother.

以上是关于Perl在ASIC中的应用——实战篇:网表处理的主要内容,如果未能解决你的问题,请参考以下文章

双十一福利:《Perl在ASIC中的应用》pdf下载

R语言实战应用精讲50篇(二十八)-R语言时空数据分析实战案例-数据处理及可视化

R语言实战应用精讲50篇(二十八)-R语言时空数据分析实战案例-数据处理及可视化

用Perl处理语言信息问题之一

SpringBoot实战 之 异常处理篇

SpringBoot实战 之 异常处理篇