* Authors: Nathan Binkert
*/
-#include <sys/types.h>
-#include <sys/time.h>
-#include <time.h>
+#include "base/time.hh"
+
+#include <cstdlib>
+#include <ctime>
#include <iostream>
-#include <string>
+#include <sstream>
-#include "base/time.hh"
+#include "base/logging.hh"
+#include "config/use_posix_clock.hh"
+#include "sim/core.hh"
+#include "sim/serialize.hh"
using namespace std;
-struct _timeval
+void
+Time::_set(bool monotonic)
{
+#if USE_POSIX_CLOCK
+ ::clock_gettime(monotonic ? CLOCK_MONOTONIC : CLOCK_REALTIME, &_time);
+#else
timeval tv;
-};
-
-double
-convert(const timeval &tv)
-{
- return (double)tv.tv_sec + (double)tv.tv_usec / 1000000.0;
+ ::gettimeofday(&tv, NULL);
+ operator=(tv);
+#endif
}
-Time::Time(bool set_now)
+void
+Time::setTick(Tick ticks)
{
- time = new _timeval;
- if (set_now)
- set();
+ uint64_t secs = ticks / SimClock::Frequency;
+ ticks -= secs * SimClock::Frequency;
+ uint64_t nsecs = static_cast<uint64_t>(ticks * SimClock::Float::GHz);
+ set(secs, nsecs);
}
-Time::Time(const timeval &val)
+Tick
+Time::getTick() const
{
- time = new _timeval;
- set(val);
+ return sec() * SimClock::Frequency +
+ static_cast<uint64_t>(nsec() * SimClock::Float::ns);
}
-Time::Time(const Time &val)
+string
+Time::date(const string &format) const
{
- time = new _timeval;
- set(val.get());
-}
+ time_t sec = this->sec();
+ char buf[256];
-Time::~Time()
-{
- delete time;
+ if (format.empty()) {
+#ifdef __SUNPRO_CC
+ ctime_r(&sec, buf, sizeof(buf));
+#else
+ ctime_r(&sec, buf);
+#endif
+ buf[24] = '\0';
+ return buf;
+ }
+
+ struct tm *tm = localtime(&sec);
+ strftime(buf, sizeof(buf), format.c_str(), tm);
+ return buf;
}
-const timeval &
-Time::get() const
+string
+Time::time() const
{
- return time->tv;
+ double time = double(*this);
+ double secs = fmod(time, 60.0);
+ double all_mins = floor(time / 60.0);
+ double mins = fmod(all_mins, 60.0);
+ double hours = floor(all_mins / 60.0);
+
+ stringstream str;
+
+ if (hours > 0.0) {
+ if (hours < 10.0)
+ str << '0';
+ str << hours << ':';
+ }
+
+ if (mins > 0.0) {
+ if (mins < 10.0)
+ str << '0';
+ str << mins << ':';
+ }
+
+ if (secs < 10.0 && !str.str().empty())
+ str << '0';
+ str << secs;
+
+ return str.str();
}
void
-Time::set()
+Time::serialize(const std::string &base, CheckpointOut &cp) const
{
- ::gettimeofday(&time->tv, NULL);
+ paramOut(cp, base + ".sec", sec());
+ paramOut(cp, base + ".nsec", nsec());
}
void
-Time::set(const timeval &tv)
+Time::unserialize(const std::string &base, CheckpointIn &cp)
{
- memcpy(&time->tv, &tv, sizeof(timeval));
+ time_t secs;
+ time_t nsecs;
+ paramIn(cp, base + ".sec", secs);
+ paramIn(cp, base + ".nsec", nsecs);
+ sec(secs);
+ nsec(nsecs);
}
-double
-Time::operator()() const
+void
+sleep(const Time &time)
{
- return convert(get());
+ timespec ts = time;
+
+#if USE_POSIX_CLOCK
+ clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL);
+#else
+ nanosleep(&ts, NULL);
+#endif
}
-string
-Time::date(string format) const
+time_t
+mkutctime(struct tm *time)
{
- const timeval &tv = get();
- time_t sec = tv.tv_sec;
- char buf[256];
-
- if (format.empty()) {
- ctime_r(&sec, buf);
- buf[24] = '\0';
- return buf;
+ // get the current timezone
+ char *tz = getenv("TZ");
+
+ // copy the string as the pointer gets invalidated when updating
+ // the environment
+ if (tz) {
+ tz = strdup(tz);
+ if (!tz) {
+ fatal("Failed to reserve memory for UTC time conversion\n");
+ }
}
- struct tm *tm = localtime(&sec);
- strftime(buf, sizeof(buf), format.c_str(), tm);
- return buf;
-}
-
-ostream &
-operator<<(ostream &out, const Time &start)
-{
- out << start.date();
- return out;
-}
+ // change to UTC and get the time
+ setenv("TZ", "", 1);
+ tzset();
+ time_t ret = mktime(time);
+
+ // restore the timezone again
+ if (tz) {
+ setenv("TZ", tz, 1);
+ free(tz);
+ } else {
+ unsetenv("TZ");
+ }
+ tzset();
-Time
-operator-(const Time &l, const Time &r)
-{
- timeval tv;
- timersub(&l.get(), &r.get(), &tv);
- return tv;
+ return ret;
}
-const Time Time::start(true);