VMM  1.2.2b
vmm_data.sv
Go to the documentation of this file.
1 //
2 // -------------------------------------------------------------
3 // Copyright 2004-2009 Synopsys, Inc.
4 // All Rights Reserved Worldwide
5 //
6 // Licensed under the Apache License, Version 2.0 (the
7 // "License"); you may not use this file except in
8 // compliance with the License. You may obtain a copy of
9 // the License at
10 //
11 // http://www.apache.org/licenses/LICENSE-2.0
12 //
13 // Unless required by applicable law or agreed to in
14 // writing, software distributed under the License is
15 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
16 // CONDITIONS OF ANY KIND, either express or implied. See
17 // the License for the specific language governing
18 // permissions and limitations under the License.
19 // -------------------------------------------------------------
20 //
21 
22 
23 // ////////////////////////////////////////////
24 // Class: vmm_data
25 //
26 // A base class for modeling transactions.
27 //
28 // Function: new
29 //
30 // Creates a new instance of this data model or transaction descriptor, with the specified
31 // message service interface. The specified message service interface is used when constructing
32 // the notify property.
33 //
34 //|
35 //| Because of the potentially large number of instances of data objects, a class-static message service interface should be used to minimize memory usage and to control class-generic messages:
36 //| class eth_frame extends vmm_data {
37 //| static vmm_log log = new(“eth_frame”, “class”);
38 //| function new();
39 //| super.new(this.log);
40 //| ...
41 //| endfunction
42 //| endclass: eth_frame
43 function vmm_data::new(vmm_log log = null
46  super.new(`VMM_DATA_BASE_NEW_CALL);
47 `endif
48 
49  if (log == null) log = this.get_vmm_log();
50 `ifndef VMM_DATA_NO_NOTIFY_ALL
51  this.notify = new(log);
53 `ifdef VMM_12_UNDERPIN_VMM_NOTIFY
54  if (parent != null) begin
55  `VMM_OBJECT_SET_PARENT(this.notify, this)
56  end
57 `endif
58 `endif
59 
60  void'(this.notify.configure(EXECUTE, vmm_notify::ON_OFF));
61  void'(this.notify.configure(STARTED, vmm_notify::ON_OFF));
62  void'(this.notify.configure(ENDED, vmm_notify::ON_OFF));
63  this.notify.indicate(EXECUTE);
64 `endif //VMM_DATA_NO_NOTIFY_ALL
65 endfunction: new
66 
67 
68 function vmm_log vmm_data::set_log(vmm_log log);
69 `ifndef VMM_DATA_NO_NOTIFY_ALL
70  set_log = this.notify.log;
71  this.notify.log = log;
72 `endif // VMM_DATA_NO_NOTIFY_ALL
73 endfunction: set_log
74 
75 
76 function string vmm_data::this_class_name();
77  return "vmm_data";
78 endfunction: this_class_name
79 
80 
81 function vmm_log vmm_data::get_vmm_log();
82 `ifndef VMM_DATA_NO_NOTIFY_ALL
83  if (this.notify == null) return null;
84  return this.notify.log;
85 `endif // VMM_DATA_NO_NOTIFY_ALL
86 endfunction
87 
88 
89 // ////////////////////////////////////////////
90 // Function: display
91 //
92 // Displays the current value of the transaction or data described by this instance, in
93 // a human-readable format on the standard output. Each line of the output will be prefixed
94 // with the specified prefix. This method prints the value returned by the psdisplay()
95 // method.
96 //
97 function void vmm_data::display(string prefix="");
98  $display(this.psdisplay(prefix));
99 endfunction: display
100 
101 
102 // ////////////////////////////////////////////
103 // Function: psdisplay
104 //
105 // Returns an image of the current value of the transaction or data described by this instance,
106 // in a human-readable format as a string. The string may contain newline characters to
107 // split the image across multiple lines. Each line of the output must be prefixed with
108 // the specified prefix.
109 //
110 function string vmm_data::psdisplay(string prefix="");
111  $sformat(psdisplay, "%0sclass %s (%0d.%0d.%0d)", prefix,
112  this.this_class_name(), this.stream_id, this.scenario_id, this.data_id);
113 endfunction: psdisplay
114 
115 
116 // ////////////////////////////////////////////
117 // Function: is_valid
118 //
119 // Checks whether the current value of the transaction or data described by this instance
120 // is valid and error free, according to the optionally specified kind or format. Returns
121 // TRUE (non-zero), if the content of the object is valid. Otherwise, it returns FALSE.
122 // The meaning (and use) of the kind argument is descriptor-specific, and defined by the
123 // user extension of this method.
124 // If silent is TRUE (non-zero), and if the content is invalid, then no error or warning
125 // messages are generated. If silent is FALSE, and if the content is invalid, then warning
126 // or error messages may be generated.
127 //
128 function bit vmm_data::is_valid(bit silent = 1,
129  int kind = -1);
130  is_valid = 1;
131 endfunction: is_valid
132 
133 
134 // ////////////////////////////////////////////
135 // Function: allocate
136 //
137 // Allocates a new instance of the same type as the object instance. Returns a reference
138 // to the new instance. Useful to implement class factories to create instances of user-defined
139 // derived class in generic code written using the base class type.
140 //
141 function vmm_data vmm_data::allocate();
142  string msg = "Virtual vmm_data::allocate() not implemented in derivative";
143  vmm_log log = this.get_vmm_log();
144  if (log == null) begin
145  $display(msg);
146  $finish;
147  end
148  else `vmm_fatal(log, msg);
149  allocate = null;
150 endfunction: allocate
151 
152 
153 // ////////////////////////////////////////////
154 // Function: copy
155 //
156 // Copies the current value of the object instance to the specified object instance. If
157 // no target object instance is specified, a new instance is allocated. Returns a reference
158 // to the target instance.
159 //
160 //|
161 //| The following trivial implementation does not work. Constructor copying is a shallow copy. The objects instantiated in the object (such as those referenced by the log and notify properties) are not copied, and both copies will share references to the same service interfaces. Moreover, it does not properly handle the case when the to argument is not null.
162 //| Invalid implementation of the copy method:
163 //| function vmm_data atm_cell::copy(vmm_data to = null) copy = new(this);
164 //| endfunction
165 //|
166 //| The following implementation is usually preferable:
167 //| Proper implementation of the copy method:
168 //| function vmm_data atm_cell::copy(vmm_data to = null)
169 //| atm_cell cpy;
170 //|
171 //| if (to != null) begin
172 //| if ($cast(cpy, to)) begin
173 //| ‘vmm_fatal(log, "Not an atm_cell instance");
174 //| return null;
175 //| end
176 //| end else cpy = new;
177 //|
178 //| this.copy_data(cpy);
179 //| cpy.vpi = this.vpi;
180 //| ...
181 //| copy = cpy;
182 //| endfunction: copy
183 //|
184 //| The base-class implementation of this method must not be called, as it contains error detection code of a derived class that forgot to supply an implementation. The copy_data method should be called, instead.
185 function vmm_data vmm_data::copy(vmm_data to = null);
186  string msg = "Virtual vmm_data::copy() not implemented in derivative";
187 
188  if (to == null) begin
189  vmm_log log = this.get_vmm_log();
190  if (log == null) begin
191  $display(msg);
192  $finish;
193  end
194  else`vmm_fatal(log, msg);
195  end
196 
197  this.copy_data(to);
198  return to;
199 endfunction: copy
200 
201 
202 // ////////////////////////////////////////////
203 // Function: copy_data
204 //
205 // Copies the current value of all base class data properties in the current data object,
206 // into the specified data object instance. This method should be called by the implementation
207 // of the <copy> method, in classes immediately derived from this base class.
208 //
209 //
210 function void vmm_data::copy_data(vmm_data to);
211  if (to == null) begin
212  string msg = "vmm_data::copy_data() called with null reference";
213  vmm_log log = this.get_vmm_log();
214 
215  if (log == null) begin
216  $display(msg);
217  $finish;
218  end
219  else`vmm_fatal(log, msg);
220  return;
221  end
222  else begin
223 `ifdef VMM_DATA_BASE_COPY_DATA_CALL
224  `VMM_DATA_BASE_COPY_DATA_CALL ;
225 `endif
226  to.stream_id = this.stream_id;
227  to.scenario_id = this.scenario_id;
228  to.data_id = this.data_id;
229  end
230 endfunction: copy_data
231 
232 
233 
234 
235 // ////////////////////////////////////////////
236 // Function: compare
237 //
238 // Compares the current value of the object instance with the current value of the specified
239 // object instance, according to the specified kind. Returns TRUE (non-zero) if the value
240 // is identical. Returns FALSE, if the value is different, and a descriptive text of the
241 // first difference found is returned in the specified string variable. The kind argument
242 // may be used to implement different comparison functions (for example, full compare,
243 // comparison of rand properties only, comparison of all properties physically implemented
244 // in a protocol, and so on.)
245 //
246 //|
247 //| function bit check(eth_frame actual)
248 //| sb_where_to_find_frame where;
249 //| eth_frame q[$];
250 //| eth_frame expect;
251 //|
252 //| check = 0;
253 //| if (!index_tbl[hash(actual)].exists()) return;
254 //| where = index_tbl[hash(actual)];
255 //| q = sb.port[where.port_no].queue[where.queue_no];
256 //| expect = q.pop_front();
257 //| if (actual.compare(expect)) check = 1;
258 //| endfunction: check
259 function bit vmm_data::compare( vmm_data to,
260  output string diff,
261  input int kind = -1);
262  return 1;
263 endfunction : compare
264 
265 
266 function int unsigned vmm_data::__vmm_byte_size(int kind = -1);
267  return 0;
268 endfunction : __vmm_byte_size
269 
270 
271 // ////////////////////////////////////////////
272 // Function: byte_size
273 //
274 // Returns the number of bytes required to pack the content of this descriptor. This method
275 // will be more efficient than the <byte_pack> method, for knowing how many
276 // bytes are required by the descriptor, because no packing is actually done.
277 // If the data can be interpreted or packed in different ways, the kind argument can be used
278 // to specify which interpretation or packing to use.
279 //
280 function int unsigned vmm_data::byte_size(int kind = -1);
281  return 0;
282 endfunction : byte_size
283 
284 
285 // ////////////////////////////////////////////
286 // Function: max_byte_size
287 //
288 // Returns the maximum number of bytes, which are required to pack the content of any instance
289 // of this descriptor. A value of 0 indicates an unknown maximum size. Thsi method can be
290 // used to allocate memory buffers in the DUT or verification environment of suitable
291 // sizes.
292 // If the data can be interpreted or packed in different ways, the kind argument can be used
293 // to specify which interpretation or packing to use.
294 //
295 function int unsigned vmm_data::max_byte_size(int kind = -1);
296  max_byte_size = 0;
297 endfunction : max_byte_size
298 
299 
300 // ////////////////////////////////////////////
301 // Function: byte_pack
302 //
303 // Packs the content of the transaction or data into the specified dynamic array of bytes,
304 // starting at the specified offset in the array. The array is resized appropriately.
305 // Returns the number of bytes added to the array.
306 // If the data can be interpreted or packed in different ways, the kind argument can be used
307 // to specify which interpretation or packing to use.
308 //
309 function int unsigned vmm_data::byte_pack(ref logic [7:0] bytes[],
310  input int unsigned offset = 0,
311  input int kind = -1);
312  return 0;
313 endfunction : byte_pack
314 
315 
316 
317 
318 // ////////////////////////////////////////////
319 // Function: byte_unpack
320 //
321 // Unpacks the specified number of bytes of data from the specified offset, in the specified
322 // dynamic array into this descriptor. If the number of bytes to unpack is specified as
323 // -1, the maximum number of bytes will be unpacked. Returns the number of bytes unpacked.
324 // If there is not enough data in the dynamic array to completely fill the descriptor, the
325 // remaining properties are set to unknown and a warning is generated.
326 // If the data can be interpreted or unpacked in different ways, the kind argument can be
327 // used to specify which interpretation or packing to use.
328 //
329 //|
330 //| class eth_frame extends vmm_data;
331 //| ...
332 //| typedef enum {UNTAGGED, TAGGED, CONTROL}
333 //| frame_formats_e;
334 //| rand frame_formats_e format;
335 //| ...
336 //| rand bit [47:0] dst;
337 //| rand bit [47:0] src;
338 //| rand bit cfi;
339 //| rand bit [ 2:0] user_priority;
340 //| rand bit [11:0] vlan_id;
341 //| ...
342 //| virtual function int unsigned byte_unpack(
343 //| const ref logic [7:0] array[],
344 //| input int unsigned offset = 0,
345 //| input int len = -1,
346 //| input int kind = -1);
347 //| integer i;
348 //|
349 //| i = offset;
350 //| this.format = UNTAGGED;
351 //| ...
352 //| if ({array[i], array[i+1]} === 16’h8100) begin
353 //| this.format = TAGGED;
354 //| i += 2;
355 //| ...
356 //| {this.user_priority, this.cfi, this.vlan_id} =
357 //| {array[i], array[i+2]};
358 //| i += 2;
359 //| ...
360 //| end
361 //| ...
362 //| endfunction: byte_unpack
363 //| ...
364 //| endclass: eth_frame
365 function int unsigned vmm_data::byte_unpack(const ref logic [7:0] bytes[],
366  input int unsigned offset = 0,
367  input int len = -1,
368  input int kind = -1);
369  return 0;
370 endfunction : byte_unpack
371 
372 
373 // ////////////////////////////////////////////
374 // Function: do_psdisplay
375 //
376 // This method overrides the default implementation of the <psdisplay> method
377 // that is created by the vmm_data shorthand macros. If defined, this method is used instead
378 // of the default implementation.
379 // The default implementation of this method in the vmm_data base class must not be called
380 // (for example, do not call super.do_psdisplay()).
381 //
382 //|
383 //| class eth_frame extends vmm_data;
384 //| ...
385 //| virtual function string do_psdisplay(string prefix = "")
386 //| $sformat(psdisplay, "%sEthernet Frame #%0d.%0d.%0d:\n",
387 //| prefix, this.stream_id, this.scenario_id,
388 //| this.data_id);
389 //| ...
390 //| endfunction
391 //| endclass
392 function string vmm_data::do_psdisplay(string prefix = "");
393  this.__vmm_done_user = 0;
394  return "";
395 endfunction: do_psdisplay
396 
397 
398 // ////////////////////////////////////////////
399 // Function: do_is_valid
400 //
401 // This method overrides the default implementation of the <is_valid() method
402 // that is created by the vmm_data shorthand macros. If defined, this method is used instead
403 // of the default implementation. The default implementation of this method in the vmm_data
404 // base class must not be called (for example, do not call super.do_is_valid>).
405 // If specified argument silent equals 1, no error or warning messages are issued if the
406 // content is invalid. If silent is FALSE, warning or error messages may be issued if the
407 // content is invalid. The meaning and use of the argument kind argument is descriptor-specific
408 // and defined by the user extension of this method.
409 //
410 //|
411 //| class eth_frame extends vmm_data;
412 //| virtual bit function do_is_valid(bit silent = 1,
413 //| int kind = -1);
414 //| do_is_valid = 1;
415 //| if (!do_is_valid && !silent) begin
416 //| `vmm_error(this.log, "Ethernet Frame is not valid");
417 //| end
418 //| endfunction
419 //| endclass
420 function bit vmm_data::do_is_valid(bit silent = 1,
421  int kind = -1);
422  this.__vmm_done_user = 0;
423  return 0;
424 endfunction: do_is_valid
425 
426 
427 function vmm_data vmm_data::do_allocate();
428  this.__vmm_done_user = 0;
429  return null;
430 endfunction: do_allocate
431 
432 
433 // ////////////////////////////////////////////
434 // Function: do_copy
435 //
436 // This method overrides the default implementation of the <copy> method
437 // that is created by the vmm_data shorthand macros. If defined, this method is used instead
438 // of the default implementation.
439 // The default implementation of this method in the vmm_data base class must not be called
440 // (for example, do not call super.do_copy()).
441 // The optional to argument specifies the transaction on which copy needs to be performed.
442 //
443 //
444 //|
445 //| class eth_frame extends vmm_data;
446 //| ...
447 //| virtual vmm_data function do_copy(vmm_data to = null);
448 //| eth_frame cpy;
449 //| if (to != null) begin
450 //| if (!$cast(cpy, to)) begin
451 //| `vmm_error(this.log, "Cannot copy to non-eth_frame\n
452 //| instance");
453 //| return null;
454 //| end
455 //| end else cpy = new;
456 //| ...
457 //| `ifdef ETH_USE_COMPOSITION
458 //| if (this.vlan != null) begin
459 //| cpy.vlan = new;
460 //| cpy.vlan.user_priority = this.vlan.user_priority;
461 //| cpy.vlan.cfi = this.vlan.cfi;
462 //| cpy.vlan.id = this.vlan.id;
463 //| end
464 //| `else
465 //| cpy.user_priority = this.user_priority;
466 //| cpy.cfi = this.cfi;
467 //| cpy.vlan_id = this.vlan_id;
468 //| `endif
469 //| ...
470 //| do_copy = cpy;
471 //| endfunction
472 //| ...
473 //| endclass
474 function vmm_data vmm_data::do_copy(vmm_data to = null);
475  this.__vmm_done_user = 0;
476  return null;
477 endfunction: do_copy
478 
479 
480 // ////////////////////////////////////////////
481 // Function: do_compare
482 //
483 // This method overrides the default implementation of the <compare> method
484 // that is created by the vmm_data shorthand macros. If defined, this method is used instead
485 // of the default implementation.
486 // The default implementation of this method in the vmm_data base class must not be called
487 // (for example, do not call super.do_compare()).
488 // The specified argument to is transaction instance with which current transaction
489 // is compared, returns TRUE if the value is identical. If the value is different, FALSE
490 // is returned and a descriptive text of the first difference found is returned in the specified
491 // string variable diff.
492 // The kind argument may be used to implement different comparison functions (for example,
493 // full compare, comparison of rand properties only, comparison of all properties physically
494 // implemented in a protocol and so on.)
495 //
496 //|
497 //| class eth_frame extends vmm_data;
498 //| ...
499 //| virtual bit function do_compare(input vmm_data to =
500 //| null,output string diff, input int kind = -1);
501 //| eth_frame fr;
502 //| do_compare = 1;
503 //| ...
504 //| `ifdef ETH_USE_COMPOSITION
505 //| if (fr.vlan == null) begin
506 //| diff = "No vlan data";
507 //| do_compare = 0;
508 //| end
509 //|
510 //| if (fr.vlan.user_priority !==
511 //| this.vlan.user_priority) begin
512 //| $sformat(diff, "user_priority (3'd%0d !== 3'd%0d)",
513 //| this.vlan.user_priority,
514 //| fr.vlan.user_priority);
515 //| do_compare = 0;
516 //| end
517 //| ...
518 //| `else
519 //| if (fr.user_priority !== this.user_priority) begin
520 //| $sformat(diff, "user_priority (3'd%0d !== 3'd%0d)",
521 //| this.user_priority, fr.user_priority);
522 //| do_compare = 0;
523 //| end
524 //| ...
525 //| `endif
526 //| ...
527 //| endfunction
528 //| endclass
529 function bit vmm_data::do_compare( vmm_data to,
530  output string diff,
531  input int kind = -1);
532  this.__vmm_done_user = 0;
533  return 0;
534 endfunction : do_compare
535 
536 
537 // ////////////////////////////////////////////
538 // Function: do_byte_size
539 //
540 // This method overrides the default implementation of the <byte_size> method
541 // that is created by the vmm_data shorthand macros. If defined, this method is used instead
542 // of the default implementation.
543 // The default implementation of this method in the vmm_data base class must not be called
544 // (for example, do not call super.do_byte_size()).
545 // The returned value is the number of bytes required to pack the content of this descriptor.
546 // The specified kind argument can be used to specify which interpretation or packing
547 // to use.
548 //
549 //|
550 //| class eth_frame extends vmm_data;
551 //| virtual int function do_byte_size(int kind = -1);
552 //| `ifdef TAGGED
553 //| do_byte_size = 14 + data.size();
554 //| `else
555 //| do_byte_size = 14 + data.size() + 4;
556 //| `endif
557 //| endfunction
558 //| endclass
559 function int unsigned vmm_data::do_byte_size(int kind = -1);
560  this.__vmm_done_user = 0;
561  return 0;
562 endfunction : do_byte_size
563 
564 
565 // ////////////////////////////////////////////
566 // Function: do_max_byte_size
567 //
568 // This method overrides the default implementation of the <max_byte_size>
569 // method that is created by the vmm_data shorthand macros. If defined, this method is
570 // used instead of the default implementation.
571 // The default implementation of this method in the vmm_data base class must not be called
572 // (for example, do not call super.do_max_byte_size()).
573 //
574 //|
575 //| class eth_frame extends vmm_data;
576 //| virtual int function do_max_byte_size(int kind = -1);
577 //| `ifdef JUMBO_PACKET
578 //| do_max_byte_size = 9000;
579 //| `else
580 //| do_max_byte_size = 1500;
581 //| `endif
582 //| endfunction
583 //| endclass
584 function int unsigned vmm_data::do_max_byte_size(int kind = -1);
585  this.__vmm_done_user = 0;
586  return 0;
587 endfunction : do_max_byte_size
588 
589 
590 // ////////////////////////////////////////////
591 // Function: do_byte_pack
592 //
593 // This method overrides the default implementation of the <byte_pack> method
594 // that is created by the vmm_data shorthand macros. If defined, this method is used instead
595 // of the default implementation.
596 // The default implementation of this method in the vmm_data base class must not be called
597 // (for example, do not call super.do_byte_pack()).
598 // The specified argument bytes is the dynamic array in which transaction contents are
599 // packed, starting at the specified offset value. The specified argument kind can be
600 // used to specify which interpretation or packing to use.
601 //
602 //|
603 //| class eth_frame extends vmm_data;
604 //| ...
605 //| virtual int function do_byte_pack(ref logic [7:0]
606 //| bytes[],input int unsigned offset = 0,
607 //| input int kind = -1);
608 //| int i;
609 //| ...
610 //| `ifdef ETH_USE_COMPOSITION
611 //| {bytes[i], bytes[i+1]} = {this.vlan.user_priority,
612 //| this.vlan.cfi, this.vlan.id};
613 //| `else
614 //| {bytes[i], bytes[i+1]} = {this.user_priority,
615 //| this.cfi, this.vlan_id};
616 //| `endif
617 //| ...
618 //| endfunction
619 //|
620 //| endclass
621 function int unsigned vmm_data::do_byte_pack(ref logic [7:0] bytes[],
622  input int unsigned offset = 0,
623  input int kind = -1);
624  this.__vmm_done_user = 0;
625  return 0;
626 endfunction : do_byte_pack
627 
628 
629 // ////////////////////////////////////////////
630 // Function: do_byte_unpack
631 //
632 // This method overrides the default implementation of the <byte_unpack>
633 // method that is created by the vmm_data shorthand macros. If defined, this method is
634 // used instead of the default implementation.
635 // The default implementation of this method in the vmm_data base class must not be called
636 // (for example, do not call super.do_byte_unpack()).
637 // The specified argument len is the number of data bytes to unpack, starting at specified
638 // offset value. The unpacked data is stored in the specified bytes dynamic array.
639 // If the number of bytes to unpack is specified as -1, the maximum number of bytes will be
640 // unpacked. This method returns the number of bytes unpacked.
641 // If the data can be interpreted or unpacked in different ways, the kind argument can be
642 // used to specify which interpretation or packing to used.
643 //
644 //|
645 //| class eth_frame extends vmm_data;
646 //| ...
647 //| virtual int function do_byte_unpack(const ref logic [7:0]
648 //| bytes[],input int unsigned offset = 0,
649 //| input int len = -1,input int kind = -1);
650 //| ...
651 //| `ifdef ETH_USE_COMPOSITION
652 //| {this.vlan.user_priority, this.vlan.cfi,
653 //| this.vlan.id} = {bytes[i], bytes[i+1]};
654 //| `else
655 //| {this.user_priority, this.cfi, this.vlan_id} =
656 //| {bytes[i], bytes[i+1]};
657 //| `endif
658 //| ...
659 //| endfunction
660 //| ...
661 //| endclass
662 function int unsigned vmm_data::do_byte_unpack(const ref logic [7:0] bytes[],
663  input int unsigned offset =0,
664  input int len = -1,
665  input int kind = -1);
666  this.__vmm_done_user = 0;
667  return 0;
668 endfunction : do_byte_unpack
669 
670 
671 
672 // ////////////////////////////////////////////
673 // Function: load
674 //
675 // Sets the content of this descriptor from the data, in the specified file. The format
676 // is user defined, and may be binary. By default, interprets a complete line as binary
677 // byte data and unpacks it.
678 // Should return FALSE (zero), if the loading operation was not successful.
679 //
680 function bit vmm_data::load(int file);
681  int len, i;
682  logic [7:0] bytes[];
683  bit escaped = 0;
684 
685  load = 0;
686 
687  // Expect one record for the object, with the following format:
688  // [<blanks>]<n><SPACE><n bytes (potentially inclusing \n)>\n
689  if ($fscanf(file, " %d", len) != 1) begin
690  string msg = "Invalid input record in vmm_data::load()";
691  vmm_log log = this.get_vmm_log();
692  if (log == null) begin
693  $display(msg);
694  $finish;
695  end
696  else`vmm_fatal(log, msg);
697  return 0;
698  end
699 
700  // Skip the <SPACE>
701  begin
702  bit [7:0] c;
703  c = $fgetc(file);
704  end
705 
706  // Read the next 'len' characters and unpack
707  bytes = new [len];
708  i = 0;
709  while (i < len) begin
710  int c = $fgetc(file);
711  if (c < 0) begin
712  string msg = "Truncated input record in vmm_data::load()";
713  vmm_log log = this.get_vmm_log();
714  if (log == null) begin
715  $display(msg);
716  $finish;
717  end
718  else`vmm_fatal(log, msg);
719  return 0;
720  end
721  bytes[i] = c;
722  // Some characters have been escaped
723  if (bytes[i] == 8'h2E) begin
724  escaped = 1;
725  continue;
726  end
727  if (escaped) begin
728  bit [7:0] c = bytes[i];
729  c[7] = ~c[7];
730  bytes[i] = c;
731  escaped = 0;
732  end
733  i++;
734  end
735  i = this.byte_unpack(bytes);
736  if (i != len) begin
737  string msg = `vmm_sformatf("Unable to fully unpack input record in vmm_data::load(): %0d bytes were unpacked instead of the full %0d.", len, i);
738  vmm_log log = this.get_vmm_log();
739  if (log == null) begin
740  $display(msg);
741  $finish;
742  end
743  else`vmm_fatal(log, msg);
744  return 0;
745  end
746 
747  // Skip the final \n
748  begin
749  bit [7:0] c;
750  c = $fgetc(file);
751  if (c != "\n") begin
752  string msg = "Corrupted record in file: extra characters present";
753  vmm_log log = this.get_vmm_log();
754  if (log == null) begin
755  $display(msg);
756  $finish;
757  end
758  else`vmm_fatal(log, msg);
759  end
760  end
761 
762  load = 1;
763 endfunction: load
764 
765 
766 // ////////////////////////////////////////////
767 // Function: save
768 //
769 // Appends the content of this descriptor to the specified file. The format is user defined,
770 // and may be binary. By default, packs the descriptor and saves the value of the bytes,
771 // in sequence, as binary values and terminated by a newline.
772 //
773 function void vmm_data::save(int file);
774  logic [7:0] bytes[];
775  int i;
776 
777  // Produce the format expected by vmm_data::load()
778  void'(this.byte_pack(bytes));
779  $fwrite(file, "%0d ", bytes.size());
780  for (i = 0; i < bytes.size(); i++) begin
781  bit [7:0] a_byte = bytes[i]; // Make sure there are no X's
782  // Some characters need to be escaped
783  case (a_byte)
784  8'h00,
785  8'hFF,
786  8'h2E: begin
787  bit [7:0] c = a_byte;
788  c[7] = ~c[7];
789  $fwrite(file, ".%c", c);
790  end
791 
792  default: $fwrite(file, "%c", a_byte);
793  endcase
794  end
795  $fwrite(file, "\n");
796 endfunction: save
797 
798 
799 
800 `ifdef VCS
801 function int vmm_data::vmt_hook(vmm_xactor xactor = null,
802  vmm_data obj = null);
803 endfunction: vmt_hook
804 
805 `endif

Studio Muzzi
Studio Muzzi
Project: VMM, Revision: 1.2.2b
Copyright (c) 2008-2010 Intelligent Design Verification, 2013 Studio Muzzi.
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
A copy of the license is included here:
fdl.txt
doxygen
Doxygen Version: 1.8.4
Sun Jun 16 2013 05:44:50