Hi,我是小杜。小杜工作中经常看到验证环境中的宏定义,之前仅有一点了解,最近小杜需要用到宏,于是整理了一下宏的使用场景和注意事项。小杜经验尚浅,如有错误,还请批评指正。
宏定义`define的用法
SV中使用预处理指令`define来定义宏,宏可以用来创建文本替换。根据场景不同,`define主要用来定义常量、简化复杂的表达式或代码段以及提高代码的可移植性。其基本语法为:
`defineMACRO_NAMEreplaced_text
下面是小杜对一些使用场景的简单举例:
定义常量
`defineDATA_WIDTH 32
条件编译
`ifdef USE_SNPS_VIP ... `endif
简化复杂表达式
`defineIS_EVEN(x)((x)%2==0) initial begin num = 10; if(`IS_EVEN(num)) ... end
定义宏函数
如果需要定义带参数的宏函数,使用``来实现变量的整体替换。
`definePRINT_MAX(a, b) if((a)> (b)) $display("Maxvalue:%0b",a); else $display("Max value: %0d", b); initial begin x = 10; y= 20; `PRINT_MAX(x,y); end
`defineTEST_PARAM(X)'"test_``x``param`" $display(`TEST_PARAM(a)); //打印:test_a_param
定义信号路径
相较于上面,这是一种常用但并非spec推荐的用法,因为`define只是文本替换工具,使用宏来指代信号路径会导致信号可读性降低,在调试和维护中容易出错。但工作中真的很有用。
`define INNER_DATA u_submodule2.u_submodule1.inner_data module submodule1; reg [31:0] inner_data; initial begin inner_data = 32'hDEADBEEF; end endmodule module submodule2; submodule1 u_submodule1(); endmodule module top; submodule2 u_submodule2(); initial begin // 使用 `define 定义的信号路径 $display("Inner Data: %h", `INNER_DATA); end endmodule
`define的作用域
`define定义的宏在SV中是全局有效的,作用域从宏被定义的地方开始,一直到文件结束,或者宏被`undef显示的取消定义为止。比如经常使用宏定义信号位宽就是全局作用。
如果在被包含的文件中定义了一个宏,该宏对包含该文件的主文件以及该文件之后的所有内容有效。
//test.sv `defineTEST_NUM 100 //main.sv `include "test.sv" module to; initial begin $display("TEST_NUM:%0d", `TEST_NUM); //将打印 TEST_NUM: 100 end endmodule
使用`undef显示取消宏定义来控制宏的作用范围。
`defineMY_MACRO 32 ... `undefMY_MACRO //在`undef之后再调用MY_MACRO就会报错
`define的使用注意事项
小杜这里列举几个会经常遇到的注意事项:
尽量使用大写字母命名,以便和变量名/函数名区分开,并且一定要避免和其他宏出现命名冲突。尽量保持宏定义简单明了,保持代码的可读性和可维护性,必要时在宏定义旁添加注释。
如果使用宏定义简化表达式,最好使用括号来确保表达式求值顺序的正确,这是因为宏展开后会直接替换文本,可能会导致变量执行顺序出错。
最重要的是避免过度使用宏!!虽然宏使用起来非常方便,但对于较大的验证环境,这会导致代码可读性变差和维护难度提升。平时随手写个宏,方便了自己,但很可能会让负责环境维护的同事付出更多的时间进行维护。
以上就是小杜对SV中`define宏定义的一些总结,工作中根据需求使用`define即可。感谢你看到这里。
-
代码
+关注
关注
30文章
4779浏览量
68518 -
宏定义
+关注
关注
0文章
50浏览量
9003 -
define
+关注
关注
0文章
15浏览量
3742
原文标题:【SV】宏定义`define的使用场景和注意事项小结
文章出处:【微信号:小杜的芯片验证日记,微信公众号:小杜的芯片验证日记】欢迎添加关注!文章转载请注明出处。
发布评论请先 登录
相关推荐
评论