PDA

View Full Version : Factory



ankit1
01-22-2008, 04:32 AM
Hi All,

Can anybody tell me what is factory and what is it's significance?

Regards,

Ankit

dlong
01-22-2008, 06:54 AM
Hi Ankit,

A factory is a common object-oriented "design pattern" that is used to create components of a specified type of component. A member function of the factory actually creates the component but it does so using a handle to a base class. Since a base class handle can be used to point to an object of a derived class, the factory can be "programmed" to create derived class objects. This provides a simple mechanism for writing generic, reusable code.

OVM contains a factory class named "ovm_factory". It is programmed by calling its set_override function for the required class type, e.g.



simple_seq seq_inst; //component handle
...
ovm_factory::set_type_override("simple_seq","read_write_seq");
$cast(seq_inst,ovm_factory::create_component("simple_seq","","seq_inst",this);



This code overrides the type of component created by the factory - the types are specified by strings so they can easily be set at run-time. The call to create_component returns a ovm_component class handle, which will require a cast to the type seq_inst.

Hope that helps.
Regards,
Dave
=================
David Long
Doulos
http://www.doulos.com

hansv
01-22-2008, 07:08 AM
Hello Ankit,

"Factory" in this context refers to an established object-oriented design pattern (or best practice), the "factory pattern". It is a class with facilities for the dynamic creation (i.e. manufacturing) of different objects.

The factory pattern is particularly useful to allow the type of an object to be constructed to be specified at run-time.

Whether this very brief description of the factory pattern is meaningful to you depends on your vocational background. Hence, may I suggest that you look at the following Wikipedia pages (as a start) for more details:

http://en.wikipedia.org/wiki/Design_Patterns
http://en.wikipedia.org/wiki/Abstract_factory_patternThere is also a link in there to a key book on this topic:

Design Patterns: Elements of Reusable Object-Oriented Software, by Gamma, Helm, Johnson and Vlissides - Addison Wesley Publishing

Regards

ahan
05-04-2008, 01:16 AM
HI All,
I had read the example of factory under ovm-1.0.1.


//use the factory to generate a package
obj = create_object("packet", "p");

//make sure it is a packet
$cast(p, obj);




//use the factory to create the generator
cmp = create_component("gen", "gen1");
$cast(gen1, cmp);




initial begin
ovm_factory::set_inst_override("ovm_test_top.gen1", "gen", "mygen");
ovm_factory::set_type_override("packet", "mypacket");
ovm_factory::print_all_overrides(1);
run_test("env");
end


It's no easy to go through the all design pattern book for verification engineer come from hardware just for one concept of factory.
I only get the basic idea of that it provide a general interface for generating object.
I am curious with how it works/realize in systemverilog.
Does anyone have a minimum case to show how it realize the function to overide the instance and type?Or explain how it work internally line by line?
Thank you in advance!

umery
05-05-2008, 06:41 AM
Hello Ahan,

I agree with you that DV engineers may not have the time to learn various design patterns and that is exactly why OVM has these patterns implemented for you so you need to learn how to use them, not necessarily how to implement them yourself.

A factory is a static object in SystemVerilog that does two things:

1) Knows how to allocate a structural component (derived from ovm_component) or a dynamic object (derived from ovm_transaction, ovm_sequence_item, etc.)
create_object(type_name, name) returns an ovm_object of type_name which has to be downcasted using $cast to the user specified type. create_component() returns an ovm_component and used in a similar way. The user has to program this knowledge into the factory. In ovm, the `ovm_object_utils and `ovm_component_utils macros fill in the method to tell the factory how to create this object or component.

Lets take a look at a simple example

Step 1 - Register an object with the factory

class my_driver extends ovm_driver;
`ovm_component_utils (my_driver) //This macro expands into code that tells the factory how to allocate my_driver

virtual task get_and_drive();
..
endfunction
function new(string name, ovm_component parent);
super.new(name, parent);
endfunction
endclass

Step 2 - Another class can now use the factory to allocate my_driver


class my_agent extends ovm_agent;
`ovm_component_utils (my_agent)
my_driver drv;
function void build();
$cast(drv, create_component("my_driver", "drv"));
endfunction
function new(string name, ovm_component parent);
super.new(name, parent);
endfunction
endclass

2) Supports type/instance overrides so the user can change behavior of an object (define new virtual functions, add properties, define additional constraints, etc) from a test layer without the need to rebuild the hierarchy. This is a very important requirement for verification that greatly reduces the time to develop specific tests using a single verification environment as well as promote Verification IP reuse between multiple projects.

set_type_override() and set_inst_override() provide an api into the factory to change the object type returned by create_object() or create_component() functions.

Step 3 - override my_driver in test


class my_bad_driver extends my_driver;
`ovm_component_utils (my_bad_driver) //This macro expands into code that tells the factory how to allocate my_driver

virtual task get_and_drive();
//do something different first and use parent's implementation if needed
super.get_and_drive();
endfunction
function new(string name, ovm_component parent);
super.new(name, parent);
endfunction
endclass

and the test ...


class my_test extends ovm_test
`ovm_component_utils (my_test) //This macro expands into code that tells the factory how to allocate my_driver
my_agent agent0;
my_agent agent1;
function void build();
set_type_override ("my_driver", "my_bad_driver");
//ALL instances of my_driver when created using factory will get my_bad_driver

set_inst_override ("agent0.*", "my_driver", "my_bad_driver");
//ALL instances of my_driver instantiated with "agent0" when created using factory will get my_bad_driver

$cast(agent0, create_component("my_agent", "agent0"));
$cast(agent1, create_component("my_agent", "agent1"));
endfunction
function new(string name, ovm_component parent);
super.new(name, parent);
endfunction
endclass

ahan
05-08-2008, 10:48 PM
Hi umery,
Thanks for your professional guide!
You always give me good tips on OVM:)
Thank you very much!

des00
11-15-2008, 05:56 AM
Hi all!!!

Could you explain me why this simple code



module tb ;

`include "ovm_macros.svh"
import ovm_pkg::*;

class base extends ovm_transaction;

`ovm_object_utils(base)
function new (string name = "");
super.new(name);
endfunction

rand int addr;
endclass

class child extends base;

`ovm_object_utils(child)
function new (string name = "");
super.new(name);
endfunction

bit [7:0] addr;
endclass

class comp extends ovm_component;
`ovm_component_utils(comp)
function new (string name = "", ovm_component parent = null);
super.new(name, parent);
endfunction

task run ();
base b;
b = base::type_id::create("b", this);
$display("this is %0s %0d", b.get_type_name(), $size(b.addr));
endtask
endclass

comp cmp;

initial begin : main

factory.set_type_override_by_type(base::get_type() , child::get_type());
cmp = comp::type_id::create("comp", null);

cmp.run();
$stop;
end

endmodule

yields the following result # this is child 32 ?

As I understand result should be # this is child 8 ?

Thank you!!!

kurts
11-16-2008, 12:48 AM
Data members of a class are not polymorphic. You can't say "virtual" with a data member.

Your code does indeed create a child object in the factory, but then you assign that object to a base handle b.

get_type_name() is a virtual function, so calling this results in the polymorphic result "child". However, when accessing the data member addr, it uses the base class version (because that is the only version of addr that a base handle knows about).

This kind of situation is exactly why it is always a bad idea to override data members in extended classes.

-Kurt

vivekm
03-19-2010, 02:55 AM
Hi Friends,

I have this code for my upper level env in which I want to create four instances of my lower level env:


class env_quad extends ovm_env;

protected int unsigned num_GTs = 4;

`ovm_component_utils_begin(env_quad)
`ovm_field_int(num_GTs, OVM_ALL_ON)
`ovm_component_utils_end

env inst_env[];
quad_sequencer quad_sqr;
quad_driver quad_drv;
.
.
.//new() function here

function void build();
string inst_name;
super.build();
quad_sqr = gt_sequencer::type_id::create("quad_sqr", this);
quad_drv = driver_quad::type_id::create("quad_drv", this);

inst_env = new[num_GTs];

for(int i = 0; i < num_GTs; i++) begin
$sformat(inst_name, "inst_env[%0d]", i);
inst_env[i] = env::type_id::create(inst_name, this);
$display("env_quad: build(): Created env inst %0d = %s\n", i, inst_name);
end

endfunction: build

function void connect();
super.connect();
quad_drv.seq_item_port.connect(quad_sqr.seq_item_e xport);

for(int j = 0; j < num_GTs; j++) begin
quad_drv.ovm_analysis_port_quad_drv.connect(inst_e nv[j].env_analysis_export);
end

endfunction: connect

endclass : env_quad

This code compiles well, but when I simulate it, it gives me this error:

env_quad: build(): Created env inst 0 = inst_env[0]

Error-[STASKE_NEAFFS] Insufficient number of arguments
/home/vivekm/ovm-2.0.2/src/base/ovm_extern_report_server.svh, 109
Number of arguments (1) passed to substitute format specifiers in the string
which are less than number of format specifiers.
Please pass number of arguments equal to number of format specifiers.

I do not see this error if I make num_GTs = 1 and the code executes fine for one instance of env. Is this a problem with factory or I am missing something here?

Please help!