芯有所想

精益求精

uvm_blocking_get_port/uvm_blocking_get_export实现的简单模型

之前介绍了uvm_blocking_put_port/uvm_blocking_put_export, 其对应的uvm_blocking_get_port/uvm_blocking_get_export的简单模型可以照猫画虎的设计,

源代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
/**
 ** tlm_get.sv 
 ** 说明: 通过简单的模型来阐述 UVM/OVM中TLM uvm_get_port
 **        和uvm_port_imp直接连接的基本原理。直接编译运行即可。
 ** 作者:Zhu,YH
 */
virtual class port_base#(type T=int) ; // 构造一个抽象类
  typedef port_base#(T) this_type;
  protected this_type port_handle; // 申明一个对象句柄(指针)

  pure virtual task get_t(output T trans); // 纯虚函数,get_port和get_imp都必须以它为基类

  function void connect(this_type port); // connect仅仅是实现对象句柄的赋值
    port_handle = port;
  endfunction // connect

endclass // port_base

class get_port#(type T=int) extends port_base#(T);
  virtual task get_t(output T trans);
    port_handle.get_t(trans);
  endtask // get_t
endclass // get_port

class get_imp#(type T=int, type IMP=int) extends port_base#(T);
  local IMP m_imp;  // imp表示具体实现get_t()函数的对象句柄。
  function new(IMP imp);
    m_imp = imp;
  endfunction // new

  virtual task get_t(output T trans);
    trans = $random;
    m_imp.get_t(trans);  // 调用实现对象对应的get_t()函数
  endtask // get_t

endclass // get_imp

class producer;
  get_imp#(int, producer) m_get_export;
  function new();
    m_get_export = new(this);//将producer句柄传递给get_imp中的imp变量,从而实现接管get_t()最终的实现
  endfunction // new

  task get_t(int trans);
    $display("[INFO]: Generated the transaction:%d", trans);
  endtask // get_t 
endclass // producer

class consumer;
  get_port#(int)  m_get_port;
  function new();
    m_get_port = new();
  endfunction // new

  task run(int num=10);
    int trans;
    for(int i=0; i<num; i++) begin  // 顺序产生10个int类型的transaction.
      m_get_port.get_t(trans);
      $display("[INFO]: Get the transaction:%d", trans);
    end
  endtask // run 
endclass // consumer

module top;
  producer p;
  consumer c;
  initial begin
    p = new();
    c = new();
    c.m_get_port.connect(p.m_get_export);  //通过句柄赋值进行连接
    c.run();
    #10 $finish;
  end
endmodule

需要说明的是,get需要使用(output T trans)做参数,这样才能将数据通过层层函数传递到消费者。

运行结果如下:


# [INFO]: Generated the transaction: 303379748
# [INFO]: Get the transaction: 303379748
# [INFO]: Generated the transaction:-1064739199
# [INFO]: Get the transaction:-1064739199
# [INFO]: Generated the transaction:-2071669239
# [INFO]: Get the transaction:-2071669239
# [INFO]: Generated the transaction:-1309649309
# [INFO]: Get the transaction:-1309649309
# [INFO]: Generated the transaction: 112818957
# [INFO]: Get the transaction: 112818957
# [INFO]: Generated the transaction: 1189058957
# [INFO]: Get the transaction: 1189058957
# [INFO]: Generated the transaction:-1295874971
# [INFO]: Get the transaction:-1295874971
# [INFO]: Generated the transaction:-1992863214
# [INFO]: Get the transaction:-1992863214
# [INFO]: Generated the transaction: 15983361
# [INFO]: Get the transaction: 15983361
# [INFO]: Generated the transaction: 114806029
# [INFO]: Get the transaction: 114806029
# ** Note: $finish : tlm_get.sv(72)
# Time: 10 ns Iteration: 0 Instance: /top


其对应的UML模型图如下:

tlm_get