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

scv_constraint_range.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_constraint_range.cpp
00022 
00023   Original Authors (Cadence Design Systems, Inc):
00024   Norris Ip, Dean Shea, John Rose, Jasvinder Singh, William Paulsen,
00025   John Pierce, Rachida Kebichi, Ted Elkind, David Bailey, Samir Agrawal
00026   2002-09-23
00027 
00028  *****************************************************************************/
00029 
00030 /*****************************************************************************
00031 
00032   MODIFICATION LOG - modifiers, enter your name, affiliation, date and
00033   changes you are making here.
00034 
00035       Name, Affiliation, Date:
00036   Description of Modification:
00037 
00038  *****************************************************************************/
00039 
00040 #include "scv/scv_util.h"
00041 #include "scv/scv_introspection.h"
00042 #include "scv/scv_report.h"
00043 
00044 
00045 //*****************************
00046 // _scv_interval
00047 //
00048 // * a private class for implementation of _scv_constraint_range
00049 // * it provides manipulation of intervals, like checking
00050 //   whether two intervals overlap one another.
00051 // * it can be used with "int" intervals, "unsigned" intervals,
00052 //   and "double" intervals.
00053 //
00054 // * assumption:
00055 //     - int/unsigned is Discrete and the upperbound is inclusive.
00056 //     - double is not Discrete and the upperbound is exclusive.
00057 // * size() returns 0 when empty or overflow (i.e. full)
00058 // * the implementation needs to check overflow/underflow whenever
00059 //   a bound is incremented or decremented for discrete types. 
00060 //*****************************
00061 
00062 #define _SCV_INTERVAL_FC_I(TypeId, EltT, SizeT, Discrete)  \
00063   _scv_interval_ ## TypeId& _scv_interval_ ## TypeId::operator=(const _scv_interval_ ## TypeId& rhs) {   \
00064     _empty = rhs._empty;  \
00065     _lowerbound = rhs._lowerbound;  \
00066     _upperbound = rhs._upperbound;  \
00067     /* don't need to copy _tmp as it is used as a temporary variable */ \
00068     return *this;  \
00069   }  \
00070   bool operator==(const _scv_interval_ ## TypeId& a,  \
00071        const _scv_interval_ ## TypeId& b) {    \
00072     if (a._empty && b._empty) return true;  \
00073     if (!a._empty && !b._empty  \
00074   && a._lowerbound == b._lowerbound  \
00075   && a._upperbound == b._upperbound) return true;  \
00076     return false;  \
00077   }  \
00078   bool operator<(const _scv_interval_ ## TypeId& a,  \
00079        const _scv_interval_ ## TypeId& b) {    \
00080     if (b._empty) return false;  \
00081     if (a._empty) return true;  \
00082     if (a._lowerbound < b._lowerbound  \
00083   || (a._lowerbound == b._lowerbound  \
00084       && a._upperbound < b._upperbound)) return true;  \
00085     return false;  \
00086   }  \
00087   void _scv_interval_ ## TypeId::print(ostream& os) const {  \
00088     if (_empty) os << "()";  \
00089     else if (Discrete) {  \
00090       if (_lowerbound != _upperbound)  \
00091   os << "[" << _lowerbound << "," << _upperbound << "]";  \
00092       else  \
00093   os << "[" << _lowerbound << "]";  \
00094     } else   \
00095       os << "[" << _lowerbound << "," << _upperbound << ")";  \
00096   }  \
00097   ostream& operator<<(ostream& os, const _scv_interval_ ## TypeId& a) {  \
00098     if (a._empty) os << "()";  \
00099     else if (Discrete) {  \
00100       if (a._lowerbound != a._upperbound)  \
00101   os << "[" << a._lowerbound << "," << a._upperbound << "]";  \
00102       else  \
00103   os << "[" << a._lowerbound << "]";  \
00104     } else   \
00105       os << "[" << a._lowerbound << "," << a._upperbound << ")";  \
00106     return os;  \
00107   }  \
00108   SizeT _scv_interval_ ## TypeId::size() const {  \
00109     if (_empty) {  \
00110       _tmp = 0;  \
00111     } else {  \
00112       _tmp = _upperbound - _lowerbound;  \
00113       if (Discrete) _tmp += 1;  \
00114     }  \
00115     return _tmp;  \
00116   }  \
00117   int _scv_interval_ ## TypeId::position(const EltT& v) const {  \
00118     if (_empty) return 1;  \
00119     if (v<_lowerbound) return -1;  \
00120     if (v>_upperbound) return 1;  \
00121     if (!Discrete && v== _upperbound) return 1;  \
00122     return 0;  \
00123   }  \
00124   bool _scv_interval_ ## TypeId::contain(const _scv_interval_ ## TypeId& i) const {  \
00125     if (_empty) return false;  \
00126     if (i._empty) return true;  \
00127     return i._upperbound <= _upperbound && i._lowerbound >= _lowerbound;  \
00128   }  \
00129   bool overlap(const _scv_interval_ ## TypeId& a,  \
00130           const _scv_interval_ ## TypeId& b) {  \
00131     if (a._empty || b._empty) return false;  \
00132     if (Discrete) {  \
00133       if (a._lowerbound > b._upperbound) return false;  \
00134       if (a._upperbound < b._lowerbound) return false;  \
00135     } else {  \
00136       if (a._lowerbound >= b._upperbound) return false;  \
00137       if (a._upperbound <= b._lowerbound) return false;  \
00138     }  \
00139     return true;  \
00140   }  \
00141   void _scv_interval_ ## TypeId::intersect(const _scv_interval_ ## TypeId& rhs) {  \
00142     if (!overlap(*this,rhs)) { _empty = true; return ; }  \
00143     if (_lowerbound < rhs._lowerbound) _lowerbound = rhs._lowerbound;  \
00144     if (_upperbound > rhs._upperbound) _upperbound = rhs._upperbound;  \
00145   }  \
00146   bool _scv_interval_ ## TypeId::subtractable(const _scv_interval_ ## TypeId& rhs) const {  \
00147     return _empty || rhs._empty  \
00148       || !( rhs._lowerbound > _lowerbound   \
00149       &&  rhs._upperbound < _upperbound);  \
00150   }  \
00151   void _scv_interval_ ## TypeId::subtract(const _scv_interval_ ## TypeId& rhs) {  \
00152     if (_empty || rhs._empty) return;  \
00153     if (!subtractable(rhs)) {  \
00154       _scv_message::message(_scv_message::CONSTRAINT_ERROR_INTERNAL,"interval subtraction");  \
00155     }  \
00156     if (Discrete) {  \
00157       if (rhs._lowerbound <= _lowerbound && _lowerbound <= rhs._upperbound) {  \
00158   _lowerbound = rhs._upperbound+1;  \
00159   if (_lowerbound < rhs._upperbound) _empty = true; /* overflow */  \
00160       }  \
00161       if (rhs._lowerbound <= _upperbound && _upperbound <= rhs._upperbound) {  \
00162   _upperbound = rhs._lowerbound-1;  \
00163   if (rhs._lowerbound < _upperbound) _empty = true; /* underflow */  \
00164       }  \
00165     } else {  \
00166       if (rhs._lowerbound <= _lowerbound && _lowerbound <= rhs._upperbound)  \
00167   _lowerbound = rhs._upperbound;  \
00168       if (rhs._lowerbound <= _upperbound && _upperbound <= rhs._upperbound)  \
00169   _upperbound = rhs._lowerbound;  \
00170     }  \
00171     if (Discrete) {  \
00172       if (_upperbound < _lowerbound) _empty = true;  \
00173     } else {  \
00174       if (_upperbound <= _lowerbound) _empty = true;  \
00175     }  \
00176   }  \
00177   bool mergeable(const _scv_interval_ ## TypeId& a,  \
00178       const _scv_interval_ ## TypeId& b) {  \
00179     if (a._empty || b._empty) return true;  \
00180     if (Discrete) {  \
00181       if ((a._upperbound < b._lowerbound && a._upperbound+1 < b._lowerbound)  \
00182     || (b._upperbound < a._lowerbound && b._upperbound+1 < a._lowerbound))  \
00183   return false;  \
00184     } else {  \
00185       if (a._upperbound < b._lowerbound  \
00186     || b._upperbound < a._lowerbound) return false;  \
00187     }  \
00188     return true;  \
00189   }  \
00190   void _scv_interval_ ## TypeId::merge(const _scv_interval_ ## TypeId& rhs) {  \
00191     if (rhs._empty) return;  \
00192     if (_empty) { operator=(rhs); return; }  \
00193     if (!mergeable(*this,rhs)) {  \
00194       _scv_message::message(_scv_message::CONSTRAINT_ERROR_INTERNAL,"interval merging");  \
00195     }  \
00196     if (_lowerbound > rhs._lowerbound) _lowerbound = rhs._lowerbound;  \
00197     if (_upperbound < rhs._upperbound) _upperbound = rhs._upperbound;  \
00198   }  \
00199 
00200 
00201 
00202 _SCV_INTERVAL_FC_I(int,int,unsigned,true);
00203 _SCV_INTERVAL_FC_I(unsigned,unsigned,unsigned,true);
00204 _SCV_INTERVAL_FC_I(double,double,double,false);
00205 
00206 _SCV_INTERVAL_FC_I(long_long,long long,unsigned long long,true);
00207 _SCV_INTERVAL_FC_I(unsigned_long_long,unsigned long long,unsigned long long,true);
00208 
00209 _SCV_INTERVAL_FC_I(sc_unsigned,sc_unsigned ,sc_unsigned,true);
00210 _SCV_INTERVAL_FC_I(sc_signed ,sc_signed ,sc_unsigned,true);
00211 
00212 
00213 
00214 // ****************************************
00215 // _scv_constraint_range class
00216 //
00217 // * _explicits is only used when 'Discrete' is false.
00218 // * _explicits and _intervals are sorted in assending order.
00219 // * get*() returns 0 with appropriate bits when empty. 
00220 // ****************************************
00221 
00222 // ****************************************
00223 // _scv_constraint_range implementation
00224 // ****************************************
00225 
00226 #define _SCV_CONSTRAINT_RANGE_FC_I(TypeId, EltT, SizeT, Discrete, FlexRandomT)  \
00227   ostream& operator<<(ostream& os, const _scv_constraint_range_ ## TypeId& a) {  \
00228     if (a.isEmpty()) os << "()";  \
00229     else {  \
00230       if (a._explicits.empty()) {  \
00231   if (a.getSize() == 0)  \
00232     os << "(size:<unconstrainted>) ";  \
00233   else  \
00234     os << "(size:" << a.getSize() << ") ";  \
00235   list<_scv_interval_ ## TypeId >::const_iterator i;  \
00236   i = a._intervals.begin();  \
00237   /* using print() instead of operator<< because gcc 3.0 has problem with -O2. */  \
00238   i->print(os);  \
00239   while (++i != a._intervals.end()) {  \
00240     os << ","; i->print(os);  \
00241   }  \
00242       } else {  \
00243   list<EltT>::const_iterator i;  \
00244   i = a._explicits.begin();  \
00245   os << "[" << *i << "]";  \
00246   while (++i != a._explicits.end())  \
00247     os << ",[" << *i << "]";  \
00248       }  \
00249     }  \
00250     return os;  \
00251   }  \
00252   \
00253   SizeT _scv_constraint_range_ ## TypeId::getSize() const {   \
00254     if (!_explicits.empty()) {  \
00255       _scv_message::message(_scv_message::CONSTRAINT_ERROR_INTERNAL,"interval size");  \
00256     }  \
00257     if (!_sizeValid)   \
00258       setSize();  \
00259     return _size;  \
00260   }  \
00261   void _scv_constraint_range_ ## TypeId::setSize() const {  \
00262     _sizeValid = true; _size = 0;  \
00263     list<_scv_interval_ ## TypeId >::const_iterator i;  \
00264     for (i = _intervals.begin(); i != _intervals.end(); ++i) {  \
00265       _size += i->size();  \
00266     }  \
00267   }  \
00268   \
00269   void _scv_constraint_range_ ## TypeId::checkExplicits() {  \
00270     if (_explicits.empty()) {  \
00271       _intervals.clear();  \
00272       _mode = EMPTY;  \
00273       _sizeValid = false;  \
00274       _size = 0;  \
00275       _intervals.push_front(_scv_interval_ ## TypeId(_size,_size));  \
00276       emptyMessage();  \
00277     }  \
00278     else {  \
00279       _intervals.push_front(_scv_interval_ ## TypeId(_explicits.front(),  \
00280                      _explicits.back()));  \
00281     }  \
00282   }  \
00283   void _scv_constraint_range_ ## TypeId::checkIntervals() {  \
00284     if (_intervals.empty()) {  \
00285       _mode = EMPTY;  \
00286       _sizeValid = false;  \
00287       _size = 0;  \
00288       _intervals.push_front(_scv_interval_ ## TypeId(_size,_size));  \
00289       emptyMessage();  \
00290     }  \
00291   }  \
00292   \
00293   void _scv_constraint_range_ ## TypeId::emptyMessage() {  \
00294     if (_nameP !="" ) {  \
00295       _scv_message::message(_scv_message::CONSTRAINT_ERROR_OVER_CONSTRAINED,_nameP.c_str());  \
00296     }  \
00297   }  \
00298 EltT  \
00299 _scv_constraint_range_ ## TypeId::  \
00300 getRandomValue(scv_shared_ptr<scv_random> random) const {  \
00301   /* if it is non-empty, generate a random value */  \
00302   if (!isEmpty()) {  \
00303     if (isUnconstrainted()) {    \
00304       return _flexRandom.next(random);   \
00305     }  \
00306     if (_explicits.empty()) {  \
00307       SizeT remain = _flexRandom.next(random,getSize());  \
00308       list<_scv_interval_ ## TypeId >::const_iterator i;  \
00309       for (i = _intervals.begin(); i != _intervals.end(); ++i) {  \
00310   if (remain < i->size()) {  \
00311     return i->lowerbound() + remain;   \
00312   }  \
00313   remain -= i->size();  \
00314       }  \
00315     } else {  \
00316       unsigned int index = random->next() % _explicits.size();  \
00317       list<EltT>::const_iterator i = _explicits.begin();  \
00318       while (index != 0) {  \
00319   --index;  \
00320   ++i;  \
00321       }  \
00322       return *i;  \
00323     }  \
00324   }  \
00325   \
00326   /* trying to generate a value from an empty set; trigger an error exception. */  \
00327   _sizeValid = false; _size = 0; return _size;  \
00328 }  \
00329   \
00330 EltT  \
00331 _scv_constraint_range_ ## TypeId::  \
00332 getScanValue(const EltT& base, const SizeT& increment) const {  \
00333     /* if it is non-empty, generate a random value */  \
00334   if (!isEmpty()) {  \
00335     EltT nextValue = base + increment;  \
00336     if (nextValue < base) return base; /* overflow */  \
00337     if (isUnconstrainted()) { return nextValue; }  \
00338     if (_explicits.empty()) {  \
00339       list<_scv_interval_ ## TypeId >::const_iterator i;  \
00340       for (i = _intervals.begin(); i != _intervals.end(); ++i) {  \
00341   int position = i->position(nextValue);  \
00342   if (position == 0)  \
00343     return nextValue; /* common case: need to be fast */  \
00344   else if (position < 0) {  \
00345     if (Discrete) {  \
00346       SizeT d = i->lowerbound() - nextValue;  \
00347       if (_flexRandom.mod(d,increment) == 0)  \
00348         return i->lowerbound();  \
00349       nextValue = nextValue + (d / increment) * increment + increment;  \
00350       if (nextValue < base) return base; /* overflow */  \
00351       if (nextValue <= i->upperbound())  \
00352         return nextValue;  \
00353     } else {  \
00354       /*      while (nextValue < i->lowerbound())  */  \
00355       /*        nextValue += increment; */  \
00356       /*      if (i->position(nextValue) == 0) return nextValue; */  \
00357       SizeT d = (i->lowerbound() - nextValue)/increment;  \
00358       if (d < 1) {  \
00359         nextValue += increment;  \
00360         if (i->position(nextValue)==0) return nextValue;  \
00361       } else {  \
00362         nextValue += _flexRandom.floor((i->lowerbound() - nextValue)/increment) * increment;  \
00363         if (i->position(nextValue)==0) return nextValue;  \
00364         nextValue += increment;  \
00365         if (i->position(nextValue)==0) return nextValue;  \
00366       }  \
00367     }  \
00368   }  \
00369       }  \
00370       return base;  \
00371     } else {  \
00372       list<EltT>::const_iterator i;  \
00373       for (i = _explicits.begin(); i != _explicits.end(); ++i) {  \
00374   if (nextValue == *i) return *i;  \
00375   if (nextValue < *i && _flexRandom.mod(*i-nextValue,increment) == 0) return *i;  \
00376       }  \
00377       return base;  \
00378     }  \
00379   }  \
00380   \
00381   /* trying to generate a value from an empty set; trigger an error exception. */  \
00382   _sizeValid = false; _size = 0; return _size;  \
00383 }  \
00384   \
00385 _scv_constraint_range_ ## TypeId::_scv_constraint_range_ ## TypeId()   \
00386   : _mode(EMPTY), _nameP(""), _intervals(), _explicits(),  \
00387     _flexRandom(), _tmpUb(0), _tmpLb(0), _sizeValid(false), _size(0) {  \
00388   _intervals.push_front(_scv_interval_ ## TypeId((EltT) 0, (EltT) 0));  \
00389 }   \
00390   \
00391 _scv_constraint_range_ ## TypeId::  \
00392 _scv_constraint_range_ ## TypeId(const EltT& sampleElt)  \
00393   : _mode(EMPTY), _nameP(""), _intervals(), _explicits(),  \
00394     _flexRandom(sampleElt), _tmpUb(sampleElt), _tmpLb(sampleElt), _sizeValid(false), _size(sampleElt) {  \
00395 }  \
00396   \
00397 _scv_constraint_range_ ## TypeId::  \
00398 _scv_constraint_range_ ## TypeId(const EltT& lb, const EltT& ub)  \
00399   : _mode(INTERVAL_LIST), _nameP(""), _intervals(), _explicits(),  \
00400     _flexRandom(lb), _tmpUb(lb), _tmpLb(lb), _sizeValid(false), _size(lb) {  \
00401   _intervals.push_front(_scv_interval_ ## TypeId(lb,ub));  \
00402 }  \
00403   \
00404 _scv_constraint_range_ ## TypeId::  \
00405 _scv_constraint_range_ ## TypeId(const _scv_constraint_range_ ## TypeId& rhs)  \
00406   : _mode(rhs._mode),  \
00407     _nameP(rhs._nameP),  \
00408     _intervals(rhs._intervals),  \
00409     _explicits(rhs._explicits),  \
00410     _flexRandom(rhs._flexRandom),  \
00411     _tmpUb(rhs._tmpUb),  \
00412     _tmpLb(rhs._tmpLb),  \
00413     _sizeValid(rhs._sizeValid),  \
00414     _size(rhs._size)  \
00415 {}  \
00416   \
00417 _scv_constraint_range_ ## TypeId&  \
00418 _scv_constraint_range_ ## TypeId::  \
00419 operator=(const _scv_constraint_range_ ## TypeId& rhs) {  \
00420   _mode = rhs._mode;   \
00421   _nameP = rhs._nameP;  \
00422   _intervals = rhs._intervals;  \
00423   _explicits = rhs._explicits;  \
00424   /* don't need to copy _flexRandom as it only contains configuration information */  \
00425   _sizeValid = rhs._sizeValid;  \
00426   _size = rhs._size;  \
00427   return *this;  \
00428 }  \
00429   \
00430 _scv_constraint_range_ ## TypeId  \
00431 _scv_constraint_range_ ## TypeId::  \
00432 merge(const _scv_constraint_range_ ## TypeId& a,  \
00433       const _scv_constraint_range_ ## TypeId& b) {  \
00434   /* simple cases */  \
00435   if (a.isUnconstrainted()) return b;  \
00436   if (b.isUnconstrainted()) return a;  \
00437   if (a.isEmpty()) return a;  \
00438   if (b.isEmpty()) return b;  \
00439   \
00440   /* special cases */  \
00441   if (!a._explicits.empty()) {  \
00442     list<EltT> common;  \
00443     list<EltT>::const_iterator i = a._explicits.begin();  \
00444     while (i != a._explicits.end()) {  \
00445       if (b.satisfy(*i)) common.push_back(*i);  \
00446       ++i;  \
00447     }  \
00448     _scv_constraint_range_ ## TypeId c(a.getLowerBound());  \
00449     if (!common.empty()) {  \
00450       c._mode = INTERVAL_LIST;  \
00451       c._explicits = common;  \
00452       c._intervals.push_front  \
00453   (_scv_interval_ ## TypeId(c._explicits.front(),  \
00454         c._explicits.back()));  \
00455     }  \
00456   \
00457     return c;  \
00458   }  \
00459   if (!b._explicits.empty()) return merge(b,a);  \
00460   \
00461   /* common cases */  \
00462   _scv_constraint_range_ ## TypeId m(a.getLowerBound());  \
00463   m._mode = INTERVAL_LIST;  \
00464   list<_scv_interval_ ## TypeId >::const_iterator i,j;  \
00465   i = a._intervals.begin();  \
00466   j = b._intervals.begin();  \
00467   while (i != a._intervals.end() && j != b._intervals.end()) {  \
00468     if (overlap(*i,*j)) {  \
00469       _scv_interval_ ## TypeId tmp = *i;  \
00470       tmp.intersect(*j);  \
00471       m._intervals.push_back(tmp);  \
00472     }  \
00473     if (i->upperbound() < j->upperbound()) ++i;  \
00474     else ++j;  \
00475   }  \
00476   m.checkIntervals();  \
00477   return m;  \
00478 }  \
00479   \
00480 void _scv_constraint_range_ ## TypeId::  \
00481 keepOnly(const EltT& lb, const EltT& ub) {  \
00482   _tmpLb = lb;  \
00483   _tmpUb = ub;  \
00484   /* simple cases */  \
00485   if (isEmpty()) return;  \
00486   if (isUnconstrainted()) {  \
00487     _sizeValid = false;  \
00488     _intervals.clear();  \
00489     _intervals.push_front(_scv_interval_ ## TypeId(_tmpLb,_tmpUb));  \
00490     return;  \
00491   }  \
00492   \
00493   /* setup */  \
00494   _sizeValid = false;  \
00495   _scv_interval_ ## TypeId interval(_tmpLb,_tmpUb);  \
00496   \
00497   /* special cases */  \
00498   if (!_explicits.empty()) {  \
00499     list<EltT>::iterator i = _explicits.begin();  \
00500     while (i != _explicits.end()) {  \
00501       int position = interval.position(*i);  \
00502       if (position != 0)  \
00503   i = _explicits.erase(i);  \
00504       else   \
00505   ++i;  \
00506     }  \
00507     checkExplicits();  \
00508     return;  \
00509   }  \
00510   \
00511   list<_scv_interval_ ## TypeId >::iterator i;  \
00512   i = _intervals.begin();  \
00513   while (i != _intervals.end()) {  \
00514     if (overlap(*i,interval)) {  \
00515       _scv_interval_ ## TypeId tmp = *i;  \
00516       tmp.intersect(interval);  \
00517       _intervals.insert(i,tmp);  \
00518       i = _intervals.erase(i);  \
00519     } else {  \
00520       i = _intervals.erase(i);  \
00521     }  \
00522   }  \
00523   checkIntervals();  \
00524   return;  \
00525 }  \
00526   \
00527 void _scv_constraint_range_ ## TypeId::keepOnly(const EltT& v) {  \
00528   if (Discrete)  \
00529     keepOnly(v,v);  \
00530   else {  \
00531     if (satisfy(v)) {  \
00532       _intervals.clear();  \
00533       _explicits.clear();  \
00534       _explicits.push_front(v);  \
00535       _intervals.push_front(_scv_interval_ ## TypeId(v,v));  \
00536     } else {  \
00537       _intervals.clear();  \
00538       _explicits.clear();  \
00539       _mode = EMPTY;  \
00540       emptyMessage();  \
00541     }  \
00542   }  \
00543 }  \
00544   \
00545 void _scv_constraint_range_ ## TypeId::keepOnly(const list<EltT>& l) {  \
00546   /* simple cases */  \
00547   if (isEmpty()) return;  \
00548   \
00549   /* convert to a list of legal values */  \
00550   list<EltT> l2;  \
00551   for (list<EltT>::const_iterator i = l.begin();  \
00552        i != l.end();  \
00553        ++i) {  \
00554     if (satisfy(*i))  \
00555       l2.push_back(*i);  \
00556   }  \
00557   if (l2.empty()) {  \
00558     _intervals.clear();  \
00559     checkIntervals();  \
00560     return;  \
00561   }  \
00562   /* common cases */  \
00563   _intervals.clear();  \
00564   _sizeValid = false;  \
00565   if (Discrete) {  \
00566     for (list<EltT>::iterator j = l2.begin();  \
00567    j != l2.end();  \
00568    ++j) {  \
00569       list< _scv_interval_ ## TypeId >::iterator k;  \
00570       for (k = _intervals.begin(); k != _intervals.end(); ++k) {  \
00571   if (k->lowerbound() > *j) {  \
00572     _tmpLb = *j;  \
00573     _intervals.insert(k,_scv_interval_ ## TypeId(_tmpLb,_tmpLb));  \
00574     break;  \
00575   }  \
00576       }  \
00577       if (k == _intervals.end()) {  \
00578   _tmpLb = *j;  \
00579   _intervals.push_back(_scv_interval_ ## TypeId(_tmpLb,_tmpLb));  \
00580       }  \
00581     }  \
00582     checkIntervals();  \
00583   } else {  \
00584     _explicits.clear();  \
00585     for (list<EltT>::iterator j = l2.begin();  \
00586    j != l2.end();  \
00587    ++j) {  \
00588       list<EltT>::iterator k;  \
00589       for (k = _explicits.begin(); k != _explicits.end(); ++k) {  \
00590   if (*j < *k) {  \
00591     _explicits.insert(k,*j);  \
00592     break;  \
00593   }   \
00594   if (*j == *k) /* remove duplicate */  \
00595     break;  \
00596       }  \
00597       if (k == _explicits.end())  \
00598   _explicits.push_back(*j);  \
00599     }  \
00600     checkExplicits();  \
00601   }  \
00602 }  \
00603   \
00604 void _scv_constraint_range_ ## TypeId::  \
00605 keepOut(const EltT& lb, const EltT& ub) {  \
00606   _tmpLb = lb;  \
00607   _tmpUb = ub;  \
00608   \
00609   /* simple cases */  \
00610   if (isEmpty()) return;  \
00611   \
00612   /* setup */  \
00613   _sizeValid = false;  \
00614   _scv_interval_ ## TypeId interval(_tmpLb,_tmpUb);  \
00615   \
00616   /* special cases */  \
00617   if (!_explicits.empty()) {  \
00618     list<EltT>::iterator i = _explicits.begin();  \
00619     while (i != _explicits.end()) {  \
00620       int position = interval.position(*i);  \
00621       if (position == 0)  \
00622   i = _explicits.erase(i);  \
00623       else   \
00624   ++i;  \
00625     }  \
00626     checkExplicits();  \
00627     return;  \
00628   }  \
00629   \
00630   /* common cases */  \
00631   list<_scv_interval_ ## TypeId >::iterator i;  \
00632   i = _intervals.begin();  \
00633   while (i != _intervals.end()) {  \
00634     if (i->contain(interval)) {  \
00635       if (Discrete) {  \
00636   if (i->lowerbound() < interval.lowerbound()) {  \
00637     _tmpUb = interval.lowerbound()-1;  \
00638     _intervals.insert  \
00639       (i, _scv_interval_ ## TypeId(i->lowerbound(),_tmpUb));  \
00640   }  \
00641   if (i->upperbound() > interval.upperbound()) {  \
00642     _tmpLb = interval.upperbound()+1;  \
00643     _intervals.insert  \
00644       (i,_scv_interval_ ## TypeId(_tmpLb,i->upperbound()));  \
00645   }  \
00646       } else {  \
00647   if (i->lowerbound() < interval.lowerbound())  \
00648     _intervals.insert  \
00649       (i,_scv_interval_ ## TypeId(i->lowerbound(),  \
00650               interval.lowerbound()));  \
00651   if (i->upperbound() > interval.upperbound())  \
00652     _intervals.insert  \
00653       (i,_scv_interval_ ## TypeId(interval.upperbound(),  \
00654               i->upperbound()));  \
00655       }  \
00656       i = _intervals.erase(i);  \
00657     } else {  \
00658       if (i->subtractable(interval))  \
00659   i->subtract(interval);  \
00660       if (i->empty())   \
00661   i = _intervals.erase(i);  \
00662       else  \
00663   ++i;  \
00664     }  \
00665   }  \
00666   checkIntervals();  \
00667 }  \
00668   \
00669 void _scv_constraint_range_ ## TypeId::keepOut(const EltT& v) {  \
00670   if (!Discrete) {  \
00671     _scv_message::message(_scv_message::CONSTRAINT_ERROR_INTERNAL,"non-discrete keepOut");  \
00672   }  \
00673   keepOut(v,v);  \
00674 }  \
00675   \
00676 void _scv_constraint_range_ ## TypeId::  \
00677 keepOut(const list<EltT>& l) {  \
00678   if (!Discrete) {  \
00679     _scv_message::message(_scv_message::CONSTRAINT_ERROR_INTERNAL,"non-discrete keepOut");  \
00680   }  \
00681   for (list<EltT>::const_iterator i = l.begin(); i != l.end(); ++i)  \
00682     keepOut(*i);  \
00683 }  \
00684   \
00685 bool _scv_constraint_range_ ## TypeId::  \
00686 satisfy(const EltT& v) const {  \
00687   \
00688   if (isEmpty()) return false;  \
00689   if (_explicits.empty()) {  \
00690     list<_scv_interval_ ## TypeId >::const_iterator i;  \
00691     for (i = _intervals.begin(); i != _intervals.end(); ++i) {  \
00692       int j = i->position(v);  \
00693       if (j== 0) return true;  \
00694       if (j < 0) return false;  \
00695     }  \
00696   } else {  \
00697     list<EltT>::const_iterator i;  \
00698     for (i = _explicits.begin(); i != _explicits.end(); ++i) {  \
00699       if (*i == v) return true;  \
00700       /* assuming that the explicit list is typically short,  */  \
00701       /* we avoid doing potentially expensive < comparison here. */  \
00702     }  \
00703   }  \
00704   return false;  \
00705 }  \
00706 
00707 
00708 
00709 
00710 _SCV_CONSTRAINT_RANGE_FC_I(int,int,unsigned,true,_scv_random_unsigned);
00711 _SCV_CONSTRAINT_RANGE_FC_I(unsigned,unsigned,unsigned,true,_scv_random_unsigned);
00712 _SCV_CONSTRAINT_RANGE_FC_I(double,double,double,false,_scv_random_double);
00713 
00714 _SCV_CONSTRAINT_RANGE_FC_I(long_long,long long,unsigned long long,true,_scv_random_unsigned_ll);
00715 _SCV_CONSTRAINT_RANGE_FC_I(unsigned_long_long,unsigned long long,unsigned long long,true,_scv_random_unsigned_ll);
00716 
00717 _SCV_CONSTRAINT_RANGE_FC_I(sc_unsigned,sc_unsigned ,sc_unsigned,true,_scv_random_unsigned_big);
00718 _SCV_CONSTRAINT_RANGE_FC_I(sc_signed ,sc_signed ,sc_unsigned,true,_scv_random_unsigned_big);
00719 
00720 
00721 
00722 
00723 // ****************************************
00724 // value generation algorithms with _scv_constraint_range 
00725 // ****************************************
00726 
00727 #define _SCV_CONSTRAINT_RANGE_GENERATOR_FC_I(TypeId, EltT, SizeT, Discrete, FlexRandomT)  \
00728   void _scv_constraint_range_generator_base_ ## TypeId::print(ostream& os, const char * prefixP) const {  \
00729     string prefix = "";  \
00730     if (prefixP) prefix = prefixP;  \
00731     os << prefix << "legal values : " << _simpleConstraint << endl;  \
00732     if (_onGoingConstraintValid)  \
00733       os << prefix << "legal values to avoid duplicate : " << _onGoingConstraint << endl;  \
00734     if (_currentScanValueValid)  \
00735       os << prefix << "scan status : last value generated is " << _currentScanValue << endl;  \
00736     if (_scanFixedIncrement)  \
00737       os << prefix << "scan interval : " << _scanIncrement << endl;  \
00738     else   \
00739       os << prefix << "scan interval : "   \
00740    << *_scanIntervalGenP << endl;  \
00741     os << prefix << "duplicate distance : " << _duplicateDistance << endl;  \
00742     if (_distributionP && !_distributionP->empty()) {  \
00743       os << prefix << "distribution : " << endl;  \
00744       os << prefix << *_distributionP << endl;  \
00745     }  \
00746   }  \
00747   void _scv_constraint_range_generator_base_ ## TypeId::checkConstraint(const char * locationP) {  \
00748     reset();  \
00749     if (isEmpty())  \
00750       _scv_constraint_range_error::overConstraint(_nameP, locationP);  \
00751     if (_distributionP && !_distributionP->empty()) {  \
00752       _setWeightDistribution(*_distributionP,_distUseMarking);  \
00753     }  \
00754   }  \
00755 EltT _scv_constraint_range_generator_base_ ## TypeId::  \
00756 randomNext() const {  \
00757   if (isEmpty())  \
00758     _scv_constraint_range_error::emptyGenerator(_nameP);  \
00759   return _simpleConstraint.getRandomValue(_randomP);  \
00760 }  \
00761   \
00762 EltT _scv_constraint_range_generator_base_ ## TypeId::  \
00763 distributionNext() const {  \
00764   if (_distributionP && !_distributionP->empty()) {  \
00765     if (_distributionP->unMarkedSize()==0) _distributionP->unmarkAll();  \
00766     return _distributionP->peekRandom(_distUseMarking);  \
00767   }  \
00768   _scv_constraint_range_error::invalidDistribution(_nameP,"next");  \
00769   return randomNext();  \
00770 }  \
00771   \
00772 EltT _scv_constraint_range_generator_base_ ## TypeId::  \
00773 randomAvoidDuplicateNext() const {  \
00774   if (isEmpty())  \
00775     _scv_constraint_range_error::emptyGenerator(_nameP);  \
00776   if (!_onGoingConstraintValid) {  \
00777     _onGoingConstraint = _simpleConstraint;  \
00778     _onGoingConstraintValid = true;  \
00779   }  \
00780   EltT newValue =   \
00781     _onGoingConstraint.getRandomValue(_randomP);  \
00782   if (Discrete)  \
00783     _onGoingConstraint.keepOut(newValue);  \
00784   else  \
00785     _onGoingConstraint.keepOut(newValue-_duplicateDistance,  \
00786              newValue+_duplicateDistance);   \
00787   if (_onGoingConstraint.isEmpty())  \
00788     _onGoingConstraintValid = false;  \
00789   return newValue;  \
00790 }  \
00791   \
00792 EltT _scv_constraint_range_generator_base_ ## TypeId::  \
00793 scanNext() const {  \
00794   if (isEmpty())  \
00795     _scv_constraint_range_error::emptyGenerator(_nameP);  \
00796   if (!_onGoingConstraintValid) {  \
00797     _onGoingConstraint = _simpleConstraint;  \
00798     _onGoingConstraintValid = true;  \
00799   }  \
00800   if (!_currentScanValueValid) {  \
00801     _currentScanValue = _onGoingConstraint.getLowerBound();  \
00802     _currentScanValueValid = true;;  \
00803     return _currentScanValue;  \
00804   }  \
00805   \
00806   if (!_scanFixedIncrement)  \
00807     _scanIncrement = _scanIntervalGenP->getRandomValue(_randomP);  \
00808   \
00809   EltT nextValue  \
00810     = _onGoingConstraint.getScanValue(_currentScanValue,  \
00811               _scanIncrement);  \
00812   if (nextValue == _currentScanValue) {  \
00813     _currentScanValueValid = false;  \
00814     _onGoingConstraintValid = false;  \
00815     return scanNext();  \
00816   }   \
00817   _currentScanValue = nextValue;  \
00818   return _currentScanValue;  \
00819 }  \
00820   \
00821 _scv_constraint_range_generator_base_ ## TypeId::  \
00822 _scv_constraint_range_generator_base_ ## TypeId(const EltT& lb, const EltT& ub,  \
00823         scv_shared_ptr<scv_random> random, const char * nameP)  \
00824   : _nameP(nameP),  \
00825     _simpleConstraint(lb,ub),  \
00826     _onGoingConstraintValid(false),  \
00827     _onGoingConstraint(lb,ub),  \
00828     _currentScanValueValid(false),  \
00829     _currentScanValue(lb),  \
00830     _randomP(random),  \
00831     _distUseMarking(false),  \
00832     _distributionP(NULL),  \
00833     _duplicateDistance(lb),  \
00834     _scanIntervalGenP(NULL),  \
00835     _scanFixedIncrement(true),  \
00836     _scanIncrement(lb)  \
00837 {  \
00838   _duplicateDistance = 1;  \
00839   _scanIncrement = 1;  \
00840 }  \
00841   \
00842 _scv_constraint_range_generator_base_ ## TypeId::  \
00843 _scv_constraint_range_generator_base_ ## TypeId(const _scv_constraint_range_generator_base_ ## TypeId& rhs,  \
00844         const char * nameP)  \
00845   : _nameP(nameP),  \
00846     _simpleConstraint(rhs._simpleConstraint),  \
00847     _onGoingConstraintValid(rhs._onGoingConstraintValid),  \
00848     _onGoingConstraint(rhs._onGoingConstraint),  \
00849     _currentScanValueValid(rhs._currentScanValueValid),  \
00850     _currentScanValue(rhs._currentScanValue),  \
00851     _randomP(rhs._randomP),  \
00852     _distUseMarking(rhs._distUseMarking),  \
00853     _distributionP(NULL),  \
00854     _duplicateDistance(rhs._duplicateDistance),  \
00855     _scanIntervalGenP(NULL),  \
00856     _scanFixedIncrement(rhs._scanFixedIncrement),  \
00857     _scanIncrement(rhs._scanIncrement)  \
00858 {  \
00859   if (rhs._distributionP) {  \
00860     _distributionP = new scv_bag<EltT>(*rhs._distributionP);  \
00861     _distributionP->setRandom(*_randomP);  \
00862   }  \
00863   if (rhs._scanIntervalGenP)   \
00864     _scanIntervalGenP = new _scv_constraint_range_ ## TypeId(*rhs._scanIntervalGenP);  \
00865 }  \
00866   \
00867 void _scv_constraint_range_generator_base_ ## TypeId::  \
00868 setScanInterval(const SizeT& lb, const SizeT& ub) {  \
00869   if (_scanIntervalGenP) {  \
00870     delete _scanIntervalGenP;  \
00871     _scanIntervalGenP = NULL;  \
00872   }  \
00873   if (lb==0)   \
00874     _scv_constraint_range_error::invalidScanInterval(_nameP);  \
00875   if (ub==0 || ub<=lb) {  \
00876     _scanFixedIncrement = true;  \
00877     _scanIncrement = lb;  \
00878   } else {  \
00879     _scanFixedIncrement = false;  \
00880     _scanIntervalGenP = new _scv_constraint_range_ ## TypeId(lb,ub);  \
00881   }  \
00882 }  \
00883   \
00884 void _scv_constraint_range_generator_base_ ## TypeId::  \
00885 setWeightDistribution(const scv_bag<EltT>& bag, bool useMarking) {  \
00886   _setWeightDistribution(bag,useMarking);  \
00887   if (_distributionP->empty()) {  \
00888     _scv_constraint_range_error::invalidDistribution(_nameP,"setWeightDistribution");  \
00889   }  \
00890 }  \
00891   \
00892 void _scv_constraint_range_generator_base_ ## TypeId::  \
00893 _setWeightDistribution(const scv_bag<EltT>& bag, bool useMarking) {  \
00894   _distUseMarking = useMarking;  \
00895   if (_distributionP)  \
00896     *_distributionP = bag;  \
00897   else {  \
00898     _distributionP = new scv_bag<EltT>(bag);  \
00899     _distributionP->setRandom(*_randomP);  \
00900   }  \
00901   unsigned int size = _distributionP->distinctSize();  \
00902   for (unsigned int i=0; i<size; ++i) {  \
00903     EltT j = _distributionP->peekNext('a',true);  \
00904     if (!satisfyConstraints(j))  \
00905       _distributionP->remove(true);  \
00906   }  \
00907 }  \
00908 
00909 
00910 
00911 _SCV_CONSTRAINT_RANGE_GENERATOR_FC_I(int,int,unsigned,true,_scv_random_unsigned);
00912 _SCV_CONSTRAINT_RANGE_GENERATOR_FC_I(unsigned,unsigned,unsigned,true,_scv_random_unsigned);
00913 _SCV_CONSTRAINT_RANGE_GENERATOR_FC_I(double,double,double,false,_scv_random_double);
00914 
00915 _SCV_CONSTRAINT_RANGE_GENERATOR_FC_I(long_long,long long,unsigned long long,true,_scv_random_unsigned_ll);
00916 _SCV_CONSTRAINT_RANGE_GENERATOR_FC_I(unsigned_long_long,unsigned long long,unsigned long long,true,_scv_random_unsigned_ll);
00917 
00918 _SCV_CONSTRAINT_RANGE_GENERATOR_FC_I(sc_unsigned,sc_unsigned ,sc_unsigned,true,_scv_random_unsigned_big);
00919 _SCV_CONSTRAINT_RANGE_GENERATOR_FC_I(sc_signed ,sc_signed ,sc_unsigned,true,_scv_random_unsigned_big);
00920 

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