1 |
16 |
HanySalah |
//----------------------------------------------------------------------
|
2 |
|
|
// Copyright 2010-2011 Mentor Graphics Corporation
|
3 |
|
|
// Copyright 2011 Synopsys, Inc.
|
4 |
|
|
// Copyright 2013 Cadence Design Inc
|
5 |
|
|
// Copyright 2014 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 |
|
|
|
24 |
|
|
typedef class uvm_sequence_library_cfg;
|
25 |
|
|
|
26 |
|
|
//
|
27 |
|
|
// CLASS: uvm_sequence_library
|
28 |
|
|
//
|
29 |
|
|
// The ~uvm_sequence_library~ is a sequence that contains a list of registered
|
30 |
|
|
// sequence types. It can be configured to create and execute these sequences
|
31 |
|
|
// any number of times using one of several modes of operation, including a
|
32 |
|
|
// user-defined mode.
|
33 |
|
|
//
|
34 |
|
|
// When started (as any other sequence), the sequence library will randomly
|
35 |
|
|
// select and execute a sequence from its ~sequences~ queue. If in
|
36 |
|
|
// mode, its property is randomized and used
|
37 |
|
|
// as an index into ~sequences~. When in mode, the
|
38 |
|
|
// property is used. When in mode, only
|
39 |
|
|
// sequence items of the ~REQ~ type are generated and executed--no sequences
|
40 |
|
|
// are executed. Finally, when in mode, the
|
41 |
|
|
// method is called to obtain the index for selecting the
|
42 |
|
|
// next sequence to start. Users can override this method in subtypes to
|
43 |
|
|
// implement custom selection algorithms.
|
44 |
|
|
//
|
45 |
|
|
// Creating a subtype of a sequence library requires invocation of the
|
46 |
|
|
// <`uvm_sequence_library_utils> macro in its declaration and calling
|
47 |
|
|
// the method in its constructor. The macro
|
48 |
|
|
// and function are needed to populate the sequence library with any
|
49 |
|
|
// sequences that were statically registered with it or any of its base
|
50 |
|
|
// classes.
|
51 |
|
|
//
|
52 |
|
|
//| class my_seq_lib extends uvm_sequence_library #(my_item);
|
53 |
|
|
//| `uvm_object_utils(my_seq_lib)
|
54 |
|
|
//| `uvm_sequence_library_utils(my_seq_lib)
|
55 |
|
|
//| function new(string name="");
|
56 |
|
|
//| super.new(name);
|
57 |
|
|
//| init_sequence_library();
|
58 |
|
|
//| endfunction
|
59 |
|
|
//| ...
|
60 |
|
|
//| endclass
|
61 |
|
|
//
|
62 |
|
|
//------------------------------------------------------------------------------
|
63 |
|
|
|
64 |
|
|
class uvm_sequence_library #(type REQ=uvm_sequence_item,RSP=REQ) extends uvm_sequence #(REQ,RSP);
|
65 |
|
|
|
66 |
|
|
// Function: new
|
67 |
|
|
//
|
68 |
|
|
// Create a new instance of this class
|
69 |
|
|
//
|
70 |
|
|
extern function new(string name="");
|
71 |
|
|
|
72 |
|
|
|
73 |
|
|
// Function: get_type_name
|
74 |
|
|
//
|
75 |
|
|
// Get the type name of this class
|
76 |
|
|
//
|
77 |
|
|
extern virtual function string get_type_name();
|
78 |
|
|
|
79 |
|
|
|
80 |
|
|
|
81 |
|
|
//--------------------------
|
82 |
|
|
// Group: Sequence selection
|
83 |
|
|
//--------------------------
|
84 |
|
|
|
85 |
|
|
// Variable: selection_mode
|
86 |
|
|
//
|
87 |
|
|
// Specifies the mode used to select sequences for execution
|
88 |
|
|
//
|
89 |
|
|
// If you do not have access to an instance of the library,
|
90 |
|
|
// use the configuration resource interface.
|
91 |
|
|
//
|
92 |
|
|
// The following example sets the ~config_seq_lib~ as the default
|
93 |
|
|
// sequence for the 'main' phase on the sequencer to be
|
94 |
|
|
// located at "env.agent.sequencer"
|
95 |
|
|
// and set the selection mode to . If the
|
96 |
|
|
// settings are being done from within a component, the first
|
97 |
|
|
// argument must be ~this~ and the second argument a path
|
98 |
|
|
// relative to that component.
|
99 |
|
|
//
|
100 |
|
|
//
|
101 |
|
|
//| uvm_config_db #(uvm_object_wrapper)::set(null,
|
102 |
|
|
//| "env.agent.sequencer.main_phase",
|
103 |
|
|
//| "default_sequence",
|
104 |
|
|
//| main_seq_lib::get_type());
|
105 |
|
|
//|
|
106 |
|
|
//| uvm_config_db #(uvm_sequence_lib_mode)::set(null,
|
107 |
|
|
//| "env.agent.sequencer.main_phase",
|
108 |
|
|
//| "default_sequence.selection_mode",
|
109 |
|
|
//| UVM_SEQ_LIB_RANDC);
|
110 |
|
|
//
|
111 |
|
|
// Alternatively, you may create an instance of the sequence library
|
112 |
|
|
// a priori, initialize all its parameters, randomize it, then set it
|
113 |
|
|
// to run as-is on the sequencer.
|
114 |
|
|
//
|
115 |
|
|
//| main_seq_lib my_seq_lib;
|
116 |
|
|
//| my_seq_lib = new("my_seq_lib");
|
117 |
|
|
//|
|
118 |
|
|
//| my_seq_lib.selection_mode = UVM_SEQ_LIB_RANDC;
|
119 |
|
|
//| my_seq_lib.min_random_count = 500;
|
120 |
|
|
//| my_seq_lib.max_random_count = 1000;
|
121 |
|
|
//| void'(my_seq_lib.randomize());
|
122 |
|
|
//|
|
123 |
|
|
//| uvm_config_db #(uvm_sequence_base)::set(null,
|
124 |
|
|
//| "env.agent.sequencer.main_phase",
|
125 |
|
|
//| "default_sequence",
|
126 |
|
|
//| my_seq_lib);
|
127 |
|
|
//|
|
128 |
|
|
//
|
129 |
|
|
uvm_sequence_lib_mode selection_mode;
|
130 |
|
|
|
131 |
|
|
|
132 |
|
|
// Variable: min_random_count
|
133 |
|
|
//
|
134 |
|
|
// Sets the minimum number of items to execute. Use the configuration
|
135 |
|
|
// mechanism to set. See for an example.
|
136 |
|
|
//
|
137 |
|
|
int unsigned min_random_count=10;
|
138 |
|
|
|
139 |
|
|
|
140 |
|
|
// Variable: max_random_count
|
141 |
|
|
//
|
142 |
|
|
// Sets the maximum number of items to execute. Use the configuration
|
143 |
|
|
// mechanism to set. See for an example.
|
144 |
|
|
//
|
145 |
|
|
//
|
146 |
|
|
int unsigned max_random_count=10;
|
147 |
|
|
|
148 |
|
|
|
149 |
|
|
|
150 |
|
|
// Variable: sequences_executed
|
151 |
|
|
//
|
152 |
|
|
// Indicates the number of sequences executed, not including the
|
153 |
|
|
// currently executing sequence, if any.
|
154 |
|
|
//
|
155 |
|
|
protected int unsigned sequences_executed;
|
156 |
|
|
|
157 |
|
|
|
158 |
|
|
// Variable: sequence_count
|
159 |
|
|
//
|
160 |
|
|
// Specifies the number of sequences to execute when this sequence
|
161 |
|
|
// library is started. If in mode, specifies the
|
162 |
|
|
// number of sequence items that will be generated.
|
163 |
|
|
//
|
164 |
|
|
rand int unsigned sequence_count = 10;
|
165 |
|
|
|
166 |
|
|
|
167 |
|
|
// Variable: select_rand
|
168 |
|
|
//
|
169 |
|
|
// The index variable that is randomized to select the next sequence
|
170 |
|
|
// to execute when in UVM_SEQ_LIB_RAND mode
|
171 |
|
|
//
|
172 |
|
|
// Extensions may place additional constraints on this variable.
|
173 |
|
|
//
|
174 |
|
|
rand int unsigned select_rand;
|
175 |
|
|
|
176 |
|
|
|
177 |
|
|
// Variable: select_randc
|
178 |
|
|
//
|
179 |
|
|
// The index variable that is randomized to select the next sequence
|
180 |
|
|
// to execute when in UVM_SEQ_LIB_RANDC mode
|
181 |
|
|
//
|
182 |
|
|
// Extensions may place additional constraints on this variable.
|
183 |
|
|
//
|
184 |
|
|
randc bit [15:0] select_randc;
|
185 |
|
|
|
186 |
|
|
|
187 |
|
|
|
188 |
|
|
// Variable- seqs_distrib
|
189 |
|
|
//
|
190 |
|
|
//
|
191 |
|
|
//
|
192 |
|
|
protected int seqs_distrib[string] = '{default:0};
|
193 |
|
|
|
194 |
|
|
|
195 |
|
|
// Variable- sequences
|
196 |
|
|
//
|
197 |
|
|
// The container of all registered sequence types. For
|
198 |
|
|
// times, this sequence library will randomly select and execute a
|
199 |
|
|
// sequence from this list of sequence types.
|
200 |
|
|
//
|
201 |
|
|
protected uvm_object_wrapper sequences[$];
|
202 |
|
|
|
203 |
|
|
|
204 |
|
|
|
205 |
|
|
// Constraint: valid_rand_selection
|
206 |
|
|
//
|
207 |
|
|
// Constrains to be a valid index into the ~sequences~ array
|
208 |
|
|
//
|
209 |
|
|
constraint valid_rand_selection {
|
210 |
|
|
select_rand inside {[0:sequences.size()-1]};
|
211 |
|
|
}
|
212 |
|
|
|
213 |
|
|
|
214 |
|
|
|
215 |
|
|
// Constraint: valid_randc_selection
|
216 |
|
|
//
|
217 |
|
|
// Constrains to be a valid index into the ~sequences~ array
|
218 |
|
|
//
|
219 |
|
|
constraint valid_randc_selection {
|
220 |
|
|
select_randc inside {[0:sequences.size()-1]};
|
221 |
|
|
}
|
222 |
|
|
|
223 |
|
|
|
224 |
|
|
// Constraint: valid_sequence_count
|
225 |
|
|
//
|
226 |
|
|
// Constrains to lie within the range defined by
|
227 |
|
|
// and .
|
228 |
|
|
//
|
229 |
|
|
constraint valid_sequence_count {
|
230 |
|
|
sequence_count inside {[min_random_count:max_random_count]};
|
231 |
|
|
}
|
232 |
|
|
|
233 |
|
|
|
234 |
|
|
|
235 |
|
|
// Function: select_sequence
|
236 |
|
|
//
|
237 |
|
|
// Generates an index used to select the next sequence to execute.
|
238 |
|
|
// Overrides must return a value between 0 and ~max~, inclusive.
|
239 |
|
|
// Used only for selection mode. The
|
240 |
|
|
// default implementation returns 0, incrementing on successive calls,
|
241 |
|
|
// wrapping back to 0 when reaching ~max~.
|
242 |
|
|
//
|
243 |
|
|
extern virtual function int unsigned select_sequence(int unsigned max);
|
244 |
|
|
|
245 |
|
|
|
246 |
|
|
|
247 |
|
|
//-----------------------------
|
248 |
|
|
// Group: Sequence registration
|
249 |
|
|
//-----------------------------
|
250 |
|
|
|
251 |
|
|
// Function: add_typewide_sequence
|
252 |
|
|
//
|
253 |
|
|
// Registers the provided sequence type with this sequence library
|
254 |
|
|
// type. The sequence type will be available for selection by all instances
|
255 |
|
|
// of this class. Sequence types already registered are silently ignored.
|
256 |
|
|
//
|
257 |
|
|
extern static function void add_typewide_sequence(uvm_object_wrapper seq_type);
|
258 |
|
|
|
259 |
|
|
|
260 |
|
|
|
261 |
|
|
// Function: add_typewide_sequences
|
262 |
|
|
//
|
263 |
|
|
// Registers the provided sequence types with this sequence library
|
264 |
|
|
// type. The sequence types will be available for selection by all instances
|
265 |
|
|
// of this class. Sequence types already registered are silently ignored.
|
266 |
|
|
//
|
267 |
|
|
extern static function void add_typewide_sequences(uvm_object_wrapper seq_types[$]);
|
268 |
|
|
|
269 |
|
|
|
270 |
|
|
// Function: add_sequence
|
271 |
|
|
//
|
272 |
|
|
// Registers the provided sequence type with this sequence library
|
273 |
|
|
// instance. Sequence types already registered are silently ignored.
|
274 |
|
|
//
|
275 |
|
|
extern function void add_sequence(uvm_object_wrapper seq_type);
|
276 |
|
|
|
277 |
|
|
|
278 |
|
|
// Function: add_sequences
|
279 |
|
|
//
|
280 |
|
|
// Registers the provided sequence types with this sequence library
|
281 |
|
|
// instance. Sequence types already registered are silently ignored.
|
282 |
|
|
//
|
283 |
|
|
extern virtual function void add_sequences(uvm_object_wrapper seq_types[$]);
|
284 |
|
|
|
285 |
|
|
|
286 |
|
|
// Function: remove_sequence
|
287 |
|
|
//
|
288 |
|
|
// Removes the given sequence type from this sequence library
|
289 |
|
|
// instance. If the type was registered statically, the sequence queues of
|
290 |
|
|
// all instances of this library will be updated accordingly.
|
291 |
|
|
// A warning is issued if the sequence is not registered.
|
292 |
|
|
//
|
293 |
|
|
extern virtual function void remove_sequence(uvm_object_wrapper seq_type);
|
294 |
|
|
|
295 |
|
|
|
296 |
|
|
// Function: get_sequences
|
297 |
|
|
//
|
298 |
|
|
//
|
299 |
|
|
// Append to the provided ~seq_types~ array the list of registered ~sequences~.
|
300 |
|
|
//
|
301 |
|
|
extern virtual function void get_sequences(ref uvm_object_wrapper seq_types[$]);
|
302 |
|
|
|
303 |
|
|
|
304 |
|
|
// Function: init_sequence_library
|
305 |
|
|
//
|
306 |
|
|
// All subtypes of this class must call init_sequence_library in its
|
307 |
|
|
// constructor.
|
308 |
|
|
extern function void init_sequence_library();
|
309 |
|
|
|
310 |
|
|
// Macro: uvm_sequence_library_utils
|
311 |
|
|
//
|
312 |
|
|
// All subtypes of this class must invoke the `uvm_sequence_library_utils
|
313 |
|
|
// macro.
|
314 |
|
|
//
|
315 |
|
|
//| class my_seq_lib extends uvm_sequence_library #(my_item);
|
316 |
|
|
//| `uvm_object_utils(my_seq_lib)
|
317 |
|
|
//| `uvm_sequence_library_utils(my_seq_lib)
|
318 |
|
|
//| function new(string name="");
|
319 |
|
|
//| super.new(name);
|
320 |
|
|
//| init_sequence_library();
|
321 |
|
|
//| endfunction
|
322 |
|
|
//| ...
|
323 |
|
|
//| endclass
|
324 |
|
|
|
325 |
|
|
//------------------------------------------
|
326 |
|
|
// PRIVATE - INTERNAL - NOT PART OF STANDARD
|
327 |
|
|
//------------------------------------------
|
328 |
|
|
|
329 |
|
|
`uvm_object_param_utils(uvm_sequence_library #(REQ,RSP))
|
330 |
|
|
typedef uvm_sequence_library #(REQ,RSP) this_type;
|
331 |
|
|
|
332 |
|
|
static const string type_name = "uvm_sequence_library #(REQ,RSP)";
|
333 |
|
|
static protected uvm_object_wrapper m_typewide_sequences[$];
|
334 |
|
|
bit m_abort;
|
335 |
|
|
|
336 |
|
|
extern static function bit m_static_check(uvm_object_wrapper seq_type);
|
337 |
|
|
extern static function bit m_check(uvm_object_wrapper seq_type, this_type lib);
|
338 |
|
|
extern function bit m_dyn_check(uvm_object_wrapper seq_type);
|
339 |
|
|
extern function void m_get_config();
|
340 |
|
|
extern static function bit m_add_typewide_sequence(uvm_object_wrapper seq_type);
|
341 |
|
|
extern virtual task execute(uvm_object_wrapper wrap);
|
342 |
|
|
|
343 |
|
|
extern virtual task body();
|
344 |
|
|
extern virtual function void do_print(uvm_printer printer);
|
345 |
|
|
extern function void pre_randomize();
|
346 |
|
|
|
347 |
|
|
endclass
|
348 |
|
|
|
349 |
|
|
|
350 |
|
|
|
351 |
|
|
//------------------------------------------------------------------------------
|
352 |
|
|
//
|
353 |
|
|
// Class: uvm_sequence_library_cfg
|
354 |
|
|
//
|
355 |
|
|
// A convenient container class for configuring all the sequence library
|
356 |
|
|
// parameters using a single ~set~ command.
|
357 |
|
|
//
|
358 |
|
|
//| uvm_sequence_library_cfg cfg;
|
359 |
|
|
//| cfg = new("seqlib_cfg", UVM_SEQ_LIB_RANDC, 1000, 2000);
|
360 |
|
|
//|
|
361 |
|
|
//| uvm_config_db #(uvm_sequence_library_cfg)::set(null,
|
362 |
|
|
//| "env.agent.sequencer.main_ph",
|
363 |
|
|
//| "default_sequence.config",
|
364 |
|
|
//| cfg);
|
365 |
|
|
//|
|
366 |
|
|
//------------------------------------------------------------------------------
|
367 |
|
|
|
368 |
|
|
class uvm_sequence_library_cfg extends uvm_object;
|
369 |
|
|
`uvm_object_utils(uvm_sequence_library_cfg)
|
370 |
|
|
uvm_sequence_lib_mode selection_mode;
|
371 |
|
|
int unsigned min_random_count;
|
372 |
|
|
int unsigned max_random_count;
|
373 |
|
|
function new(string name="",
|
374 |
|
|
uvm_sequence_lib_mode mode=UVM_SEQ_LIB_RAND,
|
375 |
|
|
int unsigned min=1,
|
376 |
|
|
int unsigned max=10);
|
377 |
|
|
super.new(name);
|
378 |
|
|
selection_mode = mode;
|
379 |
|
|
min_random_count = min;
|
380 |
|
|
max_random_count = max;
|
381 |
|
|
endfunction
|
382 |
|
|
endclass
|
383 |
|
|
|
384 |
|
|
|
385 |
|
|
|
386 |
|
|
//------------------------------------------------------------------------------
|
387 |
|
|
// IMPLEMENTATION
|
388 |
|
|
//------------------------------------------------------------------------------
|
389 |
|
|
|
390 |
|
|
// new
|
391 |
|
|
// ---
|
392 |
|
|
|
393 |
|
|
function uvm_sequence_library::new(string name="");
|
394 |
|
|
super.new(name);
|
395 |
|
|
init_sequence_library();
|
396 |
|
|
valid_rand_selection.constraint_mode(0);
|
397 |
|
|
valid_randc_selection.constraint_mode(0);
|
398 |
|
|
endfunction
|
399 |
|
|
|
400 |
|
|
|
401 |
|
|
// get_type_name
|
402 |
|
|
// -------------
|
403 |
|
|
|
404 |
|
|
function string uvm_sequence_library::get_type_name();
|
405 |
|
|
return type_name;
|
406 |
|
|
endfunction
|
407 |
|
|
|
408 |
|
|
|
409 |
|
|
// m_add_typewide_sequence
|
410 |
|
|
// -----------------------
|
411 |
|
|
|
412 |
|
|
function bit uvm_sequence_library::m_add_typewide_sequence(uvm_object_wrapper seq_type);
|
413 |
|
|
this_type::add_typewide_sequence(seq_type);
|
414 |
|
|
return 1;
|
415 |
|
|
endfunction
|
416 |
|
|
|
417 |
|
|
|
418 |
|
|
// add_typewide_sequence
|
419 |
|
|
// ---------------------
|
420 |
|
|
|
421 |
|
|
function void uvm_sequence_library::add_typewide_sequence(uvm_object_wrapper seq_type);
|
422 |
|
|
if (m_static_check(seq_type))
|
423 |
|
|
m_typewide_sequences.push_back(seq_type);
|
424 |
|
|
endfunction
|
425 |
|
|
|
426 |
|
|
|
427 |
|
|
// add_typewide_sequences
|
428 |
|
|
// ----------------------
|
429 |
|
|
|
430 |
|
|
function void uvm_sequence_library::add_typewide_sequences(uvm_object_wrapper seq_types[$]);
|
431 |
|
|
foreach (seq_types[i])
|
432 |
|
|
add_typewide_sequence(seq_types[i]);
|
433 |
|
|
endfunction
|
434 |
|
|
|
435 |
|
|
|
436 |
|
|
// add_sequence
|
437 |
|
|
// ------------
|
438 |
|
|
|
439 |
|
|
function void uvm_sequence_library::add_sequence(uvm_object_wrapper seq_type);
|
440 |
|
|
if (m_dyn_check(seq_type))
|
441 |
|
|
sequences.push_back(seq_type);
|
442 |
|
|
endfunction
|
443 |
|
|
|
444 |
|
|
|
445 |
|
|
// add_sequences
|
446 |
|
|
// -------------
|
447 |
|
|
|
448 |
|
|
function void uvm_sequence_library::add_sequences(uvm_object_wrapper seq_types[$]);
|
449 |
|
|
foreach (seq_types[i])
|
450 |
|
|
add_sequence(seq_types[i]);
|
451 |
|
|
endfunction
|
452 |
|
|
|
453 |
|
|
|
454 |
|
|
// remove_sequence
|
455 |
|
|
// ---------------
|
456 |
|
|
|
457 |
|
|
function void uvm_sequence_library::remove_sequence(uvm_object_wrapper seq_type);
|
458 |
|
|
foreach (sequences[i])
|
459 |
|
|
if (sequences[i] == seq_type) begin
|
460 |
|
|
sequences.delete(i);
|
461 |
|
|
return;
|
462 |
|
|
end
|
463 |
|
|
endfunction
|
464 |
|
|
|
465 |
|
|
|
466 |
|
|
// get_sequences
|
467 |
|
|
// -------------
|
468 |
|
|
|
469 |
|
|
function void uvm_sequence_library::get_sequences(ref uvm_object_wrapper seq_types[$]);
|
470 |
|
|
foreach (sequences[i])
|
471 |
|
|
seq_types.push_back(sequences[i]);
|
472 |
|
|
endfunction
|
473 |
|
|
|
474 |
|
|
|
475 |
|
|
// select_sequence
|
476 |
|
|
// ---------------
|
477 |
|
|
|
478 |
|
|
function int unsigned uvm_sequence_library::select_sequence(int unsigned max);
|
479 |
|
|
static int unsigned counter;
|
480 |
|
|
select_sequence = counter;
|
481 |
|
|
counter++;
|
482 |
|
|
if (counter >= max)
|
483 |
|
|
counter = 0;
|
484 |
|
|
endfunction
|
485 |
|
|
|
486 |
|
|
|
487 |
|
|
//----------//
|
488 |
|
|
// INTERNAL //
|
489 |
|
|
//----------//
|
490 |
|
|
|
491 |
|
|
|
492 |
|
|
// init_sequence_library
|
493 |
|
|
// ---------------------
|
494 |
|
|
|
495 |
|
|
function void uvm_sequence_library::init_sequence_library();
|
496 |
|
|
foreach (this_type::m_typewide_sequences[i])
|
497 |
|
|
sequences.push_back(this_type::m_typewide_sequences[i]);
|
498 |
|
|
endfunction
|
499 |
|
|
|
500 |
|
|
|
501 |
|
|
|
502 |
|
|
// m_static_check
|
503 |
|
|
// --------------
|
504 |
|
|
|
505 |
|
|
|
506 |
|
|
function bit uvm_sequence_library::m_static_check(uvm_object_wrapper seq_type);
|
507 |
|
|
if (!m_check(seq_type,null))
|
508 |
|
|
return 0;
|
509 |
|
|
foreach (m_typewide_sequences[i])
|
510 |
|
|
if (m_typewide_sequences[i] == seq_type)
|
511 |
|
|
return 0;
|
512 |
|
|
return 1;
|
513 |
|
|
endfunction
|
514 |
|
|
|
515 |
|
|
|
516 |
|
|
// m_dyn_check
|
517 |
|
|
// -----------
|
518 |
|
|
|
519 |
|
|
function bit uvm_sequence_library::m_dyn_check(uvm_object_wrapper seq_type);
|
520 |
|
|
if (!m_check(seq_type,this))
|
521 |
|
|
return 0;
|
522 |
|
|
foreach (sequences[i])
|
523 |
|
|
if (sequences[i] == seq_type)
|
524 |
|
|
return 0;
|
525 |
|
|
return 1;
|
526 |
|
|
endfunction
|
527 |
|
|
|
528 |
|
|
|
529 |
|
|
// m_check
|
530 |
|
|
// -------
|
531 |
|
|
|
532 |
|
|
function bit uvm_sequence_library::m_check(uvm_object_wrapper seq_type, this_type lib);
|
533 |
|
|
uvm_object obj;
|
534 |
|
|
uvm_sequence_base seq;
|
535 |
|
|
uvm_root top;
|
536 |
|
|
uvm_coreservice_t cs;
|
537 |
|
|
string name;
|
538 |
|
|
string typ;
|
539 |
|
|
obj = seq_type.create_object();
|
540 |
|
|
name = (lib == null) ? type_name : lib.get_full_name();
|
541 |
|
|
typ = (lib == null) ? type_name : lib.get_type_name();
|
542 |
|
|
cs = uvm_coreservice_t::get();
|
543 |
|
|
top = cs.get_root();
|
544 |
|
|
|
545 |
|
|
if (!$cast(seq, obj)) begin
|
546 |
|
|
`uvm_error_context("SEQLIB/BAD_SEQ_TYPE",
|
547 |
|
|
{"Object '",obj.get_type_name(),
|
548 |
|
|
"' is not a sequence. Cannot add to sequence library '",name,
|
549 |
|
|
"'"},top)
|
550 |
|
|
return 0;
|
551 |
|
|
end
|
552 |
|
|
return 1;
|
553 |
|
|
endfunction
|
554 |
|
|
|
555 |
|
|
|
556 |
|
|
// pre_randomize
|
557 |
|
|
// -------------
|
558 |
|
|
|
559 |
|
|
function void uvm_sequence_library::pre_randomize();
|
560 |
|
|
m_get_config();
|
561 |
|
|
endfunction
|
562 |
|
|
|
563 |
|
|
|
564 |
|
|
// m_get_config
|
565 |
|
|
// ------------
|
566 |
|
|
|
567 |
|
|
function void uvm_sequence_library::m_get_config();
|
568 |
|
|
|
569 |
|
|
uvm_sequence_library_cfg cfg;
|
570 |
|
|
string phase_name;
|
571 |
|
|
uvm_phase starting_phase = get_starting_phase();
|
572 |
|
|
|
573 |
|
|
if (starting_phase != null) begin
|
574 |
|
|
phase_name = {starting_phase.get_name(),"_phase"};
|
575 |
|
|
end
|
576 |
|
|
if (uvm_config_db #(uvm_sequence_library_cfg)::get(m_sequencer,
|
577 |
|
|
phase_name,
|
578 |
|
|
"default_sequence.config",
|
579 |
|
|
cfg) ) begin
|
580 |
|
|
selection_mode = cfg.selection_mode;
|
581 |
|
|
min_random_count = cfg.min_random_count;
|
582 |
|
|
max_random_count = cfg.max_random_count;
|
583 |
|
|
end
|
584 |
|
|
else begin
|
585 |
|
|
void'(uvm_config_db #(int unsigned)::get(m_sequencer,
|
586 |
|
|
phase_name,
|
587 |
|
|
"default_sequence.min_random_count",
|
588 |
|
|
min_random_count) );
|
589 |
|
|
|
590 |
|
|
void'(uvm_config_db #(int unsigned)::get(m_sequencer,
|
591 |
|
|
phase_name,
|
592 |
|
|
"default_sequence.max_random_count",
|
593 |
|
|
max_random_count) );
|
594 |
|
|
|
595 |
|
|
void'(uvm_config_db #(uvm_sequence_lib_mode)::get(m_sequencer,
|
596 |
|
|
phase_name,
|
597 |
|
|
"default_sequence.selection_mode",
|
598 |
|
|
selection_mode) );
|
599 |
|
|
end
|
600 |
|
|
|
601 |
|
|
if (max_random_count == 0) begin
|
602 |
|
|
`uvm_warning("SEQLIB/MAX_ZERO",
|
603 |
|
|
$sformatf("max_random_count (%0d) zero. Nothing will be done.",
|
604 |
|
|
max_random_count))
|
605 |
|
|
if (min_random_count > max_random_count)
|
606 |
|
|
min_random_count = max_random_count;
|
607 |
|
|
end
|
608 |
|
|
else if (min_random_count > max_random_count) begin
|
609 |
|
|
`uvm_error("SEQLIB/MIN_GT_MAX",
|
610 |
|
|
$sformatf("min_random_count (%0d) greater than max_random_count (%0d). Setting min to max.",
|
611 |
|
|
min_random_count,max_random_count))
|
612 |
|
|
min_random_count = max_random_count;
|
613 |
|
|
end
|
614 |
|
|
else begin
|
615 |
|
|
if (selection_mode == UVM_SEQ_LIB_ITEM) begin
|
616 |
|
|
uvm_sequencer #(REQ,RSP) seqr;
|
617 |
|
|
uvm_object_wrapper lhs = REQ::get_type();
|
618 |
|
|
uvm_object_wrapper rhs = uvm_sequence_item::get_type();
|
619 |
|
|
if (lhs == rhs) begin
|
620 |
|
|
`uvm_error("SEQLIB/BASE_ITEM", {"selection_mode cannot be UVM_SEQ_LIB_ITEM when ",
|
621 |
|
|
"the REQ type is the base uvm_sequence_item. Using UVM_SEQ_LIB_RAND mode"})
|
622 |
|
|
selection_mode = UVM_SEQ_LIB_RAND;
|
623 |
|
|
end
|
624 |
|
|
if (m_sequencer == null || !$cast(seqr,m_sequencer)) begin
|
625 |
|
|
`uvm_error("SEQLIB/VIRT_SEQ", {"selection_mode cannot be UVM_SEQ_LIB_ITEM when ",
|
626 |
|
|
"running as a virtual sequence. Using UVM_SEQ_LIB_RAND mode"})
|
627 |
|
|
selection_mode = UVM_SEQ_LIB_RAND;
|
628 |
|
|
end
|
629 |
|
|
end
|
630 |
|
|
end
|
631 |
|
|
|
632 |
|
|
endfunction
|
633 |
|
|
|
634 |
|
|
|
635 |
|
|
// body
|
636 |
|
|
// ----
|
637 |
|
|
|
638 |
|
|
task uvm_sequence_library::body();
|
639 |
|
|
|
640 |
|
|
uvm_object_wrapper wrap;
|
641 |
|
|
uvm_phase starting_phase = get_starting_phase();
|
642 |
|
|
|
643 |
|
|
if (m_sequencer == null) begin
|
644 |
|
|
`uvm_fatal("SEQLIB/VIRT_SEQ", {"Sequence library 'm_sequencer' handle is null; ",
|
645 |
|
|
" no current support for running as a virtual sequence."})
|
646 |
|
|
return;
|
647 |
|
|
end
|
648 |
|
|
|
649 |
|
|
if (sequences.size() == 0) begin
|
650 |
|
|
`uvm_error("SEQLIB/NOSEQS", "Sequence library does not contain any sequences. Did you forget to call init_sequence_library() in the constructor?")
|
651 |
|
|
return;
|
652 |
|
|
end
|
653 |
|
|
|
654 |
|
|
if (do_not_randomize)
|
655 |
|
|
m_get_config();
|
656 |
|
|
|
657 |
|
|
m_safe_raise_starting_phase({"starting sequence library ",get_full_name()," (", get_type_name(),")"});
|
658 |
|
|
|
659 |
|
|
`uvm_info("SEQLIB/START",
|
660 |
|
|
$sformatf("Starting sequence library %s in %s phase: %0d iterations in mode %s",
|
661 |
|
|
get_type_name(),
|
662 |
|
|
(starting_phase != null ? starting_phase.get_name() : "unknown"),
|
663 |
|
|
sequence_count, selection_mode.name()),UVM_LOW)
|
664 |
|
|
|
665 |
|
|
`uvm_info("SEQLIB/SPRINT",{"\n",sprint(uvm_default_table_printer)},UVM_FULL)
|
666 |
|
|
|
667 |
|
|
case (selection_mode)
|
668 |
|
|
|
669 |
|
|
UVM_SEQ_LIB_RAND: begin
|
670 |
|
|
valid_rand_selection.constraint_mode(1);
|
671 |
|
|
valid_sequence_count.constraint_mode(0);
|
672 |
|
|
for (int i=1; i<=sequence_count; i++) begin
|
673 |
|
|
if (!randomize(select_rand)) begin
|
674 |
|
|
`uvm_error("SEQLIB/RAND_FAIL", "Random sequence selection failed")
|
675 |
|
|
break;
|
676 |
|
|
end
|
677 |
|
|
else begin
|
678 |
|
|
wrap = sequences[select_rand];
|
679 |
|
|
end
|
680 |
|
|
execute(wrap);
|
681 |
|
|
end
|
682 |
|
|
valid_rand_selection.constraint_mode(0);
|
683 |
|
|
valid_sequence_count.constraint_mode(1);
|
684 |
|
|
end
|
685 |
|
|
|
686 |
|
|
UVM_SEQ_LIB_RANDC: begin
|
687 |
|
|
uvm_object_wrapper q[$];
|
688 |
|
|
valid_randc_selection.constraint_mode(1);
|
689 |
|
|
valid_sequence_count.constraint_mode(0);
|
690 |
|
|
for (int i=1; i<=sequence_count; i++) begin
|
691 |
|
|
if (!randomize(select_randc)) begin
|
692 |
|
|
`uvm_error("SEQLIB/RANDC_FAIL", "Random sequence selection failed")
|
693 |
|
|
break;
|
694 |
|
|
end
|
695 |
|
|
else begin
|
696 |
|
|
wrap = sequences[select_randc];
|
697 |
|
|
end
|
698 |
|
|
q.push_back(wrap);
|
699 |
|
|
end
|
700 |
|
|
valid_randc_selection.constraint_mode(0);
|
701 |
|
|
valid_sequence_count.constraint_mode(1);
|
702 |
|
|
foreach(q[i])
|
703 |
|
|
execute(q[i]);
|
704 |
|
|
valid_randc_selection.constraint_mode(0);
|
705 |
|
|
valid_sequence_count.constraint_mode(1);
|
706 |
|
|
end
|
707 |
|
|
|
708 |
|
|
UVM_SEQ_LIB_ITEM: begin
|
709 |
|
|
for (int i=1; i<=sequence_count; i++) begin
|
710 |
|
|
wrap = REQ::get_type();
|
711 |
|
|
execute(wrap);
|
712 |
|
|
end
|
713 |
|
|
end
|
714 |
|
|
|
715 |
|
|
UVM_SEQ_LIB_USER: begin
|
716 |
|
|
for (int i=1; i<=sequence_count; i++) begin
|
717 |
|
|
int user_selection;
|
718 |
|
|
user_selection = select_sequence(sequences.size()-1);
|
719 |
|
|
if (user_selection >= sequences.size()) begin
|
720 |
|
|
`uvm_error("SEQLIB/USER_FAIL", "User sequence selection out of range")
|
721 |
|
|
wrap = REQ::get_type();
|
722 |
|
|
end
|
723 |
|
|
else begin
|
724 |
|
|
wrap = sequences[user_selection];
|
725 |
|
|
end
|
726 |
|
|
execute(wrap);
|
727 |
|
|
end
|
728 |
|
|
end
|
729 |
|
|
|
730 |
|
|
default: begin
|
731 |
|
|
`uvm_fatal("SEQLIB/RAND_MODE",
|
732 |
|
|
$sformatf("Unknown random sequence selection mode: %0d",selection_mode))
|
733 |
|
|
end
|
734 |
|
|
endcase
|
735 |
|
|
|
736 |
|
|
`uvm_info("SEQLIB/END",{"Ending sequence library in phase ",
|
737 |
|
|
(starting_phase != null ? starting_phase.get_name() : "unknown")},UVM_LOW)
|
738 |
|
|
|
739 |
|
|
`uvm_info("SEQLIB/DSTRB",$sformatf("%p",seqs_distrib),UVM_HIGH)
|
740 |
|
|
|
741 |
|
|
m_safe_drop_starting_phase({"starting sequence library ",get_full_name()," (", get_type_name(),")"});
|
742 |
|
|
|
743 |
|
|
endtask
|
744 |
|
|
|
745 |
|
|
|
746 |
|
|
// execute
|
747 |
|
|
// -------
|
748 |
|
|
|
749 |
|
|
task uvm_sequence_library::execute(uvm_object_wrapper wrap);
|
750 |
|
|
|
751 |
|
|
uvm_object obj;
|
752 |
|
|
uvm_sequence_item seq_or_item;
|
753 |
|
|
uvm_sequence_base seq_base;
|
754 |
|
|
REQ req_item;
|
755 |
|
|
|
756 |
|
|
uvm_coreservice_t cs = uvm_coreservice_t::get();
|
757 |
|
|
uvm_factory factory=cs.get_factory();
|
758 |
|
|
|
759 |
|
|
obj = factory.create_object_by_type(wrap,get_full_name(),
|
760 |
|
|
$sformatf("%s:%0d",wrap.get_type_name(),sequences_executed+1));
|
761 |
|
|
|
762 |
|
|
if (!$cast(seq_base, obj)) begin
|
763 |
|
|
// If we're executing an item (not a sequence)
|
764 |
|
|
if (!$cast(req_item, obj)) begin
|
765 |
|
|
// But it's not our item type (This can happen if we were parameterized with
|
766 |
|
|
// a pure virtual type, because we're getting get_type() from the base class)
|
767 |
|
|
`uvm_error("SEQLIB/WRONG_ITEM_TYPE", {"The item created by '", get_full_name(), "' when in 'UVM_SEQ_LIB_ITEM' mode doesn't match the REQ type which was passed in to the uvm_sequence_library#(REQ[,RSP]), this can happen if the REQ type which was passed in was a pure-virtual type. Either configure the factory overrides to properly generate items for this sequence library, or do not execute this sequence library in UVM_SEQ_LIB_ITEM mode."})
|
768 |
|
|
return;
|
769 |
|
|
end
|
770 |
|
|
end
|
771 |
|
|
|
772 |
|
|
void'($cast(seq_or_item,obj)); // already qualified,
|
773 |
|
|
|
774 |
|
|
`uvm_info("SEQLIB/EXEC",{"Executing ",(seq_or_item.is_item() ? "item " : "sequence "),seq_or_item.get_name(),
|
775 |
|
|
" (",seq_or_item.get_type_name(),")"},UVM_FULL)
|
776 |
|
|
seq_or_item.print_sequence_info = 1;
|
777 |
|
|
`uvm_rand_send(seq_or_item)
|
778 |
|
|
seqs_distrib[seq_or_item.get_type_name()] = seqs_distrib[seq_or_item.get_type_name()]+1;
|
779 |
|
|
|
780 |
|
|
sequences_executed++;
|
781 |
|
|
|
782 |
|
|
endtask
|
783 |
|
|
|
784 |
|
|
|
785 |
|
|
|
786 |
|
|
// do_print
|
787 |
|
|
// --------
|
788 |
|
|
|
789 |
|
|
function void uvm_sequence_library::do_print(uvm_printer printer);
|
790 |
|
|
printer.print_field_int("min_random_count",min_random_count,32,UVM_DEC,,"int unsigned");
|
791 |
|
|
printer.print_field_int("max_random_count",max_random_count,32,UVM_DEC,,"int unsigned");
|
792 |
|
|
printer.print_generic("selection_mode","uvm_sequence_lib_mode",32,selection_mode.name());
|
793 |
|
|
printer.print_field_int("sequence_count",sequence_count,32,UVM_DEC,,"int unsigned");
|
794 |
|
|
|
795 |
|
|
printer.print_array_header("typewide_sequences",m_typewide_sequences.size(),"queue_object_types");
|
796 |
|
|
foreach (m_typewide_sequences[i])
|
797 |
|
|
printer.print_generic($sformatf("[%0d]",i),"uvm_object_wrapper","-",m_typewide_sequences[i].get_type_name());
|
798 |
|
|
printer.print_array_footer();
|
799 |
|
|
|
800 |
|
|
printer.print_array_header("sequences",sequences.size(),"queue_object_types");
|
801 |
|
|
foreach (sequences[i])
|
802 |
|
|
printer.print_generic($sformatf("[%0d]",i),"uvm_object_wrapper","-",sequences[i].get_type_name());
|
803 |
|
|
printer.print_array_footer();
|
804 |
|
|
|
805 |
|
|
printer.print_array_header("seqs_distrib",seqs_distrib.num(),"as_int_string");
|
806 |
|
|
foreach (seqs_distrib[typ]) begin
|
807 |
|
|
printer.print_field_int({"[",typ,"]"},seqs_distrib[typ],32,,UVM_DEC,"int unsigned");
|
808 |
|
|
end
|
809 |
|
|
printer.print_array_footer();
|
810 |
|
|
endfunction
|
811 |
|
|
|
812 |
|
|
|