[UVM] factory

 

factory 的應用

1. simv  +UVM_TESTNAME=hello_world_test

   通過指定test case 的名字就可以運行,test 是怎麼被創建的呢?

        Actually call uvm_root::run_test(), where it

        1. gets test name from command line (+UVM_TESTNAME)

        2. construct a component of that type via uvm_factory 

            factory.create_component_by_name()

2. 就是大家熟知的override。

sw_driver::type_id::set_type_override(old_sw_driver::get_type(), 0);

Which one wins depends on “replace” bit

  • replace= 1(default): later override will replace previous one
  • replace=0: otherwise

Multiple inst override

first inst override wins due to uvm_factory’sreturn first match” when finding instance override type

Mixed type/inst override

inst override wins due to uvm_factory’sinst override takes precedence” policy


How does UVM factory work

1. 註冊

class new_sw_driver extends uvm_component;
  `uvm_component_utils_begin(new_sw_driver)
    `uvm_field_int(frame_num)
    `uvm_field_int(port_num)
  `uvm_component_utils_end
endclass

 `uvm_*_utils 這個宏就是註冊到factory中,那它都做了些什麼呢(以component為例)?

`define uvm_component_utils(T) \
   `m_uvm_component_registry_internal(T,T) \
   `m_uvm_get_type_name_func(T) \

 

`define m_uvm_component_registry_internal(T,S) \
   typedef uvm_component_registry #(T,`"S`") type_id; \
   static function type_id get_type(); \
     return type_id::get(); \
   endfunction \
   virtual function uvm_object_wrapper get_object_type(); \
     return type_id::get(); \
   endfunction
  
 uvm_component_registry #(type T=uvm_component,string Tname="<unknown>") extends uvm_object_wrapper;
   typedef uvm_component_registry #(T,Tname) this_type;

  //ex: typedef uvm_component_registry #(sw_driver,"sw_driver") type_id;
   
  local static this_type me = get();//當靜態變量初始化時通過調用get函數註冊到factory中

  static function this_type get();
    if (me == null) begin
      uvm_factory f = uvm_factory::get();
      me = new;
      f.register(me);
    end
    return me;
  endfunction

  static function T create();//在build_phase 調用的create就是它 

從調用uvm_component_utils(T)可看出 T=Tname

factory 維護這一張註冊表(通過調用uvm_component_utils來把內容填入表中):

`uvm_component_utils(sw_driver)

`uvm_component_utils(new_sw_driver)

Index by name

                                                    protected uvm_object_wrapper m_type_names[string];(name)                                                   

Index

Value

sw_driver

sw_driver::type_id

new_sw_driver

new_sw_driver::type_id

當調用set_type_override_by_name和run_test時會查看此表

Index by type_id

                                                 

                                                           protected bit m_types[uvm_object_wrapper];(type)

Index

Value

sw_driver::type_id

1

new_sw_driver::type_id

1

當調用set_type_override_by_type時會查看此表

2. override

factory同樣也維護著一張關於override 信息的表,表中每一行包括以下內容:

class uvm_factory_override;
  string full_inst_path;
  string orig_type_name;
  string ovrd_type_name;
  bit selected;
  uvm_object_wrapper orig_type;
  uvm_object_wrapper ovrd_type;
  //…
endclass

通過調用factory.set_type_override_by_type(sw_driver::get_type(), new_sw_driver::get_type(), 1);把信息寫入表中

                                                         protected uvm_factory_override m_type_overrides[$];

 

[0]

orig_type

sw_driver::type_id

 

orig_type_name

sw_driver

 

ovrd_type

new_sw_driver::type_id

 

ovrd_type_name

new_sw_driver

 

full_inst_path

“*”

 

selected

0

 

當有多個override的信息時

sw_driver::type_id::set_inst_override(new_sw_driver::get_type(), "env.driver[1]", this);

sw_driver::type_id::set_inst_override(new_sw_driver::get_type(), "env.driver[0]", this);

                                                                  m_inst_override_queues[uvm_object_wrapper]

sw_driver::type_id

orig_type

sw_driver::type_id

sw_driver::type_id

orig_type_name

sw_driver

sw_driver

ovrd_type

new_sw_driver::type_id

new_sw_driver::type_id

ovrd_type_name

new_sw_driver

new_sw_driver

full_inst_path

uvm_test_top.env.driver[1]”

uvm_test_top.env.driver[0]”

selected

0

0

another type_id

orig_type

 

 

 

 

3. create 

    sw_driver::type_id::create(sw_driver",this)

    這句話都做了哪些事情呢?

function sw_driver create(
                   string name, 
                   uvm_component parent, 
                   string contxt="");

   if (contxt == "" && parent != null)
      contxt =parent.get_full_name()

   uvm_factory f = uvm_factory::get();

   uvm_object obj = f.create_component_by_type(type_id, contxt, name, parent)
   
   $cast(create, obj)//obj要和create是父子關係

function uvm_component create_component_by_type(
                       uvm_object_wrapper requested_type,
                       string parent_inst_path="“,
                       string name, 
                       uvm_component parent);
  
   string full_inst_path ;
   concatenate  full_inst_path;
   requested_type = find_override_by_type(requested_type, full_inst_path);//查表看看是否有override信息,若有則返回override的type
   return requested_type.create_component(name, parent);//把override type new出來


function uvm_object_wrapper uvm_factory::find_override_by_type(uvm_object_wrapper requested_type,
                                                               string full_inst_path);

  uvm_object_wrapper override;
  uvm_factory_queue_class qc = null;
  if (m_inst_override_queues.exists(requested_type))
    qc = m_inst_override_queues[requested_type];

  foreach (m_override_info[index]) begin//檢查override type 和original type是否相同
    if ( //index != m_override_info.size()-1 &&
       m_override_info[index].orig_type == requested_type) begin
      uvm_report_error("OVRDLOOP", "Recursive loop detected while finding override.", UVM_NONE);
      if (!m_debug_pass)
        debug_create_by_type (requested_type, full_inst_path);

      return requested_type;
    end
  end

  // inst override; return first match; takes precedence over type overrides
  if (full_inst_path != "" && qc != null)
    for (int index = 0; index < qc.queue.size(); ++index) begin
      if ((qc.queue[index].orig_type == requested_type ||
           (qc.queue[index].orig_type_name != "<unknown>" &&
            qc.queue[index].orig_type_name != "" &&
            qc.queue[index].orig_type_name == requested_type.get_type_name())) &&
          uvm_is_match(qc.queue[index].full_inst_path, full_inst_path)) begin
        m_override_info.push_back(qc.queue[index]);
        if (m_debug_pass) begin
          if (override == null) begin
            override = qc.queue[index].ovrd_type;
            qc.queue[index].selected = 1;
          end
        end
        else begin
          if (qc.queue[index].ovrd_type == requested_type)//沒有發生override
            return requested_type;
          else
            return find_override_by_type(qc.queue[index].ovrd_type,full_inst_path);
            //遞歸調用,比如1 override 2,2 override 3,最終是1 override 3
        end
      end
    end

  // type override - exact match
  foreach (m_type_overrides[index]) begin
    if (m_type_overrides[index].orig_type == requested_type ||
        (m_type_overrides[index].orig_type_name != "<unknown>" &&
         m_type_overrides[index].orig_type_name != "" &&
         requested_type != null &&
         m_type_overrides[index].orig_type_name == requested_type.get_type_name())) begin
      m_override_info.push_back(m_type_overrides[index]);
      if (m_debug_pass) begin
        if (override == null) begin
          override = m_type_overrides[index].ovrd_type;
          m_type_overrides[index].selected = 1;
        end
      end
      else begin
        if (m_type_overrides[index].ovrd_type == requested_type)
          return requested_type;
        else
          return find_override_by_type(m_type_overrides[index].ovrd_type,full_inst_path);
      end
    end
  end

  // type override with wildcard match
  //foreach (m_type_overrides[index])
  //  if (uvm_is_match(index,requested_type.get_type_name())) begin
  //    m_override_info.push_back(m_inst_overrides[index]);
  //    return find_override_by_type(m_type_overrides[index],full_inst_path);
  //  end

  if (m_debug_pass && override != null)
    if (override == requested_type)
      return requested_type;
    else
      return find_override_by_type(override,full_inst_path);

  return requested_type;

endfunction
function uvm_component create_component(
                       string name,
                       uvm_component parent);
  T obj;
  obj = new(name, parent);
  return obj;
endfunction

猜你喜欢

转载自blog.csdn.net/lbt_dvshare/article/details/84819881
今日推荐