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

Subversion Repositories uart2bus_testbench

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 16 HanySalah
//
2
//----------------------------------------------------------------------
3
//   Copyright 2007-2011 Mentor Graphics Corporation
4
//   Copyright 2007-2011 Cadence Design Systems, Inc.
5
//   Copyright 2010-2011 Synopsys, Inc.
6
//   Copyright 2013      NVIDIA Corporation
7
//   All Rights Reserved Worldwide
8
//
9
//   Licensed under the Apache License, Version 2.0 (the
10
//   "License"); you may not use this file except in
11
//   compliance with the License.  You may obtain a copy of
12
//   the License at
13
//
14
//       http://www.apache.org/licenses/LICENSE-2.0
15
//
16
//   Unless required by applicable law or agreed to in
17
//   writing, software distributed under the License is
18
//   distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
19
//   CONDITIONS OF ANY KIND, either express or implied.  See
20
//   the License for the specific language governing
21
//   permissions and limitations under the License.
22
//----------------------------------------------------------------------
23
 
24
`ifndef UVM_OBJECTION_SVH
25
`define UVM_OBJECTION_SVH
26
 
27
typedef class uvm_objection_context_object;
28
typedef class uvm_objection;
29
typedef class uvm_sequence_base;
30
typedef class uvm_objection_callback;
31
typedef uvm_callbacks #(uvm_objection,uvm_objection_callback) uvm_objection_cbs_t;
32
typedef class uvm_cmdline_processor;
33
 
34
class uvm_objection_events;
35
  int waiters;
36
  event raised;
37
  event dropped;
38
  event all_dropped;
39
endclass
40
 
41
//------------------------------------------------------------------------------
42
// Title: Objection Mechanism
43
//------------------------------------------------------------------------------
44
// The following classes define the objection mechanism and end-of-test
45
// functionality, which is based on .
46
//------------------------------------------------------------------------------
47
 
48
//------------------------------------------------------------------------------
49
//
50
// Class: uvm_objection
51
//
52
//------------------------------------------------------------------------------
53
// Objections provide a facility for coordinating status information between
54
// two or more participating components, objects, and even module-based IP.
55
//
56
// Tracing of objection activity can be turned on to follow the activity of
57
// the objection mechanism. It may be turned on for a specific objection
58
// instance with , or it can be set for all
59
// objections from the command line using the option +UVM_OBJECTION_TRACE.
60
//------------------------------------------------------------------------------
61
 
62
class uvm_objection extends uvm_report_object;
63
  `uvm_register_cb(uvm_objection, uvm_objection_callback)
64
 
65
  protected bit     m_trace_mode;
66
  protected int     m_source_count[uvm_object];
67
  protected int     m_total_count [uvm_object];
68
  protected time    m_drain_time  [uvm_object];
69
  protected uvm_objection_events m_events [uvm_object];
70
  /*protected*/ bit     m_top_all_dropped;
71
 
72
  protected uvm_root m_top;
73
 
74
  static uvm_objection m_objections[$];
75
 
76
  //// Drain Logic
77
 
78
  // The context pool holds used context objects, so that
79
  // they're not constantly being recreated.  The maximum
80
  // number of contexts in the pool is equal to the maximum
81
  // number of simultaneous drains you could have occuring,
82
  // both pre and post forks.
83
  //
84
  // There's the potential for a programmability within the
85
  // library to dictate the largest this pool should be allowed
86
  // to grow, but that seems like overkill for the time being.
87
  local static uvm_objection_context_object m_context_pool[$];
88
 
89
  // These are the active drain processes, which have been
90
  // forked off by the background process.  A raise can
91
  // use this array to kill a drain.
92
`ifndef UVM_USE_PROCESS_CONTAINER
93
  local process m_drain_proc[uvm_object];
94
`else
95
  local process_container_c m_drain_proc[uvm_object];
96
`endif
97
 
98
  // These are the contexts which have been scheduled for
99
  // retrieval by the background process, but which the
100
  // background process hasn't seen yet.
101
  local static uvm_objection_context_object m_scheduled_list[$];
102
 
103
  // Once a context is seen by the background process, it is
104
  // removed from the scheduled list, and placed in the forked
105
  // list.  At the same time, it is placed in the scheduled
106
  // contexts array.  A re-raise can use the scheduled contexts
107
  // array to detect (and cancel) the drain.
108
  local uvm_objection_context_object m_scheduled_contexts[uvm_object];
109
  local uvm_objection_context_object m_forked_list[$];
110
 
111
  // Once the forked drain has actually started (this occurs
112
  // ~1 delta AFTER the background process schedules it), the
113
  // context is removed from the above array and list, and placed
114
  // in the forked_contexts list.
115
  local uvm_objection_context_object m_forked_contexts[uvm_object];
116
 
117
  protected bit m_prop_mode = 1;
118
  protected bit m_cleared; /* for checking obj count<0 */
119
 
120
 
121
  // Function: new
122
  //
123
  // Creates a new objection instance. Accesses the command line
124
  // argument +UVM_OBJECTION_TRACE to turn tracing on for
125
  // all objection objects.
126
 
127
  function new(string name="");
128
    uvm_cmdline_processor clp;
129
    uvm_coreservice_t cs_ ;
130
    string trace_args[$];
131
    super.new(name);
132
    cs_ = uvm_coreservice_t::get();
133
    m_top  = cs_.get_root();
134
 
135
    set_report_verbosity_level(m_top.get_report_verbosity_level());
136
 
137
    // Get the command line trace mode setting
138
    clp = uvm_cmdline_processor::get_inst();
139
    if(clp.get_arg_matches("+UVM_OBJECTION_TRACE", trace_args)) begin
140
      m_trace_mode=1;
141
    end
142
    m_objections.push_back(this);
143
  endfunction
144
 
145
 
146
  // Function: trace_mode
147
  //
148
  // Set or get the trace mode for the objection object. If no
149
  // argument is specified (or an argument other than 0 or 1)
150
  // the current trace mode is unaffected. A trace_mode of
151
  // 0 turns tracing off. A trace mode of 1 turns tracing on.
152
  // The return value is the mode prior to being reset.
153
 
154
   function bit trace_mode (int mode=-1);
155
    trace_mode = m_trace_mode;
156
    if(mode == 0) m_trace_mode = 0;
157
    else if(mode == 1) m_trace_mode = 1;
158
   endfunction
159
 
160
  // Function- m_report
161
  //
162
  // Internal method for reporting count updates
163
 
164
  function void m_report(uvm_object obj, uvm_object source_obj, string description, int count, string action);
165
    string desc;
166
    int _count = m_source_count.exists(obj) ? m_source_count[obj] : 0;
167
    int _total = m_total_count.exists(obj) ? m_total_count[obj] : 0;
168
    if (!uvm_report_enabled(UVM_NONE,UVM_INFO,"OBJTN_TRC") || !m_trace_mode) return;
169
 
170
    //desc = description == "" ? "" : {" ", description, "" };
171
    if (source_obj == obj)
172
 
173
      uvm_report_info("OBJTN_TRC",
174
        $sformatf("Object %0s %0s %0d objection(s)%s: count=%0d  total=%0d",
175
           obj.get_full_name()==""?"uvm_top":obj.get_full_name(), action,
176
           count, description != ""? {" (",description,")"}:"", _count, _total), UVM_NONE);
177
    else begin
178
      int cpath = 0, last_dot=0;
179
      string sname = source_obj.get_full_name(), nm = obj.get_full_name();
180
      int max = sname.len() > nm.len() ? nm.len() : sname.len();
181
 
182
      // For readability, only print the part of the source obj hierarchy underneath
183
      // the current object.
184
      while((sname[cpath] == nm[cpath]) && (cpath < max)) begin
185
        if(sname[cpath] == ".") last_dot = cpath;
186
        cpath++;
187
      end
188
 
189
      if(last_dot) sname = sname.substr(last_dot+1, sname.len());
190
      uvm_report_info("OBJTN_TRC",
191
        $sformatf("Object %0s %0s %0d objection(s) %0s its total (%s from source object %s%s): count=%0d  total=%0d",
192
           obj.get_full_name()==""?"uvm_top":obj.get_full_name(), action=="raised"?"added":"subtracted",
193
            count, action=="raised"?"to":"from", action, sname,
194
            description != ""?{", ",description}:"", _count, _total), UVM_NONE);
195
    end
196
  endfunction
197
 
198
 
199
  // Function- m_get_parent
200
  //
201
  // Internal method for getting the parent of the given ~object~.
202
  // The ultimate parent is uvm_top, UVM's implicit top-level component.
203
 
204
  function uvm_object m_get_parent(uvm_object obj);
205
    uvm_component comp;
206
    uvm_sequence_base seq;
207
    if ($cast(comp, obj)) begin
208
      obj = comp.get_parent();
209
    end
210
    else if ($cast(seq, obj)) begin
211
       obj = seq.get_sequencer();
212
    end
213
    else
214
      obj = m_top;
215
    if (obj == null)
216
      obj = m_top;
217
    return obj;
218
  endfunction
219
 
220
 
221
  // Function- m_propagate
222
  //
223
  // Propagate the objection to the objects parent. If the object is a
224
  // component, the parent is just the hierarchical parent. If the object is
225
  // a sequence, the parent is the parent sequence if one exists, or
226
  // it is the attached sequencer if there is no parent sequence.
227
  //
228
  // obj : the uvm_object on which the objection is being raised or lowered
229
  // source_obj : the root object on which the end user raised/lowered the
230
  //   objection (as opposed to an anscestor of the end user object)a
231
  // count : the number of objections associated with the action.
232
  // raise : indicator of whether the objection is being raised or lowered. A
233
  //   1 indicates the objection is being raised.
234
 
235
  function void m_propagate (uvm_object obj,
236
                             uvm_object source_obj,
237
                             string description,
238
                             int count,
239
                             bit raise,
240
                             int in_top_thread);
241
    if (obj != null && obj != m_top) begin
242
      obj = m_get_parent(obj);
243
      if(raise)
244
        m_raise(obj, source_obj, description, count);
245
      else
246
        m_drop(obj, source_obj, description, count, in_top_thread);
247
    end
248
  endfunction
249
 
250
 
251
  // Group: Objection Control
252
 
253
  // Function: set_propagate_mode
254
  // Sets the propagation mode for this objection.
255
  //
256
  // By default, objections support hierarchical propagation for
257
  // components.  For example, if we have the following basic
258
  // component tree:
259
  //
260
  //| uvm_top.parent.child
261
  //
262
  // Any objections raised by 'child' would get propagated
263
  // down to parent, and then to uvm_test_top.  Resulting in the
264
  // following counts and totals:
265
  //
266
  //|                      | count | total |
267
  //| uvm_top.parent.child |     1 |    1  |
268
  //| uvm_top.parent       |     0 |    1  |
269
  //| uvm_top              |     0 |    1  |
270
  //|
271
  //
272
  // While propagations such as these can be useful, if they are
273
  // unused by the testbench then they are simply an unnecessary
274
  // performance hit.  If the testbench is not going to use this
275
  // functionality, then the performance can be improved by setting
276
  // the propagation mode to 0.
277
  //
278
  // When propagation mode is set to 0, all intermediate callbacks
279
  // between the ~source~ and ~top~ will be skipped.  This would
280
  // result in the following counts and totals for the above objection:
281
  //
282
  //|                      | count | total |
283
  //| uvm_top.parent.child |     1 |    1  |
284
  //| uvm_top.parent       |     0 |    0  |
285
  //| uvm_top              |     0 |    1  |
286
  //|
287
  //
288
  // Since the propagation mode changes the behavior of the objection,
289
  // it can only be safely changed if there are no objections ~raised~
290
  // or ~draining~.  Any attempts to change the mode while objections
291
  // are ~raised~ or ~draining~ will result in an error.
292
  //
293
  function void set_propagate_mode (bit prop_mode);
294
     if (!m_top_all_dropped && (get_objection_total() != 0)) begin
295
        `uvm_error("UVM/BASE/OBJTN/PROP_MODE",
296
                   {"The propagation mode of '", this.get_full_name(),
297
                    "' cannot be changed while the objection is raised ",
298
                    "or draining!"})
299
        return;
300
     end
301
 
302
     m_prop_mode = prop_mode;
303
  endfunction : set_propagate_mode
304
 
305
  // Function: get_propagate_mode
306
  // Returns the propagation mode for this objection.
307
  function bit get_propagate_mode();
308
     return m_prop_mode;
309
  endfunction : get_propagate_mode
310
 
311
  // Function: raise_objection
312
  //
313
  // Raises the number of objections for the source ~object~ by ~count~, which
314
  // defaults to 1.  The ~object~ is usually the ~this~ handle of the caller.
315
  // If ~object~ is not specified or ~null~, the implicit top-level component,
316
  // , is chosen.
317
  //
318
  // Raising an objection causes the following.
319
  //
320
  // - The source and total objection counts for ~object~ are increased by
321
  //   ~count~. ~description~ is a string that marks a specific objection
322
  //   and is used in tracing/debug.
323
  //
324
  // - The objection's  virtual method is called, which calls the
325
  //    method for all of the components up the
326
  //   hierarchy.
327
  //
328
 
329
  virtual function void raise_objection (uvm_object obj=null,
330
                                         string description="",
331
                                         int count=1);
332
    if(obj == null)
333
      obj = m_top;
334
    m_cleared = 0;
335
    m_top_all_dropped = 0;
336
    m_raise (obj, obj, description, count);
337
  endfunction
338
 
339
 
340
  // Function- m_raise
341
 
342
  function void m_raise (uvm_object obj,
343
                         uvm_object source_obj,
344
                         string description="",
345
                         int count=1);
346
    int idx;
347
    uvm_objection_context_object ctxt;
348
 
349
    // Ignore raise if count is 0
350
    if (count == 0)
351
      return;
352
 
353
    if (m_total_count.exists(obj))
354
      m_total_count[obj] += count;
355
    else
356
      m_total_count[obj] = count;
357
 
358
    if (source_obj==obj) begin
359
      if (m_source_count.exists(obj))
360
        m_source_count[obj] += count;
361
      else
362
        m_source_count[obj] = count;
363
    end
364
 
365
    if (m_trace_mode)
366
      m_report(obj,source_obj,description,count,"raised");
367
 
368
    raised(obj, source_obj, description, count);
369
 
370
      // Handle any outstanding drains...
371
 
372
    // First go through the scheduled list
373
    idx = 0;
374
    while (idx < m_scheduled_list.size()) begin
375
        if ((m_scheduled_list[idx].obj == obj) &&
376
            (m_scheduled_list[idx].objection == this)) begin
377
            // Caught it before the drain was forked
378
            ctxt = m_scheduled_list[idx];
379
            m_scheduled_list.delete(idx);
380
            break;
381
        end
382
        idx++;
383
    end
384
 
385
    // If it's not there, go through the forked list
386
    if (ctxt == null) begin
387
        idx = 0;
388
        while (idx < m_forked_list.size()) begin
389
            if (m_forked_list[idx].obj == obj) begin
390
                // Caught it after the drain was forked,
391
                // but before the fork started
392
                ctxt = m_forked_list[idx];
393
                m_forked_list.delete(idx);
394
                m_scheduled_contexts.delete(ctxt.obj);
395
                break;
396
            end
397
            idx++;
398
        end
399
    end
400
 
401
    // If it's not there, go through the forked contexts
402
    if (ctxt == null) begin
403
        if (m_forked_contexts.exists(obj)) begin
404
            // Caught it with the forked drain running
405
            ctxt = m_forked_contexts[obj];
406
            m_forked_contexts.delete(obj);
407
            // Kill the drain
408
`ifndef UVM_USE_PROCESS_CONTAINER
409
            m_drain_proc[obj].kill();
410
            m_drain_proc.delete(obj);
411
`else
412
            m_drain_proc[obj].p.kill();
413
            m_drain_proc.delete(obj);
414
`endif
415
 
416
        end
417
    end
418
 
419
    if (ctxt == null) begin
420
        // If there were no drains, just propagate as usual
421
 
422
        if (!m_prop_mode && obj != m_top)
423
          m_raise(m_top,source_obj,description,count);
424
        else if (obj != m_top)
425
          m_propagate(obj, source_obj, description, count, 1, 0);
426
    end
427
    else begin
428
        // Otherwise we need to determine what exactly happened
429
        int diff_count;
430
 
431
        // Determine the diff count, if it's positive, then we're
432
        // looking at a 'raise' total, if it's negative, then
433
        // we're looking at a 'drop', but not down to 0.  If it's
434
        // a 0, that means that there is no change in the total.
435
        diff_count = count - ctxt.count;
436
 
437
        if (diff_count != 0) begin
438
            // Something changed
439
            if (diff_count > 0) begin
440
                // we're looking at an increase in the total
441
                if (!m_prop_mode && obj != m_top)
442
                  m_raise(m_top, source_obj, description, diff_count);
443
                else if (obj != m_top)
444
                  m_propagate(obj, source_obj, description, diff_count, 1, 0);
445
            end
446
            else begin
447
                // we're looking at a decrease in the total
448
                // The count field is always positive...
449
                diff_count = -diff_count;
450
                if (!m_prop_mode && obj != m_top)
451
                  m_drop(m_top, source_obj, description, diff_count);
452
                else if (obj != m_top)
453
                  m_propagate(obj, source_obj, description, diff_count, 0, 0);
454
            end
455
        end
456
 
457
        // Cleanup
458
        ctxt.clear();
459
        m_context_pool.push_back(ctxt);
460
    end
461
 
462
  endfunction
463
 
464
 
465
  // Function: drop_objection
466
  //
467
  // Drops the number of objections for the source ~object~ by ~count~, which
468
  // defaults to 1.  The ~object~ is usually the ~this~ handle of the caller.
469
  // If ~object~ is not specified or ~null~, the implicit top-level component,
470
  // , is chosen.
471
  //
472
  // Dropping an objection causes the following.
473
  //
474
  // - The source and total objection counts for ~object~ are decreased by
475
  //   ~count~. It is an error to drop the objection count for ~object~ below
476
  //   zero.
477
  //
478
  // - The objection's  virtual method is called, which calls the
479
  //    method for all of the components up the
480
  //   hierarchy.
481
  //
482
  // - If the total objection count has not reached zero for ~object~, then
483
  //   the drop is propagated up the object hierarchy as with
484
  //   . Then, each object in the hierarchy will have updated
485
  //   their ~source~ counts--objections that they originated--and ~total~
486
  //   counts--the total number of objections by them and all their
487
  //   descendants.
488
  //
489
  // If the total objection count reaches zero, propagation up the hierarchy
490
  // is deferred until a configurable drain-time has passed and the
491
  //  callback for the current hierarchy level
492
  // has returned. The following process occurs for each instance up
493
  // the hierarchy from the source caller:
494
  //
495
  // A process is forked in a non-blocking fashion, allowing the ~drop~
496
  // call to return. The forked process then does the following:
497
  //
498
  // - If a drain time was set for the given ~object~, the process waits for
499
  //   that amount of time.
500
  //
501
  // - The objection's  virtual method is called, which calls the
502
  //    method (if ~object~ is a component).
503
  //
504
  // - The process then waits for the ~all_dropped~ callback to complete.
505
  //
506
  // - After the drain time has elapsed and all_dropped callback has
507
  //   completed, propagation of the dropped objection to the parent proceeds
508
  //   as described in , except as described below.
509
  //
510
  // If a new objection for this ~object~ or any of its descendants is raised
511
  // during the drain time or during execution of the all_dropped callback at
512
  // any point, the hierarchical chain described above is terminated and the
513
  // dropped callback does not go up the hierarchy. The raised objection will
514
  // propagate up the hierarchy, but the number of raised propagated up is
515
  // reduced by the number of drops that were pending waiting for the
516
  // all_dropped/drain time completion. Thus, if exactly one objection
517
  // caused the count to go to zero, and during the drain exactly one new
518
  // objection comes in, no raises or drops are propagated up the hierarchy,
519
  //
520
  // As an optimization, if the ~object~ has no set drain-time and no
521
  // registered callbacks, the forked process can be skipped and propagation
522
  // proceeds immediately to the parent as described.
523
 
524
  virtual function void drop_objection (uvm_object obj=null,
525
                                        string description="",
526
                                        int count=1);
527
    if(obj == null)
528
      obj = m_top;
529
    m_drop (obj, obj, description, count, 0);
530
  endfunction
531
 
532
 
533
  // Function- m_drop
534
 
535
  function void m_drop (uvm_object obj,
536
                        uvm_object source_obj,
537
                        string description="",
538
                        int count=1,
539
                        int in_top_thread=0);
540
 
541
    // Ignore drops if the count is 0
542
    if (count == 0)
543
      return;
544
 
545
    if (!m_total_count.exists(obj) || (count > m_total_count[obj])) begin
546
      if(m_cleared)
547
        return;
548
      uvm_report_fatal("OBJTN_ZERO", {"Object \"", obj.get_full_name(),
549
        "\" attempted to drop objection '",this.get_name(),"' count below zero"});
550
      return;
551
    end
552
 
553
    if (obj == source_obj) begin
554
      if (!m_source_count.exists(obj) || (count > m_source_count[obj])) begin
555
        if(m_cleared)
556
          return;
557
        uvm_report_fatal("OBJTN_ZERO", {"Object \"", obj.get_full_name(),
558
          "\" attempted to drop objection '",this.get_name(),"' count below zero"});
559
        return;
560
      end
561
      m_source_count[obj] -= count;
562
    end
563
 
564
    m_total_count[obj] -= count;
565
 
566
    if (m_trace_mode)
567
      m_report(obj,source_obj,description,count,"dropped");
568
 
569
    dropped(obj, source_obj, description, count);
570
 
571
    // if count != 0, no reason to fork
572
    if (m_total_count[obj] != 0) begin
573
      if (!m_prop_mode && obj != m_top)
574
        m_drop(m_top,source_obj,description, count, in_top_thread);
575
      else if (obj != m_top) begin
576
        this.m_propagate(obj, source_obj, description, count, 0, in_top_thread);
577
      end
578
 
579
    end
580
    else begin
581
        uvm_objection_context_object ctxt;
582
        if (m_context_pool.size())
583
          ctxt = m_context_pool.pop_front();
584
        else
585
          ctxt = new;
586
 
587
        ctxt.obj = obj;
588
        ctxt.source_obj = source_obj;
589
        ctxt.description = description;
590
        ctxt.count = count;
591
        ctxt.objection = this;
592
        // Need to be thread-safe, let the background
593
        // process handle it.
594
 
595
        // Why don't we look at in_top_thread here?  Because
596
        // a re-raise will kill the drain at object that it's
597
        // currently occuring at, and we need the leaf-level kills
598
        // to not cause accidental kills at branch-levels in
599
        // the propagation.
600
 
601
        // Using the background process just allows us to
602
        // separate the links of the chain.
603
        m_scheduled_list.push_back(ctxt);
604
 
605
    end // else: !if(m_total_count[obj] != 0)
606
 
607
  endfunction
608
 
609
 
610
  // Function: clear
611
  //
612
  // Immediately clears the objection state. All counts are cleared and the
613
  // any processes waiting on a call to wait_for(UVM_ALL_DROPPED, uvm_top)
614
  // are released.
615
  //
616
  // The caller, if a uvm_object-based object, should pass its 'this' handle
617
  // to the ~obj~ argument to document who cleared the objection.
618
  // Any drain_times set by the user are not affected.
619
  //
620
  virtual function void clear(uvm_object obj=null);
621
    string name;
622
    uvm_objection_context_object ctxt;
623
    int  idx;
624
 
625
    if (obj==null)
626
      obj=m_top;
627
    name = obj.get_full_name();
628
    if (name == "")
629
      name = "uvm_top";
630
    else
631
      name = obj.get_full_name();
632
    if (!m_top_all_dropped && get_objection_total(m_top))
633
      uvm_report_warning("OBJTN_CLEAR",{"Object '",name,
634
            "' cleared objection counts for ",get_name()});
635
    //Should there be a warning if there are outstanding objections?
636
    m_source_count.delete();
637
    m_total_count.delete();
638
 
639
    // Remove any scheduled drains from the static queue
640
    idx = 0;
641
    while (idx < m_scheduled_list.size()) begin
642
        if (m_scheduled_list[idx].objection == this) begin
643
            m_scheduled_list[idx].clear();
644
            m_context_pool.push_back(m_scheduled_list[idx]);
645
            m_scheduled_list.delete(idx);
646
        end
647
        else begin
648
            idx++;
649
        end
650
    end
651
 
652
    // Scheduled contexts and m_forked_lists have duplicate
653
    // entries... clear out one, free the other.
654
    m_scheduled_contexts.delete();
655
    while (m_forked_list.size()) begin
656
        m_forked_list[0].clear();
657
        m_context_pool.push_back(m_forked_list[0]);
658
        void'(m_forked_list.pop_front());
659
    end
660
 
661
    // running drains have a context and a process
662
    foreach (m_forked_contexts[o]) begin
663
`ifndef UVM_USE_PROCESS_CONTAINER
664
        m_drain_proc[o].kill();
665
        m_drain_proc.delete(o);
666
`else
667
        m_drain_proc[o].p.kill();
668
        m_drain_proc.delete(o);
669
`endif
670
 
671
        m_forked_contexts[o].clear();
672
        m_context_pool.push_back(m_forked_contexts[o]);
673
        m_forked_contexts.delete(o);
674
    end
675
 
676
    m_top_all_dropped = 0;
677
    m_cleared = 1;
678
    if (m_events.exists(m_top))
679
      ->m_events[m_top].all_dropped;
680
 
681
  endfunction
682
 
683
  // m_execute_scheduled_forks
684
  // -------------------------
685
 
686
  // background process; when non
687
  static task m_execute_scheduled_forks();
688
    while(1) begin
689
      wait(m_scheduled_list.size() != 0);
690
      if(m_scheduled_list.size() != 0) begin
691
          uvm_objection_context_object c;
692
          uvm_objection o;
693
          // Save off the context before the fork
694
          c = m_scheduled_list.pop_front();
695
          // A re-raise can use this to figure out props (if any)
696
          c.objection.m_scheduled_contexts[c.obj] = c;
697
          // The fork below pulls out from the forked list
698
          c.objection.m_forked_list.push_back(c);
699
          // The fork will guard the m_forked_drain call, but
700
          // a re-raise can kill m_forked_list contexts in the delta
701
          // before the fork executes.
702
          fork : guard
703
              automatic uvm_objection objection = c.objection;
704
              begin
705
                  // Check to maike sure re-raise didn't empty the fifo
706
                  if (objection.m_forked_list.size() > 0) begin
707
                      uvm_objection_context_object ctxt;
708
                      ctxt = objection.m_forked_list.pop_front();
709
                      // Clear it out of scheduled
710
                      objection.m_scheduled_contexts.delete(ctxt.obj);
711
                      // Move it in to forked (so re-raise can figure out props)
712
                      objection.m_forked_contexts[ctxt.obj] = ctxt;
713
                      // Save off our process handle, so a re-raise can kill it...
714
`ifndef UVM_USE_PROCESS_CONTAINER
715
                      objection.m_drain_proc[ctxt.obj] = process::self();
716
`else
717
                     begin
718
                        process_container_c c = new(process::self());
719
                        objection.m_drain_proc[ctxt.obj]=c;
720
                     end
721
`endif
722
                      // Execute the forked drain
723
                      objection.m_forked_drain(ctxt.obj, ctxt.source_obj, ctxt.description, ctxt.count, 1);
724
                      // Cleanup if we survived (no re-raises)
725
                      objection.m_drain_proc.delete(ctxt.obj);
726
                      objection.m_forked_contexts.delete(ctxt.obj);
727
                      // Clear out the context object (prevent memory leaks)
728
                      ctxt.clear();
729
                      // Save the context in the pool for later reuse
730
                      m_context_pool.push_back(ctxt);
731
                  end
732
              end
733
          join_none : guard
734
      end
735
    end
736
  endtask
737
 
738
 
739
  // m_forked_drain
740
  // -------------
741
 
742
  task m_forked_drain (uvm_object obj,
743
                       uvm_object source_obj,
744
                       string description="",
745
                       int count=1,
746
                       int in_top_thread=0);
747
 
748
      int diff_count;
749
 
750
      if (m_drain_time.exists(obj))
751
        `uvm_delay(m_drain_time[obj])
752
 
753
      if (m_trace_mode)
754
        m_report(obj,source_obj,description,count,"all_dropped");
755
 
756
      all_dropped(obj,source_obj,description, count);
757
 
758
          // wait for all_dropped cbs to complete
759
      wait fork;
760
 
761
      /* NOT NEEDED - Any raise would have killed us!
762
      if(!m_total_count.exists(obj))
763
        diff_count = -count;
764
      else
765
        diff_count = m_total_count[obj] - count;
766
      */
767
 
768
      // we are ready to delete the 0-count entries for the current
769
      // object before propagating up the hierarchy.
770
      if (m_source_count.exists(obj) && m_source_count[obj] == 0)
771
        m_source_count.delete(obj);
772
 
773
      if (m_total_count.exists(obj) && m_total_count[obj] == 0)
774
        m_total_count.delete(obj);
775
 
776
      if (!m_prop_mode && obj != m_top)
777
        m_drop(m_top,source_obj,description, count, 1);
778
      else if (obj != m_top)
779
        m_propagate(obj, source_obj, description, count, 0, 1);
780
 
781
  endtask
782
 
783
 
784
  // m_init_objections
785
  // -----------------
786
 
787
  // Forks off the single background process
788
  static function void m_init_objections();
789
    fork
790
      uvm_objection::m_execute_scheduled_forks();
791
    join_none
792
  endfunction
793
 
794
  // Function: set_drain_time
795
  //
796
  // Sets the drain time on the given ~object~ to ~drain~.
797
  //
798
  // The drain time is the amount of time to wait once all objections have
799
  // been dropped before calling the all_dropped callback and propagating
800
  // the objection to the parent.
801
  //
802
  // If a new objection for this ~object~ or any of its descendants is raised
803
  // during the drain time or during execution of the all_dropped callbacks,
804
  // the drain_time/all_dropped execution is terminated.
805
 
806
  // AE: set_drain_time(drain,obj=null)?
807
  function void set_drain_time (uvm_object obj=null, time drain);
808
    if (obj==null)
809
      obj = m_top;
810
    m_drain_time[obj] = drain;
811
  endfunction
812
 
813
 
814
  //----------------------
815
  // Group: Callback Hooks
816
  //----------------------
817
 
818
  // Function: raised
819
  //
820
  // Objection callback that is called when a  has reached ~obj~.
821
  // The default implementation calls .
822
 
823
  virtual function void raised (uvm_object obj,
824
                                uvm_object source_obj,
825
                                string description,
826
                                int count);
827
    uvm_component comp;
828
    if ($cast(comp,obj))
829
      comp.raised(this, source_obj, description, count);
830
    `uvm_do_callbacks(uvm_objection,uvm_objection_callback,raised(this,obj,source_obj,description,count))
831
    if (m_events.exists(obj))
832
       ->m_events[obj].raised;
833
  endfunction
834
 
835
 
836
  // Function: dropped
837
  //
838
  // Objection callback that is called when a  has reached ~obj~.
839
  // The default implementation calls .
840
 
841
  virtual function void dropped (uvm_object obj,
842
                                 uvm_object source_obj,
843
                                 string description,
844
                                 int count);
845
    uvm_component comp;
846
    if($cast(comp,obj))
847
      comp.dropped(this, source_obj, description, count);
848
    `uvm_do_callbacks(uvm_objection,uvm_objection_callback,dropped(this,obj,source_obj,description,count))
849
    if (m_events.exists(obj))
850
       ->m_events[obj].dropped;
851
  endfunction
852
 
853
 
854
  // Function: all_dropped
855
  //
856
  // Objection callback that is called when a  has reached ~obj~,
857
  // and the total count for ~obj~ goes to zero. This callback is executed
858
  // after the drain time associated with ~obj~. The default implementation
859
  // calls .
860
 
861
  virtual task all_dropped (uvm_object obj,
862
                            uvm_object source_obj,
863
                            string description,
864
                            int count);
865
    uvm_component comp;
866
    if($cast(comp,obj))
867
      comp.all_dropped(this, source_obj, description, count);
868
    `uvm_do_callbacks(uvm_objection,uvm_objection_callback,all_dropped(this,obj,source_obj,description,count))
869
    if (m_events.exists(obj))
870
       ->m_events[obj].all_dropped;
871
    if (obj == m_top)
872
      m_top_all_dropped = 1;
873
  endtask
874
 
875
 
876
  //------------------------
877
  // Group: Objection Status
878
  //------------------------
879
 
880
  // Function: get_objectors
881
  //
882
  // Returns the current list of objecting objects (objects that
883
  // raised an objection but have not dropped it).
884
 
885
  function void get_objectors(ref uvm_object list[$]);
886
    list.delete();
887
    foreach (m_source_count[obj]) list.push_back(obj);
888
  endfunction
889
 
890
 
891
  // Task: wait_for
892
  //
893
  // Waits for the raised, dropped, or all_dropped ~event~ to occur in
894
  // the given ~obj~. The task returns after all corresponding callbacks
895
  // for that event have been executed.
896
  //
897
  task wait_for(uvm_objection_event objt_event, uvm_object obj=null);
898
 
899
     if (obj==null)
900
       obj = m_top;
901
 
902
     if (!m_events.exists(obj)) begin
903
       m_events[obj] = new;
904
     end
905
 
906
     m_events[obj].waiters++;
907
     case (objt_event)
908
       UVM_RAISED:      @(m_events[obj].raised);
909
       UVM_DROPPED:     @(m_events[obj].dropped);
910
       UVM_ALL_DROPPED: @(m_events[obj].all_dropped);
911
     endcase
912
 
913
     m_events[obj].waiters--;
914
 
915
     if (m_events[obj].waiters == 0)
916
       m_events.delete(obj);
917
 
918
   endtask
919
 
920
 
921
   task wait_for_total_count(uvm_object obj=null, int count=0);
922
     if (obj==null)
923
       obj = m_top;
924
 
925
     if(!m_total_count.exists(obj) && count == 0)
926
       return;
927
     if (count == 0)
928
        wait (!m_total_count.exists(obj) && count == 0);
929
     else
930
        wait (m_total_count.exists(obj) && m_total_count[obj] == count);
931
   endtask
932
 
933
 
934
  // Function: get_objection_count
935
  //
936
  // Returns the current number of objections raised by the given ~object~.
937
 
938
  function int get_objection_count (uvm_object obj=null);
939
    if (obj==null)
940
      obj = m_top;
941
 
942
    if (!m_source_count.exists(obj))
943
      return 0;
944
    return m_source_count[obj];
945
  endfunction
946
 
947
 
948
  // Function: get_objection_total
949
  //
950
  // Returns the current number of objections raised by the given ~object~
951
  // and all descendants.
952
 
953
  function int get_objection_total (uvm_object obj=null);
954
 
955
    if (obj==null)
956
      obj = m_top;
957
 
958
    if (!m_total_count.exists(obj))
959
      return 0;
960
    else
961
      return m_total_count[obj];
962
 
963
  endfunction
964
 
965
 
966
  // Function: get_drain_time
967
  //
968
  // Returns the current drain time set for the given ~object~ (default: 0 ns).
969
 
970
  function time get_drain_time (uvm_object obj=null);
971
    if (obj==null)
972
      obj = m_top;
973
 
974
    if (!m_drain_time.exists(obj))
975
      return 0;
976
    return m_drain_time[obj];
977
  endfunction
978
 
979
 
980
  // m_display_objections
981
 
982
  protected function string m_display_objections(uvm_object obj=null, bit show_header=1);
983
 
984
    static string blank="                                                                                   ";
985
 
986
    string s;
987
    int total;
988
    uvm_object list[string];
989
    uvm_object curr_obj;
990
    int depth;
991
    string name;
992
    string this_obj_name;
993
    string curr_obj_name;
994
 
995
    foreach (m_total_count[o]) begin
996
      uvm_object theobj = o;
997
      if ( m_total_count[o] > 0)
998
        list[theobj.get_full_name()] = theobj;
999
    end
1000
 
1001
    if (obj==null)
1002
      obj = m_top;
1003
 
1004
    total = get_objection_total(obj);
1005
 
1006
    s = $sformatf("The total objection count is %0d\n",total);
1007
 
1008
    if (total == 0)
1009
      return s;
1010
 
1011
    s = {s,"---------------------------------------------------------\n"};
1012
    s = {s,"Source  Total   \n"};
1013
    s = {s,"Count   Count   Object\n"};
1014
    s = {s,"---------------------------------------------------------\n"};
1015
 
1016
 
1017
    this_obj_name = obj.get_full_name();
1018
    curr_obj_name = this_obj_name;
1019
 
1020
    do begin
1021
 
1022
      curr_obj = list[curr_obj_name];
1023
 
1024
      // determine depth
1025
      depth=0;
1026
      foreach (curr_obj_name[i])
1027
        if (curr_obj_name[i] == ".")
1028
          depth++;
1029
 
1030
      // determine leaf name
1031
      name = curr_obj_name;
1032
      for (int i=curr_obj_name.len()-1;i >= 0; i--)
1033
        if (curr_obj_name[i] == ".") begin
1034
           name = curr_obj_name.substr(i+1,curr_obj_name.len()-1);
1035
           break;
1036
        end
1037
      if (curr_obj_name == "")
1038
        name = "uvm_top";
1039
      else
1040
        depth++;
1041
 
1042
      // print it
1043
      s = {s, $sformatf("%-6d  %-6d %s%s\n",
1044
         m_source_count.exists(curr_obj) ? m_source_count[curr_obj] : 0,
1045
         m_total_count.exists(curr_obj) ? m_total_count[curr_obj] : 0,
1046
         blank.substr(0,2*depth), name)};
1047
 
1048
    end while (list.next(curr_obj_name) &&
1049
        curr_obj_name.substr(0,this_obj_name.len()-1) == this_obj_name);
1050
 
1051
    s = {s,"---------------------------------------------------------\n"};
1052
 
1053
    return s;
1054
 
1055
  endfunction
1056
 
1057
 
1058
  function string convert2string();
1059
    return m_display_objections(m_top,1);
1060
  endfunction
1061
 
1062
 
1063
  // Function: display_objections
1064
  //
1065
  // Displays objection information about the given ~object~. If ~object~ is
1066
  // not specified or ~null~, the implicit top-level component, , is
1067
  // chosen. The ~show_header~ argument allows control of whether a header is
1068
  // output.
1069
 
1070
  function void display_objections(uvm_object obj=null, bit show_header=1);
1071
        string m = m_display_objections(obj,show_header);
1072
    `uvm_info("UVM/OBJ/DISPLAY",m,UVM_NONE)
1073
  endfunction
1074
 
1075
 
1076
  // Below is all of the basic data stuff that is needed for a uvm_object
1077
  // for factory registration, printing, comparing, etc.
1078
 
1079
  typedef uvm_object_registry#(uvm_objection,"uvm_objection") type_id;
1080
  static function type_id get_type();
1081
    return type_id::get();
1082
  endfunction
1083
 
1084
  function uvm_object create (string name="");
1085
    uvm_objection tmp = new(name);
1086
    return tmp;
1087
  endfunction
1088
 
1089
  virtual function string get_type_name ();
1090
    return "uvm_objection";
1091
  endfunction
1092
 
1093
  function void do_copy (uvm_object rhs);
1094
    uvm_objection _rhs;
1095
    $cast(_rhs, rhs);
1096
    m_source_count = _rhs.m_source_count;
1097
    m_total_count  = _rhs.m_total_count;
1098
    m_drain_time   = _rhs.m_drain_time;
1099
    m_prop_mode    = _rhs.m_prop_mode;
1100
  endfunction
1101
 
1102
endclass
1103
 
1104
// TODO: change to plusarg
1105
//`define UVM_DEFAULT_TIMEOUT 9200s
1106
 
1107
typedef class uvm_cmdline_processor;
1108
 
1109
 
1110
 
1111
//------------------------------------------------------------------------------
1112
//
1113
// Class- uvm_test_done_objection DEPRECATED
1114
//
1115
// Provides built-in end-of-test coordination
1116
//------------------------------------------------------------------------------
1117
 
1118
class uvm_test_done_objection extends uvm_objection;
1119
 
1120
   protected static uvm_test_done_objection m_inst;
1121
  protected bit m_forced;
1122
 
1123
  // For communicating all objections dropped and end of phasing
1124
  local  bit m_executing_stop_processes;
1125
  local  int m_n_stop_threads;
1126
 
1127
 
1128
  // Function- new DEPRECATED
1129
  //
1130
  // Creates the singleton test_done objection. Users must not call
1131
  // this method directly.
1132
 
1133
  function new(string name="uvm_test_done");
1134
    super.new(name);
1135
  endfunction
1136
 
1137
 
1138
  // Function- qualify DEPRECATED
1139
  //
1140
  // Checks that the given ~object~ is derived from either  or
1141
  // .
1142
 
1143
  virtual function void qualify(uvm_object obj=null,
1144
                                bit is_raise,
1145
                                string description);
1146
    uvm_component c;
1147
    uvm_sequence_base s;
1148
    string nm = is_raise ? "raise_objection" : "drop_objection";
1149
    string desc = description == "" ? "" : {" (\"", description, "\")"};
1150
    if(! ($cast(c,obj) || $cast(s,obj))) begin
1151
      uvm_report_error("TEST_DONE_NOHIER", {"A non-hierarchical object, '",
1152
        obj.get_full_name(), "' (", obj.get_type_name(),") was used in a call ",
1153
        "to uvm_test_done.", nm,"(). For this objection, a sequence ",
1154
        "or component is required.", desc });
1155
    end
1156
  endfunction
1157
 
1158
 
1159
`ifndef UVM_NO_DEPRECATED
1160
  // m_do_stop_all
1161
  // -------------
1162
 
1163
  task m_do_stop_all(uvm_component comp);
1164
 
1165
    string name;
1166
 
1167
    // we use an external traversal to ensure all forks are
1168
    // made from a single threaad.
1169
    if (comp.get_first_child(name))
1170
      do begin
1171
        m_do_stop_all(comp.get_child(name));
1172
      end
1173
      while (comp.get_next_child(name));
1174
 
1175
    if (comp.enable_stop_interrupt) begin
1176
      m_n_stop_threads++;
1177
      fork begin
1178
        comp.stop_phase(run_ph);
1179
        m_n_stop_threads--;
1180
      end
1181
      join_none
1182
    end
1183
  endtask
1184
 
1185
 
1186
  // Function- stop_request DEPRECATED
1187
  //
1188
  // Calling this function triggers the process of shutting down the currently
1189
  // running task-based phase. This process involves calling all components'
1190
  // stop tasks for those components whose enable_stop_interrupt bit is set.
1191
  // Once all stop tasks return, or once the optional global_stop_timeout
1192
  // expires, all components' kill method is called, effectively ending the
1193
  // current phase. The uvm_top will then begin execution of the next phase,
1194
  // if any.
1195
 
1196
  function void stop_request();
1197
    `uvm_info_context("STOP_REQ",
1198
                      "Stop-request called. Waiting for all-dropped on uvm_test_done",
1199
                      UVM_FULL,m_top);
1200
    fork
1201
      m_stop_request();
1202
    join_none
1203
  endfunction
1204
 
1205
  task m_stop_request();
1206
    raise_objection(m_top,"stop_request called; raising test_done objection");
1207
    uvm_wait_for_nba_region();
1208
    drop_objection(m_top,"stop_request called; dropping test_done objection");
1209
  endtask
1210
 
1211
 
1212
  // Variable- stop_timeout DEPRECATED
1213
  //
1214
  // These set watchdog timers for task-based phases and stop tasks. You cannot
1215
  // disable the timeouts. When set to 0, a timeout of the maximum time possible
1216
  // is applied. A timeout at this value usually indicates a problem with your
1217
  // testbench. You should lower the timeout to prevent "never-ending"
1218
  // simulations.
1219
 
1220
  time stop_timeout = 0;
1221
 
1222
 
1223
  // Task- all_dropped DEPRECATED
1224
  //
1225
  // This callback is called when the given ~object's~ objection count reaches
1226
  // zero; if the ~object~ is the implicit top-level,  then it means
1227
  // there are no more objections raised for the ~uvm_test_done~ objection.
1228
  // Thus, after calling , this method will call
1229
  //  to stop the current task-based phase (e.g. run).
1230
 
1231
  virtual task all_dropped (uvm_object obj,
1232
                            uvm_object source_obj,
1233
                            string description,
1234
                            int count);
1235
    if (obj != m_top) begin
1236
      super.all_dropped(obj,source_obj,description,count);
1237
      return;
1238
    end
1239
 
1240
    m_top.all_dropped(this, source_obj, description, count);
1241
 
1242
    // All stop tasks are forked from a single thread within a 'guard' process
1243
    // so 'disable fork' can be used.
1244
 
1245
    if(m_cleared == 0) begin
1246
      `uvm_info_context("TEST_DONE",
1247
          "All end-of-test objections have been dropped. Calling stop tasks",
1248
          UVM_FULL,m_top);
1249
      fork begin // guard
1250
        fork
1251
          begin
1252
            m_executing_stop_processes = 1;
1253
            m_do_stop_all(m_top);
1254
            wait (m_n_stop_threads == 0);
1255
            m_executing_stop_processes = 0;
1256
          end
1257
          begin
1258
            if (stop_timeout == 0)
1259
              wait(stop_timeout != 0);
1260
            `uvm_delay(stop_timeout)
1261
            `uvm_error("STOP_TIMEOUT",
1262
              {$sformatf("Stop-task timeout of %0t expired. ", stop_timeout),
1263
                 "'run' phase ready to proceed to extract phase"})
1264
          end
1265
        join_any
1266
        disable fork;
1267
      end
1268
      join // guard
1269
 
1270
      `uvm_info_context("TEST_DONE", {"'run' phase is ready ",
1271
                        "to proceed to the 'extract' phase"}, UVM_LOW,m_top)
1272
 
1273
    end
1274
 
1275
    if (m_events.exists(obj))
1276
      ->m_events[obj].all_dropped;
1277
    m_top_all_dropped = 1;
1278
 
1279
  endtask
1280
 
1281
 
1282
  // Function- raise_objection DEPRECATED
1283
  //
1284
  // Calls  after calling .
1285
  // If the ~object~ is not provided or is ~null~, then the implicit top-level
1286
  // component, ~uvm_top~, is chosen.
1287
 
1288
  virtual function void raise_objection (uvm_object obj=null,
1289
                                         string description="",
1290
                                         int count=1);
1291
    if(obj==null)
1292
      obj=m_top;
1293
    else
1294
      qualify(obj, 1, description);
1295
 
1296
    if (m_executing_stop_processes) begin
1297
      string desc = description == "" ? "" : {"(\"", description, "\") "};
1298
      `uvm_warning("ILLRAISE", {"The uvm_test_done objection was ",
1299
        "raised ", desc, "during processing of a stop_request, i.e. stop ",
1300
        "task execution. The objection is ignored by the stop process"})
1301
        return;
1302
    end
1303
 
1304
    super.raise_objection(obj,description,count);
1305
 
1306
  endfunction
1307
 
1308
 
1309
  // Function- drop_objection DEPRECATED
1310
  //
1311
  // Calls  after calling .
1312
  // If the ~object~ is not provided or is ~null~, then the implicit top-level
1313
  // component, ~uvm_top~, is chosen.
1314
 
1315
  virtual function void drop_objection (uvm_object obj=null,
1316
                                        string description="",
1317
                                        int count=1);
1318
    if(obj==null)
1319
      obj=m_top;
1320
    else
1321
      qualify(obj, 0, description);
1322
    super.drop_objection(obj,description,count);
1323
  endfunction
1324
 
1325
 
1326
  // Task- force_stop DEPRECATED
1327
  //
1328
  // Forces the propagation of the all_dropped() callback, even if there are still
1329
  // outstanding objections. The net effect of this action is to forcibly end
1330
  // the current phase.
1331
 
1332
  virtual task force_stop(uvm_object obj=null);
1333
    uvm_report_warning("FORCE_STOP",{"Object '",
1334
       (obj!=null?obj.get_name():""),"' called force_stop"});
1335
    m_cleared = 1;
1336
    all_dropped(m_top,obj,"force_stop() called",1);
1337
    clear(obj);
1338
  endtask
1339
`endif
1340
 
1341
 
1342
  // Below are basic data operations needed for all uvm_objects
1343
  // for factory registration, printing, comparing, etc.
1344
 
1345
  typedef uvm_object_registry#(uvm_test_done_objection,"uvm_test_done") type_id;
1346
  static function type_id get_type();
1347
    return type_id::get();
1348
  endfunction
1349
 
1350
  function uvm_object create (string name="");
1351
    uvm_test_done_objection tmp = new(name);
1352
    return tmp;
1353
  endfunction
1354
 
1355
  virtual function string get_type_name ();
1356
    return "uvm_test_done";
1357
  endfunction
1358
 
1359
  static function uvm_test_done_objection get();
1360
    if(m_inst == null)
1361
      m_inst = uvm_test_done_objection::type_id::create("run");
1362
    return m_inst;
1363
  endfunction
1364
 
1365
endclass
1366
 
1367
 
1368
 
1369
// Have a pool of context objects to use
1370
class uvm_objection_context_object;
1371
    uvm_object obj;
1372
    uvm_object source_obj;
1373
    string description;
1374
    int    count;
1375
    uvm_objection objection;
1376
 
1377
    // Clears the values stored within the object,
1378
    // preventing memory leaks from reused objects
1379
    function void clear();
1380
        obj = null;
1381
        source_obj = null;
1382
        description = "";
1383
        count = 0;
1384
        objection = null;
1385
    endfunction : clear
1386
endclass
1387
 
1388
// Typedef - Exists for backwards compat
1389
typedef uvm_objection uvm_callbacks_objection;
1390
 
1391
//------------------------------------------------------------------------------
1392
//
1393
// Class: uvm_objection_callback
1394
//
1395
//------------------------------------------------------------------------------
1396
// The uvm_objection is the callback type that defines the callback
1397
// implementations for an objection callback. A user uses the callback
1398
// type uvm_objection_cbs_t to add callbacks to specific objections.
1399
//
1400
// For example:
1401
//
1402
//| class my_objection_cb extends uvm_objection_callback;
1403
//|   function new(string name);
1404
//|     super.new(name);
1405
//|   endfunction
1406
//|
1407
//|   virtual function void raised (uvm_objection objection, uvm_object obj,
1408
//|       uvm_object source_obj, string description, int count);
1409
//|       `uvm_info("RAISED","%0t: Objection %s: Raised for %s", $time, objection.get_name(),
1410
//|       obj.get_full_name());
1411
//|   endfunction
1412
//| endclass
1413
//| ...
1414
//| initial begin
1415
//|   my_objection_cb cb = new("cb");
1416
//|   uvm_objection_cbs_t::add(null, cb); //typewide callback
1417
//| end
1418
 
1419
 
1420
class uvm_objection_callback extends uvm_callback;
1421
  function new(string name);
1422
    super.new(name);
1423
  endfunction
1424
 
1425
  // Function: raised
1426
  //
1427
  // Objection raised callback function. Called by .
1428
 
1429
  virtual function void raised (uvm_objection objection, uvm_object obj,
1430
      uvm_object source_obj, string description, int count);
1431
  endfunction
1432
 
1433
  // Function: dropped
1434
  //
1435
  // Objection dropped callback function. Called by .
1436
 
1437
  virtual function void dropped (uvm_objection objection, uvm_object obj,
1438
      uvm_object source_obj, string description, int count);
1439
  endfunction
1440
 
1441
  // Function: all_dropped
1442
  //
1443
  // Objection all_dropped callback function. Called by .
1444
 
1445
  virtual task all_dropped (uvm_objection objection, uvm_object obj,
1446
      uvm_object source_obj, string description, int count);
1447
  endtask
1448
 
1449
endclass
1450
 
1451
 
1452
`endif
1453
 

powered by: WebSVN 2.1.0

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