SyoSil ApS UVM Scoreboard  1.0.3.0
cl_syoscb.svh
1 /// Top level class implementing the root of the SyoSil UVM scoreboard
2 class cl_syoscb extends uvm_scoreboard;
3  //-------------------------------------
4  // Non randomizable variables
5  //-------------------------------------
6  /// Handle to the global UVM scoreboard configuration
8 
9  /// Array holding handles to all queues
11 
12  /// Handle to the compare strategy
14 
15  /// Associative array holding a uvm_subscriber for each queue
17 
18  /// Flag indicating if a scoreboard header has been dumped when dumping shadow queues
19  local bit header_dumped[string];
20 
21  /// AA containing failed scoreboard check (e.g. no items inserted))
22  local string failed_checks[string];
23 
24  /// Mutex to be used when calls to #add_item should be mutexed
25  local semaphore add_item_mutex;
26 
27  //-------------------------------------
28  // UVM Macros
29  //-------------------------------------
30  `uvm_component_utils_begin(cl_syoscb)
31  `uvm_field_object(cfg, UVM_DEFAULT)
32  //`uvm_field_array_object(queues, UVM_DEFAULT)
33  `uvm_field_object(compare_strategy, UVM_DEFAULT)
34  `uvm_field_aa_object_string(subscribers, UVM_DEFAULT)
35  `uvm_field_aa_int_string(header_dumped, UVM_DEFAULT)
36  `uvm_component_utils_end
37 
38  //-------------------------------------
39  // Constructor
40  //-------------------------------------
41  extern function new(string name = "cl_syoscb", uvm_component parent = null);
42  //-------------------------------------
43  // UVM Phase methods
44  //-------------------------------------
45  extern function void build_phase(uvm_phase phase);
46  extern function void end_of_elaboration_phase(uvm_phase phase);
47  extern function void check_phase(uvm_phase phase);
48  extern function void report_phase(uvm_phase phase);
49  extern function void final_phase(uvm_phase phase);
50 
51  //-------------------------------------
52  // Function based API
53  //-------------------------------------
54  extern virtual function void add_item(string queue_name, string producer,
55  uvm_sequence_item item);
56  extern virtual task add_item_mutexed(string queue_name, string producer,
57  uvm_sequence_item item);
58  extern virtual function void compare_trigger(string queue_name= "",
59  cl_syoscb_item item = null);
60  extern virtual function void dump();
61  extern virtual function void flush_queues_all();
62  extern virtual function void flush_queues(string queue_name = "");
63  extern virtual function bit empty_queues(string queue_name = "");
64  extern virtual function bit insert_queues(string queue_name = "");
65  extern virtual function void compare_control(bit cc);
66  extern virtual function string create_total_stats(int unsigned offset,
67  int unsigned first_column_width);
68  extern virtual function string create_report(bit end_of_sim = 1'b1);
69  extern virtual function int unsigned get_total_cnt_add_items();
70  extern virtual function int unsigned get_total_cnt_flushed_items();
71  extern virtual function int unsigned get_total_queue_size();
72  extern virtual function string get_failed_checks();
73 
74 
75  //-------------------------------------
76  // Transaction based API
77  //-------------------------------------
78  extern virtual function cl_syoscb_subscriber get_subscriber(string queue_name, string producer);
79 
80  //-------------------------------------
81  // Misc. functions for internal usage
82  //-------------------------------------
83  extern virtual function cl_syoscb_cfg get_cfg();
84  extern virtual function string create_report_contents(int unsigned offset,
85  int unsigned first_column_width);
86  extern virtual function void pre_abort();
87 
88  extern protected virtual function void dump_txt();
89  extern protected virtual function void dump_xml();
90  extern protected virtual function void dump_split_txt();
91  extern protected virtual function void dump_join_txt();
92  extern protected virtual function void dump_split_xml();
93  extern protected virtual function void dump_join_xml();
94  extern protected virtual function string print_header(string queue_name);
95  extern protected virtual function string create_queues_stats(int unsigned offset,
96  int unsigned first_column_width);
97  extern protected virtual function string get_queue_failed_checks();
98  extern protected virtual function void override_queue_type();
99  extern protected virtual function void override_compare_type();
100  extern protected virtual function void config_validation();
101  extern protected virtual function void intermediate_queue_stat_dump(string queue_name);
102 endclass: cl_syoscb
103 
104 function cl_syoscb::new(string name = "cl_syoscb", uvm_component parent = null);
105  super.new(name, parent);
106 endfunction : new
107 
108 /// UVM build phase. Gets the scoreboard configuration and forwards it to the child components
109 /// (cl_syoscb_queue and cl_syoscb_compare). Additionally, it creates all of the queues defined
110 /// in the configuration object.
111 /// Finally, it also creates the compare strategy via a factory create call.
112 function void cl_syoscb::build_phase(uvm_phase phase);
113  if (!uvm_config_db #(cl_syoscb_cfg)::get(this, "", "cfg", this.cfg)) begin
114  // *NOTE*: If no cfg object is given then no scb name is available
115  // Thus, no scb name is printed here
116  `uvm_fatal("CFG_ERROR", "Configuration object not passed.")
117  end
118 
119  // Set the default SCB name if not specified explicitly
120  if(this.cfg.get_scb_name() == "") begin
121  this.cfg.set_scb_name(this.get_name());
122  end
123 
124  // Print the SCB cfg according to its internal member field knob
125  if(this.cfg.get_print_cfg()) begin
126  this.cfg.print();
127  end
128 
129  // Create list of queues
130  this.queues = new[this.cfg.size_queues()];
131 
132  // Override the queue type basing on current scb cfg
133  this.override_queue_type();
134 
135  // Forward the configuration to the compare_strategy
136  uvm_config_db #(cl_syoscb_cfg)::set(this, "compare_strategy", "cfg", this.cfg);
137 
138  // Override the compare type basing on current scb cfg
139  this.override_compare_type();
140 
141  // Create the compare strategy
142  this.compare_strategy = cl_syoscb_compare::type_id::create(.name("compare_strategy"),
143  .parent(this));
144 
145  //Initialize mutex if necessary
146  if(this.cfg.get_mutexed_add_item_enable()) begin
147  this.add_item_mutex = new(1);
148  end
149 
150  begin
151  string producers[];
152 
153  this.cfg.get_producers(producers);
154 
155  foreach(producers[i]) begin
156  cl_syoscb_cfg_pl pl = this.cfg.get_producer(producers[i]);
157 
158  foreach(pl.list[j]) begin
159  cl_syoscb_subscriber subscriber;
160 
161  subscriber = cl_syoscb_subscriber::type_id::create({producers[i], "_", pl.list[j], "_subscr"}, this);
162  subscriber.set_queue_name(pl.list[j]);
163  subscriber.set_producer(producers[i]);
164  subscriber.set_mutexed_add_item_enable(this.cfg.get_mutexed_add_item_enable());
165  this.subscribers[{pl.list[j], producers[i]}] = subscriber;
166  end
167  end
168  end
169 endfunction: build_phase
170 
171 /// UVM end of elaboration phase. Validate the scb configuration before proceding forward.
172 /// Generate a UVM_FATAL for configuration combinations which are not allowed, or a warning if the combination
173 /// has been internally evaluated as not recommended.
174 function void cl_syoscb::end_of_elaboration_phase(uvm_phase phase);
175  super.end_of_elaboration_phase(phase);
176 
177  this.config_validation();
178 endfunction: end_of_elaboration_phase
179 
180 /// UVM check phase. Checks if the SCB is empty. If true and cl_syoscb_cfg#enable_no_insert_check is true,
181 /// a UVM error is issued.
182 function void cl_syoscb::check_phase(uvm_phase phase);
183  // Check that this scb is empty. If not then issue an error
184  if(!this.empty_queues()) begin
185  this.failed_checks["SCB_NOT_EMPTY"] = $sformatf("Scb %s not empty", this.cfg.get_scb_name());
186  end
187 
188  // Check if insert check is enabled, and issue an error if one of the queues has not been filled with at least one element
189  if(this.cfg.get_enable_no_insert_check() && !this.insert_queues()) begin
190  this.failed_checks["SCB_NO_INSERTS"] = $sformatf("Nothing has been inserted in Scb %s", this.cfg.get_scb_name());
191  end
192 endfunction: check_phase
193 
194 /// UVM report phase. Prints the status of the scoreboard instance.
195 function void cl_syoscb::report_phase(uvm_phase phase);
196  super.report_phase(phase);
197 
198  if(!this.cfg.get_disable_report()) begin
199  string report;
200 
201  report = this.create_report();
202  // *NOTE*: Using this.get_name() is sufficient since the component
203  // instance name is the queue name by definition
204  `uvm_info("QUEUE", $sformatf("[%s]: Statistics summary:%s", this.cfg.get_scb_name(), report), UVM_NONE)
205 
206  // Report any errors when in control
207  begin
208  string failed_checks;
209 
210  failed_checks = { failed_checks, this.get_queue_failed_checks() };
211 
212  if(failed_checks != "") begin
213  `uvm_error("QUEUE_ERROR", $sformatf("[%s]: Queue errors:\n%s", this.cfg.get_scb_name(), failed_checks))
214  end
215  end
216  end
217 endfunction: report_phase
218 
219 /// UVM final phase. Prints in the file called dump.txt the information about the shadow queue of all the queues.
220 function void cl_syoscb::final_phase(uvm_phase phase);
221  if(this.cfg.get_full_scb_dump() == 1'b1) begin
222  this.dump();
223  end
224 endfunction: final_phase
225 
226 /// Gets the configuration for this scoreboard
227 function cl_syoscb_cfg cl_syoscb::get_cfg();
228  return this.cfg;
229 endfunction: get_cfg
230 
231 /// <b> Scoreboard API:</b> Adds a uvm_sequence_item to a given queue for a given producer.
232 /// The method will check if the queue and producer exists before adding it to the queue.
233 ///
234 /// \param queue_name The name of the queue the item should be added to
235 /// \param producer The name of the producer that generated this item
236 /// \param item The sequence item that should be added to the queue
237 function void cl_syoscb::add_item(string queue_name, string producer, uvm_sequence_item item);
238  cl_syoscb_queue_base queue;
239  uvm_sequence_item item_clone;
240 
241  // Check queue
242  if(!this.cfg.exist_queue(queue_name)) begin
243  `uvm_fatal("CFG_ERROR", $sformatf("[%s]: Queue: %0s is not found", this.cfg.get_scb_name(), queue_name));
244  end
245 
246  // Check producer
247  if(!this.cfg.exist_producer(producer)) begin
248  `uvm_fatal("CFG_ERROR", $sformatf("[%s]: Producer: %0s is not found", this.cfg.get_scb_name(), producer));
249  end
250 
251  // Clone the item if not disabled
252  // Clone the item in order to isolate the UVM scb from the rest of the TB
253  if(this.cfg.get_disable_clone() == 1'b0) begin
254  if(!$cast(item_clone, item.clone())) begin
255  `uvm_fatal("QUEUE_ERROR", $sformatf("[%s]: Unable to cast cloned item to uvm_sequence_item", this.cfg.get_scb_name()));
256  end
257  end else begin
258  item_clone = item;
259  end
260 
261  // Add the uvm_sequence_item to the queue for the given producer
262  queue = this.cfg.get_queue(queue_name);
263 
264  if(queue == null) begin
265  `uvm_fatal("QUEUE_ERROR", $sformatf("[%s]: Queue: %s not found by add_item method", this.cfg.get_scb_name(), queue_name));
266  end
267 
268  // Check that the max_queue_size for this queue is not reached
269  if(this.cfg.get_max_queue_size(queue_name)>0 &&
270  queue.get_size()==this.cfg.get_max_queue_size(queue_name)) begin
271  `uvm_error("QUEUE_ERROR", $sformatf("[%s]: Maximum number of items (%0d) for queue: %s reached",
272  this.cfg.get_scb_name(),
273  this.cfg.get_max_queue_size(queue_name),
274  queue_name))
275  end
276 
277  if(!queue.add_item(producer, item_clone)) begin
278  `uvm_fatal("QUEUE_ERROR", $sformatf("[%s]: Unable to add item to queue: %s", this.cfg.get_scb_name(), queue_name));
279  end
280 
281  `uvm_info("DEBUG", $sformatf("[%s]: Trigger compare by queue: %s, producer: %s", this.cfg.get_scb_name(), queue_name, producer), UVM_FULL);
282 
283  // Invoke the compare algorithm
284  // Pass the last added item for compare optimization
285  this.compare_trigger(queue_name, queue.get_last_inserted_item());
286 
287  if(this.cfg.get_full_scb_dump() == 1'b1 &&
288  this.cfg.get_full_scb_max_queue_size(queue_name) > 0 &&
289  queue.shadow_items.size() == this.cfg.get_full_scb_max_queue_size(queue_name)) begin
290  this.dump();
291  end
292 
293  //Check if queue stats should be dumped
294  if(this.cfg.get_queue_stat_interval(queue_name) > 0 && queue.get_cnt_add_item() % this.cfg.get_queue_stat_interval(queue_name) == 0) begin
295  this.intermediate_queue_stat_dump(queue_name);
296  end
297 
298  //And if full SCB stats should also be dumped
299  if(this.cfg.get_scb_stat_interval() > 0 && this.get_total_cnt_add_items() % this.cfg.get_scb_stat_interval() == 0) begin
300  `uvm_info("QUEUE_STAT", $sformatf("[%s] %0d items added to this scoreboard, intermediate statistics summary:%0s",
301  this.get_name(),
302  this.get_total_cnt_add_items(),
303  this.create_report(1'b0)),
304  UVM_LOW);
305  end
306 endfunction: add_item
307 
308 /// <b> Scoreboard API:</b> Add an item to the scoreboard, using a mutex to ensure than no more
309 /// than one item is ever added to the SCB at the same time.
310 /// For additional details on adding items to the SCB, see #add_item
311 /// \param queue_name The name of the queue the item should be added to
312 /// \param producer The name of the producer that generated this item
313 /// \param item The sequence item that should be added to the queue
314 task cl_syoscb::add_item_mutexed(string queue_name, string producer, uvm_sequence_item item);
315  if(!this.cfg.get_mutexed_add_item_enable()) begin
316  `uvm_fatal("CFG_ERROR", $sformatf("[%s]: Cannot add an item in mutexed fashion when mutexed_add_item_enable is 0", this.get_name()));
317  end
318  this.add_item_mutex.get();
319  this.add_item(queue_name, producer, item);
320  this.add_item_mutex.put();
321 endtask: add_item_mutexed
322 
323 
324 /// <b> Scoreboard API:</b> Invokes the scoreboard's compare strategy
325 function void cl_syoscb::compare_trigger(string queue_name = "", cl_syoscb_item item = null);
326  this.compare_strategy.compare_trigger(queue_name, item);
327 endfunction: compare_trigger
328 
329 /// <b> Scoreboard API:</b> Dump items to files if cl_syoscb_cfg#full_scb_dump is enabled
330 function void cl_syoscb::dump();
331  case (this.cfg.get_full_scb_dump_type())
332  pk_syoscb::TXT:
333  this.dump_txt();
334  pk_syoscb::XML:
335  this.dump_xml();
336  default: begin
337  `uvm_fatal("DUMP_ERROR", $sformatf("Incorrect full_scb_type"));
338  end
339  endcase
340 endfunction: dump
341 
342 /// <b>Scoreboard API:</b> Shorthand for flushing all queues
343 function void cl_syoscb::flush_queues_all();
344  this.flush_queues();
345 endfunction: flush_queues_all
346 
347 /// <b> Scoreboard API:</b> Flushes the contents of either all queues or a specific queue.
348 /// \param queue_name The name of the queue to flush. If "" is passed, flushes all queues
349 function void cl_syoscb::flush_queues(string queue_name = "");
350  if(queue_name == "") begin
351  foreach(this.queues[i]) begin
352  this.queues[i].flush_queue();
353  end
354  end else begin
355  cl_syoscb_queue_base queue;
356 
357  // Check queue
358  if(!this.cfg.exist_queue(queue_name)) begin
359  `uvm_fatal("CFG_ERROR", $sformatf("[%s]: Queue: %0s is not found", this.cfg.get_scb_name(), queue_name));
360  end else begin
361  queue = this.cfg.get_queue(queue_name);
362  end
363 
364  // Flush the requested queue
365  queue.flush_queue();
366  end
367 endfunction: flush_queues
368 
369 /// Returns whether all queues or a specific queue is empty or not:
370 /// \param queue_name The queue that should be checked for emptiness. If "" is passed, checks all queues
371 /// \return 1 if the given queue (or all queues) are empty, 0 otherwise
372 function bit cl_syoscb::empty_queues(string queue_name = "");
373  if(queue_name == "") begin
374  bit empty_queues = 1'b1;
375 
376  foreach(this.queues[i]) begin
377  empty_queues &= this.queues[i].empty();
378  end
379 
380  return empty_queues;
381  end else begin
382  cl_syoscb_queue_base queue;
383 
384  // Check queue
385  if(!this.cfg.exist_queue(queue_name)) begin
386  `uvm_fatal("CFG_ERROR",
387  $sformatf("[%s]: Queue: %0s is not found", this.cfg.get_scb_name(), queue_name));
388  return 0;
389  end else begin
390  queue = this.cfg.get_queue(queue_name);
391  end
392 
393  return queue.empty();
394  end
395 endfunction: empty_queues
396 
397 /// Returns whether at least one element has been inserted in all queues or in a specific queue
398 /// \param queue_name The queue to check for insertions. If "" is passed, checks all queues
399 /// \return 1 if the given queue (or all queues) has had at least one insertion, 0 otherwise
400 function bit cl_syoscb::insert_queues(string queue_name = "");
401  if(queue_name == "") begin
402  bit insert_queues = 1'b1;
403 
404  foreach(this.queues[i]) begin
405  insert_queues &= (this.queues[i].get_cnt_add_item() != 0) ? 1 : 0;
406  end
407 
408  return insert_queues;
409  end
410  else begin
411  cl_syoscb_queue_base queue;
412 
413  // Check if queue exists
414  if(!this.cfg.exist_queue(queue_name)) begin
415  `uvm_fatal("CFG_ERROR",
416  $sformatf("[%s]: Queue: %0s is not found", this.cfg.get_scb_name(), queue_name));
417  return 0;
418  end
419  else begin
420  queue = this.cfg.get_queue(queue_name);
421  end
422 
423  return (queue.get_cnt_add_item() != 0) ? 1 : 0;
424  end
425 endfunction: insert_queues
426 
427 /// <b> Scoreboard API:</b> Toggles the scoreboard's comparison control.
428 /// \param cc Compare control bit. If 1, comparisons are enabled, if 0 they are disabled
429 function void cl_syoscb::compare_control(bit cc);
430  this.compare_strategy.compare_control(cc);
431 endfunction: compare_control
432 
433 /// Performs a factory override of the queue type to be used,
434 /// based on the value of the cl_syoscb_cfg#queue_type cfg. knob.
435 /// Once factory override has been performed, creates all queues in this scoreboard and forwards
436 /// the configuration object to them
437 function void cl_syoscb::override_queue_type();
438  // Override the queue type as defined in the configuration and create them
439  begin
440  string queue_names[];
441 
442  // Get the list of queue names
443  this.cfg.get_queues(queue_names);
444 
445  foreach(queue_names[i]) begin
446  // Select queue type override type based on queue_type cfg member variable
447  unique case (this.cfg.get_queue_type())
448  pk_syoscb::SYOSCB_QUEUE_STD : begin
449  cl_syoscb_queue_base::type_id::set_inst_override(cl_syoscb_queue_std::get_type(),
450  $sformatf("%s.%s",
451  this.get_full_name(),
452  queue_names[i]));
453  end
454  pk_syoscb::SYOSCB_QUEUE_MD5 : begin
455  cl_syoscb_queue_base::type_id::set_inst_override(cl_syoscb_queue_hash_md5::get_type(),
456  $sformatf("%s.%s",
457  this.get_full_name(),
458  queue_names[i]));
459  end
460  pk_syoscb::SYOSCB_QUEUE_USER_DEFINED : begin
461  `uvm_info("SCB",
462  $sformatf("queue_type for %s scb is set to USER_DEFINED. Inst overrides must be provided by user",
463  this.cfg.get_scb_name()), UVM_NONE)
464  end
465  default : begin
466  `uvm_fatal("SCB", $sformatf("Error in overriding queue_type in %s cfg",
467  this.cfg.get_scb_name()))
468  end
469  endcase
470 
471  this.queues[i] = cl_syoscb_queue_base::type_id::create(queue_names[i], this);
472  this.cfg.set_queue(queue_names[i], this.queues[i]);
473 
474  // Forward the configuration to the queue
475  uvm_config_db #(cl_syoscb_cfg)::set(this, queue_names[i], "cfg", this.cfg);
476  end
477  end
478 endfunction: override_queue_type
479 
480 /// Performs a factory override of the compare type to be used,
481 /// based on the value of this scoreboard's cl_syoscb_cfg#compare_type
483  unique case (this.cfg.get_compare_type())
484  pk_syoscb::SYOSCB_COMPARE_IO : begin
485  cl_syoscb_compare_base::type_id::set_inst_override(cl_syoscb_compare_io::get_type(),
486  $sformatf("%0s.*", this.get_full_name()));
487  end
488  pk_syoscb::SYOSCB_COMPARE_IO2HP : begin
489  cl_syoscb_compare_base::type_id::set_inst_override(cl_syoscb_compare_io_2hp::get_type(),
490  $sformatf("%0s.*", this.get_full_name()));
491  end
492  pk_syoscb::SYOSCB_COMPARE_IOP : begin
493  cl_syoscb_compare_base::type_id::set_inst_override(cl_syoscb_compare_iop::get_type(),
494  $sformatf("%0s.*", this.get_full_name()));
495  end
496  pk_syoscb::SYOSCB_COMPARE_OOO : begin
497  cl_syoscb_compare_base::type_id::set_inst_override(cl_syoscb_compare_ooo::get_type(),
498  $sformatf("%0s.*", this.get_full_name()));
499  end
500  pk_syoscb::SYOSCB_COMPARE_USER_DEFINED : begin
501  `uvm_info("SCB",
502  $sformatf("compare_type for %s scb is set to USER_DEFINED. Inst overrides must be provided by user",
503  this.cfg.get_scb_name()), UVM_NONE)
504  end
505  default : begin
506  `uvm_fatal("SCB", $sformatf("Error in overriding compare_type in %s cfg",
507  this.cfg.get_scb_name()))
508  end
509  endcase
510 endfunction: override_compare_type
511 
512 /// Validates that the current scoreboard configuration is not invalid.
513 /// If the configuration is invalid, raises a UVM_FATAL
514 /// If the configuration is not recommended but still valid, prints a UVM_INFO message
515 function void cl_syoscb::config_validation();
516  // Validation involving MD5 queue
517  if(this.cfg.get_queue_type() == pk_syoscb::SYOSCB_QUEUE_MD5) begin
518  if(this.cfg.get_compare_type() inside {pk_syoscb::SYOSCB_COMPARE_IO,
519  pk_syoscb::SYOSCB_COMPARE_IOP,
520  pk_syoscb::SYOSCB_COMPARE_IO2HP}) begin
521  if(this.cfg.get_ordered_next() == 1'b0) begin
522  `uvm_fatal("CFG_VALIDATION",
523  $sformatf("[%0s]: The 'in-order' compares are not allowed to be used when ordered next is 0",
524  this.cfg.get_scb_name()))
525  end
526  else begin
527  `uvm_info("CFG_VALIDATION",
528  $sformatf("[%0s]: The use of MD5 with 'in-order' compares and ordered_next = 1 works. However, std queue is reccomended if using 'in-order' compares.",
529  this.cfg.get_scb_name()), UVM_LOW)
530 
531  end
532  end
533  end
534 
535  // Validation involving compare IO-2HP: this compare works with 2 queues only.
536  if(this.cfg.get_compare_type() == pk_syoscb::SYOSCB_COMPARE_IO2HP) begin
537  string l_scb_names[];
538  this.cfg.get_queues(l_scb_names);
539 
540  if(l_scb_names.size() != 2) begin
541  `uvm_fatal("CFG_VALIDATION",
542  $sformatf("[%s]: The compare io-2hp only works with 2 queues. %0d secondary queues defined instead",
543  this.cfg.get_scb_name(), l_scb_names.size()));
544  end
545  end
546 endfunction: config_validation
547 
548 
549 /// <b>Scoreboard API</b>: Creates a report containing information about this scoreboard.
550 /// The report contains information about the number of insertions, matches, flushed items and orphaned items.
551 /// \param end_of_sim A bit to indicate whether this function is called at the end of simulation or not.
552 /// This changes the name used to refer to items remaining
553 /// in the queue when the function is called (orphans vs. remaining)
554 /// \return That report
555 function string cl_syoscb::create_report(bit end_of_sim = 1'b1);
556  int unsigned offset = 2;
557  int unsigned first_column_width;
558  string stats_str;
559 
560  // Enforce first column to be minimum 8 or the max of queue name and producer name+global_report_indention
561  // as producers are printed with global_report_indention indention
562  first_column_width = min_width(max(this.cfg.get_max_length_queue_name(), pk_syoscb::GLOBAL_REPORT_INDENTION+this.cfg.get_max_length_producer()));
563 
564  if(end_of_sim) begin
565  stats_str = cl_syoscb_string_library::scb_header_str("Name", offset+first_column_width, 1'b1); //Header
566  end else begin
567  stats_str = cl_syoscb_string_library::scb_header_str("Name", offset+first_column_width, 1'b1 ,
568  .col_names('{" Inserts ", " Matches ", " Flushed ", " Remain "})); //Header row
569  end
570  stats_str = { stats_str, this.create_report_contents(offset, first_column_width) }; //Data
571  stats_str = { stats_str, cl_syoscb_string_library::scb_separator_str(offset+first_column_width+1) }; //Final separator
572 
573  return stats_str;
574 endfunction: create_report
575 
576 
577 /// <b>Scoreboard API</b>: Returns a table line summarising the insert/match/flush/orphan stats over all queues in the SCB.
578 /// \param offset The x-offset to used when printing items in the first column of the table
579 /// \param first_column_width The width of the first column of the table
580 // Scoreboard name | Inserts | Matches | Flushed | Orphans
581 function string cl_syoscb::create_total_stats(int unsigned offset, int unsigned first_column_width);
582  string total_stats;
583  int unsigned total_cnt_add_item;
584  int unsigned total_cnt_flushed_item;
585  int unsigned total_queue_size;
586  string name;
587 
588  total_cnt_add_item = this.get_total_cnt_add_items();
589  total_cnt_flushed_item = this.get_total_cnt_flushed_items();
590  total_queue_size = this.get_total_queue_size();
591 
592  if(!this.cfg.get_disable_report()) begin
593  name = "Total";
594  end else begin
595  name = this.cfg.get_scb_name();
596  end
597 
598  total_stats = { "\n",
599  $sformatf("%s%s | %8d | %8d | %8d | %8d |",
600  cl_syoscb_string_library::pad_str("", offset),
601  cl_syoscb_string_library::pad_str(name, first_column_width, " ", 1'b1),
602  total_cnt_add_item,
603  total_cnt_add_item-(total_cnt_flushed_item+total_queue_size),
604  total_cnt_flushed_item,
605  total_queue_size)};
606 
607  return total_stats;
608 endfunction: create_total_stats
609 
610 /// <b>Scoreboard API</b>: Returns a string with all queue's statistics, to be inserted into the final report generated by #create_report.
611 /// \param offset The x-offset to used when printing items in the first column of the table
612 /// \param first_column_width The width of the first column of the table
613 function string cl_syoscb::create_report_contents(int unsigned offset, int unsigned first_column_width);
614  string stats_str;
615 
616  stats_str = { stats_str, this.create_queues_stats(offset, first_column_width) };
617 
618  // Add separator and totals if not wrapped by cl_syoscbs
619  if(!this.cfg.get_disable_report()) begin
620  stats_str = { stats_str, this.create_total_stats(offset, first_column_width) };
621  end
622 
623  return stats_str;
624 endfunction: create_report_contents
625 
626 /// <b>Scoreboard API:</b> Returns the number of elements that have been inserted into the scoreboard
627 function int unsigned cl_syoscb::get_total_cnt_add_items();
628  string queue_names[];
629  int unsigned total_cnt_add_item;
630 
631  this.cfg.get_queues(queue_names);
632 
633  foreach (queue_names[i]) begin
634  cl_syoscb_queue_base queue;
635 
636  queue = this.cfg.get_queue(queue_names[i]);
637  total_cnt_add_item += queue.get_cnt_add_item();
638  end
639 
640  return total_cnt_add_item;
641 endfunction: get_total_cnt_add_items
642 
643 /// <b>Scoreboard API: </b> Returns the number of elements that have been flushed out of the scoreboard
645  string queue_names[];
646  int unsigned total_cnt_flushed_item;
647 
648  this.cfg.get_queues(queue_names);
649 
650  foreach (queue_names[i]) begin
651  cl_syoscb_queue_base queue;
652 
653  queue = this.cfg.get_queue(queue_names[i]);
654  total_cnt_flushed_item += queue.get_cnt_flushed_item();
655  end
656 
657  return total_cnt_flushed_item;
658 endfunction: get_total_cnt_flushed_items
659 
660 /// <b>Scoreboard API:</b> Returns the number of elements that the scoreboard currently contains
661 function int unsigned cl_syoscb::get_total_queue_size();
662  string queue_names[];
663  int unsigned total_queue_size;
664 
665  this.cfg.get_queues(queue_names);
666 
667  foreach (queue_names[i]) begin
668  cl_syoscb_queue_base queue;
669 
670  queue = this.cfg.get_queue(queue_names[i]);
671  total_queue_size += queue.get_size();
672  end
673 
674  return total_queue_size;
675 endfunction: get_total_queue_size
676 
677 /// Returns a string with information on which checks the different queues
678 /// have failed (e.g. not empty at end of sim, no insertions).
679 /// If they are not empty it also shows the number of orphans.
681  string failed_checks;
682 
683  foreach(this.queues[i]) begin
684  failed_checks = { failed_checks, this.queues[i].get_failed_checks()};
685  end
686 
687  return failed_checks;
688 endfunction: get_queue_failed_checks
689 
690 /// <b>Scoreboard API:</b> Returns a string with information on which checks the scoreboard
691 /// has failed (e.g. any queues non-empty, any queues with no insertions)
692 /// This report also contains the per-queue information generated
693 /// by #get_queue_failed_checks
695  if(this.failed_checks.size() == 0) begin
696  return "";
697  end else begin
698  string failed_checks_str;
699 
700  // SCB errors
701  foreach(this.failed_checks[str]) begin
702  failed_checks_str = { failed_checks_str, " ", str, ": ", this.failed_checks[str], "\n"};
703  end
704 
705  // Queue errors
706  failed_checks_str = { failed_checks_str, this.get_queue_failed_checks() };
707 
708  return failed_checks_str;
709  end
710 endfunction: get_failed_checks
711 
712 
713 /// Returns a table with per-queue statistics for all queues of the scoreboard
714 /// \param offset The x-offset to used when printing items in the first column of the table
715 /// \param first_column_width The width of the first column of the table
716 function string cl_syoscb::create_queues_stats(int unsigned offset, int unsigned first_column_width);
717  // Queue name | Inserts | Matches | Flushed | Orphans
718  string queue_names[];
719  cl_syoscb_queue_base queue;
720  string queue_stats;
721 
722  this.cfg.get_queues(queue_names);
723 
724  foreach (queue_names[i]) begin
725  queue = this.cfg.get_queue(queue_names[i]);
726  queue_stats = {queue_stats, queue.create_queue_report(offset, first_column_width)} ;
727  if(!this.cfg.get_disable_report() && i == queue_names.size()-1) begin
728  queue_stats = { queue_stats, cl_syoscb_string_library::scb_separator_str(offset+first_column_width+1) };
729  end
730  end
731 
732  return queue_stats;
733  endfunction: create_queues_stats
734 
735 /// <b>Scoreboard API:</b> Returns a UVM subscriber for a given combination of queue and producer.
736 /// The returned UVM subscriber can then be connected to a UVM monitor or similar
737 /// which produces transactions which should be scoreboarded.
738 /// \param queue_name The name of the queue that items should be added to
739 /// \param producer The name of the producer that should add items to the queue
740 /// \return A handle to a uvm_subscriber that will insert items into the given queue with that producer's name
741 function cl_syoscb_subscriber cl_syoscb::get_subscriber(string queue_name, string producer);
742  if(this.subscribers.exists({queue_name, producer})) begin
743  return this.subscribers[{queue_name, producer}];
744  end else begin
745  `uvm_fatal("SUBSCRIBER_ERROR",
746  $sformatf("[%s]: Unable to get subscriber for queue: %s and producer: %s",
747  this.cfg.get_scb_name(), queue_name, producer));
748  return null;
749  end
750 endfunction: get_subscriber
751 
752 /// Dumps the shadow queue into text files.
753 /// Will either dump shadow items into one or more files depending on cl_syoscb_cfg#full_scb_dump_split
754 function void cl_syoscb::dump_txt();
755  if (this.cfg.get_full_scb_dump_split() == 1'b1) begin
756  this.dump_split_txt();
757  end else begin
758  this.dump_join_txt();
759  end
760 endfunction: dump_txt
761 
762 /// Dump the shadow queue into XML files.
763 /// Will either dump shadow items into one or more files depending on cl_syoscb_cfg#full_scb_dump_split
764 function void cl_syoscb::dump_xml();
765  if (this.cfg.get_full_scb_dump_split() == 1'b1) begin
766  this.dump_split_xml();
767  end else begin
768  this.dump_join_xml();
769  end
770 endfunction: dump_xml
771 
772 /// Dumps the shadow queue into separate text files for each queue.
773 /// The text files are named [scoreboard_name].[queue_name].[full_scb_dump_file_name].txt
775  int fd;
776  string fname;
777  string queue_names[];
778  string name;
779  string aa_name;
780 
781  this.cfg.get_queues(queue_names);
782 
783  foreach (this.queues[i]) begin
784  aa_name = {this.get_name(), ".", queue_names[i]};
785 
786  name = cl_syoscb_string_library::pad_str(queue_names[i], 40, " ", 1'b1);
787 
788  fname = {this.get_name(), ".", queue_names[i], ".", this.cfg.get_full_scb_dump_file_name(), ".txt"};
789 
790  if(!this.header_dumped.exists(aa_name)) begin
791  this.header_dumped[aa_name] = 1'b0;
792  end
793 
794  if(this.header_dumped[aa_name] == 1'b0) begin
795  fd = $fopen (fname, "w");
796  end else begin
797  fd = $fopen (fname, "a");
798  end
799 
800  if(fd) begin
801  if(this.header_dumped[aa_name] == 1'b0) begin
802  $fwrite (fd, this.print_header(name));
803  this.header_dumped[aa_name] = 1'b1;
804  end
805  this.queues[i].dump(null, fd);
806  $fclose(fd);
807  end else begin
808  `uvm_fatal("FILE_ERROR", $sformatf("The file %s could not be opened",fname));
809  end
810  end
811 endfunction: dump_split_txt
812 
813 /// Dumps the shadow queue into one combined text file called
814 /// [scoreboard_name].[full_scb_dump_file_name].txt
815 function void cl_syoscb::dump_join_txt();
816  int fd;
817  string fname;
818  string queue_names[];
819  string name;
820 
821  fname = {this.get_name(), ".", this.cfg.get_full_scb_dump_file_name(), ".txt"};
822 
823  this.cfg.get_queues(queue_names);
824 
825  fd = $fopen (fname, "w");
826 
827  if(fd) begin
828  foreach (this.queues[i]) begin
829  name = cl_syoscb_string_library::pad_str(queue_names[i], 40, " ", 1'b1);
830  $fwrite (fd, this.print_header(name));
831  this.queues[i].dump(null, fd);
832  end
833  end else begin
834  `uvm_fatal("FILE_ERROR", $sformatf("The file %s could not be opened",fname));
835  end
836  $fclose(fd);
837 endfunction: dump_join_txt
838 
839 /// Dumps the shadow queue into separate XML files for each queue.
840 /// The files are named [scoreboard_name].[queue_name].[full_scb_dump_file_name].xml
842  int fd;
843  string fname;
844  string queue_names[];
845  string name;
846  string aa_name;
847 
848  this.cfg.get_queues(queue_names);
849 
850  foreach (this.queues[i]) begin
851  aa_name = {this.get_name(), ".", queue_names[i]};
852 
853  name = cl_syoscb_string_library::pad_str(queue_names[i], 40, " ", 1'b1);
854 
855  fname = {this.get_name(), ".", queue_names[i], ".", this.cfg.get_full_scb_dump_file_name(), ".xml"};
856 
857  if(!this.header_dumped.exists(aa_name)) begin
858  this.header_dumped[aa_name] = 1'b0;
859  end
860 
861  if(this.header_dumped[aa_name] == 1'b0) begin
862  fd = $fopen (fname, "w");
863  end else begin
864  fd = $fopen (fname, "a");
865  end
866 
867  if(fd) begin
868  if(this.header_dumped[aa_name] == 1'b0) begin
869  $fwrite (fd, "<?xml version='1.0' encoding='UTF-8'?>\n");
870  $fwrite (fd, $sformatf("<scb name='%s'>\n", this.get_name()));
871  $fwrite (fd, "<queues>\n");
872  $fwrite (fd, this.print_header(name));
873  this.header_dumped[aa_name] = 1'b1;
874  $fwrite (fd, $sformatf("<queue name='%s'>\n", queue_names[i]));
875  $fwrite (fd, "<items>\n");
876  end
877  this.queues[i].dump(null, fd);
878  $fwrite (fd, "</items>\n");
879  $fwrite (fd, "</queue>\n");
880  $fwrite (fd, "</queues>\n");
881  $fwrite (fd, "</scb>");
882  $fclose (fd);
883  end else begin
884  `uvm_fatal("FILE_ERROR", $sformatf("The file %s could not be opened",fname));
885  end
886  end
887 endfunction: dump_split_xml
888 
889 /// Dumps the shadow queue into one combined XML file called
890 /// [scoreboard_name].[full_scb_dump_file_name].xml
891 function void cl_syoscb::dump_join_xml();
892  int fd;
893  string fname;
894  string queue_names[];
895  string name;
896  string xsd_fname;
897 
898  fname = {this.get_name(), ".", this.cfg.get_full_scb_dump_file_name(), ".xml"};
899 
900  this.cfg.get_queues(queue_names);
901 
902  fd = $fopen (fname, "w");
903 
904  if(fd) begin
905  $fwrite (fd, $sformatf("<?xml version='1.0' encoding='UTF-8'?>\n<scb name='%s'>\n", this.get_name()));
906  $fwrite (fd, "<queues>\n");
907 
908  foreach (this.queues[i]) begin
909  $fwrite (fd, $sformatf("<queue name='%s'>\n", queue_names[i]));
910  $fwrite (fd, "<items>\n");
911  this.queues[i].dump(null, fd);
912  $fwrite (fd, "</items>\n");
913  $fwrite (fd, "</queue>\n");
914  end
915 
916  $fwrite (fd, "</queues>\n");
917  $fwrite (fd, "</scb>");
918  $fclose(fd);
919  end else begin
920  `uvm_fatal("FILE_ERROR", $sformatf("The file %s could not be opened",fname));
921  end
922 endfunction: dump_join_xml
923 
924 
925 /// Prints the current queue statistics for a queue.
926 /// This can be used to get queue statistics throughout simulation.
927 /// \param queue_name The name of the queue to dump statistics for.
928 function void cl_syoscb::intermediate_queue_stat_dump(string queue_name);
929  int unsigned first_column_width;
930  string stats_str;
931  int unsigned offset = 2;
932  cl_syoscb_queue_base queue;
933 
934  if(!this.cfg.exist_queue(queue_name)) begin
935  `uvm_fatal("CFG_ERROR", $sformatf("[%s]: Queue %0s was not found", this.cfg.get_scb_name(), queue_name))
936  end
937  queue = this.cfg.get_queue(queue_name);
938 
939  first_column_width = min_width(max(this.cfg.get_max_length_queue_name(), pk_syoscb::GLOBAL_REPORT_INDENTION+this.cfg.get_max_length_producer()));
940  stats_str = cl_syoscb_string_library::scb_header_str("Name", offset+first_column_width, 1'b1 ,
941  .col_names('{" Inserts ", " Matches ", " Flushed ", " Remain "})); //Header row
942  stats_str = { stats_str, queue.create_queue_report(offset, first_column_width) }; //Data
943  stats_str = { stats_str, cl_syoscb_string_library::scb_separator_str(offset+first_column_width+1) }; //Final separator str
944 
945  `uvm_info("QUEUE_STAT", $sformatf("[%s] %0d items added to %s, intermediate statistics summary:%s",
946  this.get_name(),
947  queue.get_cnt_add_item(),
948  queue_name,
949  stats_str),
950  UVM_LOW)
951 endfunction: intermediate_queue_stat_dump
952 
953 /// UVM pre_abort hook. Ensures that all shadow items are dumped if a
954 /// UVM_ERROR is about to stop simulation
955 function void cl_syoscb::pre_abort();
956  if(this.cfg.get_full_scb_dump()) begin
957  this.dump();
958  end
959 endfunction: pre_abort
960 
961 /// Gets a header string to print into a shadow queue dump file
962 /// \param queue_name The header for that queue
963 function string cl_syoscb::print_header(string queue_name);
964  case (this.cfg.get_full_scb_dump_type())
965  pk_syoscb::TXT:
966  return $sformatf({"/////////////////////////////////////////////////////\n",
967  "// Queue: %s //\n",
968  "/////////////////////////////////////////////////////\n"},queue_name);
969  pk_syoscb::XML:
970  return $sformatf({"<!--/////////////////////////////////////////////////\n",
971  "// Queue: %s //\n",
972  "//////////////////////////////////////////////////-->\n"},queue_name);
973  endcase
974 endfunction: print_header
static string scb_separator_str(int unsigned pre_length)
Creates a new separator string for scoreboard stat tables.
virtual void dump_split_txt()
Dumps the shadow queue into separate text files for each queue.
Definition: cl_syoscb.svh:774
virtual void config_validation()
Validates that the current scoreboard configuration is not invalid.
Definition: cl_syoscb.svh:515
virtual string get_failed_checks()
Scoreboard API: Returns a string with information on which checks the scoreboard has failed (e...
Definition: cl_syoscb.svh:694
virtual bit empty_queues(string queue_name="")
Returns whether all queues or a specific queue is empty or not:
Definition: cl_syoscb.svh:372
virtual int unsigned get_total_cnt_flushed_items()
Scoreboard API: Returns the number of elements that have been flushed out of the scoreboard ...
Definition: cl_syoscb.svh:644
virtual string create_report(bit end_of_sim=0b1)
Scoreboard API: Creates a report containing information about this scoreboard.
Definition: cl_syoscb.svh:555
The UVM scoreboard item which wraps uvm_sequence_item .
MD5 implementation of a hash queue which optimizes the OOO compare.
virtual void flush_queues_all()
Scoreboard API: Shorthand for flushing all queues
Definition: cl_syoscb.svh:343
virtual string create_report_contents(int unsigned offset, int unsigned first_column_width)
Scoreboard API: Returns a string with all queue&#39;s statistics, to be inserted into the final report ge...
Definition: cl_syoscb.svh:613
void build_phase(uvm_phase phase)
UVM build phase.
Definition: cl_syoscb.svh:112
virtual int unsigned get_total_queue_size()
Scoreboard API: Returns the number of elements that the scoreboard currently contains ...
Definition: cl_syoscb.svh:661
cl_syoscb_cfg cfg
Handle to the global UVM scoreboard configuration.
Definition: cl_syoscb.svh:7
virtual void dump_join_xml()
Dumps the shadow queue into one combined XML file called [scoreboard_name].
Definition: cl_syoscb.svh:891
Top level class implementing the root of the SyoSil UVM scoreboard.
Definition: cl_syoscb.svh:2
virtual string get_queue_failed_checks()
Returns a string with information on which checks the different queues have failed (e...
Definition: cl_syoscb.svh:680
virtual int unsigned get_total_cnt_add_items()
Scoreboard API: Returns the number of elements that have been inserted into the scoreboard ...
Definition: cl_syoscb.svh:627
cl_syoscb_subscriber subscribers[string]
Associative array holding a uvm_subscriber for each queue.
Definition: cl_syoscb.svh:16
virtual void override_queue_type()
Performs a factory override of the queue type to be used, based on the value of the cl_syoscb_cfg::qu...
Definition: cl_syoscb.svh:437
virtual void add_item(string queue_name, string producer, uvm_sequence_item item)
Scoreboard API: Adds a uvm_sequence_item to a given queue for a given producer.
Definition: cl_syoscb.svh:237
cl_syoscb_queue_base queues[]
Array holding handles to all queues.
Definition: cl_syoscb.svh:10
semaphore add_item_mutex
Mutex to be used when calls to add_item should be mutexed.
Definition: cl_syoscb.svh:25
string failed_checks[string]
AA containing failed scoreboard check (e.g. no items inserted))
Definition: cl_syoscb.svh:22
virtual void dump()
Scoreboard API: Dump items to files if cl_syoscb_cfg::full_scb_dump is enabled
Definition: cl_syoscb.svh:330
virtual task add_item_mutexed(string queue_name, string producer, uvm_sequence_item item)
Scoreboard API: Add an item to the scoreboard, using a mutex to ensure than no more than one item is...
Definition: cl_syoscb.svh:314
void final_phase(uvm_phase phase)
UVM final phase. Prints in the file called dump.txt the information about the shadow queue of all the...
Definition: cl_syoscb.svh:220
virtual int unsigned get_cnt_add_item()
Queue API: Returns the number of items that have been inserted in this queue
virtual string create_queues_stats(int unsigned offset, int unsigned first_column_width)
Returns a table with per-queue statistics for all queues of the scoreboard.
Definition: cl_syoscb.svh:716
virtual string create_total_stats(int unsigned offset, int unsigned first_column_width)
Scoreboard API: Returns a table line summarising the insert/match/flush/orphan stats over all queues ...
Definition: cl_syoscb.svh:581
virtual void pre_abort()
UVM pre_abort hook.
Definition: cl_syoscb.svh:955
virtual string create_queue_report(int unsigned offset, int unsigned first_column_width)
Queue API: Returns a string with overall queues statistics.
virtual void dump_join_txt()
Dumps the shadow queue into one combined text file called [scoreboard_name].
Definition: cl_syoscb.svh:815
Generic subscriber for the scoreboard.
virtual bit insert_queues(string queue_name="")
Returns whether at least one element has been inserted in all queues or in a specific queue...
Definition: cl_syoscb.svh:400
static string pad_str(string str, int unsigned max_length, string expand=" ", bit side=0b0)
Pads the input string with another string until it reaches a given length.
Class which represents the base concept of a queue.
Component which instantiates the chosen comparison algorithm.
void end_of_elaboration_phase(uvm_phase phase)
UVM end of elaboration phase.
Definition: cl_syoscb.svh:174
virtual int unsigned get_cnt_flushed_item()
Queue API: Returns the total number of elements flushed from this queue.
void check_phase(uvm_phase phase)
UVM check phase.
Definition: cl_syoscb.svh:182
Utility class for capturing the queue names associated with a producer.
Standard implementation of a queue.
virtual void compare_control(bit cc)
Scoreboard API: Toggles the scoreboard&#39;s comparison control.
Definition: cl_syoscb.svh:429
virtual void dump_split_xml()
Dumps the shadow queue into separate XML files for each queue.
Definition: cl_syoscb.svh:841
virtual void override_compare_type()
Performs a factory override of the compare type to be used, based on the value of this scoreboard&#39;s c...
Definition: cl_syoscb.svh:482
virtual cl_syoscb_cfg get_cfg()
Gets the configuration for this scoreboard.
Definition: cl_syoscb.svh:227
bit header_dumped[string]
Flag indicating if a scoreboard header has been dumped when dumping shadow queues.
Definition: cl_syoscb.svh:19
virtual void intermediate_queue_stat_dump(string queue_name)
Prints the current queue statistics for a queue.
Definition: cl_syoscb.svh:928
virtual void dump_txt()
Dumps the shadow queue into text files.
Definition: cl_syoscb.svh:754
Configuration class for the SyoSil UVM scoreboard.
void report_phase(uvm_phase phase)
UVM report phase. Prints the status of the scoreboard instance.
Definition: cl_syoscb.svh:195
virtual void compare_trigger(string queue_name="", cl_syoscb_item item=null)
Scoreboard API: Invokes the scoreboard&#39;s compare strategy
Definition: cl_syoscb.svh:325
virtual string print_header(string queue_name)
Gets a header string to print into a shadow queue dump file.
Definition: cl_syoscb.svh:963
virtual void flush_queues(string queue_name="")
Scoreboard API: Flushes the contents of either all queues or a specific queue.
Definition: cl_syoscb.svh:349
virtual void dump_xml()
Dump the shadow queue into XML files.
Definition: cl_syoscb.svh:764
cl_syoscb_compare compare_strategy
Handle to the compare strategy.
Definition: cl_syoscb.svh:13
virtual int unsigned get_size()
Queue API: Returns the current size of the queue.
virtual cl_syoscb_subscriber get_subscriber(string queue_name, string producer)
Scoreboard API: Returns a UVM subscriber for a given combination of queue and producer.
Definition: cl_syoscb.svh:741
static string scb_header_str(string hn, int unsigned pre_length, bit side, string col_names[]=(" Inserts ", " Matches ", " Flushed ", " Orphans "))
Creates a new header string for a scoreboard stat table.

Project: SyoSil ApS UVM Scoreboard, Revision: 1.0.3.0

Copyright 2014-2022 SyoSil ApS
All Rights Reserved Worldwide

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
doxygen
Doxygen Version: 1.8.14
Generated with IDV SV Filter Version: 2.6.3
Fri Sep 2 2022 14:38:53
Find a documentation bug? Report bugs to: scoreboard@syosil.com