Interval.cpp

Go to the documentation of this file.
00001 /****************** <VPR heading BEGIN do not edit this line> *****************
00002  *
00003  * VR Juggler Portable Runtime
00004  *
00005  * Original Authors:
00006  *   Allen Bierbaum, Patrick Hartling, Kevin Meinert, Carolina Cruz-Neira
00007  *
00008  * -----------------------------------------------------------------
00009  * File:          $RCSfile$
00010  * Date modified: $Date: 2005-06-15 09:11:46 -0500 (Wed, 15 Jun 2005) $
00011  * Version:       $Revision: 17686 $
00012  * -----------------------------------------------------------------
00013  *
00014  ****************** <VPR heading END do not edit this line> ******************/
00015 
00016 /*************** <auto-copyright.pl BEGIN do not edit this line> **************
00017  *
00018  * VR Juggler is (C) Copyright 1998-2005 by Iowa State University
00019  *
00020  * Original Authors:
00021  *   Allen Bierbaum, Christopher Just,
00022  *   Patrick Hartling, Kevin Meinert,
00023  *   Carolina Cruz-Neira, Albert Baker
00024  *
00025  * This library is free software; you can redistribute it and/or
00026  * modify it under the terms of the GNU Library General Public
00027  * License as published by the Free Software Foundation; either
00028  * version 2 of the License, or (at your option) any later version.
00029  *
00030  * This library is distributed in the hope that it will be useful,
00031  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00032  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00033  * Library General Public License for more details.
00034  *
00035  * You should have received a copy of the GNU Library General Public
00036  * License along with this library; if not, write to the
00037  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00038  * Boston, MA 02111-1307, USA.
00039  *
00040  *************** <auto-copyright.pl END do not edit this line> ***************/
00041 
00042 #include <vpr/vprConfig.h>
00043 
00044 #if defined(VPR_OS_IRIX)
00045 // these includes are needed for accessing the SGI cycle counter.
00046 #include <sys/utsname.h>
00047 #include <sys/types.h>
00048 #include <sys/stat.h>
00049 #include <fcntl.h>
00050 #include <sys/mman.h>
00051 #include <unistd.h>
00052 #include <sys/syssgi.h>
00053 #endif
00054 
00055 #if defined(VPR_USE_NSPR)
00056 #  include <prinrval.h>
00057 #endif
00058 
00059 #ifdef VPR_SIMULATOR
00060 #  include <vpr/md/SIM/Controller.h>
00061 #endif
00062 
00063 #include <vpr/Util/Interval.h>
00064 #include <vpr/System.h>
00065 
00066 
00067 const vpr::Interval vpr::Interval::NoWait(0,vpr::Interval::Base);
00068 const vpr::Interval vpr::Interval::NoTimeout(0xffffffffUL, vpr::Interval::Base);
00069 const vpr::Interval vpr::Interval::HalfPeriod((0xffffffffUL/2), vpr::Interval::Base);
00070 
00071 namespace vpr
00072 {
00073 
00074    // Simulator-only version of vpr::Interval::setNow().
00075 #ifdef VPR_SIMULATOR
00076 void Interval::setNow()
00077 {
00078    mMicroSeconds = vpr::sim::Controller::instance()->getClock().getCurrentTime().getBaseVal();
00079 }
00080 #else
00081 void Interval::setNow()
00082 {
00083    setNowReal();
00084 }
00085 #endif /* ifdef VPR_SIMULATOR */
00086 
00087 //
00088 // Real implementation of setNow that uses the real clock time from the system
00089 //
00090 void Interval::setNowReal()
00091 {
00092 #if defined(VPR_OS_Windows)
00093    LARGE_INTEGER count, counts_per_sec;
00094 
00095    QueryPerformanceFrequency(&counts_per_sec);
00096 
00097    // XXX: Optimize this!!
00098    vpr::Uint64 counts_per_sec64;
00099    vpr::Uint64 counts_per_sec_high64;
00100    counts_per_sec_high64 = counts_per_sec.HighPart;
00101    counts_per_sec64 = counts_per_sec.LowPart;
00102    counts_per_sec64 += (counts_per_sec_high64 << 32);
00103    double usecs_per_count =
00104       (1.0f / (double) ((vpr::Int64) counts_per_sec64)) * 1000000.0f;
00105 
00106    if (QueryPerformanceCounter(&count))
00107    {
00108       vpr::Uint64 low  = count.LowPart;
00109       vpr::Uint64 high = count.HighPart;
00110       mMicroSeconds = low + (high << 32);
00111       mMicroSeconds =
00112          (vpr::Uint64) (((double) (vpr::Int64) mMicroSeconds) * usecs_per_count);
00113    }
00114 /*
00115    else
00116    {
00117 #if defined(__MINGW32__)
00118       mMicroSeconds = time();
00119 #elif defined(WIN16)
00120       mMicroSeconds = clock();        // milliseconds since application start
00121 #else
00122       mMicroSeconds = GetTickCount();  // milliseconds since system start
00123 #endif
00124    }
00125 */
00126 #elif defined(VPR_OS_IRIX) // SGI Cycle counter version
00127    if (mMmem_fd != -1)
00128    {
00129       if (64 == mClockWidth)
00130       {
00131          Uint64 temp = *(Uint64*)mTimerAddr;
00132          mTicks = temp;
00133          mMicroSeconds = temp*mTicksToMicroseconds;
00134       }
00135       else
00136       {
00137          // clockwidth <= 32. clockmask only relevent for width=24...?
00138          Uint64 ticks = mTicks;
00139          unsigned int now = *(unsigned int*)mTimerAddr, temp;
00140          unsigned int residual = mResidual;
00141          unsigned int previous = mPrevious;
00142 
00143          //if (now < previous)
00144          //   std::cout << "wraparound occurred!!!" << std::endl;
00145 
00146          temp = now - previous + residual;
00147          residual = temp & mClockMask;
00148          ticks += temp;
00149 
00150          mPrevious = now;
00151          mResidual = residual;
00152          mTicks = ticks;
00153          mMicroSeconds = ticks * mTicksToMicroseconds;
00154       }
00155    }
00156    else
00157    {
00158       // couldn't access the cycle counter for whatever reason.
00159       // use gettimeofday as our fallback.
00160       timeval cur_time;
00161       gettimeofday(&cur_time);
00162       vpr::Uint64 storage = vpr::Uint64(1000000u) * vpr::Uint64(cur_time.tv_sec);
00163       mMicroSeconds = vpr::Uint64(cur_time.tv_usec) + storage;
00164    }
00165 #else    // Default to POSIX time setting
00166    vpr::TimeVal cur_time;
00167    vpr::System::gettimeofday(&cur_time);
00168    vpr::Uint64 storage = vpr::Uint64(1000000u) * vpr::Uint64(cur_time.tv_sec);
00169    mMicroSeconds = vpr::Uint64(cur_time.tv_usec) + storage;
00170 #endif
00171 }
00172 
00173 
00174 #if defined(VPR_OS_IRIX) // SGI Cycle counter version support code
00175 
00176 
00177 bool Interval::initializeCycleCounter()
00178 {
00179    /*
00180     * As much as I would like, the service available through this
00181     * interface on R3000's (aka, IP12) just isn't going to make it.
00182     * The register is only 24 bits wide, and rolls over at a voracious
00183     * rate.
00184     */
00185    mMmem_fd = -1;
00186    mClockWidth = 0;
00187    mTimerAddr = NULL;
00188    mClockMask = 0;
00189    mPrevious = 0;          // used for wraparound handling
00190    mResidual = 0;          // used for wraparound handling
00191 
00192    /* on R3000 (IP12) don't even try to use the 24 bit cycle counter. */
00193    struct utsname utsinfo;
00194    uname(&utsinfo);
00195    if ( (strncmp("IP12", utsinfo.machine, 4) != 0) &&
00196         ((mMmem_fd = open("/dev/mmem", O_RDONLY)) != -1) )
00197    {
00198       int poffmask = getpagesize() - 1;
00199       __psunsigned_t phys_addr, raddr;
00200       vpr::Uint32 cycleval;
00201 
00202       phys_addr = syssgi(SGI_QUERY_CYCLECNTR, &cycleval);
00203       raddr = phys_addr & ~poffmask;
00204       mTimerAddr = mmap(0, poffmask, PROT_READ, MAP_PRIVATE, mMmem_fd,
00205                         (__psint_t)raddr);
00206 
00207       mClockWidth = syssgi(SGI_CYCLECNTR_SIZE);
00208       if (mClockWidth < 0)
00209       {
00210          /*
00211           * We must be executing on a 6.0 or earlier system, since the
00212           * SGI_CYCLECNTR_SIZE call is not supported.
00213           *
00214           * The only pre-6.1 platforms with 64-bit counters are
00215           * IP19 and IP21 (Challenge, PowerChallenge, Onyx).
00216           */
00217          if (!strncmp(utsinfo.machine, "IP19", 4) ||
00218              !strncmp(utsinfo.machine, "IP21", 4))
00219          {
00220             mClockWidth = 64;
00221          }
00222          else
00223          {
00224             mClockWidth = 32;
00225          }
00226       }
00227 
00228       //std::cout << "cycleval is " << cycleval << " ps." << std::endl;
00229 
00230       mTicksToMicroseconds = cycleval / 1000000.0L;
00231       mClockMask = (1 << mClockWidth) -1;
00232       mTimerAddr = (void*)
00233          ((__psunsigned_t)mTimerAddr + (phys_addr & poffmask));
00234    }
00235 
00236    return true;
00237 }
00238 
00239 int Interval::mMmem_fd;
00240 int Interval::mClockWidth;
00241 void *Interval::mTimerAddr;
00242 vpr::Uint32 Interval::mClockMask;         // used for short cycle counters
00243 vpr::Uint32 Interval::mPrevious;          // used for wraparound handling
00244 vpr::Uint32 Interval::mResidual;          // used for wraparound handling
00245 double  Interval::mTicksToMicroseconds;
00246 
00247 const bool Interval::mInitialized = Interval::initializeCycleCounter();
00248 
00249 #endif // VPR_OS_IRIX cycle counter version
00250 
00251 } // namespace vpr
00252 

Generated on Thu Jan 4 10:52:09 2007 for VR Juggler Portable Runtime by  doxygen 1.5.1