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

Subversion Repositories uart2bus_testbench

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 16 HanySalah
//----------------------------------------------------------------------
2
//   Copyright 2007-2011 Mentor Graphics Corporation
3
//   Copyright 2007-2010 Cadence Design Systems, Inc.
4
//   Copyright 2010-2011 Synopsys, 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
`include "uvm_macros.svh"
23
 
24
`ifndef UVM_CALLBACK_SVH
25
`define UVM_CALLBACK_SVH
26
 
27
//------------------------------------------------------------------------------
28
// Title: Callbacks Classes
29
//
30
// This section defines the classes used for callback registration, management,
31
// and user-defined callbacks.
32
//------------------------------------------------------------------------------
33
 
34
typedef class uvm_root;
35
typedef class uvm_callback;
36
typedef class uvm_callbacks_base;
37
 
38
 
39
//------------------------------------------------------------------------------
40
//
41
// Class - uvm_typeid_base
42
//
43
//------------------------------------------------------------------------------
44
//
45
// Simple typeid interface. Need this to set up the base-super mapping.
46
// This is similar to the factory, but much simpler. The idea of this
47
// interface is that each object type T has a typeid that can be
48
// used for mapping type relationships. This is not a user visible class.
49
 
50
class uvm_typeid_base;
51
  static string typename;
52
  static uvm_callbacks_base typeid_map[uvm_typeid_base];
53
  static uvm_typeid_base type_map[uvm_callbacks_base];
54
endclass
55
 
56
 
57
 
58
//------------------------------------------------------------------------------
59
//
60
// Class - uvm_typeid#(T)
61
//
62
//------------------------------------------------------------------------------
63
 
64
class uvm_typeid#(type T=uvm_object) extends uvm_typeid_base;
65
  static uvm_typeid#(T) m_b_inst;
66
  static function uvm_typeid#(T) get();
67
    if(m_b_inst == null)
68
      m_b_inst = new;
69
    return m_b_inst;
70
  endfunction
71
endclass
72
 
73
//------------------------------------------------------------------------------
74
// Class - uvm_callbacks_base
75
//
76
// Base class singleton that holds generic queues for all instance
77
// specific objects. This is an internal class. This class contains a
78
// global pool that has all of the instance specific callback queues in it.
79
// All of the typewide callback queues live in the derivative class
80
// uvm_typed_callbacks#(T). This is not a user visible class.
81
//
82
// This class holds the class inheritance hierarchy information
83
// (super types and derivative types).
84
//
85
// Note, all derivative uvm_callbacks#() class singletons access this
86
// global m_pool object in order to get access to their specific
87
// instance queue.
88
//------------------------------------------------------------------------------
89
 
90
class uvm_callbacks_base extends uvm_object;
91
 
92
  typedef uvm_callbacks_base this_type;
93
 
94
  /*protected*/ static bit m_tracing = 1;
95
  static this_type m_b_inst;
96
 
97
  static uvm_pool#(uvm_object,uvm_queue#(uvm_callback)) m_pool;
98
 
99
  static function this_type m_initialize();
100
    if(m_b_inst == null) begin
101
      m_b_inst = new;
102
      m_pool = new;
103
    end
104
    return m_b_inst;
105
  endfunction
106
 
107
  //Type checking interface
108
  this_type       m_this_type[$];     //one to many T->T/CB
109
  uvm_typeid_base m_super_type;       //one to one relation
110
  uvm_typeid_base m_derived_types[$]; //one to many relation
111
 
112
  virtual function bit m_am_i_a(uvm_object obj);
113
    return 0;
114
  endfunction
115
 
116
  virtual function bit m_is_for_me(uvm_callback cb);
117
    return 0;
118
  endfunction
119
 
120
  virtual function bit m_is_registered(uvm_object obj, uvm_callback cb);
121
    return 0;
122
  endfunction
123
 
124
  virtual function uvm_queue#(uvm_callback) m_get_tw_cb_q(uvm_object obj);
125
    return null;
126
  endfunction
127
 
128
  virtual function void m_add_tw_cbs(uvm_callback cb, uvm_apprepend ordering);
129
  endfunction
130
 
131
  virtual function bit m_delete_tw_cbs(uvm_callback cb);
132
    return 0;
133
  endfunction
134
 
135
  //Check registration. To test registration, start at this class and
136
  //work down the class hierarchy. If any class returns true then
137
  //the pair is legal.
138
  function bit check_registration(uvm_object obj, uvm_callback cb);
139
    this_type st, dt;
140
 
141
    if (m_is_registered(obj,cb))
142
      return 1;
143
 
144
    // Need to look at all possible T/CB pairs of this type
145
    foreach(m_this_type[i])
146
      if(m_b_inst != m_this_type[i] && m_this_type[i].m_is_registered(obj,cb))
147
        return 1;
148
 
149
    if(obj == null) begin
150
      foreach(m_derived_types[i]) begin
151
        dt = uvm_typeid_base::typeid_map[m_derived_types[i] ];
152
        if(dt != null && dt.check_registration(null,cb))
153
          return 1;
154
      end
155
    end
156
 
157
    return 0;
158
  endfunction
159
 
160
endclass
161
 
162
 
163
 
164
//------------------------------------------------------------------------------
165
//
166
// Class - uvm_typed_callbacks#(T)
167
//
168
//------------------------------------------------------------------------------
169
//
170
// Another internal class. This contains the queue of typewide
171
// callbacks. It also contains some of the public interface methods,
172
// but those methods are accessed via the uvm_callbacks#() class
173
// so they are documented in that class even though the implementation
174
// is in this class.
175
//
176
// The , , and  methods are implemented in this class.
177
 
178
class uvm_typed_callbacks#(type T=uvm_object) extends uvm_callbacks_base;
179
 
180
  static uvm_queue#(uvm_callback) m_tw_cb_q;
181
  static string m_typename;
182
 
183
  typedef uvm_typed_callbacks#(T) this_type;
184
  typedef uvm_callbacks_base      super_type;
185
 
186
  //The actual global object from the derivative class. Note that this is
187
  //just a reference to the object that is generated in the derived class.
188
  static this_type m_t_inst;
189
 
190
  static function this_type m_initialize();
191
    if(m_t_inst == null) begin
192
      void'(super_type::m_initialize());
193
      m_t_inst = new;
194
      m_t_inst.m_tw_cb_q = new("typewide_queue");
195
    end
196
    return m_t_inst;
197
  endfunction
198
 
199
  //Type checking interface: is given ~obj~ of type T?
200
  virtual function bit m_am_i_a(uvm_object obj);
201
    T this_type;
202
    if (obj == null)
203
      return 1;
204
    return($cast(this_type,obj));
205
  endfunction
206
 
207
  //Getting the typewide queue
208
  virtual function uvm_queue#(uvm_callback) m_get_tw_cb_q(uvm_object obj);
209
    if(m_am_i_a(obj)) begin
210
      foreach(m_derived_types[i]) begin
211
        super_type dt;
212
        dt = uvm_typeid_base::typeid_map[m_derived_types[i] ];
213
        if(dt != null && dt != this) begin
214
          m_get_tw_cb_q = dt.m_get_tw_cb_q(obj);
215
          if(m_get_tw_cb_q != null)
216
            return m_get_tw_cb_q;
217
        end
218
      end
219
      return m_t_inst.m_tw_cb_q;
220
    end
221
    else
222
      return null;
223
  endfunction
224
 
225
  static function int m_cb_find(uvm_queue#(uvm_callback) q, uvm_callback cb);
226
    for(int i=0; i
227
      if(q.get(i) == cb)
228
        return i;
229
    return -1;
230
  endfunction
231
 
232
  static function int m_cb_find_name(uvm_queue#(uvm_callback) q, string name, string where);
233
    uvm_callback cb;
234
    for(int i=0; i
235
      cb = q.get(i);
236
      if(cb.get_name() == name) begin
237
         `uvm_warning("UVM/CB/NAM/SAM", {"A callback named \"", name,
238
                                         "\" is already registered with ", where})
239
         return 1;
240
      end
241
    end
242
    return 0;
243
  endfunction
244
 
245
  //For a typewide callback, need to add to derivative types as well.
246
  virtual function void m_add_tw_cbs(uvm_callback cb, uvm_apprepend ordering);
247
    super_type cb_pair;
248
    uvm_object obj;
249
    T me;
250
    bit warned;
251
    uvm_queue#(uvm_callback) q;
252
    if(m_cb_find(m_t_inst.m_tw_cb_q,cb) == -1) begin
253
       warned = m_cb_find_name(m_t_inst.m_tw_cb_q, cb.get_name(), "type");
254
       if(ordering == UVM_APPEND)
255
          m_t_inst.m_tw_cb_q.push_back(cb);
256
       else
257
          m_t_inst.m_tw_cb_q.push_front(cb);
258
    end
259
    if(m_t_inst.m_pool.first(obj)) begin
260
      do begin
261
        if($cast(me,obj)) begin
262
          q = m_t_inst.m_pool.get(obj);
263
          if(q==null) begin
264
            q=new;
265
            m_t_inst.m_pool.add(obj,q);
266
          end
267
          if(m_cb_find(q,cb) == -1) begin
268
            if (!warned) begin
269
               void'(m_cb_find_name(q, cb.get_name(), {"object instance ", me.get_full_name()}));
270
            end
271
            if(ordering == UVM_APPEND)
272
              q.push_back(cb);
273
            else
274
              q.push_front(cb);
275
          end
276
        end
277
      end while(m_t_inst.m_pool.next(obj));
278
    end
279
    foreach(m_derived_types[i]) begin
280
      cb_pair = uvm_typeid_base::typeid_map[m_derived_types[i] ];
281
      if(cb_pair != this)
282
        cb_pair.m_add_tw_cbs(cb,ordering);
283
    end
284
  endfunction
285
 
286
 
287
  //For a typewide callback, need to remove from derivative types as well.
288
  virtual function bit m_delete_tw_cbs(uvm_callback cb);
289
    super_type cb_pair;
290
    uvm_object obj;
291
    uvm_queue#(uvm_callback) q;
292
    int pos = m_cb_find(m_t_inst.m_tw_cb_q,cb);
293
 
294
    if(pos != -1) begin
295
      m_t_inst.m_tw_cb_q.delete(pos);
296
      m_delete_tw_cbs = 1;
297
    end
298
 
299
    if(m_t_inst.m_pool.first(obj)) begin
300
      do begin
301
        q = m_t_inst.m_pool.get(obj);
302
        if(q==null) begin
303
          q=new;
304
          m_t_inst.m_pool.add(obj,q);
305
        end
306
        pos = m_cb_find(q,cb);
307
        if(pos != -1) begin
308
          q.delete(pos);
309
          m_delete_tw_cbs = 1;
310
        end
311
      end while(m_t_inst.m_pool.next(obj));
312
    end
313
    foreach(m_derived_types[i]) begin
314
      cb_pair = uvm_typeid_base::typeid_map[m_derived_types[i] ];
315
      if(cb_pair != this)
316
        m_delete_tw_cbs |= cb_pair.m_delete_tw_cbs(cb);
317
    end
318
  endfunction
319
 
320
 
321
  static function void display(T obj=null);
322
    T me;
323
    super_type ib = m_t_inst;
324
    string cbq[$];
325
    string inst_q[$];
326
    string mode_q[$];
327
    uvm_callback cb;
328
    string blanks = "                             ";
329
    uvm_object bobj = obj;
330
    string qs[$];
331
 
332
    uvm_queue#(uvm_callback) q;
333
    string tname, str;
334
 
335
    int max_cb_name=0, max_inst_name=0;
336
 
337
    m_tracing = 0; //don't allow tracing during display
338
 
339
    if(m_typename != "") tname = m_typename;
340
    else if(obj != null) tname = obj.get_type_name();
341
    else tname = "*";
342
 
343
    q = m_t_inst.m_tw_cb_q;
344
    for(int i=0; i
345
      cb = q.get(i);
346
      cbq.push_back(cb.get_name());
347
      inst_q.push_back("(*)");
348
      if(cb.is_enabled()) mode_q.push_back("ON");
349
      else mode_q.push_back("OFF");
350
 
351
      str = cb.get_name();
352
      max_cb_name = max_cb_name > str.len() ? max_cb_name : str.len();
353
      str = "(*)";
354
      max_inst_name = max_inst_name > str.len() ? max_inst_name : str.len();
355
    end
356
 
357
    if(obj ==null) begin
358
      if(m_t_inst.m_pool.first(bobj)) begin
359
        do
360
          if($cast(me,bobj)) break;
361
        while(m_t_inst.m_pool.next(bobj));
362
      end
363
      if(me != null || m_t_inst.m_tw_cb_q.size()) begin
364
        qs.push_back($sformatf("Registered callbacks for all instances of %s\n", tname));
365
        qs.push_back("---------------------------------------------------------------\n");
366
      end
367
      if(me != null) begin
368
        do begin
369
          if($cast(me,bobj)) begin
370
            q = m_t_inst.m_pool.get(bobj);
371
            if (q==null) begin
372
              q=new;
373
              m_t_inst.m_pool.add(bobj,q);
374
            end
375
            for(int i=0; i
376
              cb = q.get(i);
377
              cbq.push_back(cb.get_name());
378
              inst_q.push_back(bobj.get_full_name());
379
              if(cb.is_enabled()) mode_q.push_back("ON");
380
              else mode_q.push_back("OFF");
381
 
382
              str = cb.get_name();
383
              max_cb_name = max_cb_name > str.len() ? max_cb_name : str.len();
384
              str = bobj.get_full_name();
385
              max_inst_name = max_inst_name > str.len() ? max_inst_name : str.len();
386
            end
387
          end
388
        end while (m_t_inst.m_pool.next(bobj));
389
      end
390
      else begin
391
        qs.push_back($sformatf("No callbacks registered for any instances of type %s\n", tname));
392
      end
393
    end
394
    else begin
395
      if(m_t_inst.m_pool.exists(bobj) || m_t_inst.m_tw_cb_q.size()) begin
396
       qs.push_back($sformatf("Registered callbacks for instance %s of %s\n", obj.get_full_name(), tname));
397
       qs.push_back("---------------------------------------------------------------\n");
398
      end
399
      if(m_t_inst.m_pool.exists(bobj)) begin
400
        q = m_t_inst.m_pool.get(bobj);
401
        if(q==null) begin
402
          q=new;
403
          m_t_inst.m_pool.add(bobj,q);
404
        end
405
        for(int i=0; i
406
          cb = q.get(i);
407
          cbq.push_back(cb.get_name());
408
          inst_q.push_back(bobj.get_full_name());
409
          if(cb.is_enabled()) mode_q.push_back("ON");
410
          else mode_q.push_back("OFF");
411
 
412
          str = cb.get_name();
413
          max_cb_name = max_cb_name > str.len() ? max_cb_name : str.len();
414
          str = bobj.get_full_name();
415
          max_inst_name = max_inst_name > str.len() ? max_inst_name : str.len();
416
        end
417
      end
418
    end
419
    if(!cbq.size()) begin
420
      if(obj == null) str = "*";
421
      else str = obj.get_full_name();
422
      qs.push_back($sformatf("No callbacks registered for instance %s of type %s\n", str, tname));
423
    end
424
 
425
    foreach (cbq[i]) begin
426
      qs.push_back($sformatf("%s  %s %s on %s  %s\n", cbq[i], blanks.substr(0,max_cb_name-cbq[i].len()-1), inst_q[i], blanks.substr(0,max_inst_name - inst_q[i].len()-1), mode_q[i]));
427
    end
428
    `uvm_info("UVM/CB/DISPLAY",`UVM_STRING_QUEUE_STREAMING_PACK(qs),UVM_NONE)
429
 
430
    m_tracing = 1; //allow tracing to be resumed
431
  endfunction
432
 
433
endclass
434
 
435
 
436
 
437
//------------------------------------------------------------------------------
438
//
439
// CLASS: uvm_callbacks #(T,CB)
440
//
441
// The ~uvm_callbacks~ class provides a base class for implementing callbacks,
442
// which are typically used to modify or augment component behavior without
443
// changing the component class. To work effectively, the developer of the
444
// component class defines a set of "hook" methods that enable users to
445
// customize certain behaviors of the component in a manner that is controlled
446
// by the component developer. The integrity of the component's overall behavior
447
// is intact, while still allowing certain customizable actions by the user.
448
//
449
// To enable compile-time type-safety, the class is parameterized on both the
450
// user-defined callback interface implementation as well as the object type
451
// associated with the callback. The object type-callback type pair are
452
// associated together using the <`uvm_register_cb> macro to define
453
// a valid pairing; valid pairings are checked when a user attempts to add
454
// a callback to an object.
455
//
456
// To provide the most flexibility for end-user customization and reuse, it
457
// is recommended that the component developer also define a corresponding set
458
// of virtual method hooks in the component itself. This affords users the ability
459
// to customize via inheritance/factory overrides as well as callback object
460
// registration. The implementation of each virtual method would provide the
461
// default traversal algorithm for the particular callback being called. Being
462
// virtual, users can define subtypes that override the default algorithm,
463
// perform tasks before and/or after calling super. to execute any
464
// registered callbacks, or to not call the base implementation, effectively
465
// disabling that particular hook. A demonstration of this methodology is
466
// provided in an example included in the kit.
467
//------------------------------------------------------------------------------
468
 
469
class uvm_callbacks #(type T=uvm_object, type CB=uvm_callback)
470
    extends uvm_typed_callbacks#(T);
471
 
472
  // Parameter: T
473
  //
474
  // This type parameter specifies the base object type with which the
475
  //  callback objects will be registered. This object must be
476
  // a derivative of ~uvm_object~.
477
 
478
  // Parameter: CB
479
  //
480
  // This type parameter specifies the base callback type that will be
481
  // managed by this callback class. The callback type is typically a
482
  // interface class, which defines one or more virtual method prototypes
483
  // that users can override in subtypes. This type must be a derivative
484
  // of .
485
 
486
  typedef uvm_typed_callbacks#(T) super_type;
487
  typedef uvm_callbacks#(T,CB) this_type;
488
 
489
 
490
  // Singleton instance is used for type checking
491
  local static this_type m_inst;
492
 
493
  // typeinfo
494
  static uvm_typeid_base m_typeid;
495
  static uvm_typeid_base m_cb_typeid;
496
 
497
  static string m_typename;
498
  static string m_cb_typename;
499
  static uvm_report_object reporter = new("cb_tracer");
500
  static uvm_callbacks#(T,uvm_callback) m_base_inst;
501
 
502
  bit m_registered;
503
 
504
  // get
505
  // ---
506
 
507
  static function this_type get();
508
 
509
    if (m_inst == null) begin
510
      uvm_typeid_base cb_base_type;
511
 
512
      void'(super_type::m_initialize());
513
 
514
      cb_base_type = uvm_typeid#(uvm_callback)::get();
515
      m_cb_typeid  = uvm_typeid#(CB)::get();
516
      m_typeid     = uvm_typeid#(T)::get();
517
 
518
      m_inst = new;
519
 
520
      if (cb_base_type == m_cb_typeid) begin
521
        $cast(m_base_inst, m_inst);
522
        // The base inst in the super class gets set to this base inst
523
        m_t_inst = m_base_inst;
524
        uvm_typeid_base::typeid_map[m_typeid] = m_inst;
525
        uvm_typeid_base::type_map[m_b_inst] = m_typeid;
526
      end
527
      else begin
528
        m_base_inst = uvm_callbacks#(T,uvm_callback)::get();
529
        m_base_inst.m_this_type.push_back(m_inst);
530
      end
531
 
532
      if (m_inst == null)
533
        `uvm_fatal("CB/INTERNAL","get(): m_inst is null")
534
    end
535
 
536
    return m_inst;
537
  endfunction
538
 
539
 
540
 
541
  // m_register_pair
542
  // -------------
543
  // Register valid callback type
544
 
545
  static function bit m_register_pair(string tname="", cbname="");
546
    this_type inst = get();
547
 
548
    m_typename = tname;
549
    super_type::m_typename = tname;
550
    m_typeid.typename = tname;
551
 
552
    m_cb_typename = cbname;
553
    m_cb_typeid.typename = cbname;
554
 
555
    inst.m_registered = 1;
556
 
557
    return 1;
558
  endfunction
559
 
560
  virtual function bit m_is_registered(uvm_object obj, uvm_callback cb);
561
    if(m_is_for_me(cb) && m_am_i_a(obj)) begin
562
      return m_registered;
563
    end
564
  endfunction
565
 
566
  //Does type check to see if the callback is valid for this type
567
  virtual function bit m_is_for_me(uvm_callback cb);
568
    CB this_cb;
569
    return($cast(this_cb,cb));
570
  endfunction
571
 
572
  // Group: Add/delete interface
573
 
574
  // Function: add
575
  //
576
  // Registers the given callback object, ~cb~, with the given
577
  // ~obj~ handle. The ~obj~ handle can be ~null~, which allows
578
  // registration of callbacks without an object context. If
579
  // ~ordering~ is UVM_APPEND (default), the callback will be executed
580
  // after previously added callbacks, else  the callback
581
  // will be executed ahead of previously added callbacks. The ~cb~
582
  // is the callback handle; it must be non-~null~, and if the callback
583
  // has already been added to the object instance then a warning is
584
  // issued. Note that the CB parameter is optional. For example, the
585
  // following are equivalent:
586
  //
587
  //| uvm_callbacks#(my_comp)::add(comp_a, cb);
588
  //| uvm_callbacks#(my_comp, my_callback)::add(comp_a,cb);
589
 
590
  static function void add(T obj, uvm_callback cb, uvm_apprepend ordering=UVM_APPEND);
591
    uvm_queue#(uvm_callback) q;
592
    string nm,tnm;
593
 
594
    void'(get());
595
 
596
    if (cb==null) begin
597
       if (obj==null)
598
         nm = "(*)";
599
       else
600
         nm = obj.get_full_name();
601
 
602
       if (m_base_inst.m_typename!="")
603
         tnm = m_base_inst.m_typename;
604
       else if (obj != null)
605
         tnm = obj.get_type_name();
606
       else
607
         tnm = "uvm_object";
608
 
609
       uvm_report_error("CBUNREG",
610
                       {"Null callback object cannot be registered with object ",
611
                        nm, " (", tnm, ")"}, UVM_NONE);
612
       return;
613
    end
614
 
615
    if (!m_base_inst.check_registration(obj,cb)) begin
616
 
617
       if (obj==null)
618
         nm = "(*)";
619
       else
620
         nm = obj.get_full_name();
621
 
622
       if (m_base_inst.m_typename!="")
623
         tnm = m_base_inst.m_typename;
624
       else if(obj != null)
625
         tnm = obj.get_type_name();
626
       else
627
         tnm = "uvm_object";
628
 
629
       uvm_report_warning("CBUNREG",
630
                          {"Callback ", cb.get_name(), " cannot be registered with object ",
631
                          nm, " because callback type ", cb.get_type_name(),
632
                          " is not registered with object type ", tnm }, UVM_NONE);
633
    end
634
 
635
    if(obj == null) begin
636
 
637
      if (m_cb_find(m_t_inst.m_tw_cb_q,cb) != -1) begin
638
 
639
        if (m_base_inst.m_typename!="")
640
          tnm = m_base_inst.m_typename;
641
        else tnm = "uvm_object";
642
 
643
        uvm_report_warning("CBPREG",
644
                           {"Callback object ", cb.get_name(),
645
                           " is already registered with type ", tnm }, UVM_NONE);
646
      end
647
      else begin
648
        `uvm_cb_trace_noobj(cb,$sformatf("Add (%s) typewide callback %0s for type %s",
649
                            ordering.name(), cb.get_name(), m_base_inst.m_typename))
650
        m_t_inst.m_add_tw_cbs(cb,ordering);
651
      end
652
    end
653
 
654
    else begin
655
 
656
      `uvm_cb_trace_noobj(cb,$sformatf("Add (%s) callback %0s to object %0s ",
657
                          ordering.name(), cb.get_name(), obj.get_full_name()))
658
 
659
      q = m_base_inst.m_pool.get(obj);
660
 
661
      if (q==null) begin
662
        q=new;
663
        m_base_inst.m_pool.add(obj,q);
664
      end
665
 
666
      if(q.size() == 0) begin
667
        // Need to make sure that registered report catchers are added. This
668
        // way users don't need to set up uvm_report_object as a super type.
669
        uvm_report_object o;
670
 
671
        if($cast(o,obj)) begin
672
          uvm_queue#(uvm_callback) qr;
673
          void'(uvm_callbacks#(uvm_report_object, uvm_callback)::get());
674
          qr = uvm_callbacks#(uvm_report_object,uvm_callback)::m_t_inst.m_tw_cb_q;
675
          for(int i=0; i
676
              q.push_back(qr.get(i));
677
        end
678
 
679
        for(int i=0; i
680
          q.push_back(m_t_inst.m_tw_cb_q.get(i));
681
      end
682
 
683
      //check if already exists in the queue
684
      if(m_cb_find(q,cb) != -1) begin
685
        uvm_report_warning("CBPREG", { "Callback object ", cb.get_name(), " is already registered",
686
                           " with object ", obj.get_full_name() }, UVM_NONE);
687
      end
688
      else begin
689
        void'(m_cb_find_name(q, cb.get_name(), {"object instance ", obj.get_full_name()}));
690
        if(ordering == UVM_APPEND)
691
          q.push_back(cb);
692
        else
693
          q.push_front(cb);
694
      end
695
    end
696
  endfunction
697
 
698
  // Function: add_by_name
699
  //
700
  // Registers the given callback object, ~cb~, with one or more uvm_components.
701
  // The components must already exist and must be type T or a derivative. As
702
  // with  the CB parameter is optional. ~root~ specifies the location in
703
  // the component hierarchy to start the search for ~name~. See 
704
  // for more details on searching by name.
705
 
706
  static function void add_by_name(string name,
707
                                   uvm_callback cb,
708
                                   uvm_component root,
709
                                   uvm_apprepend ordering=UVM_APPEND);
710
    uvm_component cq[$];
711
    uvm_root top;
712
    uvm_coreservice_t cs;
713
    T t;
714
    void'(get());
715
    cs = uvm_coreservice_t::get();
716
    top = cs.get_root();
717
 
718
    if(cb==null) begin
719
       uvm_report_error("CBUNREG", { "Null callback object cannot be registered with object(s) ",
720
         name }, UVM_NONE);
721
       return;
722
    end
723
    `uvm_cb_trace_noobj(cb,$sformatf("Add (%s) callback %0s by name to object(s) %0s ",
724
                    ordering.name(), cb.get_name(), name))
725
    top.find_all(name,cq,root);
726
    if(cq.size() == 0) begin
727
      uvm_report_warning("CBNOMTC", { "add_by_name failed to find any components matching the name ",
728
        name, ", callback ", cb.get_name(), " will not be registered." }, UVM_NONE);
729
    end
730
    foreach(cq[i]) begin
731
      if($cast(t,cq[i])) begin
732
        add(t,cb,ordering);
733
      end
734
    end
735
  endfunction
736
 
737
 
738
  // Function: delete
739
  //
740
  // Deletes the given callback object, ~cb~, from the queue associated with
741
  //  the given ~obj~ handle. The ~obj~ handle can be ~null~, which allows
742
  // de-registration of callbacks without an object context.
743
  // The ~cb~ is the callback handle; it must be non-~null~, and if the callback
744
  // has already been removed from the object instance then a warning is
745
  // issued. Note that the CB parameter is optional. For example, the
746
  // following are equivalent:
747
  //
748
  //| uvm_callbacks#(my_comp)::delete(comp_a, cb);
749
  //| uvm_callbacks#(my_comp, my_callback)::delete(comp_a,cb);
750
 
751
  static function void delete(T obj, uvm_callback cb);
752
    uvm_object b_obj = obj;
753
    uvm_queue#(uvm_callback) q;
754
    bit found;
755
    int pos;
756
    void'(get());
757
 
758
    if(obj == null) begin
759
      `uvm_cb_trace_noobj(cb,$sformatf("Delete typewide callback %0s for type %s",
760
                       cb.get_name(), m_base_inst.m_typename))
761
      found = m_t_inst.m_delete_tw_cbs(cb);
762
    end
763
    else begin
764
      `uvm_cb_trace_noobj(cb,$sformatf("Delete callback %0s from object %0s ",
765
                      cb.get_name(), obj.get_full_name()))
766
      q = m_base_inst.m_pool.get(b_obj);
767
      pos = m_cb_find(q,cb);
768
      if(pos != -1) begin
769
        q.delete(pos);
770
        found = 1;
771
      end
772
    end
773
    if(!found) begin
774
      string nm;
775
      if(obj==null) nm = "(*)"; else nm = obj.get_full_name();
776
      uvm_report_warning("CBUNREG", { "Callback ", cb.get_name(), " cannot be removed from object ",
777
        nm, " because it is not currently registered to that object." }, UVM_NONE);
778
    end
779
  endfunction
780
 
781
 
782
  // Function: delete_by_name
783
  //
784
  // Removes the given callback object, ~cb~, associated with one or more
785
  // uvm_component callback queues. As with  the CB parameter is
786
  // optional. ~root~ specifies the location in the component hierarchy to start
787
  // the search for ~name~. See  for more details on searching
788
  // by name.
789
 
790
  static function void delete_by_name(string name, uvm_callback cb,
791
     uvm_component root);
792
    uvm_component cq[$];
793
    uvm_root top;
794
    T t;
795
    uvm_coreservice_t cs;
796
    void'(get());
797
    cs = uvm_coreservice_t::get();
798
    top = cs.get_root();
799
 
800
    `uvm_cb_trace_noobj(cb,$sformatf("Delete callback %0s by name from object(s) %0s ",
801
                    cb.get_name(), name))
802
    top.find_all(name,cq,root);
803
    if(cq.size() == 0) begin
804
      uvm_report_warning("CBNOMTC", { "delete_by_name failed to find any components matching the name ",
805
        name, ", callback ", cb.get_name(), " will not be unregistered." }, UVM_NONE);
806
    end
807
    foreach(cq[i]) begin
808
      if($cast(t,cq[i])) begin
809
        delete(t,cb);
810
      end
811
    end
812
  endfunction
813
 
814
 
815
  //--------------------------
816
  // Group: Iterator Interface
817
  //--------------------------
818
  //
819
  // This set of functions provide an iterator interface for callback queues. A facade
820
  // class,  is also available, and is the generally preferred way to
821
  // iterate over callback queues.
822
 
823
  static function void m_get_q (ref uvm_queue #(uvm_callback) q, input T obj);
824
    if(!m_base_inst.m_pool.exists(obj)) begin //no instance specific
825
      q = (obj == null) ? m_t_inst.m_tw_cb_q : m_t_inst.m_get_tw_cb_q(obj);
826
    end
827
    else begin
828
      q = m_base_inst.m_pool.get(obj);
829
      if(q==null) begin
830
        q=new;
831
        m_base_inst.m_pool.add(obj,q);
832
      end
833
    end
834
  endfunction
835
 
836
 
837
  // Function: get_first
838
  //
839
  // Returns the first enabled callback of type CB which resides in the queue for ~obj~.
840
  // If ~obj~ is ~null~ then the typewide queue for T is searched. ~itr~ is the iterator;
841
  // it will be updated with a value that can be supplied to  to get the next
842
  // callback object.
843
  //
844
  // If the queue is empty then ~null~ is returned.
845
  //
846
  // The iterator class  may be used as an alternative, simplified,
847
  // iterator interface.
848
 
849
  static function CB get_first (ref int itr, input T obj);
850
    uvm_queue#(uvm_callback) q;
851
    CB cb;
852
    void'(get());
853
    m_get_q(q,obj);
854
    for(itr = 0; itr
855
      if($cast(cb, q.get(itr)) && cb.callback_mode())
856
         return cb;
857
    return null;
858
  endfunction
859
 
860
  // Function: get_last
861
  //
862
  // Returns the last enabled callback of type CB which resides in the queue for ~obj~.
863
  // If ~obj~ is ~null~ then the typewide queue for T is searched. ~itr~ is the iterator;
864
  // it will be updated with a value that can be supplied to  to get the previous
865
  // callback object.
866
  //
867
  // If the queue is empty then ~null~ is returned.
868
  //
869
  // The iterator class  may be used as an alternative, simplified,
870
  // iterator interface.
871
 
872
  static function CB get_last (ref int itr, input T obj);
873
    uvm_queue#(uvm_callback) q;
874
    CB cb;
875
    void'(get());
876
    m_get_q(q,obj);
877
    for(itr = q.size()-1; itr>=0; --itr)
878
      if ($cast(cb, q.get(itr)) && cb.callback_mode())
879
         return cb;
880
    return null;
881
  endfunction
882
 
883
 
884
  // Function: get_next
885
  //
886
  // Returns the next enabled callback of type CB which resides in the queue for ~obj~,
887
  // using ~itr~ as the starting point. If ~obj~ is ~null~ then the typewide queue for T
888
  // is searched. ~itr~ is the iterator; it will be updated with a value that can be
889
  // supplied to  to get the next callback object.
890
  //
891
  // If no more callbacks exist in the queue, then ~null~ is returned.  will
892
  // continue to return ~null~ in this case until  or  has been used to reset
893
  // the iterator.
894
  //
895
  // The iterator class  may be used as an alternative, simplified,
896
  // iterator interface.
897
 
898
  static function CB get_next (ref int itr, input T obj);
899
    uvm_queue#(uvm_callback) q;
900
    CB cb;
901
    void'(get());
902
    m_get_q(q,obj);
903
    for(itr = itr+1; itr
904
      if ($cast(cb, q.get(itr)) && cb.callback_mode())
905
         return cb;
906
    return null;
907
  endfunction
908
 
909
 
910
  // Function: get_prev
911
  //
912
  // Returns the previous enabled callback of type CB which resides in the queue for ~obj~,
913
  // using ~itr~ as the starting point. If ~obj~ is ~null~ then the typewide queue for T
914
  // is searched. ~itr~ is the iterator; it will be updated with a value that can be
915
  // supplied to  to get the previous callback object.
916
  //
917
  // If no more callbacks exist in the queue, then ~null~ is returned.  will
918
  // continue to return ~null~ in this case until  or  has been used to reset
919
  // the iterator.
920
  //
921
  // The iterator class  may be used as an alternative, simplified,
922
  // iterator interface.
923
 
924
  static function CB get_prev (ref int itr, input T obj);
925
    uvm_queue#(uvm_callback) q;
926
    CB cb;
927
    void'(get());
928
    m_get_q(q,obj);
929
    for(itr = itr-1; itr>= 0; --itr)
930
      if($cast(cb, q.get(itr)) && cb.callback_mode())
931
         return cb;
932
    return null;
933
  endfunction
934
 
935
 
936
  //-------------
937
  // Group: Debug
938
  //-------------
939
 
940
  // Function: display
941
  //
942
  // This function displays callback information for ~obj~. If ~obj~ is
943
  // ~null~, then it displays callback information for all objects
944
  // of type ~T~, including typewide callbacks.
945
 
946
  static function void display(T obj=null);
947
    // For documentation purposes, need a function wrapper here.
948
    void'(get());
949
    super_type::display(obj);
950
  endfunction
951
 
952
endclass
953
 
954
 
955
 
956
//------------------------------------------------------------------------------
957
//
958
// Class- uvm_derived_callbacks #(T,ST,CB)
959
//
960
//------------------------------------------------------------------------------
961
// This type is not really expected to be used directly by the user, instead they are
962
// expected to use the macro `uvm_set_super_type. The sole purpose of this type is to
963
// allow for setting up of the derived_type/super_type mapping.
964
//------------------------------------------------------------------------------
965
 
966
class uvm_derived_callbacks#(type T=uvm_object, type ST=uvm_object, type CB=uvm_callback)
967
    extends uvm_callbacks#(T,CB);
968
 
969
  typedef uvm_derived_callbacks#(T,ST,CB) this_type;
970
  typedef uvm_callbacks#(T)            this_user_type;
971
  typedef uvm_callbacks#(ST)           this_super_type;
972
 
973
  // Singleton instance is used for type checking
974
  static this_type m_d_inst;
975
  static this_user_type m_user_inst;
976
  static this_super_type m_super_inst;
977
 
978
  // typeinfo
979
  static uvm_typeid_base m_s_typeid;
980
 
981
  static function this_type get();
982
    m_user_inst = this_user_type::get();
983
    m_super_inst = this_super_type::get();
984
    m_s_typeid = uvm_typeid#(ST)::get();
985
    if(m_d_inst == null) begin
986
      m_d_inst = new;
987
    end
988
    return m_d_inst;
989
  endfunction
990
 
991
  static function bit register_super_type(string tname="", sname="");
992
    this_user_type u_inst = this_user_type::get();
993
    this_type      inst = this_type::get();
994
    uvm_callbacks_base s_obj;
995
 
996
    this_user_type::m_t_inst.m_typename = tname;
997
 
998
    if(sname != "") m_s_typeid.typename = sname;
999
 
1000
    if(u_inst.m_super_type != null) begin
1001
      if(u_inst.m_super_type == m_s_typeid) return 1;
1002
      uvm_report_warning("CBTPREG", { "Type ", tname, " is already registered to super type ",
1003
        this_super_type::m_t_inst.m_typename, ". Ignoring attempt to register to super type ",
1004
        sname}, UVM_NONE);
1005
      return 1;
1006
    end
1007
    if(this_super_type::m_t_inst.m_typename == "")
1008
      this_super_type::m_t_inst.m_typename = sname;
1009
    u_inst.m_super_type = m_s_typeid;
1010
    u_inst.m_base_inst.m_super_type = m_s_typeid;
1011
    s_obj = uvm_typeid_base::typeid_map[m_s_typeid];
1012
    s_obj.m_derived_types.push_back(m_typeid);
1013
    return 1;
1014
  endfunction
1015
 
1016
endclass
1017
 
1018
 
1019
//------------------------------------------------------------------------------
1020
//
1021
// CLASS: uvm_callback_iter
1022
//
1023
//------------------------------------------------------------------------------
1024
// The ~uvm_callback_iter~ class is an iterator class for iterating over
1025
// callback queues of a specific callback type. The typical usage of
1026
// the class is:
1027
//
1028
//| uvm_callback_iter#(mycomp,mycb) iter = new(this);
1029
//| for(mycb cb = iter.first(); cb != null; cb = iter.next())
1030
//|    cb.dosomething();
1031
//
1032
// The callback iteration macros, <`uvm_do_callbacks> and
1033
// <`uvm_do_callbacks_exit_on> provide a simple method for iterating
1034
// callbacks and executing the callback methods.
1035
//------------------------------------------------------------------------------
1036
 
1037
class uvm_callback_iter#(type T = uvm_object, type CB = uvm_callback);
1038
 
1039
   local int m_i;
1040
   local T   m_obj;
1041
   local CB  m_cb;
1042
 
1043
   // Function: new
1044
   //
1045
   // Creates a new callback iterator object. It is required that the object
1046
   // context be provided.
1047
 
1048
   function new(T obj);
1049
      m_obj = obj;
1050
   endfunction
1051
 
1052
   // Function: first
1053
   //
1054
   // Returns the first valid (enabled) callback of the callback type (or
1055
   // a derivative) that is in the queue of the context object. If the
1056
   // queue is empty then ~null~ is returned.
1057
 
1058
   function CB first();
1059
      m_cb = uvm_callbacks#(T,CB)::get_first(m_i, m_obj);
1060
      return m_cb;
1061
   endfunction
1062
 
1063
   // Function: last
1064
   //
1065
   // Returns the last valid (enabled) callback of the callback type (or
1066
   // a derivative) that is in the queue of the context object. If the
1067
   // queue is empty then ~null~ is returned.
1068
 
1069
   function CB last();
1070
      m_cb = uvm_callbacks#(T,CB)::get_last(m_i, m_obj);
1071
      return m_cb;
1072
   endfunction
1073
 
1074
   // Function: next
1075
   //
1076
   // Returns the next valid (enabled) callback of the callback type (or
1077
   // a derivative) that is in the queue of the context object. If there
1078
   // are no more valid callbacks in the queue, then ~null~ is returned.
1079
 
1080
   function CB next();
1081
      m_cb = uvm_callbacks#(T,CB)::get_next(m_i, m_obj);
1082
      return m_cb;
1083
   endfunction
1084
 
1085
   // Function: prev
1086
   //
1087
   // Returns the previous valid (enabled) callback of the callback type (or
1088
   // a derivative) that is in the queue of the context object. If there
1089
   // are no more valid callbacks in the queue, then ~null~ is returned.
1090
 
1091
   function CB prev();
1092
      m_cb = uvm_callbacks#(T,CB)::get_prev(m_i, m_obj);
1093
      return m_cb;
1094
   endfunction
1095
 
1096
   // Function: get_cb
1097
   //
1098
   // Returns the last callback accessed via a first() or next()
1099
   // call.
1100
 
1101
   function CB get_cb();
1102
      return m_cb;
1103
   endfunction
1104
 
1105
/****
1106
   function void trace(uvm_object obj = null);
1107
      if (m_cb != null && T::cbs::get_debug_flags() & UVM_CALLBACK_TRACE) begin
1108
         uvm_report_object reporter = null;
1109
         string who = "Executing ";
1110
         void'($cast(reporter, obj));
1111
         if (reporter == null) void'($cast(reporter, m_obj));
1112
         if (reporter == null) reporter = uvm_top;
1113
         if (obj != null) who = {obj.get_full_name(), " is executing "};
1114
         else if (m_obj != null) who = {m_obj.get_full_name(), " is executing "};
1115
         reporter.uvm_report_info("CLLBK_TRC", {who, "callback ", m_cb.get_name()}, UVM_LOW);
1116
      end
1117
   endfunction
1118
****/
1119
endclass
1120
 
1121
 
1122
 
1123
//------------------------------------------------------------------------------
1124
// CLASS: uvm_callback
1125
//
1126
// The ~uvm_callback~ class is the base class for user-defined callback classes.
1127
// Typically, the component developer defines an application-specific callback
1128
// class that extends from this class. In it, he defines one or more virtual
1129
// methods, called a ~callback interface~, that represent the hooks available
1130
// for user override.
1131
//
1132
// Methods intended for optional override should not be declared ~pure.~ Usually,
1133
// all the callback methods are defined with empty implementations so users have
1134
// the option of overriding any or all of them.
1135
//
1136
// The prototypes for each hook method are completely application specific with
1137
// no restrictions.
1138
//------------------------------------------------------------------------------
1139
 
1140
class uvm_callback extends uvm_object;
1141
 
1142
  static uvm_report_object reporter = new("cb_tracer");
1143
 
1144
  protected bit m_enabled = 1;
1145
 
1146
  // Function: new
1147
  //
1148
  // Creates a new uvm_callback object, giving it an optional ~name~.
1149
 
1150
  function new(string name="uvm_callback");
1151
    super.new(name);
1152
  endfunction
1153
 
1154
 
1155
  // Function: callback_mode
1156
  //
1157
  // Enable/disable callbacks (modeled like rand_mode and constraint_mode).
1158
 
1159
  function bit callback_mode(int on=-1);
1160
    if(on == 0 || on == 1) begin
1161
      `uvm_cb_trace_noobj(this,$sformatf("Setting callback mode for %s to %s",
1162
            get_name(), ((on==1) ? "ENABLED":"DISABLED")))
1163
    end
1164
    else begin
1165
      `uvm_cb_trace_noobj(this,$sformatf("Callback mode for %s is %s",
1166
            get_name(), ((m_enabled==1) ? "ENABLED":"DISABLED")))
1167
    end
1168
    callback_mode = m_enabled;
1169
    if(on==0) m_enabled=0;
1170
    if(on==1) m_enabled=1;
1171
  endfunction
1172
 
1173
 
1174
  // Function: is_enabled
1175
  //
1176
  // Returns 1 if the callback is enabled, 0 otherwise.
1177
 
1178
  function bit is_enabled();
1179
    return callback_mode();
1180
  endfunction
1181
 
1182
  static string type_name = "uvm_callback";
1183
 
1184
 
1185
  // Function: get_type_name
1186
  //
1187
  // Returns the type name of this callback object.
1188
 
1189
  virtual function string get_type_name();
1190
     return type_name;
1191
  endfunction
1192
 
1193
endclass
1194
 
1195
 
1196
`endif // UVM_CALLBACK_SVH
1197
 
1198
 

powered by: WebSVN 2.1.0

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