【学习记录丨UVM】1.7参考模型reference_model

《UVM白皮书》关于reference_model的介绍

reference_model用来模拟DUT的功能,并将结果送入scoreboard与DUT的结果进行比较。

在reference_model的示例中会出现很多新的UVM内容,这些会在后边更详细地介绍,现在我们先理解并记住就好了。 

另外这个组件并不是每个验证平台中必须的,其他组件也是。验证平台包含什么,这都是根据我们的实际需要来确定的。

一、一个reference_model示例

class my_model extends uvm_component;//UVM库中并没有uvm_referce_model这种源文件
    //所以 my_model 直接派生自uvm_component
  uvm_blocking_get_port #(my_transaction) port;//注意!!
  uvm_analysis_port     #(my_transaction) ap;//注意!!

  `uvm_component_utils(my_model)
  function new(string name="my_model",uvm_component parent);
    super.new(name,parent);
  endfunction

  extern function void build_phase(uvm_phase phase);
  extern virtual task main_phase(uvm_phase phase); 
endclass

function void my_mode::build_phase(uvm_phase phase);
  super.build_phase(phase);
  port= new("port",this);//注意!!
  ap  = new("ap",this);//注意!!
endfunction

task my_model::main_phase(uvm_phase phase);
  my_transaction tr;
  my_transaction new_tr;
  super.main_phase(phase);
/////////////////////////////这里只是书上的例子,暂时可忽略,后边会简单介绍
  while(1)begin
    port.get(tr);
    new_tr=new("new_tr");
    new_tr.my_copy(tr);
    `uvm_info("my_model","get one transaction,copy and print it:",UVM_LOW)
    new_tr.my_print();
    ap.write(new_tr);
  end
//////////////////////////
endtask

二、在env中例化reference_model 

和前面文章中例化组件相同,在env中加入 my_model mdl; 在env的build_phase中加入 mdl=my_model::type_id::create("mdl",this); 即可。

此时的uvm树形结构为:

三、介绍reference_model 

验证平台各个组件之间的信息传递都是基于transaction的。reference_model的作用是实现和DUT相同的功能,并将输出传递给scoreboard组件与真实dut的输出进行比较。

简单示例my_model结构并不复杂。但是其中重要的是,其中my_transaction的传递方式。

my_model是从i_agt获得my_transaction,并把my_transaction传递给scoreboard。

在UVM中,通常使用TLM实现component之间transaction级通信。

1. TLM(transaction level modeling事务级建模)通信

要实现通信,有两个问题:① 怎么发送数据?②怎么接收数据?

① 一种数据发送方式—uvm_analysis_port 

uvm_analysis_port 是一个参数化的类,其参数就是它要传递的数据类型。即#()中的内容。

发送transaction是在monitor中进行的。

  1. monitor中声明uvm_annalysis_port类变量 ap;
  2. monitor的build_phase中实例化ap;
  3. 在main_phase中,当收集完一个transaction后,需要将其写入ap;
...
uvm_analysis_port #(my_transaction) ap;//声明ap
...
virtual function void build_phase(uvm_phase phase);
  ...
  ap = new ("ap",this);//实例化ap
endfunction
task my_monitor::main_phase(uvm_phase phase);
  my_transaction tr;
  while(1) begin
    tr = new("tr");
    collect_one_pkt(tr);
    ap.write(tr);//write是uvm_annalysisi_port的一个内建函数
  end
endtask

至此,在my_monitor中需要为transaction通信准备的工作已经全部完成。

 ② 一种数据接收方式—uvm_blocking_get_port 

 uvm_blocking_get_port 也是一个参数化的类,其参数就是它要传递的数据类型。即#()中的内容。

在reference_model中接收transaction。

  1. my_model中定义uvm_blocking_get_port类变量 port;
  2. my_model的build_phase中实例化port;
  3. 在main_phase中,通过port.get任务来接收从i_agt的monitor中发出的transaction;
class my_model extends uvm_component;
  uvm_blocking_get_port #(my_transaction) port;//注意!!
  uvm_analysis_port     #(my_transaction) ap;//注意!!
  ...
  extern function void build_phase(uvm_phase phase);
endclass

function void my_mode::build_phase(uvm_phase phase);
  super.build_phase(phase);
  port= new("port",this);//注意!!
  ap  = new("ap",this);//注意!!
endfunction

task my_model::main_phase(uvm_phase phase);
  my_transaction tr;
  super.main_phase(phase);
  while(1)begin
    port.get(tr);
    ...
  end
endtask

在my_monitor和my_model中定义并实现了各自的端口后,通信功能并没有实现,还需要在my_env中使用fifo将两个端口联系在一起。 

③ 用fifo连接①②中的两个端口 
  1. my_env中定义1个fifo;
  2. my_env的build_phase中实例化fifo;
  3. my_env的connect_phase中将fifo分别与monitor中的ap和model中的port相连。
class my_env extends uvm_env;
  ...
  uvm_tlm_analysis_fifo #(my_transaction) agt_mdl_fifo;
  ...
  virtual function void build_pase(uvm_phase phase);
    ...
    agt_mdl_fifo = new("agt_mdl_fifo",this);
  endfunction
  extern virtual function void connect_phase(uvm_phase phase);
endclass

fifo的类型是uvm_tlm_analysis_fifo,它本身也是一个参数化的类,其参数就是存储在其中的transaction的类型,这里是my_transaction。 

function void my_env::connect_phase(uvm_phase phase);
  super.connect_phase(phase);
  i_agt.ap.connect(agt_mdl_fifo.analysis_export);//注意fifo这里都是.xx_export
  mdl.port.connect(agt_mdl_fifo.blocking_get_export);//注意fifo这里都是.xx_export
endfunction

注意这里是i_agt.ap而不是mon.ap,因为前边我们已经把driver和monitor封装在agent里了。遵循UVM树形组织结构。

我们需要在my_agent中定义一个ap:

uvm_analysis_port #(my_transaction) ap;

然后在my_agent的connect_phase中,把monitor的ap值赋给agent中的ap即可:

virtual function void connect_phase(uvm_phase phase);
  super.connect_phase(phase);
  ap = mon.ap;
endfunction

2. 为什么需要使用fifo? 

——为什么需要使用fifo? 为什么不能直接把ap和port相连接呢?

——由于annlysis_port是非阻塞性质的,ap.write函数调用完成后马上返回,不会等待数据被接受。          那么假如write函数调用时,blocking_get_port正在忙其他事情,尚未准备好接受新数据时,那么那么此时被write函数写入的my_trannsaction就需要一个暂存的位置,这就是fifo。

3. connect_phase  

connect_phase也是UVM的内建phase之一。

  1. 它在build_phase之后执行;
  2. 它的执行顺序是从UVM树的树叶到树根,和build_phase的执行顺序相反;

至此结束,主要介绍了transaction怎么从i_agt.monitor传递给reference_model。其他组件之间的transaction传递也是类似的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值