Setting data members for factory-created objects
Posted by Avinash Agrawal on 11th October 2010
Avinash Agrawal, Corporate Applications, Synopsys
One question asked by verification engineers is that given that we are using the VMM factory, how do we assign the data members of VMM class factory service while calling the create_instance method ?
For example, the create_instance() method of class factory service always calls the class constructor with default arguments. Therefore, it would appear that extra arguments cannot be passed to the class instance class. i.e., there is no way to pass additional arguments for class members with the following statements: tr = ahb_trans::create_instance(this, "Ahb_Tr0", `__FILE__, `__LINE__); The answer is that while you cannot use the create_instance() function to initialize ? data members, you can use any of the following methods to deal with this assignment:1. By using virtual function/task set_* in the base class and derived class, and the arguments are passed from the arguments list of set_* function/task. But there is a limitation with this as the set_* function/task arguments for the base class and the derived class must be the same. 2. By using vmm_opts::set_* and vmm_opts::get_* combination to set the value of properties of class. Examples: 1. By using set_* to pass arguments as described in point 1: //////////////////// //Source code //////////////////// `define VMM_12 program P; `include "vmm.sv" // Define base class class ahb_trans extends vmm_data; `vmm_typename(ahb_trans00) rand int addr; static vmm_log log = new("ahb_trans", "object"); `vmm_data_member_begin(ahb_trans) `vmm_data_member_scalar(addr, DO_ALL) `vmm_data_member_end(ahb_trans) virtual function void set_data(int addr=0, int data=0); // <-- Two arguments this.addr = addr; endfunction virtual function void display_data(); `vmm_note(log, $psprintf("ahb_trans.addr=='h%0h", this.addr)); endfunction `vmm_class_factory(ahb_trans) endclass // Define derived class class my_ahb_trans extends ahb_trans; `vmm_typename(my_ahb_trans) rand int data; static vmm_log log = new("my_ahb_trans", "object"); `vmm_data_member_begin(my_ahb_trans) `vmm_data_member_scalar(data, DO_ALL) `vmm_data_member_end(my_ahb_trans) virtual function void set_data(int addr=0, int data=0); // <-- Two arguments this.addr = addr; this.data = data; endfunction virtual function void display_data(); `vmm_note(log, $psprintf("my_ahb_trans.addr=='h%0h, my_ahb_trans.data=='h%0h", this.addr, this.data)); endfunction `vmm_class_factory(my_ahb_trans) endclass class env extends vmm_env; ahb_trans tr; function new; super.new("ENV"); endfunction; function void build; super.build; ahb_trans::override_with_new("@%*", my_ahb_trans::this_type, log, `__FILE__, `__LINE__); tr = ahb_trans::create_instance(this, "Ahb_Tr0", `__FILE__, `__LINE__); if(!(tr.get_typename == "class P.my_ahb_trans")) `vmm_error(log,"ERROR"); tr.set_data(32'h5555_5555, 32'haaaa_aaaa); // <-- Call set_* after create_instance tr.display_data(); endfunction endclass initial begin env env = new(); env.run; end endprogram //////////////////// //Simulation Result //////////////////// Normal[NOTE] on my_ahb_trans(object) at 0: my_ahb_trans.addr=='h55555555, my_ahb_trans.data=='haaaaaaaa Simulation PASSED on /./ (/./) at 0 (0 warnings, 0 demoted errors & 0 demoted warnings) 2. By using vmm_opts::set_* and vmm_opts::get_* combination as described in point 2: //////////////////// //Source code //////////////////// `define VMM_12 program P; `include "vmm.sv" // Define base class class ahb_trans extends vmm_data; `vmm_typename(ahb_trans00) rand int addr; static vmm_log log = new("ahb_trans", "object"); `vmm_data_member_begin(ahb_trans) `vmm_data_member_scalar(addr, DO_ALL) `vmm_data_member_end(ahb_trans) virtual function void set_data(); this.addr = vmm_opts::get_int ("ADDR", 0, "Value set for addr"); endfunction virtual function void display_data(); //<-- no arguments passed, so there is no limitation on number of arguments `vmm_note(log, $psprintf("ahb_trans.addr=='h%0h", this.addr)); endfunction `vmm_class_factory(ahb_trans) endclass // Define derived class class my_ahb_trans extends ahb_trans; `vmm_typename(my_ahb_trans) rand int data; static vmm_log log = new("my_ahb_trans", "object"); `vmm_data_member_begin(my_ahb_trans) `vmm_data_member_scalar(data, DO_ALL) `vmm_data_member_end(my_ahb_trans) virtual function void set_data(); //<-- no arguments passed, so there is no limitation on number of arguments this.addr = vmm_opts::get_int ("ADDR", 0, "Value set for addr"); this.data = vmm_opts::get_int ("DATA", 0, "Value set for data"); endfunction virtual function void display_data(); `vmm_note(log, $psprintf("my_ahb_trans.addr=='h%0h, my_ahb_trans.data=='h%0h", this.addr, this.data)); endfunction `vmm_class_factory(my_ahb_trans) endclass class env extends vmm_env; ahb_trans tr; function new; super.new("ENV"); endfunction; function void build; super.build; vmm_opts::set_int("ADDR", 32'h55,null); // <-- Call vmm_opts::set_* vmm_opts::set_int("DATA", 32'haa,null); ahb_trans::override_with_new("@%*", my_ahb_trans::this_type, log, `__FILE__, `__LINE__); tr = ahb_trans::create_instance(this, "Ahb_Tr0", `__FILE__, `__LINE__); if(!(tr.get_typename == "class P.my_ahb_trans")) `vmm_error(log,"ERROR"); tr.set_data(); tr.display_data(); endfunction endclass initial begin env env = new(); env.run; end endprogram //////////////////// //Simulation Result //////////////////// Normal[NOTE] on my_ahb_trans(object) at 0: my_ahb_trans.addr=='h55, my_ahb_trans.data=='haa Simulation PASSED on /./ (/./) at 0 (0 warnings, 0 demoted errors & 0 demoted warnings)
Posted in vmm_log | No Comments »

