uvm中的factory重载机制

在uvm 中可以利用factory机制的重载作用改变某些component的特性, 而不用去修改testbench。比如说:

你写了2个driver的class, 但是uvm环境中只需要用到一个,如果这两个driver都是用factory注册,那么就可以用override的方式替换当前uvm环境中的driver。

使用override有两点需要注意: 一、注册component时候使用uvm_component_utils, 并且在创建instance的时候使用::type_id::creat(), 而不是使用new()

下面举一个例子加以说明:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Components:
- Agents
- my_agent
1. my_agent_v2 (child)
- Drivers
base_driver
1. eth_driver (child)
2. spi_driver (child)
- Sequencer - my_seqeuncer
- Sequences
- base_sequence
1. seq1 (child)
2. seq2 (child)
3. seq3 (child)
- Data
- eth_packet
- eth_v2_packet (child)

Sequencer within m_agnt2 operate on seq3, while the other two operate on seq1 by default
  1. 定义一个data packet的base class, 然后在派生出一个子类:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//------------------ eth_packet-----------------------------------
class eth_packet extends uvm_sequence_item;
`uvm_object_utils (eth_packet)

...

function new (string name = "eth_packet");
super.new (name);
`uvm_info (get_type_name(), "Packet created", UVM_MEDIUM)
endfunction
endclass

//------------------ eth_v2_packet-----------------------------------
class eth_v2_packet extends eth_packet;
`uvm_object_utils (eth_v2_packet)

...

function new (string name = "eth_v2_packet");
super.new (name);
endfunction
endclass
  1. 创建一个driver的base class, 然后派生出两个子类:eth_driverspi_driver
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
//------------------ base_driver-----------------------------------

class base_driver #(type T=eth_packet) extends uvm_driver;
`uvm_component_utils (base_driver #(T))

T pkt;

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

virtual function void build_phase (uvm_phase phase);
super.build_phase (phase);
pkt = T::type_id::create ("pkt0");
endfunction

virtual task run_phase (uvm_phase phase);
super.run_phase (phase);
`uvm_info (get_type_name(), $sformatf("Driver running ...with packet of type : %s", pkt.get_type_name()), UVM_MEDIUM)
endtask

endclass

//----------------- eth_driver-----------------------------------

class eth_driver #(type T=eth_packet) extends base_driver #(T);
`uvm_component_utils (eth_driver #(T))

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

//----------------- spi_driver-----------------------------------

class spi_driver #(type T=eth_packet) extends base_driver #(T);
`uvm_component_utils (spi_driver #(T))

function new (string name, uvm_component parent);
super.new (name, parent);
endfunction
endclass
  1. 定义几个sequence:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//----------------- base_sequence-----------------------------------
class base_sequence extends uvm_sequence;
`uvm_object_utils (base_sequence)
endclass

//----------------- seq1 -------------------------------------------
class seq1 extends base_eth_sequence;
`uvm_object_utils (seq1)
...
endclass

//----------------- seq2 -------------------------------------------
class seq2 extends base_eth_sequence;
`uvm_object_utils (seq2)
...
endclass

//----------------- seq3 -------------------------------------------
class seq3 extends base_eth_sequence;
`uvm_object_utils (seq3)
...
endclass
  1. 如下所示创建2个 agent
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
//----------------- my_agent -------------------------------------------
class my_agent extends uvm_agent;
`uvm_component_utils (my_agent)

base_driver m_drv0;
my_sequencer m_seqr0;

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

virtual function void build_phase (uvm_phase phase);
super.build_phase (phase);
m_drv0 = base_driver::type_id::create ("m_drv0", this);
m_seqr0 = my_sequencer::type_id::create ("m_seqr0", this);
endfunction

virtual function void connect_phase (uvm_phase phase);
super.connect_phase (phase);
m_drv0.seq_item_port.connect (m_seqr0.seq_item_export);
endfunction
endclass

//----------------- my_agent_v2 -------------------------------------------
class my_agent_v2 extends uvm_agent;
`uvm_component_utils (my_agent_v2)

eth_driver m_drv0;
my_sequencer m_seqr0;

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

virtual function void build_phase (uvm_phase phase);
super.build_phase (phase);
m_drv0 = eth_driver::type_id::create ("m_drv0", this);
m_seqr0 = my_sequencer::type_id::create ("m_seqr0", this);
endfunction

virtual function void connect_phase (uvm_phase phase);
super.connect_phase (phase);
m_drv0.seq_item_port.connect (m_seqr0.seq_item_export);
endfunction
endclass
  1. my_agent包含base_driver, my_agent_v2包含eth_driver, 那么env如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class my_env extends uvm_env ;
`uvm_component_utils (my_env)

my_agent m_agnt0;
my_agent m_agnt1;
my_agent_v2 m_agnt2;

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

virtual function void build_phase (uvm_phase phase);
super.build_phase (phase);
m_agnt0 = my_agent::type_id::create ("m_agnt0", this);
m_agnt1 = my_agent::type_id::create ("m_agnt1", this);
m_agnt2 = my_agent_v2::type_id::create ("m_agnt2", this);
endfunction : build_phase
endclass : my_env

整个uvm环境如下图所示:

  1. 创建test case如下:
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
class feature_test extends base_test;
`uvm_component_utils (feature_test)

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

virtual function void build_phase (uvm_phase phase);
super.build_phase (phase);

`ifdef PKT_OVERRIDE
// Substitute all eth_packets with eth_v2_packet
set_type_override_by_type (eth_packet::get_type(), eth_v2_packet::get_type());
`endif



// These are the three different styles to override something

`ifdef DRV_STYLE1
// Substitute all instances of base_driver with driver2
set_type_override_by_type (base_driver::get_type(), spi_driver::get_type());
`elsif DRV_STYLE2
// Substitute only eth_driver in agnt2 with spi_driver - by calling the component to be replaced method
eth_driver::type_id::set_inst_override (spi_driver::get_type(), "m_top_env.m_agnt2.m_drv0", this);
`elsif DRV_STYLE3
// Substitute base_driver only in agnt0 - by calling the factory method
factory.set_inst_override_by_type (base_driver::get_type(), eth_driver::get_type(), {get_full_name(), ".m_top_env.m_agnt0.*"});
`endif



// Trying to override a sequence

`ifdef SEQ_TYPE
// Substitute seq1 with seq2
set_type_override_by_type (seq1::get_type(), seq3::get_type());
`elsif SEQ_INST
// Substitute seq1 with seq2 only for agnt1
set_inst_override_by_type ("m_top_env.m_agnt1.m_seqr0.*", seq1::get_type(), seq2::get_type());
`else
`endif
factory.print();
endfunction
// Enter test code for feature here
endclass

定义PKT_OVERRIDEDRV_STYLE3SEQ_INST, 那么运行结果为:

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
107
108
----------------------------------------------------------------
CDNS-UVM-1.1d (14.10-s013)
(C) 2007-2013 Mentor Graphics Corporation
(C) 2007-2013 Cadence Design Systems, Inc.
(C) 2006-2013 Synopsys, Inc.
(C) 2011-2013 Cypress Semiconductor Corp.
----------------------------------------------------------------
UVM_INFO @ 0: reporter [RNTST] Running test feature_test...

#### Factory Configuration (*)

Instance Overrides:

Requested Type Override Path Override Type
---------------- ---------------------------------------- ---------------
base_driver #(T) uvm_test_top.m_top_env.m_agnt0.* eth_driver #(T)
seq1 uvm_test_top.m_top_env.m_agnt1.m_seqr0.* seq2

Type Overrides:

Requested Type Override Type
---------------- ----------------------------------------
eth_packet eth_v2_packet

All types registered with the factory: 51 total
(types without type names will not be printed)

Type Name
---------
base_driver #(T)
base_eth_sequence
base_test
eth_driver #(T)
eth_packet
eth_v2_packet
feature_test
my_agent
my_agent_v2
my_env
my_sequencer
reg_test
seq1
seq2
seq3
(*) Types with no associated type name will be printed as

####

UVM_INFO ./tb/my_pkg.sv(45) @ 0: reporter@@eth_v2_packet [eth_v2_packet] Packet created
UVM_INFO ./tb/my_pkg.sv(45) @ 0: reporter@@eth_v2_packet [eth_v2_packet] Packet created
UVM_INFO ./tb/my_pkg.sv(45) @ 0: reporter@@eth_v2_packet [eth_v2_packet] Packet created
UVM_INFO @ 0: reporter [UVMTOP] UVM testbench topology:
--------------------------------------------------------------
Name Type Size Value
--------------------------------------------------------------
uvm_test_top feature_test - @2657
m_top_env my_env - @218
m_agnt0 my_agent - @2772
m_drv0 eth_driver #(T) - @2770
rsp_port uvm_analysis_port - @2963
seq_item_port uvm_seq_item_pull_port - @2912
m_seqr0 my_sequencer - @2996
rsp_export uvm_analysis_export - @3054
seq_item_export uvm_seq_item_pull_imp - @3602
arbitration_queue array 0 -
lock_queue array 0 -
num_last_reqs integral 32 'd1
num_last_rsps integral 32 'd1
m_agnt1 my_agent - @2751
m_drv0 base_driver #(T) - @3676
rsp_port uvm_analysis_port - @3773
seq_item_port uvm_seq_item_pull_port - @3725
m_seqr0 my_sequencer - @3754
rsp_export uvm_analysis_export - @3859
seq_item_export uvm_seq_item_pull_imp - @4399
arbitration_queue array 0 -
lock_queue array 0 -
num_last_reqs integral 32 'd1
num_last_rsps integral 32 'd1
m_agnt2 my_agent_v2 - @2802
m_drv0 eth_driver #(T) - @4455
rsp_port uvm_analysis_port - @4553
seq_item_port uvm_seq_item_pull_port - @4505
m_seqr0 my_sequencer - @3803
rsp_export uvm_analysis_export - @4639
seq_item_export uvm_seq_item_pull_imp - @5179
arbitration_queue array 0 -
lock_queue array 0 -
num_last_reqs integral 32 'd1
num_last_rsps integral 32 'd1
--------------------------------------------------------------

UVM_INFO ./tb/my_pkg.sv(94) @ 0: uvm_test_top.m_top_env.m_agnt2.m_drv0 [eth_driver #(T)] Driver running ...with packet of type : eth_v2_packet
UVM_INFO ./tb/my_pkg.sv(94) @ 0: uvm_test_top.m_top_env.m_agnt1.m_drv0 [base_driver #(T)] Driver running ...with packet of type : eth_v2_packet
UVM_INFO ./tb/my_pkg.sv(94) @ 0: uvm_test_top.m_top_env.m_agnt0.m_drv0 [eth_driver #(T)] Driver running ...with packet of type : eth_v2_packet
UVM_INFO ./tb/my_pkg.sv(278) @ 0: uvm_test_top.m_top_env.m_agnt2.m_seqr0@@seq3 [seq3] Executing pre_body
UVM_INFO ./tb/my_pkg.sv(250) @ 0: uvm_test_top.m_top_env.m_agnt1.m_seqr0@@seq1 [seq2] Executing pre_body
UVM_INFO ./tb/my_pkg.sv(282) @ 0: uvm_test_top.m_top_env.m_agnt2.m_seqr0@@seq3 [SEQ3] Starting seq3
UVM_INFO ./tb/my_pkg.sv(255) @ 0: uvm_test_top.m_top_env.m_agnt1.m_seqr0@@seq1 [SEQ2] Starting seq2
UVM_INFO ./tb/my_pkg.sv(232) @ 0: uvm_test_top.m_top_env.m_agnt0.m_seqr0@@seq1 [SEQ1] Starting seq1
UVM_INFO ./tb/my_pkg.sv(284) @ 10000: uvm_test_top.m_top_env.m_agnt2.m_seqr0@@seq3 [SEQ3] Ending seq3
UVM_INFO ./tb/my_pkg.sv(257) @ 10000: uvm_test_top.m_top_env.m_agnt1.m_seqr0@@seq1 [SEQ2] Ending seq2
UVM_INFO ./tb/my_pkg.sv(234) @ 10000: uvm_test_top.m_top_env.m_agnt0.m_seqr0@@seq1 [SEQ1] Ending seq1
UVM_INFO ./tb/my_pkg.sv(288) @ 10000: uvm_test_top.m_top_env.m_agnt2.m_seqr0@@seq3 [seq3] Executing post_body
UVM_INFO ./tb/my_pkg.sv(262) @ 10000: uvm_test_top.m_top_env.m_agnt1.m_seqr0@@seq1 [seq2] Executing post_body
UVM_INFO ./tb/my_pkg.sv(292) @ 10000: uvm_test_top.m_top_env.m_agnt2.m_seqr0@@seq3 [seq3] Executing post_start

--- UVM Report catcher Summary ---