1 |
16 |
HanySalah |
//----------------------------------------------------------------------
|
2 |
|
|
// Copyright 2011 Cypress Semiconductor
|
3 |
|
|
// Copyright 2010-2011 Mentor Graphics Corporation
|
4 |
|
|
// Copyright 2014 NVIDIA Corporation
|
5 |
|
|
// All Rights Reserved Worldwide
|
6 |
|
|
//
|
7 |
|
|
// Licensed under the Apache License, Version 2.0 (the
|
8 |
|
|
// "License"); you may not use this file except in
|
9 |
|
|
// compliance with the License. You may obtain a copy of
|
10 |
|
|
// the License at
|
11 |
|
|
//
|
12 |
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
13 |
|
|
//
|
14 |
|
|
// Unless required by applicable law or agreed to in
|
15 |
|
|
// writing, software distributed under the License is
|
16 |
|
|
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
17 |
|
|
// CONDITIONS OF ANY KIND, either express or implied. See
|
18 |
|
|
// the License for the specific language governing
|
19 |
|
|
// permissions and limitations under the License.
|
20 |
|
|
//----------------------------------------------------------------------
|
21 |
|
|
|
22 |
|
|
typedef class uvm_phase;
|
23 |
|
|
|
24 |
|
|
//----------------------------------------------------------------------
|
25 |
|
|
// Title: UVM Configuration Database
|
26 |
|
|
//
|
27 |
|
|
// Topic: Intro
|
28 |
|
|
//
|
29 |
|
|
// The class provides a convenience interface
|
30 |
|
|
// on top of the to simplify the basic interface
|
31 |
|
|
// that is used for configuring instances.
|
32 |
|
|
//
|
33 |
|
|
// If the run-time ~+UVM_CONFIG_DB_TRACE~ command line option is specified,
|
34 |
|
|
// all configuration DB accesses (read and write) are displayed.
|
35 |
|
|
//----------------------------------------------------------------------
|
36 |
|
|
|
37 |
|
|
//Internal class for config waiters
|
38 |
|
|
class m_uvm_waiter;
|
39 |
|
|
string inst_name;
|
40 |
|
|
string field_name;
|
41 |
|
|
event trigger;
|
42 |
|
|
function new (string inst_name, string field_name);
|
43 |
|
|
this.inst_name = inst_name;
|
44 |
|
|
this.field_name = field_name;
|
45 |
|
|
endfunction
|
46 |
|
|
endclass
|
47 |
|
|
|
48 |
|
|
typedef class uvm_root;
|
49 |
|
|
typedef class uvm_config_db_options;
|
50 |
|
|
|
51 |
|
|
//----------------------------------------------------------------------
|
52 |
|
|
// class: uvm_config_db
|
53 |
|
|
//
|
54 |
|
|
// All of the functions in uvm_config_db#(T) are static, so they
|
55 |
|
|
// must be called using the :: operator. For example:
|
56 |
|
|
//
|
57 |
|
|
//| uvm_config_db#(int)::set(this, "*", "A");
|
58 |
|
|
//
|
59 |
|
|
// The parameter value "int" identifies the configuration type as
|
60 |
|
|
// an int property.
|
61 |
|
|
//
|
62 |
|
|
// The and methods provide the same API and
|
63 |
|
|
// semantics as the set/get_config_* functions in .
|
64 |
|
|
//----------------------------------------------------------------------
|
65 |
|
|
class uvm_config_db#(type T=int) extends uvm_resource_db#(T);
|
66 |
|
|
|
67 |
|
|
// Internal lookup of config settings so they can be reused
|
68 |
|
|
// The context has a pool that is keyed by the inst/field name.
|
69 |
|
|
static uvm_pool#(string,uvm_resource#(T)) m_rsc[uvm_component];
|
70 |
|
|
|
71 |
|
|
// Internal waiter list for wait_modified
|
72 |
|
|
static local uvm_queue#(m_uvm_waiter) m_waiters[string];
|
73 |
|
|
|
74 |
|
|
// function: get
|
75 |
|
|
//
|
76 |
|
|
// Get the value for ~field_name~ in ~inst_name~, using component ~cntxt~ as
|
77 |
|
|
// the starting search point. ~inst_name~ is an explicit instance name
|
78 |
|
|
// relative to ~cntxt~ and may be an empty string if the ~cntxt~ is the
|
79 |
|
|
// instance that the configuration object applies to. ~field_name~
|
80 |
|
|
// is the specific field in the scope that is being searched for.
|
81 |
|
|
//
|
82 |
|
|
// The basic ~get_config_*~ methods from are mapped to
|
83 |
|
|
// this function as:
|
84 |
|
|
//
|
85 |
|
|
//| get_config_int(...) => uvm_config_db#(uvm_bitstream_t)::get(cntxt,...)
|
86 |
|
|
//| get_config_string(...) => uvm_config_db#(string)::get(cntxt,...)
|
87 |
|
|
//| get_config_object(...) => uvm_config_db#(uvm_object)::get(cntxt,...)
|
88 |
|
|
|
89 |
|
|
static function bit get(uvm_component cntxt,
|
90 |
|
|
string inst_name,
|
91 |
|
|
string field_name,
|
92 |
|
|
inout T value);
|
93 |
|
|
//TBD: add file/line
|
94 |
|
|
int unsigned p;
|
95 |
|
|
uvm_resource#(T) r, rt;
|
96 |
|
|
uvm_resource_pool rp = uvm_resource_pool::get();
|
97 |
|
|
uvm_resource_types::rsrc_q_t rq;
|
98 |
|
|
uvm_coreservice_t cs = uvm_coreservice_t::get();
|
99 |
|
|
|
100 |
|
|
if(cntxt == null)
|
101 |
|
|
cntxt = cs.get_root();
|
102 |
|
|
if(inst_name == "")
|
103 |
|
|
inst_name = cntxt.get_full_name();
|
104 |
|
|
else if(cntxt.get_full_name() != "")
|
105 |
|
|
inst_name = {cntxt.get_full_name(), ".", inst_name};
|
106 |
|
|
|
107 |
|
|
rq = rp.lookup_regex_names(inst_name, field_name, uvm_resource#(T)::get_type());
|
108 |
|
|
r = uvm_resource#(T)::get_highest_precedence(rq);
|
109 |
|
|
|
110 |
|
|
if(uvm_config_db_options::is_tracing())
|
111 |
|
|
m_show_msg("CFGDB/GET", "Configuration","read", inst_name, field_name, cntxt, r);
|
112 |
|
|
|
113 |
|
|
if(r == null)
|
114 |
|
|
return 0;
|
115 |
|
|
|
116 |
|
|
value = r.read(cntxt);
|
117 |
|
|
|
118 |
|
|
return 1;
|
119 |
|
|
endfunction
|
120 |
|
|
|
121 |
|
|
// function: set
|
122 |
|
|
//
|
123 |
|
|
// Create a new or update an existing configuration setting for
|
124 |
|
|
// ~field_name~ in ~inst_name~ from ~cntxt~.
|
125 |
|
|
// The setting is made at ~cntxt~, with the full scope of the set
|
126 |
|
|
// being {~cntxt~,".",~inst_name~}. If ~cntxt~ is ~null~ then ~inst_name~
|
127 |
|
|
// provides the complete scope information of the setting.
|
128 |
|
|
// ~field_name~ is the target field. Both ~inst_name~ and ~field_name~
|
129 |
|
|
// may be glob style or regular expression style expressions.
|
130 |
|
|
//
|
131 |
|
|
// If a setting is made at build time, the ~cntxt~ hierarchy is
|
132 |
|
|
// used to determine the setting's precedence in the database.
|
133 |
|
|
// Settings from hierarchically higher levels have higher
|
134 |
|
|
// precedence. Settings from the same level of hierarchy have
|
135 |
|
|
// a last setting wins semantic. A precedence setting of
|
136 |
|
|
// is used for uvm_top, and
|
137 |
|
|
// each hierarchical level below the top is decremented by 1.
|
138 |
|
|
//
|
139 |
|
|
// After build time, all settings use the default precedence and thus
|
140 |
|
|
// have a last wins semantic. So, if at run time, a low level
|
141 |
|
|
// component makes a runtime setting of some field, that setting
|
142 |
|
|
// will have precedence over a setting from the test level that was
|
143 |
|
|
// made earlier in the simulation.
|
144 |
|
|
//
|
145 |
|
|
// The basic ~set_config_*~ methods from are mapped to
|
146 |
|
|
// this function as:
|
147 |
|
|
//
|
148 |
|
|
//| set_config_int(...) => uvm_config_db#(uvm_bitstream_t)::set(cntxt,...)
|
149 |
|
|
//| set_config_string(...) => uvm_config_db#(string)::set(cntxt,...)
|
150 |
|
|
//| set_config_object(...) => uvm_config_db#(uvm_object)::set(cntxt,...)
|
151 |
|
|
|
152 |
|
|
static function void set(uvm_component cntxt,
|
153 |
|
|
string inst_name,
|
154 |
|
|
string field_name,
|
155 |
|
|
T value);
|
156 |
|
|
|
157 |
|
|
uvm_root top;
|
158 |
|
|
uvm_phase curr_phase;
|
159 |
|
|
uvm_resource#(T) r;
|
160 |
|
|
bit exists;
|
161 |
|
|
string lookup;
|
162 |
|
|
uvm_pool#(string,uvm_resource#(T)) pool;
|
163 |
|
|
string rstate;
|
164 |
|
|
uvm_coreservice_t cs = uvm_coreservice_t::get();
|
165 |
|
|
|
166 |
|
|
//take care of random stability during allocation
|
167 |
|
|
process p = process::self();
|
168 |
|
|
if(p != null)
|
169 |
|
|
rstate = p.get_randstate();
|
170 |
|
|
|
171 |
|
|
top = cs.get_root();
|
172 |
|
|
|
173 |
|
|
curr_phase = top.m_current_phase;
|
174 |
|
|
|
175 |
|
|
if(cntxt == null)
|
176 |
|
|
cntxt = top;
|
177 |
|
|
if(inst_name == "")
|
178 |
|
|
inst_name = cntxt.get_full_name();
|
179 |
|
|
else if(cntxt.get_full_name() != "")
|
180 |
|
|
inst_name = {cntxt.get_full_name(), ".", inst_name};
|
181 |
|
|
|
182 |
|
|
if(!m_rsc.exists(cntxt)) begin
|
183 |
|
|
m_rsc[cntxt] = new;
|
184 |
|
|
end
|
185 |
|
|
pool = m_rsc[cntxt];
|
186 |
|
|
|
187 |
|
|
// Insert the token in the middle to prevent cache
|
188 |
|
|
// oddities like i=foobar,f=xyz and i=foo,f=barxyz.
|
189 |
|
|
// Can't just use '.', because '.' isn't illegal
|
190 |
|
|
// in field names
|
191 |
|
|
lookup = {inst_name, "__M_UVM__", field_name};
|
192 |
|
|
|
193 |
|
|
if(!pool.exists(lookup)) begin
|
194 |
|
|
r = new(field_name, inst_name);
|
195 |
|
|
pool.add(lookup, r);
|
196 |
|
|
end
|
197 |
|
|
else begin
|
198 |
|
|
r = pool.get(lookup);
|
199 |
|
|
exists = 1;
|
200 |
|
|
end
|
201 |
|
|
|
202 |
|
|
if(curr_phase != null && curr_phase.get_name() == "build")
|
203 |
|
|
r.precedence = uvm_resource_base::default_precedence - (cntxt.get_depth());
|
204 |
|
|
else
|
205 |
|
|
r.precedence = uvm_resource_base::default_precedence;
|
206 |
|
|
|
207 |
|
|
r.write(value, cntxt);
|
208 |
|
|
|
209 |
|
|
if(exists) begin
|
210 |
|
|
uvm_resource_pool rp = uvm_resource_pool::get();
|
211 |
|
|
rp.set_priority_name(r, uvm_resource_types::PRI_HIGH);
|
212 |
|
|
end
|
213 |
|
|
else begin
|
214 |
|
|
//Doesn't exist yet, so put it in resource db at the head.
|
215 |
|
|
r.set_override();
|
216 |
|
|
end
|
217 |
|
|
|
218 |
|
|
//trigger any waiters
|
219 |
|
|
if(m_waiters.exists(field_name)) begin
|
220 |
|
|
m_uvm_waiter w;
|
221 |
|
|
for(int i=0; i
|
222 |
|
|
w = m_waiters[field_name].get(i);
|
223 |
|
|
if(uvm_re_match(uvm_glob_to_re(inst_name),w.inst_name) == 0)
|
224 |
|
|
->w.trigger;
|
225 |
|
|
end
|
226 |
|
|
end
|
227 |
|
|
|
228 |
|
|
if(p != null)
|
229 |
|
|
p.set_randstate(rstate);
|
230 |
|
|
|
231 |
|
|
if(uvm_config_db_options::is_tracing())
|
232 |
|
|
m_show_msg("CFGDB/SET", "Configuration","set", inst_name, field_name, cntxt, r);
|
233 |
|
|
endfunction
|
234 |
|
|
|
235 |
|
|
|
236 |
|
|
// function: exists
|
237 |
|
|
//
|
238 |
|
|
// Check if a value for ~field_name~ is available in ~inst_name~, using
|
239 |
|
|
// component ~cntxt~ as the starting search point. ~inst_name~ is an explicit
|
240 |
|
|
// instance name relative to ~cntxt~ and may be an empty string if the
|
241 |
|
|
// ~cntxt~ is the instance that the configuration object applies to.
|
242 |
|
|
// ~field_name~ is the specific field in the scope that is being searched for.
|
243 |
|
|
// The ~spell_chk~ arg can be set to 1 to turn spell checking on if it
|
244 |
|
|
// is expected that the field should exist in the database. The function
|
245 |
|
|
// returns 1 if a config parameter exists and 0 if it doesn't exist.
|
246 |
|
|
//
|
247 |
|
|
|
248 |
|
|
static function bit exists(uvm_component cntxt, string inst_name,
|
249 |
|
|
string field_name, bit spell_chk=0);
|
250 |
|
|
uvm_coreservice_t cs = uvm_coreservice_t::get();
|
251 |
|
|
|
252 |
|
|
if(cntxt == null)
|
253 |
|
|
cntxt = cs.get_root();
|
254 |
|
|
if(inst_name == "")
|
255 |
|
|
inst_name = cntxt.get_full_name();
|
256 |
|
|
else if(cntxt.get_full_name() != "")
|
257 |
|
|
inst_name = {cntxt.get_full_name(), ".", inst_name};
|
258 |
|
|
|
259 |
|
|
return (uvm_resource_db#(T)::get_by_name(inst_name,field_name,spell_chk) != null);
|
260 |
|
|
endfunction
|
261 |
|
|
|
262 |
|
|
|
263 |
|
|
// Function: wait_modified
|
264 |
|
|
//
|
265 |
|
|
// Wait for a configuration setting to be set for ~field_name~
|
266 |
|
|
// in ~cntxt~ and ~inst_name~. The task blocks until a new configuration
|
267 |
|
|
// setting is applied that effects the specified field.
|
268 |
|
|
|
269 |
|
|
static task wait_modified(uvm_component cntxt, string inst_name,
|
270 |
|
|
string field_name);
|
271 |
|
|
process p = process::self();
|
272 |
|
|
string rstate = p.get_randstate();
|
273 |
|
|
m_uvm_waiter waiter;
|
274 |
|
|
uvm_coreservice_t cs = uvm_coreservice_t::get();
|
275 |
|
|
|
276 |
|
|
if(cntxt == null)
|
277 |
|
|
cntxt = cs.get_root();
|
278 |
|
|
if(cntxt != cs.get_root()) begin
|
279 |
|
|
if(inst_name != "")
|
280 |
|
|
inst_name = {cntxt.get_full_name(),".",inst_name};
|
281 |
|
|
else
|
282 |
|
|
inst_name = cntxt.get_full_name();
|
283 |
|
|
end
|
284 |
|
|
|
285 |
|
|
waiter = new(inst_name, field_name);
|
286 |
|
|
|
287 |
|
|
if(!m_waiters.exists(field_name))
|
288 |
|
|
m_waiters[field_name] = new;
|
289 |
|
|
m_waiters[field_name].push_back(waiter);
|
290 |
|
|
|
291 |
|
|
p.set_randstate(rstate);
|
292 |
|
|
|
293 |
|
|
// wait on the waiter to trigger
|
294 |
|
|
@waiter.trigger;
|
295 |
|
|
|
296 |
|
|
// Remove the waiter from the waiter list
|
297 |
|
|
for(int i=0; i
|
298 |
|
|
if(m_waiters[field_name].get(i) == waiter) begin
|
299 |
|
|
m_waiters[field_name].delete(i);
|
300 |
|
|
break;
|
301 |
|
|
end
|
302 |
|
|
end
|
303 |
|
|
endtask
|
304 |
|
|
|
305 |
|
|
|
306 |
|
|
endclass
|
307 |
|
|
|
308 |
|
|
// Section: Types
|
309 |
|
|
|
310 |
|
|
//----------------------------------------------------------------------
|
311 |
|
|
// Topic: uvm_config_int
|
312 |
|
|
//
|
313 |
|
|
// Convenience type for uvm_config_db#(uvm_bitstream_t)
|
314 |
|
|
//
|
315 |
|
|
//| typedef uvm_config_db#(uvm_bitstream_t) uvm_config_int;
|
316 |
|
|
typedef uvm_config_db#(uvm_bitstream_t) uvm_config_int;
|
317 |
|
|
|
318 |
|
|
//----------------------------------------------------------------------
|
319 |
|
|
// Topic: uvm_config_string
|
320 |
|
|
//
|
321 |
|
|
// Convenience type for uvm_config_db#(string)
|
322 |
|
|
//
|
323 |
|
|
//| typedef uvm_config_db#(string) uvm_config_string;
|
324 |
|
|
typedef uvm_config_db#(string) uvm_config_string;
|
325 |
|
|
|
326 |
|
|
//----------------------------------------------------------------------
|
327 |
|
|
// Topic: uvm_config_object
|
328 |
|
|
//
|
329 |
|
|
// Convenience type for uvm_config_db#(uvm_object)
|
330 |
|
|
//
|
331 |
|
|
//| typedef uvm_config_db#(uvm_object) uvm_config_object;
|
332 |
|
|
typedef uvm_config_db#(uvm_object) uvm_config_object;
|
333 |
|
|
|
334 |
|
|
//----------------------------------------------------------------------
|
335 |
|
|
// Topic: uvm_config_wrapper
|
336 |
|
|
//
|
337 |
|
|
// Convenience type for uvm_config_db#(uvm_object_wrapper)
|
338 |
|
|
//
|
339 |
|
|
//| typedef uvm_config_db#(uvm_object_wrapper) uvm_config_wrapper;
|
340 |
|
|
typedef uvm_config_db#(uvm_object_wrapper) uvm_config_wrapper;
|
341 |
|
|
|
342 |
|
|
|
343 |
|
|
//----------------------------------------------------------------------
|
344 |
|
|
// Class: uvm_config_db_options
|
345 |
|
|
//
|
346 |
|
|
// Provides a namespace for managing options for the
|
347 |
|
|
// configuration DB facility. The only thing allowed in this class is static
|
348 |
|
|
// local data members and static functions for manipulating and
|
349 |
|
|
// retrieving the value of the data members. The static local data
|
350 |
|
|
// members represent options and settings that control the behavior of
|
351 |
|
|
// the configuration DB facility.
|
352 |
|
|
|
353 |
|
|
// Options include:
|
354 |
|
|
//
|
355 |
|
|
// * tracing: on/off
|
356 |
|
|
//
|
357 |
|
|
// The default for tracing is off.
|
358 |
|
|
//
|
359 |
|
|
//----------------------------------------------------------------------
|
360 |
|
|
class uvm_config_db_options;
|
361 |
|
|
|
362 |
|
|
static local bit ready;
|
363 |
|
|
static local bit tracing;
|
364 |
|
|
|
365 |
|
|
// Function: turn_on_tracing
|
366 |
|
|
//
|
367 |
|
|
// Turn tracing on for the configuration database. This causes all
|
368 |
|
|
// reads and writes to the database to display information about
|
369 |
|
|
// the accesses. Tracing is off by default.
|
370 |
|
|
//
|
371 |
|
|
// This method is implicitly called by the ~+UVM_CONFIG_DB_TRACE~.
|
372 |
|
|
|
373 |
|
|
static function void turn_on_tracing();
|
374 |
|
|
if (!ready) init();
|
375 |
|
|
tracing = 1;
|
376 |
|
|
endfunction
|
377 |
|
|
|
378 |
|
|
// Function: turn_off_tracing
|
379 |
|
|
//
|
380 |
|
|
// Turn tracing off for the configuration database.
|
381 |
|
|
|
382 |
|
|
static function void turn_off_tracing();
|
383 |
|
|
if (!ready) init();
|
384 |
|
|
tracing = 0;
|
385 |
|
|
endfunction
|
386 |
|
|
|
387 |
|
|
// Function: is_tracing
|
388 |
|
|
//
|
389 |
|
|
// Returns 1 if the tracing facility is on and 0 if it is off.
|
390 |
|
|
|
391 |
|
|
static function bit is_tracing();
|
392 |
|
|
if (!ready) init();
|
393 |
|
|
return tracing;
|
394 |
|
|
endfunction
|
395 |
|
|
|
396 |
|
|
|
397 |
|
|
static local function void init();
|
398 |
|
|
uvm_cmdline_processor clp;
|
399 |
|
|
string trace_args[$];
|
400 |
|
|
|
401 |
|
|
clp = uvm_cmdline_processor::get_inst();
|
402 |
|
|
|
403 |
|
|
if (clp.get_arg_matches("+UVM_CONFIG_DB_TRACE", trace_args)) begin
|
404 |
|
|
tracing = 1;
|
405 |
|
|
end
|
406 |
|
|
|
407 |
|
|
ready = 1;
|
408 |
|
|
endfunction
|
409 |
|
|
|
410 |
|
|
endclass
|