宁安找小姐小妹包夜上门服务 ... https://blog.eetop.cn/116762 [收藏] [复制] [分享] [RSS] 【微信:99093588】宁安找小姐上门服务【微信:99093588】宁安找小姐保健按摩服务【微信:99093588】《宁安小姐服务电话》【微信:99093588】《宁安 ...

空间首页 动态 记录 日志 相册 主题 分享 留言板 个人资料

日志

OVM_cookbook 第四章中Factory

已有 622 次阅读| 2013-3-10 19:19 |个人分类:验证SV/OVM/UVM

OVM重要概念之——Factory模式

当你希望改变Testbench结构但又不想改变Testbench代码时,例如想换一个driverFactory模式可以满足你的需求。

.Factory模式提供了一个 不改变testbench代码替换object的方法。Factory保留了一个registered objects列表。当你创建新的对象时,列表被访问。如果已经存在,则返回override object,否则返回registered object

 

想要仔细了解factory机制有点费工夫,(但是想要知道怎样使用还是很容易的).下面的例子展示factory机制:

 

class object_base;
  virtual function void print();
    $display("object_base");
  endfunction
endclass

//----------------------------------------------------------------------
// wrapper_base
//
// Wrapper base for all objects registered with the factory.  Since
// wrappers are parmaeterized, this base class lets us deal with the all
// the paramerized derived classes polymorphically.
//----------------------------------------------------------------------
class wrapper_base;
  virtual function object_base create_object();
    return null;
  endfunction
endclass

//----------------------------------------------------------------------
// factory
//
// Singleton object that contains the core data structure for the
// factory and the methods for accessing the data structure.  The data
// structure is an associative array of overrides indexed by type
// handle.
//----------------------------------------------------------------------
class factory;

  static factory f;
  wrapper_base override_map[wrapper_base];

  local function new();
  endfunction

  static function factory get();
    if(f == null)
      f = new();
    return f;
  endfunction

  function void register(wrapper_base w);
    override_map[w] = w;
  endfunction

  function void set_override(wrapper_base requested_type,
                             wrapper_base override_type);
    override_map[requested_type] = override_type;
  endfunction

  function object_base create(wrapper_base
                              requested_type);
    object_base obj;
    wrapper_base override_type =
      override_map[requested_type];
    bj = override_type.create_object();
    return obj;
  endfunction

endclass

//----------------------------------------------------------------------
// parameterized wrapper
//
// Each specialization of the parameterized wrapper represents a type.
// These objects are singletons so there can never be more than one
// handle for each type.
//
// The constructor, new(), is a private function.  The only way to
// create a new wrapper is by using the get_type() function, the
// constructor cannot be called directly.
//----------------------------------------------------------------------
class wrapper #(type T=object_base) extends wrapper_base;

  typedef wrapper#(T) this_type;

  static this_type type_handle = get_type();

  local function new();
  endfunction

  function object_base create_object();
    T t = new();
    return t;
  endfunction

  static function T create();
    T obj;
    factory f = factory::get();
    assert($cast(obj, f.create(get_type())));
    return obj;
  endfunction

  static function this_type get_type();
    factory f;
    if(type_handle == null) begin
      type_handle = new();
      f = factory::get();
      f.register(type_handle);
    end
    return type_handle;
  endfunction

  static function void set_override(wrapper_base
                                    override_type);
    factory f = factory::get();
    f.set_override(type_handle, override_type);
  endfunction

endclass

//----------------------------------------------------------------------
// family of classes derived from a single base class
//----------------------------------------------------------------------
class family_base extends object_base;

  typedef wrapper#(family_base) type_id;

  virtual function void print();
    $display("family_base");
  endfunction
endclass

class A extends family_base;

  typedef wrapper#(A) type_id;

  virtual function void print();
    $display("A");
  endfunction
endclass

class B extends family_base;

  typedef wrapper#(B) type_id;

  virtual function void print();
    $display("B");
  endfunction
endclass

class C extends family_base;

  typedef wrapper#(C) type_id;

  virtual function void print();
    $display("C");
  endfunction
endclass

//----------------------------------------------------------------------
// env
//
// top-level environment where we execute the example
//----------------------------------------------------------------------
class env;

  factory f;
  family_base h;

  function void run();

    f = factory::get();

    h = family_base::type_id::create();
    h.print();

    family_base::type_id::set_override(B::type_id::get_type());

    h = family_base::type_id::create();
    h.print();

  endfunction

endclass

//----------------------------------------------------------------------
// top
//----------------------------------------------------------------------
module top;

  env e;

  initial begin
    e = new();
    e.run();
  end

endmodule

 

 

 

 

 

引用网上牛人对此例的解释

OVM Cookbook中对OVM中的工厂模式进行了详细的介绍,其中使用了一个toy factory的例子来阐述工厂模式的实现原理,让读者的理解更加深入。
  

几个重要的概念需要强调一下:
  
1.
单例模式实现的重点:
  

·         将构造函数申明为私有成员函数,防止外部调用构造函数来创建对象

 

·         申明一个类型为本身的静态对象句柄,通过静态函数来创建唯一的一个对象,并将其赋值给此对象句柄。此对象句柄就可以作为访问此单例的一个窗口,也可以用静态函数返回值来访问此单例的对象句柄。



2.
工厂中可以互相overide的类型必须来自于同一个基类。
  

·         由于工厂中保存的是对象的关联数组,在有些编程语言中也叫做字典(python中好像就这么称呼),此关联数组的关键字(key)是对象句柄。而关联数组要求关键字必须是同一个类型,所以overrige的类型必须从属于同一个基类,以保证他们是同一个类型。

 

·         对每一个类,都生成一个wrapper类,此wrapper类也是一个单例,其对象被静态创建,这个对象一旦被创建,其对象句柄就是唯一的(因为只有一个对象实例)。因此很容易定位此对象句柄,从而通过这个句柄来访问关联数组。

  


3.
静态函数,静态变量
  

·         静态函数和静态变量不会和具体的对象实例相关联,实在运行时初始化阶段被创建的,某一种类型只有唯一的一套。因此可以通过类型修饰符"::"访问,而非静态函数和变量是不能用类型修饰符进行访问的。比如OVM Cookbook中实例04-07中:

 

h = family_base::type_id::create();语句换成如下语句:

h = family_base::type_id::create_object();
   
就会报错,因为create_object()并不是静态函数。不能通过类型修饰符访问。(使用create_object创建对象是不能实现类型重载的,在这里只是用来演示用)


  

    

·         静态函数是静态创建的,那么他也只能访问类型的静态变量和静态函数,因为其他变量并没有被创建。

  


4. OVM
除了提供以对象句柄作为关键字的关联数组来实现工厂,同时也提供了以字符串作为关键字的关联数组来实现工厂
  

·         +OVM_TESTNAME="testcase1" 这种命令行参数中,字符串工厂比较实用,仅此而已

 

·         字符串工厂实现更简单,不需要引入wrapper类。直接通过factory.create_component_by_name()函数来创建对象,返回类型必须通过向下转型(downcast)来赋值到实际的具体类型。

 

·         字符串工厂并没有类型检查,没有对象句柄方式安全。

  

5  wrapper
的设计思想
  

·         wrapper#(T)是单例的,因此外部不能调用其构造函数,只能通过get_type()来得到其唯一的一个静态对象

·         get_type()除了用来生成wrapper类的唯一对象,同时还将自身注册到factory工厂中的关联数组中,注册也就是给关联数组增加一个元素,其关键字就是此wrapper#(T)的唯一静态对象的句柄。

 

·         wrapper#(T)必须提供一个函数来生成类型T的对象,此函数就是create_object(), 类型T的对象实际中可能有多个,因此create_object()不同的调用将返回不同的类型T的对象,此函数不需要是静态的,此函数仅仅被工厂中的关联数组的值(关联数组的值就是具体的对象句柄)来调用。

 

·         wrapper#(T)必须提供一个静态函数,通过类型方式进行调用,也就是create()函数。wrapper中的静态create()函数将通过调用工厂中的create函数来创建对象。

 

 

 


点赞

评论 (0 个评论)

facelist

您需要登录后才可以评论 登录 | 注册

  • 关注TA
  • 加好友
  • 联系TA
  • 0

    周排名
  • 0

    月排名
  • 0

    总排名
  • 0

    关注
  • 1

    粉丝
  • 3

    好友
  • 0

    获赞
  • 6

    评论
  • 470

    访问数
关闭

站长推荐 上一条 /1 下一条

小黑屋| 关于我们| 联系我们| 在线咨询| 隐私声明| EETOP 创芯网
( 京ICP备:10050787号 京公网安备:11010502037710 )

GMT+8, 2024-4-27 17:15 , Processed in 0.017932 second(s), 7 queries , Gzip On, Redis On.

eetop公众号 创芯大讲堂 创芯人才网
返回顶部