03日目~モデルのひな形ステップ1
2日目で説明したモデルの構造と実行フェーズの一部を使って、モデルのひな形を作ってみます。説明内容としては、簡単な仕様のモデルの作り方と実行とかぶるのですが、ここでは「噛み砕いて」、1歩ずつ進 めていきたいと思います。
ファイルの分離
ベースは「01日目」のtb_top.svです。
`timescale 1ps/1ps
module tb_top;
`include "uvm_macros.svh"
import uvm_pkg::*;
class sample_test extends uvm_test;
`uvm_component_utils(sample_test)
function new (string name="sample_test", uvm_component parent=null);
super.new(name,parent);
endfunction
task run_phase(uvm_phase phase);
uvm_report_info("TEST", "Hello World");
endtask
endclass
initial begin
run_test();
end
endmodule
class記述が増えていくので、上記のclass記述を別ファイルにしてincludeします。
--- tb_top.sv
`timescale 1ps/1ps
module tb_top;
// UVM class library
`include "uvm_macros.svh"
import uvm_pkg::*;
// uvm user code
`include "sample_test.sv" /// ←ここ
/////////////////////////////////////
initial begin
run_test();
end
endmodule
--- sample_test.sv
class sample_test extends uvm_test;
`uvm_component_utils(sample_test)
function new (string name="sample_test", uvm_component parent=null);
super.new(name,parent);
endfunction
task run_phase(uvm_phase phase);
uvm_report_info("TEST", "Hello World");
endtask
endclass
tb_top.svとsample_test.svが「同じディレクトリ」にある状態を想定して、compileとrunします。
- vlog -sv +incdir+./+../uvm-1.1d/src tb_top.sv sample_test.sv
- vsim -c tb_top +UVM_TESTNAME=sample_test -do "run -all; quit"
これで、Hello Worldが表示されることを確認しましょう。
uvm_envを追加してみる
追加する前に、サンプルモデルを置くディレクトリを作成しておきます。
- mkdir model
ディレクトリを移動して、sample_env.svを記述します。
class sample_env extends uvm_env;
`uvm_component_utils(sample_env)
function new (string name, uvm_component parent);
super.new(name,parent);
endfunction
task run_phase(uvm_phase phase);
uvm_report_info("ENV", "Hello ENV");
endtask
endclass
uvm_component_utilsマクロは半定型文みたいなものです。newも。ところで、uvm_testクラスのnewにはnameに初期値を入れていますが、uvm_envクラスのnewにはnameに初期値を入れていません。何故かと いうと、uvm_envクラスは「uvm_testクラスにインスタンスして、生成記述をするときに名前を指定する」のですが、uvm_testクラスはユーザー側でインスタンス、生成しないんですね。だから、というわけで す。
もう1つファイルを作っておきます。
--- sample_model.svh
`include "sample_env.sv"
今後まだファイルを追加していくので、このようにモデル毎にincludeファイルを作るのが定番です。
uvm_envを組み込む
それでは次に、上記で記述したuvm_envクラスを組み込みましょう。uvm_testクラスにインスタンスして、「生成」します。
class sample_test extends uvm_test;
`uvm_component_utils(sample_test)
sample_env env;
function new (string name="sample_test", uvm_component parent=null);
super.new(name,parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
env = sample_env::type_id::create("env", this); //注意
endfunction
task run_phase(uvm_phase phase);
uvm_report_info("TEST", "Hello World");
endtask
endclass
黄色いところが「追加」した記述です。
- sample_env env;
- これはインスタンスしている記述です。
- function void build_phase...
- 実行フェーズのところで登場した、newの次に実行されるメソッドです。特に、「注意」と書いたところは独特な記述なので慣れてください。記述が定型なので、defineマクロ化してもいいですね。ここ の「create("env", this)」ですが、この引数がuvm_envクラスのnewへ渡されます。
実行
現在、tb_top.svは以下のようになっています。
`timescale 1ps/1ps
module tb_top;
// UVM class library
`include "uvm_macros.svh"
import uvm_pkg::*;
// uvm user code
`include "sample_model.svh"
`include "sample_test.sv"
/////////////////////////////////////
initial begin
run_test();
end
endmodule
それでは、コンパイルして実行してみましょう。include記述が3つありますので、vlogに指定する +incdir+パス+パス... に注意してください。
実行すると、以下のように表示されるはずです。
# UVM_INFO @ 0: reporter [RNTST] Running test sample_test...
# UVM_INFO @ 0: uvm_test_top [TEST] Hello World
# UVM_INFO @ 0: uvm_test_top.env [ENV] Hello ENV