ovm_misc.sv

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

Intelligent Design Verification
Intelligent Design Verification
Project: OVM, Revision: 1.1.0
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.4.6
Mon Sep 29 14:20:12 2008
Find a documentation bug? Report bugs to: bugs.intelligentdv.com Project: DoxygenFilterSV