精益求精
在TLM based的验证环境中,往往会碰到这样的需求:将来自不同地方的数据源进行统一处理。比如在USB的物理层driver建模中,packet来自不同的device,在物理层统一发送出去。
TLM的建模方式提供了多对一的连接方式,为了演示这个功能,特此写了一个小程序。
程序的结构如下:
声明了一个fifo, fifo的get_export, put_export都有3个连接。
为了区分不同的producer, 在producer class中用到了静态变量,每次例化一个相同的类,静态变量都会增加1. 而各自的pkt会记录当时的静态变量值,作为producer产生的transaction值。 源程序如下:
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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
/***************************************************************
* Filename : multi_connect.sv
* Author : Zhu,YH
* Created On : Mon May 28 04:53:14 2012
* Description : multiple port connect to export.
**************************************************************
* Revision History : Initialized On Mon May 28 04:53:25 2012
*
**************************************************************/
`include "uvm_macros.svh"
import uvm_pkg::*;
class producer extends uvm_component;
static int num = 0;
int pkt;
uvm_blocking_put_port#(int) pkt_put_port;
function new(string name = "", uvm_component parent);
super.new(name, parent);
pkt = num++;
endfunction:new
function void build_phase(uvm_phase phase);
super.build_phase(phase);
pkt_put_port = new("put_port",this);
endfunction:build_phase
task main_phase(uvm_phase phase);
phase.raise_objection(this);
for(int i = 0; i<5; i++) begin
int delay;
delay = $urandom(10);
#delay;
`uvm_warning(get_full_name(), $sformatf("put item:%0d", pkt))
pkt_put_port.put(pkt);
end
phase.drop_objection(this);
endtask:main_phase
endclass:producer
class consumer extends uvm_component;
uvm_blocking_get_port pkt_get_port;
function new(string name = "", uvm_component parent);
super.new(name, parent);
endfunction:new
function void build_phase(uvm_phase phase);
super.build_phase(phase);
pkt_get_port = new("get_port",this);
endfunction:build_phase
task main_phase(uvm_phase phase);
phase.raise_objection(this);
for(int i=0; i<5; i++) begin
int pkt;
int delay;
delay = $urandom(10);
#delay;
pkt_get_port.get(pkt);
`uvm_warning(get_full_name(), $sformatf("Got item:%0d",pkt))
end
phase.drop_objection(this);
endtask:main_phase
endclass:consumer
class test extends uvm_test;
uvm_tlm_fifo#(int) fifo;
producer p[3];
consumer c[3];
`uvm_component_utils(test)
function new(string name = "", uvm_component parent);
super.new(name, parent);
endfunction:new
function void build_phase(uvm_phase phase);
super.build_phase(phase);
fifo = new("fifo", this, 20);
for(int i=0; i<3; i++) begin
c[i] = new($sformatf("consumer%0d", i), this);
p[i] = new($sformatf("producer%0d", i), this);
end
endfunction:build_phase
function void connect_phase(uvm_phase phase);
for(int i=0; i<3; i++) begin
c[i].pkt_get_port.connect(fifo.get_export);
p[i].pkt_put_port.connect(fifo.put_export);
end
endfunction:connect_phase
endclass:test
module multi_connect(/*AUTOARG*/) ;
initial begin
run_test("test");
end
endmodule
运行结果如下:
# UVM-1.1
# (C) 2007-2011 Mentor Graphics Corporation
# (C) 2007-2011 Cadence Design Systems, Inc.
# (C) 2006-2011 Synopsys, Inc.
# (C) 2011 Cypress Semiconductor Corp.
# —————————————————————-
# UVM_INFO @ 0: reporter [RNTST] Running test test…
# UVM_WARNING multi_connect.sv(34) @ 1373569184: uvm_test_top.producer2 [uvm_test_top.producer2] put item:2
# UVM_WARNING multi_connect.sv(34) @ 1373569184: uvm_test_top.producer1 [uvm_test_top.producer1] put item:1
# UVM_WARNING multi_connect.sv(34) @ 1373569184: uvm_test_top.producer0 [uvm_test_top.producer0] put item:0
# UVM_WARNING multi_connect.sv(63) @ 1373569184: uvm_test_top.consumer2 [uvm_test_top.consumer2] Got item:2
# UVM_WARNING multi_connect.sv(63) @ 1373569184: uvm_test_top.consumer1 [uvm_test_top.consumer1] Got item:1
# UVM_WARNING multi_connect.sv(63) @ 1373569184: uvm_test_top.consumer0 [uvm_test_top.consumer0] Got item:0
# UVM_WARNING multi_connect.sv(34) @ 2747138368: uvm_test_top.producer2 [uvm_test_top.producer2] put item:2
# UVM_WARNING multi_connect.sv(34) @ 2747138368: uvm_test_top.producer1 [uvm_test_top.producer1] put item:1
# UVM_WARNING multi_connect.sv(34) @ 2747138368: uvm_test_top.producer0 [uvm_test_top.producer0] put item:0
# UVM_WARNING multi_connect.sv(63) @ 2747138368: uvm_test_top.consumer2 [uvm_test_top.consumer2] Got item:2
# UVM_WARNING multi_connect.sv(63) @ 2747138368: uvm_test_top.consumer1 [uvm_test_top.consumer1] Got item:1
# UVM_WARNING multi_connect.sv(63) @ 2747138368: uvm_test_top.consumer0 [uvm_test_top.consumer0] Got item:0
# UVM_WARNING multi_connect.sv(34) @ 4120707552: uvm_test_top.producer2 [uvm_test_top.producer2] put item:2
# UVM_WARNING multi_connect.sv(34) @ 4120707552: uvm_test_top.producer1 [uvm_test_top.producer1] put item:1
# UVM_WARNING multi_connect.sv(34) @ 4120707552: uvm_test_top.producer0 [uvm_test_top.producer0] put item:0
# UVM_WARNING multi_connect.sv(63) @ 4120707552: uvm_test_top.consumer2 [uvm_test_top.consumer2] Got item:2
# UVM_WARNING multi_connect.sv(63) @ 4120707552: uvm_test_top.consumer1 [uvm_test_top.consumer1] Got item:1
# UVM_WARNING multi_connect.sv(63) @ 4120707552: uvm_test_top.consumer0 [uvm_test_top.consumer0] Got item:0
# UVM_WARNING multi_connect.sv(34) @ 5494276736: uvm_test_top.producer2 [uvm_test_top.producer2] put item:2
# UVM_WARNING multi_connect.sv(34) @ 5494276736: uvm_test_top.producer1 [uvm_test_top.producer1] put item:1
# UVM_WARNING multi_connect.sv(34) @ 5494276736: uvm_test_top.producer0 [uvm_test_top.producer0] put item:0
# UVM_WARNING multi_connect.sv(63) @ 5494276736: uvm_test_top.consumer2 [uvm_test_top.consumer2] Got item:2
# UVM_WARNING multi_connect.sv(63) @ 5494276736: uvm_test_top.consumer1 [uvm_test_top.consumer1] Got item:1
# UVM_WARNING multi_connect.sv(63) @ 5494276736: uvm_test_top.consumer0 [uvm_test_top.consumer0] Got item:0
# UVM_WARNING multi_connect.sv(34) @ 6867845920: uvm_test_top.producer2 [uvm_test_top.producer2] put item:2
# UVM_WARNING multi_connect.sv(34) @ 6867845920: uvm_test_top.producer1 [uvm_test_top.producer1] put item:1
# UVM_WARNING multi_connect.sv(34) @ 6867845920: uvm_test_top.producer0 [uvm_test_top.producer0] put item:0
# UVM_WARNING multi_connect.sv(63) @ 6867845920: uvm_test_top.consumer2 [uvm_test_top.consumer2] Got item:2
# UVM_WARNING multi_connect.sv(63) @ 6867845920: uvm_test_top.consumer1 [uvm_test_top.consumer1] Got item:1
# UVM_WARNING multi_connect.sv(63) @ 6867845920: uvm_test_top.consumer0 [uvm_test_top.consumer0] Got item:0
#
# — UVM Report Summary —
#
# ** Report counts by severity
# UVM_INFO : 1
# UVM_WARNING : 30
# UVM_ERROR : 0
# UVM_FATAL : 0
# ** Report counts by id
# [RNTST] 1
# [uvm_test_top.consumer0] 5
# [uvm_test_top.consumer1] 5
# [uvm_test_top.consumer2] 5
# [uvm_test_top.producer0] 5
# [uvm_test_top.producer1] 5
# [uvm_test_top.producer2] 5