ovm_packer.sv

Go to the documentation of this file.
00001 // $Id: a00249.html,v 1.1 2009/01/07 19:29:49 alex.marin Exp $
00002 //----------------------------------------------------------------------
00003 //   Copyright 2007-2008 Mentor Graphics Corporation
00004 //   Copyright 2007-2008 Cadence Design Systems, Inc.
00005 //   All Rights Reserved Worldwide
00006 //
00007 //   Licensed under the Apache License, Version 2.0 (the
00008 //   "License"); you may not use this file except in
00009 //   compliance with the License.  You may obtain a copy of
00010 //   the License at
00011 //
00012 //       http://www.apache.org/licenses/LICENSE-2.0
00013 //
00014 //   Unless required by applicable law or agreed to in
00015 //   writing, software distributed under the License is
00016 //   distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
00017 //   CONDITIONS OF ANY KIND, either express or implied.  See
00018 //   the License for the specific language governing
00019 //   permissions and limitations under the License.
00020 //----------------------------------------------------------------------
00021 
00022 `include "base/ovm_packer.svh"
00023 
00024 //-----------------------------------------------------------------------------
00025 //
00026 // ovm_packer
00027 //
00028 //-----------------------------------------------------------------------------
00029 
00030 // NOTE: max size limited to BITSTREAM bits parameter (default: 4096)
00031 
00032 
00033 // index_ok
00034 // --------
00035 
00036 function void ovm_packer::index_error(int index, string id, int sz);
00037     ovm_report_error("PCKIDX", 
00038         $psprintf("index %0d for get_%0s too large; valid index range is 0-%0d.",
00039                   index,id,((m_packed_size+sz-1)/sz)-1));
00040 endfunction
00041 
00042 
00043 // enough_bits
00044 // -----------
00045 
00046 function bit ovm_packer::enough_bits(int needed, string id);
00047   if ((m_packed_size - count) < needed) begin
00048     ovm_report_error("PCKSZ",
00049         $psprintf("%0d bits needed to unpack %0s, yet only %0d available.",
00050                   needed, id, (m_packed_size - count)));
00051     return 0;
00052   end
00053   return 1;
00054 endfunction
00055 
00056 
00057 // get_packed_size
00058 // ---------------
00059 
00060 function int ovm_packer::get_packed_size();
00061   return m_packed_size;
00062 endfunction
00063 
00064 
00065 // set_packed_size
00066 // ---------------
00067 
00068 function void ovm_packer::set_packed_size();
00069   m_packed_size = count;
00070   count = 0;
00071 endfunction
00072 
00073 
00074 // reset
00075 // -----
00076 
00077 function void ovm_packer::reset();
00078   count = 0;
00079   m_bits = 0;
00080   m_packed_size = 0;
00081 endfunction
00082 
00083 
00084 // get_packed_bits
00085 // ---------------
00086 
00087 function ovm_bitstream_t ovm_packer::get_packed_bits();
00088   //bits = m_bits;
00089   return m_bits;
00090 endfunction
00091 
00092 
00093 // get_bits
00094 // --------
00095 
00096 function void ovm_packer::get_bits(ref bit unsigned bits[]);
00097   bits = new[m_packed_size];
00098   for (int i=0;i<m_packed_size;i++)
00099     bits[i] = m_bits[i];
00100 endfunction
00101 
00102 
00103 // get_bytes
00104 // ---------
00105 
00106 function void ovm_packer::get_bytes(ref byte unsigned bytes[]);
00107   int sz;
00108   byte v;
00109   sz = (m_packed_size+7) / 8;
00110   bytes = new[sz];
00111   for (int i=0;i<sz;i++) begin
00112     if (i != sz-1) 
00113       v = m_bits[ i*8 +: 8 ];
00114     else
00115       v = m_bits[ i*8 +: 8 ] & ('hFF >> (m_packed_size%8));
00116     if(big_endian) begin
00117       byte tmp; tmp = v;
00118       for(int j=0; j<8; ++j) v[j] = tmp[7-j];
00119     end
00120     bytes[i] = v;
00121   end
00122 endfunction
00123 
00124 
00125 // get_ints
00126 // --------
00127 
00128 function void ovm_packer::get_ints(ref int unsigned ints[]);
00129   int sz, v;
00130   sz = (m_packed_size+31) / 32;
00131   ints = new[sz];
00132   for (int i=0;i<sz;i++) begin
00133     if (i != sz-1) 
00134       v = m_bits[ i*32 +: 32 ];
00135     else
00136       v = m_bits[ i*32 +: 32 ] & ('hFFFFFFFF >> (m_packed_size%32));
00137     if(big_endian) begin
00138       int tmp; tmp = v;
00139       for(int j=0; j<32; ++j) v[j] = tmp[31-j];
00140     end
00141     ints[i] = v;
00142   end
00143 endfunction
00144 
00145 
00146 // put_bits
00147 // --------
00148 
00149 function void ovm_packer::put_bits (ref bit bitstream []);
00150 
00151   int bit_size;
00152 
00153   bit_size = bitstream.size();
00154 
00155   if(big_endian)
00156     for (int i=bit_size-1;i>=0;i--)
00157       m_bits[i] = bitstream[i];
00158   else
00159     for (int i=0;i<bit_size;i++)
00160       m_bits[i] = bitstream[i];
00161 
00162   m_packed_size = bit_size;
00163   count = 0;
00164  
00165 endfunction
00166 
00167 // put_bytes
00168 // ---------
00169 
00170 function void ovm_packer::put_bytes (ref byte unsigned bytestream []);
00171 
00172   int byte_size;
00173   int index;
00174   byte unsigned b;
00175 
00176   byte_size = bytestream.size();
00177   index = 0;
00178   for (int i=0;i<byte_size;i++) begin
00179     b = bytestream[i];
00180     if(big_endian) begin
00181       byte unsigned tb; tb = b;
00182       for(int j=0;j<8;++j) b[j] = tb[7-j];
00183     end
00184     m_bits[index +:8] = b;
00185     index += 8;
00186   end
00187 
00188   m_packed_size = byte_size*8;
00189   count = 0;
00190 endfunction
00191 
00192 
00193 // put_ints
00194 // --------
00195 
00196 function void ovm_packer::put_ints (ref int unsigned intstream []);
00197 
00198   int int_size;
00199   int index;
00200   int unsigned v;
00201 
00202   int_size = intstream.size();
00203 
00204   index = 0;
00205   for (int i=0;i<int_size;i++) begin
00206     v = intstream[i];
00207     if(big_endian) begin
00208       int unsigned tv; tv = v;
00209       for(int j=0;j<32;++j) v[j] = tv[31-j];
00210     end
00211     m_bits[index +:32] = v;
00212     index += 32;
00213   end
00214 
00215   m_packed_size = int_size*32;
00216   count = 0;
00217 endfunction
00218 
00219 
00220 
00221 
00222 // get_bit
00223 // -------
00224 
00225 function bit unsigned ovm_packer::get_bit(int unsigned index);
00226   if (index >= m_packed_size)
00227     index_error(index, "bit",1);
00228   return m_bits[index];
00229 endfunction
00230 
00231 
00232 // get_byte
00233 // --------
00234 
00235 function byte unsigned ovm_packer::get_byte(int unsigned index);
00236   if (index >= (m_packed_size+7)/8)
00237     index_error(index, "byte",8);
00238   return m_bits[index*8 +: 8];
00239 endfunction
00240 
00241 
00242 // get_int
00243 // -------
00244 
00245 function int unsigned ovm_packer::get_int(int unsigned index);
00246   if (index >= (m_packed_size+31)/32)
00247     index_error(index, "int",32);
00248   return m_bits[(index*32) +: 32];
00249 endfunction
00250 
00251 
00252 // PACK
00253 
00254 
00255 // pack_object
00256 // ---------
00257 
00258 function void ovm_packer::pack_object(ovm_object value);
00259 
00260   if(scope.in_hierarchy(value)) begin
00261     `ifdef INCA
00262     ovm_report_warning("CYCFND", $psprintf("Cycle detected for object @%0d during pack", this));
00263     `else
00264     ovm_report_warning("CYCFND", $psprintf("Cycle detected during pack"));
00265     `endif
00266     return;
00267   end
00268 
00269   if((policy != OVM_REFERENCE) && (value != null) ) begin
00270       if(use_metadata == 1) begin
00271         m_bits[count +: 4] = 1;
00272         count += 4; // to better debug when display packed bits in hexidecimal
00273       end
00274       scope.down(value.get_name(), value);
00275       value.m_field_automation(null, OVM_PACK,"");
00276       value.do_pack(this);
00277       scope.up(value);
00278   end
00279   else if(use_metadata == 1) begin
00280     m_bits[count +: 4] = 0;
00281     count += 4;
00282   end
00283 endfunction
00284 
00285   
00286 // pack_real
00287 // ---------
00288 
00289 function void ovm_packer::pack_real(real value);
00290   pack_field_int($realtobits(value), 64);
00291 endfunction
00292   
00293 
00294 // pack_time
00295 // ---------
00296 
00297 function void ovm_packer::pack_time(time value);
00298   pack_field_int(value, 64);
00299   //m_bits[count +: 64] = value; this overwrites endian adjustments
00300 endfunction
00301   
00302 
00303 // pack_field
00304 // ----------
00305 
00306 function void ovm_packer::pack_field(ovm_bitstream_t value, int size);
00307   for (int i=0; i<size; i++)
00308     if(big_endian == 1)
00309       m_bits[count+i] = value[size-1-i];
00310     else
00311       m_bits[count+i] = value[i];
00312   count += size;
00313 endfunction
00314   
00315 
00316 // pack_field_int
00317 // --------------
00318 
00319 function void ovm_packer::pack_field_int(logic [63:0] value, int size);
00320   for (int i=0; i<size; i++)
00321     if(big_endian == 1)
00322       m_bits[count+i] = value[size-1-i];
00323     else
00324       m_bits[count+i] = value[i];
00325   count += size;
00326 endfunction
00327   
00328 
00329 // pack_string
00330 // -----------
00331 
00332 function void ovm_packer::pack_string(string value);
00333   byte b;
00334   foreach (value[index]) begin
00335     if(big_endian == 0)
00336       m_bits[count +: 8] = value[index];
00337     else begin
00338       b = value[index];
00339       for(int i=0; i<8; ++i)
00340         m_bits[count+i] = b[7-i];
00341     end 
00342     count += 8;
00343   end
00344   if(use_metadata == 1) begin
00345     m_bits[count +: 8] = 0;
00346     count += 8;
00347   end
00348 endfunction 
00349 
00350 
00351 // UNPACK
00352 
00353 
00354 // is_null
00355 // -------
00356 
00357 function bit ovm_packer::is_null();
00358   return (m_bits[count+:4]==0);
00359 endfunction
00360 
00361 // unpack_object
00362 // -------------
00363 
00364 function void ovm_packer::unpack_object_ext(inout ovm_object value);
00365   unpack_object(value);
00366 endfunction
00367 
00368 function void ovm_packer::unpack_object(ovm_object value);
00369 
00370   byte is_non_null; is_non_null = 1;
00371 
00372   if(scope.in_hierarchy(value)) begin
00373     `ifdef INCA
00374     ovm_report_warning("CYCFND", $psprintf("Cycle detected for object @%0d during unpack", this));
00375     `else
00376     ovm_report_warning("CYCFND", $psprintf("Cycle detected during unpack", this));
00377     `endif
00378     return;
00379   end
00380 
00381   if(use_metadata == 1) begin
00382     is_non_null = m_bits[count +: 4];
00383     count+=4;
00384   end
00385 
00386   // NOTE: policy is a _pack_ policy, not unpack policy;
00387   //       and you can't pack an object by REFERENCE
00388   if (value != null)begin
00389     if (is_non_null > 0) begin
00390       scope.down(value.get_name(), value);
00391       value.m_field_automation(null, OVM_UNPACK,"");
00392       value.do_unpack(this);
00393       scope.up(value);
00394     end
00395     else begin
00396       // TODO: help do_unpack know whether unpacked result would be null
00397       //       to avoid new'ing unnecessarily;
00398       //       this does not nullify argument; need to pass obj by ref
00399     end
00400   end
00401   else if ((is_non_null != 0) && (value == null)) begin
00402      ovm_report_error("UNPOBJ","can not unpack into null object");
00403      return;
00404   end
00405 
00406 endfunction
00407 
00408   
00409 // unpack_real
00410 // -----------
00411 
00412 function real ovm_packer::unpack_real();
00413   if (enough_bits(64,"real")) begin
00414     return $bitstoreal(unpack_field_int(64));
00415   end
00416 endfunction
00417   
00418 
00419 // unpack_time
00420 // -----------
00421 
00422 function time ovm_packer::unpack_time();
00423   if (enough_bits(64,"time")) begin
00424     return unpack_field_int(64);
00425   end
00426 endfunction
00427   
00428 
00429 // unpack_field
00430 // ------------
00431 
00432 function ovm_bitstream_t ovm_packer::unpack_field(int size);
00433   unpack_field = 'b0;
00434   if (enough_bits(size,"integral")) begin
00435     count += size;
00436     for (int i=0; i<size; i++)
00437       if(big_endian == 1)
00438         unpack_field[i] = m_bits[count-i-1];
00439       else
00440         unpack_field[i] = m_bits[count-size+i];
00441   end
00442 endfunction
00443   
00444 
00445 // unpack_field_int
00446 // ----------------
00447 
00448 function logic[63:0] ovm_packer::unpack_field_int(int size);
00449   unpack_field_int = 'b0;
00450   if (enough_bits(size,"integral")) begin
00451     count += size;
00452     for (int i=0; i<size; i++)
00453       if(big_endian == 1)
00454         unpack_field_int[i] = m_bits[count-i-1];
00455       else
00456         unpack_field_int[i] = m_bits[count-size+i];
00457   end
00458 endfunction
00459   
00460 
00461 // unpack_string
00462 // -------------
00463 
00464 // If num_chars is not -1, then the user only wants to unpack a
00465 // specific number of bytes into the string.
00466 function string ovm_packer::unpack_string(int num_chars=-1);
00467   byte b;
00468   bit  is_null_term; // Assumes a null terminated string
00469   int i; i=0;
00470   if(num_chars == -1) is_null_term = 1;
00471   else is_null_term = 0;
00472 
00473   while(enough_bits(8,"string") && 
00474         ((m_bits[count+:8] != 0) || (is_null_term == 0)) &&
00475         ((i<num_chars)||(is_null_term==1)) )
00476   begin
00477     // silly, because can not append byte/char to string
00478     unpack_string = {unpack_string," "};
00479     if(big_endian == 0)
00480       unpack_string[i] = m_bits[count +: 8];
00481     else begin
00482       for(int j=0; j<8; ++j)
00483         b[7-j] = m_bits[count+j];
00484       unpack_string[i] = b;
00485     end 
00486     count += 8;
00487     ++i;
00488   end
00489   if(enough_bits(8,"string"))
00490     count += 8;
00491 endfunction 
00492 
00493 
00494 

Intelligent Design Verification
Intelligent Design Verification
Project: OVM, Revision: 2.0.1
Copyright (c) 2008 Intelligent Design Verification.
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:
http://www.intelligentdv.com/licenses/fdl.txt
doxygen
Doxygen Version: 1.5.5
Wed Jan 7 19:27:18 2009
Find a documentation bug? Report bugs to: bugs.intelligentdv.com Project: DoxygenFilterSV