上海台风天气,哪也去不了,就又敲了一篇文章。讲讲SystemVerilog中的Package。
Package的应用通常在代码文件较多或者复用别人的代码的时候会用到,这就导致了这块东西容易被忽略。本文内容分两部分,第一部分通过类比来介绍package包的两大作用,第二部分将提供package的代码例程作为编程指导。
Package两大作用
Package这个概念在很多编程语言中都有对应的语法结构,比如Python、Java、Perl等等,足以说明它有多么重要!Package有两大作用,一方面是为了代码分发,package提供了代码封装效果,提高了代码的重用性(reuseability);另一方面是为了提供对代码元素(比如数据结构、函数等)访问权限的控制机制。
先看看第一件事情,代码分发。代码分发(release)是软件开发工程中非常常见的需求,换句话说可以理解为代码的发布和复用方式。代码分发本身没有一个严格的规范,更多的是按照协作者之间约定好的方式就可以进行了。这样一来,代码分发的方式就非常多样,可以只是源代码的拷贝,可以是提供一个文件列表(filelist),也可以是通过Package包来发布等等。
Package在代码分发上的作用不容忽视,举两个例子,在Python开发中经常会依赖于各种各样的轮子(wheel),当我们需要哪些功能的时候就导入对应的package,这样就可以尽情地使用这些package中提供的函数了;UVM作为目前最通用的芯片验证方法学,它的代码库同样是通过package来进行封装和发布的。
再看看第二件事情,访问权限控制。访问控制(access control)是代码管理中经常会关注的点:比如在类成员和函数的可用范围上,提供了封装特性(public/protected/local);又比如为了避免继承导致的函数冲突,提供了多态特性(polymorphism);现在在更高层面上,比如类定义、参数定义、接口定义等,提供了package包的概念作为区分。
在访问权限控制上,package跟C++中的命名空间(namespace)的概念是相似的。举个栗子,假设你有两个叫二狗的同学,为了区分他们,你可能会这么记他们:王家的二狗叫王二狗,李家的二狗叫李二狗,当然只有一个人的时候你可以不加姓的叫二狗。对应到代码中实际上是一样的,当我们无法区分来自两个不同package的同名函数时,可以直接在函数前面加上package的名字来区分。
Package编程指导
Package提供了可方便在不同代码块中共享的声明空间(declaration space)。在该空间内,可以定义很多东西,包括typedef、struct、import、task、functions、const、parameter、localparameter、class等,该空间可以通过import被导入到module、interface、program甚至其他package里面。
包含有Package的代码,在编译之后包的内容会被放到当前的工作库(work)中,在实现阶段才会被实例化。尽管如此,我们还需要确保在import之前你的package已经首先完成了编译,所以可以关注一下编译顺序,避免package导入错误。
在引用package内容存在命名冲突的时候,可以加上package的名字和::符号来做具体区分。在没有命名冲突的时候,可以直接大胆地引用package中的内容。如果要引用嵌套在package中的子package中的内容,直接引用是不行的,同样需要加上子package的名字和::符号。
另外,SystemVerilog有内置的package,那就是std,因为有了std我们在可以直接使用旗语(semaphore)、信箱(mailbox)还有一些随机函数等等。不过这不重要,压根不需要去注意到它。
文件1:
文件2:
仿真结果:
参考资料
[1] IEEE Standard Association. "IEEE Standard for SystemVerilog-Unified Hardware Design, Specification, and Verification Language." (2013).