Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members  

scv_random.cpp

Go to the documentation of this file.
00001 //  -*- C++ -*- <this line is for emacs to recognize it as C++ code>
00002 /*****************************************************************************
00003 
00004   The following code is derived, directly or indirectly, from the SystemC
00005   source code Copyright (c) 1996-2002 by all Contributors.
00006   All Rights reserved.
00007 
00008   The contents of this file are subject to the restrictions and limitations
00009   set forth in the SystemC Open Source License Version 2.3 (the "License");
00010   You may not use this file except in compliance with such restrictions and
00011   limitations. You may obtain instructions on how to receive a copy of the
00012   License at http://www.systemc.org/. Software distributed by Contributors
00013   under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
00014   ANY KIND, either express or implied. See the License for the specific
00015   language governing rights and limitations under the License.
00016 
00017  *****************************************************************************/
00018 
00019 /*****************************************************************************
00020 
00021   scv_random.cpp -- The public interface for unsigned random stream and seed
00022   file manipulation
00023 
00024   Original Authors (Cadence Design Systems, Inc):
00025   Norris Ip, Dean Shea, John Rose, Jasvinder Singh, William Paulsen,
00026   John Pierce, Rachida Kebichi, Ted Elkind, David Bailey
00027   2002-09-23
00028 
00029  *****************************************************************************/
00030 
00031 /*****************************************************************************
00032 
00033   MODIFICATION LOG - modifiers, enter your name, affiliation, date and
00034   changes you are making here.
00035 
00036       Name, Affiliation, Date:
00037   Description of Modification:
00038 
00039  *****************************************************************************/
00040 
00041 
00042 #include "scv/scv_util.h"
00043 #include "scv/scv_random.h"
00044 #include "scv/scv_report.h"
00045 
00046 #include <stdio.h>  
00047 #include <stdlib.h> 
00048 
00049 
00050 #ifdef _MSC_VER
00051 inline int rand_r(unsigned int *) { return rand(); }
00052 #endif
00053 
00054 
00055 //#define OLD_SEED_GENERATION_SEMANTICS
00056 //#define DONT_UNIQUIFY_NAMES
00057 
00059 // Class : scv_random_error
00060 //   - Error message interface for the scv_random class
00061 //   - static methods to print respective messages
00063 
00064 class scv_random_error {
00065 public:
00066   static void missing_algorithm(const string algorithm_name) {
00067     _scv_message::message(_scv_message::RANDOM_NULL_ALGORITHM,algorithm_name.c_str());
00068   }
00069 
00070   static void out_of_order_seed(const string instance_name_p, 
00071     const string fileNameP) 
00072   { 
00073     if (instance_name_p =="") {
00074       _scv_message::message(_scv_message::RANDOM_OUT_OF_ORDER_SEED,
00075         "<anonymous>",fileNameP.c_str());
00076     } else  {
00077       _scv_message::message(_scv_message::RANDOM_OUT_OF_ORDER_SEED,
00078         instance_name_p.c_str(),fileNameP.c_str());
00079     }
00080   }
00081   static void cannot_match_seed(const string instance_name, 
00082     const string fileName) 
00083   {
00084     if (instance_name == "") {
00085       _scv_message::message(_scv_message::RANDOM_CANNOT_MATCH_SEED,
00086         "<anonymous>",fileName.c_str());
00087     } else  {
00088       _scv_message::message(_scv_message::RANDOM_CANNOT_MATCH_SEED,
00089         instance_name.c_str(),fileName.c_str());
00090     }
00091   }
00092   static void retrieving_with_same_name(const string instance_name, 
00093     const string fileName) 
00094   {
00095     if (instance_name == "") {
00096       _scv_message::message(_scv_message::RANDOM_RETRIEVING_SEED_WITH_SAME_NAME,
00097              "<anonymous>",fileName.c_str());
00098     } else {
00099       _scv_message::message(_scv_message::RANDOM_RETRIEVING_SEED_WITH_SAME_NAME,
00100              instance_name.c_str(), fileName.c_str());
00101     }
00102   }
00103   static void storing_with_same_name(const string instance_name, 
00104     const string fileName) 
00105   {
00106     if (instance_name == "") {
00107       _scv_message::message(_scv_message::RANDOM_STORING_SEED_WITH_SAME_NAME,
00108              "<anonymous>",fileName.c_str());
00109     } else  {
00110       _scv_message::message(_scv_message::RANDOM_STORING_SEED_WITH_SAME_NAME,
00111              instance_name.c_str(), fileName.c_str());
00112     }
00113   }
00114   static void seed_monitor_not_off(const string fileName) 
00115   {
00116     _scv_message::message(_scv_message::RANDOM_SEED_MONITOR_NOT_OFF,
00117            fileName.c_str());
00118   }
00119   static void seed_not_exhausted(const string fileName) {
00120     _scv_message::message(_scv_message::RANDOM_SEED_NOT_EXHAUSTED,
00121            fileName.c_str());
00122   }
00123   static void cannot_open_seed_file(const string fileName) {
00124     _scv_message::message(_scv_message::RANDOM_CANNOT_OPEN_SEED_FILE,
00125             fileName.c_str());
00126   }
00127 };
00128 
00130 // Class : _scv_random_impl
00131 //   - class encapsulating implementation details of scv_random 
00132 //   - 
00134 
00135 #ifdef OLD_SEED_GENERATION_SEMANTICS
00136 static scv_random * s_seed_generator = NULL;
00137 #endif
00138 
00139 static bool s_retrieve = false;
00140 static void retrieve_seed(const string & name, unsigned long long * seed); 
00141 static unsigned long long _scv_generate_seed(const string& name);
00142 static void _scv_update_current_thread_info(const string& name);
00143 static inline unsigned int _scv_jrand48(unsigned short next[3]); 
00144 
00145 static string s_current_thread_name;
00146 static char s_current_inst_num[64];
00147 static int s_inst_num;
00148 
00149 static string _scv_get_unique_name(const string & name);
00150 static string _scv_extract_name(const char * str); 
00151 
00152 
00153 class _scv_random_impl {
00154 public:
00155   static int debug;
00156   scv_random::value_generation_algorithm _alg_type;
00157   unsigned long long _seed;
00158   scv_random::alg_func _algorithm;
00159   union {
00160     unsigned long long _next;
00161     unsigned int _rand_next;
00162     unsigned short _next48[3];
00163   } u ;
00164 
00165   _scv_random_impl(const string name,
00166        unsigned long long seed,
00167        scv_random::alg_func algorithm,
00168        scv_random::value_generation_algorithm alg_type) :
00169          _alg_type(alg_type) {
00170 
00171     // generate a seed regardless of whether a seed is 
00172     // to be retrieved or not,
00173     // for better predictability even when there is problem
00174     // in the seed file.
00175 
00176 
00177     _scv_update_current_thread_info(name);
00178 
00179     if (seed == 0) {
00180 #ifdef OLD_SEED_GENERATION_SEMANTICS
00181       if (!s_seed_generator) scv_random::set_global_seed();
00182 #endif
00183       _seed = _scv_generate_seed(name);
00184     } else {
00185       _seed = seed;
00186     }
00187 
00188     if (s_retrieve) retrieve_seed(_scv_get_unique_name(name), &_seed);
00189 
00190     _algorithm = algorithm;
00191     if (_algorithm) {
00192       u._next = _seed;
00193     } else if (_alg_type == scv_random::RAND48) {
00194       u._next48[0] = (unsigned short)(_seed >> 16);
00195       u._next48[1] = (unsigned short)(_seed & 0xffff);
00196       u._next48[2] = 0x330E;
00197     } else if (_alg_type == scv_random::RAND ||
00198                _alg_type == scv_random::RAND32) {
00199       u._rand_next = (unsigned int)_seed;
00200     } else {
00201       _scv_message::message(_scv_message::INTERNAL_ERROR, " unknown _alg_type ");
00202     }
00203   }
00204   ~_scv_random_impl() {}
00205 
00206   unsigned int next() {
00207     if (_algorithm) {
00208       return _algorithm(u._next);
00209     } else if (_alg_type == scv_random::RAND48) {
00210       return _scv_jrand48(u._next48);
00211     } else if (_alg_type == scv_random::RAND) {
00212       return rand_r(&u._rand_next);
00213     } else if (_alg_type == scv_random::RAND32) {
00214 #ifdef LINUX_SOURCE
00215       return rand_r(&u._rand_next);
00216 #else
00217       // RAND_MAX on SUN/HP is 32767, so still will not be generating
00218       // negative values for signed types and also the 16th and 32nd
00219       // bits will be 0.
00220       unsigned int val = rand_r(&u._rand_next);
00221       val |= (rand_r(&u._rand_next) << 16);
00222       return val;
00223 #endif
00224     } else {
00225       // should never happen
00226       return 0;
00227     }
00228   }
00229 
00230   unsigned int testNext() {
00231     if (_algorithm) {
00232       unsigned long long tmp = u._next; 
00233       return _algorithm(tmp);
00234     } else if (_alg_type == scv_random::RAND48) {
00235       unsigned short tmp[3];
00236       tmp[0] = u._next48[0]; 
00237       tmp[1] = u._next48[1]; 
00238       tmp[2] = u._next48[2];
00239       return _scv_jrand48(tmp);
00240     } else if (_alg_type == scv_random::RAND) {
00241       return rand_r(&u._rand_next);
00242     } else {
00243       // should never happen
00244       return 0;
00245     }
00246   }
00247   static int get_debug(void) {
00248     return debug;
00249   }
00250   static void set_debug(int dbg) {
00251     if ( debug == dbg ) return;
00252     debug = dbg;
00253     scv_debug::set_facility_level(scv_debug::RANDOMIZATION, dbg);
00254   }
00255 };
00256 
00257 int _scv_random_impl::debug = scv_debug::INITIAL_DEBUG_LEVEL;
00258 
00260 // Class: scv_random
00261 //   - Implementation of scv_random interface
00262 //   - Generate multiple independent unsigned random streams
00263 //   - seed management for maintaining reproducibility 
00264 //     across various simulation runs and even kernel
00265 //     implementations. Thread ordering is one of the 
00266 //   - Explicit seed management with storage and retrieval 
00267 //     from seed registry 
00269 
00270 unsigned long long scv_random::global_seed = 1;
00271 
00272 scv_random::value_generation_algorithm scv_random::global_alg_type = scv_random::RAND48;
00273 
00274 //---------------------------------------------
00275 // global configuration on algorithm and seed
00276 //---------------------------------------------
00277 static scv_random::alg_func s_algorithm = NULL;
00278 extern unsigned long long _scv_default_global_init_seed(
00279   unsigned long job_number = 0);
00280 extern unsigned long long _scv_get_seed_from_name(const char *, unsigned);
00281 
00282 static void _scv_set_algorithm(scv_random::value_generation_algorithm alg,
00283   scv_random::alg_func custom_alg, scv_random::alg_func * scv_be_set,
00284   const string & algorithm_name) ;
00285 
00286 void scv_random::set_global_seed(unsigned long long seed) 
00287 {
00288 #ifdef OLD_SEED_GENERATION_SEMANTICS
00289   if (s_seed_generator) {
00290     delete s_seed_generator;
00291     s_seed_generator = NULL;   
00292   }
00293   if (seed==0) seed = _scv_default_global_init_seed();
00294 #endif
00295 
00296   global_seed = seed;
00297 
00298 #ifdef OLD_SEED_GENERATION_SEMANTICS
00299   s_seed_generator = new scv_random("internal seed generator",seed);
00300 #endif
00301 
00302 }
00303 
00304 unsigned long long scv_random::get_global_seed(void) {
00305   return global_seed;
00306 }
00307 
00308 unsigned long long scv_random::pick_random_seed(unsigned long job_number) {
00309   return _scv_default_global_init_seed(job_number);
00310 }
00311 
00312 void scv_random::set_default_algorithm(value_generation_algorithm alg,
00313              alg_func custom_alg) {
00314   ::_scv_set_algorithm(alg,custom_alg,&s_algorithm,
00315     "the global algorithm for scv_random");
00316   global_alg_type = alg;
00317 }
00318 
00319 static list<scv_random *>& s_list_of_generators();
00320 
00321 void scv_random::get_generators(list<scv_random *>& genList) 
00322 {
00323   list<scv_random*>::iterator iter;
00324   for (iter = s_list_of_generators().begin();
00325      !(iter == s_list_of_generators().end()); 
00326        iter++ ) {
00327     genList.push_back(*iter);
00328   }
00329 }
00330 
00331 //---------------------------------------------
00332 // constructors for independent random streams
00333 //---------------------------------------------
00334 static void addSelf(scv_random * self);
00335 
00336 scv_random::scv_random(const char* name)
00337   : _scv_data_structure(_scv_extract_name(name).c_str()),
00338     _coreP(new _scv_random_impl(_name,0,s_algorithm, global_alg_type))
00339 {
00340   _name = _scv_get_unique_name(_name);
00341   addSelf(this);
00342 }
00343 
00344 scv_random::scv_random(unsigned long long seed)
00345   : _scv_data_structure("<anonymous>"),
00346     _coreP(new _scv_random_impl(_name,seed,s_algorithm, global_alg_type))
00347 {
00348   _name = _scv_get_unique_name(_name);
00349   addSelf(this);
00350 }
00351 
00352 scv_random::scv_random(const char* name, unsigned long long seed)
00353   : _scv_data_structure(_scv_extract_name(name).c_str()),
00354     _coreP(new _scv_random_impl(_name,seed,s_algorithm, global_alg_type))
00355 {
00356   _name = _scv_get_unique_name(_name);
00357   addSelf(this);
00358 }
00359   
00360 scv_random::scv_random(const scv_random& other,
00361          const char* name, unsigned long long seed)
00362   : _scv_data_structure(_scv_extract_name(name).c_str()),
00363     _coreP(new _scv_random_impl(_name,seed,other._coreP->_algorithm, other._coreP->_alg_type))
00364 {
00365   _name = _scv_get_unique_name(_name);
00366   addSelf(this);
00367 }
00368 
00369 scv_random::~scv_random() 
00370 { 
00371   s_list_of_generators().remove(this);
00372   delete _coreP;
00373 }
00374 
00375 //---------------------------------------------
00376 // random value generation and configuration of
00377 // independent random streams 
00378 //---------------------------------------------
00379 unsigned int scv_random::next() 
00380 {
00381   return _coreP->next();
00382 }
00383 
00384 void scv_random::set_algorithm(value_generation_algorithm m,
00385        alg_func algorithm) 
00386 {
00387   _coreP->_alg_type = m;
00388   ::_scv_set_algorithm(m,algorithm,&_coreP->_algorithm,get_name());
00389 }
00390 
00391 unsigned long long scv_random::get_initial_seed() const 
00392 { 
00393   return _coreP->_seed; 
00394 }
00395 
00396 unsigned long long scv_random::get_current_seed() const 
00397 { 
00398   if (_coreP->_algorithm) {
00399     return _coreP->u._next;
00400   } else if (_coreP->_alg_type == scv_random::RAND48) {
00401     unsigned long long seed = 0;
00402     unsigned long long tmp = 0;
00403   
00404     tmp = _coreP->u._next48[2]; 
00405     seed = tmp << 32;
00406   
00407     tmp = _coreP->u._next48[1];
00408     seed = seed | tmp << 16;
00409   
00410     tmp = _coreP->u._next48[0];
00411     seed = seed | tmp;
00412   
00413     return seed;
00414   } else if (_coreP->_alg_type == scv_random::RAND ||
00415              _coreP->_alg_type == scv_random::RAND32) {
00416     return _coreP->u._rand_next;
00417   } else {
00418     // should not have reached here
00419     return 0;
00420   }
00421   // return to make compiler happy
00422   return 0;
00423 }
00424 
00425 void scv_random::set_current_seed(unsigned long long seed) 
00426 { 
00427   if (_coreP->_algorithm) {
00428     _coreP->u._next = seed;
00429   } else if (_coreP->_alg_type == scv_random::RAND48) {
00430     _coreP->u._next48[0] = (unsigned short ) (seed & 0xffff);
00431     _coreP->u._next48[1] = (unsigned short ) (seed >> 16) & 0xffff;
00432     _coreP->u._next48[2] = (unsigned short ) (seed >> 32) & 0xffff;
00433   } else if (_coreP->_alg_type == scv_random::RAND ||
00434              _coreP->_alg_type == scv_random::RAND32) {
00435     _coreP->u._rand_next = (unsigned int)seed;
00436   } else {
00437     // should not have reached here
00438   }
00439   return;
00440 }
00441 
00442 //----------------------------------------------------------------------
00443 // -initial seed is the seed assigned to this object when it is created
00444 // -current seed is the current seed value that will be used to generate
00445 // -the next unsigned integer value
00446 // -these methods print the seeds of all current scv_random objects
00447 //----------------------------------------------------------------------
00448 
00449 void scv_random::print_initial_seeds(const char* fileName) 
00450 {
00451   if (fileName != NULL) {
00452     FILE * filePtr = fopen(fileName,"wb");
00453 
00454     list<scv_random*>::iterator iter;
00455     for (iter = s_list_of_generators().begin();
00456    !(iter == s_list_of_generators().end());
00457    ++iter) {
00458 
00459       string s = (*iter)->get_name();
00460       if (s!="") {
00461   fprintf(filePtr,"\"%s\" :: %llu\n",s.c_str(),
00462           (*iter)->get_initial_seed());
00463       } else {
00464   fprintf(filePtr,"\"<anonymous>\" :: %llu\n",(*iter)->get_initial_seed());
00465       }
00466     }
00467   } else {
00468     print_initial_seeds();
00469   }
00470 }
00471 
00472 void scv_random::print_initial_seeds(ostream& os) 
00473 {
00474   list<scv_random*>::iterator iter;
00475   for (iter = s_list_of_generators().begin();
00476        !(iter == s_list_of_generators().end());
00477        ++iter) {
00478     string s = (*iter)->get_name();
00479     if (s!="") {
00480       os << "\"" << s.c_str() << "\" :: " << 
00481         (*iter)->get_initial_seed() << endl;
00482     } else {
00483       os << "\"<anonymous>\" :: " << (*iter)->get_initial_seed() << endl;
00484     }
00485   }
00486 }
00487 
00488 void scv_random::print_current_seeds(const char* fileName) 
00489 {
00490   if (fileName != NULL) {
00491     FILE * filePtr = fopen(fileName,"wb");
00492 
00493     list<scv_random*>::iterator iter;
00494     for (iter = s_list_of_generators().begin();
00495    !(iter == s_list_of_generators().end());
00496    ++iter) {
00497 
00498       string s = (*iter)->get_name();
00499       if (s!="") {
00500   fprintf(filePtr,"\"%s\" :: %llu\n",s.c_str(),
00501           (*iter)->get_current_seed());
00502       } else {
00503   fprintf(filePtr,"\"<anonymous>\" :: %llu\n", 
00504           (*iter)->get_current_seed());
00505       }
00506     }
00507   } else {
00508     print_current_seeds();
00509   }
00510 }
00511 
00512 void scv_random::print_current_seeds(ostream& os) 
00513 {
00514   list<scv_random*>::iterator iter;
00515   for (iter = s_list_of_generators().begin();
00516        !(iter == s_list_of_generators().end());
00517        ++iter) {
00518     string s = (*iter)->get_name();
00519     if (s!="") {
00520       os << "\"" << s.c_str() << "\" :: " << 
00521         (*iter)->get_current_seed() << endl;
00522     } else {
00523       os << "\"<anonymous>\" :: " << (*iter)->get_current_seed() << endl;
00524     }
00525   }
00526 }
00527 
00528 static bool s_store = false;
00529 static bool s_exclusive_seed_file = false;
00530 static FILE *s_seed_file_ptr = NULL;
00531 static int s_numOutstanding_seeds = 0;
00532 static bool s_warnedOutOfOrder = false;
00533 static bool s_warned_same_name = false;
00534 static bool s_warned_anonymous = false;
00535 static bool s_has_anonymous_generator = false;
00536 
00537 static string& s_seed_file_name(); 
00538 static _scv_associative_array<string,list<unsigned long long> >& s_outstanding_seeds(); 
00539 static _scv_associative_array<string,int>& s_names(); 
00540 static bool readname_and_seed(string& nextName, unsigned long long& next_seed);
00541 static _scv_associative_array<string, int> unique_name_hash("unique_name_hash", 0);
00542 
00543 void scv_random::seed_monitor_on(bool retrieve, const char* fileName) 
00544 {
00545   if (s_store || s_retrieve) {
00546     scv_random_error::seed_monitor_not_off(s_seed_file_name());
00547     seed_monitor_off();
00548   }
00549   if (fileName != NULL) {
00550     s_exclusive_seed_file = true;
00551     if (retrieve) {
00552       s_store = false; 
00553       s_retrieve = true;
00554       s_seed_file_name() = fileName;
00555       s_seed_file_ptr = fopen(fileName,"r");
00556 #ifdef OLD_SEED_GENERATION_SEMANTICS
00557       if (s_seed_generator) {
00558         delete s_seed_generator;
00559         s_seed_generator = NULL;   
00560       }
00561 #endif
00562     } else {
00563       s_store = true;
00564       s_retrieve = false;
00565       s_seed_file_name() = fileName;
00566       s_seed_file_ptr = fopen(fileName,"wb");
00567     }
00568     if (!s_seed_file_ptr) {
00569       scv_random_error::cannot_open_seed_file(fileName);
00570       s_store = false;
00571       s_retrieve = false;
00572     }
00573   }
00574 }
00575 
00576 void scv_random::seed_monitor_on(bool retrieve, const char* sectionName, 
00577   FILE * file) 
00578 {
00579   if (s_store || s_retrieve) {
00580     scv_random_error::seed_monitor_not_off(s_seed_file_name());
00581     seed_monitor_off();
00582   }
00583   if (file) {
00584     s_exclusive_seed_file = false;
00585     s_seed_file_name() = sectionName?sectionName:"";
00586     s_seed_file_ptr = file;
00587     if (retrieve) {
00588       s_store = false; 
00589       s_retrieve = true;
00590     } else {
00591       s_store = true;
00592       s_retrieve = false;
00593     }
00594 #ifdef OLD_SEED_GENERATION_SEMANTICS
00595     if (s_seed_generator) {
00596       delete s_seed_generator;
00597       s_seed_generator = NULL;   
00598     }
00599 #endif
00600   }
00601 }
00602 
00603 void scv_random::seed_monitor_off() 
00604 {
00605   if (s_store || s_retrieve) {
00606     s_names().clear();
00607     s_warned_same_name = false;
00608     s_warned_anonymous = false;
00609     s_has_anonymous_generator = false;
00610   }
00611   if (s_store) {
00612     s_store = false;
00613     if (s_exclusive_seed_file) fclose(s_seed_file_ptr);
00614     s_seed_file_name() = "";
00615   }
00616   if (s_retrieve) {
00617     string dummyName;
00618     unsigned long long dummy_seed;
00619     s_retrieve = false;
00620     if (s_seed_file_ptr && readname_and_seed(dummyName,dummy_seed)) {
00621       scv_random_error::seed_not_exhausted(s_seed_file_name());
00622     }
00623     if (s_numOutstanding_seeds>0) {
00624       scv_random_error::seed_not_exhausted(s_seed_file_name());
00625     }
00626     if (s_exclusive_seed_file && s_seed_file_ptr) fclose(s_seed_file_ptr);
00627     s_seed_file_name() = "";
00628     s_seed_file_ptr = NULL;
00629     s_numOutstanding_seeds = 0;
00630     s_outstanding_seeds().clear();
00631     s_warnedOutOfOrder = false;
00632   }
00633 }
00634 
00635 int scv_random::get_debug() {
00636   return _scv_random_impl::get_debug();
00637 }
00638 
00639 const char *scv_random::kind() const {
00640   static const char *name = "scv_random";
00641   return name;
00642 }
00643 
00644 void scv_random::print(ostream& o, int details, int indent) const {
00645   char algorithm[100];
00646 
00647   o << "scv_random Name: " <<  get_name() << endl;
00648   switch(_coreP->_alg_type) {
00649     case scv_random::RAND48 :
00650       strcpy(algorithm, "jrand48");
00651       break;
00652     case scv_random::RAND:
00653       strcpy(algorithm, "rand");
00654       break;
00655     case scv_random::RAND32:
00656       strcpy(algorithm, "rand32");
00657       break;
00658     case scv_random::CUSTOM:
00659       strcpy(algorithm, "custom");
00660       break;
00661     default:
00662       break;
00663   }
00664   o << "\talgorithm: " << algorithm << endl; 
00665   o << "\tseed: " << _coreP->_seed << endl;
00666   o << "\tnext: " << get_current_seed() << endl;
00667   o << "\tnext value: " << _coreP->testNext() << endl;
00668 }
00669 
00670 void scv_random::set_debug(int debug) {
00671   _scv_random_impl::set_debug(debug);
00672 }
00673 
00674 void scv_random::show(int details, int indent) const {
00675   print(scv_out, details, indent);
00676 }
00677 
00679 // Staic functions used for scv_random implementation
00680 //   * _scv_set_algorithm
00681 //   * _scv_generate_seed
00682 //   * s_seed_file_name
00683 //   * s_outstanding_seeds
00684 //   * s_names
00685 //   * s_list_of_generators
00686 //   * readname_and_seed
00687 //   * retrieve_seed
00688 //   * addSelf
00689 //   * _scv_default_global_init_seed
00690 //   * _scv_jrand48
00692 
00693 extern const char *scv_get_process_name(sc_process_b*) ;
00694 
00695 static void _scv_update_current_thread_info(const string& name)  
00696 {
00697   sc_process_b * handle = sc_get_curr_process_handle();
00698   if (handle) {
00699     s_current_thread_name = scv_get_process_name(handle);
00700   } else {
00701     s_current_thread_name = "scv_main_thread";
00702   }
00703   string thread_based_name = s_current_thread_name + name;
00704   s_inst_num = unique_name_hash.getValue(thread_based_name);
00705   if (s_inst_num == 0) {
00706     sprintf(s_current_inst_num, "<noappend>");
00707   } else {
00708     sprintf(s_current_inst_num, "%d", s_inst_num);
00709   }
00710   unique_name_hash.insert(thread_based_name, (s_inst_num+1));
00711 }
00712 
00713 static unsigned long long _scv_generate_seed(const string& name)
00714 {
00715 #ifdef OLD_SEED_GENERATION_SEMANTICS
00716   return s_seed_generator->next();
00717 #else 
00718   string thread_based_name = s_current_thread_name + name;
00719   return _scv_get_seed_from_name(thread_based_name.c_str(), s_inst_num);
00720 #endif
00721 }
00722 
00723 static void
00724 _scv_set_algorithm(scv_random::value_generation_algorithm alg,
00725        scv_random::alg_func custom_alg,
00726        scv_random::alg_func * scv_be_set,
00727        const string & algorithm_name) {
00728   switch(alg) {
00729   case scv_random::RAND48:
00730   case scv_random::RAND:
00731   case scv_random::RAND32:
00732     *scv_be_set = NULL; break;
00733   case scv_random::CUSTOM:
00734     if (custom_alg==NULL) {
00735       scv_random_error::missing_algorithm(algorithm_name);
00736       *scv_be_set = NULL; break;
00737     } else {
00738       *scv_be_set = custom_alg; break;
00739     }
00740   }
00741 }
00742 
00743 static string& s_seed_file_name() {
00744   static string seed_file_name;
00745   return seed_file_name;
00746 }
00747 
00748 static _scv_associative_array<string,list<unsigned long long> >&
00749 s_outstanding_seeds() {
00750   static _scv_associative_array<string,list<unsigned long long> >
00751     outstanding_seeds("outstanding_seeds",list<unsigned long long>());
00752   return outstanding_seeds;
00753 }
00754 
00755 static _scv_associative_array<string,int>&
00756 s_names() {
00757   static _scv_associative_array<string,int>
00758     names("_generator Name Data Base",0);
00759   return names;
00760 }
00761 
00762 static list<scv_random *> *_list_of_generators = NULL;
00763 
00764 static list<scv_random *>& s_list_of_generators() {
00765   if (!_list_of_generators) {
00766     _list_of_generators = new list<scv_random*>;
00767   } 
00768   return *(_list_of_generators);
00769 }
00770 
00771 static bool readname_and_seed(string& nextName, unsigned long long & next_seed) {
00772   char nextChar;
00773   string name; 
00774   name.reserve(60);
00775 
00776   if (s_exclusive_seed_file) {
00777     do {
00778       nextChar = getc(s_seed_file_ptr);
00779       if (nextChar == EOF) return false;
00780     } while (nextChar != '\"');
00781   } else {
00782     bool done = false;
00783 
00784     while (!done) {
00785       do {
00786   nextChar = getc(s_seed_file_ptr);
00787   if (nextChar == EOF) return false;
00788       } while (nextChar != '<');
00789       do {
00790   nextChar = getc(s_seed_file_ptr);
00791   if (nextChar == EOF) return false;
00792   if (nextChar != '>') name = name.append(1,nextChar);
00793       } while (nextChar != '>');
00794       if (name == s_seed_file_name())  
00795   done = true;
00796       else
00797   name = "";
00798     }
00799     do {
00800       nextChar = getc(s_seed_file_ptr);
00801       if (nextChar == EOF) return false;
00802     } while (nextChar != '\"');
00803   }
00804 
00805   name = "";
00806 
00807 
00808   do {
00809     nextChar = getc(s_seed_file_ptr);
00810     if (nextChar == EOF) return false;
00811     if (nextChar != '\"') name = name.append(1,nextChar);
00812   } while (nextChar != '\"');
00813   nextName = name.c_str();
00814 
00815   int result = fscanf(s_seed_file_ptr," :: %llu", &next_seed);
00816 
00817   return result != EOF;
00818 }
00819 
00820 static void retrieve_seed(const string & name, unsigned long long * seed) {
00821   string s = name;
00822 
00823   if (s == string("")) s = string("<anonymous>");
00824   if (s_numOutstanding_seeds>0 && s_outstanding_seeds()[s].size()>0) {
00825     *seed = s_outstanding_seeds()[s].front();
00826     s_outstanding_seeds()[s].pop_front();
00827     --s_numOutstanding_seeds;
00828     return;
00829   }
00830 
00831   if (s_seed_file_ptr) {
00832     string nextName;
00833     unsigned long long next_seed;
00834     bool done = false;
00835 
00836     while (!done && readname_and_seed(nextName,next_seed)) {
00837       if (nextName == s || 
00838     (nextName == string("<anonymous>") && s == string("")) ) {
00839   *seed = next_seed;
00840   done = true;
00841       } else {
00842   ++s_numOutstanding_seeds;
00843   s_outstanding_seeds()[nextName].push_back(next_seed);
00844   if (!s_warnedOutOfOrder) {
00845     s_warnedOutOfOrder = true;
00846     scv_random_error::out_of_order_seed(s, s_seed_file_name());
00847   }
00848       }
00849     }
00850 
00851     if (!done) {
00852       scv_random_error::cannot_match_seed(s, s_seed_file_name());
00853       fclose(s_seed_file_ptr);
00854       s_seed_file_ptr = NULL;
00855     } 
00856   } else {
00857       scv_random_error::cannot_match_seed(s, s_seed_file_name());
00858   }
00859 }
00860 
00861 static void addSelf(scv_random * self) {
00862   s_list_of_generators().push_back(self);
00863   if (s_store || s_retrieve) {
00864     string s = self->get_name();
00865 
00866     if (s!="") {
00867       if (++s_names()[s]>1) {
00868   if (!s_warned_same_name) {
00869     s_warned_same_name = true;
00870     if (s_store) scv_random_error::storing_with_same_name(s, s_seed_file_name());
00871     else scv_random_error::retrieving_with_same_name(s, s_seed_file_name());
00872   }
00873       }
00874     } else {
00875       if (s_has_anonymous_generator && !s_warned_anonymous) {
00876   s_warned_anonymous = true;
00877   if (s_store) scv_random_error::storing_with_same_name("", s_seed_file_name());
00878   else scv_random_error::retrieving_with_same_name("", s_seed_file_name());
00879       } else {
00880   s_has_anonymous_generator = true;
00881       }
00882     }
00883 
00884     if (s_store) {
00885       if (s_exclusive_seed_file) {
00886   if (s!="") {
00887     fprintf(s_seed_file_ptr,"\"%s\" :: %llu\n",self->get_name(),self->get_initial_seed());
00888   } else {
00889     fprintf(s_seed_file_ptr,"\"<anonymous>\" :: %llu\n",self->get_initial_seed());
00890   }
00891       } else {
00892   if (s!="") {
00893     fprintf(s_seed_file_ptr,"<%s> \"%s\" :: %llu\n",s_seed_file_name().c_str(),self->get_name(),self->get_initial_seed());
00894   } else {
00895     fprintf(s_seed_file_ptr,"<%s> \"<anonymous>\" :: %llu\n",s_seed_file_name().c_str(),self->get_initial_seed());
00896   }
00897       }
00898     }
00899   }
00900 }
00901 
00902 unsigned long long _scv_get_global_seed(void) {
00903   return scv_random::get_global_seed();
00904 }
00905 
00906 static string _scv_get_unique_name(const string & name) {
00907 #ifndef DONT_UNIQUIFY_NAMES
00908   string hier_object_name;
00909   if (!strcmp(s_current_inst_num,"<noappend>")) {
00910     hier_object_name = s_current_thread_name + "." + name; 
00911   } else {
00912     hier_object_name = s_current_thread_name + "." + name +
00913         "_" + s_current_inst_num;
00914   }
00915   return hier_object_name;
00916 #else
00917   return name;
00918 #endif
00919 }
00920 
00921 static string _scv_extract_name(const char * str) {
00922   if (!str || 0==strcmp("",str)) return string("<anonymous>");
00923   string s(str);
00924   return s;
00925 }
00926 
00928 // Static methods for implementation of the jrand48 for LINUX
00929 //   - jrand48 on RH 7.0 is incompatible with RH 7.1 or other platforms
00930 //   - Following implementation is from RH7.1 jrand48 and is compatible
00931 //     with other platforms. 
00932 //   - This is important to obtain reproducible random streams across 
00933 //     various different platforms
00935 
00936 #if defined(__linux__) || defined(_MSC_VER)
00937 
00938 struct _scv_linux_drand48_data
00939 {
00940   unsigned short int __x[3];
00941   unsigned short int __old_x[3];
00942   unsigned short int __c;
00943   unsigned short int __init;
00944   unsigned long long int __a;
00945 };
00946 
00947 static struct _scv_linux_drand48_data drand48_data_glbl;
00948 
00949 static int _scv_linux_drand48_iterate(unsigned short int xsubi[3], 
00950   struct _scv_linux_drand48_data *buffer)
00951 {
00952   unsigned long long X;
00953   unsigned long long result;
00954 
00955   if (!buffer->__init)
00956     {
00957       buffer->__a = 0x5deece66dull;
00958       buffer->__c = 0xb;
00959       buffer->__init = 1;
00960     }
00961 
00962   X = ((unsigned long long) xsubi[2]) << 32 | ((unsigned long) xsubi[1]) << 16 | xsubi[0];
00963 
00964   result = X * buffer->__a + buffer->__c;
00965 
00966   xsubi[0] = (unsigned short) (result & 0xffff);
00967   xsubi[1] = (unsigned short) (result >> 16) & 0xffff;
00968   xsubi[2] = (unsigned short) (result >> 32) & 0xffff;
00969 
00970   return 0;
00971 }
00972 
00973 static int _scv_linux_jrand48_r(unsigned short int xsubi[3],
00974   struct _scv_linux_drand48_data *buffer,
00975   long int *result)
00976 {
00977   if (_scv_linux_drand48_iterate (xsubi, buffer) < 0)
00978     return -1;
00979 
00980   *result = ((xsubi[2] << 16) | xsubi[1]) & 0xffffffffl;
00981 
00982   return 0;
00983 }
00984 
00985 static long int _scv_linux_jrand48(unsigned short xsubi[3])
00986 {
00987   long int result;
00988 
00989   (void) _scv_linux_jrand48_r(xsubi, &drand48_data_glbl, &result);
00990 
00991   return result;
00992 }
00993 
00994 #endif
00995 
00996 static inline unsigned int _scv_jrand48(unsigned short next[3]) {
00997 #if defined(__linux__) || defined(_MSC_VER)
00998   return (unsigned int) _scv_linux_jrand48(next);
00999 #else
01000   return (unsigned int) jrand48(next);
01001 #endif
01002 }
01003 

Generated on Fri Jan 14 08:29:11 2005 for SystemC2.1beta11(excludingMSLib)(IncludingSCV)\nProvidedby:www.openverificationfoundation.org by doxygen1.2.18