UVMにはFactory Overrideの機構が組み込まれていて、Factoryに対し指示する事によって、上位の階層クラスから下位クラスのインスタンス化を変更する事ができる。
Factory Overrideで同じ対象に対して複数のインスタンス置換指示をした場合、やり方によってどの指示が優先され、実際のインスタンス化が行われるかが違くなる。なので意図しない置換が実行されてしまい混乱するので注意が必要。
通常のType Overrideでの優先順位
良く使われる通常Type Overrideでは、後に指示をされたものが優先され実行される。通常、プログラミング言語では上から下に順に実行され、後に設定された物がそこから有効になるのでこれは分かり易いであろう。
以下の例の様に同じmy_envに対してmy_env_1と_2へのoverride指示をすると、my_env_1への置換指示は行われず、後に指示したmy_env_2への置換が実行される。
my_env::type_id::set_type_override(my_env_1::get_type()); // Replace my_env with my_env_1
my_env::type_id::set_type_override(my_env_2::get_type()); // Replace my_env with my_env_2 <-- Prioritized!!!
こんな事普通はやらないだろうとか思うかもしれないが、ここでは分かり易く説明する為にわざわざ同じ個所にFactory Overrideの指示を書いている。実用上は継承したクラスのfunction内でsuper.の後にFactory Overrideの指示を書いて、親クラスでの指示を上書きして別のFactory Overrideをしたりする事は日常的に良く使う。
virtual function void set_factory_override();
super.set_factory_override();
my_env::type_id::set_type_override(my_env_2::get_type());
endfunction
Type Overrideで先に設定された物を優先させる
set_type_overrid()の引数を見てみると以下の様になっている。
static function void set_type_override (
uvm_object_wrapper override_type,
bit replace = 1
)
replaceと言う引数を与える事ができ、replace = 0を設定すると、これ以前にFactory Overridenの指示が有った場合には、そちらを優先し、当該のFactory Overrideは実行されない。
my_env::type_id::set_type_override(my_env_1::get_type() ); // Replace my_env with my_env_1 <-- Prioritized!!!
my_env::type_id::set_type_override(my_env_2::get_type(), 0); // Replace my_env with my_env_2 <-- Yield.
Instance Overrideの優先順位
指定したTypeの全てのInstanceを対象にFactory Overrideを行うType Overrideの他に、個別のInstanceに対してのみFactory Overrideを行うInstance Overrideがある。
Instance Overrideの場合には優先順位が逆となり、先に指示されたものが優先されされる。良く使うType Overrideとは優先順位が違うので、この事を知らないと意図した通りにFactory Overrideがされなくて混乱するので注意が必要。
又、Instance Overrideの後にType OverrideがあってもInstance Overrideの方が優先される。
my_env::type_id::set_inst_override(my_env_2::get_type(), "env", this); // Override to create my_env_2 <-- Prioritized!!!
my_env::type_id::set_inst_override(my_env_1::get_type(), "env", this); // Override to create my_env_1 <-- Yield.
my_env::type_id::set_type_override(my_env_1::get_type(), 1 ); // Override to create my_env_1 <-- Yield.
なので、優先順位として
- Instance Override
- Type Override (replace = 1)
- Type Override (replace = 0)
の優先順位となる。
継承クラスでInstance Overrideを親クラスから変えたい場合にはsuper.の後ではなく、super.の前に書く必要がある。
virtual function void set_factory_override();
my_env::type_id::set_inst_override(my_env_x::get_type(), "env", this);
super.set_factory_override();
endfunction
サンプルテストベンチ
`include "uvm_macros.svh"
module tb;
import uvm_pkg::*;
class my_env extends uvm_env;
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
`uvm_component_utils(my_env)
virtual function void build_phase(uvm_phase phase);
`uvm_info(get_type_name(), "Building my_env", UVM_MEDIUM)
endfunction
endclass
class my_env_1 extends my_env;
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
`uvm_component_utils(my_env_1)
virtual function void build_phase(uvm_phase phase);
`uvm_info(get_type_name(), "Building my_env_1", UVM_MEDIUM)
endfunction
endclass
class my_env_2 extends my_env;
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
`uvm_component_utils(my_env_2)
virtual function void build_phase(uvm_phase phase);
`uvm_info(get_type_name(), "Building my_env_2", UVM_MEDIUM)
endfunction
endclass
class my_test extends uvm_test;
my_env env;
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
`uvm_component_utils(my_test)
virtual function void build_phase(uvm_phase phase);
env = my_env::type_id::create("env", this);
endfunction
virtual function void end_of_elaboration_phase(uvm_phase phase);
super.end_of_elaboration_phase(phase);
uvm_factory::get().print(0);
endfunction
endclass
class my_test_1 extends my_test;
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
`uvm_component_utils(my_test_1)
virtual function void build_phase(uvm_phase phase);
my_env::type_id::set_type_override(my_env_1::get_type()); // Override to create my_env_1
my_env::type_id::set_type_override(my_env_2::get_type()); // Override to create my_env_2 <-- Prioritized!!!
super.build_phase(phase);
endfunction
endclass
class my_test_2 extends my_test;
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
`uvm_component_utils(my_test_2)
virtual function void build_phase(uvm_phase phase);
my_env::type_id::set_type_override(my_env_1::get_type(), 1); // Override to create my_env_1 <-- Prioritized!!!
my_env::type_id::set_type_override(my_env_2::get_type(), 0); // Override to create my_env_2
super.build_phase(phase);
endfunction
endclass
class my_test_3 extends my_test;
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
`uvm_component_utils(my_test_3)
virtual function void build_phase(uvm_phase phase);
my_env::type_id::set_inst_override(my_env_2::get_type(), "env", this); // Override to create my_env_2 <-- Prioritized!!!
my_env::type_id::set_inst_override(my_env_1::get_type(), "env", this); // Override to create my_env_1
my_env::type_id::set_type_override(my_env_1::get_type(), 1 ); // Override to create my_env_1
super.build_phase(phase);
endfunction
endclass
initial run_test("my_test");
endmodule
結果
UVM_INFO @ 0: reporter [RNTST] Running test my_test_1...
UVM_INFO @ 0: reporter [TPREGR] Original object type 'my_env' already registered to produce 'my_env_1'. Replacing with override to produce type 'my_env_2'.
UVM_INFO tb.sv(42) @ 0: uvm_test_top.env [my_env_2] Building my_env_2
UVM_INFO uvm/2020.3.1/src/base/uvm_factory.svh(2050) @ 0: reporter [UVM/FACTORY/PRINT]
#### Factory Configuration (*)
No instance overrides are registered with this factory
Type Overrides:
Requested Type Override Type
-------------- -------------
my_env my_env_2
(*) Types with no associated type name will be printed as <unknown>
####
UVM_INFO @ 0: reporter [RNTST] Running test my_test_2...
UVM_INFO @ 0: reporter [TPREGD] Original object type 'my_env' already registered to produce 'my_env_1'. Set 'replace' argument to replace the existing entry.
UVM_INFO tb.sv(28) @ 0: uvm_test_top.env [my_env_1] Building my_env_1
UVM_INFO uvm/2020.3.1/src/base/uvm_factory.svh(2050) @ 0: reporter [UVM/FACTORY/PRINT]
#### Factory Configuration (*)
No instance overrides are registered with this factory
Type Overrides:
Requested Type Override Type
-------------- -------------
my_env my_env_1
(*) Types with no associated type name will be printed as <unknown>
####
UVM_INFO @ 0: reporter [RNTST] Running test my_test_3...
UVM_INFO tb.sv(42) @ 0: uvm_test_top.env [my_env_2] Building my_env_2
UVM_INFO uvm/2020.3.1/src/base/uvm_factory.svh(2050) @ 0: reporter [UVM/FACTORY/PRINT]
#### Factory Configuration (*)
Instance Overrides:
Requested Type Override Path Override Type
-------------- ---------------- -------------
my_env uvm_test_top.env my_env_2
my_env uvm_test_top.env my_env_1
Type Overrides:
Requested Type Override Type
-------------- ----------------
my_env my_env_1
(*) Types with no associated type name will be printed as <unknown>
####
参考記事