路科验证(Rocker IC)专注于验证系统思想和前沿工程资讯,拥有一支活跃的技术原创团队,著有《芯片验证漫游指南》一书,致力为高校微电子相关专业学生与IC从业人员提供技术食粮。 您可以在手机移动端同步关注微信订阅号“路科验证”或是登录网页www.rockeric.com了解更多资讯。如果您需要联系我们,请发送邮件至 bin.rocker.liu@intel.com 。

SV及UVM高级话题篇之一:SystemVerilog开源公共库(上)

上一篇 / 下一篇  2018-06-12 21:02:20 / 个人分类:验证系统思想

  

伴随着SV推广的热浪,SV已经不只是作为一种验证语言流行开来,实际上它同样在早期也作为了一种硬件描述语言和一种通用编程语言得到了应用。在软件编程的过程中,SV同Java一般也有了更为丰富的数据类型和类的相应概念,这种面向对象编程的思想使得一些软件工程师在“移民”到验证领域时的阵痛期并不会太久,但随后他们会感到一些失望,因为SV尽管有着类Java的编程方式、内存管理方式等等,但又缺少一些东西,比如在一些底层数据类型操作的函数在使用起来有点掣肘,下面是一些数据:


这张表格是对于各个主流编程语言中对于字符串String类型的函数数量对比,而更习惯于软件编程的用户(同时精通于Java、Python等)就会对SV目前底层函数的支持表示不满。这些软件用户们更怀念过去在Java、Python中各种丰富的底层函数应用,而从硬件一侧迁移到SV的新用户们则有点“刘姥姥进大观园”,已经觉得新添加的特性有点应接不暇,够学几辈子的了(比起之前的HDL硬件编程需要的语法来看)。


Python的忠实粉丝都知道Python世界的一句谚语“Batteries included”,这指的是官方发行的Python版本自带了相当齐全的软件库,拿来就可以直接写程序,一般不需要安装额外的库,就同一出生就含着金钥匙为自己生命代言的天才一样,做什么都是手到擒来。而SV的用户,尤其在适应了软件编程思维,同时又熟悉一些其它编程语言特性的时候,就对SV缺少像Python一样丰富底层函数的气质颇有微词了。


所以,那些见识过“好东西”的verifier们就局部地联合了起来(公共的验证开源项目数量少而死亡率太高),他们首先在自己的公司内部按照所处项目的实际要求,试图在SV基础上开发一些扩展地库,来弥补一些SV应该具备的底层库;同时,在这些库后来日益完善的基础上,经过公司的同意,他们将这些库开源了出来,并希望不断更新(或者被收入SV的标准第三方库)。我们本节为大家分享两个开源质量较高且至今保持活力的SV的第三方库,通过简明地介绍它们的主要特性,希望读者们首先知道这些库提供的基本特性,而在后期项目使用中,如果有需要就可以快速安装它们,不必再重复造轮子。同时,我们也希望通过本节,读者在以后的工作中,可以有目的性地将库分为公共库(有更广的使用潜力)和VIP库(更有针对性),而将过去那些有收录进公共库潜力的方法、类可以整理到一起,相应地做好单元测试(库开发的标准流程)和文档,造福公司内更多的同事,或者在允许的情况下也开源出来。


SV开源库之一:svlib

Verilog公司开源了他们之前开发的SV的扩展底层库svlib,这个库可以从这个链接中找到。另外既然推荐了他们的功德库svlib,也简单介绍一下这家公司,作为他们共享svlib的一点回报吧。路桑跟这家公司之前在项目中有过合作,他们是一家“高端”的验证咨询公司,可以说里面的接触到的每一位工程师都很有气质(验证工程师的软硬通吃的气质),而且个个以一当十。截止到目前他们在中国还没有直接的业务,但如果接下来他们进入中国寻求业务而且在招聘质量不打折的前提下,这是一家提供良好咨询服务平台的公司。好了,这一段软广告就嵌入到这里吧。

www.verilab.com/resources


svlib分成了若干个分支,不同分支具备相应的功能,这些可以拆解和独立开发的功能包括有:

  • 通用的字符串处理和正则表达式功能。

  • 可以对文件和目录操作的功能,包括目录查找、列表、文件属性征询的功能。

  • 可以同操作系统互动的功能,包括有查找环境变量、传入命令行、时钟日期信息查询等功能。

  • 各种其它方便的功能,例如与枚举类型相关的函数操作。

  • 成套的插件用来从.ini或者YAML配置文件读入,继而存储为配置数据格式DOM;或者反之,从DOM格式,存为.ini或者YAML标准格式。


另外,svlib也有类似uvm_macros.svh的宏文件svlib_macros.svh,该文件也定义了一些易用的宏,方便使用者。下面我们就上面的几种主要的功能做简单介绍。


字符串处理

正如上面拿字符串string类型的例子,SV的string有一点尴尬的是,它并不允许直接让用户在string类型上面扩展,而尽管它看起来就有点像类,但又无法去继承。

string S = "   Some text   ";

int n = S.len();

S = S.toupper();


对于上面字符串的操作,跟对象的使用很像,但如果像扩展string类型,只能考虑在svlib中添加一个新的类Str,通过类的方法来实现扩展。例如下面的例子:

Str ss = Str::create("   Some text   ");

ss.trim(Str::Right);

$display("\"%s\"", ss.get());

输出结果:

"   Some text"


通过添加新的字符串类Str(内嵌string变量并且对其操作),这可以在原有string类型的基础上扩展更多需要的方法,例如上面的去除字符串右边的空格。这个新的方法看起来可以带来更多新的特性,但同时也带来了一点麻烦。例如原有的SV用户已经习惯于对string变量本身的操作、通过操作符例如{}来合并字符串、或者直接赋值的形式来获取字符串内容等,这一点同新添加的Str类通过自带函数的操作有明显的差别。


如果SV的用户不习惯新的方式,又或者原有的SV代码不想大规模改动的时候怎么办呢?svlib同时也提供了经典的package内建函数的形式,将一些主要的函数也同时按照就有的函数操作的形式来实现。

$display("\"%s\"", str_strim(S, Str::BOTH));

输出结果:

"Some text"


上面这个方式更贴近于原有的字符串操作,用户可以选择任何一种方式来实现字符串的操作。


正则表达式处理

对于熟悉正则表达式的读者,尤其是Python中正则表达式习惯的读者,对于svlib中新添加的正则表达式类Regex和其函数处理应该不会感到陌生。

Regex re;

re = regex_match("06/07/17", "([0-9]+)/([0-9]+)/([0-9]+)");

if (re != null) begin

$display("Looks like a data");

void'(re.subst("$2-$1-20$3"));

$display("data = %s", re.getStrContents());

end

输出结果:

Look like a data

07-06-2017


svlib提供非常全面的跟正则表达式相关的匹配和替换的方法,更多的函数可以在svlib的文档中找到。


文件和目录操作

文件和目录的操作在脚本语言中是经常使用到的,而SV欠缺这一点(或者说现有的文件打开、读写的操作不满足多样需求)。svlib提供了与路径相关的类、与文本信息相关的类等等。譬如,SV无法批量地得到相关的文件名,而这一些与目录有关的操作,svlib提供了方法。下面的例码就可以将当前目录下所有后缀名以sv结尾的文件都找到并写入到一个字符串的队列中。

string dirList [$];

dirList = sys_fileGlob("*sv");


下面通过Pathname类来完成文件路径的有关操作,通过自带的函数可以取得文件的扩展名、路径名以及文件名本身。

Pathname path = Pathname::create("/home/svlib/src/svlib_pkg.sv");

$display(path.extension()); // .sv

$diaplay(path.dirname()); // /home/svlib/src

$display(path.tail()); // svlib_pkg.sv


在得到了文件列表之后,我们可以通过svlib提供的更多函数将与文本状态信息获取,继而做更多的操作。例如下面的例码中,通过file_mTime来提供任何一种文件最后修改的日期,同时将这一日期按照更易读的形式通过函数sys_formatTime取得转化。

longint mostRecentTime = sys_dayTime() – 24*60*60;

string mostRecentFile = "";

foreach (dirlist[i]) begin

 longint t = file_mTime(dirlist[i]);

 if (t > mostRecentTime) begin

   mostRecentTime = t;

   mostRecentFile = dirlist[i];

 end

end

if (mostRecentFile != "") begin

 $display("The most recent file is \"%s\"");

 $display("It was modified at %s",

 sys_formatTime(mostRecentTime, "%c");

end


操作系统互动

svlib也提供一些函数可以获得当前工作目录下的环境变量、查询用来调用simulator的完整命令行参数等。下面这个例码就通过查询当前工作环境变量,来修改一些变量值。

string cfgVar = "SIM_CFG_DIR";

string cfgDir = "cfg"; // default value

if (sys_hasEnv(cfgVar))

 cfgDir = sys_getEnv(cfgVar);

 ...


错误处理

所谓精细化的软件编程方式,一定离不开对于各种可能出现的错误代码的排查处理,进而提高代码的健壮性。而SV用户还不适应这么做,尽管Java、Python的编程种这已经是一种习惯了。svlib是在充分考虑了用户习惯的基础上,对于错误的处理方式作出了既满足基础用户又满足高级用户的选择:

  • 默认情况下,svlib中的函数当发生错误时,会由内置的assertion发起断言错误提醒,继而在仿真器的命令窗口中提示。

  • 用户也可以通过$assertoff的命令来关闭svlib中内嵌的与错误处理相关的断言。

  • 高级用户也可以从函数的参数列表中取得错误号,继而做精细化的错误处理。

例如上面的错误处理默认情况下,会通过断言的方式来报告错误信息。

longint t = file_mTime("MISSING/FILE");

输出结果:

<Assertion>: Failed to stat "MISSING/FILE", errno=2 (No such file or directory)


或者用户也可以用高级的错误处理方式,通过error_userHandling(1)来使能这一处理方式,而通过error_getLast()来取得最近的一次处理结果,如果处理结果非0的话,那么可以根据错误号来做具体的处理。下面便是一段高级错误处理代码:

error_userHandling(1);

t = file_mTime("MISSING/FILE");

if (error_getLast() != 0)

 $display("whoops, my bad: %s", error_fullMessage());


原有随机处理的稳定性

在上面的例子中,用户会发现,svlib并不建议直接调用new构建函数来创建对象,而是通过create()函数来交由svlib内部动态创建对象。这种创建对象的方式会直接影响随机种子的创建,而当svlib作为基础库被引入到原有代码时,我们并不希望一些底层函数操作会影响随机数的生成。因此,为了消除svlib中动态对象的创建可能对随机处理的影响,svlib要求用户只能够使用create()来创建对象。下面是create()函数的实现代码:

class svlib_C extends svlib_base;

 static function svlib_C create(...);

   std::process p = std::process::self();

   string rs = p.get_randstate();

   create = new(...);

   p.set_randstate(rs);

   ... // any other initialization activity here

   endfunction

 ...


例如一个svlib中的类svlib_C,它的create()函数在创建对象前,首先保存了随机的状态get_randstate(),而在例化了对象之后又还原了随机状态set_randstate()。通过这种方式,就可以避免由于svlib的介入,创建了新的对象之后,对随机数生成的影响。因此,尽管svlib中存在着大量的由对象创建解决问题的方案,但依然可以保证原有仿真环境中随机处理的稳定性。


配置文件解析和输出

在HDL设计和验证环境的配置中,通过结构化的文件格式例如YAML或者.ini来作为输入继而进行配置的情况很普遍。也许读者所在的公司还在使用DOC、CSV等格式来配置,但结构化、层次化清晰的格式YAML或者.ini更为合适。这个文件格式需要首选转化为树状的或者队列状的软件对象配置信息,继而保存、修改和反向输出它们。对于Python,有第三方库给予支持,这就方便文件的解析,而SV也参照这一特性,使得可以解析文件、放入配置对象(DOM,Document Object Model),而在需要的时候将DOM对象再反向输出为需要的格式,例如YAML、.ini。下面给出一段综合的例码,来介绍这一过程。这种读取配置文件的格式对于验证环境,可以用来通过文本的形式来解析验证的配置结构、变量等(而不是直接编写配置对象)。

largerConfig cfg; // The object to be populated

cfgNode dom; // The DOM root node

cfgFileINI fi; // INI file reader/writer

cfgFileYAML fy; // YAML file reader/writer

// Read the YAML file into a DOM

fy = cfgFileYAML.create();

dom = fy.deserialize("src.yaml");

// Populate cfg from the DOM

cfg = new; // or perhaps use UVM factory

cfg.fromDOM(dom); // also constructs inner object

// Modify the cfg objects

cfg.scalarInt = 42;

cfg.objectSC.scalarString = "new value";

// Make a new DOM from objects. Name it "NewCfg"

dom = cfg.toDOM("NewCfg");

// Write the new DOM to a .INI file

fi = new;

fi.serialize("dst.ini", dom);


上面的例码首先解析了YAML文件格式,继而将配置信息存储到DOM结构对象中,稍后对其进行数据修改,并将更新后的数据再输出为.ini格式。存储到dst.ini文件的数据内容如下:

scalarInt=42

[objectSC]

scalarInt=1234

scalarString=new value


从这里介绍的第一个SV开源库身上我们可以看出,svlib的开发者们有着丰富的软件开发经验,而当这些从软件世界迁移过来的开发者在面对SV寥寥可数的方法集时,就会不由自主怀念以前软件开发时的各种可用的第三方库。而在svlib的开发中,又借用了C的一些库和系统接口,例如配置文件YAML的解析包是从C复用并导入到svlib中的。这些分类的方法簇、类簇都可以在Python、Java的标准库中找到原型,所以说这些类和函数并不是凭空产生的,而是认识到其它软件编程语言的标准库中一些类和方法对SV能够产生帮助时,才移植到SV一侧的。又比如上一节在谈论SV与其它语言的接口时,我们也谈到了SV在处理浮点数计算和数学库上面的欠缺,而如果SV暂时不提供这样的数学库的情况下,只能建立SV通其它支持数学库的语言Python或者Matlab等建立接口,进行混合仿真。


下面这张图给出了svlib构建的组织。可以看到svlib的一部分函数是由SV完全实现的,而另外一部分函数则是间接调用的DPI-C的函数,譬如C的内存管理方案、复用其它C库(YAML)等。


读者如果对这个开源库感兴趣,可以下载并且查看源代码和文档。通过阅读源代码,读者也可以体会到一些开发标准库需要考虑的地方:

  • 在对于库、类、函数和参数等命名时需要遵守一定的规则,这不但便于记忆和理解,也便于在文档中查找。

  • 考虑到库可能在不同的仿真器和平台上使用,需要尽量在可能的仿真器和平台上测试。

  • 最好不要依赖于其它的库。svlib只基于SV的标准库和自带的DPI C库,这也使得它可以在其它的方法学库中使用,譬如UVM、OVM。

  • 当然还有一点,如果你想让你的第三方库为更多的人使用的时候,就将它开发地更规范化一些,包装起来,并且想办法让更多的人知道它还感兴趣。


我们下一节还将继续介绍开发库和类的过程中可以采样的标准单元测试方法SVUnit,这一点也借鉴与其它软件更早些时间的方法,例如JUnit和PyUnit。


谢谢你对路科验证的关注,也欢迎你分享和转发真正的技术价值,你的支持是我们保持前行的动力。



TAG:

 

评分:0

我来说两句

显示全部

:loveliness: :handshake :victory: :funk: :time: :kiss: :call: :hug: :lol :'( :Q :L ;P :$ :P :o :@ :D :( :)

路科验证

路科验证

路科验证(Rocker IC)专注于验证系统思想和前沿工程资讯,拥有一支活跃的技术原创团队,为高校微电子相关专业学生与IC从业人员提供技术食粮。 您可以在手机移动端同步关注微信订阅号“路科验证”。如果您需要联系我们,请发送邮件至 rocker.ic@vip.163.com 或者 bin.rocker.liu@intel.com 。

日历

« 2018-06-21  
     12
3456789
10111213141516
17181920212223
24252627282930

数据统计

  • 访问量: 114799
  • 日志数: 221
  • 建立时间: 2016-06-25
  • 更新时间: 2018-06-14

RSS订阅

Open Toolbar
博聚网