package包

systemverilog中的package 为在module、interface、program之间共享parameter、data、type、function、task、class等提供了额外的机制;

在package 中一般包括类型定义、task、function以及class等,这些条目(item)都不能包含层次引用,如在某个包的class 中给某个rtl路径下的变量赋值,这是不允许的;

为了在一个范围内使用 package 中的内容,必须在使用之前导入package;如果在某个 module 中导入了包,那么该包的作用域为从导入语句后往下;

需要注意的是,不同的 package 中可以包含同名的文件,原因在于在每个同名文件的作用范围都仅限于当前所在的 package,而在导入package 之后,则需要注意区分当前使用的是哪个 package 中的同名文件!!

看下面的例子:

package regs_pkg;
	'include "stimulator.sv"
	'include "monitor.sv"
	'include "chker.sv"
	'include "env.sv"
endpacakge

package arb_pkg;
	'include "stimulator.sv"
	'include "monitor.sv"
	'include "chker.sv"
	'include "env.sv"
endpackage

上面的两个包 包括4个同名的文件,但是当将二者同时在一个 module 中导入时并不会因为同名而产生,这是因为二者在两个 package 中,作用域也仅仅在 package 内部,使用时需要注明使用哪个 package 中的类:

module mcdf_tb;
	regs_pkg::monitor mon1 = new();
	arb_pkg::monitor mon2 = new();

需要注意:

 之前在项目中有遇到过,如果多个目录下有同名文件,并且这些目录的路径都被 include 进来了,此时不能保证当前 package 中 include 进来的文件是想要的文件,默认来说 通过 include 方式添加的文件是第一个具有该文件的目录下的文件,因此为了避免出现错误 include 的情况,尽量不要让不同目录下具有同名的文件!!

下面来看一个具体例子:

package color1;
	typedef enum bit[1:0] {RED, YELLOE, BLUE} color_1;
endpackage
package color2;
	typedef enum bit[1:0] {PURPLE, WHITE, BLACK} color_1;
endpackage

使用时:

一个包中可以包括另一个包,如下:

 其中package color1的定义如下:

 此时,如果想在导入 color 的module 中调用 color1 中的display1 函数,也就是实现二级引用,则需要添加上面的 export 语句,这是因为 import 操作使得display1 的可见范围仅限于 color 这个包里面,此时还需要在 module 中使用 :: 操作符,如下:

 实际上最好的方式还是直接将 color1 导入进来,如下:

 此时,不再需要使用 :: 就可以调用 display1 函数;

 包与库的区别

  • 尽管上面regs_pkg和arb_pkg中都存在着一个名字为monitor的类,我们可以在引用类名的时候通过域名索引::操作符的方式来显式支出所引用的monitor类具体来自于哪一个package,这样能很好地通过不同名的package来管理同名的类,package这个容器可以对类名做一个隔离的作用;
  • package更多的意义在于将软件(类、类型、方法等)封装在不同的命名空间中,这样就可以与全局的命名空间进行隔离,package需要额外定义,容纳各种数据、方法、类;
  • library库是编译的产物,在没有介绍软件之前,硬件(module、interface、program)都会编译到库中,如果不指定编译库的话,会被编译进入默认的库中。从容纳的类型来看,库既可以容纳硬件类型,也可以容纳软件类型,例如类和方法,也包括package
     
  • 在创建package的时候,已经在指定包名称的时候隐含地指定了包的默认路径,即包文件所在的路径。如果有其他要被包含在包内的文件在默认路径之外,需要在编译包的时候加上额外指定的搜寻路径选项“+incdir+PATH” ;
  • 如果遵循package的命名习惯,不但要求定义的package名称独一无二,其内部定义的类应该也尽可能的独一无二;

  •  

 `include 的使用

从上面对包的讲解中可以看到,`include 常用来在包中添加文件,如上面的regs_pkg,事实上 `include 有两种格式:

`include "filename"
`include <filename>#很少用

 当 filename 是绝对路径时,此时`include 进来的是绝对路径下的文件,并且只能使用"" 的方式添加进来;而如果是相对路径时,文件的搜索路径为当前工作目录和用户指定的目录,也就是说文件中 `include "相对路径" 时,这个相对路径相对的不是当前文件所在的路径,而是进行仿真的路径和设定的编译全局搜索路径!

例如dir1和dir2下都包括文件a.sv,如果在package中include a.sv,并且package 在dir2下,此时如果+incdir 添加的dir1在 dir2的前面,则此时 package 中 include 进来的 a.sv 实际上是 dir1 目录下的文件,这一点要特别注意!!

实际上,`include 就是将 .sv 文件中的内容原封不动的添加到 include 的文件的位置,常用在 top 中将 top_if_connect 文件添加进来,看下面例子:

task01.sv(后面被include文件)文件如下:

$display("task01");

 task02.sv(后面被include文件)文件如下:

$display("task02");

 task03.sv(后面被include文件)文件如下:


$display("task03");
`include "task01.sv"

 顶层:

module;
    initial begin
            `include "task01.sv"
            `include "task02.sv"
            `include "task03.sv"
    end
endmodule

结果如下:

 

 

`include 与 import 的区别:

  • `include 常用来在包中添加文件,要注意添加文件的顺序,如果某个文件引用了其他文件的内容,这个文件必须放在其他文件后添加,而 import 常用来导入包;
  • `inlcude 是将文件中的所有文本插入到包含的文件中,这是一个预处理语句,也就是说 import 在 `include 之后执行;
  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 Golang 中,可以通过创建一个共用的 package 来存放多个项目都需要的通用代码。下面是创建共用 package 的步骤: 1. 创建一个新的文件夹,用于存放共用的 package 。 2. 在该文件夹下创建一个名为 `go.mod` 的文件,用于管理 package 的依赖关系。 3. 在该文件夹下创建一个名为 `main.go` 的文件,用于编写共用的代码。 4. 在 `main.go` 中定义需要共用的函数、变量等。 5. 在需要使用该共用 package 的项目中,可以通过 `import` 语句来引用该 package 。 下面是一个示例: 假设我们需要创建一个共用的 package ,用于存放一些常用的字符串处理函数。 1. 创建一个名为 `stringutil` 的文件夹。 2. 在 `stringutil` 文件夹中创建一个名为 `go.mod` 的文件,内容如下: ``` module github.com/yourusername/stringutil ``` 其中,`yourusername` 是你的 GitHub 用户名。 3. 在 `stringutil` 文件夹中创建一个名为 `main.go` 的文件,内容如下: ```go package stringutil import "strings" func ToUpper(s string) string { return strings.ToUpper(s) } func ToLower(s string) string { return strings.ToLower(s) } ``` 其中,我们定义了两个函数 `ToUpper` 和 `ToLower`,分别用于将字符串转换为大写和小写。 4. 在需要使用 `stringutil` 的项目中,可以通过 `import` 语句来引用该 package ,例如: ```go package main import ( "fmt" "github.com/yourusername/stringutil" ) func main() { s := "Hello, World!" fmt.Println(stringutil.ToUpper(s)) } ``` 在上面的示例中,我们使用 `import` 语句来引用 `stringutil` package ,并使用 `stringutil.ToUpper` 函数将字符串转换为大写。 注意:在使用共用 package 时,需要确保该 package 已经被正确地安装和编译。你可以通过运行 `go get` 命令来安装该 package ,并在需要使用该 package 的项目中引用它。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值