VMM  1.2.2b
vmm_object.sv
Go to the documentation of this file.
1 //
2 // -------------------------------------------------------------
3 // Copyright 2004-2009 Synopsys, Inc.
4 // All Rights Reserved Worldwide
5 //
6 // Licensed under the Apache License, Version 2.0 (the
7 // "License"); you may not use this file except in
8 // compliance with the License. You may obtain a copy of
9 // the License at
10 //
11 // http://www.apache.org/licenses/LICENSE-2.0
12 //
13 // Unless required by applicable law or agreed to in
14 // writing, software distributed under the License is
15 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
16 // CONDITIONS OF ANY KIND, either express or implied. See
17 // the License for the specific language governing
18 // permissions and limitations under the License.
19 // -------------------------------------------------------------
20 //
21 
22 `ifndef VMM_OBJECT__SV
24 
25 `ifndef VMM_OBJECT
27 `endif
28 `ifndef VMM_OBJECT_NEW_ARGS
32 `endif
36 `endif
37 `ifdef VMM_OBJECT_BASE
38  `ifndef VMM_OBJECT_BASE_NEW_CALL
39  `define VMM_OBJECT_BASE_NEW_CALL
40  `endif
41 `endif
44 `endif
45 
46 typedef class `VMM_OBJECT;
47 `ifdef VMM_OBJECT_BASE
48 typedef class `VMM_OBJECT_BASE;
49 `endif
50 
51 `ifndef NO_VMM12_PHASING
52 typedef class vmm_phase_def;
53 `endif
54 
55 //---------------------------------------------------------------------
56 // vmm_object
57 //
58 `ifdef VCS
59 (* _vcs_vmm_class = 1 *)
60 `endif
61 //
62 // Class: vmm_object
63 // The vmm_object class is a virtual class that is used as the common base class
64 // for all VMM related classes. This helps to provide parent or child relationships for class instances.
65 //
66 // Additionally, it provides local, relative, and absolute hierarchical naming.
67 
68 virtual class vmm_object
69 `ifdef VMM_OBJECT_BASE
70  extends `VMM_OBJECT_BASE
71 `endif // VMM_OBJECT_BASE
72 ;
73 
78 
79  typedef enum {IN_BY_DEFAULT, OUT_BY_DEFAULT} namespace_typ_e;
80 
81  //----------------------
82  // variables
83  //----------------------
84  static local vmm_log log = new("Global", "default");
85  static bit do_object_thresh_check = vmm_opts::get_bit("object_thresh_check", "Gloabal setting for checking object threshhold in object hierarchy, channel and scoreboard");
86  static int children_thresh = vmm_opts::get_int("object_children_thresh", 100, "GLOBAL option that sets the number of child objects threshold");
87  static int root_thresh = vmm_opts::get_int("object_root_thresh", 1000, "GLOBAL option that sets the number of root objects threshold");
88 
89  local string name;
90 
91  protected vmm_object _parent;
92  local vmm_object children[$];
93 
94  local static vmm_object registered_objects[$];
95  local static vmm_object roots[$];
96  local static int next_root = 0;
97 
98  local static namespace_typ_e namespace_type[string];
99  local string name_in_namespace[string];
100 
101  local bit implicit_phasing_enabled = 1;
102  local bit disable_hier_insert = 0;
103 
104 
105  //----------------------
106  // methods
107  //----------------------
108 
111 `endif
112 
113  //------------------------
114  // VMM1.1 functions
115  //------------------------
116 
117  extern function new(vmm_object parent = null
119  extern function void set_parent(vmm_object parent);
120  extern function vmm_object get_parent(type_e typ = VMM_OBJECT);
121  extern function type_e get_type();
122  extern function string get_hier_inst_name();
123  extern local function vmm_log get_child_log(vmm_object child);
124  extern local function vmm_log get_parent_log(vmm_object parent);
125 
126 
127  //-----------------------------
128  // VMM1.2 functions
129  //-----------------------------
130 
131  //--------
132  // public
133  //--------
134  //pure virtual function string get_typename(); //implementation should be left empty
135  extern virtual function void set_object_name(string name, string space = "");
136  extern virtual function void set_parent_object(vmm_object parent);
137 
138  extern function vmm_object get_parent_object(string space = "");
139  extern function vmm_object get_root_object(string space = "");
140  extern function int get_num_children();
141  extern function vmm_object get_nth_child(int n);
142  extern function bit is_parent_of(vmm_object obj, string space = "");
143 
144  extern function string get_object_name(string space = "");
145  extern function string get_object_hiername(vmm_object root = null, string space = "");
146 
147  extern function vmm_object find_child_by_name(string name, string space = "");
148  extern static function vmm_object find_object_by_name(string name, string space = "");
149 
150  extern static function int get_num_roots(string space = "");
151  extern static function vmm_object get_nth_root(int n, string space = "");
152 
153  extern virtual function vmm_log get_log();
154  extern virtual function void kill_object();
155 
156  extern function void display(string prefix = "");
157  extern virtual function string psdisplay(string prefix = "");
158 
159  extern static function void print_hierarchy(vmm_object root = null, bit verbose = 0);
160 
161  extern virtual function void implicit_phasing(bit is_on);
162  extern virtual function bit is_implicitly_phased();
163 
164  extern static function bit create_namespace(string name, namespace_typ_e typ = OUT_BY_DEFAULT);
165  extern static function void get_namespaces(output string names[]);
166  extern function bit is_in_namespace(string space);
167  extern static function void register_object(vmm_object obj);
168  extern static function void unregister_object(vmm_object obj);
169 
170 
171  //--------
172  // local
173  //--------
174 
175  extern local function void print_tree(int level = 0, bit verbose = 0);
176 
177 endclass: vmm_object
178 
179 //------------------------
180 // VMM1.1 implementation
181 //------------------------
182 
183 // ////////////////////////////////////////////
184 // Function: set_parent
185 //
186 // Specifies a new parent object to this object. Specifying a null parent, breaks any current
187 // parent or child relationship. An object may contain only one parent, but the identity
188 // of a parent can be changed dynamically.
189 //
190 //| class C extends vmm_object;
191 //| function new(string name, vmm_object parent=null);
192 //| super.new (parent,name);
193 //| endfunction
194 //| endclass
195 //| class D extends vmm_object;
196 //| C c1;
197 //| function new(string name, vmm_object parent=null);
198 //| super.new (parent,name);
199 //| c1 = new ("c1",this);
200 //| endfunction
201 //| endclass
202 //|
203 //| initial begin
204 //| D d1 = new ("d1");
205 //| D d2 = new ("d2");
206 //| d1.c1.set_parent_object (d2);
207 //| end
208 function void vmm_object::set_parent(vmm_object parent);
209  vmm_log par;
210  vmm_log log = null;
211 
212  if (parent == null && this._parent != null) begin
213  // Break the existing parent/child relationship
214  par = this.get_parent_log(this._parent);
215  log = this.get_child_log(this);
216  if (par != null && log != null) par.is_not_above(log);
217  end
218 
219  this._parent = parent;
220  if (parent == null) return;
221 
222  // If both this and the parent have a vmm_log instance
223  // make this log below the parent's log
224  par = this.get_parent_log(this._parent);
225  if (log == null) log = this.get_child_log(this);
226  if (par != null && log != null) par.is_above(log);
227 endfunction
228 
229 
231  // Note: only SOME of the VMM objects have their own log instances
232  begin
233  vmm_channel obj;
234  if ($cast(obj, child)) begin
235  // If is a shared instance, abort
236  if (obj.log.get_instance() == "[shared]") return null;
237  return obj.log;
238  end
239  end
240  begin
241  vmm_xactor obj;
242  if ($cast(obj, child)) begin
243  return obj.log;
244  end
245  end
246  begin
247  vmm_subenv obj;
248  if ($cast(obj, child)) begin
249  return obj.log;
250  end
251  end
252  begin
253  vmm_env obj;
254  if ($cast(obj, child)) begin
255  return obj.log;
256  end
257  end
258  begin
259  vmm_consensus obj;
260  if ($cast(obj, child)) begin
261  return obj.log;
262  end
263  end
264 `ifdef NOT_YET_IMPLEMENTED
265  begin
266  vmm_test obj;
267  if ($cast(obj, child)) begin
268  return obj.log;
269  end
270  end
271 `endif
272 
273  return null;
274 endfunction: get_child_log
275 
276 
278  // Only some kind of objects can be hierarhical parents
279  begin
280  vmm_xactor obj;
281  if ($cast(obj, parent)) begin
282  return obj.log;
283  end
284  end
285  begin
286  vmm_subenv obj;
287  if ($cast(obj, parent)) begin
288  return obj.log;
289  end
290  end
291  begin
292  vmm_env obj;
293  if ($cast(obj, parent)) begin
294  return obj.log;
295  end
296  end
297 `ifdef NOT_YET_IMPLEMENTED
298  begin
299  vmm_test obj;
300  if ($cast(obj, parent)) begin
301  return obj.log;
302  end
303  end
304 `endif
305 
306  // if the parent is unsuitable, nothing to do
307  return null;
308 endfunction: get_parent_log
309 
310 
311 // ////////////////////////////////////////////
312 // Function: get_parent
313 //
314 // Returns the parent object of the specified type, if any. Returns NULL, if no such parent
315 // is found. Specifying VMM_OBJECT returns the immediate parent of any type.
316 //
317 //|
318 //| class tb_env extends vmm_env;
319 //| tr_scenario_gen gen1;
320 //| function new(string inst, vmm_consensus end_vote);
321 //| gen1.set_parent(this);
322 //| endfunction
323 //| endclass
324 //| initial begin
325 //| tb_env env;
326 //| if (env.gen1.randomized_obj.get_parent() != env.gen1) begin
327 //| `vmm_error(log, "Factory instance in atomic_gen returns wrong parent");
328 //| end
329 //| end
331  vmm_object obj = this;
332 
333  while (obj._parent != null) begin
334  if (typ == VMM_OBJECT ||
335  obj._parent.get_type() == typ) return obj._parent;
336 
337  obj = obj._parent;
338  end
339  return null;
340 endfunction
341 
342 
343 // ////////////////////////////////////////////
344 // Function: get_type
345 //
346 // Returns the type of this vmm_object extension.
347 // Returns the VMM_OBJECT, if it is not one of the known VMM class extensions. VMM_UNKNOWN
348 // is purely an internal value, and is never returned.
349 //
350 //|
351 //| class tb_env extends vmm_env;
352 //| tr_scenario_gen gen1;
353 //| gen1.set_parent(this);
354 //| endclass
355 //|
356 //| initial begin
357 //| tb_env env;
358 //| if (env.get_type() != VMM_ENV)
359 //| begin
360 //| `vmm_error(log, "Wrong type returned from vmm_env
361 //| instance");
362 //| end
363 //| end
365  // Find out -- and cache -- the object type
366  begin
367  vmm_scenario obj;
368  if ($cast(obj, this)) begin
369  return VMM_SCENARIO;
370  end
371  end
372  begin
373  vmm_data obj;
374  if ($cast(obj, this)) begin
375  return VMM_DATA;
376  end
377  end
378 `ifdef NOT_YET_IMPLEMENTED
379  begin
380  vmm_ms_scenario obj;
381  if ($cast(obj, this)) begin
382  return VMM_MS_SCENARIO;
383  end
384  end
385 `endif
386  begin
387  vmm_channel obj;
388  if ($cast(obj, this)) begin
389  return VMM_CHANNEL;
390  end
391  end
392  begin
393  vmm_notify obj;
394  if ($cast(obj, this)) begin
395  return VMM_NOTIFY;
396  end
397  end
398  begin
399  vmm_xactor obj;
400  if ($cast(obj, this)) begin
401  return VMM_XACTOR;
402  end
403  end
404  begin
405  vmm_subenv obj;
406  if ($cast(obj, this)) begin
407  return VMM_SUBENV;
408  end
409  end
410  begin
411  vmm_env obj;
412  if ($cast(obj, this)) begin
413  return VMM_ENV;
414  end
415  end
416  begin
417  vmm_consensus obj;
418  if ($cast(obj, this)) begin
419  return VMM_CONSENSUS;
420  end
421  end
422 `ifdef NOT_YET_IMPLEMENTED
423  begin
424  vmm_test obj;
425  if ($cast(obj, this)) begin
426  return VMM_TEST;
427  end
428  end
429 `endif
430 
431  // I give up!
432  return VMM_OBJECT;
433 endfunction
434 
435 
436 // ////////////////////////////////////////////
437 // Function: get_hier_inst_name
438 //
439 // Returns the vmm_log instance of this object, or the nearest enclosing object. If no
440 // vmm_log instance is available in the object genealogy, a default global vmm_log instance
441 // is returned.
442 //
443 //| class ABC extends vmm_object;
444 //| vmm_log log = new("ABC", "class");
445 //| ...
446 //| function vmm_log get_log();
447 //| return this.log;
448 //| endfunction
449 //| ...
450 //| endclass
451 //|
452 //| vmm_log test_log;
453 //| ABC abc_inst = new("test_abc");
454 //| initial begin
455 //| test_log = abc_inst.get_log();
456 //| ...
457 //| end
459  vmm_xactor xact;
460  vmm_subenv sub;
461  vmm_env env;
462  vmm_log log;
463  string name;
464 
465  log = null;
466  name = "[unknown]";
467 
468  case (this.get_type())
469 
470  VMM_DATA: name = "[vmm_data]";
471  VMM_SCENARIO: name = "[vmm_scenario]";
472  VMM_MS_SCENARIO: name = "[vmm_ms_scenario]";
473  VMM_NOTIFY: name = "[vmm_notify]";
474 
475  VMM_CHANNEL: begin
476  vmm_channel obj;
477  $cast(obj, this);
478  log = obj.log;
479  end
480 
481  VMM_XACTOR: begin
482  vmm_xactor obj;
483  $cast(obj, this);
484  log = obj.log;
485  end
486 
487  VMM_SUBENV: begin
488  vmm_subenv obj;
489  $cast(obj, this);
490  log = obj.log;
491  end
492 
493  VMM_ENV: begin
494  vmm_env obj;
495  $cast(obj, this);
496  log = obj.log;
497  end
498 
499  VMM_CONSENSUS: begin
500  vmm_consensus obj;
501  $cast(obj, this);
502  log = obj.log;
503  end
504 
505 `ifdef NOT_YET_IMPLEMENTED
506  VMM_TEST: begin
507  vmm_test obj;
508  $cast(obj, this);
509  log = obj.log;
510  end
511 `endif
512  endcase
513 
514  // Unamed object?
515  if (log == null) begin
516  if (this._parent == null) return name;
517  return {this._parent.get_hier_inst_name(), ".", name};
518  end
519 
520  name = log.get_instance();
521 
522  // If named using hierarchical names, that's it!
523  if (log.uses_hier_inst_name()) return name;
524 
525  // If the log instance does not have an instance name...
526  if (name == "") name = log.get_name();
527  if (name == "") name = "[Anonymous]";
528 
529  // If no parent, that's it.
530  if (this._parent == null) return name;
531 
532  return {this._parent.get_hier_inst_name(), ".", name};
533 endfunction
534 
535 //------------------------
536 // VMM1.2 implementation
537 //------------------------
538 
539 //-----------
540 // public
541 //-----------
542 function vmm_object::new(vmm_object parent = null
544  string space;
545  bit ok;
546 
547  this.name = name;
548  //if (name == "") `vmm_warning(this.log, "Object has no name. Please specify a name for the object");
549  this.disable_hier_insert = disable_hier_insert;
550  if (parent == null) begin
551  //if parent is null then check if hierarchy insertion is disabled
552  if (disable_hier_insert) return;
553  end
554  else if (parent == this) begin
555  `vmm_fatal(this.log,`vmm_sformatf("Object %s is setting itself as its parent!", name));
556  return;
557  end
558  else this._parent = parent;
559  if (this._parent != null) this._parent.children.push_back(this);
560  if (this._parent == null) this.roots.push_back(this);
561  registered_objects.push_back(this);
562 
563  ok = namespace_type.first(space);
564  while(ok) begin
565  if (namespace_type[space] == IN_BY_DEFAULT) this.name_in_namespace[space] = this.name;
566  else if (namespace_type[space] == OUT_BY_DEFAULT) this.name_in_namespace[space] = "";
567  ok = namespace_type.next(space);
568  end
569 
570  endfunction:new
571 
572 // ////////////////////////////////////////////
573 // Function: set_object_name
574 //
575 // This method is used to set or replace the name of this object in the specified namespace.
576 // If no namespace is specified, the name of the object is replaced. If a name is not specified
577 // for a namespace, it defaults to the object name. Names in a named namespace may contain
578 // colons (:) to create additional levels of hierarchy, or may be empty to skip a level of
579 // hierarchy. A name starting with a caret (^) indicates that it is a root in the specified
580 // namespace. However, this does not apply to the object name where parentless objects
581 // create roots in the default namespace.
582 //
583 //| class E extends vmm_object;
584 //| ...
585 //| endclass
586 //| initial begin
587 //| vmm_object obj;
588 //| E e1 = new ("e1");
589 //| create_namespace("NS1",
590 //| IN_BY_DEFAULT);
591 //| ...
592 //| obj = e1;
593 //| obj.set_object_name ("new_e1","NS1");
594 //| ...
595 //| end
596  function void vmm_object::set_object_name(string name, string space = "");
597  if (space == "") begin
598  this.name = name;
599  if (name == "") `vmm_warning(this.log, "Object has no name in default namespace. Please specify a name for the object");
600  end
601  else begin
602  if (namespace_type.exists(space)) this.name_in_namespace[space] = name;
603  else `vmm_warning(this.log, `vmm_sformatf("Namespace /%s/ does not exists.", space));
604  end
605  endfunction:set_object_name
606 
608 
609 
610  if (parent == null) begin
611  //check if this is vmm_data
612  if (this.disable_hier_insert) return;
613  end
614  else if (this._parent == parent) return; //nothing changed
615 
616  if (this._parent == null && parent != null) begin //add parent
617  if (this.is_parent_of(parent)) begin
618  `vmm_fatal(this.log, `vmm_sformatf("Setting %s as parent of %s will form hierarchy cycle. Object hierarchies should be strict trees.", parent.get_object_name(), this.get_object_name()));
619  return;
620  end
621  else this._parent = parent;
622  foreach (vmm_object::roots[i]) begin
623  if (vmm_object::roots[i] == this) begin
624  vmm_object::roots.delete(i);
625  break;
626  end
627  end
628  this._parent.children.push_back(this);
629 
630  //in this case, check children threshhold
631  if (do_object_thresh_check && this._parent.children.size() >= children_thresh)
632  `vmm_warning(this.log, `vmm_sformatf("The number of children of object [%s] passes the specified threshold ( = %0d ) indicating a potential garbage collection/memory leak problem. Please use vmm_object::kill_object() or increase the threshold.", this._parent.get_object_hiername(), children_thresh));
633  return;
634  end
635 
636  if (this._parent != null && parent == null) begin //remove parent
637  this.roots.push_back(this);
638  foreach (this._parent.children[i]) begin
639  if (this._parent.children[i] == this) begin
640  this._parent.children.delete(i);
641  break;
642  end
643  end
644  this._parent = parent;
645 
646  //in this case, check root threshhold
647  if (do_object_thresh_check && this.roots.size() >= root_thresh)
648  `vmm_warning(this.log, `vmm_sformatf("The number of root objects passes the specified threshold ( = %0d ) indicating a potential garbage collection/memory leak problem. Please use vmm_object::kill_object() or increase the threshold.", root_thresh));
649  return;
650  end
651 
652  if (this._parent != null && parent != null) begin //replace parent
653  if (this.is_parent_of(parent)) begin
654  `vmm_fatal(this.log, `vmm_sformatf("Setting %s as parent of %s will form hierarchy cycle. Object hierarchies should be strict trees.", parent.get_object_name(), this.get_object_name()));
655  return;
656  end
657  else begin
658  foreach (this._parent.children[i]) begin
659  if (this._parent.children[i] == this) begin
660  this._parent.children.delete(i);
661  break;
662  end
663  end
664  this._parent = parent;
665  this._parent.children.push_back(this);
666  end
667 
668  //in this case, check children threshhold
669  if (do_object_thresh_check && this._parent.children.size() >= children_thresh)
670  `vmm_warning(this.log, `vmm_sformatf("The number of children of object [%s] passes the specified threshold ( = %0d ) indicating a potential garbage collection/memory leak problem. Please use vmm_object::kill_object() or increase the threshold.", this._parent.get_object_hiername(), children_thresh));
671 
672  return;
673  end
674  endfunction:set_parent_object
675 
676 // ////////////////////////////////////////////
677 // Function: get_parent_object
678 //
679 // Returns the parent object of this object for specified namespace, if any. Returns null,
680 // if no parent is found. A root object contains no parent.
681 //
682 //| class C extends vmm_object;
683 //| ...
684 //| endclass
685 //| class D extends vmm_object;
686 //| C c1;
687 //| function new(string name, vmm_object parent=null);
688 //| c1 = new ("c1",this);
689 //| endfunction
690 //| endclass
691 //|
692 //| initial begin
693 //| vmm_object parent;
694 //| D d1 = new ("d1");
695 //| parent = d1.c1.get_parent_object;
696 //| end
697  function vmm_object vmm_object::get_parent_object(string space = "");
698  vmm_object physical_parent;
699  vmm_object return_parent;
700  string tmp;
701 
702  if (space == "") return this._parent;
703  if (this.is_in_namespace(space)) begin
704  tmp = this.name_in_namespace[space];
705  if (tmp[0] == "^") return null; // if the name indicates it's root
706  physical_parent = this._parent;
707  if (physical_parent == null) return null; //if physically it's root
708  tmp = physical_parent.name_in_namespace[space];
709  if (tmp == "^") return null; //if its parent's name indicates it's root
710  if (tmp == "") begin //if parent is skipped
711  physical_parent = physical_parent._parent;
712  while (physical_parent != null) begin
713  tmp = physical_parent.name_in_namespace[space];
714  if (tmp != "" && tmp != "^") return physical_parent;
715  if (tmp == "^") return null;
716  if (tmp == "") begin
717  physical_parent = physical_parent._parent;
718  end
719  end
720  return null; //if all hierarchy up to root are skipped
721  end
722  return physical_parent; //if parent is present
723  end
724  `vmm_error(this.log, "Namespace does not exist or Object is not in Namespace.");
725  return null;
726  endfunction:get_parent_object
727 
728 // ////////////////////////////////////////////
729 // Function: get_root_object
730 //
731 // Gets the root parent of this object, for the specified namespace.
732 //
733 //| class C extends vmm_object;
734 //| ...
735 //| endclass
736 //| class D extends vmm_object;
737 //| C c1;
738 //| function new(string name, vmm_object parent=null);
739 //| c1 = new ("c1",this);
740 //| endfunction
741 //| endclass
742 //| class E extends vmm_object;
743 //| D d1;
744 //| function new(string name, vmm_object parent=null);
745 //| ...
746 //| d1 = new ("d1",this);
747 //| endfunction
748 //| endclass
749 //| ...
750 //| initial begin
751 //| vmm_object root;
752 //| E e1 = new ("e1");
753 //| root = e1.d1.c1.get_root_object;
754 //| ...
755 //| end
756  function vmm_object vmm_object::get_root_object(string space = "");
757  vmm_object root;
758 
759  if ( this.is_in_namespace(space)) begin
760  root = this;
761  while (root.get_parent_object(space) != null) root = root.get_parent_object(space);
762  return root;
763  end
764  `vmm_error(this.log, "Namespace does not exist or Object is not in Namespace.");
765  return null;
766  endfunction:get_root_object
767 
768 // ////////////////////////////////////////////
769 // Function: get_num_children
770 //
771 // Gets the total number of root objects in the specified namespace.
772 //
773 //| class D extends vmm_object;
774 //| ...
775 //| endclass
776 //| class E extends vmm_object;
777 //| D d1;
778 //| D d2;
779 //| function new(string name, vmm_object parent=null);
780 //| ...
781 //| d1 = new ("d1");
782 //| d2 = new ("d2");
783 //| endfunction
784 //| endclass
785 //| ...
786 //| int num_roots;
787 //| initial begin
788 //| E e1 = new ("e1");
789 //| ...
790 //| num_roots = E :: get_num_roots; //Returns 2
791 //| ...
792 //| end
794  return this.children.size();
795  endfunction:get_num_children
796 
797 // ////////////////////////////////////////////
798 // Function: get_nth_child
799 //
800 // Returns the nth child of this object. Returns null, if there is no child.
801 //
802 //| class C extends vmm_object;
803 //| ...
804 //| endclass
805 //| class D extends vmm_object;
806 //| ...
807 //| endclass
808 //| class E extends vmm_object;
809 //| C c1;
810 //| D d1;
811 //| D d2;
812 //| function new(string name, vmm_object parent=null);
813 //| c1 = new ("c1",this);
814 //| d1 = new ("d1");
815 //| d2 = new ("d2",this);
816 //| endfunction
817 //| endclass
818 //| initial begin
819 //| vmm_object obj;
820 //| string name;
821 //| E e1 = new ("e1");
822 //| obj = e1.get_nth_child(0);
823 //| name = obj.get_object_name(); //Returns c1
824 //| ...
825 //| end
827  if (n < 0 || n >= this.children.size()) return null;
828  return this.children[n];
829  endfunction:get_nth_child
830 
831 // ////////////////////////////////////////////
832 // Function: get_object_name
833 //
834 // Gets the local name of this object, in the specified namespace. If no namespace is specified,
835 // then returns the actual name of the object.
836 //
837 //| class C extends vmm_object;
838 //| function new(string name, vmm_object parent=null);
839 //| super.new (parent,name);
840 //| endfunction
841 //| endclass
842 //| ...
843 //| initial begin
844 //| string obj_name;
845 //| C c1 = new ("c1");
846 //| ...
847 //| obj_name = c1.get_object_name(); //Returns c1
848 //| ...
849 //| end
850  function string vmm_object::get_object_name(string space = "");
851  string tmp;
852 
853  if (space == "") return this.name;
854  else begin
855  if (namespace_type.exists(space)) begin
856  tmp = this.name_in_namespace[space];
857  if (tmp[0] == "^") tmp = tmp.substr(1, tmp.len()-1);
858  return tmp;
859  end
860  else begin
861  `vmm_warning(this.log, `vmm_sformatf("Namespace /%s/ does not exists.", space));
862  return "";
863  end
864  end
865  endfunction:get_object_name
866 
867 // ////////////////////////////////////////////
868 // Function: get_object_hiername
869 //
870 // Gets the complete hierarchical name of this object in the specified namespace, relative
871 // to the specified root object. If no root object is specified, returns the complete hierarchical
872 // name of the object. The instance name is composed of the period-separated instance
873 // names of the message service interface of all the parents of the object.
874 //
875 //| class D extends vmm_object;
876 //| ...
877 //| endclass
878 //| class E extends vmm_object;
879 //| D d1;
880 //| function new(string name, vmm_object parent=null);
881 //| ...
882 //| d1 = new ("d1",this);
883 //| endfunction
884 //| endclass
885 //| ...
886 //| initial begin
887 //| string hier_name;
888 //| E e1 = new ("e1");
889 //| ...
890 //| hier_name = e1.d1.get_object_hiername();
891 //| ...
892 //| end
893  function string vmm_object::get_object_hiername(vmm_object root = null, string space = "");
894  string hiername = "";
895  vmm_object next_parent;
896 
897  next_parent = this;
898  while (next_parent != null) begin
899  if (next_parent == root) break;
900  if (next_parent == this) hiername = next_parent.get_object_name(space);
901  else hiername = {next_parent.get_object_name(space), ":", hiername};
902  next_parent = next_parent.get_parent_object(space);
903  end
904  return hiername;
905  endfunction:get_object_hiername
906 
907 // ////////////////////////////////////////////
908 // Function: find_child_by_name
909 //
910 // Finds the named object, interpreting the name as an absolute name in the specified namespace.
911 // If the name is a match pattern or regular expression, the first object matching the name
912 // is returned.
913 // Returns null, if no object was found under the specified name.
914 //
915 //| class D extends vmm_object;
916 //| ...
917 //| endclass
918 //| class E extends vmm_object;
919 //| D d1;
920 //| function new(string name, vmm_object parent=null);
921 //| ...
922 //| d1 = new ("d1");
923 //| endfunction
924 //| endclass
925 //| ...
926 //| initial begin
927 //| vmm_object obj;
928 //| ...
929 //| obj = E :: find_object_by_name ("d1");
930 //| ...
931 //| end
932  function vmm_object vmm_object::find_child_by_name(string name, string space = "");
933  string hiername;
934  `vmm_path_compiled compiled_hiername;
935  `vmm_path_regexp compiled_pattern;
936 
937  compiled_pattern = vmm_path_match::compile_pattern(name, log);
938 
939  foreach(registered_objects[i]) begin
940  if (!registered_objects[i].is_in_namespace(space)) continue;
941  if (this.is_parent_of(registered_objects[i], space)) begin
942  hiername = registered_objects[i].get_object_hiername(this, space);
943  compiled_hiername = vmm_path_match::compile_path(log, this, hiername, space);
944  if (vmm_path_match::match(compiled_hiername, compiled_pattern)) return registered_objects[i];
945  end
946  end
947  return null;
948  endfunction:find_child_by_name
949 
950  function vmm_object vmm_object::find_object_by_name(string name, string space = "");
951  `vmm_path_compiled compiled_hiername;
952  `vmm_path_regexp compiled_pattern;
953 
954  compiled_pattern = vmm_path_match::compile_pattern(name, log);
955 
956  foreach(registered_objects[i]) begin
957  if (!registered_objects[i].is_in_namespace(space)) continue;
958  compiled_hiername = vmm_path_match::compile_path(log, registered_objects[i], "", space);
959  if (vmm_path_match::match(compiled_hiername, compiled_pattern)) return registered_objects[i];
960  end
961  return null;
962  endfunction:find_object_by_name
963 
964  function int vmm_object::get_num_roots(string space = "");
965  int root_count = 0;
966 
967  if (space == "") return vmm_object::roots.size();
968 
969  if (namespace_type.exists(space)) begin
970  foreach (registered_objects[i]) begin
971  if (registered_objects[i].name_in_namespace[space] != "" &&
972  registered_objects[i].name_in_namespace[space] != "^" &&
973  registered_objects[i].get_parent_object(space) == null) root_count++;
974  end
975  return root_count;
976  end
977  `vmm_error(log, "Namespace does not exist.");
978  return 0;
979  endfunction:get_num_roots
980 
981 // ////////////////////////////////////////////
982 // Function: get_nth_root
983 //
984 // Returns the nth root object in the specified namespace. Returns null, if there is no
985 // such root.
986 //
987 //| class D extends vmm_object;
988 //| ...
989 //| endclass
990 //| class E extends vmm_object;
991 //| D d1;
992 //| D d2;
993 //| function new(string name, vmm_object parent=null);
994 //| ...
995 //| d1 = new ("d1");
996 //| d2 = new ("d2");
997 //| endfunction
998 //| endclass
999 //| ...
1000 //| int num_roots;
1001 //| initial begin
1002 //| vmm_object root;
1003 //| E e1 = new ("e1");
1004 //| ...
1005 //| root= E :: get_nth_root(0); //Returns d1
1006 //| ...
1007 //| end
1008  function vmm_object vmm_object::get_nth_root(int n, string space = "");
1009  int num_roots;
1010  int root_count = 0;
1011 
1012  if (space == "") begin
1013  if (n < 0 || n >= roots.size()) return null;
1014  return roots[n];
1015  end
1016 
1017  if (namespace_type.exists(space)) begin
1018  num_roots = get_num_roots(space);
1019  if (n < 0 || n >= num_roots) return null;
1020  foreach (registered_objects[i]) begin
1021  if (registered_objects[i].name_in_namespace[space] != "" &&
1022  registered_objects[i].name_in_namespace[space] != "^" &&
1023  registered_objects[i].get_parent_object(space) == null) root_count++;
1024  if ( n == root_count - 1) return registered_objects[i];
1025  end
1026  return null;
1027  end
1028  `vmm_error(log, "Namespace does not exist.");
1029  return null;
1030  endfunction:get_nth_root
1031 
1033  return vmm_object::log;
1034  endfunction:get_log
1035 
1036 // ////////////////////////////////////////////
1037 // Function: kill_object
1038 //
1039 // Constructs a new instance of this object, optionally specifying another object as
1040 // its parent. The specified named cannot contain any colons (:). Specified argument
1041 // disable_hier_insert indicates whether hierarchical insertion needs to be enabled
1042 // or not.
1043 //
1044 //| class A extends vmm_object;
1045 //| function new (string name, vmm_object parent=null);
1046 //| super.new (parent, name);
1047 //| endfunction
1048 //| endclass
1049  function void vmm_object::kill_object();
1050 
1051  foreach (this.registered_objects[i]) begin
1052  if (this.registered_objects[i] == this) begin
1053  this.registered_objects.delete(i);
1054  break;
1055  end
1056  end
1057 
1058  for (int j = 0; j < this.registered_objects.size(); j++) begin
1059  if (this.is_parent_of(this.registered_objects[j])) this.registered_objects.delete(j--);
1060  end
1061 
1062  if (this._parent == null) begin
1063  foreach (this.roots[i]) begin
1064  if (this.roots[i] == this) begin
1065  this.roots.delete(i);
1066  break;
1067  end
1068  end
1069  end
1070 
1071  if (this._parent != null) begin
1072  foreach (this._parent.children[i]) begin
1073  if (this._parent.children[i] == this) begin
1074  this._parent.children.delete(i);
1075  break;
1076  end
1077  end
1078  this._parent = null;
1079  end
1080 
1081  endfunction:kill_object
1082 
1083 // ////////////////////////////////////////////
1084 // Function: display
1085 //
1086 // Displays the image returned by “type_e” to the standard output. Each
1087 // line of the output will be prefixed with the specified argument prefix.
1088 // If this method conflicts with a previously declared method in a class, which is now based
1089 // on the vmm_object class, it can be removed by defining the ‘VMM_OBJECT_NO_DISPLAY
1090 // symbol at compile-time.
1091 //
1092 //|
1093 //| class trans_data extends vmm_data;
1094 //| byte data;
1095 //| ...
1096 //| endclass
1097 //|
1098 //| initial begin
1099 //| trans_data trans;
1100 //| trans.display("Test Trans: ");
1101 //| end
1102  function void vmm_object::display(string prefix = "");
1103  $display(this.psdisplay(prefix));
1104  endfunction :display
1105 
1106  function string vmm_object::psdisplay(string prefix = "");
1107  $sformat(psdisplay, "%sObject \"%s\"", prefix,this.get_object_hiername());
1108  endfunction:psdisplay
1109 
1110 // ////////////////////////////////////////////
1111 // Function: print_hierarchy
1112 //
1113 // Creates a human-readable description of the content of this object. Each line of the
1114 // image is prefixed with the specified prefix.
1115 // Example
1116 // class D extends vmm_object;
1117 // ...
1118 // function string psdisplay(string prefix = "");
1119 // ...
1120 // endfuntion
1121 // endclass
1122 // ...
1123 // vmm_log log = new ("Test", "main");
1124 // initial begin
1125 // D d1 = new ("d1");
1126 // ...
1127 // `vmm_note (log, d1.psdisplay);
1128 // ...
1129 // end
1130 //
1131 //
1132 //| class D extends vmm_object;
1133 //| ...
1134 //| endclass
1135 //| class E extends vmm_object;
1136 //| D d1;
1137 //| function new(string name, vmm_object parent=null);
1138 //| ...
1139 //| d1 = new ("d1",this);
1140 //| endfunction
1141 //| endclass
1142 //| initial begin
1143 //| E e1 = new ("e1");
1144 //| ...
1145 //| E :: print_hierarchy;
1146 //| ...
1147 //| end
1148 //| psdisplay
1149 //| Creates a description of the object.
1150 //| SystemVerilog
1151  function void vmm_object::print_hierarchy(vmm_object root = null, bit verbose = 0);
1152  if (root == null) begin
1153  foreach (roots[i]) begin
1154  print_hierarchy(roots[i], verbose);
1155  $write("\n");
1156  end
1157  return;
1158  end
1159 
1160  root.print_tree(0, verbose);
1161  endfunction:print_hierarchy
1162 
1163 // ////////////////////////////////////////////
1164 // Function: implicit_phasing
1165 //
1166 // If the is_on argument is false, inhibits the implicit phasing for this object and all
1167 // of its children objects. Used to prevent a large object hierarchy that does not require
1168 // phasing from being needlessly walked by the implicit phaser (for example, a RAL model).
1169 // By default, implicit phasing is enabled.
1170 //
1171 //| class subsys_env extends vmm_subenv;
1172 //| ...
1173 //| endclass
1174 //|
1175 //| class sys_env extends vmm_subenv;
1176 //| subsys_env subenv1;
1177 //| ...
1178 //| function void build();
1179 //| ...
1180 //| subenv1 = new ("subenv1", "subenv1");
1181 //| subenv1.set_parent_object(this);
1182 //| subenv1.implicit_phasing(0);
1183 //| ...
1184 //| endfunction
1185 //| ...
1186 //| endclass
1187  function void vmm_object::implicit_phasing(bit is_on);
1188  this.implicit_phasing_enabled = is_on;
1189  endfunction:implicit_phasing
1190 
1191 // ////////////////////////////////////////////
1192 // Function: is_implicitly_phased
1193 //
1194 // Returns true, if the implicit phasing is enabled for this object.
1195 //
1196 //| class subsys_env extends vmm_subenv;
1197 //| ...
1198 //| endclass
1199 //|
1200 //| class sys_env extends vmm_env;
1201 //| subsys_env subenv1;
1202 //| ...
1203 //| function void build();
1204 //| ...
1205 //| subenv1 = new ("subenv1", "subenv1");
1206 //| subenv1.set_parent_object(this);
1207 //| subenv1.implicit_phasing(0);
1208 //| if(subenv1.is_implicitly_phased)
1209 //| `vmm_error(log, "Implict Phasing for subenv1 not
1210 //| disabled");
1211 //| ...
1212 //| endfunction
1213 //| ...
1214 //| endclass
1216  return this.implicit_phasing_enabled;
1217  endfunction:is_implicitly_phased
1218 
1219 
1220 // ////////////////////////////////////////////
1221 // Function: create_namespace
1222 //
1223 // Defines a namespace with the specified default object inclusion policy. A namespace
1224 // must be previously created using this method, before it can be used or referenced. Returns
1225 // true, if the namespace was successfully created. The empty name space ("") is reserved
1226 // and cannot be defined.
1227 //
1228 //| class A extends vmm_object;
1229 //| function new (string name, vmm_object parent=null);
1230 //| super.new (parent, name);
1231 //| create_namesapce("NS1",
1232 //| IN_BY_DEFAULT);
1233 //| endfunction
1234 //| endclass
1235  function bit vmm_object::create_namespace(string name, namespace_typ_e typ = OUT_BY_DEFAULT);
1236  if (name == "") begin
1237  `vmm_error(log, "Namespace can not be named to empty string.");
1238  return 0;
1239  end
1240 
1241  if (namespace_type.exists(name)) begin
1242  `vmm_warning(log, `vmm_sformatf("Namespace \"%s\" already exists.", name));
1243  return 0;
1244  end
1245 
1246  namespace_type[name] = typ;
1247 
1248  foreach(registered_objects[i]) begin
1249  if (typ == IN_BY_DEFAULT) registered_objects[i].name_in_namespace[name] = registered_objects[i].name;
1250  else if (typ == OUT_BY_DEFAULT) registered_objects[i].name_in_namespace[name] = "";
1251  end
1252  endfunction:create_namespace
1253 
1254 // ////////////////////////////////////////////
1255 // Function: get_namespaces
1256 //
1257 // This method returns all namespaces created by the create_namespace() method that
1258 // belong to a dynamic array of strings as specified by names[].
1259 //
1260 //| initial begin
1261 //| string ns_array[];
1262 //| ...
1263 //| get_namespaces(ns_array);
1264 //| ...
1265 //| end
1266  function void vmm_object::get_namespaces(output string names[]);
1267  string name;
1268  string tmp[];
1269  int i;
1270  bit ok;
1271 
1272  tmp = new[namespace_type.num()];
1273  i = 0;
1274 
1275  ok = namespace_type.first(name);
1276  while (ok) begin
1277  tmp[i++] = name;
1278  ok = namespace_type.next(name);
1279  end
1280  names = new [i] (tmp);
1281  endfunction:get_namespaces
1282 
1283  function bit vmm_object::is_in_namespace(string space);
1284  return ( space == "" || (namespace_type.exists(space) && this.name_in_namespace[space] != "" && this.name_in_namespace[space] != "^") );
1285  endfunction:is_in_namespace
1286 
1288  if (obj == null) begin
1289  `vmm_error(log,"null objects cannot be registered");
1290  return;
1291  end
1292  foreach (registered_objects[i]) begin
1293  if (registered_objects[i] == obj) begin
1294  return;
1295  end
1296  end
1297  registered_objects.push_back(obj);
1298  endfunction:register_object
1299 
1301  foreach (registered_objects[i]) begin
1302  if (registered_objects[i] == obj) begin
1303  registered_objects.delete(i);
1304  return;
1305  end
1306  end
1307  endfunction:unregister_object
1308 
1309 
1310 // ////////////////////////////////////////////
1311 // Function: is_parent_of
1312 //
1313 // Returns true, if the specified object is a parent of this object under specified argument
1314 // space namespace.
1315 //
1316 //| class sub extends vmm_subenv;
1317 //| ...
1318 //| endclass
1319 //|
1320 //| class tb_env extends vmm_env;
1321 //| sub s1 ;
1322 //| ...
1323 //| virtual function void build();
1324 //| super.build();
1325 //| s1 = new ("s1");
1326 //| s1.set_parent(this);
1327 //| if (!this.is_parent_of(s1))
1328 //| `vmm_error(log, "Unable to set parent for s1");
1329 //| ...
1330 //| endfunction
1331 //| endclass
1332  function bit vmm_object::is_parent_of(vmm_object obj, string space = "");
1333  vmm_object next_parent;
1334 
1335  if (obj == null) return 0;
1336  else next_parent = obj;
1337 
1338  while (next_parent != null) begin
1339  next_parent = next_parent.get_parent_object(space);
1340  if (next_parent == this) return 1;
1341  end
1342 
1343  return 0;
1344 
1345  endfunction:is_parent_of
1346 
1347  function void vmm_object::print_tree(int level = 0, bit verbose = 0);
1348  int i;
1349  vmm_object child;
1350  vmm_notify tmp_notify;
1351  vmm_consensus tmp_consensus;
1352 `ifndef NO_VMM12_PHASING
1353  vmm_phase_def tmp_phase_def;
1354 `endif
1355  bit print_it;
1356 
1357  print_it = 1;
1358 
1359  if (verbose == 0) begin
1360  if ( $cast(tmp_notify, this) ||
1361  $cast(tmp_consensus, this) ||
1362 `ifndef NO_VMM12_PHASING
1363  $cast(tmp_phase_def, this) ||
1364 `endif
1365  this.get_object_name() == "" ||
1366  this.get_object_name() == "Anonymous" ) print_it = 0;
1367  end
1368 
1369  if (print_it) begin
1370  if (level > 1) repeat (level-1) $write("| ");
1371  if (level > 0) $write("|--");
1372  $write("[%s]\n", this.get_object_name());
1373  end
1374 
1375  i = 0;
1376  child = this.get_nth_child(i++);
1377  while (child != null) begin
1378  child.print_tree(level+1, verbose);
1379  child = this.get_nth_child(i++);
1380  end
1381 
1382  endfunction:print_tree
1383 
1384 
1385 `endif // VMM_OBJECT__SV

Studio Muzzi
Studio Muzzi
Project: VMM, Revision: 1.2.2b
Copyright (c) 2008-2010 Intelligent Design Verification, 2013 Studio Muzzi.
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
A copy of the license is included here:
fdl.txt
doxygen
Doxygen Version: 1.8.4
Sun Jun 16 2013 05:44:50