ovm_misc.sv

Go to the documentation of this file.
00001 // $Id: a00241.html,v 1.1 2009/01/07 19:29:48 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_misc.svh"
00023 
00024 // Create a seed which is based off of the ius seed which can be used to seed
00025 // srandom processes but will change if the command line seed setting is 
00026 // changed.
00027 
00028 int unsigned ovm_global_random_seed = $urandom;
00029 
00030 // This map is a seed map that can be used to update seeds. The update
00031 // is done automatically by the seed hashing routine. The seed_table_lookup
00032 // uses an instance name lookup and the seed_table inside a given map
00033 // uses a type name for the lookup.
00034 
00035 class ovm_seed_map;
00036   int unsigned seed_table [string];
00037 endclass
00038 ovm_seed_map ovm_random_seed_table_lookup [string];
00039 
00040 //
00041 // ovm_instance_scope;
00042 //
00043 // A function that returns the scope that the urm library lives in, either
00044 // an instance, a module, or a package.
00045 
00046 function string ovm_instance_scope();
00047   byte c;
00048   int pos;
00049   //first time through the scope is null and we need to calculate, afterwards it
00050   //is correctly set.
00051 
00052   if(ovm_instance_scope != "") 
00053     return ovm_instance_scope;
00054 
00055   $swrite(ovm_instance_scope, "%m");
00056   //remove the extraneous .ovm_instance_scope piece or ::ovm_instance_scope
00057   pos = ovm_instance_scope.len()-1;
00058   c = ovm_instance_scope[pos];
00059   while(pos && (c != ".") && (c != ":")) 
00060     c = ovm_instance_scope[--pos];
00061   assert(pos != 0);
00062   ovm_instance_scope = ovm_instance_scope.substr(0,pos);
00063 endfunction
00064 
00065 
00066 //
00067 // ovm_oneway_hash
00068 //
00069 // A one-way hash function that is useful for creating srandom seeds. An
00070 // unsigned int value is generated from the string input. An initial seed can
00071 // be used to seed the hash, if not supplied the ovm_global_random_seed 
00072 // value is used. Uses a CRC like functionality to minimize collisions.
00073 
00074 parameter OVM_STR_CRC_POLYNOMIAL = 32'h04c11db6;
00075 function int unsigned ovm_oneway_hash ( string string_in, int unsigned seed=0 );
00076   bit          msb;
00077   bit [7:0]    current_byte;
00078   bit [31:0]   crc1;
00079       
00080   if(!seed) seed = ovm_global_random_seed;
00081   ovm_oneway_hash = seed;
00082 
00083   crc1 = 32'hffffffff;
00084   for (int _byte=0; _byte < string_in.len(); _byte++) begin
00085      current_byte = string_in[_byte];
00086      if (current_byte == 0) break;
00087      for (int _bit=0; _bit < 8; _bit++) begin
00088         msb = crc1[31];
00089         crc1 <<= 1;
00090         if (msb ^ current_byte[_bit]) begin
00091            crc1 ^=  OVM_STR_CRC_POLYNOMIAL;
00092            crc1[0] = 1;
00093         end
00094      end
00095   end
00096   ovm_oneway_hash += ~{crc1[7:0], crc1[15:8], crc1[23:16], crc1[31:24]};
00097 
00098 endfunction
00099 
00100 //
00101 // ovm_create_random_seed
00102 //
00103 // Creates a random seed and updates the seed map so that if the same string
00104 // is used again, a new value will be generated. The inst_id is used to hash
00105 // by instance name and get a map of type name hashes which the type_id uses
00106 // for it's lookup.
00107 
00108 function int unsigned ovm_create_random_seed ( string type_id, string inst_id="" );
00109   ovm_seed_map seed_map;
00110 
00111   if(inst_id == "")
00112     inst_id = "__global__";
00113 
00114   if(!ovm_random_seed_table_lookup.exists(inst_id))
00115     ovm_random_seed_table_lookup[inst_id] = new;
00116   seed_map = ovm_random_seed_table_lookup[inst_id];
00117 
00118   type_id = {ovm_instance_scope(),type_id};
00119 
00120   if(!seed_map.seed_table.exists(type_id)) begin
00121     seed_map.seed_table[type_id] = ovm_oneway_hash ({type_id,"::",inst_id}, ovm_global_random_seed);
00122   end
00123 
00124   //can't just increment, otherwise too much chance for collision, so 
00125   //randomize the seed using the last seed as the seed value. Check if
00126   //the seed has been used before and if so increment it.
00127   seed_map.seed_table[type_id] = $urandom(seed_map.seed_table[type_id]); 
00128 
00129   return seed_map.seed_table[type_id];
00130 endfunction
00131 
00132 
00133 //----------------------------------------------------------------------------
00134 //
00135 // CLASS: ovm_scope_stack
00136 //
00137 //----------------------------------------------------------------------------
00138 
00139 // depth
00140 // -----
00141 
00142 function int ovm_scope_stack::depth();
00143   return m_stack.size();
00144 endfunction
00145 
00146 
00147 // scope
00148 // -----
00149 
00150 function string ovm_scope_stack::get();
00151   return m_scope;
00152 endfunction
00153 
00154 
00155 // scope_arg
00156 // ---------
00157 
00158 function string ovm_scope_stack::get_arg();
00159   return m_scope_arg;
00160 endfunction
00161 
00162 
00163 // set_scope
00164 // ---------
00165 
00166 function void ovm_scope_stack::set (string s, ovm_object obj);
00167   ovm_void v; v=obj;
00168   m_scope_arg = s;
00169   m_scope = s;
00170 
00171   // When no arg delete() is supported for queues, can just call m_stack.delete().
00172   while(m_stack.size()) void'(m_stack.pop_front());
00173   
00174   m_stack.push_back(v);
00175   if(v!=null) begin
00176    m_object_map[v] = 1;
00177   end
00178 endfunction
00179 
00180 
00181 // down
00182 // ----
00183 
00184 function void ovm_scope_stack::down (string s, ovm_object obj);
00185   ovm_void v; v=obj;
00186   if(m_scope == "")
00187     m_scope = s;
00188   else if(s.len()) begin
00189     if(s[0] == "[")
00190       m_scope = {m_scope,s};
00191     else
00192       m_scope = {m_scope,".",s};
00193   end
00194   m_scope_arg=m_scope;
00195   if(v!=null) begin
00196     m_object_map[v] = 1;
00197   end
00198   m_stack.push_back(v);
00199 endfunction
00200 
00201 
00202 // down_element
00203 // ------------
00204 
00205 function void ovm_scope_stack::down_element (int element, ovm_object obj);
00206   string tmp_value_str;
00207   ovm_void v; v=obj;
00208   tmp_value_str.itoa(element);
00209 
00210   m_scope = {m_scope, "[", tmp_value_str, "]"};
00211   m_scope_arg=m_scope;
00212   m_stack.push_back(v);
00213   if(v!=null)
00214     m_object_map[v] = 1;
00215 endfunction
00216 
00217 // current
00218 // -------
00219 
00220 function ovm_object ovm_scope_stack::current ();
00221   ovm_void v;
00222   if(m_stack.size()) begin
00223     v = m_stack[m_stack.size()-1];
00224     $cast(current, v);
00225   end
00226   else
00227     return null;
00228 endfunction
00229 
00230 // up
00231 // --
00232 
00233 function void ovm_scope_stack::up (ovm_object obj, byte separator =".");
00234   string tmp_value_str;
00235   int last_dot;
00236   if(!m_scope.len()) begin
00237     // When no arg delete() is supported for associative arrays, can just call 
00238     // m_object_map.delete().
00239     foreach(m_object_map[i]) m_object_map.delete(i);
00240     // When no arg delete() is supported for queues, can just call m_stack.delete().
00241     while(m_stack.size()) void'(m_stack.pop_front());
00242     return;
00243   end
00244   //Find the last scope separator
00245   for(last_dot = m_scope.len()-1; last_dot != 0; --last_dot)
00246     if(m_scope[last_dot] == separator) break;
00247 
00248   if(!last_dot)
00249     m_scope = "";
00250 
00251   tmp_value_str = "";
00252   for(int i=0; i<last_dot; ++i) begin
00253     tmp_value_str = {tmp_value_str, " "};
00254     tmp_value_str[i] = m_scope[i];
00255   end
00256   m_scope = tmp_value_str;
00257   void'(m_stack.pop_back());
00258   if(m_stack.size() == 0)
00259     m_scope = "";
00260 
00261   m_scope_arg = m_scope;
00262   m_object_map.delete(obj);
00263 endfunction
00264 
00265 
00266 // up_element
00267 // ----------
00268 
00269 function void ovm_scope_stack::up_element (ovm_object obj);
00270   up(obj, "[");
00271 endfunction
00272 
00273 
00274 // set_arg
00275 // -------
00276 
00277 function void ovm_scope_stack::set_arg (string arg);
00278   if(m_scope == "")
00279     m_scope_arg = arg;
00280   else if(arg[0] == "[")
00281     m_scope_arg = {m_scope, arg};
00282   else 
00283     m_scope_arg = {m_scope, ".", arg};
00284 endfunction
00285 
00286 
00287 // set_arg_element
00288 // ---------------
00289 
00290 function void ovm_scope_stack::set_arg_element (string arg, int ele);
00291   string tmp_value_str;
00292   tmp_value_str.itoa(ele);
00293   if(m_scope == "")
00294     m_scope_arg = {arg, "[", tmp_value_str, "]"};
00295   else
00296     m_scope_arg = {m_scope, ".", arg, "[", tmp_value_str, "]"};
00297 endfunction
00298 
00299 function void ovm_scope_stack::unset_arg (string arg);
00300   int s, sa; 
00301   s=m_scope_arg.len();
00302   sa=arg.len();
00303   if(m_scope_arg[s-1] == "]" && arg[sa-1] != "]") 
00304     s--;
00305   if(s<sa) return;
00306   while(sa>=0) begin
00307     if(m_scope_arg[s] != arg[sa]) return;
00308     s--; sa--;
00309   end
00310   if(m_scope_arg[s] == ".") 
00311     s--;
00312   else if(m_scope_arg[s] == "[" && m_scope_arg[m_scope_arg.len()-1]=="]")
00313     s--;
00314   m_scope_arg = m_scope_arg.substr(0,s);
00315 endfunction
00316 
00317 // in_hierarchy
00318 // ------------
00319 
00320 function bit ovm_scope_stack::in_hierarchy (ovm_object obj);
00321   ovm_void v; v = obj;
00322   if (!m_object_map.exists(v)) return 0;
00323   return m_object_map[v];
00324 endfunction
00325 
00326 // ovm_leaf_scope
00327 // --------------
00328 function string ovm_leaf_scope (string full_name, byte scope_separator = ".");
00329   byte bracket_match;
00330   int  pos;
00331   int  bmatches;
00332 
00333   bmatches = 0;
00334   case(scope_separator)
00335     "[": bracket_match = "]";
00336     "(": bracket_match = ")";
00337     "<": bracket_match = ">";
00338     "{": bracket_match = "}";
00339     default: bracket_match = "";
00340   endcase
00341 
00342   //Only use bracket matching if the input string has the end match
00343   if(bracket_match != "" && bracket_match != full_name[full_name.len()-1])
00344     bracket_match = "";
00345 
00346   for(pos=full_name.len()-1; pos!=0; --pos) begin
00347     if(full_name[pos] == bracket_match) bmatches++;
00348     else if(full_name[pos] == scope_separator) begin
00349       bmatches--;
00350       if(!bmatches || (bracket_match == "")) break;
00351     end
00352   end
00353   if(pos) begin
00354     if(scope_separator != ".") pos--;
00355     ovm_leaf_scope = full_name.substr(pos+1,full_name.len()-1);
00356   end
00357   else begin
00358     ovm_leaf_scope = full_name;
00359   end
00360 endfunction
00361 
00362 
00363 // OVM does not provide any kind of recording functionality, but provides hooks
00364 // when a component/object may need such a hook.
00365 
00366 
00367 `ifndef OVM_RECORD_INTERFACE
00368 `define OVM_RECORD_INTERFACE
00369 
00370 // ovm_create_fiber
00371 // ----------------
00372 
00373 function integer ovm_create_fiber (string name,
00374                                    string t,
00375                                    string scope);
00376   return 0;
00377 endfunction
00378 
00379 // ovm_set_index_attribute_by_name
00380 // -------------------------------
00381 
00382 function void ovm_set_index_attribute_by_name (integer txh,
00383                                          string nm,
00384                                          int index,
00385                                          logic [1023:0] value,
00386                                          string radix,
00387                                          integer numbits=32);
00388   return;
00389 endfunction
00390 
00391 
00392 // ovm_set_attribute_by_name
00393 // -------------------------
00394 
00395 function void ovm_set_attribute_by_name (integer txh,
00396                                          string nm,
00397                                          logic [1023:0] value,
00398                                          string radix,
00399                                          integer numbits=0);
00400   return;
00401 endfunction
00402 
00403 
00404 // ovm_check_handle_kind
00405 // ---------------------
00406 
00407 function integer ovm_check_handle_kind (string htype, integer handle);
00408   return 1;
00409 endfunction
00410 
00411 
00412 // ovm_begin_transaction
00413 // ---------------
00414 
00415 function integer ovm_begin_transaction(string txtype,
00416                                  integer stream,
00417                                  string nm
00418                                  , string label="",
00419                                  string desc="",
00420                                  time begin_time=0
00421                                  );
00422 
00423   return 0;
00424 endfunction
00425 
00426 
00427 // ovm_end_transaction
00428 // -------------------
00429 
00430 function void ovm_end_transaction (integer handle
00431                                  , time end_time=0
00432 );
00433   return;
00434 endfunction
00435 
00436 
00437 // ovm_link_transaction
00438 // --------------------
00439 
00440 function void ovm_link_transaction(integer h1, integer h2,
00441                                    string relation="");
00442   return;
00443 endfunction
00444 
00445 
00446 
00447 // ovm_free_transaction_handle
00448 // ---------------------------
00449 
00450 function void ovm_free_transaction_handle(integer handle);
00451   return;
00452 endfunction
00453 
00454 `endif // OVM_RECORD_INTERFACE
00455 
00456 // The following functions check to see if a string is representing an array
00457 // index, and if so, what the index is.
00458 
00459 function int ovm_get_array_index_int(string arg, output bit is_wildcard);
00460   int i;
00461   ovm_get_array_index_int = 0;
00462   is_wildcard = 1;
00463   i = arg.len() - 1;
00464   if(arg[i] == "]")
00465     while(i > 0 && (arg[i] != "[")) begin
00466       --i;
00467       if((arg[i] == "*") || (arg[i] == "?")) i=0;
00468       else if((arg[i] < "0") || (arg[i] > "9") && (arg[i] != "[")) begin
00469         ovm_get_array_index_int = -1; //illegal integral index
00470         i=0;
00471       end
00472     end
00473   else begin
00474     is_wildcard = 0;
00475     return 0;
00476   end
00477 
00478   if(i>0) begin
00479     arg = arg.substr(i+1, arg.len()-2);
00480     ovm_get_array_index_int = arg.atoi(); 
00481     is_wildcard = 0;
00482   end
00483 endfunction 
00484   
00485 function string ovm_get_array_index_string(string arg, output bit is_wildcard);
00486   int i;
00487   ovm_get_array_index_string = "";
00488   is_wildcard = 1;
00489   i = arg.len() - 1;
00490   if(arg[i] == "]")
00491     while(i > 0 && (arg[i] != "[")) begin
00492       if((arg[i] == "*") || (arg[i] == "?")) i=0;
00493       --i;
00494     end
00495   if(i>0) begin
00496     ovm_get_array_index_string = arg.substr(i+1, arg.len()-2);
00497     is_wildcard = 0;
00498   end
00499 endfunction
00500 
00501 function bit ovm_is_array(string arg);
00502   int last;
00503   ovm_is_array = 0;
00504   last = arg.len()-1;
00505   if(arg[last] == "]") ovm_is_array = 1;
00506 endfunction
00507 
00508 

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