04日目~モデルのひな形ステップ2
3日目は、uvm_testクラスの下にuvm_envクラスを組み込みました。4日目は、同様の記述方法で、一気に残りを組み込んでいきます。
- uvm_agent
- uvm_driver
- uvm_monitor
- uvm_sequencer
組み込みの順番を考えて、下から作っていきます。コードは、「model/」の下に記述していき、記述したファイルを「sample.svh」に追記していきます。
uvm_driver
class sample_driver extends uvm_driver;
`uvm_component_utils(sample_driver)
function new (string name, uvm_component parent);
super.new(name, parent);
endfunction
task run_phase(uvm_phase phase);
uvm_report_info("DRIVER", "Hi");
endtask
endclass
uvm_monitor
class sample_monitor extends uvm_monitor;
`uvm_component_utils(sample_monitor)
function new (string name, uvm_component parent);
super.new(name, parent);
endfunction
task run_phase(uvm_phase phase);
uvm_report_info("MONITOR", "Hi");
endtask
endclass
uvm_sequencer
class sample_sequencer extends uvm_sequencer;
`uvm_component_utils(sample_sequencer)
function new (string name, uvm_component parent);
super.new(name, parent);
endfunction
task run_phase(uvm_phase phase);
uvm_report_info("SEQR", "Hi");
endtask
endclass
sequencerは、最小限の構成で使うときは「定義しなくてもいい」ですが、ちゃんとテストベンチを組み立てようと考えたとき、sequencerも自分でextendsして作成することを推奨します。その理由は、後日の 内容で説明するか、ワンランク上の技術説明の箇所で行います。
uvm_agentと下位コンポーネントの組み込み(修正)
uvm_agentクラスは、上記3クラスの上位にあたるので、彼らをインスタンスして生成する記述を追加します。
#太字部分を修正しました。文字列なので、好きなな名前をセットしていいのですが、紛らわしいケースが発生するので、「インスタンス名」にしておくのがお勧めです
class sample_agent extends uvm_agent;
`uvm_component_utils(sample_agent)
sample_driver driver;
sample_monitor monitor;
sample_sequencer sequencer;
function new (string name, uvm_component parent);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
driver = sample_driver::type_id::create("driver", this); //修正
monitor = sample_monitor::type_id::create("monitor", this); //修正
sequencer = sample_sequencer::type_id::create("sequencer", this); //修正
endfunction
task run_phase(uvm_phase phase);
uvm_report_info("AGENT", "Hi");
endtask
endclass
uvm_envへの組み込み
uvm_agentクラスをuvm_envクラスに組み込みます。
class sample_env extends uvm_env;
`uvm_component_utils(sample_env)
sample_agent agent;
function new (string name, uvm_component parent);
super.new(name,parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
agent = sample_agent::type_id::create("agent", this);
endfunction
task run_phase(uvm_phase phase);
uvm_report_info("ENV", "Hello ENV");
endtask
endclass
黄色いところが、追記した部分です。
includeファイルの中身
model/以下に
- sample_model.svh
- sample_env.sv
- sample_agent.sv
- sample_driver.sv
- sample_monitor.sv
- sample_sequencer.sv
がある状態で、「sample_model.svh」を以下のようにします。includeの順番は「下位階層」から行っていきます。なお、「typedef」をうまく使うことで、includeの順番を好きなようにすることもできます。で すが、ここではそれを行いません。
`include "sample_driver.sv"
`include "sample_monitor.sv"
`include "sample_sequencer.sv"
`include "sample_agent.sv"
`include "sample_env.sv"
コンパイル
コンパイルすると、以下のWarningが出ます。
** Warning: model//sample_driver.sv(1): (vlog-2181) Use of a parameterized class uvm_driver as a type creates a default specialization.
** Warning: model//sample_sequencer.sv(1): (vlog-2181) Use of a parameterized class uvm_sequencer as a type creates a default specialization.
これは、uvm_driverとuvm_sequencerは「parameterized class」となっており、extends時にパラメータを記述していないため、defaultのパラメータが使われるよ?というメッセージです。これについては、後 日のお話で展開しますので、いまは「そういうものだ」と無視してください。
実行
実行すると、以下のようなログが出ます。
# 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
# UVM_INFO @ 0: uvm_test_top.env.agent [AGENT] Hi
# UVM_INFO @ 0: uvm_test_top.env.agent.sample_sequencer [SEQR] Hi
# UVM_INFO @ 0: uvm_test_top.env.agent.sample_monitor [MONITOR] Hi
# UVM_INFO @ 0: uvm_test_top.env.agent.sample_driver [DRIVER] Hi