SV——package

1. package

SystemVerilog中package是用来在多个modules、interfaces、programs和checkers之间共享parameter、net、variables、type、task、function、sequence、property和checker declaration这些东西。

package是最外层的命名空间,在package中可以定义parameter、net、variables、type、task、function、sequence、property和checker declaration这些东西。

2. package declarations

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package package_name;
// 这些里可以声明一些东西
// net_declaration
// data_declaration
// task_declaration
// function_declaration
// checker_declaration
// dpi_import_export
// extern_constraint_declaration
// class_declaration
// class_constructor_declaration
// local_parameter_declaration ;
// parameter_declaration ;
// covergroup_declaration
// assertion_item_declaration
endpackage

// 一个package例子
package ComplexPkg;
typedef struct {
shortreal i, r;
} Complex;
function Complex add(Complex a, b);
add.r = a.r + b.r;
add.i = a.i + b.i;
endfunction
function Complex mul(Complex a, b);
mul.r = (a.r * b.r) - (a.i * b.i);
mul.i = (a.r * b.i) + (a.i * b.r);
endfunction
endpackage : ComplexPkg

3. using package

使用package中的定义,用作用域符号 ::

1
2
// 使用上面定义的结构体Complex和函数mul
ComplexPkg::Complex cout = ComplexPkg::mul(a, b);

还可以使用import关键字引入package中定义的对象,在使用这些对象的时候不用加包名和作用域符号了。

1
2
3
import package_name::package_item;//引入包中定义的package_item对象
// 或者
import package_name::* //引入包中定义的所有对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package p;
typedef enum { FALSE, TRUE } bool_t;
endpackage
package q;
typedef enum { ORIGINAL, FALSE } teeth_t;
endpackage
module top1 ;
import p::*;
import q::teeth_t;
teeth_t myteeth;
initial begin
myteeth = q:: FALSE; // OK:
myteeth = FALSE; // ERROR: Direct reference to FALSE refers to the
end // FALSE enumeration literal imported from p
endmodule
module top2 ;
import p::*;
import q::teeth_t, q::ORIGINAL, q::FALSE;
teeth_t myteeth;
initial begin
myteeth = FALSE; // OK: Direct reference to FALSE refers to the
end // FALSE enumeration literal imported from q
endmodule

package定义在文件中,需要先将文件名 `include才可以import

1
2
`include "pkg.sv"
import package_name;

4. 作用域冲突

package还有一些作用域冲突的问题,比如package的作用域是在top层,如果import的package中定义的变量与原来top层的变量名字一样就会发生冲突,具体参见SV手册吧。

5. package的编译顺序

如果有多个package之间相互import的情况,那么在VCS编译的时候,被引用的package要写在前面,比如

1
vcs ... -f filelist

在filelist中,package文件的顺寻有要求

1
2
3
#filelist
./packages/pkg1.sv
./packages/pkg2.sv

被引用的写在前面。

6. 使用中的gotcha(”陷阱“)

  1. 通过import package得到的变量不能被hierarchy access,只能通过作用域符号访问。

    Hierarchical paths are used to access signals where they are declared.

  2. 对枚举类型import,只是import枚举的名字,没有import枚举标签,不能直接使用枚举的标签。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    package chip_types;
    typedef enum logic [1:0] {RESET, HOLD, LOAD, READY} states_t;
    endpackage
    module chip (... );
    import chip_types::states_t; II explicit import of states t type
    states_t state_e, nstate_e;
    always_ff @(posedge clock, negedge reset_n)
    if (!reset_n) state_e <= RESET; II GOTCHA: RESET not imported
    else state_e <= nstate_e;
    endmodule

    可以通过通配符import方式,这样会将枚举的名字和标签都引进来。

    1
    import chip_types::*;

    当然也可以通过分别将标签枚举进来。

    1
    2
    3
    4
    5
    import chip_types::states_t; II explicit import of states t type
    import chip_types::RESET; II and its labels
    import chip_types:: HOLD;
    import chip_types::LOAD;
    import chip_types:: READY ;
  3. 当多个package中的标识符冲突时,import通配符会编译出错。

    The gotcha with wildcard package imports occurs when there are identifiers
    common to more than one package, To avoid this gotcha, explicitly import any
    duplicate identifiers from the desired package. Wildcard imports of other packages will not import identifiers that have been explicitly declared or explicitly imported in the localscope

    1
    2
    3
    import chip_types::*; II wildcard import of a package
    import bus_types::*; II wildcard import of another package
    import chip_types::HOLD; II explicit import of HOLD