uvm-1.2 examples —— 2.8 interfaces

2.8 interfaces



前言

本文以uvm-1.2/examples/simple/interfaces为例,通过代码了解UVM中的一些用法。通过这个例子可以基本了解以下知识点:

  • interface的作用
  • 如何创建一个interface
  • 如何使用modport封装信号
  • resource_db机制及其dump
  • 如何interface实现验证环境与待测设计DUT之间的连接

一、基本介绍

interface翻译过来就是接口的意思,interface的作用就是将接口单独封装出来,用于验证环境与待测设计DUT之间的连接。将接口单独封装出来的好处是,避免接口很多的时候,连接的时候容易出错,另外,当接口有改动的时候,只需要改变一个文件即可,不用在每个接口例化的地方全部改一遍。

在这个测试用例中,将通过interface封装一个接口,在接口内部再通过modport关键字,对接口进行分类,最后通过interface,实现验证环境和待测设计DUT之间的连接。

二、代码分析

代码比较简单,只有一个interface.sv文件

1、interface.sv

/*
About: uvm_exmples/mechanism/interfaces

This example will illustrate how to create a pin interface and mod port interfaces for a simple dut.

Connect a component "driver" to the pin interfaces, then to the dut.
*/



//----------------------------------------------------------------------
// interface mem_pins_if
//----------------------------------------------------------------------
interface pin_if (input clk);
  bit [15:0] address;
  bit [7:0]  wr_data;
  bit [7:0] rd_data;
  bit rst;
  bit rw;
  bit req;
  bit ack;
  bit err;

  modport master_mp(             
   input  clk,
   input  rst,          
   output address,
   output wr_data,  
   input  rd_data,            
   output req,
   output rw,           
   input  ack,
   input  err );         
                                 
  modport slave_mp(              
   input  clk,
   input  rst,          
   input  address,
   input  wr_data,  
   output rd_data,            
   input  req,
   input  rw,           
   output ack,
   output err );         
                                 
  modport monitor_mp(            
   input  clk,
   input  rst,          
   input  address,
   input  wr_data,  
   input  rd_data,            
   input  req,
   input  rw ,
   input  ack,
   input  err );
endinterface

import uvm_pkg::*;

package top_pkg;
   typedef virtual pin_if pin_vif;
endpackage


package user_pkg;
import uvm_pkg::*;
import top_pkg::*;
`include "uvm_macros.svh"

//---------------------------------------------------------------------
// component driver
//----------------------------------------------------------------------
class driver extends uvm_component;

  pin_vif pif;

  function new(string name, uvm_component parent = null);
    super.new(name, parent);
  endfunction

  function void connect_phase(uvm_phase phase);
     assert(uvm_resource_db#(pin_vif)::read_by_name(get_full_name(),
                                                    "pif", pif));
  endfunction

  task run_phase(uvm_phase phase);
    forever begin
      @(posedge pif.clk);
      `uvm_info("driver", "posedge clk", UVM_NONE);
      //...
    end
  endtask

endclass

//----------------------------------------------------------------------
// environment env
//----------------------------------------------------------------------
class env extends uvm_env;

  local pin_vif pif;
  driver d;

  function new(string name, uvm_component parent = null);
    super.new(name, parent);
    d = new("driver", this);
  endfunction

  task run_phase(uvm_phase phase);
    phase.raise_objection(this);
     #100;
    phase.drop_objection(this);
  endtask

endclass

endpackage
//import user_pkg::*;

//----------------------------------------------------------------------
// module dut
//----------------------------------------------------------------------
module dut(pin_if pif);

  always @(posedge pif.clk) begin
    `uvm_info("dut", "posedge clk", UVM_NONE);
    //...
  end
endmodule

//----------------------------------------------------------------------
// module clkgen
//----------------------------------------------------------------------
module clkgen(output bit clk);

  initial begin
    forever begin
      #5 clk = 1;
      #5 clk = 0;
    end
  end

endmodule

//----------------------------------------------------------------------
// module top
//----------------------------------------------------------------------
module top;

  import top_pkg::*;
  import user_pkg::*;

  bit clk;
  clkgen ck(clk);
  pin_if pif(clk);

  env e;
  dut d(pif.slave_mp);

  initial begin
    e = new("env");
    uvm_resource_db#(pin_vif)::set("env.driver", "pif", pif);
    uvm_resource_db#(pin_vif)::dump();
    run_test();
    //$finish;
  end
  
endmodule

第14到56行,利用interface——endinterface关键字封装了一组接口。
14行interface封装的名字是pin_if,参数clk。
15到22行利用bit声明了一系列的端口名,其实这里用logic声明端口名会更好,因为logic声明的变量支持四个状态,包括0、1、x、z,而bit声明的变量只支持两个状态,包括0和1。
24到55行利用modport关键字,将信号进行了分组,并指定了每组中变量的输入输出状态。这里分了三组,包括master_mp、slave_mp和monitor_mp,前两组用于驱动,最后一组用于监控。

60到62行,通过package封装了top_pkg,在top_pkg中,利用typedef关键字,将virtual pin_if取名叫pin_vif。

65行到117行,通过package封装了user_pkg,在user_pkg中,声明了driver和env。
73到94行声明了dirver组件,其中关键的是81到84行的connect_phase,通过调用uvm_resource_db实现验证环境和待测设计DUT的连接,resource_db机制中,存在一个资源池,在顶层将interface放入这个资源池,这里将资源池里面的interface按照名字读出来,从而实现连接。assert关键字是断言,用于判断uvm_resource_db连接是否成功,如果连接失败,断言就会报错。
99到115行声明了env组件,env中声明并例化了drver组件,另外,在109到113的run_phase中,通过“举手”和“放手”来保证仿真执行的时间。这里的举手和放手可以参考张强《UVM实战》的5.2节objection机制。

123到143行,声明了两个简单的dut和clkgen模块。dut模块带interface参数,clkgen模块带时钟clk参数。

148到168行,声明了顶层top模块。在该模块中例化了interface、dut、clkgen以及env模块。
其中,153到158行,clkgen用于产生时钟信号,interface封装了端口信号,env构成了验证环境,dut是待测设计(design under test)。clkgen产生的时钟信号,送入了interface;interface封装的slave_mp送入了dut。
160到166行,先例化了env,再通过uvm_resource_db的set函数,将interface送入resource_db机制的资源池中,这里set函数的第一个参数是路径,第二个参数是标识符,第三个参数是变量。
163行调用uvm_resource_db的dump函数,打印资源池中的信号用于debug调试。打印的结果如下所示:

UVM_INFO ../../../src/base/uvm_resource.svh(1347) @ 0: reporter [UVM/RESOURCE/DUMP] 
=== resource pool ===
 pif [/^env\.driver$/] : (virtual interface pin_if) '{clk:'h0, address:'h0, wr_data:'h0, rd_data:'h0, rst:'h0, rw:'h0, req:'h0, ack:'h0, err:'h0}

164行执行仿真。

2、仿真结果

UVM_INFO ../../../src/base/uvm_resource.svh(1347) @ 0: reporter [UVM/RESOURCE/DUMP] 
=== resource pool ===
 pif [/^env\.driver$/] : (virtual interface pin_if) '{clk:'h0, address:'h0, wr_data:'h0, rd_data:'h0, rst:'h0, rw:'h0, req:'h0, ack:'h0, err:'h0}   
UVM_INFO ../../../src/base/uvm_resource.svh(1354) @ 0: reporter [UVM/RESOURCE/DUMP] === end of resource pool ===
UVM_INFO @ 0: reporter [RNTST] Running test ...
UVM_INFO interface.sv(89) @ 5: env.driver [driver] posedge clk
UVM_INFO interface.sv(126) @ 5: reporter [dut] posedge clk
UVM_INFO interface.sv(89) @ 15: env.driver [driver] posedge clk
UVM_INFO interface.sv(126) @ 15: reporter [dut] posedge clk
UVM_INFO interface.sv(89) @ 25: env.driver [driver] posedge clk
UVM_INFO interface.sv(126) @ 25: reporter [dut] posedge clk
UVM_INFO interface.sv(89) @ 35: env.driver [driver] posedge clk
UVM_INFO interface.sv(126) @ 35: reporter [dut] posedge clk
UVM_INFO interface.sv(89) @ 45: env.driver [driver] posedge clk
UVM_INFO interface.sv(126) @ 45: reporter [dut] posedge clk
UVM_INFO interface.sv(89) @ 55: env.driver [driver] posedge clk
UVM_INFO interface.sv(126) @ 55: reporter [dut] posedge clk
UVM_INFO interface.sv(89) @ 65: env.driver [driver] posedge clk
UVM_INFO interface.sv(126) @ 65: reporter [dut] posedge clk
UVM_INFO interface.sv(89) @ 75: env.driver [driver] posedge clk
UVM_INFO interface.sv(126) @ 75: reporter [dut] posedge clk
UVM_INFO interface.sv(89) @ 85: env.driver [driver] posedge clk
UVM_INFO interface.sv(126) @ 85: reporter [dut] posedge clk
UVM_INFO interface.sv(89) @ 95: env.driver [driver] posedge clk
UVM_INFO interface.sv(126) @ 95: reporter [dut] posedge clk
UVM_INFO ../../../src/base/uvm_objection.svh(1270) @ 100: reporter [TEST_DONE] 'run' phase is ready to proceed to the 'extract' phase
UVM_INFO ../../../src/base/uvm_report_server.svh(847) @ 100: reporter [UVM/REPORT/SERVER] 
--- UVM Report Summary ---

** Report counts by severity
UVM_INFO :   25
UVM_WARNING :    0
UVM_ERROR :    0
UVM_FATAL :    0
** Report counts by id
[RNTST]     1
[TEST_DONE]     1
[UVM/RELNOTES]     1
[UVM/RESOURCE/DUMP]     2
[driver]    10
[dut]    10

$finish called from file "../../../src/base/uvm_root.svh", line 517.
$finish at simulation time                  100
           V C S   S i m u l a t i o n   R e p o r t 
Time: 100 ns

通过log可以看到,首先在82行设定的断言没有报错,其次driver打印一个posedge clk,同一时刻dut也打印了一个posedge clk,这说明验证环境和dut已经完成连接。


总结

这个测试用例非常简单,利用resource_db实现了验证环境与待测设计之间,通过interface进行连接。其实,还可以利用config_db机制进行连接,具体可以参考张强的《UVM实战》3.5节config_db机制。

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值