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