芯有所想

精益求精

OVM Cookbook中Factory原理分析总结

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

几个重要的概念需要强调一下:

  1. 单例模式实现的重点:
    1. 将构造函数申明为私有成员函数,防止外部调用构造函数来创建对象
    2. 申明一个类型为本身的静态对象句柄,通过静态函数来创建唯一的一个对象,并将其赋值给此对象句柄。此对象句柄就可以作为访问此单例的一个窗口,也可以用静态函数返回值来访问此单例的对象句柄。
  2. 工厂中可以互相overide的类型必须来自于同一个基类。
    1. 由于工厂中保存的是对象的关联数组,在有些编程语言中也叫做字典(python中好像就这么称呼),此关联数组的关键字(key)是对象句柄。而关联数组要求关键字必须是同一个类型,所以overrige的类型必须从属于同一个基类,以保证他们是同一个类型。
    2. 对每一个类,都生成一个wrapper类,此wrapper类也是一个单例,其对象被静态创建,这个对象一旦被创建,其对象句柄就是唯一的(因为只有一个对象实例)。因此很容易定位此对象句柄,从而通过这个句柄来访问关联数组。
  3. 静态函数,静态变量
    1. 静态函数和静态变量不会和具体的对象实例相关联,是在运行时的初始化阶段被创建的,某一种类型只有唯一的一套。因此可以通过类型修饰符”::”访问,而非静态函数和变量是不能用类型修饰符进行访问的。比如OVM Cookbook中实例04-07中: 将 h = family_base::type_id::create();语句换成如下语句: h = family_base::type_id::create_object(); 就会报错,因为create_object()并不是静态函数。不能通过类型修饰符访问。(使用create_object创建对象是不能实现类型重载的,在这里只是用来演示用)
    2. 静态函数是静态创建的,那么他也只能访问类中的静态变量和静态函数,因为此时其他变量并没有被创建。
  4. OVM除了提供以对象句柄作为关键字的关联数组来实现工厂,同时也提供了以字符串作为关键字的关联数组来实现工厂。
    1. +OVM_TESTNAME=”testcase1” 这种命令行参数中,字符串工厂比较实用,仅此而已
    2. 字符串工厂实现更简单,不需要引入wrapper类。直接通过factory.create_component_by_name()函数来创建对象,返回类型必须通过向下转型(downcast)到实际的具体类型。
    3. 字符串工厂并没有类型检查,因此,没有对象句柄方式安全。
  5. wrapper的设计思想
    1. wrapper#(T)是单例的,因此,外部不能调用其构造函数,只能通过get_type()来得到其唯一的一个静态对象。
    2. get_type()除了用来生成wrapper类的唯一对象,同时还将自身注册到factory工厂中的关联数组中,注册也就是给关联数组增加一个元素,其关键字就是此wrapper#(T)的唯一静态对象的句柄。
    3. wrapper#(T)必须提供一个函数来生成类型T的对象,此函数就是create_object(), 类型T的对象实际中可能有多个,因此create_object()不同的调用将返回不同的类型T的对象,此函数不需要是静态的,此函数仅仅被工厂中的关联数组的值(关联数组的值就是具体的对象句柄)来调用。
    4. wrapper#(T)必须提供一个静态函数,通过类型方式进行调用,也就是create()函数。wrapper中的静态create()函数将通过调用工厂中的create函数来创建对象。