在高级验证方法学(AVM)和通用可重用验证方法学(URM)的基础上,Mentor Graphics和Cadence共同推出了业界第一个通用、开放的验证方法学OVM;OVM为验证工程师提供了丰富的类库和高级验证技术,实现验证平台从模块级到系统级的重用,公司内外的重用,并且可以在多个厂家的仿真验证平台上运行。
可重用的验证平台
搭建一个高级的验证平台有很多要求,其中一个主要的要求就是要让验证平台可重用。验证平台的可重用性体现在以下几个方面:模块级验证到系统级验证的重用,同一个项目下不同测试环境的重用,在公司内部不同项目之间的重用,在不同公司之间的重用;从重用对象的角度来看,存在着验证组件的可重用、事务激励和产生算法的可重用等等。
OVM提供了事务交易级的架构,借助这些事务交易级的接口,可以搭建模块化,可重用的验证组件;它的类库可以帮助使用者创建约束随机的激励和序列,搜集和分析功能覆盖信息,包括断言在内的可配置和层次性管理的验证环境;其中基于Factory Pattern的对象生成方式,验证平台架构的动态构建,动态的参数配置,激励产生与验证架构分离和测试作为验证的顶层等高级技术使得可重用的验证平台更易实现。
验证平台架构的动态构建
在验证中经常遇到一个可重用性的难题就是需要及时调整特定的验证平台环境,对DUT应用一系列新的功能测试。通常,我们通过修改已有验证平台中特定的验证组件源代码,得到一个新的验证环境。例如,通过用一个注错功能的驱动器去替换通用的驱动器。这很容易就可以通过面向编程语言的技术,在例化原驱动器的位置上添加代码,例化一个注错功能的驱动器,从而扩展基类环境到一个新的环境。假如两个驱动器接口都是兼容的,那么验证环境的其他部分的代码便可以保持不变。
传统上,基于类的层次化对象产生创建是通过对象的构造函数new()来实现的。高层次的组件通过调用低层次组件的构造函数,创建低层次组件的对象。这种方法限制了创建对象的灵活性,因为对象的类型在编译的时候就已经确定了。另外,我们需要维护两个不同的验证环境,虽然我们可以通过面向编程技术使原有的代码得到重用,但是我们更加希望整个验证架构也能够重用;也就是说,我们希望可以不改动任何原有的代码,而调整其内容从而实现一个验证架构的重用。在OVM中我们可以通过Factory Pattern的方法来实现的。
Factory Pattern是一个很出名的面向对象的编程技巧,Factory是一个可以动态创建对象的类。它的主要好处是可以在特定的时刻创建特定的对象。Factory不是层次化验证架构中的一部分,而是处于层次化结构之外。OVM提供了一个Factory可以创建任何类型的事务交易或者任何验证组件,只要事前他们在Factory做过注册。Factory提供类型重写可以动态的改变所创建对象的类型。在OVM中我们通过ovm_factory来实现,见代码段1:
class my_env extends ovm_env;
drv d1,d2;
…..
function void build();
…… //build the rest of the environment
d1=new(“d1”,this); //explicit constructor:new()
assert($cast(d2,create_component(“drv”, “d2”))); // factory method: create_component //create an object of drv type
endfunction
…
endclass
我们从上面的代码可以看到d1和d2采用不同的例化和构造方式。d1这个对象是通过调用其构造函数来实现的,这限制了可重用性。相反,Factory的create_component()方法返回了一个drv类的对象并且赋给了d2。这两段代码都是一个drv的例化对象被创建,但是Factory提供了更大的灵活性,因为它可以在my_env类以外对其进行控制,也就是其上层的ovm_test例化中进行操作,从而可以从Factory中返回一个期望类型的组件给drvier的例化对象,如代码段2:
class err_test extends ovm_test;
my_env env;
function void build();
ovm_facotry::set_type_override(“drv”,“err_driv”); //factory type override meotod
env=new(“env”);
….
endfunction
…
endclass
set_type_override()方法告诉Factory:一旦验证环境通过create_component()要求一个drv基类对象的时候,请为其返回一个err_drv类的例化对象。在Factory中也可以针对特定的例化对象做类型修改。这个机制使得一个相同的验证环境类可以被例化到多个测试中,每一个测试都可能要求一个不同类型的driver的扩展,但是环境的代码没有改变。这个环境本身是一个可重用和上下文相关的(取决于测试如何控制Factory去生成相应类型的对象)。当在各个层次的build()阶段都采用这种的方式,每个上层的组件通过Factory去创建一个子组件的例化对象,那么任何一个组件就可以通过类似的方式来指定需要的类型。
动态的配置机制
传统的基于类的层次化验证环境中使用构造函数的参数来配置验证平台。例如验证平台的架构,参数设置(数组的大小和常数),操作模式(错误注入和调试)是可以通过这个方法来配置的;但是在层次复杂的结构中,这种方法使用起来变得困难而且很难添加新的参数。
OVM支持内置动态的配置机制,来实现结构化属性和运行时参数的配置,从而避免通过构造函数的参数来传递信息。一个高层次的组件可以设置配置信息,这些信息被对应的低层组件的获取后使用。每个可配置的组件负责在合法的时刻去获取自己的配置信息:结构化配置信息,例如多少个子模块可以被例化,可以通过build()这个阶段来控制;运行时的信息,例如在总线周期之间需要等待多少个状态才注错,可以通过组件的build()或者configure()阶段来实现,他们也可以在run()这个阶段来实现。OVM提供了一个API来实现这个配置信息的设置和获取的过程。如代码段3:
class drv extends ovm_threaded_component;
local int delay;
virtual function void build();
if(get_config_int(“numdly”,numdly)) //get the configuration from the global table
set_delay_length(numdly);
endfunction
virtual task run();
…
case(state)
DONE:begin
if(get_config_int(“numdly”,numdly))
if(numdly<=10)
set_delay_length(numdly);
else ovm_report_error(“Driver”,”ILLEGAL length sepcification”);
state=IDLE;
IDLE:begin
if(delay==0)
state=GO;
…
endcase
….
endtask
endclass
配置信息可以通过高层的组件来指定,而常常由顶层的验证环境或者顶层的测试来决定;通过set_config_*(),配置也可以对一个特定例化上实现;配置信息可以直接的被制定为整数或者字符串的值,但是有些比较复杂的需要封装在一个ovm_object的对象中通过使用set_config_object()方法来实现。代码段4是一个例子,测试将配置driver中的延迟时间:
代码段4:
class dly_test extends ovm_test;
virtual function void build()
set_config_int(“env.d1”,”numdly”,5);
…..
endfunction
…
endclass
在OVM中这些配置是通过一个全局的查找表来实现的,其为验证平台提供了可重用性。第一,对组件的配置信息独立于自身的构造函数,这使得测试可以更灵活的根据其他配置信息或者随机地去为还未被例化组件配置信息。使用者还可以通过使用通配符来在多个组件中对多个参数做配置。组件自主获取其配置信息可以让组件保证无论在那种情况下都要被合法的配置。如果其中有不匹配的地方,组件作为一个仲裁者,会要求恰当的配置。
测试作为验证的顶层
标准验证平台的结构中有一个顶层的模块(top),在顶层模块中例化了DUT(alu),DUT接口(alu_if)和一个顶层的类(test_env);顶层的类(test_env)即验证环境中包含了验证平台的所有组件,可以在这个架构中应用的SystemVerilog技术例如约束随机数的产生和功能覆盖率。
图1 标准验证平台的顶层结构
在标准的验证架构中,如图1所示,顶层的对象是一个环境类,其中嵌入了激励产生器。这限制了添加和修改测试的灵活性。
将激励生成算法从验证平台的结构中分离出来,这样可以让我们将一个测试的类(test)作为顶层的对象而不是一个环境的类(env)。
图2 测试作为验证的顶层
如图2所示,test_MAC是我们的测试,它是一个类,其中包含四个成员:
1.一个sequence(MAC_sequence),其可以生成一系列事务交易;在这个例子中,事务交易通过sequence生成,是一个实现了乘累加算法的激励序列。
2.一个验证环境(t_env),其例化包含了各种验证组件。
3.Factory的重写,可以为MAC的测试动态地创建一个验证环境。
4.配置信息,可以为MAC的测试动态地配置验证环境。
相对于标准的验证平台,测试作为验证的顶层在添加和修改测试上提供了很大的灵活性。每个测试可以定义它自己特定的配置信息,在编译完所有的测试和验证组件之后,每个测试可以不用重新编译就能运行,因为每个测试在它运行的时候可以动态的创建和配置验证架构。
采用了这种方法,上述例子可以根据不同的应用被配置到特定的测试中,包括选择特定的记分板,给测试指定一个合适的衡量机制,选择一个特殊的事务处理器或者配置一个可预测的结果。在某些情况下,整个层次化的模块可能被代替,例如激励生成模块,分析模块和监视模块。从而,同一个验证环境(test_env)能够被不同的测试(test)多次重用,动态创建和配置。
激励产生与验证架构分离
图3 标准的激励产生模块
就如我们前面所说的激励产生、事务交易在验证平台中的验证组件――激励产生器中创建生成;如图3所示,在我们的例子中driver是一个事务处理器,可以接受ALU的事务交易,例如加、减操作,将其分解送入到ALU的管脚级的端口中。在DUT和事务处理器之间通过虚接口(virtual interface)来实现。
激励生成算法被嵌入在产生器的类中:stimulus_gen,这种接口限制了修改测试的灵活性。为了添加或者修改测试,产生器的对象需要被另外一个产生器代替,从而需要重新配置和重新编译。除了支持上述方法,OVM推荐了另外一种方法:把激励生成的算法模块从验证平台的结构中分离出来,从而在添加和修改测试上提供更大的灵活性。
图4 层次化的激励产生模块
在图4中,生成事务交易的算法包含在一个sequence对象中:MAC_sequence,这不是一个结构化的验证组件,而是存在于验证架构以外。OVM提供了sequence,在验证架构以外来生成事务交易。整个激励层次由一个sequence (MAC_sequence),一个sequencer和一个事务交易器driver组成。sequencer同步了MAC_sequence和driver之间的通信。
作者:钟文枫
应用工程师
Mentor Graphics
ahan.mail@g mail.com
评论
查看更多