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

Subversion Repositories uart2bus_testbench

[/] [uart2bus_testbench/] [trunk/] [tb/] [uvm_src/] [base/] [uvm_heartbeat.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-2009 Cadence Design Systems, Inc.
4
//   Copyright 2010 Synopsys, Inc.
5
//   Copyright 2013 NVIDIA Corporation
6
//   All Rights Reserved Worldwide
7
//
8
//   Licensed under the Apache License, Version 2.0 (the
9
//   "License"); you may not use this file except in
10
//   compliance with the License.  You may obtain a copy of
11
//   the License at
12
//
13
//       http://www.apache.org/licenses/LICENSE-2.0
14
//
15
//   Unless required by applicable law or agreed to in
16
//   writing, software distributed under the License is
17
//   distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
18
//   CONDITIONS OF ANY KIND, either express or implied.  See
19
//   the License for the specific language governing
20
//   permissions and limitations under the License.
21
//----------------------------------------------------------------------
22
 
23
`ifndef UVM_HEARTBEAT_SVH
24
`define UVM_HEARTBEAT_SVH
25
 
26
typedef enum {
27
  UVM_ALL_ACTIVE,
28
  UVM_ONE_ACTIVE,
29
  UVM_ANY_ACTIVE,
30
  UVM_NO_HB_MODE
31
} uvm_heartbeat_modes;
32
 
33
typedef class uvm_heartbeat_callback;
34
typedef uvm_callbacks #(uvm_objection,uvm_heartbeat_callback) uvm_heartbeat_cbs_t;
35
 
36
 
37
//------------------------------------------------------------------------------
38
//
39
// Class: uvm_heartbeat
40
//
41
//------------------------------------------------------------------------------
42
// Heartbeats provide a way for environments to easily ensure that their
43
// descendants are alive. A uvm_heartbeat is associated with a specific
44
// objection object. A component that is being tracked by the heartbeat
45
// object must raise (or drop) the synchronizing objection during
46
// the heartbeat window.
47
//
48
// The uvm_heartbeat object has a list of participating objects. The heartbeat
49
// can be configured so that all components (UVM_ALL_ACTIVE), exactly one
50
// (UVM_ONE_ACTIVE), or any component (UVM_ANY_ACTIVE) must trigger the
51
// objection in order to satisfy the heartbeat condition.
52
//------------------------------------------------------------------------------
53
 
54
typedef class uvm_objection_callback;
55
class uvm_heartbeat extends uvm_object;
56
 
57
  protected uvm_objection m_objection;
58
  protected uvm_heartbeat_callback m_cb;
59
  protected uvm_component   m_cntxt;
60
  protected uvm_heartbeat_modes   m_mode;
61
  protected uvm_component   m_hblist[$];
62
  protected uvm_event#(uvm_object)       m_event;
63
  protected bit             m_started;
64
  protected event           m_stop_event;
65
 
66
  // Function: new
67
  //
68
  // Creates a new heartbeat instance associated with ~cntxt~. The context
69
  // is the hierarchical location that the heartbeat objections will flow
70
  // through and be monitored at. The ~objection~ associated with the heartbeat
71
  // is optional, if it is left ~null~ but it must be set before the heartbeat
72
  // monitor will activate.
73
  //
74
  //| uvm_objection myobjection = new("myobjection"); //some shared objection
75
  //| class myenv extends uvm_env;
76
  //|    uvm_heartbeat hb = new("hb", this, myobjection);
77
  //|    ...
78
  //| endclass
79
 
80
  function new(string name, uvm_component cntxt, uvm_objection objection=null);
81
     uvm_coreservice_t cs;
82
    super.new(name);
83
    m_objection = objection;
84
    cs  = uvm_coreservice_t::get();
85
 
86
    //if a cntxt is given it will be used for reporting.
87
    if(cntxt != null) m_cntxt = cntxt;
88
    else m_cntxt = cs.get_root();
89
 
90
    m_cb = new({name,"_cb"},m_cntxt);
91
 
92
  endfunction
93
 
94
 
95
  // Function: set_mode
96
  //
97
  // Sets or retrieves the heartbeat mode. The current value for the heartbeat
98
  // mode is returned. If an argument is specified to change the mode then the
99
  // mode is changed to the new value.
100
 
101
  function uvm_heartbeat_modes set_mode (uvm_heartbeat_modes mode = UVM_NO_HB_MODE);
102
    set_mode = m_mode;
103
    if(mode == UVM_ANY_ACTIVE || mode == UVM_ONE_ACTIVE || mode == UVM_ALL_ACTIVE)
104
      m_mode = mode;
105
  endfunction
106
 
107
 
108
  // Function: set_heartbeat
109
  //
110
  // Sets up the heartbeat event and assigns a list of objects to watch. The
111
  // monitoring is started as soon as this method is called. Once the
112
  // monitoring has been started with a specific event, providing a new
113
  // monitor event results in an error. To change trigger events, you
114
  // must first  the monitor and then  with a new event trigger.
115
  //
116
  // If the trigger event ~e~ is ~null~ and there was no previously set
117
  // trigger event, then the monitoring is not started. Monitoring can be
118
  // started by explicitly calling .
119
 
120
  function void set_heartbeat (uvm_event#(uvm_object) e, ref uvm_component comps[$]);
121
    uvm_object c;
122
    foreach(comps[i]) begin
123
      c = comps[i];
124
      if(!m_cb.cnt.exists(c))
125
        m_cb.cnt[c]=0;
126
      if(!m_cb.last_trigger.exists(c))
127
        m_cb.last_trigger[c]=0;
128
    end
129
    if(e==null && m_event==null) return;
130
    start(e);
131
  endfunction
132
 
133
  // Function: add
134
  //
135
  // Add a single component to the set of components to be monitored.
136
  // This does not cause monitoring to be started. If monitoring is
137
  // currently active then this component will be immediately added
138
  // to the list of components and will be expected to participate
139
  // in the currently active event window.
140
 
141
  function void add (uvm_component comp);
142
    uvm_object c = comp;
143
    if(m_cb.cnt.exists(c)) return;
144
    m_cb.cnt[c]=0;
145
    m_cb.last_trigger[c]=0;
146
  endfunction
147
 
148
  // Function: remove
149
  //
150
  // Remove a single component to the set of components being monitored.
151
  // Monitoring is not stopped, even if the last component has been
152
  // removed (an explicit stop is required).
153
 
154
  function void remove (uvm_component comp);
155
    uvm_object c = comp;
156
    if(m_cb.cnt.exists(c)) m_cb.cnt.delete(c);
157
    if(m_cb.last_trigger.exists(c)) m_cb.last_trigger.delete(c);
158
  endfunction
159
 
160
 
161
  // Function: start
162
  //
163
  // Starts the heartbeat monitor. If ~e~ is ~null~ then whatever event
164
  // was previously set is used. If no event was previously set then
165
  // a warning is issued. It is an error if the monitor is currently
166
  // running and ~e~ is specifying a different trigger event from the
167
  // current event.
168
 
169
  function void start (uvm_event#(uvm_object) e=null);
170
    if(m_event == null && e == null) begin
171
      m_cntxt.uvm_report_warning("NOEVNT", { "start() was called for: ",
172
        get_name(), " with a null trigger and no currently set trigger" },
173
        UVM_NONE);
174
      return;
175
    end
176
    if((m_event != null) && (e != m_event) && m_started) begin
177
      m_cntxt.uvm_report_error("ILHBVNT", { "start() was called for: ",
178
        get_name(), " with trigger ", e.get_name(), " which is different ",
179
        "from the original trigger ", m_event.get_name() }, UVM_NONE);
180
      return;
181
    end
182
    if(e != null) m_event = e;
183
    m_enable_cb();
184
    m_start_hb_process();
185
  endfunction
186
 
187
  // Function: stop
188
  //
189
  // Stops the heartbeat monitor. Current state information is reset so
190
  // that if  is called again the process will wait for the first
191
  // event trigger to start the monitoring.
192
 
193
  function void stop ();
194
    m_started = 0;
195
    ->m_stop_event;
196
    m_disable_cb();
197
  endfunction
198
 
199
  function void m_start_hb_process();
200
    if(m_started) return;
201
    m_started = 1;
202
    fork
203
      m_hb_process;
204
    join_none
205
  endfunction
206
 
207
  protected bit m_added;
208
  function void m_enable_cb;
209
    void'(m_cb.callback_mode(1));
210
    if(m_objection == null) return;
211
    if(!m_added)
212
      uvm_heartbeat_cbs_t::add(m_objection, m_cb);
213
    m_added = 1;
214
  endfunction
215
 
216
  function void m_disable_cb;
217
    void'(m_cb.callback_mode(0));
218
  endfunction
219
 
220
  task m_hb_process;
221
    uvm_object obj;
222
    bit  triggered;
223
    time last_trigger=0;
224
    fork
225
      begin
226
        // The process waits for the event trigger. The first trigger is
227
        // ignored, but sets the first start window. On susequent triggers
228
        // the monitor tests that the mode criteria was full-filled.
229
        while(1) begin
230
          m_event.wait_trigger();
231
          if(triggered) begin
232
            case (m_mode)
233
              UVM_ALL_ACTIVE:
234
                begin
235
                  foreach(m_cb.cnt[idx]) begin
236
                    obj = idx;
237
                    if(!m_cb.cnt[obj]) begin
238
                      m_cntxt.uvm_report_fatal("HBFAIL", $sformatf("Did not recieve an update of %s for component %s since last event trigger at time %0t : last update time was %0t",
239
                        m_objection.get_name(), obj.get_full_name(),
240
                        last_trigger, m_cb.last_trigger[obj]), UVM_NONE);
241
                    end
242
                  end
243
                end
244
              UVM_ANY_ACTIVE:
245
                begin
246
                  if(m_cb.cnt.num() && !m_cb.objects_triggered()) begin
247
                    string s;
248
                    foreach(m_cb.cnt[idx]) begin
249
                      obj = idx;
250
                      s={s,"\n  ",obj.get_full_name()};
251
                    end
252
                    m_cntxt.uvm_report_fatal("HBFAIL", $sformatf("Did not recieve an update of %s on any component since last event trigger at time %0t. The list of registered components is:%s",
253
                      m_objection.get_name(), last_trigger, s), UVM_NONE);
254
                  end
255
                end
256
              UVM_ONE_ACTIVE:
257
                begin
258
                  if(m_cb.objects_triggered() > 1) begin
259
                    string s;
260
                    foreach(m_cb.cnt[idx])  begin
261
                      obj = idx;
262
                      if(m_cb.cnt[obj]) $swrite(s,"%s\n  %s (updated: %0t)",
263
                         s, obj.get_full_name(), m_cb.last_trigger[obj]);
264
                    end
265
                    m_cntxt.uvm_report_fatal("HBFAIL", $sformatf("Recieved update of %s from more than one component since last event trigger at time %0t. The list of triggered components is:%s",
266
                      m_objection.get_name(), last_trigger, s), UVM_NONE);
267
                  end
268
                  if(m_cb.cnt.num() && !m_cb.objects_triggered()) begin
269
                    string s;
270
                    foreach(m_cb.cnt[idx]) begin
271
                      obj = idx;
272
                      s={s,"\n  ",obj.get_full_name()};
273
                    end
274
                    m_cntxt.uvm_report_fatal("HBFAIL", $sformatf("Did not recieve an update of %s on any component since last event trigger at time %0t. The list of registered components is:%s",
275
                      m_objection.get_name(), last_trigger, s), UVM_NONE);
276
                  end
277
                end
278
            endcase
279
          end
280
          m_cb.reset_counts();
281
          last_trigger = $realtime;
282
          triggered = 1;
283
        end
284
      end
285
      @(m_stop_event);
286
    join_any
287
    disable fork;
288
  endtask
289
endclass
290
 
291
 
292
class uvm_heartbeat_callback extends uvm_objection_callback;
293
  int  cnt [uvm_object];
294
  time last_trigger [uvm_object];
295
  uvm_object target;
296
  uvm_coreservice_t cs = uvm_coreservice_t::get();
297
 
298
  function new(string name, uvm_object target);
299
    super.new(name);
300
    if (target != null)
301
       this.target = target;
302
    else
303
       this.target = cs.get_root();
304
  endfunction
305
 
306
  virtual function void raised (uvm_objection objection,
307
                                uvm_object obj,
308
                                uvm_object source_obj,
309
                                string description,
310
                                int count);
311
    if(obj == target) begin
312
      if(!cnt.exists(source_obj))
313
        cnt[source_obj] = 0;
314
      cnt[source_obj] = cnt[source_obj]+1;
315
      last_trigger[source_obj] = $realtime;
316
    end
317
  endfunction
318
 
319
  virtual function void dropped (uvm_objection objection,
320
                                 uvm_object obj,
321
                                 uvm_object source_obj,
322
                                 string description,
323
                                 int count);
324
    raised(objection,obj,source_obj,description,count);
325
  endfunction
326
 
327
  function void reset_counts;
328
    foreach(cnt[i]) cnt[i] = 0;
329
  endfunction
330
 
331
  function int objects_triggered;
332
    objects_triggered = 0;
333
    foreach(cnt[i])
334
      if (cnt[i] != 0)
335
        objects_triggered++;
336
  endfunction
337
 
338
endclass
339
 
340
`endif
341
 

powered by: WebSVN 2.1.0

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