/*
 * Copyright 2018 Google, Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <cmath>
#include <cstring>
#include <sstream>
#include <vector>

#include "base/types.hh"
#include "sim/core.hh"
#include "systemc/core/time.hh"
#include "systemc/ext/core/messages.hh"
#include "systemc/ext/core/sc_main.hh"
#include "systemc/ext/core/sc_time.hh"
#include "systemc/ext/utils/sc_report_handler.hh"

namespace sc_core
{

namespace
{

void
set(::sc_core::sc_time *time, double d, ::sc_core::sc_time_unit tu)
{
    if (d != 0)
        gem5::fixClockFrequency();

    double scale = sc_gem5::TimeUnitScale[tu] * gem5::sim_clock::as_float::s;
    // Accellera claims there is a linux bug, and that these next two
    // lines work around them.
    volatile double tmp = d * scale + 0.5;
    *time = sc_time::from_value(static_cast<uint64_t>(tmp));
}

double defaultUnit = 1.0e-9;

} // anonymous namespace

sc_time::sc_time() : val(0) {}

sc_time::sc_time(double d, sc_time_unit tu)
{
    val = 0;
    set(this, d, tu);
}

sc_time::sc_time(const sc_time &t)
{
    val = t.val;
}

sc_time::sc_time(double d, const char *unit)
{
    sc_time_unit tu;
    for (tu = SC_FS; tu <= SC_SEC; tu = (sc_time_unit)(tu + 1)) {
        if (strcmp(unit, sc_gem5::TimeUnitNames[tu]) == 0 ||
            strcmp(unit, sc_gem5::TimeUnitConstantNames[tu]) == 0) {
            break;
        }
    }

    if (tu > SC_SEC) {
        SC_REPORT_ERROR(SC_ID_TIME_CONVERSION_FAILED_,"invalid unit given");
        val = 0;
        return;
    }
    set(this, d, tu);
}

sc_time::sc_time(double d, bool scale)
{
    double scaler = scale ? defaultUnit : gem5::sim_clock::as_float::Hz;
    set(this, d * scaler, SC_SEC);
}

sc_time::sc_time(sc_dt::uint64 v, bool scale)
{
    double scaler = scale ? defaultUnit : gem5::sim_clock::as_float::Hz;
    set(this, static_cast<double>(v) * scaler, SC_SEC);
}

sc_time &
sc_time::operator = (const sc_time &t)
{
    val = t.val;
    return *this;
}

sc_dt::uint64
sc_time::value() const
{
    return val;
}

double
sc_time::to_double() const
{
    return static_cast<double>(val);
}
double
sc_time::to_seconds() const
{
    return to_double() * gem5::sim_clock::as_float::Hz;
}

const std::string
sc_time::to_string() const
{
    std::ostringstream ss;
    print(ss);
    return ss.str();
}

bool
sc_time::operator == (const sc_time &t) const
{
    return val == t.val;
}

bool
sc_time::operator != (const sc_time &t) const
{
    return val != t.val;
}

bool
sc_time::operator < (const sc_time &t) const
{
    return val < t.val;
}

bool
sc_time::operator <= (const sc_time &t) const
{
    return val <= t.val;
}

bool
sc_time::operator > (const sc_time &t) const
{
    return val > t.val;
}

bool
sc_time::operator >= (const sc_time &t) const
{
    return val >= t.val;
}

sc_time &
sc_time::operator += (const sc_time &t)
{
    val += t.val;
    return *this;
}

sc_time &
sc_time::operator -= (const sc_time &t)
{
    val -= t.val;
    return *this;
}

sc_time &
sc_time::operator *= (double d)
{
    val = static_cast<int64_t>(static_cast<double>(val) * d + 0.5);
    return *this;
}

sc_time &
sc_time::operator /= (double d)
{
    val = static_cast<int64_t>(static_cast<double>(val) / d + 0.5);
    return *this;
}

void
sc_time::print(std::ostream &os) const
{
    os << sc_time_tuple(*this).to_string();
}

sc_time
sc_time::from_value(sc_dt::uint64 u)
{
    if (u)
        gem5::fixClockFrequency();
    sc_time t;
    t.val = u;
    return t;
}

sc_time
sc_time::from_seconds(double d)
{
    sc_time t;
    set(&t, d, SC_SEC);
    return t;
}

sc_time
sc_time::from_string(const char *str)
{
    char *end = nullptr;

    double d = str ? std::strtod(str, &end) : 0.0;
    if (str == end || d < 0.0) {
        SC_REPORT_ERROR(SC_ID_TIME_CONVERSION_FAILED_, "invalid value given");
        return SC_ZERO_TIME;
    }

    while (*end && std::isspace(*end))
        end++;

    return sc_time(d, end);
}

const sc_time
operator + (const sc_time &a, const sc_time &b)
{
    return sc_time::from_value(a.value() + b.value());
}

const sc_time
operator - (const sc_time &a, const sc_time &b)
{
    return sc_time::from_value(a.value() - b.value());
}

const sc_time
operator * (const sc_time &t, double d)
{
    volatile double tmp = static_cast<double>(t.value()) * d + 0.5;
    return sc_time::from_value(static_cast<int64_t>(tmp));
}

const sc_time
operator * (double d, const sc_time &t)
{
    volatile double tmp = d * static_cast<double>(t.value()) + 0.5;
    return sc_time::from_value(static_cast<int64_t>(tmp));
}

const sc_time
operator / (const sc_time &t, double d)
{
    volatile double tmp = static_cast<double>(t.value()) / d + 0.5;
    return sc_time::from_value(static_cast<int64_t>(tmp));
}

double
operator / (const sc_time &t1, const sc_time &t2)
{
    return t1.to_double() / t2.to_double();
}

std::ostream &
operator << (std::ostream &os, const sc_time &t)
{
    t.print(os);
    return os;
}

const sc_time SC_ZERO_TIME;

void
sc_set_time_resolution(double d, sc_time_unit tu)
{
    if (d <= 0.0)
        SC_REPORT_ERROR(SC_ID_SET_TIME_RESOLUTION_, "value not positive");

    double dummy;
    if (modf(log10(d), &dummy) != 0.0) {
        SC_REPORT_ERROR(SC_ID_SET_TIME_RESOLUTION_,
                "value not a power of ten");
    }
    if (sc_is_running())
        SC_REPORT_ERROR(SC_ID_SET_TIME_RESOLUTION_, "simulation running");

    static bool specified = false;
    if (specified)
        SC_REPORT_ERROR(SC_ID_SET_TIME_RESOLUTION_, "already specified");

    // This won't detect the timescale being fixed outside of systemc, but
    // it's at least some protection.
    if (gem5::clockFrequencyFixed()) {
        SC_REPORT_ERROR(SC_ID_SET_TIME_RESOLUTION_,
                "sc_time object(s) constructed");
    }

    double seconds = d * sc_gem5::TimeUnitScale[tu];
    if (seconds < sc_gem5::TimeUnitScale[SC_FS])
        SC_REPORT_ERROR(SC_ID_SET_TIME_RESOLUTION_, "value smaller than 1 fs");

    if (seconds > defaultUnit) {
        SC_REPORT_WARNING(SC_ID_DEFAULT_TIME_UNIT_CHANGED_, "");
        defaultUnit = seconds;
    }

    // Get rid of fractional parts of d.
    while (d < 1.0 && tu > SC_FS) {
        d *= 1000;
        tu = (sc_time_unit)(tu - 1);
    }

    gem5::Tick ticks_per_second =
        sc_gem5::TimeUnitFrequency[tu] / static_cast<gem5::Tick>(d);
    gem5::setClockFrequency(ticks_per_second);
    specified = true;
}

sc_time
sc_get_time_resolution()
{
    return sc_time::from_value(1);
}

const sc_time &
sc_max_time()
{
    static const sc_time MaxScTime = sc_time::from_value(gem5::MaxTick);
    return MaxScTime;
}

void
sc_set_default_time_unit(double d, sc_time_unit tu)
{
    if (d < 0.0)
        SC_REPORT_ERROR(SC_ID_SET_DEFAULT_TIME_UNIT_, "value not positive");

    double dummy;
    if (modf(log10(d), &dummy) != 0.0) {
        SC_REPORT_ERROR(SC_ID_SET_DEFAULT_TIME_UNIT_,
                "value not a power of ten");
    }
    if (sc_is_running())
        SC_REPORT_ERROR(SC_ID_SET_DEFAULT_TIME_UNIT_, "simulation running");

    static bool specified = false;
    if (specified) {
        SC_REPORT_ERROR(SC_ID_SET_DEFAULT_TIME_UNIT_, "already specified");
    }
    // This won't detect the timescale being fixed outside of systemc, but
    // it's at least some protection.
    if (gem5::clockFrequencyFixed()) {
        SC_REPORT_ERROR(SC_ID_SET_DEFAULT_TIME_UNIT_,
                "sc_time object(s) constructed");
    }

    // Normalize d to seconds.
    defaultUnit = d * sc_gem5::TimeUnitScale[tu];
    specified = true;

    double resolution = gem5::sim_clock::as_float::Hz;
    if (resolution == 0.0)
        resolution = sc_gem5::TimeUnitScale[SC_PS];
    if (defaultUnit < resolution) {
        SC_REPORT_ERROR(SC_ID_SET_DEFAULT_TIME_UNIT_,
                "value smaller than time resolution");
    }
}

sc_time
sc_get_default_time_unit()
{
    return sc_time(defaultUnit, SC_SEC);
}

sc_time_tuple::sc_time_tuple(const sc_time &t) :
    _value(), _unit(SC_SEC), _set(true)
{
    if (!t.value())
        return;

    gem5::Tick frequency = gem5::sim_clock::Frequency;

    // Shrink the frequency by scaling down the time period, ie converting
    // it from cycles per second to cycles per millisecond, etc.
    while (_unit > 1 && (frequency % 1000 == 0)) {
        _unit = (sc_time_unit)((int)_unit - 1);
        frequency /= 1000;
    }

    // Convert the frequency into a period.
    gem5::Tick period;
    if (frequency > 1) {
        _unit = (sc_time_unit)((int)_unit - 1);
        period = 1000 / frequency;
    } else {
        period = frequency;
    }

    // Scale our integer value by the period.
    _value = t.value() * period;

    // Shrink the scaled time value by increasing the size of the units
    // it's measured by, avoiding fractional parts.
    while (_unit < SC_SEC && (_value % 1000) == 0) {
        _unit = (sc_time_unit)((int)_unit + 1);
        _value /= 1000;
    }
}

bool
sc_time_tuple::has_value() const
{
    return _set;
}

sc_dt::uint64 sc_time_tuple::value() const { return _value; }

const char *
sc_time_tuple::unit_symbol() const
{
    return sc_gem5::TimeUnitNames[_unit];
}

double sc_time_tuple::to_double() const { return static_cast<double>(_value); }

std::string
sc_time_tuple::to_string() const
{
    std::ostringstream ss;
    ss << _value << ' ' << unit_symbol();
    return ss.str();
}

} // namespace sc_core
