四十多年前,设计师从门级(gate-level)设计转向RTL设计,这种转变主要是由Verilog/VHDL RTL编码标准以及可用的RTL综合和实现工具支持的,其带来的好处是设计人员可以将更多的精力放在周期级(cycle level)行为设计上,不需要考虑太多门级因素。
相比RTL设计验证,事务级建模(TLM)重点是建模系统的数据流,减少关注周期级行为。
TLM已在验证平台中使用了很多年,通常我们都是在事务级产生激励以及检查输出数据,其中需要使用drivers和monitors等总线功能模型(BFM)进行事务级和信号级之间的转换。使用TLM有几个好处:
1、TLM模型比RTL模型更简洁,仿真更快。
2、TLM模型处于更高的抽象级别并且更紧密地匹配了验证工程师或设计工程师预期的功能,这也使得其他工程师更容易理解。
3、TLM模型更可重用,因为移出了不必要的细节。
UVM提供了基于TLM 1.0标准的类和API,在使验证环境代码重用方面发挥了关键作用。事务(transaction)是从uvm_sequence_item扩展的类,其由用户定义的建模验证环境中不同组件之间信息传输所需的字段和方法组成。例如,一个简单的数据包可以按以下方式建模:
classs imple_packet extends uvm_sequence_item;
rand int src_addr;
rand int dst_addr;
rand byte unsigned data[];
constraint addr_constraint { src_addr!= dst_addr; }
. . .
endclass
事务包含足够的数据字段以使driver能够创建实际的电平信号,还包含用于验证环境的随机化约束。
UVM中的TLM API指定了一组在组件之间进行事务通信的方法。在UVM中,port指定可以调用的方法,export则提供方法的实现,它们通过connect()方法连接在一起。
在UVM TLM中,put可用于将事务从生产者(producer)发送到消费者(consumer),如下:
class producer extends uvm_component;
uvm_blocking_put_port #(simple_packet) put_port;
function new(string name, uvm_component parent);
put_port = new("put_port", this);
endfunction
virtual task run();
simple_packet p = new() ;
put_port.put(p);
endtask
endclass
如前所述,put port通过connect()连接到put export。put方法在consumer中实现:
class consumer extends uvm_component;
uvm_blocking_put_imp #(simple_packet, consumer) put_export;
task put(simple_packet p);
// consume the packet
endtask
endclass
类似的,在UVM TLM中,get可用于消费者(consumer)从生产者(producer)中获取事务,如下:
class consumer_2 extends uvm_component ;
uvm_blocking_get_port# (simple_packet) get_port;
function new(string name, uvm_component parent);
get_port= new("get_port", this);
endfunction
virtual task run();
simple_packet p;
...
get_port.get(p);
endtask
endclass
class producer_2 extends uvm_component;
uvm_blocking_get_imp#(simple_packet, producer_2) get_export;
task get(output simple_paeket p) ;
simple_packetp_temp = new();
...
p =p_temp;
endtask
endclass
上面的示例需要在父类组件中调用connect()方法来完成port-to-export的连接,以put port为例:
class parent_comp extends uvm_component;
producer producer_inst;
consumer consumer_inst;
. . .
virtual function void connect();
producer_inst.put_port.connect(consumer_inst.put_export);
endfunction
endclass
在Verilog RTL中,模块可能包含内部子模块,它们本身具有信号端口,这使得实际验证工作中具有port-port和export-export连接的需求。同样以put 操作为例:
//Connecting a Child Port to a Parent Port
class parent_producer extends uvm_component;
uvm_blocking_put_port#(simple_packet) put_port;
producer child_producer_inst;
function new(string name,uvm_component parent);
put_port= new("put_port", this);
child_producer_inst= new("child_producer_inst",this);
endfunction
virtual function void connect();
child_producer_inst.put_port.connect(put_port);
endfunction
endclass
//Connecting a Child Export to a Parent Export
class parent_consumer extends uvm_component;
uvm_blocking_put_export#(simple_paeket) put_export;
consumer child_consumer_inst;
function new(string name, uvm_component parent);
put_export= new("put_export", this);
child_consumer_inst= new("child_consumer_inst", this);
endfunction
virtual function void connect();
put_export.connect(child_consumer_inst.put_export);
endfunction
endclass