たまに「vritual」がついたfunction/taskをみかけますが、動作の違いが不明だったので、試してみました
はじめに
UVMのコードを書いていると「virtural」型がついたfunction/taskをみかけます
しらべてもよくわからなったので、実際に動かして動作を確認します
vritualあり/なしでどうかわるか
virtualなしの場合
まず、virtual型を付けずに定義したクラスを使って以下のサンプルコードを作成しました
class base_class;
function void print();
$display("base_class");
endfunction
endclass
class extends_class extends base_class;
function void print();
$display("extends_class");
endfunction
endclass
module tb;
initial begin
base_class b_class; // base_class型のb_classを宣言
extends_class e_class; // extends_class型のe_classを宣言
e_class = new(); // e_classを初期化
b_class = e_class; // e_classの内容をb_classに代入
// 継承元のprintが反映されれば"base_class"を出力
// 継承後のprintが反映されれば"extends_clss"を出力
b_class.print;
e_class.print;
end
endmodule
// 実行結果
// base_class
// extends_class
base_classで宣言したb_classは、base_classのprint()が実行され
extends_classで宣言したe_classは、extends_classのprint()が実行されました
virtualありの場合
次に、virtualありでfunctionを定義してみます
class base_class;
// function void print();
virtual function void print();
$display("base_class");
endfunction
endclass
class extends_class extends base_class;
function void print();
$display("extends_class");
endfunction
endclass
module tb;
initial begin
base_class b_class; // base_class型のb_classを宣言
extends_class e_class; // extends_class型のe_classを宣言
e_class = new(); // e_classを初期化
b_class = e_class; // e_classの内容をb_classに代入
// 継承元のprintが反映されれば"base_class"を出力
// 継承後のprintが反映されれば"extends_clss"を出力
b_class.print;
e_class.print;
end
endmodule
// 実行結果
// extends_class
// extends_class
base_classで宣言したb_classは、extends_classのprint()が実行され
extends_classで宣言したe_classは、extends_classのprint()が実行されました
解説
virtualあり/なしの動作の違いを解説します
virtualなしの場合、シミュレーション実行前に動作が確定します
virtualありの場合、シミュレーション実行後に動作が確定します
コードを追って説明します
virtualなしの場合
まずは、virtualがなしの場合です
base_class b_class; // base_class型のb_classを宣言
extends_class e_class; // extends_class型のe_classを宣言
base_class, extends_class型の変数b_class, e_classを宣言します
この時点で、print()がどんな動作をするか決定します
次からの行でnew()や代入を行っていますが、print()の動作は変化しません
virtualありの場合
次にvirtualありの場合です
base_class b_class; // base_class型のb_classを宣言
extends_class e_class; // extends_class型のe_classを宣言
virtualを付けてprint()を定義している場合、この時点では、print()がどんな動作をするか決定しません
e_class = new(); // e_classを初期化
new()でe_classを初期化しました。このとき、e_classのprint()の動作が決定します
extends_classのprint()は”extends_class”を出力するfunctionなので、”extends_class”が出力されます
b_class = e_class; // e_classの内容をb_classに代入
e_classをb_classに代入しました。このとき、b_classのprint()の動作が決定します
e_classのprint()の動作がb_classのprint()に引き継がれます
まとめ
「virtual」あり/なしでどう動作が変化するかをサンプルコードを作成して確認しました
コメント