OpenCores
URL https://opencores.org/ocsvn/uart2bus_testbench/uart2bus_testbench/trunk

Subversion Repositories uart2bus_testbench

[/] [uart2bus_testbench/] [trunk/] [tb/] [uvm_src/] [base/] [uvm_packer.svh] - Blame information for rev 16

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 16 HanySalah
//
2
//------------------------------------------------------------------------------
3
//   Copyright 2007-2011 Mentor Graphics Corporation
4
//   Copyright 2007-2011 Cadence Design Systems, Inc.
5
//   Copyright 2010 Synopsys, Inc.
6
//   Copyright 2013 NVIDIA Corporation
7
//   All Rights Reserved Worldwide
8
//
9
//   Licensed under the Apache License, Version 2.0 (the
10
//   "License"); you may not use this file except in
11
//   compliance with the License.  You may obtain a copy of
12
//   the License at
13
//
14
//       http://www.apache.org/licenses/LICENSE-2.0
15
//
16
//   Unless required by applicable law or agreed to in
17
//   writing, software distributed under the License is
18
//   distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
19
//   CONDITIONS OF ANY KIND, either express or implied.  See
20
//   the License for the specific language governing
21
//   permissions and limitations under the License.
22
//------------------------------------------------------------------------------
23
 
24
 
25
//------------------------------------------------------------------------------
26
// CLASS: uvm_packer
27
//
28
// The uvm_packer class provides a policy object for packing and unpacking
29
// uvm_objects. The policies determine how packing and unpacking should be done.
30
// Packing an object causes the object to be placed into a bit (byte or int)
31
// array. If the `uvm_field_* macro are used to implement pack and unpack,
32
// by default no metadata information is stored for the packing of dynamic
33
// objects (strings, arrays, class objects).
34
//
35
//-------------------------------------------------------------------------------
36
 
37
typedef bit signed [(`UVM_PACKER_MAX_BYTES*8)-1:0] uvm_pack_bitstream_t;
38
 
39
class uvm_packer;
40
 
41
  //----------------//
42
  // Group: Packing //
43
  //----------------//
44
 
45
  // Function: pack_field
46
  //
47
  // Packs an integral value (less than or equal to 4096 bits) into the
48
  // packed array. ~size~ is the number of bits of ~value~ to pack.
49
 
50
  extern virtual function void pack_field (uvm_bitstream_t value, int size);
51
 
52
 
53
  // Function: pack_field_int
54
  //
55
  // Packs the integral value (less than or equal to 64 bits) into the
56
  // pack array.  The ~size~ is the number of bits to pack, usually obtained by
57
  // ~$bits~. This optimized version of  is useful for sizes up
58
  // to 64 bits.
59
 
60
  extern virtual function void pack_field_int (uvm_integral_t value, int size);
61
 
62
  // Function: pack_bits
63
  //
64
  // Packs bits from upacked array of bits into the pack array.
65
  //
66
  // See  for additional information.
67
  extern virtual function void pack_bits(ref bit value[], input int size = -1);
68
 
69
  // Function: pack_bytes
70
  //
71
  // Packs bits from an upacked array of bytes into the pack array.
72
  //
73
  // See  for additional information.
74
  extern virtual function void pack_bytes(ref byte value[], input int size = -1);
75
 
76
  // Function: pack_ints
77
  //
78
  // Packs bits from an unpacked array of ints into the pack array.
79
  //
80
  // The bits are appended to the internal pack array.
81
  // This method allows for fields of arbitrary length to be
82
  // passed in, using the SystemVerilog ~stream~ operator.
83
  //
84
  // For example
85
  // | bit[511:0] my_field;
86
  // | begin
87
  // |   int my_stream[];
88
  // |   { << int {my_stream}} = my_field;
89
  // |   packer.pack_ints(my_stream);
90
  // | end
91
  //
92
  // When appending the stream to the internal pack array, the packer will obey
93
  // the value of  (appending the array from MSB to LSB if set).
94
  //
95
  // An optional ~size~ parameter is provided, which defaults to '-1'.  If set
96
  // to any value greater than '-1' (including 0), then the packer will use
97
  // the size as the number of bits to pack, otherwise the packer will simply
98
  // pack the entire stream.
99
  //
100
  // An error will be asserted if the ~size~ has been specified, and exceeds the
101
  // size of the source array.
102
  //
103
  extern virtual function void pack_ints(ref int value[], input int size = -1);
104
 
105
 
106
  // Function: pack_string
107
  //
108
  // Packs a string value into the pack array.
109
  //
110
  // When the metadata flag is set, the packed string is terminated by a ~null~
111
  // character to mark the end of the string.
112
  //
113
  // This is useful for mixed language communication where unpacking may occur
114
  // outside of SystemVerilog UVM.
115
 
116
  extern virtual function void pack_string (string value);
117
 
118
 
119
  // Function: pack_time
120
  //
121
  // Packs a time ~value~ as 64 bits into the pack array.
122
 
123
  extern virtual function void pack_time (time value);
124
 
125
 
126
  // Function: pack_real
127
  //
128
  // Packs a real ~value~ as 64 bits into the pack array.
129
  //
130
  // The real ~value~ is converted to a 6-bit scalar value using the function
131
  // $real2bits before it is packed into the array.
132
 
133
  extern virtual function void pack_real (real value);
134
 
135
 
136
  // Function: pack_object
137
  //
138
  // Packs an object value into the pack array.
139
  //
140
  // A 4-bit header is inserted ahead of the string to indicate the number of
141
  // bits that was packed. If a ~null~ object was packed, then this header will
142
  // be 0.
143
  //
144
  // This is useful for mixed-language communication where unpacking may occur
145
  // outside of SystemVerilog UVM.
146
 
147
  extern virtual function void pack_object (uvm_object value);
148
 
149
 
150
  //------------------//
151
  // Group: Unpacking //
152
  //------------------//
153
 
154
  // Function: is_null
155
  //
156
  // This method is used during unpack operations to peek at the next 4-bit
157
  // chunk of the pack data and determine if it is 0.
158
  //
159
  // If the next four bits are all 0, then the return value is a 1; otherwise
160
  // it is 0.
161
  //
162
  // This is useful when unpacking objects, to decide whether a new object
163
  // needs to be allocated or not.
164
 
165
  extern virtual function bit is_null ();
166
 
167
 
168
  // Function: unpack_field
169
  //
170
  // Unpacks bits from the pack array and returns the bit-stream that was
171
  // unpacked. ~size~ is the number of bits to unpack; the maximum is 4096 bits.
172
 
173
  extern virtual function uvm_bitstream_t unpack_field (int size);
174
 
175
  // Function: unpack_field_int
176
  //
177
  // Unpacks bits from the pack array and returns the bit-stream that was
178
  // unpacked.
179
  //
180
  // ~size~ is the number of bits to unpack; the maximum is 64 bits.
181
  // This is a more efficient variant than unpack_field when unpacking into
182
  // smaller vectors.
183
 
184
  extern virtual function uvm_integral_t unpack_field_int (int size);
185
 
186
  // Function: unpack_bits
187
  //
188
  // Unpacks bits from the pack array into an unpacked array of bits.
189
  //
190
  extern virtual function void unpack_bits(ref bit value[], input int size = -1);
191
 
192
  // Function: unpack_bytes
193
  //
194
  // Unpacks bits from the pack array into an unpacked array of bytes.
195
  //
196
  extern virtual function void unpack_bytes(ref byte value[], input int size = -1);
197
 
198
  // Function: unpack_ints
199
  //
200
  // Unpacks bits from the pack array into an unpacked array of ints.
201
  //
202
  // The unpacked array is unpacked from the internal pack array.
203
  // This method allows for fields of arbitrary length to be
204
  // passed in without expanding into a pre-defined integral type first.
205
  //
206
  // For example
207
  // | bit[511:0] my_field;
208
  // | begin
209
  // |   int my_stream[] = new[16]; // 512/32 = 16
210
  // |   packer.unpack_ints(my_stream);
211
  // |   my_field = {<<{my_stream}};
212
  // | end
213
  //
214
  // When unpacking the stream from the internal pack array, the packer will obey
215
  // the value of  (unpacking the array from MSB to LSB if set).
216
  //
217
  // An optional ~size~ parameter is provided, which defaults to '-1'.  If set
218
  // to any value greater than '-1' (including 0), then the packer will use
219
  // the size as the number of bits to unpack, otherwise the packer will simply
220
  // unpack the entire stream.
221
  //
222
  // An error will be asserted if the ~size~ has been specified, and
223
  // exceeds the size of the target array.
224
  //
225
  extern virtual function void unpack_ints(ref int value[], input int size = -1);
226
 
227
 
228
  // Function: unpack_string
229
  //
230
  // Unpacks a string.
231
  //
232
  // num_chars bytes are unpacked into a string. If num_chars is -1 then
233
  // unpacking stops on at the first ~null~ character that is encountered.
234
 
235
  extern virtual function string unpack_string (int num_chars=-1);
236
 
237
 
238
  // Function: unpack_time
239
  //
240
  // Unpacks the next 64 bits of the pack array and places them into a
241
  // time variable.
242
 
243
  extern virtual function time unpack_time ();
244
 
245
 
246
  // Function: unpack_real
247
  //
248
  // Unpacks the next 64 bits of the pack array and places them into a
249
  // real variable.
250
  //
251
  // The 64 bits of packed data are converted to a real using the $bits2real
252
  // system function.
253
 
254
  extern virtual function real unpack_real ();
255
 
256
 
257
  // Function: unpack_object
258
  //
259
  // Unpacks an object and stores the result into ~value~.
260
  //
261
  // ~value~ must be an allocated object that has enough space for the data
262
  // being unpacked. The first four bits of packed data are used to determine
263
  // if a ~null~ object was packed into the array.
264
  //
265
  // The  function can be used to peek at the next four bits in
266
  // the pack array before calling this method.
267
 
268
  extern virtual function void unpack_object (uvm_object value);
269
 
270
 
271
  // Function: get_packed_size
272
  //
273
  // Returns the number of bits that were packed.
274
 
275
  extern virtual function int get_packed_size();
276
 
277
 
278
  //------------------//
279
  // Group: Variables //
280
  //------------------//
281
 
282
  // Variable: physical
283
  //
284
  // This bit provides a filtering mechanism for fields.
285
  //
286
  // The  and physical settings allow an object to distinguish between
287
  // two different classes of fields. It is up to you, in the
288
  //  and  methods, to test the
289
  // setting of this field if you want to use it as a filter.
290
 
291
  bit physical = 1;
292
 
293
 
294
  // Variable: abstract
295
  //
296
  // This bit provides a filtering mechanism for fields.
297
  //
298
  // The abstract and physical settings allow an object to distinguish between
299
  // two different classes of fields. It is up to you, in the
300
  //  and  routines, to test the
301
  // setting of this field if you want to use it as a filter.
302
 
303
  bit abstract;
304
 
305
 
306
  // Variable: use_metadata
307
  //
308
  // This flag indicates whether to encode metadata when packing dynamic data,
309
  // or to decode metadata when unpacking.  Implementations of 
310
  // and  should regard this bit when performing their
311
  // respective operation. When set, metadata should be encoded as follows:
312
  //
313
  // - For strings, pack an additional ~null~ byte after the string is packed.
314
  //
315
  // - For objects, pack 4 bits prior to packing the object itself. Use 4'b0000
316
  //   to indicate the object being packed is ~null~, otherwise pack 4'b0001 (the
317
  //   remaining 3 bits are reserved).
318
  //
319
  // - For queues, dynamic arrays, and associative arrays, pack 32 bits
320
  //   indicating the size of the array prior to packing individual elements.
321
 
322
  bit use_metadata;
323
 
324
 
325
  // Variable: big_endian
326
  //
327
  // This bit determines the order that integral data is packed (using
328
  // , , , or ) and how the
329
  // data is unpacked from the pack array (using ,
330
  // , , or ). When the bit is set,
331
  // data is associated msb to lsb; otherwise, it is associated lsb to msb.
332
  //
333
  // The following code illustrates how data can be associated msb to lsb and
334
  // lsb to msb:
335
  //
336
  //|  class mydata extends uvm_object;
337
  //|
338
  //|    logic[15:0] value = 'h1234;
339
  //|
340
  //|    function void do_pack (uvm_packer packer);
341
  //|      packer.pack_field_int(value, 16);
342
  //|    endfunction
343
  //|
344
  //|    function void do_unpack (uvm_packer packer);
345
  //|      value = packer.unpack_field_int(16);
346
  //|    endfunction
347
  //|  endclass
348
  //|
349
  //|  mydata d = new;
350
  //|  bit bits[];
351
  //|
352
  //|  initial begin
353
  //|    d.pack(bits);  // 'b0001001000110100
354
  //|    uvm_default_packer.big_endian = 0;
355
  //|    d.pack(bits);  // 'b0010110001001000
356
  //|  end
357
 
358
  bit big_endian = 1;
359
 
360
 
361
  // variables and methods primarily for internal use
362
 
363
  static bit bitstream[];   // local bits for (un)pack_bytes
364
  static bit fabitstream[]; // field automation bits for (un)pack_bytes
365
  int count;                // used to count the number of packed bits
366
  uvm_scope_stack scope= new;
367
 
368
  bit   reverse_order;      //flip the bit order around
369
  byte  byte_size     = 8;  //set up bytesize for endianess
370
  int   word_size     = 16; //set up worksize for endianess
371
  bit   nopack;             //only count packable bits
372
 
373
  uvm_recursion_policy_enum policy = UVM_DEFAULT_POLICY;
374
 
375
  uvm_pack_bitstream_t m_bits;
376
  int m_packed_size;
377
 
378
  extern virtual function void unpack_object_ext  (inout uvm_object value);
379
 
380
  extern virtual function uvm_pack_bitstream_t get_packed_bits ();
381
 
382
  extern virtual function bit  unsigned get_bit  (int unsigned index);
383
  extern virtual function byte unsigned get_byte (int unsigned index);
384
  extern virtual function int  unsigned get_int  (int unsigned index);
385
 
386
  extern virtual function void get_bits (ref bit unsigned bits[]);
387
  extern virtual function void get_bytes(ref byte unsigned bytes[]);
388
  extern virtual function void get_ints (ref int unsigned ints[]);
389
 
390
  extern virtual function void put_bits (ref bit unsigned bitstream[]);
391
  extern virtual function void put_bytes(ref byte unsigned bytestream[]);
392
  extern virtual function void put_ints (ref int unsigned intstream[]);
393
 
394
  extern virtual function void set_packed_size();
395
  extern function void index_error(int index, string id, int sz);
396
  extern function bit enough_bits(int needed, string id);
397
 
398
  extern function void reset();
399
 
400
endclass
401
 
402
 
403
 
404
//------------------------------------------------------------------------------
405
// IMPLEMENTATION
406
//------------------------------------------------------------------------------
407
 
408
// NOTE- max size limited to BITSTREAM bits parameter (default: 4096)
409
 
410
 
411
// index_ok
412
// --------
413
 
414
function void uvm_packer::index_error(int index, string id, int sz);
415
    uvm_report_error("PCKIDX",
416
        $sformatf("index %0d for get_%0s too large; valid index range is 0-%0d.",
417
                  index,id,((m_packed_size+sz-1)/sz)-1), UVM_NONE);
418
endfunction
419
 
420
 
421
// enough_bits
422
// -----------
423
 
424
function bit uvm_packer::enough_bits(int needed, string id);
425
  if ((m_packed_size - count) < needed) begin
426
    uvm_report_error("PCKSZ",
427
        $sformatf("%0d bits needed to unpack %0s, yet only %0d available.",
428
                  needed, id, (m_packed_size - count)), UVM_NONE);
429
    return 0;
430
  end
431
  return 1;
432
endfunction
433
 
434
 
435
// get_packed_size
436
// ---------------
437
 
438
function int uvm_packer::get_packed_size();
439
  return m_packed_size;
440
endfunction
441
 
442
 
443
// set_packed_size
444
// ---------------
445
 
446
function void uvm_packer::set_packed_size();
447
  m_packed_size = count;
448
  count = 0;
449
endfunction
450
 
451
 
452
// reset
453
// -----
454
 
455
function void uvm_packer::reset();
456
  count = 0;
457
  m_bits = 0;
458
  m_packed_size = 0;
459
endfunction
460
 
461
 
462
// get_packed_bits
463
// ---------------
464
 
465
function uvm_pack_bitstream_t uvm_packer::get_packed_bits();
466
  //bits = m_bits;
467
  return m_bits;
468
endfunction
469
 
470
 
471
// get_bits
472
// --------
473
 
474
function void uvm_packer::get_bits(ref bit unsigned bits[]);
475
  bits = new[m_packed_size];
476
  for (int i=0;i
477
    bits[i] = m_bits[i];
478
endfunction
479
 
480
 
481
// get_bytes
482
// ---------
483
 
484
function void uvm_packer::get_bytes(ref byte unsigned bytes[]);
485
  int sz;
486
  byte v;
487
  sz = (m_packed_size+7) / 8;
488
  bytes = new[sz];
489
  for (int i=0;i
490
    if (i != sz-1 || (m_packed_size % 8) == 0)
491
      v = m_bits[ i*8 +: 8 ];
492
    else
493
      v = m_bits[ i*8 +: 8 ] & ('hFF >> (8-(m_packed_size%8)));
494
    if(big_endian) begin
495
      byte tmp; tmp = v;
496
      for(int j=0; j<8; ++j) v[j] = tmp[7-j];
497
    end
498
    bytes[i] = v;
499
  end
500
endfunction
501
 
502
 
503
// get_ints
504
// --------
505
 
506
function void uvm_packer::get_ints(ref int unsigned ints[]);
507
  int sz, v;
508
  sz = (m_packed_size+31) / 32;
509
  ints = new[sz];
510
  for (int i=0;i
511
    if (i != sz-1 || (m_packed_size % 32) == 0)
512
      v = m_bits[ i*32 +: 32 ];
513
    else
514
      v = m_bits[ i*32 +: 32 ] & ('hFFFFFFFF >> (32-(m_packed_size%32)));
515
    if(big_endian) begin
516
      int tmp; tmp = v;
517
      for(int j=0; j<32; ++j) v[j] = tmp[31-j];
518
    end
519
    ints[i] = v;
520
  end
521
endfunction
522
 
523
 
524
// put_bits
525
// --------
526
 
527
function void uvm_packer::put_bits (ref bit bitstream []);
528
 
529
  int bit_size;
530
 
531
  bit_size = bitstream.size();
532
 
533
  if(big_endian)
534
    for (int i=bit_size-1;i>=0;i--)
535
      m_bits[i] = bitstream[i];
536
  else
537
    for (int i=0;i
538
      m_bits[i] = bitstream[i];
539
 
540
  m_packed_size = bit_size;
541
  count = 0;
542
 
543
endfunction
544
 
545
// put_bytes
546
// ---------
547
 
548
function void uvm_packer::put_bytes (ref byte unsigned bytestream []);
549
 
550
  int byte_size;
551
  int index;
552
  byte unsigned b;
553
 
554
  byte_size = bytestream.size();
555
  index = 0;
556
  for (int i=0;i
557
    b = bytestream[i];
558
    if(big_endian) begin
559
      byte unsigned tb; tb = b;
560
      for(int j=0;j<8;++j) b[j] = tb[7-j];
561
    end
562
    m_bits[index +:8] = b;
563
    index += 8;
564
  end
565
 
566
  m_packed_size = byte_size*8;
567
  count = 0;
568
endfunction
569
 
570
 
571
// put_ints
572
// --------
573
 
574
function void uvm_packer::put_ints (ref int unsigned intstream []);
575
 
576
  int int_size;
577
  int index;
578
  int unsigned v;
579
 
580
  int_size = intstream.size();
581
 
582
  index = 0;
583
  for (int i=0;i
584
    v = intstream[i];
585
    if(big_endian) begin
586
      int unsigned tv; tv = v;
587
      for(int j=0;j<32;++j) v[j] = tv[31-j];
588
    end
589
    m_bits[index +:32] = v;
590
    index += 32;
591
  end
592
 
593
  m_packed_size = int_size*32;
594
  count = 0;
595
endfunction
596
 
597
 
598
 
599
 
600
// get_bit
601
// -------
602
 
603
function bit unsigned uvm_packer::get_bit(int unsigned index);
604
  if (index >= m_packed_size)
605
    index_error(index, "bit",1);
606
  return m_bits[index];
607
endfunction
608
 
609
 
610
// get_byte
611
// --------
612
 
613
function byte unsigned uvm_packer::get_byte(int unsigned index);
614
  if (index >= (m_packed_size+7)/8)
615
    index_error(index, "byte",8);
616
  return m_bits[index*8 +: 8];
617
endfunction
618
 
619
 
620
// get_int
621
// -------
622
 
623
function int unsigned uvm_packer::get_int(int unsigned index);
624
  if (index >= (m_packed_size+31)/32)
625
    index_error(index, "int",32);
626
  return m_bits[(index*32) +: 32];
627
endfunction
628
 
629
 
630
// PACK
631
 
632
 
633
// pack_object
634
// ---------
635
 
636
function void uvm_packer::pack_object(uvm_object value);
637
 
638
  if(value.__m_uvm_status_container.cycle_check.exists(value)) begin
639
    uvm_report_warning("CYCFND", $sformatf("Cycle detected for object @%0d during pack", value.get_inst_id()), UVM_NONE);
640
    return;
641
  end
642
  value.__m_uvm_status_container.cycle_check[value] = 1;
643
 
644
  if((policy != UVM_REFERENCE) && (value != null) ) begin
645
      if(use_metadata == 1) begin
646
        m_bits[count +: 4] = 1;
647
        count += 4; // to better debug when display packed bits in hexadecimal
648
      end
649
      scope.down(value.get_name());
650
      value.__m_uvm_field_automation(null, UVM_PACK,"");
651
      value.do_pack(this);
652
      scope.up();
653
  end
654
  else if(use_metadata == 1) begin
655
    m_bits[count +: 4] = 0;
656
    count += 4;
657
  end
658
  value.__m_uvm_status_container.cycle_check.delete(value);
659
endfunction
660
 
661
 
662
// pack_real
663
// ---------
664
 
665
function void uvm_packer::pack_real(real value);
666
  pack_field_int($realtobits(value), 64);
667
endfunction
668
 
669
 
670
// pack_time
671
// ---------
672
 
673
function void uvm_packer::pack_time(time value);
674
  pack_field_int(value, 64);
675
  //m_bits[count +: 64] = value; this overwrites endian adjustments
676
endfunction
677
 
678
 
679
// pack_field
680
// ----------
681
 
682
function void uvm_packer::pack_field(uvm_bitstream_t value, int size);
683
  for (int i=0; i
684
    if(big_endian == 1)
685
      m_bits[count+i] = value[size-1-i];
686
    else
687
      m_bits[count+i] = value[i];
688
  count += size;
689
endfunction
690
 
691
 
692
// pack_field_int
693
// --------------
694
 
695
function void uvm_packer::pack_field_int(uvm_integral_t value, int size);
696
  for (int i=0; i
697
    if(big_endian == 1)
698
      m_bits[count+i] = value[size-1-i];
699
    else
700
      m_bits[count+i] = value[i];
701
  count += size;
702
endfunction
703
 
704
// pack_bits
705
// -----------------
706
 
707
function void uvm_packer::pack_bits(ref bit value[], input int size = -1);
708
   if (size < 0)
709
     size = value.size();
710
 
711
   if (size > value.size()) begin
712
      `uvm_error("UVM/BASE/PACKER/BAD_SIZE",
713
                 $sformatf("pack_bits called with size '%0d', which exceeds value.size() of '%0d'",
714
                           size,
715
                           value.size()))
716
      return;
717
   end
718
 
719
   for (int i=0; i
720
     if (big_endian == 1)
721
       m_bits[count+i] = value[size-1-i];
722
     else
723
       m_bits[count+i] = value[i];
724
   count += size;
725
endfunction
726
 
727
// pack_bytes
728
// -----------------
729
 
730
function void uvm_packer::pack_bytes(ref byte value[], input int size = -1);
731
   int max_size = value.size() * $bits(byte);
732
 
733
   if (size < 0)
734
     size = max_size;
735
 
736
   if (size > max_size) begin
737
      `uvm_error("UVM/BASE/PACKER/BAD_SIZE",
738
                 $sformatf("pack_bytes called with size '%0d', which exceeds value size of '%0d'",
739
                           size,
740
                           max_size))
741
      return;
742
   end
743
   else begin
744
      int idx_select;
745
 
746
      for (int i=0; i
747
         if (big_endian == 1)
748
           idx_select = size-1-i;
749
         else
750
           idx_select = i;
751
 
752
         m_bits[count+i] = value[idx_select / $bits(byte)][idx_select % $bits(byte)];
753
      end
754
 
755
      count += size;
756
   end
757
endfunction
758
 
759
// pack_ints
760
// -----------------
761
 
762
function void uvm_packer::pack_ints(ref int value[], input int size = -1);
763
   int max_size = value.size() * $bits(int);
764
 
765
   if (size < 0)
766
     size = max_size;
767
 
768
   if (size > max_size) begin
769
      `uvm_error("UVM/BASE/PACKER/BAD_SIZE",
770
                 $sformatf("pack_ints called with size '%0d', which exceeds value size of '%0d'",
771
                           size,
772
                           max_size))
773
      return;
774
   end
775
   else begin
776
      int idx_select;
777
 
778
      for (int i=0; i
779
         if (big_endian == 1)
780
           idx_select = size-1-i;
781
         else
782
           idx_select = i;
783
 
784
         m_bits[count+i] = value[idx_select / $bits(int)][idx_select % $bits(int)];
785
      end
786
 
787
      count += size;
788
   end
789
endfunction
790
 
791
 
792
// pack_string
793
// -----------
794
 
795
function void uvm_packer::pack_string(string value);
796
  byte b;
797
  foreach (value[index]) begin
798
    if(big_endian == 0)
799
      m_bits[count +: 8] = value[index];
800
    else begin
801
      b = value[index];
802
      for(int i=0; i<8; ++i)
803
        m_bits[count+i] = b[7-i];
804
    end
805
    count += 8;
806
  end
807
  if(use_metadata == 1) begin
808
    m_bits[count +: 8] = 0;
809
    count += 8;
810
  end
811
endfunction
812
 
813
 
814
// UNPACK
815
 
816
 
817
// is_null
818
// -------
819
 
820
function bit uvm_packer::is_null();
821
  return (m_bits[count+:4]==0);
822
endfunction
823
 
824
// unpack_object
825
// -------------
826
 
827
function void uvm_packer::unpack_object_ext(inout uvm_object value);
828
  unpack_object(value);
829
endfunction
830
 
831
function void uvm_packer::unpack_object(uvm_object value);
832
 
833
  byte is_non_null; is_non_null = 1;
834
 
835
  if(value.__m_uvm_status_container.cycle_check.exists(value)) begin
836
    uvm_report_warning("CYCFND", $sformatf("Cycle detected for object @%0d during unpack", value.get_inst_id()), UVM_NONE);
837
    return;
838
  end
839
  value.__m_uvm_status_container.cycle_check[value] = 1;
840
 
841
  if(use_metadata == 1) begin
842
    is_non_null = m_bits[count +: 4];
843
    count+=4;
844
  end
845
 
846
  // NOTE- policy is a ~pack~ policy, not unpack policy;
847
  //       and you can't pack an object by REFERENCE
848
  if (value != null)begin
849
    if (is_non_null > 0) begin
850
      scope.down(value.get_name());
851
      value.__m_uvm_field_automation(null, UVM_UNPACK,"");
852
      value.do_unpack(this);
853
      scope.up();
854
    end
855
    else begin
856
      // TODO: help do_unpack know whether unpacked result would be null
857
      //       to avoid new'ing unnecessarily;
858
      //       this does not nullify argument; need to pass obj by ref
859
    end
860
  end
861
  else if ((is_non_null != 0) && (value == null)) begin
862
     uvm_report_error("UNPOBJ","cannot unpack into null object", UVM_NONE);
863
  end
864
  value.__m_uvm_status_container.cycle_check.delete(value);
865
 
866
endfunction
867
 
868
 
869
// unpack_real
870
// -----------
871
 
872
function real uvm_packer::unpack_real();
873
  if (enough_bits(64,"real")) begin
874
    return $bitstoreal(unpack_field_int(64));
875
  end
876
endfunction
877
 
878
 
879
// unpack_time
880
// -----------
881
 
882
function time uvm_packer::unpack_time();
883
  if (enough_bits(64,"time")) begin
884
    return unpack_field_int(64);
885
  end
886
endfunction
887
 
888
 
889
// unpack_field
890
// ------------
891
 
892
function uvm_bitstream_t uvm_packer::unpack_field(int size);
893
  unpack_field = 'b0;
894
  if (enough_bits(size,"integral")) begin
895
    count += size;
896
    for (int i=0; i
897
      if(big_endian == 1)
898
        unpack_field[i] = m_bits[count-i-1];
899
      else
900
        unpack_field[i] = m_bits[count-size+i];
901
  end
902
endfunction
903
 
904
 
905
// unpack_field_int
906
// ----------------
907
 
908
function uvm_integral_t uvm_packer::unpack_field_int(int size);
909
  unpack_field_int = 'b0;
910
  if (enough_bits(size,"integral")) begin
911
    count += size;
912
    for (int i=0; i
913
      if(big_endian == 1)
914
        unpack_field_int[i] = m_bits[count-i-1];
915
      else
916
        unpack_field_int[i] = m_bits[count-size+i];
917
  end
918
endfunction
919
 
920
// unpack_bits
921
// -------------------
922
 
923
function void uvm_packer::unpack_bits(ref bit value[], input int size = -1);
924
   if (size < 0)
925
     size = value.size();
926
 
927
   if (size > value.size()) begin
928
      `uvm_error("UVM/BASE/PACKER/BAD_SIZE",
929
                 $sformatf("unpack_bits called with size '%0d', which exceeds value.size() of '%0d'",
930
                           size,
931
                           value.size()))
932
      return;
933
   end
934
 
935
   if (enough_bits(size, "integral")) begin
936
      count += size;
937
      for (int i=0; i
938
        if (big_endian == 1)
939
          value[i] = m_bits[count-i-1];
940
        else
941
          value[i] = m_bits[count-size+i];
942
   end
943
endfunction
944
 
945
// unpack_bytes
946
// -------------------
947
 
948
function void uvm_packer::unpack_bytes(ref byte value[], input int size = -1);
949
   int max_size = value.size() * $bits(byte);
950
   if (size < 0)
951
     size = max_size;
952
 
953
   if (size > max_size) begin
954
      `uvm_error("UVM/BASE/PACKER/BAD_SIZE",
955
                 $sformatf("unpack_bytes called with size '%0d', which exceeds value size of '%0d'",
956
                           size,
957
                           value.size()))
958
      return;
959
   end
960
   else begin
961
      if (enough_bits(size, "integral")) begin
962
         count += size;
963
 
964
         for (int i=0; i
965
            if (big_endian == 1)
966
              value[ i / $bits(byte) ][ i % $bits(byte) ] = m_bits[count-i-1];
967
            else
968
              value[ i / $bits(byte) ][ i % $bits(byte) ] = m_bits[count-size+i];
969
 
970
         end
971
      end // if (enough_bits(size, "integral"))
972
   end
973
endfunction
974
 
975
// unpack_ints
976
// -------------------
977
 
978
function void uvm_packer::unpack_ints(ref int value[], input int size = -1);
979
   int max_size = value.size() * $bits(int);
980
   if (size < 0)
981
     size = max_size;
982
 
983
   if (size > max_size) begin
984
      `uvm_error("UVM/BASE/PACKER/BAD_SIZE",
985
                 $sformatf("unpack_ints called with size '%0d', which exceeds value size of '%0d'",
986
                           size,
987
                           value.size()))
988
      return;
989
   end
990
   else begin
991
      if (enough_bits(size, "integral")) begin
992
         count += size;
993
 
994
         for (int i=0; i
995
            if (big_endian == 1)
996
              value[ i / $bits(int) ][ i % $bits(int) ] = m_bits[count-i-1];
997
            else
998
              value[ i / $bits(int) ][ i % $bits(int) ] = m_bits[count-size+i];
999
         end
1000
      end
1001
   end
1002
endfunction
1003
 
1004
 
1005
// unpack_string
1006
// -------------
1007
 
1008
// If num_chars is not -1, then the user only wants to unpack a
1009
// specific number of bytes into the string.
1010
function string uvm_packer::unpack_string(int num_chars=-1);
1011
  byte b;
1012
  bit  is_null_term; // Assumes a ~null~ terminated string
1013
  int i; i=0;
1014
  if(num_chars == -1) is_null_term = 1;
1015
  else is_null_term = 0;
1016
 
1017
  while(enough_bits(8,"string") &&
1018
        ((m_bits[count+:8] != 0) || (is_null_term == 0)) &&
1019
        ((i
1020
  begin
1021
    // silly, because cannot append byte/char to string
1022
    unpack_string = {unpack_string," "};
1023
    if(big_endian == 0)
1024
      unpack_string[i] = m_bits[count +: 8];
1025
    else begin
1026
      for(int j=0; j<8; ++j)
1027
        b[7-j] = m_bits[count+j];
1028
      unpack_string[i] = b;
1029
    end
1030
    count += 8;
1031
    ++i;
1032
  end
1033
  if(enough_bits(8,"string"))
1034
    count += 8;
1035
endfunction
1036
 
1037
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.