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