| // |
| //----------------------------------------------------------------------------- |
| // Copyright 2007-2011 Mentor Graphics Corporation |
| // Copyright 2007-2011 Cadence Design Systems, Inc. |
| // Copyright 2010 Synopsys, Inc. |
| // All Rights Reserved Worldwide |
| // |
| // Licensed under the Apache License, Version 2.0 (the |
| // "License"); you may not use this file except in |
| // compliance with the License. You may obtain a copy of |
| // the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in |
| // writing, software distributed under the License is |
| // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR |
| // CONDITIONS OF ANY KIND, either express or implied. See |
| // the License for the specific language governing |
| // permissions and limitations under the License. |
| //----------------------------------------------------------------------------- |
| |
| |
| typedef class uvm_report_object; |
| typedef class uvm_object_wrapper; |
| typedef class uvm_objection; |
| typedef class uvm_component; |
| |
| |
| // internal |
| typedef class uvm_status_container; |
| |
| //------------------------------------------------------------------------------ |
| // |
| // CLASS: uvm_object |
| // |
| // The uvm_object class is the base class for all UVM data and hierarchical |
| // classes. Its primary role is to define a set of methods for such common |
| // operations as <create>, <copy>, <compare>, <print>, and <record>. Classes |
| // deriving from uvm_object must implement the pure virtual methods such as |
| // <create> and <get_type_name>. |
| // |
| //------------------------------------------------------------------------------ |
| |
| virtual class uvm_object extends uvm_void; |
| |
| |
| // Function: new |
| // |
| // Creates a new uvm_object with the given instance ~name~. If ~name~ is not |
| // supplied, the object is unnamed. |
| |
| extern function new (string name=""); |
| |
| |
| // Group: Seeding |
| |
| // Variable: use_uvm_seeding |
| // |
| // This bit enables or disables the UVM seeding mechanism. It globally affects |
| // the operation of the reseed method. |
| // |
| // When enabled, UVM-based objects are seeded based on their type and full |
| // hierarchical name rather than allocation order. This improves random |
| // stability for objects whose instance names are unique across each type. |
| // The <uvm_component> class is an example of a type that has a unique |
| // instance name. |
| |
| static bit use_uvm_seeding = 1; |
| |
| |
| // Function: reseed |
| // |
| // Calls ~srandom~ on the object to reseed the object using the UVM seeding |
| // mechanism, which sets the seed based on type name and instance name instead |
| // of based on instance position in a thread. |
| // |
| // If the <use_uvm_seeding> static variable is set to 0, then reseed() does |
| // not perform any function. |
| |
| extern function void reseed (); |
| |
| |
| // Group: Identification |
| |
| // Function: set_name |
| // |
| // Sets the instance name of this object, overwriting any previously |
| // given name. |
| |
| extern virtual function void set_name (string name); |
| |
| |
| // Function: get_name |
| // |
| // Returns the name of the object, as provided by the ~name~ argument in the |
| // <new> constructor or <set_name> method. |
| |
| extern virtual function string get_name (); |
| |
| |
| // Function: get_full_name |
| // |
| // Returns the full hierarchical name of this object. The default |
| // implementation is the same as <get_name>, as uvm_objects do not inherently |
| // possess hierarchy. |
| // |
| // Objects possessing hierarchy, such as <uvm_components>, override the default |
| // implementation. Other objects might be associated with component hierarchy |
| // but are not themselves components. For example, <uvm_sequence #(REQ,RSP)> |
| // classes are typically associated with a <uvm_sequencer #(REQ,RSP)>. In this |
| // case, it is useful to override get_full_name to return the sequencer's |
| // full name concatenated with the sequence's name. This provides the sequence |
| // a full context, which is useful when debugging. |
| |
| extern virtual function string get_full_name (); |
| |
| |
| // Function: get_inst_id |
| // |
| // Returns the object's unique, numeric instance identifier. |
| |
| extern virtual function int get_inst_id (); |
| |
| |
| // Function: get_inst_count |
| // |
| // Returns the current value of the instance counter, which represents the |
| // total number of uvm_object-based objects that have been allocated in |
| // simulation. The instance counter is used to form a unique numeric instance |
| // identifier. |
| |
| extern static function int get_inst_count(); |
| |
| |
| // Function: get_type |
| // |
| // Returns the type-proxy (wrapper) for this object. The <uvm_factory>'s |
| // type-based override and creation methods take arguments of |
| // <uvm_object_wrapper>. This method, if implemented, can be used as convenient |
| // means of supplying those arguments. |
| // |
| // The default implementation of this method produces an error and returns |
| // null. To enable use of this method, a user's subtype must implement a |
| // version that returns the subtype's wrapper. |
| // |
| // For example: |
| // |
| //| class cmd extends uvm_object; |
| //| typedef uvm_object_registry #(cmd) type_id; |
| //| static function type_id get_type(); |
| //| return type_id::get(); |
| //| endfunction |
| //| endclass |
| // |
| // Then, to use: |
| // |
| //| factory.set_type_override(cmd::get_type(),subcmd::get_type()); |
| // |
| // This function is implemented by the `uvm_*_utils macros, if employed. |
| |
| extern static function uvm_object_wrapper get_type (); |
| |
| |
| // Function: get_object_type |
| // |
| // Returns the type-proxy (wrapper) for this object. The <uvm_factory>'s |
| // type-based override and creation methods take arguments of |
| // <uvm_object_wrapper>. This method, if implemented, can be used as convenient |
| // means of supplying those arguments. This method is the same as the static |
| // <get_type> method, but uses an already allocated object to determine |
| // the type-proxy to access (instead of using the static object). |
| // |
| // The default implementation of this method does a factory lookup of the |
| // proxy using the return value from <get_type_name>. If the type returned |
| // by <get_type_name> is not registered with the factory, then a null |
| // handle is returned. |
| // |
| // For example: |
| // |
| //| class cmd extends uvm_object; |
| //| typedef uvm_object_registry #(cmd) type_id; |
| //| static function type_id get_type(); |
| //| return type_id::get(); |
| //| endfunction |
| //| virtual function type_id get_object_type(); |
| //| return type_id::get(); |
| //| endfunction |
| //| endclass |
| // |
| // This function is implemented by the `uvm_*_utils macros, if employed. |
| |
| extern virtual function uvm_object_wrapper get_object_type (); |
| |
| |
| // Function: get_type_name |
| // |
| // This function returns the type name of the object, which is typically the |
| // type identifier enclosed in quotes. It is used for various debugging |
| // functions in the library, and it is used by the factory for creating |
| // objects. |
| // |
| // This function must be defined in every derived class. |
| // |
| // A typical implementation is as follows: |
| // |
| //| class mytype extends uvm_object; |
| //| ... |
| //| const static string type_name = "mytype"; |
| //| |
| //| virtual function string get_type_name(); |
| //| return type_name; |
| //| endfunction |
| // |
| // We define the ~type_name~ static variable to enable access to the type name |
| // without need of an object of the class, i.e., to enable access via the |
| // scope operator, ~mytype::type_name~. |
| |
| virtual function string get_type_name (); return "<unknown>"; endfunction |
| |
| |
| // Group: Creation |
| |
| // Function: create |
| // |
| // The create method allocates a new object of the same type as this object |
| // and returns it via a base uvm_object handle. Every class deriving from |
| // uvm_object, directly or indirectly, must implement the create method. |
| // |
| // A typical implementation is as follows: |
| // |
| //| class mytype extends uvm_object; |
| //| ... |
| //| virtual function uvm_object create(string name=""); |
| //| mytype t = new(name); |
| //| return t; |
| //| endfunction |
| |
| virtual function uvm_object create (string name=""); return null; endfunction |
| |
| |
| // Function: clone |
| // |
| // The clone method creates and returns an exact copy of this object. |
| // |
| // The default implementation calls <create> followed by <copy>. As clone is |
| // virtual, derived classes may override this implementation if desired. |
| |
| extern virtual function uvm_object clone (); |
| |
| |
| // Group: Printing |
| |
| // Function: print |
| // |
| // The print method deep-prints this object's properties in a format and |
| // manner governed by the given ~printer~ argument; if the ~printer~ argument |
| // is not provided, the global <uvm_default_printer> is used. See |
| // <uvm_printer> for more information on printer output formatting. See also |
| // <uvm_line_printer>, <uvm_tree_printer>, and <uvm_table_printer> for details |
| // on the pre-defined printer "policies," or formatters, provided by the UVM. |
| // |
| // The ~print~ method is not virtual and must not be overloaded. To include |
| // custom information in the ~print~ and ~sprint~ operations, derived classes |
| // must override the <do_print> method and use the provided printer policy |
| // class to format the output. |
| |
| extern function void print (uvm_printer printer=null); |
| |
| |
| // Function: sprint |
| // |
| // The ~sprint~ method works just like the <print> method, except the output |
| // is returned in a string rather than displayed. |
| // |
| // The ~sprint~ method is not virtual and must not be overloaded. To include |
| // additional fields in the ~print~ and ~sprint~ operation, derived classes |
| // must override the <do_print> method and use the provided printer policy |
| // class to format the output. The printer policy will manage all string |
| // concatenations and provide the string to ~sprint~ to return to the caller. |
| |
| extern function string sprint (uvm_printer printer=null); |
| |
| |
| // Function: do_print |
| // |
| // The ~do_print~ method is the user-definable hook called by <print> and |
| // <sprint> that allows users to customize what gets printed or sprinted |
| // beyond the field information provided by the `uvm_field_* macros, |
| // <Utility and Field Macros for Components and Objects>. |
| // |
| // The ~printer~ argument is the policy object that governs the format and |
| // content of the output. To ensure correct <print> and <sprint> operation, |
| // and to ensure a consistent output format, the ~printer~ must be used |
| // by all <do_print> implementations. That is, instead of using ~$display~ or |
| // string concatenations directly, a ~do_print~ implementation must call |
| // through the ~printer's~ API to add information to be printed or sprinted. |
| // |
| // An example implementation of ~do_print~ is as follows: |
| // |
| //| class mytype extends uvm_object; |
| //| data_obj data; |
| //| int f1; |
| //| virtual function void do_print (uvm_printer printer); |
| //| super.do_print(printer); |
| //| printer.print_int("f1", f1, $bits(f1), DEC); |
| //| printer.print_object("data", data); |
| //| endfunction |
| // |
| // Then, to print and sprint the object, you could write: |
| // |
| //| mytype t = new; |
| //| t.print(); |
| //| uvm_report_info("Received",t.sprint()); |
| // |
| // See <uvm_printer> for information about the printer API. |
| |
| extern virtual function void do_print (uvm_printer printer); |
| |
| |
| // Function: convert2string |
| // |
| // This virtual function is a user-definable hook, called directly by the |
| // user, that allows users to provide object information in the form of |
| // a string. Unlike <sprint>, there is no requirement to use an <uvm_printer> |
| // policy object. As such, the format and content of the output is fully |
| // customizable, which may be suitable for applications not requiring the |
| // consistent formatting offered by the <print>/<sprint>/<do_print> |
| // API. |
| // |
| // Fields declared in <Utility Macros> macros (`uvm_field_*), if used, will |
| // not automatically appear in calls to convert2string. |
| // |
| // An example implementation of convert2string follows. |
| // |
| //| class base extends uvm_object; |
| //| string field = "foo"; |
| //| virtual function string convert2string(); |
| //| convert2string = {"base_field=",field}; |
| //| endfunction |
| //| endclass |
| //| |
| //| class obj2 extends uvm_object; |
| //| string field = "bar"; |
| //| virtual function string convert2string(); |
| //| convert2string = {"child_field=",field}; |
| //| endfunction |
| //| endclass |
| //| |
| //| class obj extends base; |
| //| int addr = 'h123; |
| //| int data = 'h456; |
| //| bit write = 1; |
| //| obj2 child = new; |
| //| virtual function string convert2string(); |
| //| convert2string = {super.convert2string(), |
| //| $sformatf(" write=%0d addr=%8h data=%8h ",write,addr,data), |
| //| child.convert2string()}; |
| //| endfunction |
| //| endclass |
| // |
| // Then, to display an object, you could write: |
| // |
| //| obj o = new; |
| //| uvm_report_info("BusMaster",{"Sending:\n ",o.convert2string()}); |
| // |
| // The output will look similar to: |
| // |
| //| UVM_INFO @ 0: reporter [BusMaster] Sending: |
| //| base_field=foo write=1 addr=00000123 data=00000456 child_field=bar |
| |
| |
| extern virtual function string convert2string(); |
| |
| |
| // Group: Recording |
| |
| // Function: record |
| // |
| // The record method deep-records this object's properties according to an |
| // optional ~recorder~ policy. The method is not virtual and must not be |
| // overloaded. To include additional fields in the record operation, derived |
| // classes should override the <do_record> method. |
| // |
| // The optional ~recorder~ argument specifies the recording policy, which |
| // governs how recording takes place. If a recorder policy is not provided |
| // explicitly, then the global <uvm_default_recorder> policy is used. See |
| // uvm_recorder for information. |
| // |
| // A simulator's recording mechanism is vendor-specific. By providing access |
| // via a common interface, the uvm_recorder policy provides vendor-independent |
| // access to a simulator's recording capabilities. |
| |
| extern function void record (uvm_recorder recorder=null); |
| |
| |
| // Function: do_record |
| // |
| // The do_record method is the user-definable hook called by the <record> |
| // method. A derived class should override this method to include its fields |
| // in a record operation. |
| // |
| // The ~recorder~ argument is policy object for recording this object. A |
| // do_record implementation should call the appropriate recorder methods for |
| // each of its fields. Vendor-specific recording implementations are |
| // encapsulated in the ~recorder~ policy, thereby insulating user-code from |
| // vendor-specific behavior. See <uvm_recorder> for more information. |
| // |
| // A typical implementation is as follows: |
| // |
| //| class mytype extends uvm_object; |
| //| data_obj data; |
| //| int f1; |
| //| function void do_record (uvm_recorder recorder); |
| //| recorder.record_field_int("f1", f1, $bits(f1), DEC); |
| //| recorder.record_object("data", data); |
| //| endfunction |
| |
| extern virtual function void do_record (uvm_recorder recorder); |
| |
| |
| // Group: Copying |
| |
| // Function: copy |
| // |
| // The copy makes this object a copy of the specified object. |
| // |
| // The copy method is not virtual and should not be overloaded in derived |
| // classes. To copy the fields of a derived class, that class should override |
| // the <do_copy> method. |
| |
| extern function void copy (uvm_object rhs); |
| |
| |
| // Function: do_copy |
| // |
| // The do_copy method is the user-definable hook called by the copy method. |
| // A derived class should override this method to include its fields in a copy |
| // operation. |
| // |
| // A typical implementation is as follows: |
| // |
| //| class mytype extends uvm_object; |
| //| ... |
| //| int f1; |
| //| function void do_copy (uvm_object rhs); |
| //| mytype rhs_; |
| //| super.do_copy(rhs); |
| //| $cast(rhs_,rhs); |
| //| field_1 = rhs_.field_1; |
| //| endfunction |
| // |
| // The implementation must call ~super.do_copy~, and it must $cast the rhs |
| // argument to the derived type before copying. |
| |
| extern virtual function void do_copy (uvm_object rhs); |
| |
| |
| // Group: Comparing |
| |
| // Function: compare |
| // |
| // Deep compares members of this data object with those of the object provided |
| // in the ~rhs~ (right-hand side) argument, returning 1 on a match, 0 othewise. |
| // |
| // The compare method is not virtual and should not be overloaded in derived |
| // classes. To compare the fields of a derived class, that class should |
| // override the <do_compare> method. |
| // |
| // The optional ~comparer~ argument specifies the comparison policy. It allows |
| // you to control some aspects of the comparison operation. It also stores the |
| // results of the comparison, such as field-by-field miscompare information |
| // and the total number of miscompares. If a compare policy is not provided, |
| // then the global ~uvm_default_comparer~ policy is used. See <uvm_comparer> |
| // for more information. |
| |
| extern function bit compare (uvm_object rhs, uvm_comparer comparer=null); |
| |
| |
| // Function: do_compare |
| // |
| // The do_compare method is the user-definable hook called by the <compare> |
| // method. A derived class should override this method to include its fields |
| // in a compare operation. It should return 1 if the comparison succeeds, 0 |
| // otherwise. |
| // |
| // A typical implementation is as follows: |
| // |
| //| class mytype extends uvm_object; |
| //| ... |
| //| int f1; |
| //| virtual function bit do_compare (uvm_object rhs,uvm_comparer comparer); |
| //| mytype rhs_; |
| //| do_compare = super.do_compare(rhs,comparer); |
| //| $cast(rhs_,rhs); |
| //| do_compare &= comparer.compare_field_int("f1", f1, rhs_.f1); |
| //| endfunction |
| // |
| // A derived class implementation must call ~super.do_compare()~ to ensure its |
| // base class' properties, if any, are included in the comparison. Also, the |
| // rhs argument is provided as a generic uvm_object. Thus, you must ~$cast~ it |
| // to the type of this object before comparing. |
| // |
| // The actual comparison should be implemented using the uvm_comparer object |
| // rather than direct field-by-field comparison. This enables users of your |
| // class to customize how comparisons are performed and how much miscompare |
| // information is collected. See uvm_comparer for more details. |
| |
| extern virtual function bit do_compare (uvm_object rhs, |
| uvm_comparer comparer); |
| |
| // Group: Packing |
| |
| // Function: pack |
| |
| extern function int pack (ref bit bitstream[], |
| input uvm_packer packer=null); |
| |
| // Function: pack_bytes |
| |
| extern function int pack_bytes (ref byte unsigned bytestream[], |
| input uvm_packer packer=null); |
| |
| // Function: pack_ints |
| // |
| // The pack methods bitwise-concatenate this object's properties into an array |
| // of bits, bytes, or ints. The methods are not virtual and must not be |
| // overloaded. To include additional fields in the pack operation, derived |
| // classes should override the <do_pack> method. |
| // |
| // The optional ~packer~ argument specifies the packing policy, which governs |
| // the packing operation. If a packer policy is not provided, the global |
| // <uvm_default_packer> policy is used. See <uvm_packer> for more information. |
| // |
| // The return value is the total number of bits packed into the given array. |
| // Use the array's built-in ~size~ method to get the number of bytes or ints |
| // consumed during the packing process. |
| |
| extern function int pack_ints (ref int unsigned intstream[], |
| input uvm_packer packer=null); |
| |
| |
| // Function: do_pack |
| // |
| // The do_pack method is the user-definable hook called by the <pack> methods. |
| // A derived class should override this method to include its fields in a pack |
| // operation. |
| // |
| // The ~packer~ argument is the policy object for packing. The policy object |
| // should be used to pack objects. |
| // |
| // A typical example of an object packing itself is as follows |
| // |
| //| class mysubtype extends mysupertype; |
| //| ... |
| //| shortint myshort; |
| //| obj_type myobj; |
| //| byte myarray[]; |
| //| ... |
| //| function void do_pack (uvm_packer packer); |
| //| super.do_pack(packer); // pack mysupertype properties |
| //| packer.pack_field_int(myarray.size(), 32); |
| //| foreach (myarray) |
| //| packer.pack_field_int(myarray[index], 8); |
| //| packer.pack_field_int(myshort, $bits(myshort)); |
| //| packer.pack_object(myobj); |
| //| endfunction |
| // |
| // The implementation must call ~super.do_pack~ so that base class properties |
| // are packed as well. |
| // |
| // If your object contains dynamic data (object, string, queue, dynamic array, |
| // or associative array), and you intend to unpack into an equivalent data |
| // structure when unpacking, you must include meta-information about the |
| // dynamic data when packing as follows. |
| // |
| // - For queues, dynamic arrays, or associative arrays, pack the number of |
| // elements in the array in the 32 bits immediately before packing |
| // individual elements, as shown above. |
| // |
| // - For string data types, append a zero byte after packing the string |
| // contents. |
| // |
| // - For objects, pack 4 bits immediately before packing the object. For null |
| // objects, pack 4'b0000. For non-null objects, pack 4'b0001. |
| // |
| // When the `uvm_field_* macros are used, |
| // <Utility and Field Macros for Components and Objects>, |
| // the above meta information is included provided the <uvm_packer::use_metadata> |
| // variable is set for the packer. |
| // |
| // Packing order does not need to match declaration order. However, unpacking |
| // order must match packing order. |
| |
| extern virtual function void do_pack (uvm_packer packer); |
| |
| |
| // Group: Unpacking |
| |
| // Function: unpack |
| |
| extern function int unpack (ref bit bitstream[], |
| input uvm_packer packer=null); |
| |
| // Function: unpack_bytes |
| |
| extern function int unpack_bytes (ref byte unsigned bytestream[], |
| input uvm_packer packer=null); |
| |
| // Function: unpack_ints |
| // |
| // The unpack methods extract property values from an array of bits, bytes, or |
| // ints. The method of unpacking ~must~ exactly correspond to the method of |
| // packing. This is assured if (a) the same ~packer~ policy is used to pack |
| // and unpack, and (b) the order of unpacking is the same as the order of |
| // packing used to create the input array. |
| // |
| // The unpack methods are fixed (non-virtual) entry points that are directly |
| // callable by the user. To include additional fields in the <unpack> |
| // operation, derived classes should override the <do_unpack> method. |
| // |
| // The optional ~packer~ argument specifies the packing policy, which governs |
| // both the pack and unpack operation. If a packer policy is not provided, |
| // then the global ~uvm_default_packer~ policy is used. See uvm_packer for |
| // more information. |
| // |
| // The return value is the actual number of bits unpacked from the given array. |
| |
| extern function int unpack_ints (ref int unsigned intstream[], |
| input uvm_packer packer=null); |
| |
| |
| // Function: do_unpack |
| // |
| // The do_unpack method is the user-definable hook called by the <unpack> |
| // method. A derived class should override this method to include its fields |
| // in an unpack operation. |
| // |
| // The ~packer~ argument is the policy object for both packing and unpacking. |
| // It must be the same packer used to pack the object into bits. Also, |
| // do_unpack must unpack fields in the same order in which they were packed. |
| // See <uvm_packer> for more information. |
| // |
| // The following implementation corresponds to the example given in do_pack. |
| // |
| //| function void do_unpack (uvm_packer packer); |
| //| int sz; |
| //| super.do_unpack(packer); // unpack super's properties |
| //| sz = packer.unpack_field_int(myarray.size(), 32); |
| //| myarray.delete(); |
| //| for(int index=0; index<sz; index++) |
| //| myarray[index] = packer.unpack_field_int(8); |
| //| myshort = packer.unpack_field_int($bits(myshort)); |
| //| packer.unpack_object(myobj); |
| //| endfunction |
| // |
| // If your object contains dynamic data (object, string, queue, dynamic array, |
| // or associative array), and you intend to <unpack> into an equivalent data |
| // structure, you must have included meta-information about the dynamic data |
| // when it was packed. |
| // |
| // - For queues, dynamic arrays, or associative arrays, unpack the number of |
| // elements in the array from the 32 bits immediately before unpacking |
| // individual elements, as shown above. |
| // |
| // - For string data types, unpack into the new string until a null byte is |
| // encountered. |
| // |
| // - For objects, unpack 4 bits into a byte or int variable. If the value |
| // is 0, the target object should be set to null and unpacking continues to |
| // the next property, if any. If the least significant bit is 1, then the |
| // target object should be allocated and its properties unpacked. |
| |
| extern virtual function void do_unpack (uvm_packer packer); |
| |
| |
| // Group: Configuration |
| |
| // Function: set_int_local |
| |
| extern virtual function void set_int_local (string field_name, |
| uvm_bitstream_t value, |
| bit recurse=1); |
| |
| // Function: set_string_local |
| |
| extern virtual function void set_string_local (string field_name, |
| string value, |
| bit recurse=1); |
| |
| // Function: set_object_local |
| // |
| // These methods provide write access to integral, string, and |
| // uvm_object-based properties indexed by a ~field_name~ string. The object |
| // designer choose which, if any, properties will be accessible, and overrides |
| // the appropriate methods depending on the properties' types. For objects, |
| // the optional ~clone~ argument specifies whether to clone the ~value~ |
| // argument before assignment. |
| // |
| // The global <uvm_is_match> function is used to match the field names, so |
| // ~field_name~ may contain wildcards. |
| // |
| // An example implementation of all three methods is as follows. |
| // |
| //| class mytype extends uvm_object; |
| //| |
| //| local int myint; |
| //| local byte mybyte; |
| //| local shortint myshort; // no access |
| //| local string mystring; |
| //| local obj_type myobj; |
| //| |
| //| // provide access to integral properties |
| //| function void set_int_local(string field_name, uvm_bitstream_t value); |
| //| if (uvm_is_match (field_name, "myint")) |
| //| myint = value; |
| //| else if (uvm_is_match (field_name, "mybyte")) |
| //| mybyte = value; |
| //| endfunction |
| //| |
| //| // provide access to string properties |
| //| function void set_string_local(string field_name, string value); |
| //| if (uvm_is_match (field_name, "mystring")) |
| //| mystring = value; |
| //| endfunction |
| //| |
| //| // provide access to sub-objects |
| //| function void set_object_local(string field_name, uvm_object value, |
| //| bit clone=1); |
| //| if (uvm_is_match (field_name, "myobj")) begin |
| //| if (value != null) begin |
| //| obj_type tmp; |
| //| // if provided value is not correct type, produce error |
| //| if (!$cast(tmp, value) ) |
| //| /* error */ |
| //| else begin |
| //| if(clone) |
| //| $cast(myobj, tmp.clone()); |
| //| else |
| //| myobj = tmp; |
| //| end |
| //| end |
| //| else |
| //| myobj = null; // value is null, so simply assign null to myobj |
| //| end |
| //| endfunction |
| //| ... |
| // |
| // Although the object designer implements these methods to provide outside |
| // access to one or more properties, they are intended for internal use (e.g., |
| // for command-line debugging and auto-configuration) and should not be called |
| // directly by the user. |
| |
| extern virtual function void set_object_local (string field_name, |
| uvm_object value, |
| bit clone=1, |
| bit recurse=1); |
| |
| |
| |
| //--------------------------------------------------------------------------- |
| // **** Internal Methods and Properties *** |
| // Do not use directly |
| //--------------------------------------------------------------------------- |
| |
| extern local function void m_pack (inout uvm_packer packer); |
| extern local function void m_unpack_pre (inout uvm_packer packer); |
| extern local function void m_unpack_post (uvm_packer packer); |
| |
| // The print_matches bit causes an informative message to be printed |
| // when a field is set using one of the set methods. |
| |
| local string m_leaf_name; |
| |
| local int m_inst_id; |
| static protected int m_inst_count; |
| |
| static /*protected*/ uvm_status_container __m_uvm_status_container = new; |
| |
| extern virtual function void __m_uvm_field_automation (uvm_object tmp_data__, |
| int what__, |
| string str__); |
| |
| extern protected virtual function uvm_report_object m_get_report_object(); |
| |
| endclass |
| |
| |
| uvm_copy_map uvm_global_copy_map = new; |
| |
| //------------------------------------------------------------------------------ |
| // IMPLEMENTATION |
| //------------------------------------------------------------------------------ |
| |
| // new |
| // --- |
| |
| function uvm_object::new (string name=""); |
| |
| m_inst_id = m_inst_count++; |
| m_leaf_name = name; |
| endfunction |
| |
| |
| // reseed |
| // ------ |
| |
| function void uvm_object::reseed (); |
| if(use_uvm_seeding) |
| this.srandom(uvm_create_random_seed(get_type_name(), get_full_name())); |
| endfunction |
| |
| |
| // get type |
| // -------- |
| |
| function uvm_object_wrapper uvm_object::get_type(); |
| uvm_report_error("NOTYPID", "get_type not implemented in derived class.", UVM_NONE); |
| return null; |
| endfunction |
| |
| |
| // get inst_id |
| // ----------- |
| |
| function int uvm_object::get_inst_id(); |
| return m_inst_id; |
| endfunction |
| |
| |
| // get_object_type |
| // --------------- |
| |
| function uvm_object_wrapper uvm_object::get_object_type(); |
| if(get_type_name() == "<unknown>") return null; |
| return factory.find_by_name(get_type_name()); |
| endfunction |
| |
| |
| // get inst_count |
| // -------------- |
| |
| function int uvm_object::get_inst_count(); |
| return m_inst_count; |
| endfunction |
| |
| |
| // get_name |
| // -------- |
| |
| function string uvm_object::get_name (); |
| return m_leaf_name; |
| endfunction |
| |
| |
| // get_full_name |
| // ------------- |
| |
| function string uvm_object::get_full_name (); |
| return get_name(); |
| endfunction |
| |
| |
| // set_name |
| // -------- |
| |
| function void uvm_object::set_name (string name); |
| m_leaf_name = name; |
| endfunction |
| |
| |
| // print |
| // ----- |
| |
| function void uvm_object::print(uvm_printer printer=null); |
| if (printer==null) |
| printer = uvm_default_printer; |
| if (printer == null) |
| `uvm_error("NULLPRINTER","uvm_default_printer is null") |
| $fwrite(printer.knobs.mcd,sprint(printer)); |
| endfunction |
| |
| |
| // sprint |
| // ------ |
| |
| function string uvm_object::sprint(uvm_printer printer=null); |
| bit p; |
| |
| if(printer==null) |
| printer = uvm_default_printer; |
| |
| // not at top-level, must be recursing into sub-object |
| if(!printer.istop()) begin |
| __m_uvm_status_container.printer = printer; |
| __m_uvm_field_automation(null, UVM_PRINT, ""); |
| do_print(printer); |
| return ""; |
| end |
| |
| printer.print_object(get_name(), this); |
| // backward compat with sprint knob: if used, |
| // print that, do not call emit() |
| if (printer.m_string != "") |
| return printer.m_string; |
| |
| return printer.emit(); |
| |
| endfunction |
| |
| |
| // convert2string (virtual) |
| // -------------- |
| |
| function string uvm_object::convert2string(); |
| return ""; |
| endfunction |
| |
| |
| // set_int_local |
| // ------------- |
| |
| function void uvm_object::set_int_local (string field_name, |
| uvm_bitstream_t value, |
| bit recurse=1); |
| __m_uvm_status_container.cycle_check.delete(); |
| __m_uvm_status_container.m_uvm_cycle_scopes.delete(); |
| |
| this.__m_uvm_status_container.status = 0; |
| this.__m_uvm_status_container.bitstream = value; |
| |
| __m_uvm_field_automation(null, UVM_SETINT, field_name); |
| |
| if(__m_uvm_status_container.warning && !this.__m_uvm_status_container.status) begin |
| uvm_report_error("NOMTC", $sformatf("did not find a match for field %s", field_name),UVM_NONE); |
| end |
| __m_uvm_status_container.cycle_check.delete(); |
| endfunction |
| |
| |
| // set_object_local |
| // ---------------- |
| |
| function void uvm_object::set_object_local (string field_name, |
| uvm_object value, |
| bit clone=1, |
| bit recurse=1); |
| uvm_object cc; |
| __m_uvm_status_container.cycle_check.delete(); |
| __m_uvm_status_container.m_uvm_cycle_scopes.delete(); |
| |
| if(clone && (value!=null)) begin |
| cc = value.clone(); |
| if(cc != null) cc.set_name(field_name); |
| value = cc; |
| end |
| |
| this.__m_uvm_status_container.status = 0; |
| this.__m_uvm_status_container.object = value; |
| __m_uvm_status_container.clone = clone; |
| |
| __m_uvm_field_automation(null, UVM_SETOBJ, field_name); |
| |
| if(__m_uvm_status_container.warning && !this.__m_uvm_status_container.status) begin |
| uvm_report_error("NOMTC", $sformatf("did not find a match for field %s", field_name), UVM_NONE); |
| end |
| __m_uvm_status_container.cycle_check.delete(); |
| |
| endfunction |
| |
| |
| // set_string_local |
| // ---------------- |
| function void uvm_object::set_string_local (string field_name, |
| string value, |
| bit recurse=1); |
| |
| __m_uvm_status_container.cycle_check.delete(); |
| __m_uvm_status_container.m_uvm_cycle_scopes.delete(); |
| |
| this.__m_uvm_status_container.status = 0; |
| this.__m_uvm_status_container.stringv = value; |
| |
| __m_uvm_field_automation(null, UVM_SETSTR, field_name); |
| |
| if(__m_uvm_status_container.warning && !this.__m_uvm_status_container.status) begin |
| uvm_report_error("NOMTC", $sformatf("did not find a match for field %s (@%0d)", field_name, this.get_inst_id()), UVM_NONE); |
| end |
| __m_uvm_status_container.cycle_check.delete(); |
| endfunction |
| |
| |
| // clone |
| // ----- |
| |
| function uvm_object uvm_object::clone(); |
| uvm_object tmp; |
| tmp = this.create(get_name()); |
| if(tmp == null) |
| uvm_report_warning("CRFLD", $sformatf("The create method failed for %s, object cannot be cloned", get_name()), UVM_NONE); |
| else |
| tmp.copy(this); |
| return(tmp); |
| endfunction |
| |
| |
| // copy |
| // ---- |
| |
| function void uvm_object::copy (uvm_object rhs); |
| //For cycle checking |
| static int depth; |
| if((rhs !=null) && (uvm_global_copy_map.get(rhs) != null)) begin |
| return; |
| end |
| |
| if(rhs==null) begin |
| uvm_report_warning("NULLCP", "A null object was supplied to copy; copy is ignored", UVM_NONE); |
| return; |
| end |
| |
| uvm_global_copy_map.set(rhs, this); |
| ++depth; |
| |
| __m_uvm_field_automation(rhs, UVM_COPY, ""); |
| do_copy(rhs); |
| |
| --depth; |
| if(depth==0) begin |
| uvm_global_copy_map.clear(); |
| end |
| endfunction |
| |
| |
| // do_copy |
| // ------- |
| |
| function void uvm_object::do_copy (uvm_object rhs); |
| return; |
| endfunction |
| |
| |
| // compare |
| // ------- |
| |
| function bit uvm_object::compare (uvm_object rhs, |
| uvm_comparer comparer=null); |
| bit t, dc; |
| static int style; |
| bit done; |
| done = 0; |
| if(comparer != null) |
| __m_uvm_status_container.comparer = comparer; |
| else |
| __m_uvm_status_container.comparer = uvm_default_comparer; |
| comparer = __m_uvm_status_container.comparer; |
| |
| if(!__m_uvm_status_container.scope.depth()) begin |
| comparer.compare_map.clear(); |
| comparer.result = 0; |
| comparer.miscompares = ""; |
| comparer.scope = __m_uvm_status_container.scope; |
| if(get_name() == "") |
| __m_uvm_status_container.scope.down("<object>"); |
| else |
| __m_uvm_status_container.scope.down(this.get_name()); |
| end |
| if(!done && (rhs == null)) begin |
| if(__m_uvm_status_container.scope.depth()) begin |
| comparer.print_msg_object(this, rhs); |
| end |
| else begin |
| comparer.print_msg_object(this, rhs); |
| uvm_report_info("MISCMP", |
| $sformatf("%0d Miscompare(s) for object %s@%0d vs. null", |
| comparer.result, |
| __m_uvm_status_container.scope.get(), |
| this.get_inst_id()), |
| __m_uvm_status_container.comparer.verbosity); |
| done = 1; |
| end |
| end |
| |
| if(!done && (comparer.compare_map.get(rhs) != null)) begin |
| if(comparer.compare_map.get(rhs) != this) begin |
| comparer.print_msg_object(this, comparer.compare_map.get(rhs)); |
| end |
| done = 1; //don't do any more work after this case, but do cleanup |
| end |
| |
| if(!done && comparer.check_type && (rhs != null) && (get_type_name() != rhs.get_type_name())) begin |
| __m_uvm_status_container.stringv = { "lhs type = \"", get_type_name(), |
| "\" : rhs type = \"", rhs.get_type_name(), "\""}; |
| comparer.print_msg(__m_uvm_status_container.stringv); |
| end |
| |
| if(!done) begin |
| comparer.compare_map.set(rhs, this); |
| __m_uvm_field_automation(rhs, UVM_COMPARE, ""); |
| dc = do_compare(rhs, comparer); |
| end |
| |
| if(__m_uvm_status_container.scope.depth()==1) begin |
| __m_uvm_status_container.scope.up(); |
| end |
| |
| if(rhs != null) |
| comparer.print_rollup(this, rhs); |
| return (comparer.result == 0 && dc == 1); |
| endfunction |
| |
| |
| // do_compare |
| // ---------- |
| |
| function bit uvm_object::do_compare (uvm_object rhs, |
| uvm_comparer comparer); |
| return 1; |
| endfunction |
| |
| |
| // __m_uvm_field_automation |
| // ------------------ |
| |
| function void uvm_object::__m_uvm_field_automation (uvm_object tmp_data__, |
| int what__, |
| string str__ ); |
| return; |
| endfunction |
| |
| |
| |
| // do_print (virtual override) |
| // ------------ |
| |
| function void uvm_object::do_print(uvm_printer printer); |
| return; |
| endfunction |
| |
| |
| // m_pack |
| // ------ |
| |
| function void uvm_object::m_pack (inout uvm_packer packer); |
| |
| if(packer!=null) |
| __m_uvm_status_container.packer = packer; |
| else |
| __m_uvm_status_container.packer = uvm_default_packer; |
| packer = __m_uvm_status_container.packer; |
| |
| packer.reset(); |
| packer.scope.down(get_name()); |
| |
| __m_uvm_field_automation(null, UVM_PACK, ""); |
| do_pack(packer); |
| |
| packer.set_packed_size(); |
| |
| packer.scope.up(); |
| |
| endfunction |
| |
| |
| // pack |
| // ---- |
| |
| function int uvm_object::pack (ref bit bitstream [], |
| input uvm_packer packer =null ); |
| m_pack(packer); |
| packer.get_bits(bitstream); |
| return packer.get_packed_size(); |
| endfunction |
| |
| // pack_bytes |
| // ---------- |
| |
| function int uvm_object::pack_bytes (ref byte unsigned bytestream [], |
| input uvm_packer packer=null ); |
| m_pack(packer); |
| packer.get_bytes(bytestream); |
| return packer.get_packed_size(); |
| endfunction |
| |
| |
| // pack_ints |
| // --------- |
| |
| function int uvm_object::pack_ints (ref int unsigned intstream [], |
| input uvm_packer packer=null ); |
| m_pack(packer); |
| packer.get_ints(intstream); |
| return packer.get_packed_size(); |
| endfunction |
| |
| |
| // do_pack |
| // ------- |
| |
| function void uvm_object::do_pack (uvm_packer packer ); |
| return; |
| endfunction |
| |
| |
| // m_unpack_pre |
| // ------------ |
| |
| function void uvm_object::m_unpack_pre (inout uvm_packer packer); |
| if(packer!=null) |
| __m_uvm_status_container.packer = packer; |
| else |
| __m_uvm_status_container.packer = uvm_default_packer; |
| packer = __m_uvm_status_container.packer; |
| packer.reset(); |
| endfunction |
| |
| |
| // m_unpack_post |
| // ------------- |
| |
| function void uvm_object::m_unpack_post (uvm_packer packer); |
| |
| int provided_size; |
| |
| provided_size = packer.get_packed_size(); |
| |
| //Put this object into the hierarchy |
| packer.scope.down(get_name()); |
| |
| __m_uvm_field_automation(null, UVM_UNPACK, ""); |
| |
| do_unpack(packer); |
| |
| //Scope back up before leaving |
| packer.scope.up(); |
| |
| if(packer.get_packed_size() != provided_size) begin |
| uvm_report_warning("BDUNPK", $sformatf("Unpack operation unsuccessful: unpacked %0d bits from a total of %0d bits", packer.get_packed_size(), provided_size), UVM_NONE); |
| end |
| |
| endfunction |
| |
| |
| // unpack |
| // ------ |
| |
| function int uvm_object::unpack (ref bit bitstream [], |
| input uvm_packer packer=null); |
| m_unpack_pre(packer); |
| packer.put_bits(bitstream); |
| m_unpack_post(packer); |
| packer.set_packed_size(); |
| return packer.get_packed_size(); |
| endfunction |
| |
| |
| // unpack_bytes |
| // ------------ |
| |
| function int uvm_object::unpack_bytes (ref byte unsigned bytestream [], |
| input uvm_packer packer=null); |
| m_unpack_pre(packer); |
| packer.put_bytes(bytestream); |
| m_unpack_post(packer); |
| packer.set_packed_size(); |
| return packer.get_packed_size(); |
| endfunction |
| |
| |
| // unpack_ints |
| // ----------- |
| |
| function int uvm_object::unpack_ints (ref int unsigned intstream [], |
| input uvm_packer packer=null); |
| m_unpack_pre(packer); |
| packer.put_ints(intstream); |
| m_unpack_post(packer); |
| packer.set_packed_size(); |
| return packer.get_packed_size(); |
| endfunction |
| |
| |
| // do_unpack |
| // --------- |
| |
| function void uvm_object::do_unpack (uvm_packer packer); |
| return; |
| endfunction |
| |
| |
| // record |
| // ------ |
| |
| function void uvm_object::record (uvm_recorder recorder=null); |
| |
| if(recorder == null) |
| recorder = uvm_default_recorder; |
| |
| if(!recorder.tr_handle) return; |
| |
| __m_uvm_status_container.recorder = recorder; |
| recorder.recording_depth++; |
| __m_uvm_field_automation(null, UVM_RECORD, ""); |
| do_record(recorder); |
| |
| recorder.recording_depth--; |
| |
| if(recorder.recording_depth==0) begin |
| recorder.tr_handle = 0; |
| end |
| endfunction |
| |
| |
| // do_record (virtual) |
| // --------- |
| |
| function void uvm_object::do_record (uvm_recorder recorder); |
| return; |
| endfunction |
| |
| |
| // m_get_report_object |
| // ------------------- |
| |
| function uvm_report_object uvm_object::m_get_report_object(); |
| return null; |
| endfunction |
| |