SyoSil ApS UVM Scoreboard  1.0.3.0
uvm_xml_printer.svh
1 /// An XML printer for cl_syoscb_items
2 class uvm_xml_printer extends uvm_printer;
3  //-------------------------------------
4  // Non randomizable variables
5  //-------------------------------------
6  int unsigned indent_level;
7  local string spaces = " ";
8 
9  //-------------------------------------
10  // Constructor
11  //-------------------------------------
12  function new();
13  super.new();
14  endfunction: new
15 
16  //-------------------------------------
17  // Functions
18  //-------------------------------------
19  //uvm_printer functions
20  extern virtual function string emit();
21 
22  //Helper functions for formatting data
23  `ifdef UVM_VERSION // UVM-IEEE version
24  extern virtual function string format_syoscb_item(uvm_printer_element element);
25  extern virtual function string format_primitive(uvm_printer_element element);
26  extern virtual function string format_object(uvm_printer_element element);
27  extern virtual function string format_array(uvm_printer_element element);
28 
29  extern virtual function bit is_primitive(uvm_printer_element element);
30  extern virtual function bit is_object(uvm_printer_element element);
31  extern virtual function bit is_array(uvm_printer_element element);
32  `else
33  extern virtual function string format_syoscb_item(int unsigned idx);
34  extern virtual function int unsigned format_object(int unsigned idx, ref string result);
35  extern virtual function int unsigned format_primitive(int unsigned idx, ref string result);
36  extern virtual function int unsigned format_array(int unsigned idx, ref string result);
37 
38  extern virtual function bit is_primitive(uvm_printer_row_info row);
39  extern virtual function bit is_object(uvm_printer_row_info row);
40  extern virtual function bit is_array(uvm_printer_row_info row);
41  `endif
42 
43  //Internal helper functions
44  extern virtual function void increase_indent(int unsigned steps = 1);
45  extern virtual function void decrease_indent(int unsigned steps = 1);
46  extern virtual function string get_indent();
47 
48 endclass: uvm_xml_printer
49 
50 // BEGIN UVM-IEEE IMPLEMENTATATION
51 `ifdef UVM_VERSION
52 function string uvm_xml_printer::emit();
53  string result;
54  indent_level = 0;
55 
56  result = this.format_syoscb_item(this.get_bottom_element());
57 
58  return result;
59 endfunction: emit
60 
61 /// Formats a cl_syoscb_item and all of its children.
62 /// \param element The element representing the cl_syoscb_item
63 /// \return The XML formatted string of this cl_syoscb_item
64 function string uvm_xml_printer::format_syoscb_item(uvm_printer_element element);
65  string result, producer, queue_index, insertion_index, inst;
66  uvm_printer_element children[$];
67  static uvm_printer_element_proxy proxy = new("proxy");
68 
69  proxy.get_immediate_children(element, children);
70 
71  //Perform preliminary error checks to ensure that the uvm_xml_printer is being invoked on a cl_syoscb_item
72  if (element.get_element_type_name() != "cl_syoscb_item") begin
73  `uvm_warning("XML_PRINT", $sformatf({"The uvm_xml_printer is only meant to be invoked on items of type cl_syoscb_item. ",
74  "This item has type %s. Formatting as a uvm_sequence_item instead. This breaks the built-in XML transformations."}, element.get_element_type_name()))
75  return this.format_object(element);
76  end else if (children[0].get_element_name() != "insertion_index" ||
77  children[1].get_element_name() != "queue_index" ||
78  children[2].get_element_name() != "producer") begin
79  `uvm_warning("XML_PRINT", $sformatf({"cl_syoscb_item metadata fields must be in the order [insertion_index, queue_index, producer]. ",
80  "This item had order [%s, %s, %s]"}, children[0].get_element_type_name(), children[1].get_element_type_name(), children[2].get_element_type_name()))
81  return "";
82  end
83 
84  inst = element.get_element_name();
85  insertion_index = children[0].get_element_value();
86  queue_index = children[1].get_element_value();
87  producer = children[2].get_element_value();
88 
89  result = $sformatf("<item inst=\"%s\" producer=\"%s\" queue_index=\"%s\" insertion_index=\"%s\">\n",
90  inst,
91  producer,
92  queue_index,
93  insertion_index.substr(2, insertion_index.len()-1)); //Using substr[2..len-1] to strip out leading 'd
94 
95  this.increase_indent();
96  result = {result, this.format_object(children[3])};
97  this.decrease_indent();
98  result = {result, "</item>\n"};
99 
100  return result;
101 endfunction: format_syoscb_item
102 
103 /// Formats a sequence item/object, and recursively formats all children of this seq item
104 /// \param element The element being formatted
105 /// \return The formatted string for this object and all of its children
106 function string uvm_xml_printer::format_object(uvm_printer_element element);
107  string result;
108  uvm_printer_element children[$];
109  static uvm_printer_element_proxy proxy = new("proxy");
110 
111  proxy.get_immediate_children(element, children);
112 
113  result = $sformatf("%s<member_object name=\"%s\" type=\"%s\">\n",
114  this.get_indent(),
115  element.get_element_name(),
116  element.get_element_type_name());
117 
118  if(element.get_element_value() == "<null>") begin
119  this.increase_indent();
120  result = {result, $sformatf("%s<null/>\n", this.get_indent())};
121  this.decrease_indent();
122  result = {result, $sformatf("%s</member_object>\n", this.get_indent())};
123  return result;
124  end
125 
126  this.increase_indent();
127  result = {result, $sformatf("%s<members>\n", this.get_indent())};
128  this.increase_indent();
129 
130  foreach(children[i]) begin
131  if(is_primitive(children[i])) begin
132  result = {result, this.format_primitive(children[i])};
133  end else if (is_object(children[i])) begin
134  result = {result, this.format_object(children[i])};
135  end else if (is_array(children[i])) begin
136  result = {result, this.format_array(children[i])};
137  end else begin //It's most likely an enum if this is the case, can be formatted as a primitive
138  result = {result, this.format_primitive(children[i])};
139  end
140  end
141 
142  this.decrease_indent();
143  result = {result, $sformatf("%s</members>\n", this.get_indent())};
144  this.decrease_indent();
145  result = {result, $sformatf("%s</member_object>\n", this.get_indent())};
146 
147  return result;
148 endfunction: format_object
149 
150 /// Formats an array and all of its children
151 /// \param element The element representing the array to format
152 /// \return The formatted string for this array and all children
153 function string uvm_xml_printer::format_array(uvm_printer_element element);
154  string result, member_array;
155  uvm_printer_element children[$];
156  static uvm_printer_element_proxy proxy = new("proxy");
157 
158  proxy.get_immediate_children(element, children);
159 
160  result = $sformatf("%s<member_array name=\"%s\" type=\"%s\" size=\"%s\">\n", this.get_indent(), element.get_element_name(), element.get_element_type_name(), element.get_element_size());
161 
162  if(element.get_element_size() == "0") begin
163  result = {result, $sformatf("%s</member_array>\n", this.get_indent())};
164  return result;
165  end
166 
167  this.increase_indent();
168  result = {result, $sformatf("%s<values>\n", this.get_indent())};
169  this.increase_indent();
170 
171  foreach(children[i]) begin
172  result = {result, $sformatf("%s<value>\n", this.get_indent())};
173  this.increase_indent();
174  if(is_primitive(children[i])) begin
175  result = {result, this.format_primitive(children[i])};
176  end else if (is_object(children[i])) begin
177  result = {result, this.format_object(children[i])};
178  end else if (is_array(children[i])) begin
179  result = {result, this.format_array(children[i])};
180  end else begin //It's most likely an enum if this is the case, can be formatted as a primitive
181  result = {result, this.format_primitive(children[i])};
182  end
183  this.decrease_indent();
184  result = {result, $sformatf("%s</value>\n", this.get_indent())};
185  end
186 
187  this.decrease_indent();
188  result = {result, $sformatf("%s</values>\n", this.get_indent())};
189  this.decrease_indent();
190  result = {result, $sformatf("%s</member_array>\n", this.get_indent())};
191 
192  return result;
193 endfunction: format_array
194 
195 /// Formats a primitive value
196 /// \param element The element being formatted
197 /// \return That element formatted as XML
198 function string uvm_xml_printer::format_primitive(uvm_printer_element element);
199  return $sformatf("%s<member name=\"%s\" type=\"%s\" size=\"%s\">%s</member>\n",
200  this.get_indent(),
201  element.get_element_name(),
202  element.get_element_type_name(),
203  element.get_element_size(),
204  element.get_element_value());
205 
206 endfunction: format_primitive
207 
208 /// Checks whether an element is a SystemVerilog primitive.
209 /// Here, a "primitive" is one that maps to the UVM printer representations: integral, real, string
210 /// \param element The element to check against
211 /// \return 1'b1 if the current element is a primitive, 1'b0 otherwise
212 function bit uvm_xml_printer::is_primitive(uvm_printer_element element);
213  string type_name;
214  type_name = element.get_element_type_name();
215 
216  return (type_name == "integral") || (type_name == "real") || (type_name == "string");
217 endfunction: is_primitive
218 
219 /// Checks whether an element is an array
220 /// Arrays are recognized as dynamic, associative or static arrays.
221 /// The UVM printer interprets queues as dynamic arrays
222 /// \param element The element to check against
223 /// \return 1 if the current element is an array, 0 otherwise
224 function bit uvm_xml_printer::is_array(uvm_printer_element element);
225  //If type name start with 'da(', 'sa(' or 'aa(' and ends with ')', it's most likely an array
226  //If value is also "-", then it must be an array
227  string type_name, val;
228  type_name = element.get_element_type_name();
229  val = element.get_element_value();
230 
231  return (type_name.substr(0,2) == "da(" || type_name.substr(0,2) == "aa(" || type_name.substr(0,2) == "sa(") &&
232  type_name[type_name.len()-1] == ")" && val[0] == "-";
233 endfunction: is_array
234 
235 /// Checks whether an element is an object.
236 /// \param element The element to check against
237 /// \return 1 if the current element is an object, 0 otherwise
238 function bit uvm_xml_printer::is_object(uvm_printer_element element);
239  //It is an object if size is "-" and value starts with "@", or if it is null
240  string size, val;
241  size = element.get_element_size();
242  val = element.get_element_value();
243 
244  return size == "-" && (val[0] == "@" || val == "<null>");
245 endfunction: is_object
246 
247 
248 `else //BEGIN UVM-NON-IEEE IMPLEMENTATION
249 
250 function string uvm_xml_printer::emit();
251  string result;
252  indent_level = 0;
253 
254  result = this.format_syoscb_item(0);
255  m_rows.delete();
256  return result;
257 endfunction: emit
258 
259 /// Formats a cl_syoscb_item and all of its children. It is assumed
260 /// that the cl_syoscb_item is at position m_rows[idx]
261 /// \param idx The id at which this cl_syoscb_item is placed (should always be 0)
262 /// \return The XML formatted string
263 function string uvm_xml_printer::format_syoscb_item(int unsigned idx);
264  string result, producer, queue_index, insertion_index, inst;
265 
266  //Perform preliminary error checks to ensure that the uvm_xml_printer is being invoked on a correctly formatted cl_syoscb_item
267  if(m_rows[idx].type_name != "cl_syoscb_item") begin
268  `uvm_warning("XML_PRINT", $sformatf({"The uvm_xml_printer is only meant to be invoked on items of type cl_syoscb_item. ",
269  "This item has type %s. Formatting as a uvm_sequence_item instead. This breaks the built-in XML transformations."}, m_rows[idx].type_name))
270  void'(this.format_object(idx, result));
271  return result;
272  end else if(m_rows[idx+1].name != "insertion_index" ||
273  m_rows[idx+2].name != "queue_index" ||
274  m_rows[idx+3].name != "producer") begin
275  `uvm_warning("XML_PRINT", $sformatf({"cl_syoscb_item metadata fields must be in the order [insertion_index, queue_index, producer]. ",
276  "This item had order [%s, %s, %s]"}, m_rows[idx+1].name, m_rows[idx+2].name, m_rows[idx+3].name))
277  return "";
278  end
279 
280  inst = m_rows[idx].name;
281  insertion_index = m_rows[idx+1].val;
282  queue_index = m_rows[idx+2].val;
283  producer = m_rows[idx+3].val;
284  //At idx+4 is the start of our member_object. This is always the case
285 
286  result = $sformatf("<item inst=\"%s\" producer=\"%s\" queue_index=\"%s\" insertion_index=\"%s\">\n",
287  inst,
288  producer,
289  queue_index,
290  insertion_index.substr(2, insertion_index.len()-1)); //Using substr[2..len-1] to strip out leading 'd
291 
292  this.increase_indent();
293  void'(this.format_object(idx+4, result));
294  this.decrease_indent();
295 
296  result = {result, "</item>\n"};
297 
298  return result;
299 endfunction: format_syoscb_item
300 
301 /// Formats a sequence item/object, and recursively formats all children of this seq item
302 /// \param idx The position in m_rows where this sequence item is located
303 /// \param result The result string being built
304 function int unsigned uvm_xml_printer::format_object(int unsigned idx, ref string result);
305  string member_object;
306  uvm_printer_row_info row, child;
307 
308  row = m_rows[idx];
309  member_object = $sformatf("%s<member_object name=\"%s\" type=\"%s\">\n", this.get_indent(), row.name, row.type_name);
310  result = {result, member_object};
311 
312  if(row.val == "<null>") begin
313  this.increase_indent();
314  result = {result, $sformatf("%s<null/>\n", this.get_indent())};
315  this.decrease_indent();
316  result = {result, $sformatf("%s</member_object>\n", this.get_indent())};
317  return idx + 1;
318  end
319 
320  this.increase_indent();
321  result = {result, $sformatf("%s<members>\n", this.get_indent())};
322  this.increase_indent();
323 
324  //Parse all children.
325  idx = idx+1;
326  while(m_rows[idx].level > row.level && idx < m_rows.size()) begin
327  child = m_rows[idx];
328  if(is_primitive(child)) begin
329  idx = this.format_primitive(idx, result);
330  end else if (is_object(child)) begin
331  idx = this.format_object(idx, result);
332  end else if (is_array(child)) begin
333  idx = this.format_array(idx, result);
334  end else begin //It's most likely an enum if this is the case, can be formatted as a primitive
335  idx = this.format_primitive(idx, result);
336  end
337  end
338 
339  this.decrease_indent();
340  result = {result, $sformatf("%s</members>\n", this.get_indent())};
341  this.decrease_indent();
342  result = {result, $sformatf("%s</member_object>\n", this.get_indent())};
343 
344  return idx;
345 endfunction: format_object
346 
347 /// Formats an array and all of its children
348 /// \param idx The position in m_rows where the array is located
349 /// \param result The result string being built
350 function int unsigned uvm_xml_printer::format_array(int unsigned idx, ref string result);
351  string member_array;
352  uvm_printer_row_info row, child;
353 
354  row = m_rows[idx];
355  member_array = $sformatf("%s<member_array name=\"%s\" type=\"%s\" size=\"%s\">\n", this.get_indent(), row.name, row.type_name, row.size);
356  result = {result, member_array};
357 
358  if(row.size == "0") begin
359  result = {result, $sformatf("%s</member_array>\n", this.get_indent())};
360  return idx+1;
361  end
362 
363  this.increase_indent();
364  result = {result, $sformatf("%s<values>\n", this.get_indent())};
365  this.increase_indent();
366 
367  idx = idx+1;
368  child = m_rows[idx]; //Type of all children is the same, only need to access child once
369  while(m_rows[idx].level > row.level && idx < m_rows.size()) begin
370  result = {result, $sformatf("%s<value>\n", this.get_indent())};
371  this.increase_indent();
372  if(is_primitive(child)) begin
373  idx = this.format_primitive(idx, result);
374  end else if (is_object(child)) begin
375  idx = this.format_object(idx, result);
376  end else if (is_array(child)) begin
377  idx = this.format_array(idx, result);
378  end else begin //It's most likely an enum if this is the case, can be formatted as a primitive
379  idx = this.format_primitive(idx, result);
380  end
381  this.decrease_indent();
382  result = {result, $sformatf("%s</value>\n", this.get_indent())};
383  end
384 
385  this.decrease_indent();
386  result = {result, $sformatf("%s</values>\n", this.get_indent())};
387  this.decrease_indent();
388  result = {result, $sformatf("%s</member_array>\n", this.get_indent())};
389 
390  return idx;
391 endfunction: format_array
392 
393 /// Formats a primitive value
394 /// \param idx The position in m_rows where the primitive is located
395 /// \param result The result being built
396 function int unsigned uvm_xml_printer::format_primitive(int unsigned idx, ref string result);
397  uvm_printer_row_info row;
398 
399  row = m_rows[idx];
400  result = {result, $sformatf("%s<member name=\"%s\" type=\"%s\" size=\"%s\">%s</member>\n", this.get_indent(), row.name, row.type_name, row.size, row.val)};
401  return idx+1;
402 endfunction: format_primitive
403 
404 
405 /// Checks whether an element is a SystemVerilog primitive.
406 /// Here, a "primitive" is one that maps to the UVM printer representations: integral, real, string
407 /// \param type_name The type name field of the currently parsed element
408 /// \return 1 if the current element is a primitive, 0 otherwise
409 function bit uvm_xml_printer::is_primitive(uvm_printer_row_info row);
410  string type_name;
411  type_name = row.type_name;
412 
413  return (type_name == "integral") || (type_name == "real") || (type_name == "string");
414 endfunction: is_primitive
415 
416 /// Checks whether an element is an array
417 /// Arrays are recognized as dynamic, associative or static arrays.
418 /// The UVM printer interprets queues as dynamic arrays
419 /// \param type_name The type name field of the currently parsed element
420 /// \param value The value field of the currently parsed element
421 /// \return 1'b1 if the current element is an array, 1'b0 otherwise
422 function bit uvm_xml_printer::is_array(uvm_printer_row_info row);
423  //If type name start with 'da(', 'sa(' or 'aa(' and ends with ')', it's most likely an array
424  //If value is "-", then it must be an array
425  string type_name, val;
426  type_name = row.type_name;
427  val = row.val;
428 
429  return (type_name.substr(0,2) == "da(" || type_name.substr(0,2) == "aa(" || type_name.substr(0,2) == "sa(") &&
430  type_name[type_name.len()-1] == ")" && val[0] == "-";
431 endfunction: is_array
432 
433 /// Checks whether an element is an object.
434 /// \param size The size field of the currently parsed element.
435 /// \param val The value field of the currently parsed element
436 /// \return 1 if the current element is an object, 0 otherwise
437 function bit uvm_xml_printer::is_object(uvm_printer_row_info row);
438  //It is an object if size is "-" and value starts with "@"
439  string size, val;
440  size = row.size;
441  val = row.val;
442 
443  return size == "-" && (val[0] == "@" || val == "<null>");
444 endfunction: is_object
445 
446 
447 `endif
448 
449 /// Increases the indentation used by a set amount of steps
450 /// The size of each step is controlled by knobs.indent
451 function void uvm_xml_printer::increase_indent(int unsigned steps = 1);
452  `ifdef UVM_VERSION
453  this.indent_level += this.get_knobs().indent*steps;
454  `else
455  this.indent_level += this.knobs.indent*steps;
456  `endif
457 endfunction: increase_indent
458 
459 /// Decreases the indentation used by a set amount of steps
460 /// The size of each step is controlled by knobs.indent
461 function void uvm_xml_printer::decrease_indent(int unsigned steps = 1);
462  `ifdef UVM_VERSION
463  this.indent_level -= this.get_knobs().indent*steps;
464  `else
465  this.indent_level -= this.knobs.indent*steps;
466  `endif
467  if(this.indent_level < 0) begin
468  this.indent_level = 0;
469  end
470 endfunction: decrease_indent
471 
472 /// Gets an indentation string consisting of this.indent_level spaces
473 function string uvm_xml_printer::get_indent();
474  return this.spaces.substr(0, indent_level-1);
475 endfunction: get_indent
virtual void increase_indent(int unsigned steps=1)
Increases the indentation used by a set amount of steps The size of each step is controlled by knobs...
Definition: pk_syoscb.sv:452
virtual void decrease_indent(int unsigned steps=1)
Decreases the indentation used by a set amount of steps The size of each step is controlled by knobs...
Definition: pk_syoscb.sv:462
An XML printer for cl_syoscb_items.
virtual int unsigned format_primitive(int unsigned idx, ref string result)
Formats a primitive value.
Definition: pk_syoscb.sv:397
virtual int unsigned format_object(int unsigned idx, ref string result)
Formats a sequence item/object, and recursively formats all children of this seq item.
Definition: pk_syoscb.sv:305
virtual string format_syoscb_item(int unsigned idx)
Formats a cl_syoscb_item and all of its children.
virtual bit is_primitive(uvm_printer_row_info row)
Checks whether an element is a SystemVerilog primitive.
Definition: pk_syoscb.sv:410
virtual bit is_array(uvm_printer_row_info row)
Checks whether an element is an array Arrays are recognized as dynamic, associative or static arrays...
Definition: pk_syoscb.sv:423
virtual int unsigned format_array(int unsigned idx, ref string result)
Formats an array and all of its children.
Definition: pk_syoscb.sv:351
virtual string get_indent()
Gets an indentation string consisting of this.indent_level spaces.
Definition: pk_syoscb.sv:474
virtual bit is_object(uvm_printer_row_info row)
Checks whether an element is an object.
Definition: pk_syoscb.sv:438

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:40:35
Find a documentation bug? Report bugs to: scoreboard@syosil.com