1
16
HanySalah
//
2
//-----------------------------------------------------------------------------
3
// Copyright 2007-2011 Mentor Graphics Corporation
4
// Copyright 2007-2011 Cadence Design Systems, Inc.
5
// Copyright 2010 Synopsys, Inc.
6
// Copyright 2013 NVIDIA Corporation
7
// All Rights Reserved Worldwide
8
//
9
// Licensed under the Apache License, Version 2.0 (the
10
// "License"); you may not use this file except in
11
// compliance with the License. You may obtain a copy of
12
// the License at
13
//
14
// http://www.apache.org/licenses/LICENSE-2.0
15
//
16
// Unless required by applicable law or agreed to in
17
// writing, software distributed under the License is
18
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
19
// CONDITIONS OF ANY KIND, either express or implied. See
20
// the License for the specific language governing
21
// permissions and limitations under the License.
22
//-----------------------------------------------------------------------------
23
24
25
typedef class uvm_report_object;
26
typedef class uvm_object_wrapper;
27
typedef class uvm_objection;
28
typedef class uvm_component;
29
30
31
// internal
32
typedef class uvm_status_container;
33
34
//------------------------------------------------------------------------------
35
//
36
// CLASS: uvm_object
37
//
38
// The uvm_object class is the base class for all UVM data and hierarchical
39
// classes. Its primary role is to define a set of methods for such common
40
// operations as , , , , and . Classes
41
// deriving from uvm_object must implement the pure virtual methods such as
42
// and .
43
//
44
//------------------------------------------------------------------------------
45
46
virtual class uvm_object extends uvm_void;
47
48
49
// Function: new
50
//
51
// Creates a new uvm_object with the given instance ~name~. If ~name~ is not
52
// supplied, the object is unnamed.
53
54
extern function new (string name="");
55
56
57
// Group: Seeding
58
59
// Variable: use_uvm_seeding
60
//
61
// This bit enables or disables the UVM seeding mechanism. It globally affects
62
// the operation of the method.
63
//
64
// When enabled, UVM-based objects are seeded based on their type and full
65
// hierarchical name rather than allocation order. This improves random
66
// stability for objects whose instance names are unique across each type.
67
// The class is an example of a type that has a unique
68
// instance name.
69
70
static bit use_uvm_seeding = 1;
71
72
73
// Function: reseed
74
//
75
// Calls ~srandom~ on the object to reseed the object using the UVM seeding
76
// mechanism, which sets the seed based on type name and instance name instead
77
// of based on instance position in a thread.
78
//
79
// If the static variable is set to 0, then reseed() does
80
// not perform any function.
81
82
extern function void reseed ();
83
84
85
// Group: Identification
86
87
// Function: set_name
88
//
89
// Sets the instance name of this object, overwriting any previously
90
// given name.
91
92
extern virtual function void set_name (string name);
93
94
95
// Function: get_name
96
//
97
// Returns the name of the object, as provided by the ~name~ argument in the
98
// constructor or method.
99
100
extern virtual function string get_name ();
101
102
103
// Function: get_full_name
104
//
105
// Returns the full hierarchical name of this object. The default
106
// implementation is the same as , as uvm_objects do not inherently
107
// possess hierarchy.
108
//
109
// Objects possessing hierarchy, such as , override the default
110
// implementation. Other objects might be associated with component hierarchy
111
// but are not themselves components. For example,
112
// classes are typically associated with a . In this
113
// case, it is useful to override get_full_name to return the sequencer's
114
// full name concatenated with the sequence's name. This provides the sequence
115
// a full context, which is useful when debugging.
116
117
extern virtual function string get_full_name ();
118
119
120
// Function: get_inst_id
121
//
122
// Returns the object's unique, numeric instance identifier.
123
124
extern virtual function int get_inst_id ();
125
126
127
// Function: get_inst_count
128
//
129
// Returns the current value of the instance counter, which represents the
130
// total number of uvm_object-based objects that have been allocated in
131
// simulation. The instance counter is used to form a unique numeric instance
132
// identifier.
133
134
extern static function int get_inst_count();
135
136
137
// Function: get_type
138
//
139
// Returns the type-proxy (wrapper) for this object. The 's
140
// type-based override and creation methods take arguments of
141
// . This method, if implemented, can be used as convenient
142
// means of supplying those arguments.
143
//
144
// The default implementation of this method produces an error and returns
145
// ~null~. To enable use of this method, a user's subtype must implement a
146
// version that returns the subtype's wrapper.
147
//
148
// For example:
149
//
150
//| class cmd extends uvm_object;
151
//| typedef uvm_object_registry #(cmd) type_id;
152
//| static function type_id get_type();
153
//| return type_id::get();
154
//| endfunction
155
//| endclass
156
//
157
// Then, to use:
158
//
159
//| factory.set_type_override(cmd::get_type(),subcmd::get_type());
160
//
161
// This function is implemented by the `uvm_*_utils macros, if employed.
162
163
extern static function uvm_object_wrapper get_type ();
164
165
166
// Function: get_object_type
167
//
168
// Returns the type-proxy (wrapper) for this object. The 's
169
// type-based override and creation methods take arguments of
170
// . This method, if implemented, can be used as convenient
171
// means of supplying those arguments. This method is the same as the static
172
// method, but uses an already allocated object to determine
173
// the type-proxy to access (instead of using the static object).
174
//
175
// The default implementation of this method does a factory lookup of the
176
// proxy using the return value from . If the type returned
177
// by is not registered with the factory, then a ~null~
178
// handle is returned.
179
//
180
// For example:
181
//
182
//| class cmd extends uvm_object;
183
//| typedef uvm_object_registry #(cmd) type_id;
184
//| static function type_id get_type();
185
//| return type_id::get();
186
//| endfunction
187
//| virtual function type_id get_object_type();
188
//| return type_id::get();
189
//| endfunction
190
//| endclass
191
//
192
// This function is implemented by the `uvm_*_utils macros, if employed.
193
194
extern virtual function uvm_object_wrapper get_object_type ();
195
196
197
// Function: get_type_name
198
//
199
// This function returns the type name of the object, which is typically the
200
// type identifier enclosed in quotes. It is used for various debugging
201
// functions in the library, and it is used by the factory for creating
202
// objects.
203
//
204
// This function must be defined in every derived class.
205
//
206
// A typical implementation is as follows:
207
//
208
//| class mytype extends uvm_object;
209
//| ...
210
//| const static string type_name = "mytype";
211
//|
212
//| virtual function string get_type_name();
213
//| return type_name;
214
//| endfunction
215
//
216
// We define the ~type_name~ static variable to enable access to the type name
217
// without need of an object of the class, i.e., to enable access via the
218
// scope operator, ~mytype::type_name~.
219
220
virtual function string get_type_name (); return ""; endfunction
221
222
223
// Group: Creation
224
225
// Function: create
226
//
227
// The ~create~ method allocates a new object of the same type as this object
228
// and returns it via a base uvm_object handle. Every class deriving from
229
// uvm_object, directly or indirectly, must implement the create method.
230
//
231
// A typical implementation is as follows:
232
//
233
//| class mytype extends uvm_object;
234
//| ...
235
//| virtual function uvm_object create(string name="");
236
//| mytype t = new(name);
237
//| return t;
238
//| endfunction
239
240
virtual function uvm_object create (string name=""); return null; endfunction
241
242
243
// Function: clone
244
//
245
// The ~clone~ method creates and returns an exact copy of this object.
246
//
247
// The default implementation calls followed by . As clone is
248
// virtual, derived classes may override this implementation if desired.
249
250
extern virtual function uvm_object clone ();
251
252
253
// Group: Printing
254
255
// Function: print
256
//
257
// The ~print~ method deep-prints this object's properties in a format and
258
// manner governed by the given ~printer~ argument; if the ~printer~ argument
259
// is not provided, the global is used. See
260
// for more information on printer output formatting. See also
261
// , , and for details
262
// on the pre-defined printer "policies," or formatters, provided by the UVM.
263
//
264
// The ~print~ method is not virtual and must not be overloaded. To include
265
// custom information in the ~print~ and operations, derived classes
266
// must override the method and use the provided printer policy
267
// class to format the output.
268
269
extern function void print (uvm_printer printer=null);
270
271
272
// Function: sprint
273
//
274
// The ~sprint~ method works just like the method, except the output
275
// is returned in a string rather than displayed.
276
//
277
// The ~sprint~ method is not virtual and must not be overloaded. To include
278
// additional fields in the and ~sprint~ operation, derived classes
279
// must override the method and use the provided printer policy
280
// class to format the output. The printer policy will manage all string
281
// concatenations and provide the string to ~sprint~ to return to the caller.
282
283
extern function string sprint (uvm_printer printer=null);
284
285
286
// Function: do_print
287
//
288
// The ~do_print~ method is the user-definable hook called by and
289
// that allows users to customize what gets printed or sprinted
290
// beyond the field information provided by the `uvm_field_* macros,
291
// .
292
//
293
// The ~printer~ argument is the policy object that governs the format and
294
// content of the output. To ensure correct and operation,
295
// and to ensure a consistent output format, the ~printer~ must be used
296
// by all implementations. That is, instead of using ~$display~ or
297
// string concatenations directly, a ~do_print~ implementation must call
298
// through the ~printer's~ API to add information to be printed or sprinted.
299
//
300
// An example implementation of ~do_print~ is as follows:
301
//
302
//| class mytype extends uvm_object;
303
//| data_obj data;
304
//| int f1;
305
//| virtual function void do_print (uvm_printer printer);
306
//| super.do_print(printer);
307
//| printer.print_field_int("f1", f1, $bits(f1), UVM_DEC);
308
//| printer.print_object("data", data);
309
//| endfunction
310
//
311
// Then, to print and sprint the object, you could write:
312
//
313
//| mytype t = new;
314
//| t.print();
315
//| uvm_report_info("Received",t.sprint());
316
//
317
// See for information about the printer API.
318
319
extern virtual function void do_print (uvm_printer printer);
320
321
322
// Function: convert2string
323
//
324
// This virtual function is a user-definable hook, called directly by the
325
// user, that allows users to provide object information in the form of
326
// a string. Unlike , there is no requirement to use a
327
// policy object. As such, the format and content of the output is fully
328
// customizable, which may be suitable for applications not requiring the
329
// consistent formatting offered by the //
330
// API.
331
//
332
// Fields declared in macros (`uvm_field_*), if used, will
333
// not automatically appear in calls to convert2string.
334
//
335
// An example implementation of convert2string follows.
336
//
337
//| class base extends uvm_object;
338
//| string field = "foo";
339
//| virtual function string convert2string();
340
//| convert2string = {"base_field=",field};
341
//| endfunction
342
//| endclass
343
//|
344
//| class obj2 extends uvm_object;
345
//| string field = "bar";
346
//| virtual function string convert2string();
347
//| convert2string = {"child_field=",field};
348
//| endfunction
349
//| endclass
350
//|
351
//| class obj extends base;
352
//| int addr = 'h123;
353
//| int data = 'h456;
354
//| bit write = 1;
355
//| obj2 child = new;
356
//| virtual function string convert2string();
357
//| convert2string = {super.convert2string(),
358
//| $sformatf(" write=%0d addr=%8h data=%8h ",write,addr,data),
359
//| child.convert2string()};
360
//| endfunction
361
//| endclass
362
//
363
// Then, to display an object, you could write:
364
//
365
//| obj o = new;
366
//| uvm_report_info("BusMaster",{"Sending:\n ",o.convert2string()});
367
//
368
// The output will look similar to:
369
//
370
//| UVM_INFO @ 0: reporter [BusMaster] Sending:
371
//| base_field=foo write=1 addr=00000123 data=00000456 child_field=bar
372
373
374
extern virtual function string convert2string();
375
376
377
// Group: Recording
378
379
// Function: record
380
//
381
// The ~record~ method deep-records this object's properties according to an
382
// optional ~recorder~ policy. The method is not virtual and must not be
383
// overloaded. To include additional fields in the record operation, derived
384
// classes should override the method.
385
//
386
// The optional ~recorder~ argument specifies the recording policy, which
387
// governs how recording takes place. See
388
// for information.
389
//
390
// A simulator's recording mechanism is vendor-specific. By providing access
391
// via a common interface, the uvm_recorder policy provides vendor-independent
392
// access to a simulator's recording capabilities.
393
394
extern function void record (uvm_recorder recorder=null);
395
396
397
// Function: do_record
398
//
399
// The ~do_record~ method is the user-definable hook called by the
400
// method. A derived class should override this method to include its fields
401
// in a record operation.
402
//
403
// The ~recorder~ argument is policy object for recording this object. A
404
// do_record implementation should call the appropriate recorder methods for
405
// each of its fields. Vendor-specific recording implementations are
406
// encapsulated in the ~recorder~ policy, thereby insulating user-code from
407
// vendor-specific behavior. See for more information.
408
//
409
// A typical implementation is as follows:
410
//
411
//| class mytype extends uvm_object;
412
//| data_obj data;
413
//| int f1;
414
//| function void do_record (uvm_recorder recorder);
415
//| recorder.record_field("f1", f1, $bits(f1), UVM_DEC);
416
//| recorder.record_object("data", data);
417
//| endfunction
418
419
extern virtual function void do_record (uvm_recorder recorder);
420
421
422
// Group: Copying
423
424
// Function: copy
425
//
426
// The copy makes this object a copy of the specified object.
427
//
428
// The ~copy~ method is not virtual and should not be overloaded in derived
429
// classes. To copy the fields of a derived class, that class should override
430
// the method.
431
432
extern function void copy (uvm_object rhs);
433
434
435
// Function: do_copy
436
//
437
// The ~do_copy~ method is the user-definable hook called by the method.
438
// A derived class should override this method to include its fields in a
439
// operation.
440
//
441
// A typical implementation is as follows:
442
//
443
//| class mytype extends uvm_object;
444
//| ...
445
//| int f1;
446
//| function void do_copy (uvm_object rhs);
447
//| mytype rhs_;
448
//| super.do_copy(rhs);
449
//| $cast(rhs_,rhs);
450
//| field_1 = rhs_.field_1;
451
//| endfunction
452
//
453
// The implementation must call ~super.do_copy~, and it must $cast the rhs
454
// argument to the derived type before copying.
455
456
extern virtual function void do_copy (uvm_object rhs);
457
458
459
// Group: Comparing
460
461
// Function: compare
462
//
463
// Deep compares members of this data object with those of the object provided
464
// in the ~rhs~ (right-hand side) argument, returning 1 on a match, 0 otherwise.
465
//
466
// The ~compare~ method is not virtual and should not be overloaded in derived
467
// classes. To compare the fields of a derived class, that class should
468
// override the method.
469
//
470
// The optional ~comparer~ argument specifies the comparison policy. It allows
471
// you to control some aspects of the comparison operation. It also stores the
472
// results of the comparison, such as field-by-field miscompare information
473
// and the total number of miscompares. If a compare policy is not provided,
474
// then the global ~uvm_default_comparer~ policy is used. See
475
// for more information.
476
477
extern function bit compare (uvm_object rhs, uvm_comparer comparer=null);
478
479
480
// Function: do_compare
481
//
482
// The ~do_compare~ method is the user-definable hook called by the
483
// method. A derived class should override this method to include its fields
484
// in a compare operation. It should return 1 if the comparison succeeds, 0
485
// otherwise.
486
//
487
// A typical implementation is as follows:
488
//
489
//| class mytype extends uvm_object;
490
//| ...
491
//| int f1;
492
//| virtual function bit do_compare (uvm_object rhs,uvm_comparer comparer);
493
//| mytype rhs_;
494
//| do_compare = super.do_compare(rhs,comparer);
495
//| $cast(rhs_,rhs);
496
//| do_compare &= comparer.compare_field_int("f1", f1, rhs_.f1);
497
//| endfunction
498
//
499
// A derived class implementation must call ~super.do_compare()~ to ensure its
500
// base class' properties, if any, are included in the comparison. Also, the
501
// rhs argument is provided as a generic uvm_object. Thus, you must ~$cast~ it
502
// to the type of this object before comparing.
503
//
504
// The actual comparison should be implemented using the uvm_comparer object
505
// rather than direct field-by-field comparison. This enables users of your
506
// class to customize how comparisons are performed and how much miscompare
507
// information is collected. See uvm_comparer for more details.
508
509
extern virtual function bit do_compare (uvm_object rhs,
510
uvm_comparer comparer);
511
512
// Group: Packing
513
514
// Function: pack
515
516
extern function int pack (ref bit bitstream[],
517
input uvm_packer packer=null);
518
519
// Function: pack_bytes
520
521
extern function int pack_bytes (ref byte unsigned bytestream[],
522
input uvm_packer packer=null);
523
524
// Function: pack_ints
525
//
526
// The pack methods bitwise-concatenate this object's properties into an array
527
// of bits, bytes, or ints. The methods are not virtual and must not be
528
// overloaded. To include additional fields in the pack operation, derived
529
// classes should override the method.
530
//
531
// The optional ~packer~ argument specifies the packing policy, which governs
532
// the packing operation. If a packer policy is not provided, the global
533
// policy is used. See for more information.
534
//
535
// The return value is the total number of bits packed into the given array.
536
// Use the array's built-in ~size~ method to get the number of bytes or ints
537
// consumed during the packing process.
538
539
extern function int pack_ints (ref int unsigned intstream[],
540
input uvm_packer packer=null);
541
542
543
// Function: do_pack
544
//
545
// The ~do_pack~ method is the user-definable hook called by the methods.
546
// A derived class should override this method to include its fields in a pack
547
// operation.
548
//
549
// The ~packer~ argument is the policy object for packing. The policy object
550
// should be used to pack objects.
551
//
552
// A typical example of an object packing itself is as follows
553
//
554
//| class mysubtype extends mysupertype;
555
//| ...
556
//| shortint myshort;
557
//| obj_type myobj;
558
//| byte myarray[];
559
//| ...
560
//| function void do_pack (uvm_packer packer);
561
//| super.do_pack(packer); // pack mysupertype properties
562
//| packer.pack_field_int(myarray.size(), 32);
563
//| foreach (myarray)
564
//| packer.pack_field_int(myarray[index], 8);
565
//| packer.pack_field_int(myshort, $bits(myshort));
566
//| packer.pack_object(myobj);
567
//| endfunction
568
//
569
// The implementation must call ~super.do_pack~ so that base class properties
570
// are packed as well.
571
//
572
// If your object contains dynamic data (object, string, queue, dynamic array,
573
// or associative array), and you intend to unpack into an equivalent data
574
// structure when unpacking, you must include meta-information about the
575
// dynamic data when packing as follows.
576
//
577
// - For queues, dynamic arrays, or associative arrays, pack the number of
578
// elements in the array in the 32 bits immediately before packing
579
// individual elements, as shown above.
580
//
581
// - For string data types, append a zero byte after packing the string
582
// contents.
583
//
584
// - For objects, pack 4 bits immediately before packing the object. For ~null~
585
// objects, pack 4'b0000. For non-~null~ objects, pack 4'b0001.
586
//
587
// When the `uvm_field_* macros are used,
588
// ,
589
// the above meta information is included provided the
590
// variable is set for the packer.
591
//
592
// Packing order does not need to match declaration order. However, unpacking
593
// order must match packing order.
594
595
extern virtual function void do_pack (uvm_packer packer);
596
597
598
// Group: Unpacking
599
600
// Function: unpack
601
602
extern function int unpack (ref bit bitstream[],
603
input uvm_packer packer=null);
604
605
// Function: unpack_bytes
606
607
extern function int unpack_bytes (ref byte unsigned bytestream[],
608
input uvm_packer packer=null);
609
610
// Function: unpack_ints
611
//
612
// The unpack methods extract property values from an array of bits, bytes, or
613
// ints. The method of unpacking ~must~ exactly correspond to the method of
614
// packing. This is assured if (a) the same ~packer~ policy is used to pack
615
// and unpack, and (b) the order of unpacking is the same as the order of
616
// packing used to create the input array.
617
//
618
// The unpack methods are fixed (non-virtual) entry points that are directly
619
// callable by the user. To include additional fields in the
620
// operation, derived classes should override the method.
621
//
622
// The optional ~packer~ argument specifies the packing policy, which governs
623
// both the pack and unpack operation. If a packer policy is not provided,
624
// then the global ~uvm_default_packer~ policy is used. See uvm_packer for
625
// more information.
626
//
627
// The return value is the actual number of bits unpacked from the given array.
628
629
extern function int unpack_ints (ref int unsigned intstream[],
630
input uvm_packer packer=null);
631
632
633
// Function: do_unpack
634
//
635
// The ~do_unpack~ method is the user-definable hook called by the
636
// method. A derived class should override this method to include its fields
637
// in an unpack operation.
638
//
639
// The ~packer~ argument is the policy object for both packing and unpacking.
640
// It must be the same packer used to pack the object into bits. Also,
641
// do_unpack must unpack fields in the same order in which they were packed.
642
// See for more information.
643
//
644
// The following implementation corresponds to the example given in do_pack.
645
//
646
//| function void do_unpack (uvm_packer packer);
647
//| int sz;
648
//| super.do_unpack(packer); // unpack super's properties
649
//| sz = packer.unpack_field_int(myarray.size(), 32);
650
//| myarray.delete();
651
//| for(int index=0; index
652
//| myarray[index] = packer.unpack_field_int(8);
653
//| myshort = packer.unpack_field_int($bits(myshort));
654
//| packer.unpack_object(myobj);
655
//| endfunction
656
//
657
// If your object contains dynamic data (object, string, queue, dynamic array,
658
// or associative array), and you intend to into an equivalent data
659
// structure, you must have included meta-information about the dynamic data
660
// when it was packed.
661
//
662
// - For queues, dynamic arrays, or associative arrays, unpack the number of
663
// elements in the array from the 32 bits immediately before unpacking
664
// individual elements, as shown above.
665
//
666
// - For string data types, unpack into the new string until a ~null~ byte is
667
// encountered.
668
//
669
// - For objects, unpack 4 bits into a byte or int variable. If the value
670
// is 0, the target object should be set to ~null~ and unpacking continues to
671
// the next property, if any. If the least significant bit is 1, then the
672
// target object should be allocated and its properties unpacked.
673
674
extern virtual function void do_unpack (uvm_packer packer);
675
676
677
// Group: Configuration
678
679
// Function: set_int_local
680
681
extern virtual function void set_int_local (string field_name,
682
uvm_bitstream_t value,
683
bit recurse=1);
684
685
// Function: set_string_local
686
687
extern virtual function void set_string_local (string field_name,
688
string value,
689
bit recurse=1);
690
691
// Function: set_object_local
692
//
693
// These methods provide write access to integral, string, and
694
// uvm_object-based properties indexed by a ~field_name~ string. The object
695
// designer choose which, if any, properties will be accessible, and overrides
696
// the appropriate methods depending on the properties' types. For objects,
697
// the optional ~clone~ argument specifies whether to clone the ~value~
698
// argument before assignment.
699
//
700
// The global function is used to match the field names, so
701
// ~field_name~ may contain wildcards.
702
//
703
// An example implementation of all three methods is as follows.
704
//
705
//| class mytype extends uvm_object;
706
//|
707
//| local int myint;
708
//| local byte mybyte;
709
//| local shortint myshort; // no access
710
//| local string mystring;
711
//| local obj_type myobj;
712
//|
713
//| // provide access to integral properties
714
//| function void set_int_local(string field_name, uvm_bitstream_t value);
715
//| if (uvm_is_match (field_name, "myint"))
716
//| myint = value;
717
//| else if (uvm_is_match (field_name, "mybyte"))
718
//| mybyte = value;
719
//| endfunction
720
//|
721
//| // provide access to string properties
722
//| function void set_string_local(string field_name, string value);
723
//| if (uvm_is_match (field_name, "mystring"))
724
//| mystring = value;
725
//| endfunction
726
//|
727
//| // provide access to sub-objects
728
//| function void set_object_local(string field_name, uvm_object value,
729
//| bit clone=1);
730
//| if (uvm_is_match (field_name, "myobj")) begin
731
//| if (value != null) begin
732
//| obj_type tmp;
733
//| // if provided value is not correct type, produce error
734
//| if (!$cast(tmp, value) )
735
//| /* error */
736
//| else begin
737
//| if(clone)
738
//| $cast(myobj, tmp.clone());
739
//| else
740
//| myobj = tmp;
741
//| end
742
//| end
743
//| else
744
//| myobj = null; // value is null, so simply assign null to myobj
745
//| end
746
//| endfunction
747
//| ...
748
//
749
// Although the object designer implements these methods to provide outside
750
// access to one or more properties, they are intended for internal use (e.g.,
751
// for command-line debugging and auto-configuration) and should not be called
752
// directly by the user.
753
754
extern virtual function void set_object_local (string field_name,
755
uvm_object value,
756
bit clone=1,
757
bit recurse=1);
758
759
760
761
//---------------------------------------------------------------------------
762
// **** Internal Methods and Properties ***
763
// Do not use directly
764
//---------------------------------------------------------------------------
765
766
extern local function void m_pack (inout uvm_packer packer);
767
extern local function void m_unpack_pre (inout uvm_packer packer);
768
extern local function void m_unpack_post (uvm_packer packer);
769
770
// The print_matches bit causes an informative message to be printed
771
// when a field is set using one of the set methods.
772
773
local string m_leaf_name;
774
775
local int m_inst_id;
776
static protected int m_inst_count;
777
778
static /*protected*/ uvm_status_container __m_uvm_status_container = new;
779
780
extern virtual function void __m_uvm_field_automation (uvm_object tmp_data__,
781
int what__,
782
string str__);
783
784
extern protected virtual function uvm_report_object m_get_report_object();
785
786
// the lookup table
787
local static uvm_object uvm_global_copy_map[uvm_object];
788
endclass
789
790
//------------------------------------------------------------------------------
791
// IMPLEMENTATION
792
//------------------------------------------------------------------------------
793
794
// new
795
// ---
796
797
function uvm_object::new (string name="");
798
799
m_inst_id = m_inst_count++;
800
m_leaf_name = name;
801
endfunction
802
803
804
// reseed
805
// ------
806
807
function void uvm_object::reseed ();
808
if(use_uvm_seeding)
809
this.srandom(uvm_create_random_seed(get_type_name(), get_full_name()));
810
endfunction
811
812
813
// get type
814
// --------
815
816
function uvm_object_wrapper uvm_object::get_type();
817
uvm_report_error("NOTYPID", "get_type not implemented in derived class.", UVM_NONE);
818
return null;
819
endfunction
820
821
822
// get inst_id
823
// -----------
824
825
function int uvm_object::get_inst_id();
826
return m_inst_id;
827
endfunction
828
829
830
// get_object_type
831
// ---------------
832
833
function uvm_object_wrapper uvm_object::get_object_type();
834
uvm_coreservice_t cs = uvm_coreservice_t::get();
835
uvm_factory factory=cs.get_factory();
836
if(get_type_name() == "") return null;
837
return factory.find_wrapper_by_name(get_type_name());
838
endfunction
839
840
841
// get inst_count
842
// --------------
843
844
function int uvm_object::get_inst_count();
845
return m_inst_count;
846
endfunction
847
848
849
// get_name
850
// --------
851
852
function string uvm_object::get_name ();
853
return m_leaf_name;
854
endfunction
855
856
857
// get_full_name
858
// -------------
859
860
function string uvm_object::get_full_name ();
861
return get_name();
862
endfunction
863
864
865
// set_name
866
// --------
867
868
function void uvm_object::set_name (string name);
869
m_leaf_name = name;
870
endfunction
871
872
873
// print
874
// -----
875
876
function void uvm_object::print(uvm_printer printer=null);
877
if (printer==null)
878
printer = uvm_default_printer;
879
if (printer == null)
880
`uvm_error("NULLPRINTER","uvm_default_printer is null")
881
$fwrite(printer.knobs.mcd,sprint(printer));
882
endfunction
883
884
885
// sprint
886
// ------
887
888
function string uvm_object::sprint(uvm_printer printer=null);
889
bit p;
890
891
if(printer==null)
892
printer = uvm_default_printer;
893
894
// not at top-level, must be recursing into sub-object
895
if(!printer.istop()) begin
896
__m_uvm_status_container.printer = printer;
897
__m_uvm_field_automation(null, UVM_PRINT, "");
898
do_print(printer);
899
return "";
900
end
901
902
printer.print_object(get_name(), this);
903
// backward compat with sprint knob: if used,
904
// print that, do not call emit()
905
if (printer.m_string != "")
906
return printer.m_string;
907
908
return printer.emit();
909
910
endfunction
911
912
913
// convert2string (virtual)
914
// --------------
915
916
function string uvm_object::convert2string();
917
return "";
918
endfunction
919
920
921
// set_int_local
922
// -------------
923
924
function void uvm_object::set_int_local (string field_name,
925
uvm_bitstream_t value,
926
bit recurse=1);
927
__m_uvm_status_container.cycle_check.delete();
928
__m_uvm_status_container.m_uvm_cycle_scopes.delete();
929
930
this.__m_uvm_status_container.status = 0;
931
this.__m_uvm_status_container.bitstream = value;
932
933
__m_uvm_field_automation(null, UVM_SETINT, field_name);
934
935
if(__m_uvm_status_container.warning && !this.__m_uvm_status_container.status) begin
936
uvm_report_error("NOMTC", $sformatf("did not find a match for field %s", field_name),UVM_NONE);
937
end
938
__m_uvm_status_container.cycle_check.delete();
939
endfunction
940
941
942
// set_object_local
943
// ----------------
944
945
function void uvm_object::set_object_local (string field_name,
946
uvm_object value,
947
bit clone=1,
948
bit recurse=1);
949
uvm_object cc;
950
__m_uvm_status_container.cycle_check.delete();
951
__m_uvm_status_container.m_uvm_cycle_scopes.delete();
952
953
if(clone && (value!=null)) begin
954
cc = value.clone();
955
if(cc != null) cc.set_name(field_name);
956
value = cc;
957
end
958
959
this.__m_uvm_status_container.status = 0;
960
this.__m_uvm_status_container.object = value;
961
__m_uvm_status_container.clone = clone;
962
963
__m_uvm_field_automation(null, UVM_SETOBJ, field_name);
964
965
if(__m_uvm_status_container.warning && !this.__m_uvm_status_container.status) begin
966
uvm_report_error("NOMTC", $sformatf("did not find a match for field %s", field_name), UVM_NONE);
967
end
968
__m_uvm_status_container.cycle_check.delete();
969
970
endfunction
971
972
973
// set_string_local
974
// ----------------
975
function void uvm_object::set_string_local (string field_name,
976
string value,
977
bit recurse=1);
978
979
__m_uvm_status_container.cycle_check.delete();
980
__m_uvm_status_container.m_uvm_cycle_scopes.delete();
981
982
this.__m_uvm_status_container.status = 0;
983
this.__m_uvm_status_container.stringv = value;
984
985
__m_uvm_field_automation(null, UVM_SETSTR, field_name);
986
987
if(__m_uvm_status_container.warning && !this.__m_uvm_status_container.status) begin
988
uvm_report_error("NOMTC", $sformatf("did not find a match for field %s (@%0d)", field_name, this.get_inst_id()), UVM_NONE);
989
end
990
__m_uvm_status_container.cycle_check.delete();
991
endfunction
992
993
994
// clone
995
// -----
996
997
function uvm_object uvm_object::clone();
998
uvm_object tmp;
999
tmp = this.create(get_name());
1000
if(tmp == null)
1001
uvm_report_warning("CRFLD", $sformatf("The create method failed for %s, object cannot be cloned", get_name()), UVM_NONE);
1002
else
1003
tmp.copy(this);
1004
return(tmp);
1005
endfunction
1006
1007
1008
// copy
1009
// ----
1010
1011
function void uvm_object::copy (uvm_object rhs);
1012
//For cycle checking
1013
static int depth;
1014
if((rhs !=null) && uvm_global_copy_map.exists(rhs)) begin
1015
return;
1016
end
1017
1018
if(rhs==null) begin
1019
uvm_report_warning("NULLCP", "A null object was supplied to copy; copy is ignored", UVM_NONE);
1020
return;
1021
end
1022
1023
uvm_global_copy_map[rhs]= this;
1024
++depth;
1025
1026
__m_uvm_field_automation(rhs, UVM_COPY, "");
1027
do_copy(rhs);
1028
1029
--depth;
1030
if(depth==0) begin
1031
uvm_global_copy_map.delete();
1032
end
1033
endfunction
1034
1035
1036
// do_copy
1037
// -------
1038
1039
function void uvm_object::do_copy (uvm_object rhs);
1040
return;
1041
endfunction
1042
1043
1044
// compare
1045
// -------
1046
1047
function bit uvm_object::compare (uvm_object rhs,
1048
uvm_comparer comparer=null);
1049
bit t, dc;
1050
static int style;
1051
bit done;
1052
done = 0;
1053
if(comparer != null)
1054
__m_uvm_status_container.comparer = comparer;
1055
else
1056
__m_uvm_status_container.comparer = uvm_default_comparer;
1057
comparer = __m_uvm_status_container.comparer;
1058
1059
if(!__m_uvm_status_container.scope.depth()) begin
1060
comparer.compare_map.delete();
1061
comparer.result = 0;
1062
comparer.miscompares = "";
1063
comparer.scope = __m_uvm_status_container.scope;
1064
if(get_name() == "")
1065
__m_uvm_status_container.scope.down("");
1066
else
1067
__m_uvm_status_container.scope.down(this.get_name());
1068
end
1069
if(!done && (rhs == null)) begin
1070
if(__m_uvm_status_container.scope.depth()) begin
1071
comparer.print_msg_object(this, rhs);
1072
end
1073
else begin
1074
comparer.print_msg_object(this, rhs);
1075
uvm_report_info("MISCMP",
1076
$sformatf("%0d Miscompare(s) for object %s@%0d vs. null",
1077
comparer.result,
1078
__m_uvm_status_container.scope.get(),
1079
this.get_inst_id()),
1080
__m_uvm_status_container.comparer.verbosity);
1081
done = 1;
1082
end
1083
end
1084
1085
if(!done && comparer.compare_map.exists(rhs)) begin
1086
if(comparer.compare_map[rhs] != this) begin
1087
comparer.print_msg_object(this, comparer.compare_map[rhs]);
1088
end
1089
done = 1; //don't do any more work after this case, but do cleanup
1090
end
1091
1092
if(!done && comparer.check_type && (rhs != null) && (get_type_name() != rhs.get_type_name())) begin
1093
__m_uvm_status_container.stringv = { "lhs type = \"", get_type_name(),
1094
"\" : rhs type = \"", rhs.get_type_name(), "\""};
1095
comparer.print_msg(__m_uvm_status_container.stringv);
1096
end
1097
1098
if(!done) begin
1099
comparer.compare_map[rhs]= this;
1100
__m_uvm_field_automation(rhs, UVM_COMPARE, "");
1101
dc = do_compare(rhs, comparer);
1102
end
1103
1104
if(__m_uvm_status_container.scope.depth()==1) begin
1105
__m_uvm_status_container.scope.up();
1106
end
1107
1108
if(rhs != null)
1109
comparer.print_rollup(this, rhs);
1110
return (comparer.result == 0 && dc == 1);
1111
endfunction
1112
1113
1114
// do_compare
1115
// ----------
1116
1117
function bit uvm_object::do_compare (uvm_object rhs,
1118
uvm_comparer comparer);
1119
return 1;
1120
endfunction
1121
1122
1123
// __m_uvm_field_automation
1124
// ------------------
1125
1126
function void uvm_object::__m_uvm_field_automation (uvm_object tmp_data__,
1127
int what__,
1128
string str__ );
1129
return;
1130
endfunction
1131
1132
1133
1134
// do_print (virtual override)
1135
// ------------
1136
1137
function void uvm_object::do_print(uvm_printer printer);
1138
return;
1139
endfunction
1140
1141
1142
// m_pack
1143
// ------
1144
1145
function void uvm_object::m_pack (inout uvm_packer packer);
1146
1147
if(packer!=null)
1148
__m_uvm_status_container.packer = packer;
1149
else
1150
__m_uvm_status_container.packer = uvm_default_packer;
1151
packer = __m_uvm_status_container.packer;
1152
1153
packer.reset();
1154
packer.scope.down(get_name());
1155
1156
__m_uvm_field_automation(null, UVM_PACK, "");
1157
do_pack(packer);
1158
1159
packer.set_packed_size();
1160
1161
packer.scope.up();
1162
1163
endfunction
1164
1165
1166
// pack
1167
// ----
1168
1169
function int uvm_object::pack (ref bit bitstream [],
1170
input uvm_packer packer =null );
1171
m_pack(packer);
1172
packer.get_bits(bitstream);
1173
return packer.get_packed_size();
1174
endfunction
1175
1176
// pack_bytes
1177
// ----------
1178
1179
function int uvm_object::pack_bytes (ref byte unsigned bytestream [],
1180
input uvm_packer packer=null );
1181
m_pack(packer);
1182
packer.get_bytes(bytestream);
1183
return packer.get_packed_size();
1184
endfunction
1185
1186
1187
// pack_ints
1188
// ---------
1189
1190
function int uvm_object::pack_ints (ref int unsigned intstream [],
1191
input uvm_packer packer=null );
1192
m_pack(packer);
1193
packer.get_ints(intstream);
1194
return packer.get_packed_size();
1195
endfunction
1196
1197
1198
// do_pack
1199
// -------
1200
1201
function void uvm_object::do_pack (uvm_packer packer );
1202
return;
1203
endfunction
1204
1205
1206
// m_unpack_pre
1207
// ------------
1208
1209
function void uvm_object::m_unpack_pre (inout uvm_packer packer);
1210
if(packer!=null)
1211
__m_uvm_status_container.packer = packer;
1212
else
1213
__m_uvm_status_container.packer = uvm_default_packer;
1214
packer = __m_uvm_status_container.packer;
1215
packer.reset();
1216
endfunction
1217
1218
1219
// m_unpack_post
1220
// -------------
1221
1222
function void uvm_object::m_unpack_post (uvm_packer packer);
1223
1224
int provided_size;
1225
1226
provided_size = packer.get_packed_size();
1227
1228
//Put this object into the hierarchy
1229
packer.scope.down(get_name());
1230
1231
__m_uvm_field_automation(null, UVM_UNPACK, "");
1232
1233
do_unpack(packer);
1234
1235
//Scope back up before leaving
1236
packer.scope.up();
1237
1238
if(packer.get_packed_size() != provided_size) begin
1239
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);
1240
end
1241
1242
endfunction
1243
1244
1245
// unpack
1246
// ------
1247
1248
function int uvm_object::unpack (ref bit bitstream [],
1249
input uvm_packer packer=null);
1250
m_unpack_pre(packer);
1251
packer.put_bits(bitstream);
1252
m_unpack_post(packer);
1253
packer.set_packed_size();
1254
return packer.get_packed_size();
1255
endfunction
1256
1257
1258
// unpack_bytes
1259
// ------------
1260
1261
function int uvm_object::unpack_bytes (ref byte unsigned bytestream [],
1262
input uvm_packer packer=null);
1263
m_unpack_pre(packer);
1264
packer.put_bytes(bytestream);
1265
m_unpack_post(packer);
1266
packer.set_packed_size();
1267
return packer.get_packed_size();
1268
endfunction
1269
1270
1271
// unpack_ints
1272
// -----------
1273
1274
function int uvm_object::unpack_ints (ref int unsigned intstream [],
1275
input uvm_packer packer=null);
1276
m_unpack_pre(packer);
1277
packer.put_ints(intstream);
1278
m_unpack_post(packer);
1279
packer.set_packed_size();
1280
return packer.get_packed_size();
1281
endfunction
1282
1283
1284
// do_unpack
1285
// ---------
1286
1287
function void uvm_object::do_unpack (uvm_packer packer);
1288
return;
1289
endfunction
1290
1291
1292
// record
1293
// ------
1294
1295
function void uvm_object::record (uvm_recorder recorder=null);
1296
1297
if(recorder == null)
1298
return;
1299
// recorder = uvm_default_recorder;
1300
1301
//if(!recorder.tr_handle) return;
1302
1303
__m_uvm_status_container.recorder = recorder;
1304
recorder.recording_depth++;
1305
__m_uvm_field_automation(null, UVM_RECORD, "");
1306
do_record(recorder);
1307
1308
recorder.recording_depth--;
1309
1310
//if(recorder.recording_depth==0) begin
1311
// recorder.tr_handle = 0;
1312
//end
1313
endfunction
1314
1315
1316
// do_record (virtual)
1317
// ---------
1318
1319
function void uvm_object::do_record (uvm_recorder recorder);
1320
return;
1321
endfunction
1322
1323
1324
// m_get_report_object
1325
// -------------------
1326
1327
function uvm_report_object uvm_object::m_get_report_object();
1328
return null;
1329
endfunction
1330