3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

[UVM] Factory overrideの方法を整理する

Last updated at Posted at 2019-09-08

Factory overrideには似たようなメソッドがたくさんあって、それぞれどのように違うのか、どう使い分ければいいのかわかりづらいです。そこで全種類を網羅し、どのような違いがあるのかをまとめてみることにしました。

本解説で引用するソースコードのUVMのバージョンは1.2ではなく、1.1dになります。これは1.1dのほうがソースが単純で説明しやすいからです。本解説で扱う範囲では本質的には1.2も1.1dも同じ構造になっていますので、同様に取り扱い可能です。

前知識

最初にFactory overrideの周辺部分の説明です。

typeとtype_name

Factory overrideでのオリジナルクラスとオーバライドクラスの指定は、type_nameかtypeいずれかで行います。type_nameの型はstringでtypeの型はuvm_object_wrapperになります。uvm_object_wrapperが何者かを正確に説明するのはとても難しいので、ここでは簡単に、factory overrideを簡単にするためにUVMで定義されたクラスと考えて下さい。

各クラスのtype, type_nameは以下のマクロで定義されます。引数typeを文字列(string)に変換したものがそのクラスのtype_nameになります。

  • `uvm_object_utils(type)
  • `uvm_object_utils_begin(type)
  • `uvm_object_param_utils(type)
  • `uvm_object_param_utils_begin(type)
  • `uvm_component_utils(type)
  • `uvm_component_utils_begin(type)
  • `uvm_component_param_utils(type)
  • `uvm_component_param_utils_begin(type)

以下のコードの場合、type_nameは"my_env_c"という文字列になります。またこのクラスに対応するuvm_object_wrapperが定義され、そのオブジェクトはmy_env_c::get_type()またはmy_env_c::type_id::get()で取得することができます。この部分は次節でもう少し説明します。

class my_env_c extends uvm_env;
  `uvm_component_utils(my_env_c)

  function new(string name, uvm_component parent);
    super.new(name, parent);
  endfunction
endclass

`uvm_object_param_utils等のパラメタライズクラス用のマクロでは定義されるのはtypeだけでtype_nameが定義されません。パラメータが異なる同一クラス名のクラスはSystemVerilogでは異なるクラスとして扱うので、それらのtype_nameが一緒になってしまうと都合が悪いからです (type_nameにparameterをstringに変換したものを付け加えられれば良いのですが、マクロで実現するのは不可能でしょう)。typeのほうは以下のように取得するときにパラメータも指定するので、このようなあいまいさが発生しません。

uvm_object_wrapper ctype;
ctype = my_param_env_c#(param)::get_type();

uvm_driverの派生クラスはuvm_sequence_itemのサブクラスをパラメータとしたparameterized classですので、`uvm_component_param_utils()を使わなければならないはずですが、そのような例はとてもまれでほとんどが`uvm_component_utils()を使用しています。通常uvm_driverは各クラス一種類のパラメータだけ受け取るように設計されるため、複数種類のパラメータへの対応を気にする必要がないためです。

get_type()とtype_id::get()

あるクラスのtypeを取得するのに、2種類の方法が使われます。一つはClass::get_type()で、もう一つはClass::type_id::get()です。両方ともスタティックメソッドなので、new()/create()しないで使用できます。以下のような感じで使用します。

set_type_override_by_type(Original_class::get_type(), Override_class::get_type());
set_type_override_by_type(Original_class::type_id::get(), Override_class::type_id::get());

両者に違いはなく、同じ値を返します。

class::get_type()は以下のように定義されているので、class::type_id::get()と全く同じ動作になります。

static function type_id get_type();
  return type_id::get();
endfunction

本記事ではこれ以降class::get_type()を使う例に統一します。

Type_override_by_type

特定のtypeのクラスを全て新しいtypeで置き換える方法です。3つの書式があります。

一つ目はuvm_componentで定義されているメソッドを使用する方法です。従ってuvm_objectからは使用できません。

set_type_override_by_type(original_class::get_type(), override_class::get_type());

このメソッドはUVMでは以下のように定義されていて、後で説明するfactory.set_type_override_by_type()を呼んでいるだけです。

function void uvm_component::set_type_override_by_type (uvm_object_wrapper original_type,
                                                        uvm_object_wrapper override_type,
                                                        bit    replace=1);
   factory.set_type_override_by_type(original_type, override_type, replace);
endfunction 

次が対象クラスのメソッドを呼び出してオーバーライドする方法です。uvm_component_registery #(T, Tname)::set_type_override()が呼ばれます。

original_class::type_id::set_type_override(override_class::get_type());

このメソッドはUVM-1.1dでは以下のように定義されていて、同様に後で説明するfactory.set_type_override_by_type()を呼んでいるだけです。

  static function void set_type_override (uvm_object_wrapper override_type,
                                          bit replace=1);
    factory.set_type_override_by_type(get(),override_type,replace);
  endfunction

最後にuvm_factoryのメソッドを使用する方法です。

factory.set_type_override_by_type(original_class::get_type(),
                                  override_class::get_type());

要するに、どの方法を使っても最後にはfactory.set_type_override_by_type()が呼び出されるわけです。

Inst_override_by_type

指定されたクラスのうち、特定のインスタンスのクラスを新しいtypeで置き換える方法です。インスタンスには正規表現が適用され、複数のインスタンスを一度にオーバーライドすることも可能です。3つの書式があります。

一つ目はuvm_componentで定義されているメソッドを使用する方法です。従ってuvm_objectからは使用できません。

set_inst_override_by_type("agent0.*,         // Relative path from current path
                          original_class::get_type(),
                          override_class::get_type());

このメソッドはUVMでは以下のように定義されていて、パス名を絶対パスに変換して後で説明するfactory.set_inst_override_by_type()を呼んでいるだけです。

function void uvm_component::set_inst_override_by_type (string relative_inst_path,  
                                                        uvm_object_wrapper original_type,
                                                        uvm_object_wrapper override_type);
  string full_inst_path;

  if (relative_inst_path == "")
    full_inst_path = get_full_name();
  else
    full_inst_path = {get_full_name(), ".", relative_inst_path};

  factory.set_inst_override_by_type(original_type, override_type, full_inst_path);

endfunction

次が対象クラスのメソッドを呼び出してオーバーライドする方法です。3番目の引数は2番目の引数の起点となるオブジェクトへのハンドルを指定します。


original_class::type_id::set_inst_override(override_class::get_type(),
                                           "agent0.*", // Relative path from parent
                                           parent);    // Class handle to base path

このメソッドはUVMでは以下のように定義されていて、後で説明するfactory.set_inst_override_by_type()を呼んでいるだけです。

  static function void set_inst_override(uvm_object_wrapper override_type,
                                         string inst_path,
                                         uvm_component parent=null);
    string full_inst_path;
    if (parent != null) begin
      if (inst_path == "")
        inst_path = parent.get_full_name();
      else
        inst_path = {parent.get_full_name(),".",inst_path};
    end
    factory.set_inst_override_by_type(get(),override_type,inst_path);
  endfunction

最後にuvm_factoryのメソッドを使用する方法です。

factory.set_inst_override_by_type(original_class::get_type(),
                                  override_class::get_type(),
                                  "uvm_test_top.agent0.*"); // Full path

Type_override_by_name

overrideするクラスの指定をtypeではなくtype_nameで行う方法です。Deprecatedではないですが推奨されていません。クラスに対して`uvm_*_param_utilsを使った場合はtype_nameが設定されないため、この方法が使用できないためです。

一つ目はuvm_componentで定義されているメソッドを使用する方法です。従ってuvm_objectからは使用できません。

set_type_override("original_class_name", "override_class_name");

二つ目はuvm_factoryのメソッドを使用する方法です。

factory.set_type_override_by_name("original_class_name", "override_class_name");

Inst_override_by_name

Type_override_by_nameと同じですが、オーバーライドの範囲を引数で限定したUVM_componentの階層に絞ります。同様にDeprecatedではないですが推奨されていません。

一つ目はuvm_componentで定義されているメソッドを使用する方法です。従ってuvm_objectからは使用できません。

set_inst_override("agent0.*", // Relative path from current path
                  "original_type_name",
                  "override_type_name");

二つ目はuvm_factoryのメソッドを使用する方法です。

factory.set_inst_override_by_name("uvm_test_top.agent0.*", // Full path
                                  "original_type_name",
                                  "override_type_name");

参考文献

Accellera, "8.2 UVM factory", [Universal Verification Methodology (UVM) 1.2 Class Reference]
(https://www.accellera.org/images/downloads/standards/uvm/UVM_Class_Reference_Manual_1.2.pdf), pp.110-124.

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?