Advertisement

IEEE Standard for SystemVerilog Chapter 22. Compiler directives

阅读量:

22.1 General

此子句描述以下编译器指令(按字母顺序列出):
__FILE__ [22.13] LINE [22.13]
begin_keywords [22.14] celldefine [22.10]
default_nettype [22.8] define [22.5.1]
else [22.6] elsif [22.6]
end_keywords [22.14] endcelldefine [22.10]
endif [22.6] ifdef [22.6]
ifndef [22.6] include [22.4]
line [22.12] nounconnected_drive [22.9]
pragma [22.11] resetall [22.3]
timescale [22.7] unconnected_drive [22.9]
undef [22.5.2] undefineall [22.5.3]

22.2 Overview

所有编译器指令前面都有(`)字符。此字符称为 抑音符(ASCII 0x60)。它与字符(')不同,后者是撇号字符(ASCII 0x27)。编译器指令的范围从当前编译单元中处理的所有文件的处理点扩展到另一个编译器指令取代它或编译单元的处理完成的点。编译器指令的语义在3.12.1和5.6.4中进行了定义。

22.3 `resetall

当在编译过程中遇到“restall编译器指令”时,所有编译器指令都设置为默认值。这对于确保只有编译特定源文件所需的指令处于活动状态非常有用。 建议的用法是将“resetall”放在每个源文本文件的开头,然后紧跟文件中所需的指令。在设计元素中指定“restall指令”是违法的。并非所有编译器指令都有默认值(例如“define”和“include”)。 没有默认值的指令不受“restall”的影响。

22.4 `include

文件包含(include)编译器指令用于在编译期间将源文件的全部内容插入另一个文件中。 结果是,所包含的源文件的内容似乎代替了include编译器指令出现。
语法22-1中给出了`include编译器指令的语法。

复制代码
 include_compiler_directive ::=

    
     `include " filename "
    
     | `include < filename >
    
    
    
    

Syntax 22-1—Syntax for include compiler directive (not in Annex A)
编译器指令include可以在SystemVerilog源描述中的任何位置指定。只有空白或注释可以出现在include编译器指令的同一行。
文件名是要包含在源文件中的文件的名称。
文件名可以是完整的或相对的路径名。
文件名可以用引号或尖括号括起来,这会影响工具搜索文件的方式,如下所示:
--当文件名用双引号(“filename”)括起来时,将搜索编译器的当前工作目录以及用户指定的位置的相对路径。
--当文件名包含在尖括号(<filename>)中时,则仅依赖于实现搜索包含由语言标准定义的文件的位置。相对路径名称是相对于该位置进行解释的。
当文件名是绝对路径时,只包括该文件名,并且只能使用include的双引号形式。使用“include编译器指令”包含在源中的文件可能包含其他“include编译程序指令”。包含文件的嵌套级别的数量应是有限的。实现可能会限制包含文件可以嵌套的最大级别数,但该限制应至少为15。 “include编译器指令”的示例如下:

复制代码
 `include "parts/count.v"

    
 `include "fileB" // including fileB
    
 `include <List.vh>
    
    
    
    

22.5 define, undef, and `undefineall

提供了文本宏替换功能,以便使用有意义的名称来表示常用的文本片段。例如,在整个描述中重复使用常量的情况下,如果需要更改常量的值,则只需要更改源描述中的一个位置,因此文本宏将非常有用。
文本宏功能不受编译器指令“`resetall”的影响。

22.5.1 `define

指令“define”创建了一个用于文本替换的宏。此指令既可用于设计元素内部,也可用于设计元素外部。定义文本宏后,可以在源描述中使用(`)字符,后跟宏名称。编译器应将宏的文本替换为字符串“text_macro_name”及其后面的任何实际参数。所有编译器指令都应被视为预定义的宏名称;将编译器指令重新定义为宏名称是违法的。
文本宏可以用参数定义。这允许为每次单独使用自定义宏。
语法22-2给出了文本宏定义的语法。

复制代码
 text_macro_definition ::=

    
     `define text_macro_name macro_text
    
 text_macro_name ::=
    
     text_macro_identifier [ ( list_of_formal_arguments ) ]
    
 list_of_formal_arguments ::=
    
     formal_argument { , formal_argument }
    
 formal_argument ::=
    
     simple_identifier [ = default_text ]
    
 text_macro_identifier ::=
    
     identifier
    
    
    
    

Syntax 22-2—Syntax for text macro definition (not in Annex A)

宏文本可以是与文本宏名称在同一行上指定的任意文本。如果指定文本需要多行,换行符前面应加一个反斜杠(\)。第一个没有反斜杠的换行符应结束宏文本。
在扩展宏中,以反斜杠开头的换行符应替换为换行符(但不包括前面的反斜杠)。当使用形式参数定义文本宏时,形式参数的范围应延伸到宏文本的末尾。
形式参数可以在宏文本中以与标识符相同的方式使用。如果使用了形式参数,则形式参数名称列表应包含在宏名称后面的括号中。形式参数名称应为simple_identifiers,用逗号和空格分隔(可选)。左括号应紧跟在文本宏名称后面,中间不得有空格。形式宏参数可能有默认值。默认值是通过在正式参数名称后附加一个=标记,后跟默认文本来指定的。如果未指定相应的实际参数,则将用默认文本替代形式参数。
默认文本可以显式指定为空,方法是在正式参数名称后添加=标记,后跟逗号(如果它是参数列表中的最后一个参数,则可以使用右括号)。如果文本中包含单行注释(即用字符//指定的注释),则该注释不应成为替换文本的一部分。宏文本可以为空,在这种情况下,文本宏被定义为空,并且在使用宏时不会替换任何文本。
语法22-3中给出了使用文本宏的语法。

复制代码
 text_macro_usage ::=

    
     `text_macro_identifier [ ( list_of_actual_arguments ) ]
    
 list_of_actual_arguments ::=
    
     actual_argument { , actual_argument }
    
 actual_argument ::=
    
     expression 
    
    
    
    

Syntax 22-3—Syntax for text macro usage (not in Annex A)
对于没有参数的宏,每次出现`text_macro_identifier时,都应按原样替换文本。但是,具有一个或多个参数的文本宏应通过将每个形式参数替换为宏使用中用作实际参数的表达式来进行扩展。
要使用用参数定义的宏,文本宏的名称后面应加上一个用逗号分隔的括号中的实际参数列表。实际参数和默认值不应在匹配的左右括号()、方括号[]、大括号{}、双引号“”或转义标识符之外包含逗号或右括号字符。
在宏使用中,文本宏名称和左括号之间应留有空白。实际参数可能为空或仅为空白,在这种情况下,如果指定了参数default,则形式参数将被替换;如果未指定默认值,则不替换。如果指定的实际参数少于形式参数的数量,并且所有剩余的形式参数都有默认值,则将用默认值替换其他形式参数。如果任何剩余的形式参数没有指定默认值,则这将是一个错误。对于带参数的宏,即使所有参数都有默认值,在宏调用中也始终需要括号。指定的实际参数多于正式参数的数量是错误的。
没有默认值的宏示例:

复制代码
 `define D(x,y) initial $display("start", x , y, "end");

    
 `D( "msg1" , "msg2" )
    
 // expands to 'initial $display("start", "msg1" , "msg2", "end");'
    
 `D( " msg1", )
    
 // expands to 'initial $display("start", " msg1" , , "end");'
    
 `D(, "msg2 ")
    
 // expands to 'initial $display("start", , "msg2 ", "end");'
    
 `D(,)
    
 // expands to 'initial $display("start", , , "end");'
    
 `D( , )
    
 // expands to 'initial $display("start", , , "end");'
    
 `D("msg1")
    
 // illegal, only one argument
    
 `D()
    
 // illegal, only one empty argument
    
 `D(,,)
    
 // illegal, more actual than formal arguments
    
    
    
    

具有默认值的宏示例:

复制代码
 `define MACRO1(a=5,b="B",c) $display(a,,b,,c);

    
 `MACRO1 ( , 2, 3 ) // argument a omitted, replaced by default
    
  // expands to '$display(5,,2,,3);'
    
 `MACRO1 ( 1 , , 3 ) // argument b omitted, replaced by default
    
  // expands to '$display(1,,"B",,3);'
    
 `MACRO1 ( , 2, ) // argument c omitted, replaced by nothing
    
  // expands to '$display(5,,2,,);'
    
 `MACRO1 ( 1 ) // ILLEGAL: b and c omitted, no default for c
    
 `define MACRO2(a=5, b, c="C") $display(a,,b,,c);
    
 `MACRO2 (1, , 3) // argument b omitted, replaced by nothing
    
  // expands to '$display(1,,,,3);'
    
 `MACRO2 (, 2, ) // a and c omitted, replaced by defaults
    
  // expands to '$display(5,,2,,"C");'
    
 `MACRO2 (, 2) // a and c omitted, replaced by defaults
    
  // expands to '$display(5,,2,,"C");'
    
 `define MACRO3(a=5, b=0, c="C") $display(a,,b,,c);
    
 `MACRO3 ( 1 ) // b and c omitted, replaced by defaults
    
  // expands to '$display(1,,0,,"C");'
    
 `MACRO3 ( ) // all arguments replaced by defaults
    
  // expands to '$display(5,,0,,"C");'
    
 `MACRO3 // ILLEGAL: parentheses required
    
    
    
    

一旦定义了文本宏名称,它就可以在编译单元中定义它的任何地方使用。 一旦进入编译单元,就没有其他范围限制。实现方式还可以允许以交互方式定义和使用文本宏。
为宏文本指定的文本不得拆分为以下词法标记:
— Comments
— Numbers
— String literals
— Identifiers
— Keywords
— Operators
例如:

复制代码
 `define wordsize 8

    
 logic [1:`wordsize] data;
    
 //define a nand with variable delay
    
 `define var_nand(dly) nand #dly
    
 `var_nand(2) g121 (q21, n10, n11);
    
 `var_nand(5) g122 (q22, n10, n11);
    
    
    
    

以下是非法语法,因为它被拆分为一个字符串:

复制代码
 `define first_half "start of string

    
 $display(`first_half end of string");
    
    
    
    

每个实际的参数都被相应的形式参数从字面上取代。因此,当一个表达式用作实际参数时,该表达式将被整体替换。如果在宏文本中多次使用形式参数,这可能会导致表达式被多次求值。
例如:

复制代码
 `define max(a,b)((a) > (b) ? (a) : (b))

    
 n = `max(p+q, r+s) ;
    
    
    
    

将被扩展为:

复制代码
    n = ((p+q) > (r+s) ? (p+q) : (r+s)) ;
    

这里,两个表达式p+q和r+s中较大的一个将被求值两次。define这个词被称为编译器指令关键字,它不是正常关键字集的一部分。因此,SystemVerilog源描述中的正常标识符可以与编译器指令关键字相同。
应考虑以下问题:
a) 文本宏名称不得与编译器指令关键字相同。
b) 文本宏名称可以重用用作普通标识符的名称。例如,signal_name和signal_name是不同的。 c) 允许重新定义文本宏;由读取的特定文本宏的最新定义。当在源文本中遇到宏名称时,编译器占上风。 宏文本和参数默认值可能包含其他文本宏的用法。此类用法应在外部宏被替换后进行替换,而不是在定义时进行替换。 如果实际参数或参数默认值包含宏用法,则只有在替换为外部宏文本后,才能扩展宏用法。如果一个形式参数有一个非空的默认值,并且希望用一个空的实际参数替换该形式参数,则不能简单地省略实际参数,因为这样就会使用默认值。但是,可以定义一个空文本宏,比如empty,并将其用作实际参数。它将取代形式参数,并在展开空文本宏后被空文本替换。当宏用法作为实际参数或默认参数传递给另一个宏时,参数扩展不会将形式参数的新用法引入顶级宏。
示例:

复制代码
 `define TOP(a,b) a + b

    
 `TOP( `TOP(b,1), `TOP(42,a) )
    
    
    
    
复制代码
 扩展到: b + 1 + 42 + a

    
 not into: 42 + a + 1 + 42 + a
    
 nor into: b + 1 + 42 + b + 1
    
    
    
    

宏直接或间接扩展到包含其自身另一用法的文本(递归宏)是错误的。但是,宏或默认值的实际参数可能包含其自身的用法,如前面的示例所示。字符串文字中不应出现宏替换和参数替换。例如:(字符串中的宏不会替换),例如 define LO "HI, world" ,`HI不会替换为Hello。

复制代码
 module main;

    
     `define HI Hello
    
     `define LO "`HI, world"
    
     `define H(x) "Hello, x"
    
  
    
 initial begin
    
     $display("`HI, world");
    
     $display(`LO);
    
     $display(`H(world));
    
     end
    
 endmodule
    
    
    
    

打印结果如下:

复制代码
 `HI, world

    
 `HI, world
    
 Hello, x
    
    
    
    

define宏文本还可以包括"、\" 和``。
"覆盖了的常用词汇含义",表示扩展应包括引号、实际参数的替换和嵌入宏的扩展。 这允许从宏参数构造字符串文字。 宏文本中允许混合使用"和",但是使用 " 总是以字符串文字开头,并且必须具有终止符 "。
嵌入此字符串文本中的任何字符,包括",都将成为替换的宏文本中字符串的一部分。因此,如果" 后面跟有",则 " 将启动最后一个字符为 的字符串文字,并以 " of"结尾。'' 表示展开应该包括转义序列 " 。
例如:

复制代码
    `define msg(x,y) `"x: `\`"y`\`"`"
    

使用`msg宏的一个示例:

复制代码
     $display(`msg(left side,right side));
    

上面的例子扩展为:

复制代码
    $display("left side: \"right side\"");
    
    

' '在不引入空格的情况下对词法标记进行定界,从而允许根据参数构造标识符。例如:

复制代码
    `define append(f) f``_master
    

使用`append宏的一个示例:

复制代码
    `append(clock)
    

这个示例被扩展为:

复制代码
    clock_master 
    

`include指令后面可以跟一个宏,而不是字符串文字:

复制代码
 `define home(filename) `"/home/mydir/filename`"

    
 `include `home(myfile)
    
    
    
    

22.5.2 `undef

如果指令undef以前是由编译单元中的define编译器指令定义的,则该指令undf应取消对指定文本宏的定义。尝试使用define编译器指令取消定义以前未定义的文本宏可能会发出警告。`undef编译器指令的语法在语法22-4中给出。

复制代码
 undefine_compiler_directive ::=

    
     `undef text_macro_identifier
    
    
    
    

Syntax 22-4—Syntax for undef compiler directive (not in Annex A)

未定义的文本宏没有值,就像从未定义过一样。

22.5.3 `undefineall

undefineall指令应取消定义编译单元内define编译器指令先前定义的所有文本宏。此指令不接受任何参数,并且可能出现在源描述中的任何位置。

全部评论 (0)

还没有任何评论哟~