OpenCores
URL https://opencores.org/ocsvn/uart2bus_testbench/uart2bus_testbench/trunk

Subversion Repositories uart2bus_testbench

[/] [uart2bus_testbench/] [trunk/] [tb/] [uvm_src/] [base/] [uvm_resource.svh] - Blame information for rev 16

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 16 HanySalah
//----------------------------------------------------------------------
2
//   Copyright 2011 Cypress Semiconductor
3
//   Copyright 2010 Mentor Graphics Corporation
4
//   Copyright 2011 Cadence Design Systems, Inc.
5
//   All Rights Reserved Worldwide
6
//
7
//   Licensed under the Apache License, Version 2.0 (the
8
//   "License"); you may not use this file except in
9
//   compliance with the License.  You may obtain a copy of
10
//   the License at
11
//
12
//       http://www.apache.org/licenses/LICENSE-2.0
13
//
14
//   Unless required by applicable law or agreed to in
15
//   writing, software distributed under the License is
16
//   distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
17
//   CONDITIONS OF ANY KIND, either express or implied.  See
18
//   the License for the specific language governing
19
//   permissions and limitations under the License.
20
//----------------------------------------------------------------------
21
 
22
//----------------------------------------------------------------------
23
// Title: Resources
24
//
25
// Topic: Intro
26
//
27
// A resource is a parameterized container that holds arbitrary data.
28
// Resources can be used to configure components, supply data to
29
// sequences, or enable sharing of information across disparate parts of
30
// a testbench.  They are stored using scoping information so their
31
// visibility can be constrained to certain parts of the testbench.
32
// Resource containers can hold any type of data, constrained only by
33
// the data types available in SystemVerilog.  Resources can contain
34
// scalar objects, class handles, queues, lists, or even virtual
35
// interfaces.
36
//
37
// Resources are stored in a resource database so that each resource can
38
// be retrieved by name or by type. The database has both a name table
39
// and a type table and each resource is entered into both. The database
40
// is globally accessible.
41
//
42
// Each resource has a set of scopes over which it is visible.  The set
43
// of scopes is represented as a regular expression.  When a resource is
44
// looked up the scope of the entity doing the looking up is supplied to
45
// the lookup function.  This is called the ~current scope~.  If the
46
// current scope is in the set of scopes over which a resource is
47
// visible then the resource can be retuned in the lookup.
48
//
49
// Resources can be looked up by name or by type. To support type lookup
50
// each resource has a static type handle that uniquely identifies the
51
// type of each specialized resource container.
52
//
53
// Multiple resources that have the same name are stored in a queue.
54
// Each resource is pushed into a queue with the first one at the front
55
// of the queue and each subsequent one behind it.  The same happens for
56
// multiple resources that have the same type.  The resource queues are
57
// searched front to back, so those placed earlier in the queue have
58
// precedence over those placed later.
59
//
60
// The precedence of resources with the same name or same type can be
61
// altered.  One way is to set the ~precedence~ member of the resource
62
// container to any arbitrary value.  The search algorithm will return
63
// the resource with the highest precedence.  In the case where there
64
// are multiple resources that match the search criteria and have the
65
// same (highest) precedence, the earliest one located in the queue will
66
// be one returned.  Another way to change the precedence is to use the
67
// set_priority function to move a resource to either the front or back
68
// of the queue.
69
//
70
// The classes defined here form the low level layer of the resource
71
// database.  The classes include the resource container and the database
72
// that holds the containers.  The following set of classes are defined
73
// here:
74
//
75
// : A class without methods or members, only
76
// typedefs and enums. These types and enums are used throughout the
77
// resources facility.  Putting the types in a class keeps them confined
78
// to a specific name space.
79
//
80
// : policy class for setting options, such
81
// as auditing, which effect resources.
82
//
83
// : the base (untyped) resource class living in the
84
// resource database.  This class includes the interface for setting a
85
// resource as read-only, notification, scope management, altering
86
// search priority, and managing auditing.
87
//
88
// : parameterized resource container.  This class
89
// includes the interfaces for reading and writing each resource.
90
// Because the class is parameterized, all the access functions are type
91
// safe.
92
//
93
// : the resource database. This is a singleton
94
// class object.
95
//----------------------------------------------------------------------
96
 
97
typedef class uvm_resource_base; // forward reference
98
 
99
 
100
//----------------------------------------------------------------------
101
// Class: uvm_resource_types
102
//
103
// Provides typedefs and enums used throughout the resources facility.
104
// This class has no members or methods, only typedefs.  It's used in
105
// lieu of package-scope types.  When needed, other classes can use
106
// these types by prefixing their usage with uvm_resource_types::.  E.g.
107
//
108
//|  uvm_resource_types::rsrc_q_t queue;
109
//
110
//----------------------------------------------------------------------
111
class uvm_resource_types;
112
 
113
  // types uses for setting overrides
114
  typedef bit[1:0] override_t;
115
  typedef enum override_t { TYPE_OVERRIDE = 2'b01,
116
                            NAME_OVERRIDE = 2'b10 } override_e;
117
 
118
   // general purpose queue of resourcex
119
  typedef uvm_queue#(uvm_resource_base) rsrc_q_t;
120
 
121
  // enum for setting resource search priority
122
  typedef enum { PRI_HIGH, PRI_LOW } priority_e;
123
 
124
  // access record for resources.  A set of these is stored for each
125
  // resource by accessing object.  It's updated for each read/write.
126
  typedef struct
127
  {
128
    time read_time;
129
    time write_time;
130
    int unsigned read_count;
131
    int unsigned write_count;
132
  } access_t;
133
 
134
endclass
135
 
136
//----------------------------------------------------------------------
137
// Class: uvm_resource_options
138
//
139
// Provides a namespace for managing options for the
140
// resources facility.  The only thing allowed in this class is static
141
// local data members and static functions for manipulating and
142
// retrieving the value of the data members.  The static local data
143
// members represent options and settings that control the behavior of
144
// the resources facility.
145
 
146
// Options include:
147
//
148
//  * auditing:  on/off
149
//
150
//    The default for auditing is on.  You may wish to turn it off to
151
//    for performance reasons.  With auditing off memory is not
152
//    consumed for storage of auditing information and time is not
153
//    spent collecting and storing auditing information.  Of course,
154
//    during the period when auditing is off no audit trail information
155
//    is available
156
//
157
//----------------------------------------------------------------------
158
class uvm_resource_options;
159
 
160
  static local bit auditing = 1;
161
 
162
  // Function: turn_on_auditing
163
  //
164
  // Turn auditing on for the resource database. This causes all
165
  // reads and writes to the database to store information about
166
  // the accesses. Auditing is turned on by default.
167
 
168
  static function void turn_on_auditing();
169
    auditing = 1;
170
  endfunction
171
 
172
  // Function: turn_off_auditing
173
  //
174
  // Turn auditing off for the resource database. If auditing is turned off,
175
  // it is not possible to get extra information about resource
176
  // database accesses.
177
 
178
  static function void turn_off_auditing();
179
    auditing = 0;
180
  endfunction
181
 
182
  // Function: is_auditing
183
  //
184
  // Returns 1 if the auditing facility is on and 0 if it is off.
185
 
186
  static function bit is_auditing();
187
    return auditing;
188
  endfunction
189
endclass
190
 
191
//----------------------------------------------------------------------
192
// Class: uvm_resource_base
193
//
194
// Non-parameterized base class for resources.  Supports interfaces for
195
// scope matching, and virtual functions for printing the resource and
196
// for printing the accessor list
197
//----------------------------------------------------------------------
198
 
199
virtual class uvm_resource_base extends uvm_object;
200
 
201
  protected string scope;
202
  protected bit modified;
203
  protected bit read_only;
204
 
205
  uvm_resource_types::access_t access[string];
206
 
207
  // variable: precedence
208
  //
209
  // This variable is used to associate a precedence that a resource
210
  // has with respect to other resources which match the same scope
211
  // and name. Resources are set to the  initially,
212
  // and may be set to a higher or lower precedence as desired.
213
 
214
  int unsigned precedence;
215
 
216
  // variable: default_precedence
217
  //
218
  // The default precedence for an resource that has been created.
219
  // When two resources have the same precedence, the first resource
220
  // found has precedence.
221
  //
222
 
223
  static int unsigned default_precedence = 1000;
224
 
225
  // Function: new
226
  //
227
  // constructor for uvm_resource_base.  The constructor takes two
228
  // arguments, the name of the resource and a regular expression which
229
  // represents the set of scopes over which this resource is visible.
230
 
231
  function new(string name = "", string s = "*");
232
    super.new(name);
233
    set_scope(s);
234
    modified = 0;
235
    read_only = 0;
236
    precedence = default_precedence;
237
  endfunction
238
 
239
  // Function: get_type_handle
240
  //
241
  // Pure virtual function that returns the type handle of the resource
242
  // container.
243
 
244
  pure virtual function uvm_resource_base get_type_handle();
245
 
246
 
247
  //---------------------------
248
  // Group: Read-only Interface
249
  //---------------------------
250
 
251
  // Function: set_read_only
252
  //
253
  // Establishes this resource as a read-only resource.  An attempt
254
  // to call  on the resource will cause an error.
255
 
256
  function void set_read_only();
257
    read_only = 1;
258
  endfunction
259
 
260
  // function set_read_write
261
  //
262
  // Returns the resource to normal read-write capability.
263
 
264
  // Implementation question: Not sure if this function is necessary.
265
  // Once a resource is set to read_only no one should be able to change
266
  // that.  If anyone can flip the read_only bit then the resource is not
267
  // truly read_only.
268
 
269
  function void set_read_write();
270
    read_only = 0;
271
  endfunction
272
 
273
  // Function: is_read_only
274
  //
275
  // Returns one if this resource has been set to read-only, zero
276
  // otherwise
277
  function bit is_read_only();
278
    return read_only;
279
  endfunction
280
 
281
 
282
  //--------------------
283
  // Group: Notification
284
  //--------------------
285
 
286
  // Task: wait_modified
287
  //
288
  // This task blocks until the resource has been modified -- that is, a
289
  //  operation has been performed.  When a
290
  //  is performed the modified bit is set which
291
  // releases the block.  Wait_modified() then clears the modified bit so
292
  // it can be called repeatedly.
293
 
294
  task wait_modified();
295
    wait (modified == 1);
296
    modified = 0;
297
  endtask
298
 
299
  //-----------------------
300
  // Group: Scope Interface
301
  //-----------------------
302
  //
303
  // Each resource has a name, a value and a set of scopes over which it
304
  // is visible. A scope is a hierarchical entity or a context.  A scope
305
  // name is a multi-element string that identifies a scope.  Each
306
  // element refers to a scope context and the elements are separated by
307
  // dots (.).
308
  //
309
  //|    top.env.agent.monitor
310
  //
311
  // Consider the example above of a scope name.  It consists of four
312
  // elements: "top", "env", "agent", and "monitor".  The elements are
313
  // strung together with a dot separating each element.  ~top.env.agent~
314
  // is the parent of ~top.env.agent.monitor~, ~top.env~ is the parent of
315
  // ~top.env.agent~, and so on.  A set of scopes can be represented by a
316
  // set of scope name strings.  A very straightforward way to represent
317
  // a set of strings is to use regular expressions.  A regular
318
  // expression is a special string that contains placeholders which can
319
  // be substituted in various ways to generate or recognize a
320
  // particular set of strings.  Here are a few simple examples:
321
  //
322
  //|     top\..*                       all of the scopes whose top-level component
323
  //|                            is top
324
  //|    top\.env\..*\.monitor  all of the scopes in env that end in monitor;
325
  //|                            i.e. all the monitors two levels down from env
326
  //|    .*\.monitor                all of the scopes that end in monitor; i.e.
327
  //|                            all the monitors (assuming a naming convention
328
  //|                            was used where all monitors are named "monitor")
329
  //|    top\.u[1-5]\.*         all of the scopes rooted and named u1, u2, u3,
330
  //                             u4, or u5, and any of their subscopes.
331
  //
332
  // The examples above use POSIX regular expression notation.  This is
333
  // a very general and expressive notation.  It is not always the case
334
  // that so much expressiveness is required.  Sometimes an expression
335
  // syntax that is easy to read and easy to write is useful, even if
336
  // the syntax is not as expressive as the full power of POSIX regular
337
  // expressions.  A popular substitute for regular expressions is
338
  // globs.  A glob is a simplified regular expression. It only has
339
  // three metacharacters -- *, +, and ?.  Character ranges are not
340
  // allowed and dots are not a metacharacter in globs as they are in
341
  // regular expressions.  The following table shows glob
342
  // metacharacters.
343
  //
344
  //|      char meaning                 regular expression
345
  //|                                    equivalent
346
  //|      *        0 or more characters        .*
347
  //|      +        1 or more characters        .+
348
  //|      ?        exactly one character       .
349
  //
350
  // Of the examples above, the first three can easily be translated
351
  // into globs.  The last one cannot.  It relies on notation that is
352
  // not available in glob syntax.
353
  //
354
  //|    regular expression         glob equivalent
355
  //|    ---------------------      ------------------
356
  //|    top\..*                    top.*
357
  //|    top\.env\..*\.monitor      top.env.*.monitor
358
  //|    .*\.monitor                *.monitor
359
  //
360
  // The resource facility supports both regular expression and glob
361
  // syntax.  Regular expressions are identified as such when they
362
  // surrounded by '/' characters. For example, ~/^top\.*/~ is
363
  // interpreted as the regular expression ~^top\.*~, where the
364
  // surrounding '/' characters have been removed. All other expressions
365
  // are treated as glob expressions. They are converted from glob
366
  // notation to regular expression notation internally.  Regular expression
367
  // compilation and matching as well as glob-to-regular expression
368
  // conversion are handled by two DPI functions:
369
  //
370
  //|    function int uvm_re_match(string re, string str);
371
  //|    function string uvm_glob_to_re(string glob);
372
  //
373
  // uvm_re_match both compiles and matches the regular expression.
374
  // All of the matching is done using regular expressions, so globs are
375
  // converted to regular expressions and then processed.
376
 
377
 
378
  // Function: set_scope
379
  //
380
  // Set the value of the regular expression that identifies the set of
381
  // scopes over which this resource is visible.  If the supplied
382
  // argument is a glob it will be converted to a regular expression
383
  // before it is stored.
384
  //
385
  function void set_scope(string s);
386
    scope = uvm_glob_to_re(s);
387
  endfunction
388
 
389
  // Function: get_scope
390
  //
391
  // Retrieve the regular expression string that identifies the set of
392
  // scopes over which this resource is visible.
393
  //
394
  function string get_scope();
395
    return scope;
396
  endfunction
397
 
398
  // Function: match_scope
399
  //
400
  // Using the regular expression facility, determine if this resource
401
  // is visible in a scope.  Return one if it is, zero otherwise.
402
  //
403
  function bit match_scope(string s);
404
    int err = uvm_re_match(scope, s);
405
    return (err == 0);
406
  endfunction
407
 
408
  //----------------
409
  // Group: Priority
410
  //----------------
411
  //
412
  // Functions for manipulating the search priority of resources.  The
413
  // function definitions here are pure virtual and are implemented in
414
  // derived classes.  The definitons serve as a priority management
415
  // interface.
416
 
417
  // Function: set priority
418
  //
419
  // Change the search priority of the resource based on the value of
420
  // the priority enum argument.
421
  //
422
  pure virtual function void set_priority (uvm_resource_types::priority_e pri);
423
 
424
  //-------------------------
425
  // Group: Utility Functions
426
  //-------------------------
427
 
428
  // function convert2string
429
  //
430
  // Create a string representation of the resource value.  By default
431
  // we don't know how to do this so we just return a "?".  Resource
432
  // specializations are expected to override this function to produce a
433
  // proper string representation of the resource value.
434
 
435
  function string convert2string();
436
    return "?";
437
  endfunction
438
 
439
  // Function: do_print
440
  //
441
  // Implementation of do_print which is called by print().
442
 
443
  function void do_print (uvm_printer printer);
444
    printer.print_string("",$sformatf("%s [%s] : %s", get_name(), get_scope(), convert2string()));
445
  endfunction
446
 
447
  //-------------------
448
  // Group: Audit Trail
449
  //-------------------
450
  //
451
  // To find out what is happening as the simulation proceeds, an audit
452
  // trail of each read and write is kept. The  and
453
  //  methods each take an accessor argument.  This is a
454
  // handle to the object that performed that resource access.
455
  //
456
  //|    function T read(uvm_object accessor = null);
457
  //|    function void write(T t, uvm_object accessor = null);
458
  //
459
  // The accessor can by anything as long as it is derived from
460
  // uvm_object.  The accessor object can be a component or a sequence
461
  // or whatever object from which a read or write was invoked.
462
  // Typically the ~this~ handle is used as the
463
  // accessor.  For example:
464
  //
465
  //|    uvm_resource#(int) rint;
466
  //|    int i;
467
  //|    ...
468
  //|    rint.write(7, this);
469
  //|    i = rint.read(this);
470
  //
471
  // The accessor's ~get_full_name()~ is stored as part of the audit trail.
472
  // This way you can find out what object performed each resource access.
473
  // Each audit record also includes the time of the access (simulation time)
474
  // and the particular operation performed (read or write).
475
  //
476
  // Auditing is controlled through the  class.
477
 
478
  // function: record_read_access
479
 
480
  function void record_read_access(uvm_object accessor = null);
481
 
482
    string str;
483
    uvm_resource_types::access_t access_record;
484
 
485
    // If an accessor object is supplied then get the accessor record.
486
    // Otherwise create a new access record.  In either case populate
487
    // the access record with information about this access.  Check
488
    // first to make sure that auditing is turned on.
489
 
490
    if(!uvm_resource_options::is_auditing())
491
      return;
492
 
493
    // If an accessor is supplied, then use its name
494
        // as the database entry for the accessor record.
495
        // Otherwise, use "" as the database entry.
496
    if(accessor != null)
497
      str = accessor.get_full_name();
498
    else
499
      str = "";
500
 
501
    // Create a new accessor record if one does not exist
502
    if(access.exists(str))
503
      access_record = access[str];
504
    else
505
      init_access_record(access_record);
506
 
507
    // Update the accessor record
508
    access_record.read_count++;
509
    access_record.read_time = $realtime;
510
    access[str] = access_record;
511
 
512
  endfunction
513
 
514
  // function: record_write_access
515
 
516
  function void record_write_access(uvm_object accessor = null);
517
 
518
    string str;
519
 
520
    // If an accessor object is supplied then get the accessor record.
521
    // Otherwise create a new access record.  In either case populate
522
    // the access record with information about this access.  Check
523
    // first that auditing is turned on
524
 
525
    if(uvm_resource_options::is_auditing()) begin
526
      if(accessor != null) begin
527
        uvm_resource_types::access_t access_record;
528
        string str;
529
        str = accessor.get_full_name();
530
        if(access.exists(str))
531
          access_record = access[str];
532
        else
533
          init_access_record(access_record);
534
        access_record.write_count++;
535
        access_record.write_time = $realtime;
536
        access[str] = access_record;
537
      end
538
    end
539
  endfunction
540
 
541
  // Function: print_accessors
542
  //
543
  // Dump the access records for this resource
544
  //
545
  virtual function void print_accessors();
546
 
547
    string str;
548
    uvm_component comp;
549
    uvm_resource_types::access_t access_record;
550
    string qs[$];
551
 
552
    if(access.num() == 0)
553
      return;
554
 
555
    foreach (access[i]) begin
556
      str = i;
557
      access_record = access[str];
558
      qs.push_back($sformatf("%s reads: %0d @ %0t  writes: %0d @ %0t\n",str,
559
               access_record.read_count,
560
               access_record.read_time,
561
               access_record.write_count,
562
               access_record.write_time));
563
    end
564
    `uvm_info("UVM/RESOURCE/ACCESSOR",`UVM_STRING_QUEUE_STREAMING_PACK(qs),UVM_NONE)
565
 
566
  endfunction
567
 
568
 
569
  // Function: init_access_record
570
  //
571
  // Initialize a new access record
572
  //
573
  function void init_access_record (inout uvm_resource_types::access_t access_record);
574
    access_record.read_time = 0;
575
    access_record.write_time = 0;
576
    access_record.read_count = 0;
577
    access_record.write_count = 0;
578
  endfunction
579
endclass
580
 
581
 
582
//----------------------------------------------------------------------
583
// Class - get_t
584
//
585
// Instances of get_t are stored in the history list as a record of each
586
// get.  Failed gets are indicated with rsrc set to ~null~.  This is part
587
// of the audit trail facility for resources.
588
//----------------------------------------------------------------------
589
class get_t;
590
  string name;
591
  string scope;
592
  uvm_resource_base rsrc;
593
  time t;
594
endclass
595
 
596
//----------------------------------------------------------------------
597
// Class: uvm_resource_pool
598
//
599
// The global (singleton) resource database.
600
//
601
// Each resource is stored both by primary name and by type handle.  The
602
// resource pool contains two associative arrays, one with name as the
603
// key and one with the type handle as the key.  Each associative array
604
// contains a queue of resources.  Each resource has a regular
605
// expression that represents the set of scopes over which it is visible.
606
//
607
//|  +------+------------+                          +------------+------+
608
//|  | name | rsrc queue |                          | rsrc queue | type |
609
//|  +------+------------+                          +------------+------+
610
//|  |      |            |                          |            |      |
611
//|  +------+------------+                  +-+-+   +------------+------+
612
//|  |      |            |                  | | |<--+---*        |  T   |
613
//|  +------+------------+   +-+-+          +-+-+   +------------+------+
614
//|  |  A   |        *---+-->| | |           |      |            |      |
615
//|  +------+------------+   +-+-+           |      +------------+------+
616
//|  |      |            |      |            |      |            |      |
617
//|  +------+------------+      +-------+  +-+      +------------+------+
618
//|  |      |            |              |  |        |            |      |
619
//|  +------+------------+              |  |        +------------+------+
620
//|  |      |            |              V  V        |            |      |
621
//|  +------+------------+            +------+      +------------+------+
622
//|  |      |            |            | rsrc |      |            |      |
623
//|  +------+------------+            +------+      +------------+------+
624
//
625
// The above diagrams illustrates how a resource whose name is A and
626
// type is T is stored in the pool.  The pool contains an entry in the
627
// type map for type T and an entry in the name map for name A.  The
628
// queues in each of the arrays each contain an entry for the resource A
629
// whose type is T.  The name map can contain in its queue other
630
// resources whose name is A which may or may not have the same type as
631
// our resource A.  Similarly, the type map can contain in its queue
632
// other resources whose type is T and whose name may or may not be A.
633
//
634
// Resources are added to the pool by calling ; they are retrieved
635
// from the pool by calling  or .  When an object
636
// creates a new resource and calls  the resource is made available to be
637
// retrieved by other objects outside of itself; an object gets a
638
// resource when it wants to access a resource not currently available
639
// in its scope.
640
//
641
// The scope is stored in the resource itself (not in the pool) so
642
// whether you get by name or by type the resource's visibility is
643
// the same.
644
//
645
// As an auditing capability, the pool contains a history of gets.  A
646
// record of each get, whether by  or , is stored
647
// in the audit record.  Both successful and failed gets are recorded. At
648
// the end of simulation, or any time for that matter, you can dump the
649
// history list.  This will tell which resources were successfully
650
// located and which were not.  You can use this information
651
// to determine if there is some error in name, type, or
652
// scope that has caused a resource to not be located or to be incorrectly
653
// located (i.e. the wrong resource is located).
654
//
655
//----------------------------------------------------------------------
656
 
657
class uvm_resource_pool;
658
 
659
  static local uvm_resource_pool rp = get();
660
 
661
  uvm_resource_types::rsrc_q_t rtab [string];
662
  uvm_resource_types::rsrc_q_t ttab [uvm_resource_base];
663
 
664
  get_t get_record [$];  // history of gets
665
 
666
  local function new();
667
  endfunction
668
 
669
 
670
  // Function: get
671
  //
672
  // Returns the singleton handle to the resource pool
673
 
674
  static function uvm_resource_pool get();
675
    if(rp == null)
676
      rp = new();
677
    return rp;
678
  endfunction
679
 
680
 
681
  // Function: spell_check
682
  //
683
  // Invokes the spell checker for a string s.  The universe of
684
  // correctly spelled strings -- i.e. the dictionary -- is the name
685
  // map.
686
 
687
  function bit spell_check(string s);
688
    return uvm_spell_chkr#(uvm_resource_types::rsrc_q_t)::check(rtab, s);
689
  endfunction
690
 
691
 
692
  //-----------
693
  // Group: Set
694
  //-----------
695
 
696
  // Function: set
697
  //
698
  // Add a new resource to the resource pool.  The resource is inserted
699
  // into both the name map and type map so it can be located by
700
  // either.
701
  //
702
  // An object creates a resources and ~sets~ it into the resource pool.
703
  // Later, other objects that want to access the resource must ~get~ it
704
  // from the pool
705
  //
706
  // Overrides can be specified using this interface.  Either a name
707
  // override, a type override or both can be specified.  If an
708
  // override is specified then the resource is entered at the front of
709
  // the queue instead of at the back.  It is not recommended that users
710
  // specify the override parameter directly, rather they use the
711
  // , , or 
712
  // functions.
713
  //
714
  function void set (uvm_resource_base rsrc,
715
                     uvm_resource_types::override_t override = 0);
716
 
717
    uvm_resource_types::rsrc_q_t rq;
718
    string name;
719
    uvm_resource_base type_handle;
720
 
721
    // If resource handle is ~null~ then there is nothing to do.
722
    if(rsrc == null)
723
      return;
724
 
725
    // insert into the name map.  Resources with empty names are
726
    // anonymous resources and are not entered into the name map
727
    name = rsrc.get_name();
728
    if(name != "") begin
729
      if(rtab.exists(name))
730
        rq = rtab[name];
731
      else
732
        rq = new();
733
 
734
      // Insert the resource into the queue associated with its name.
735
      // If we are doing a name override then insert it in the front of
736
      // the queue, otherwise insert it in the back.
737
      if(override & uvm_resource_types::NAME_OVERRIDE)
738
        rq.push_front(rsrc);
739
      else
740
        rq.push_back(rsrc);
741
 
742
      rtab[name] = rq;
743
    end
744
 
745
    // insert into the type map
746
    type_handle = rsrc.get_type_handle();
747
    if(ttab.exists(type_handle))
748
      rq = ttab[type_handle];
749
    else
750
      rq = new();
751
 
752
    // insert the resource into the queue associated with its type.  If
753
    // we are doing a type override then insert it in the front of the
754
    // queue, otherwise insert it in the back of the queue.
755
    if(override & uvm_resource_types::TYPE_OVERRIDE)
756
      rq.push_front(rsrc);
757
    else
758
      rq.push_back(rsrc);
759
    ttab[type_handle] = rq;
760
 
761
  endfunction
762
 
763
  // Function: set_override
764
  //
765
  // The resource provided as an argument will be entered into the pool
766
  // and will override both by name and type.
767
 
768
  function void set_override(uvm_resource_base rsrc);
769
    set(rsrc, (uvm_resource_types::NAME_OVERRIDE |
770
               uvm_resource_types::TYPE_OVERRIDE));
771
  endfunction
772
 
773
 
774
  // Function: set_name_override
775
  //
776
  // The resource provided as an argument will entered into the pool
777
  // using normal precedence in the type map and will override the name.
778
 
779
  function void set_name_override(uvm_resource_base rsrc);
780
    set(rsrc, uvm_resource_types::NAME_OVERRIDE);
781
  endfunction
782
 
783
 
784
  // Function: set_type_override
785
  //
786
  // The resource provided as an argument will be entered into the pool
787
  // using normal precedence in the name map and will override the type.
788
 
789
  function void set_type_override(uvm_resource_base rsrc);
790
    set(rsrc, uvm_resource_types::TYPE_OVERRIDE);
791
  endfunction
792
 
793
 
794
  // function - push_get_record
795
  //
796
  // Insert a new record into the get history list.
797
 
798
  function void push_get_record(string name, string scope,
799
                                  uvm_resource_base rsrc);
800
    get_t impt;
801
 
802
    // if auditing is turned off then there is no reason
803
    // to save a get record
804
    if(!uvm_resource_options::is_auditing())
805
      return;
806
 
807
    impt = new();
808
 
809
    impt.name  = name;
810
    impt.scope = scope;
811
    impt.rsrc  = rsrc;
812
    impt.t     = $realtime;
813
 
814
    get_record.push_back(impt);
815
  endfunction
816
 
817
  // function - dump_get_records
818
  //
819
  // Format and print the get history list.
820
 
821
  function void dump_get_records();
822
 
823
    get_t record;
824
    bit success;
825
    string qs[$];
826
 
827
    qs.push_back("--- resource get records ---\n");
828
    foreach (get_record[i]) begin
829
      record = get_record[i];
830
      success = (record.rsrc != null);
831
      qs.push_back($sformatf("get: name=%s  scope=%s  %s @ %0t\n",
832
               record.name, record.scope,
833
               ((success)?"success":"fail"),
834
               record.t));
835
    end
836
    `uvm_info("UVM/RESOURCE/GETRECORD",`UVM_STRING_QUEUE_STREAMING_PACK(qs),UVM_NONE)
837
  endfunction
838
 
839
  //--------------
840
  // Group: Lookup
841
  //--------------
842
  //
843
  // This group of functions is for finding resources in the resource database.
844
  //
845
  //  and  locate the set of resources that
846
  // matches the name or type (respectively) and is visible in the
847
  // current scope.  These functions return a queue of resources.
848
  //
849
  //  traverse a queue of resources and
850
  // returns the one with the highest precedence -- i.e. the one whose
851
  // precedence member has the highest value.
852
  //
853
  //  and  use  and 
854
  // (respectively) and  to find the resource with
855
  // the highest priority that matches the other search criteria.
856
 
857
 
858
  // Function: lookup_name
859
  //
860
  // Lookup resources by ~name~.  Returns a queue of resources that
861
  // match the ~name~, ~scope~, and ~type_handle~.  If no resources
862
  // match the queue is returned empty. If ~rpterr~ is set then a
863
  // warning is issued if no matches are found, and the spell checker is
864
  // invoked on ~name~.  If ~type_handle~ is ~null~ then a type check is
865
  // not made and resources are returned that match only ~name~ and
866
  // ~scope~.
867
 
868
  function uvm_resource_types::rsrc_q_t lookup_name(string scope = "",
869
                                                    string name,
870
                                                    uvm_resource_base type_handle = null,
871
                                                    bit rpterr = 1);
872
    uvm_resource_types::rsrc_q_t rq;
873
    uvm_resource_types::rsrc_q_t q;
874
    uvm_resource_base rsrc;
875
    uvm_resource_base r;
876
 
877
     // ensure rand stability during lookup
878
     begin
879
        process p = process::self();
880
        string s;
881
        if(p!=null) s=p.get_randstate();
882
        q=new();
883
        if(p!=null) p.set_randstate(s);
884
     end
885
 
886
 
887
    // resources with empty names are anonymous and do not exist in the name map
888
    if(name == "")
889
      return q;
890
 
891
    // Does an entry in the name map exist with the specified name?
892
    // If not, then we're done
893
    if(!rtab.exists(name)) begin
894
            if(rpterr) void'(spell_check(name));
895
                return q;
896
    end
897
 
898
    rsrc = null;
899
    rq = rtab[name];
900
    for(int i=0; i
901
      r = rq.get(i);
902
      // does the type and scope match?
903
      if(((type_handle == null) || (r.get_type_handle() == type_handle)) &&
904
          r.match_scope(scope))
905
        q.push_back(r);
906
    end
907
 
908
    return q;
909
 
910
  endfunction
911
 
912
  // Function: get_highest_precedence
913
  //
914
  // Traverse a queue, ~q~, of resources and return the one with the highest
915
  // precedence.  In the case where there exists more than one resource
916
  // with the highest precedence value, the first one that has that
917
  // precedence will be the one that is returned.
918
 
919
  function uvm_resource_base get_highest_precedence(ref uvm_resource_types::rsrc_q_t q);
920
 
921
    uvm_resource_base rsrc;
922
    uvm_resource_base r;
923
    int unsigned i;
924
    int unsigned prec;
925
 
926
    if(q.size() == 0)
927
      return null;
928
 
929
    // get the first resources in the queue
930
    rsrc = q.get(0);
931
    prec = rsrc.precedence;
932
 
933
    // start searching from the second resource
934
    for(int i = 1; i < q.size(); ++i) begin
935
      r = q.get(i);
936
      if(r.precedence > prec) begin
937
        rsrc = r;
938
        prec = r.precedence;
939
      end
940
    end
941
 
942
    return rsrc;
943
 
944
  endfunction
945
 
946
  // Function: sort_by_precedence
947
  //
948
  // Given a list of resources, obtained for example from ,
949
  // sort the resources in  precedence order. The highest precedence
950
  // resource will be first in the list and the lowest precedence will
951
  // be last. Resources that have the same precedence and the same name
952
  // will be ordered by most recently set first.
953
 
954
  static function void sort_by_precedence(ref uvm_resource_types::rsrc_q_t q);
955
    uvm_resource_types::rsrc_q_t all[int];
956
    uvm_resource_base r;
957
    for(int i=0; i
958
      r = q.get(i);
959
      if(!all.exists(r.precedence))
960
         all[r.precedence] = new;
961
      all[r.precedence].push_front(r); //since we will push_front in the final
962
    end
963
    q.delete();
964
    foreach(all[i]) begin
965
      for(int j=0; j
966
        r = all[i].get(j);
967
        q.push_front(r);
968
      end
969
    end
970
  endfunction
971
 
972
 
973
  // Function: get_by_name
974
  //
975
  // Lookup a resource by ~name~, ~scope~, and ~type_handle~.  Whether
976
  // the get succeeds or fails, save a record of the get attempt.  The
977
  // ~rpterr~ flag indicates whether to report errors or not.
978
  // Essentially, it serves as a verbose flag.  If set then the spell
979
  // checker will be invoked and warnings about multiple resources will
980
  // be produced.
981
 
982
  function uvm_resource_base get_by_name(string scope = "",
983
                                         string name,
984
                                         uvm_resource_base type_handle,
985
                                         bit rpterr = 1);
986
 
987
    uvm_resource_types::rsrc_q_t q;
988
    uvm_resource_base rsrc;
989
 
990
    q = lookup_name(scope, name, type_handle, rpterr);
991
 
992
    if(q.size() == 0) begin
993
      push_get_record(name, scope, null);
994
      return null;
995
    end
996
 
997
    rsrc = get_highest_precedence(q);
998
    push_get_record(name, scope, rsrc);
999
    return rsrc;
1000
 
1001
  endfunction
1002
 
1003
 
1004
  // Function: lookup_type
1005
  //
1006
  // Lookup resources by type. Return a queue of resources that match
1007
  // the ~type_handle~ and ~scope~.  If no resources match then the returned
1008
  // queue is empty.
1009
 
1010
  function uvm_resource_types::rsrc_q_t lookup_type(string scope = "",
1011
                                                    uvm_resource_base type_handle);
1012
 
1013
    uvm_resource_types::rsrc_q_t q = new();
1014
    uvm_resource_types::rsrc_q_t rq;
1015
    uvm_resource_base r;
1016
    int unsigned i;
1017
 
1018
    if(type_handle == null || !ttab.exists(type_handle)) begin
1019
      return q;
1020
    end
1021
 
1022
    rq = ttab[type_handle];
1023
    for(int i = 0; i < rq.size(); ++i) begin
1024
      r = rq.get(i);
1025
      if(r.match_scope(scope))
1026
        q.push_back(r);
1027
    end
1028
 
1029
    return q;
1030
 
1031
  endfunction
1032
 
1033
  // Function: get_by_type
1034
  //
1035
  // Lookup a resource by ~type_handle~ and ~scope~.  Insert a record into
1036
  // the get history list whether or not the get succeeded.
1037
 
1038
  function uvm_resource_base get_by_type(string scope = "",
1039
                                         uvm_resource_base type_handle);
1040
 
1041
    uvm_resource_types::rsrc_q_t q;
1042
    uvm_resource_base rsrc;
1043
 
1044
    q = lookup_type(scope, type_handle);
1045
 
1046
    if(q.size() == 0) begin
1047
      push_get_record("", scope, null);
1048
      return null;
1049
    end
1050
 
1051
    rsrc = q.get(0);
1052
    push_get_record("", scope, rsrc);
1053
    return rsrc;
1054
 
1055
  endfunction
1056
 
1057
  // Function: lookup_regex_names
1058
  //
1059
  // This utility function answers the question, for a given ~name~,
1060
  // ~scope~, and ~type_handle~, what are all of the resources with requested name,
1061
  // a matching scope (where the resource scope may be a
1062
  // regular expression), and a matching type?
1063
  // ~name~ and ~scope~ are explicit values.
1064
 
1065
  function uvm_resource_types::rsrc_q_t lookup_regex_names(string scope,
1066
                                                           string name,
1067
                                                           uvm_resource_base type_handle = null);
1068
      return lookup_name(scope, name, type_handle, 0);
1069
  endfunction
1070
 
1071
  // Function: lookup_regex
1072
  //
1073
  // Looks for all the resources whose name matches the regular
1074
  // expression argument and whose scope matches the current scope.
1075
 
1076
  function uvm_resource_types::rsrc_q_t lookup_regex(string re, scope);
1077
 
1078
    uvm_resource_types::rsrc_q_t rq;
1079
    uvm_resource_types::rsrc_q_t result_q;
1080
    int unsigned i;
1081
    uvm_resource_base r;
1082
 
1083
    re = uvm_glob_to_re(re);
1084
    result_q = new();
1085
 
1086
    foreach (rtab[name]) begin
1087
      if(uvm_re_match(re, name))
1088
        continue;
1089
      rq = rtab[name];
1090
      for(i = 0; i < rq.size(); i++) begin
1091
        r = rq.get(i);
1092
        if(r.match_scope(scope))
1093
          result_q.push_back(r);
1094
      end
1095
    end
1096
 
1097
    return result_q;
1098
 
1099
  endfunction
1100
 
1101
  // Function: lookup_scope
1102
  //
1103
  // This is a utility function that answers the question: For a given
1104
  // ~scope~, what resources are visible to it?  Locate all the resources
1105
  // that are visible to a particular scope.  This operation could be
1106
  // quite expensive, as it has to traverse all of the resources in the
1107
  // database.
1108
 
1109
  function uvm_resource_types::rsrc_q_t lookup_scope(string scope);
1110
 
1111
    uvm_resource_types::rsrc_q_t rq;
1112
    uvm_resource_base r;
1113
    int unsigned i;
1114
 
1115
    int unsigned err;
1116
    uvm_resource_types::rsrc_q_t q = new();
1117
 
1118
    //iterate in reverse order for the special case of autoconfig
1119
    //of arrays. The array name with no [] needs to be higher priority.
1120
    //This has no effect an manual accesses.
1121
    string name;
1122
    if(rtab.last(name)) begin
1123
    do begin
1124
      rq = rtab[name];
1125
      for(int i = 0; i < rq.size(); ++i) begin
1126
        r = rq.get(i);
1127
        if(r.match_scope(scope)) begin
1128
          q.push_back(r);
1129
        end
1130
      end
1131
    end while(rtab.prev(name));
1132
    end
1133
 
1134
    return q;
1135
 
1136
  endfunction
1137
 
1138
  //--------------------
1139
  // Group: Set Priority
1140
  //--------------------
1141
  //
1142
  // Functions for altering the search priority of resources.  Resources
1143
  // are stored in queues in the type and name maps.  When retrieving
1144
  // resources, either by type or by name, the resource queue is search
1145
  // from front to back.  The first one that matches the search criteria
1146
  // is the one that is returned.  The ~set_priority~ functions let you
1147
  // change the order in which resources are searched.  For any
1148
  // particular resource, you can set its priority to UVM_HIGH, in which
1149
  // case the resource is moved to the front of the queue, or to UVM_LOW in
1150
  // which case the resource is moved to the back of the queue.
1151
 
1152
  // function- set_priority_queue
1153
  //
1154
  // This function handles the mechanics of moving a resource to either
1155
  // the front or back of the queue.
1156
 
1157
  local function void set_priority_queue(uvm_resource_base rsrc,
1158
                                         ref uvm_resource_types::rsrc_q_t q,
1159
                                         uvm_resource_types::priority_e pri);
1160
 
1161
    uvm_resource_base r;
1162
    int unsigned i;
1163
 
1164
    string msg;
1165
    string name = rsrc.get_name();
1166
 
1167
    for(i = 0; i < q.size(); i++) begin
1168
      r = q.get(i);
1169
      if(r == rsrc) break;
1170
    end
1171
 
1172
    if(r != rsrc) begin
1173
      $sformat(msg, "Handle for resource named %s is not in the name name; cannot change its priority", name);
1174
      uvm_report_error("NORSRC", msg);
1175
      return;
1176
    end
1177
 
1178
    q.delete(i);
1179
 
1180
    case(pri)
1181
      uvm_resource_types::PRI_HIGH: q.push_front(rsrc);
1182
      uvm_resource_types::PRI_LOW:  q.push_back(rsrc);
1183
    endcase
1184
 
1185
  endfunction
1186
 
1187
 
1188
  // Function: set_priority_type
1189
  //
1190
  // Change the priority of the ~rsrc~ based on the value of ~pri~, the
1191
  // priority enum argument.  This function changes the priority only in
1192
  // the type map, leaving the name map untouched.
1193
 
1194
  function void set_priority_type(uvm_resource_base rsrc,
1195
                                  uvm_resource_types::priority_e pri);
1196
 
1197
    uvm_resource_base type_handle;
1198
    string msg;
1199
    uvm_resource_types::rsrc_q_t q;
1200
 
1201
    if(rsrc == null) begin
1202
      uvm_report_warning("NULLRASRC", "attempting to change the serach priority of a null resource");
1203
      return;
1204
    end
1205
 
1206
    type_handle = rsrc.get_type_handle();
1207
    if(!ttab.exists(type_handle)) begin
1208
      $sformat(msg, "Type handle for resrouce named %s not found in type map; cannot change its search priority", rsrc.get_name());
1209
      uvm_report_error("RNFTYPE", msg);
1210
      return;
1211
    end
1212
 
1213
    q = ttab[type_handle];
1214
    set_priority_queue(rsrc, q, pri);
1215
  endfunction
1216
 
1217
 
1218
  // Function: set_priority_name
1219
  //
1220
  // Change the priority of the ~rsrc~ based on the value of ~pri~, the
1221
  // priority enum argument.  This function changes the priority only in
1222
  // the name map, leaving the type map untouched.
1223
 
1224
  function void set_priority_name(uvm_resource_base rsrc,
1225
                                  uvm_resource_types::priority_e pri);
1226
 
1227
    string name;
1228
    string msg;
1229
    uvm_resource_types::rsrc_q_t q;
1230
 
1231
    if(rsrc == null) begin
1232
      uvm_report_warning("NULLRASRC", "attempting to change the serach priority of a null resource");
1233
      return;
1234
    end
1235
 
1236
    name = rsrc.get_name();
1237
    if(!rtab.exists(name)) begin
1238
      $sformat(msg, "Resrouce named %s not found in name map; cannot change its search priority", name);
1239
      uvm_report_error("RNFNAME", msg);
1240
      return;
1241
    end
1242
 
1243
    q = rtab[name];
1244
    set_priority_queue(rsrc, q, pri);
1245
 
1246
  endfunction
1247
 
1248
 
1249
  // Function: set_priority
1250
  //
1251
  // Change the search priority of the ~rsrc~ based on the value of ~pri~,
1252
  // the priority enum argument.  This function changes the priority in
1253
  // both the name and type maps.
1254
 
1255
  function void set_priority (uvm_resource_base rsrc,
1256
                              uvm_resource_types::priority_e pri);
1257
    set_priority_type(rsrc, pri);
1258
    set_priority_name(rsrc, pri);
1259
  endfunction
1260
 
1261
  //--------------------------------------------------------------------
1262
  // Group: Debug
1263
  //--------------------------------------------------------------------
1264
 
1265
  // Function: find_unused_resources
1266
  //
1267
  // Locate all the resources that have at least one write and no reads
1268
 
1269
  function uvm_resource_types::rsrc_q_t find_unused_resources();
1270
 
1271
    uvm_resource_types::rsrc_q_t rq;
1272
    uvm_resource_types::rsrc_q_t q = new;
1273
    int unsigned i;
1274
    uvm_resource_base r;
1275
    uvm_resource_types::access_t a;
1276
    int reads;
1277
    int writes;
1278
 
1279
    foreach (rtab[name]) begin
1280
      rq = rtab[name];
1281
      for(int i=0; i
1282
        r = rq.get(i);
1283
        reads = 0;
1284
        writes = 0;
1285
        foreach(r.access[str]) begin
1286
          a = r.access[str];
1287
          reads += a.read_count;
1288
          writes += a.write_count;
1289
        end
1290
        if(writes > 0 && reads == 0)
1291
          q.push_back(r);
1292
      end
1293
    end
1294
 
1295
    return q;
1296
 
1297
  endfunction
1298
 
1299
 
1300
  // Function: print_resources
1301
  //
1302
  // Print the resources that are in a single queue, ~rq~.  This is a utility
1303
  // function that can be used to print any collection of resources
1304
  // stored in a queue.  The ~audit~ flag determines whether or not the
1305
  // audit trail is printed for each resource along with the name,
1306
  // value, and scope regular expression.
1307
 
1308
  function void print_resources(uvm_resource_types::rsrc_q_t rq, bit audit = 0);
1309
 
1310
    int unsigned i;
1311
    uvm_resource_base r;
1312
    static uvm_line_printer printer = new();
1313
 
1314
    printer.knobs.separator="";
1315
    printer.knobs.full_name=0;
1316
    printer.knobs.identifier=0;
1317
    printer.knobs.type_name=0;
1318
    printer.knobs.reference=0;
1319
 
1320
    if(rq == null || rq.size() == 0) begin
1321
      `uvm_info("UVM/RESOURCE/PRINT","",UVM_NONE)
1322
      return;
1323
    end
1324
 
1325
    for(int i=0; i
1326
      r = rq.get(i);
1327
      r.print(printer);
1328
      if(audit == 1)
1329
        r.print_accessors();
1330
    end
1331
 
1332
  endfunction
1333
 
1334
 
1335
  // Function: dump
1336
  //
1337
  // dump the entire resource pool.  The resource pool is traversed and
1338
  // each resource is printed.  The utility function print_resources()
1339
  // is used to initiate the printing. If the ~audit~ bit is set then
1340
  // the audit trail is dumped for each resource.
1341
 
1342
  function void dump(bit audit = 0);
1343
 
1344
    uvm_resource_types::rsrc_q_t rq;
1345
    string name;
1346
 
1347
    `uvm_info("UVM/RESOURCE/DUMP","\n=== resource pool ===",UVM_NONE)
1348
 
1349
    foreach (rtab[name]) begin
1350
      rq = rtab[name];
1351
      print_resources(rq, audit);
1352
    end
1353
 
1354
    `uvm_info("UVM/RESOURCE/DUMP","=== end of resource pool ===",UVM_NONE)
1355
 
1356
  endfunction
1357
 
1358
endclass
1359
 
1360
`ifdef UVM_USE_RESOURCE_CONVERTER
1361
typedef class m_uvm_resource_converter;
1362
`endif
1363
 
1364
//----------------------------------------------------------------------
1365
// Class: uvm_resource #(T)
1366
//
1367
// Parameterized resource.  Provides essential access methods to read
1368
// from and write to the resource database.
1369
//----------------------------------------------------------------------
1370
 
1371
class uvm_resource #(type T=int) extends uvm_resource_base;
1372
 
1373
  typedef uvm_resource#(T) this_type;
1374
 
1375
  // singleton handle that represents the type of this resource
1376
  static this_type my_type = get_type();
1377
 
1378
  // Can't be rand since things like rand strings are not legal.
1379
  protected T val;
1380
 
1381
`ifdef UVM_USE_RESOURCE_CONVERTER
1382
 
1383
  // Singleton used to convert this resource to a string
1384
  local static m_uvm_resource_converter#(T) m_r2s;
1385
 
1386
  // Function- m_get_converter
1387
  // Get the conversion policy class that specifies how to convert the value
1388
  // of a resource of this type to a string
1389
  //
1390
  static function m_uvm_resource_converter#(T) m_get_converter();
1391
    if (m_r2s==null) m_r2s = new();
1392
    return m_r2s;
1393
  endfunction
1394
 
1395
 
1396
  // Function- m_set_converter
1397
  // Specify how to convert the value of a resource of this type to a string
1398
  //
1399
  // If not specified (or set to ~null~),
1400
  // a default converter that display the name of the resource type is used.
1401
  // Default conversion policies are specified for the built-in type.
1402
  //
1403
  static function void m_set_converter(m_uvm_resource_converter#(T) r2s);
1404
    m_r2s = r2s;
1405
  endfunction
1406
 
1407
`endif
1408
 
1409
  function new(string name="", scope="");
1410
    super.new(name, scope);
1411
 
1412
`ifndef UVM_NO_DEPRECATED
1413
begin
1414
        for(int i=0;i
1415
                if(name.getc(i) inside {".","/","[","*","{"}) begin
1416
                        `uvm_warning("UVM/RSRC/NOREGEX", $sformatf("a resource with meta characters in the field name has been created \"%s\"",name))
1417
                        break;
1418
                end
1419
        end
1420
end
1421
 
1422
`endif
1423
  endfunction
1424
 
1425
  function string convert2string();
1426
`ifdef UVM_USE_RESOURCE_CONVERTER
1427
    void'(m_get_converter());
1428
    return m_r2s.convert2string(val);
1429
`else
1430
        return $sformatf("(%s) %0p", `uvm_typename(val), val);
1431
`endif
1432
  endfunction
1433
 
1434
 
1435
  //----------------------
1436
  // Group: Type Interface
1437
  //----------------------
1438
  //
1439
  // Resources can be identified by type using a static type handle.
1440
  // The parent class provides the virtual function interface
1441
  // .  Here we implement it by returning the static type
1442
  // handle.
1443
 
1444
  // Function: get_type
1445
  //
1446
  // Static function that returns the static type handle.  The return
1447
  // type is this_type, which is the type of the parameterized class.
1448
 
1449
  static function this_type get_type();
1450
    if(my_type == null)
1451
      my_type = new();
1452
    return my_type;
1453
  endfunction
1454
 
1455
  // Function: get_type_handle
1456
  //
1457
  // Returns the static type handle of this resource in a polymorphic
1458
  // fashion.  The return type of get_type_handle() is
1459
  // uvm_resource_base.  This function is not static and therefore can
1460
  // only be used by instances of a parameterized resource.
1461
 
1462
  function uvm_resource_base get_type_handle();
1463
    return get_type();
1464
  endfunction
1465
 
1466
  //-------------------------
1467
  // Group: Set/Get Interface
1468
  //-------------------------
1469
  //
1470
  // uvm_resource#(T) provides an interface for setting and getting a
1471
  // resources.  Specifically, a resource can insert itself into the
1472
  // resource pool.  It doesn't make sense for a resource to get itself,
1473
  // since you can't call a function on a handle you don't have.
1474
  // However, a static get interface is provided as a convenience.  This
1475
  // obviates the need for the user to get a handle to the global
1476
  // resource pool as this is done for him here.
1477
 
1478
  // Function: set
1479
  //
1480
  // Simply put this resource into the global resource pool
1481
 
1482
  function void set();
1483
    uvm_resource_pool rp = uvm_resource_pool::get();
1484
    rp.set(this);
1485
  endfunction
1486
 
1487
 
1488
  // Function: set_override
1489
  //
1490
  // Put a resource into the global resource pool as an override.  This
1491
  // means it gets put at the head of the list and is searched before
1492
  // other existing resources that occupy the same position in the name
1493
  // map or the type map.  The default is to override both the name and
1494
  // type maps.  However, using the ~override~ argument you can specify
1495
  // that either the name map or type map is overridden.
1496
 
1497
  function void set_override(uvm_resource_types::override_t override = 2'b11);
1498
    uvm_resource_pool rp = uvm_resource_pool::get();
1499
    rp.set(this, override);
1500
  endfunction
1501
 
1502
  // Function: get_by_name
1503
  //
1504
  // looks up a resource by ~name~ in the name map. The first resource
1505
  // with the specified name, whose type is the current type, and is
1506
  // visible in the specified ~scope~ is returned, if one exists.  The
1507
  // ~rpterr~ flag indicates whether or not an error should be reported
1508
  // if the search fails.  If ~rpterr~ is set to one then a failure
1509
  // message is issued, including suggested spelling alternatives, based
1510
  // on resource names that exist in the database, gathered by the spell
1511
  // checker.
1512
 
1513
  static function this_type get_by_name(string scope,
1514
                                        string name,
1515
                                        bit rpterr = 1);
1516
 
1517
    uvm_resource_pool rp = uvm_resource_pool::get();
1518
    uvm_resource_base rsrc_base;
1519
    this_type rsrc;
1520
    string msg;
1521
 
1522
    rsrc_base = rp.get_by_name(scope, name, my_type, rpterr);
1523
    if(rsrc_base == null)
1524
      return null;
1525
 
1526
    if(!$cast(rsrc, rsrc_base)) begin
1527
      if(rpterr) begin
1528
        $sformat(msg, "Resource with name %s in scope %s has incorrect type", name, scope);
1529
        `uvm_warning("RSRCTYPE", msg);
1530
      end
1531
      return null;
1532
    end
1533
 
1534
    return rsrc;
1535
 
1536
  endfunction
1537
 
1538
  // Function: get_by_type
1539
  //
1540
  // looks up a resource by ~type_handle~ in the type map. The first resource
1541
  // with the specified ~type_handle~ that is visible in the specified ~scope~ is
1542
  // returned, if one exists. If there is no resource matching the specifications,
1543
  // ~null~ is returned.
1544
 
1545
  static function this_type get_by_type(string scope = "",
1546
                                        uvm_resource_base type_handle);
1547
 
1548
    uvm_resource_pool rp = uvm_resource_pool::get();
1549
    uvm_resource_base rsrc_base;
1550
    this_type rsrc;
1551
    string msg;
1552
 
1553
    if(type_handle == null)
1554
      return null;
1555
 
1556
    rsrc_base = rp.get_by_type(scope, type_handle);
1557
    if(rsrc_base == null)
1558
      return null;
1559
 
1560
    if(!$cast(rsrc, rsrc_base)) begin
1561
      $sformat(msg, "Resource with specified type handle in scope %s was not located", scope);
1562
      `uvm_warning("RSRCNF", msg);
1563
      return null;
1564
    end
1565
 
1566
    return rsrc;
1567
 
1568
  endfunction
1569
 
1570
  //----------------------------
1571
  // Group: Read/Write Interface
1572
  //----------------------------
1573
  //
1574
  //  and  provide a type-safe interface for getting and
1575
  // setting the object in the resource container.  The interface is
1576
  // type safe because the value argument for  and the return
1577
  // value of  are T, the type supplied in the class parameter.
1578
  // If either of these functions is used in an incorrect type context
1579
  // the compiler will complain.
1580
 
1581
  // Function: read
1582
  //
1583
  // Return the object stored in the resource container.  If an ~accessor~
1584
  // object is supplied then also update the accessor record for this
1585
  // resource.
1586
 
1587
  function T read(uvm_object accessor = null);
1588
    record_read_access(accessor);
1589
    return val;
1590
  endfunction
1591
 
1592
  // Function: write
1593
  // Modify the object stored in this resource container.  If the
1594
  // resource is read-only then issue an error message and return
1595
  // without modifying the object in the container.  If the resource is
1596
  // not read-only and an ~accessor~ object has been supplied then also
1597
  // update the accessor record.  Lastly, replace the object value in
1598
  // the container with the value supplied as the argument, ~t~, and
1599
  // release any processes blocked on
1600
  // .  If the value to be written is
1601
  // the same as the value already present in the resource then the
1602
  // write is not done.  That also means that the accessor record is not
1603
  // updated and the modified bit is not set.
1604
 
1605
  function void write(T t, uvm_object accessor = null);
1606
 
1607
    if(is_read_only()) begin
1608
      uvm_report_error("resource", $sformatf("resource %s is read only -- cannot modify", get_name()));
1609
      return;
1610
    end
1611
 
1612
    // Set the modified bit and record the transaction only if the value
1613
    // has actually changed.
1614
    if(val == t)
1615
      return;
1616
 
1617
    record_write_access(accessor);
1618
 
1619
    // set the value and set the dirty bit
1620
    val = t;
1621
    modified = 1;
1622
  endfunction
1623
 
1624
  //----------------
1625
  // Group: Priority
1626
  //----------------
1627
  //
1628
  // Functions for manipulating the search priority of resources.  These
1629
  // implementations of the interface defined in the base class delegate
1630
  // to the resource pool.
1631
 
1632
 
1633
  // Function: set priority
1634
  //
1635
  // Change the search priority of the resource based on the value of
1636
  // the priority enum argument, ~pri~.
1637
 
1638
  function void set_priority (uvm_resource_types::priority_e pri);
1639
    uvm_resource_pool rp = uvm_resource_pool::get();
1640
    rp.set_priority(this, pri);
1641
  endfunction
1642
 
1643
 
1644
  // Function: get_highest_precedence
1645
  //
1646
  // In a queue of resources, locate the first one with the highest
1647
  // precedence whose type is T.  This function is static so that it can
1648
  // be called from anywhere.
1649
 
1650
  static function this_type get_highest_precedence(ref uvm_resource_types::rsrc_q_t q);
1651
 
1652
    this_type rsrc;
1653
    this_type r;
1654
    int unsigned i;
1655
    int unsigned prec;
1656
    int unsigned first;
1657
 
1658
    if(q.size() == 0)
1659
      return null;
1660
 
1661
    first = 0;
1662
    rsrc = null;
1663
    prec = 0;
1664
 
1665
    // Locate first resources in the queue whose type is T
1666
    for(first = 0; first < q.size() && !$cast(rsrc, q.get(first)); first++);
1667
 
1668
    // no resource in the queue whose type is T
1669
    if(rsrc == null)
1670
      return null;
1671
 
1672
    prec = rsrc.precedence;
1673
 
1674
    // start searching from the next resource after the first resource
1675
    // whose type is T
1676
    for(int i = first+1; i < q.size(); ++i) begin
1677
      if($cast(r, q.get(i))) begin
1678
        if(r.precedence > prec) begin
1679
          rsrc = r;
1680
          prec = r.precedence;
1681
        end
1682
      end
1683
    end
1684
 
1685
    return rsrc;
1686
 
1687
  endfunction
1688
 
1689
endclass
1690
 
1691
//----------------------------------------------------------------------
1692
// static global resource pool handle
1693
//----------------------------------------------------------------------
1694
const uvm_resource_pool uvm_resources = uvm_resource_pool::get();

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.