UVM的组建类(uvm_component)是验证环境的骨架,用于验证环境的结构的创建。主要包括uvm_driver、uvm_monitor、uvm_sequencer、uvm_agent、uvm_scoreboard、uvm_env、uvm_test等。
在对组件类进行工厂机制的注册时,需使用宏`uvm_component_utils()。而对于组件的构建函数,其固定形式为:
function new(string name, uvm_component parent);
其中,string name 用来声明当前例化的组件的名称,用来自动和它所在的父一级层次组合为组件的整个层次名称,可以通过get_full_name()方法获取;uvm_component parent 用来指示所例化的父一级句柄,通常用“this”替代,即例化在当前的父一级组件中。
注意与uvm_object类的构建函数new (string name)进行区分:由于uvm_object并不参与验证环境的层次构建,因此它只有一个形参name。
driver,即驱动。该类会从uvm_sequencer类中获取事务(transaction),经过转化进而在接口(interface)中对DUT进行时序激励。
任何继承于uvm_driver的类都需要注意的是:该类是参数化的类,因此在定义时需要声明参数的类型。uvm_driver类的定义如下:
class uvm_driver #(type REQ = uvm_sequence_item, type RSP = REQ) extends uvm_component;
可以看出,默认的参数类型是uvm_sequence_item类的句柄,所以在声明时要注意传入子类句柄,否则会造成无法访问子类成员变量。
driver类与sequencer类之间的通信就是为了获取新的transaction,而这一操作是通过其上的TLM端口的pull的方式,从sequencer一侧get到的。
monitor,即监控器。该类是为了监测接口数据。任何需要用户自定义数据监测行为的monitor都应当继承于该类。
uvm_monitor组件类通常执行的功能包括:
(1)观测DUT的接口,并且收集总线信息;
(2)永远保持PASSIVE模式:即永远不会驱动DUT;
(3)在总线协议或者内部信号协议的观察时,可以做一些功能和时序的检查;
(4)对于更复杂的检查要求,它们可以将数据发送至其它验证组件,如scoreboard、reference model等。
sequencer,即测序器。该组件就如同一根管道。从这个管道中会产生连续的激励事务,并最终通过TLM端口送至driver一侧。它也是一个参数类。
sequencer既管理着sequence,同时也将sequence中产生的transaction item传送到driver的一侧。
agent,即代理。该组件是一个容器类,是一个标准的验证环境“单元”,里面通常包含一个driver、一个monitor以及一个sequencer。
有时为了复用,uvm_agent中只需要包含一个monitor,而不需要driver和sequencer。此时可以通过设置变量 is_active 来进行有条件的例化:
uvm_active_passive_enum is_active = UVM_ACTIVE;
当is_active的值为 UVM_ACTIVE 时,表示处于active模式的agent需要例化driver、sequencer和monitor。如果值为 UVM_PASSIVE,则表示agent是passive模式,只可以例化monitor。即:active模式的agent既能激励DUT,也可以监测它;passive模式则只有监测功能。
scoreboard,即记分板。该组件用于进行数据的比对报告:对来自monitor的数据和来自reference_model的数据进行比对,看结果是否一致。通常会在scoreboard中声明TLM端口以供monitor传输数据。
env,即环境。该组件是一个结构化的容器,它可以容纳其它组件,也可以作为子环境在更高层次中被嵌入。其中例化了多个uvm_agent和其它组件,这些不同组件共同构成一个完整的验证环境。
uvm_test为用户自定义类的顶层结构,是验证环境建立的唯一入口。只有通过uvm_test才能正常运转UVM的phase机制,进而控制整个验证平台的有序运行。它不但决定着验证环境的结构和连接关系,也决定着使用哪一个测试序列。所有的test类都应该继承于uvm_test,否则将无法启动test的运行。