从今天开始,我们介绍 Perl 在 ASIC 应用中的高级篇。高级篇主要介绍正则表达式、module、package、面向对象、进程等。
正则表达式最常见的有两个应用,高级查找和替换。而替换的核心部分也是查找。
那么,我们如何定义这个查找(或者说叫匹配)的规则。匹配的基本语法是:
m/.../
匹配规则就写在 m 开头的两个斜杠之间。
定义规则中的特殊字符称为元字符。元字符有以下这些(只列了常用的,基本够用了):
分类一:(转义)
/ 反斜杠加接元字符表示转义,比如 /+, /*, /?等,表示这些字符本身
/b 匹配单词边界
/B 非单词边界
/d 数字,就是 0-9 中的任一个字符
/D 非数字
/w 匹配大小写字母和下划线
/W 非大小写字母和下划线
/s 匹配空白字符,包括空格、制表符等
/S 非空白字符
/n 换行符,ASCII 的 0x0A
/t 制表符
/x /x 后接十六进制数,匹配这个数的 ASCII 符号
分类二:
^ 匹配开头
$ 匹配结尾
. 区配除换行符以外的所有字符
分类三:(匹配次数)
* 匹配零次或多次
+ 匹配一次或多次
? 匹配零次或一次
分类四:括号(), [], {}
() 圆括号表示取值,把()里的值存到$1, $2, ... , $n 里
[] 表示多选一。如[abc]匹配 a 或 b 或 c。连续的字符可以简写,如[a-z],[0-9]
[^] 表示[]里列出的其它字符
{n} 匹配 n 次
{n,m} 匹配 n 到 m 次
| 分组,如 m/bill|mike/,表示 bill 或 mike
? 当?跟在*,+,?等后面时,表示非贪婪模式。如,
my $test = "aaaaabb";
$test =~ m/a+?/;
匹配的结果是"a",而不是"aaaaa"
Perl 的绑定操作符
=~ 表示满足匹配
!~ 表示不满足匹配
如:
if($tc =~ m/^tc_/){ ... } 表示如果$tc 变量以 tc_ 开头,则执行{}里的语句。
if($tc !~ m/^tc_/){ ... } 表示如果$tc 变量不以 tc_ 开头,则执行{}里的语句。
正则表达式的匹配模式
i 忽略大小写
m 多行处理,即字符串中的换行符把字符串分为多行。匹配时不能越行
s 单行处理,在这个模式下,元字符 . 可以匹配换行符
x 允许正则表达式换行和加注释,忽略空白字符
g 查到全局所有可能的匹配,即会匹配多次
e 用于替换,表示替换的新值要先计算,如
s/(ab+c)/&replace($1)/e
表示查换 ab+c,并把找到的结果传给 replace()函数,用函数的返回值来替换。这种方法可用于复杂的查找替换。这种用法,我在编辑 APR 的 IO 坐标文件时实际用过,比 GVIM 或者 Emacs 的列填充更强大。
下面举几个例子:
1. m/(output|input|inout)/s+wire|reg/s*(/[.*/])?(/w+),/ 脚本提取 RTL 端口定义
2. s//s*(/w+)/s*/.$1/t/t($1)/ 可用来模块例化时,自动连接端口
3. my @testcase = `ls`;
foreach my $tc (@testcase){
if($tc =~ m/^tc_/){
... #查找目录下的"tc_"开头所有的文件名,在写仿真脚本时常用到
}
}
4. if($pwd =~ m///(trunk|tags|release)$/){
... #通过脚本确认当前目录是否是项目根目录
}
Perl 正则表达式是非常博大精深的,需要在工作中慢慢积累。所以,今天的练习题多一点,主要是想多提供一些实际使用场景,并自己动手解决问题。
练习题:
1. 用正则表达式从 RTL 里抓取所有寄存器的路径。(用于自动产生 UVM 寄存器模型)
2. 用正则表达式把门级网表拆分成多个仅包含单个 module 的文件。
3. 用正则表达式把 PR 网表中大小写敏感的 net 改成大小写不敏感。(用于 calibre 做 LVS)
下一次,我们将开始介绍 module。
审核编辑 黄宇
-
asic
+关注
关注
34文章
1182浏览量
120215 -
PERL
+关注
关注
0文章
14浏览量
10376
发布评论请先 登录
相关推荐
评论