| ||
在得到了文件列表之后,我们可以通过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");