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

Subversion Repositories uart2bus_testbench

[/] [uart2bus_testbench/] [trunk/] [tb/] [uvm_src/] [base/] [uvm_port_base.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 Synopsys, Inc.
6
//   Copyright 2013 Cisco Systems, Inc.
7
//   All Rights Reserved Worldwide
8
//
9
//   Licensed under the Apache License, Version 2.0 (the "License"); you may not
10
//   use this file except in compliance with the License.  You may obtain a copy
11
//   of the License at
12
//
13
//       http://www.apache.org/licenses/LICENSE-2.0
14
//
15
//   Unless required by applicable law or agreed to in writing, software
16
//   distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
17
//   WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
18
//   License for the specific language governing permissions and limitations
19
//   under the License.
20
//------------------------------------------------------------------------------
21
 
22
const int UVM_UNBOUNDED_CONNECTIONS = -1;
23
const string s_connection_error_id = "Connection Error";
24
const string s_connection_warning_id = "Connection Warning";
25
const string s_spaces = "                       ";
26
 
27
typedef class uvm_port_component_base;
28
typedef uvm_port_component_base uvm_port_list[string];
29
 
30
 
31
// TITLE: Port Base Classes
32
//
33
 
34
 
35
//------------------------------------------------------------------------------
36
//
37
// CLASS: uvm_port_component_base
38
//
39
//------------------------------------------------------------------------------
40
// This class defines an interface for obtaining a port's connectivity lists
41
// after or during the end_of_elaboration phase.  The sub-class,
42
// , implements this interface.
43
//
44
// The connectivity lists are returned in the form of handles to objects of this
45
// type. This allowing traversal of any port's fan-out and fan-in network
46
// through recursive calls to  and . Each
47
// port's full name and type name can be retrieved using ~get_full_name~ and
48
// ~get_type_name~ methods inherited from .
49
//------------------------------------------------------------------------------
50
 
51
virtual class uvm_port_component_base extends uvm_component;
52
 
53
  function new (string name, uvm_component parent);
54
    super.new(name,parent);
55
  endfunction
56
 
57
  // Function: get_connected_to
58
  //
59
  // For a port or export type, this function fills ~list~ with all
60
  // of the ports, exports and implementations that this port is
61
  // connected to.
62
 
63
  pure virtual function void get_connected_to(ref uvm_port_list list);
64
 
65
  // Function: get_provided_to
66
  //
67
  // For an implementation or export type, this function fills ~list~ with all
68
  // of the ports, exports and implementations that this port is
69
  // provides its implementation to.
70
 
71
  pure virtual function void get_provided_to(ref uvm_port_list list);
72
 
73
  // Function: is_port
74
  //
75
  pure virtual function bit is_port();
76
 
77
  // Function: is_export
78
  //
79
  pure virtual function bit is_export();
80
 
81
  // Function: is_imp
82
  //
83
  // These function determine the type of port. The functions are
84
  // mutually exclusive; one will return 1 and the other two will
85
  // return 0.
86
 
87
  pure virtual function bit is_imp();
88
 
89
  // Turn off auto config by not calling build_phase()
90
  virtual function void build_phase(uvm_phase phase);
91
    build(); //for backward compat
92
    return;
93
  endfunction
94
 
95
  virtual task do_task_phase (uvm_phase phase);
96
  endtask
97
endclass
98
 
99
 
100
//------------------------------------------------------------------------------
101
//
102
// CLASS: uvm_port_component #(PORT)
103
//
104
//------------------------------------------------------------------------------
105
// See description of  for information about this class
106
//------------------------------------------------------------------------------
107
 
108
 
109
class uvm_port_component #(type PORT=uvm_object) extends uvm_port_component_base;
110
 
111
  PORT m_port;
112
 
113
  function new (string name, uvm_component parent, PORT port);
114
    super.new(name,parent);
115
    if (port == null)
116
      uvm_report_fatal("Bad usage", "Null handle to port", UVM_NONE);
117
    m_port = port;
118
  endfunction
119
 
120
  virtual function string get_type_name();
121
    if(m_port == null) return "uvm_port_component";
122
    return m_port.get_type_name();
123
  endfunction
124
 
125
  virtual function void resolve_bindings();
126
    m_port.resolve_bindings();
127
  endfunction
128
 
129
  // Function: get_port
130
  //
131
  // Retrieve the actual port object that this proxy refers to.
132
 
133
  function PORT get_port();
134
    return m_port;
135
  endfunction
136
 
137
  virtual function void get_connected_to(ref uvm_port_list list);
138
    m_port.get_connected_to(list);
139
  endfunction
140
 
141
  virtual function void get_provided_to(ref uvm_port_list list);
142
    m_port.get_provided_to(list);
143
  endfunction
144
 
145
  function bit is_port ();
146
    return m_port.is_port();
147
  endfunction
148
 
149
  function bit is_export ();
150
    return m_port.is_export();
151
  endfunction
152
 
153
  function bit is_imp ();
154
    return m_port.is_imp();
155
  endfunction
156
 
157
endclass
158
 
159
 
160
//------------------------------------------------------------------------------
161
//
162
// CLASS: uvm_port_base #(IF)
163
//
164
//------------------------------------------------------------------------------
165
//
166
// Transaction-level communication between components is handled via its ports,
167
// exports, and imps, all of which derive from this class.
168
//
169
// The uvm_port_base extends IF, which is the type of the interface implemented
170
// by derived port, export, or implementation. IF is also a type parameter to
171
// uvm_port_base.
172
//
173
//   IF  - The interface type implemented by the subtype to this base port
174
//
175
// The UVM provides a complete set of ports, exports, and imps for the OSCI-
176
// standard TLM interfaces. They can be found in the ../src/tlm/ directory.
177
// For the TLM interfaces, the IF parameter is always .
178
//
179
// Just before , an internal
180
//  process occurs, after which each port and
181
// export holds a list of all imps connected to it via hierarchical connections
182
// to other ports and exports. In effect, we are collapsing the port's fanout,
183
// which can span several levels up and down the component hierarchy, into a
184
// single array held local to the port. Once the list is determined, the port's
185
// min and max connection settings can be checked and enforced.
186
//
187
// uvm_port_base possesses the properties of components in that they have a
188
// hierarchical instance path and parent. Because SystemVerilog does not support
189
// multiple inheritance, uvm_port_base cannot extend both the interface it
190
// implements and . Thus, uvm_port_base contains a local instance
191
// of uvm_component, to which it delegates such commands as get_name,
192
// get_full_name, and get_parent.
193
//
194
//------------------------------------------------------------------------------
195
 
196
virtual class uvm_port_base #(type IF=uvm_void) extends IF;
197
 
198
 
199
  typedef uvm_port_base #(IF) this_type;
200
 
201
  // local, protected, and non-user properties
202
  protected int unsigned  m_if_mask;
203
  protected this_type     m_if;    // REMOVE
204
  protected int unsigned  m_def_index;
205
  uvm_port_component #(this_type) m_comp;
206
  local this_type m_provided_by[string];
207
  local this_type m_provided_to[string];
208
  local uvm_port_type_e   m_port_type;
209
  local int               m_min_size;
210
  local int               m_max_size;
211
  local bit               m_resolved;
212
  local this_type         m_imp_list[string];
213
 
214
  // Function: new
215
  //
216
  // The first two arguments are the normal  constructor
217
  // arguments.
218
  //
219
  // The ~port_type~ can be one of , , or
220
  // .
221
  //
222
  // The ~min_size~ and ~max_size~ specify the minimum and maximum number of
223
  // implementation (imp) ports that must be connected to this port base by the
224
  // end of elaboration. Setting ~max_size~ to ~UVM_UNBOUNDED_CONNECTIONS~ sets no
225
  // maximum, i.e., an unlimited number of connections are allowed.
226
  //
227
  // By default, the parent/child relationship of any port being connected to
228
  // this port is not checked. This can be overridden by configuring the
229
  // port's ~check_connection_relationships~ bit via ~uvm_config_int::set()~. See
230
  //  for more information.
231
 
232
  function new (string name,
233
                uvm_component parent,
234
                uvm_port_type_e port_type,
235
                int min_size=0,
236
                int max_size=1);
237
    uvm_component comp;
238
    int tmp;
239
    m_port_type = port_type;
240
    m_min_size  = min_size;
241
    m_max_size  = max_size;
242
    m_comp = new(name, parent, this);
243
 
244
    if (!uvm_config_int::get(m_comp, "", "check_connection_relationships",tmp))
245
      m_comp.set_report_id_action(s_connection_warning_id, UVM_NO_ACTION);
246
 
247
  endfunction
248
 
249
 
250
  // Function: get_name
251
  //
252
  // Returns the leaf name of this port.
253
 
254
  function string get_name();
255
    return m_comp.get_name();
256
  endfunction
257
 
258
 
259
  // Function: get_full_name
260
  //
261
  // Returns the full hierarchical name of this port.
262
 
263
  virtual function string get_full_name();
264
    return m_comp.get_full_name();
265
  endfunction
266
 
267
 
268
  // Function: get_parent
269
  //
270
  // Returns the handle to this port's parent, or ~null~ if it has no parent.
271
 
272
  virtual function uvm_component get_parent();
273
    return m_comp.get_parent();
274
  endfunction
275
 
276
 
277
  // Function: get_comp
278
  //
279
  // Returns a handle to the internal proxy component representing this port.
280
  //
281
  // Ports are considered components. However, they do not inherit
282
  // . Instead, they contain an instance of
283
  //  that serves as a proxy to this port.
284
 
285
  virtual function uvm_port_component_base get_comp();
286
    return m_comp;
287
  endfunction
288
 
289
 
290
  // Function: get_type_name
291
  //
292
  // Returns the type name to this port. Derived port classes must implement
293
  // this method to return the concrete type. Otherwise, only a generic
294
  // "uvm_port", "uvm_export" or "uvm_implementation" is returned.
295
 
296
  virtual function string get_type_name();
297
    case( m_port_type )
298
      UVM_PORT : return "port";
299
      UVM_EXPORT : return "export";
300
      UVM_IMPLEMENTATION : return "implementation";
301
    endcase
302
  endfunction
303
 
304
 
305
  // Function: min_size
306
  //
307
  // Returns the minimum number of implementation ports that must
308
  // be connected to this port by the end_of_elaboration phase.
309
 
310
  function int max_size ();
311
    return m_max_size;
312
  endfunction
313
 
314
 
315
  // Function: max_size
316
  //
317
  // Returns the maximum number of implementation ports that must
318
  // be connected to this port by the end_of_elaboration phase.
319
 
320
  function int min_size ();
321
    return m_min_size;
322
  endfunction
323
 
324
 
325
  // Function: is_unbounded
326
  //
327
  // Returns 1 if this port has no maximum on the number of implementation
328
  // ports this port can connect to. A port is unbounded when the ~max_size~
329
  // argument in the constructor is specified as ~UVM_UNBOUNDED_CONNECTIONS~.
330
 
331
  function bit is_unbounded ();
332
    return (m_max_size ==  UVM_UNBOUNDED_CONNECTIONS);
333
  endfunction
334
 
335
 
336
  // Function: is_port
337
 
338
  function bit is_port ();
339
    return m_port_type == UVM_PORT;
340
  endfunction
341
 
342
  // Function: is_export
343
 
344
  function bit is_export ();
345
    return m_port_type == UVM_EXPORT;
346
  endfunction
347
 
348
  // Function: is_imp
349
  //
350
  // Returns 1 if this port is of the type given by the method name,
351
  // 0 otherwise.
352
 
353
  function bit is_imp ();
354
    return m_port_type == UVM_IMPLEMENTATION;
355
  endfunction
356
 
357
 
358
  // Function: size
359
  //
360
  // Gets the number of implementation ports connected to this port. The value
361
  // is not valid before the end_of_elaboration phase, as port connections have
362
  // not yet been resolved.
363
 
364
  function int size ();
365
    return m_imp_list.num();
366
  endfunction
367
 
368
 
369
  function void set_if (int index=0);
370
    m_if = get_if(index);
371
    if (m_if != null)
372
      m_def_index = index;
373
  endfunction
374
 
375
  function int m_get_if_mask();
376
    return m_if_mask;
377
  endfunction
378
 
379
 
380
  // Function: set_default_index
381
  //
382
  // Sets the default implementation port to use when calling an interface
383
  // method. This method should only be called on UVM_EXPORT types. The value
384
  // must not be set before the end_of_elaboration phase, when port connections
385
  // have not yet been resolved.
386
 
387
  function void set_default_index (int index);
388
    m_def_index = index;
389
  endfunction
390
 
391
 
392
  // Function: connect
393
  //
394
  // Connects this port to the given ~provider~ port. The ports must be
395
  // compatible in the following ways
396
  //
397
  // - Their type parameters must match
398
  //
399
  // - The ~provider~'s interface type (blocking, non-blocking, analysis, etc.)
400
  //   must be compatible. Each port has an interface mask that encodes the
401
  //   interface(s) it supports. If the bitwise AND of these masks is equal to
402
  //   the this port's mask, the requirement is met and the ports are
403
  //   compatible. For example, a uvm_blocking_put_port #(T) is compatible with
404
  //   a uvm_put_export #(T) and uvm_blocking_put_imp #(T) because the export
405
  //   and imp provide the interface required by the uvm_blocking_put_port.
406
  //
407
  // - Ports of type  can only connect to other exports or imps.
408
  //
409
  // - Ports of type  cannot be connected, as they are
410
  //   bound to the component that implements the interface at time of
411
  //   construction.
412
  //
413
  // In addition to type-compatibility checks, the relationship between this
414
  // port and the ~provider~ port will also be checked if the port's
415
  // ~check_connection_relationships~ configuration has been set. (See 
416
  // for more information.)
417
  //
418
  // Relationships, when enabled, are checked are as follows:
419
  //
420
  // - If this port is a UVM_PORT type, the ~provider~ can be a parent port,
421
  //   or a sibling export or implementation port.
422
  //
423
  // - If this port is a  type, the provider can be a child
424
  //   export or implementation port.
425
  //
426
  // If any relationship check is violated, a warning is issued.
427
  //
428
  // Note- the  method is related to but not the same
429
  // as this method. The component's ~connect~ method is a phase callback where
430
  // port's ~connect~ method calls are made.
431
 
432
  virtual function void connect (this_type provider);
433
     uvm_root top;
434
     uvm_coreservice_t cs;
435
     cs = uvm_coreservice_t::get();
436
     top = cs.get_root();
437
    if (end_of_elaboration_ph.get_state() == UVM_PHASE_EXECUTING || // TBD tidy
438
        end_of_elaboration_ph.get_state() == UVM_PHASE_DONE ) begin
439
       m_comp.uvm_report_warning("Late Connection",
440
         {"Attempt to connect ",this.get_full_name()," (of type ",this.get_type_name(),
441
          ") at or after end_of_elaboration phase.  Ignoring."});
442
       return;
443
     end
444
 
445
    if (provider == null) begin
446
      m_comp.uvm_report_error(s_connection_error_id,
447
                       "Cannot connect to null port handle", UVM_NONE);
448
      return;
449
    end
450
 
451
    if (provider == this) begin
452
      m_comp.uvm_report_error(s_connection_error_id,
453
                       "Cannot connect a port instance to itself", UVM_NONE);
454
      return;
455
    end
456
 
457
    if ((provider.m_if_mask & m_if_mask) != m_if_mask) begin
458
      m_comp.uvm_report_error(s_connection_error_id,
459
        {provider.get_full_name(),
460
         " (of type ",provider.get_type_name(),
461
         ") does not provide the complete interface required of this port (type ",
462
         get_type_name(),")"}, UVM_NONE);
463
      return;
464
    end
465
 
466
    // IMP.connect(anything) is illegal
467
    if (is_imp()) begin
468
      m_comp.uvm_report_error(s_connection_error_id,
469
        $sformatf(
470
"Cannot call an imp port's connect method. An imp is connected only to the component passed in its constructor. (You attempted to bind this imp to %s)", provider.get_full_name()), UVM_NONE);
471
      return;
472
    end
473
 
474
    // EXPORT.connect(PORT) are illegal
475
    if (is_export() && provider.is_port()) begin
476
      m_comp.uvm_report_error(s_connection_error_id,
477
        $sformatf(
478
"Cannot connect exports to ports Try calling port.connect(export) instead. (You attempted to bind this export to %s).", provider.get_full_name()), UVM_NONE);
479
      return;
480
    end
481
 
482
    void'(m_check_relationship(provider));
483
 
484
    m_provided_by[provider.get_full_name()] = provider;
485
    provider.m_provided_to[get_full_name()] = this;
486
 
487
  endfunction
488
 
489
 
490
  // Function: debug_connected_to
491
  //
492
  // The ~debug_connected_to~ method outputs a visual text display of the
493
  // port/export/imp network to which this port connects (i.e., the port's
494
  // fanout).
495
  //
496
  // This method must not be called before the end_of_elaboration phase, as port
497
  // connections are not resolved until then.
498
 
499
  function void debug_connected_to (int level=0, int max_level=-1);
500
    int sz, num, curr_num;
501
    string s_sz;
502
    static string indent, save;
503
    this_type port;
504
 
505
    if (level <  0) level = 0;
506
    if (level == 0) begin save = ""; indent="  "; end
507
 
508
    if (max_level != -1 && level >= max_level)
509
      return;
510
 
511
    num = m_provided_by.num();
512
 
513
    if (m_provided_by.num() != 0) begin
514
      foreach (m_provided_by[nm]) begin
515
        curr_num++;
516
        port = m_provided_by[nm];
517
        save = {save, indent, "  | \n"};
518
        save = {save, indent, "  |_",nm," (",port.get_type_name(),")\n"};
519
        indent = (num > 1 && curr_num != num) ?  {indent,"  | "}:{indent, "    "};
520
        port.debug_connected_to(level+1, max_level);
521
        indent = indent.substr(0,indent.len()-4-1);
522
      end
523
    end
524
 
525
    if (level == 0) begin
526
      if (save != "")
527
        save = {"This port's fanout network:\n\n  ",
528
               get_full_name()," (",get_type_name(),")\n",save,"\n"};
529
      if (m_imp_list.num() == 0) begin
530
         uvm_root top;
531
         uvm_coreservice_t cs;
532
         cs = uvm_coreservice_t::get();
533
         top = cs.get_root();
534
        if (end_of_elaboration_ph.get_state() == UVM_PHASE_EXECUTING ||
535
            end_of_elaboration_ph.get_state() == UVM_PHASE_DONE )  // TBD tidy
536
           save = {save,"  Connected implementations: none\n"};
537
        else
538
           save = {save,
539
                 "  Connected implementations: not resolved until end-of-elab\n"};
540
      end
541
      else begin
542
        save = {save,"  Resolved implementation list:\n"};
543
        foreach (m_imp_list[nm]) begin
544
          port = m_imp_list[nm];
545
          s_sz.itoa(sz);
546
          save = {save, indent, s_sz, ": ",nm," (",port.get_type_name(),")\n"};
547
          sz++;
548
        end
549
      end
550
      m_comp.uvm_report_info("debug_connected_to", save);
551
    end
552
  endfunction
553
 
554
 
555
  // Function: debug_provided_to
556
  //
557
  // The ~debug_provided_to~ method outputs a visual display of the port/export
558
  // network that ultimately connect to this port (i.e., the port's fanin).
559
  //
560
  // This method must not be called before the end_of_elaboration phase, as port
561
  // connections are not resolved until then.
562
 
563
  function void debug_provided_to  (int level=0, int max_level=-1);
564
    string nm;
565
    int num,curr_num;
566
    this_type port;
567
    static string indent, save;
568
 
569
    if (level <  0) level = 0;
570
    if (level == 0) begin save = ""; indent = "  "; end
571
 
572
    if (max_level != -1 && level > max_level)
573
      return;
574
 
575
    num = m_provided_to.num();
576
 
577
    if (num != 0) begin
578
      foreach (m_provided_to[nm]) begin
579
        curr_num++;
580
        port = m_provided_to[nm];
581
        save = {save, indent, "  | \n"};
582
        save = {save, indent, "  |_",nm," (",port.get_type_name(),")\n"};
583
        indent = (num > 1 && curr_num != num) ?  {indent,"  | "}:{indent, "    "};
584
        port.debug_provided_to(level+1, max_level);
585
        indent = indent.substr(0,indent.len()-4-1);
586
      end
587
    end
588
 
589
    if (level == 0) begin
590
      if (save != "")
591
        save = {"This port's fanin network:\n\n  ",
592
               get_full_name()," (",get_type_name(),")\n",save,"\n"};
593
      if (m_provided_to.num() == 0)
594
        save = {save,indent,"This port has not been bound\n"};
595
      m_comp.uvm_report_info("debug_provided_to", save);
596
    end
597
 
598
  endfunction
599
 
600
 
601
  // get_connected_to
602
  // ----------------
603
 
604
  function void get_connected_to (ref uvm_port_list list);
605
    this_type port;
606
    list.delete();
607
    foreach (m_provided_by[name]) begin
608
      port = m_provided_by[name];
609
      list[name] = port.get_comp();
610
    end
611
  endfunction
612
 
613
 
614
  // get_provided_to
615
  // ---------------
616
 
617
  function void get_provided_to (ref uvm_port_list list);
618
    this_type port;
619
    list.delete();
620
    foreach (m_provided_to[name]) begin
621
      port = m_provided_to[name];
622
      list[name] = port.get_comp();
623
    end
624
  endfunction
625
 
626
 
627
  // m_check_relationship
628
  // --------------------
629
 
630
  local function bit  m_check_relationship (this_type provider);
631
    string s;
632
    this_type from;
633
    uvm_component from_parent;
634
    uvm_component to_parent;
635
    uvm_component from_gparent;
636
    uvm_component to_gparent;
637
 
638
    // Checks that the connection is between ports that are hierarchically
639
    // adjacent (up or down one level max, or are siblings),
640
    // and check for legal direction, requirer.connect(provider).
641
 
642
    // if we're an analysis port, allow connection to anywhere
643
    if (get_type_name() == "uvm_analysis_port")
644
      return 1;
645
 
646
    from         = this;
647
    from_parent  = get_parent();
648
    to_parent    = provider.get_parent();
649
 
650
    // skip check if we have a parentless port
651
    if (from_parent == null || to_parent == null)
652
      return 1;
653
 
654
    from_gparent = from_parent.get_parent();
655
    to_gparent   = to_parent.get_parent();
656
 
657
    // Connecting port-to-port: CHILD.port.connect(PARENT.port)
658
    //
659
    if (from.is_port() && provider.is_port() && from_gparent != to_parent) begin
660
      s = {provider.get_full_name(),
661
           " (of type ",provider.get_type_name(),
662
           ") is not up one level of hierarchy from this port. ",
663
           "A port-to-port connection takes the form ",
664
           "child_component.child_port.connect(parent_port)"};
665
      m_comp.uvm_report_warning(s_connection_warning_id, s, UVM_NONE);
666
      return 0;
667
    end
668
 
669
    // Connecting port-to-export: SIBLING.port.connect(SIBLING.export)
670
    // Connecting port-to-imp:    SIBLING.port.connect(SIBLING.imp)
671
    //
672
    else if (from.is_port() && (provider.is_export() || provider.is_imp()) &&
673
             from_gparent != to_gparent) begin
674
        s = {provider.get_full_name(),
675
           " (of type ",provider.get_type_name(),
676
           ") is not at the same level of hierarchy as this port. ",
677
           "A port-to-export connection takes the form ",
678
           "component1.port.connect(component2.export)"};
679
      m_comp.uvm_report_warning(s_connection_warning_id, s, UVM_NONE);
680
      return 0;
681
    end
682
 
683
    // Connecting export-to-export: PARENT.export.connect(CHILD.export)
684
    // Connecting export-to-imp:    PARENT.export.connect(CHILD.imp)
685
    //
686
    else if (from.is_export() && (provider.is_export() || provider.is_imp()) &&
687
             from_parent != to_gparent) begin
688
      s = {provider.get_full_name(),
689
           " (of type ",provider.get_type_name(),
690
           ") is not down one level of hierarchy from this export. ",
691
           "An export-to-export or export-to-imp connection takes the form ",
692
           "parent_export.connect(child_component.child_export)"};
693
      m_comp.uvm_report_warning(s_connection_warning_id, s, UVM_NONE);
694
      return 0;
695
    end
696
 
697
    return 1;
698
  endfunction
699
 
700
 
701
  // m_add_list
702
  //
703
  // Internal method.
704
 
705
  local function void m_add_list           (this_type provider);
706
    string sz;
707
    this_type imp;
708
 
709
    for (int i = 0; i < provider.size(); i++) begin
710
      imp = provider.get_if(i);
711
      if (!m_imp_list.exists(imp.get_full_name()))
712
        m_imp_list[imp.get_full_name()] = imp;
713
    end
714
 
715
  endfunction
716
 
717
 
718
  // Function: resolve_bindings
719
  //
720
  // This callback is called just before entering the end_of_elaboration phase.
721
  // It recurses through each port's fanout to determine all the imp
722
  // destinations. It then checks against the required min and max connections.
723
  // After resolution,  returns a valid value and 
724
  // can be used to access a particular imp.
725
  //
726
  // This method is automatically called just before the start of the
727
  // end_of_elaboration phase. Users should not need to call it directly.
728
 
729
  virtual function void resolve_bindings();
730
    if (m_resolved) // don't repeat ourselves
731
     return;
732
 
733
    if (is_imp()) begin
734
      m_imp_list[get_full_name()] = this;
735
    end
736
    else begin
737
      foreach (m_provided_by[nm]) begin
738
        this_type port;
739
        port = m_provided_by[nm];
740
        port.resolve_bindings();
741
        m_add_list(port);
742
      end
743
    end
744
 
745
    m_resolved = 1;
746
 
747
    if (size() < min_size() ) begin
748
      m_comp.uvm_report_error(s_connection_error_id,
749
        $sformatf("connection count of %0d does not meet required minimum of %0d",
750
        size(), min_size()), UVM_NONE);
751
    end
752
 
753
    if (max_size() != UVM_UNBOUNDED_CONNECTIONS && size() > max_size() ) begin
754
      m_comp.uvm_report_error(s_connection_error_id,
755
        $sformatf("connection count of %0d exceeds maximum of %0d",
756
        size(), max_size()), UVM_NONE);
757
    end
758
 
759
    if (size())
760
      set_if(0);
761
 
762
  endfunction
763
 
764
 
765
  // Function: get_if
766
  //
767
  // Returns the implementation (imp) port at the given index from the array of
768
  // imps this port is connected to. Use  to get the valid range for index.
769
  // This method can only be called at the end_of_elaboration phase or after, as
770
  // port connections are not resolved before then.
771
 
772
  function uvm_port_base #(IF) get_if(int index=0);
773
    string s;
774
    if (size()==0) begin
775
      m_comp.uvm_report_warning("get_if",
776
        "Port size is zero; cannot get interface at any index", UVM_NONE);
777
      return null;
778
    end
779
    if (index < 0 || index >= size()) begin
780
      $sformat(s, "Index %0d out of range [0,%0d]", index, size()-1);
781
      m_comp.uvm_report_warning(s_connection_error_id, s, UVM_NONE);
782
      return null;
783
    end
784
    foreach (m_imp_list[nm]) begin
785
      if (index == 0)
786
        return m_imp_list[nm];
787
      index--;
788
    end
789
  endfunction
790
 
791
endclass
792
 

powered by: WebSVN 2.1.0

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