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 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 Version: 1.4.6 Mon Sep 29 14:20:12 2008 |