/*
 * Copyright (c) 2015-2016 ARM Limited
 * All rights reserved
 *
 * The license below extends only to copyright in the software and shall
 * not be construed as granting a license to any other intellectual
 * property including but not limited to intellectual property relating
 * to a hardware implementation of the functionality of the software
 * licensed hereunder.  You may use the software subject to the license
 * terms below provided that you ensure that this notice is replicated
 * unmodified and in its entirety in all distributions of the software,
 * modified or unmodified, in source code or in binary form.
 *
 * 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 "sim/clocked_object.hh"

#include "base/logging.hh"
#include "sim/power/power_model.hh"

ClockedObject::ClockedObject(const ClockedObjectParams *p) :
    SimObject(p), Clocked(*p->clk_domain),
    _currPwrState(p->default_p_state),
    prvEvalTick(0),
    stats(*this)
{
    // Register the power_model with the object
    for (auto & power_model: p->power_model)
        power_model->setClockedObject(this);
}

void
ClockedObject::serialize(CheckpointOut &cp) const
{
    unsigned int currPwrState = (unsigned int)_currPwrState;

    SERIALIZE_SCALAR(currPwrState);
    SERIALIZE_SCALAR(prvEvalTick);
}

void
ClockedObject::unserialize(CheckpointIn &cp)
{
    unsigned int currPwrState;

    UNSERIALIZE_SCALAR(currPwrState);
    UNSERIALIZE_SCALAR(prvEvalTick);

    _currPwrState = Enums::PwrState(currPwrState);
}

void
ClockedObject::pwrState(Enums::PwrState p)
{
    // Function should ideally be called only when there is a state change
    if (_currPwrState == p) {
        warn_once("ClockedObject: Already in the requested power state, " \
                  "request ignored");
        return;
    }

    // No need to compute stats if in the same tick, update state though. This
    // can happen in cases like a) during start of the simulation multiple
    // state changes happens in init/startup phase, b) one takes a decision to
    // migrate state but decides to reverts back to the original state in the
    // same tick if other conditions are not met elsewhere.
    // Any state change related stats would have been recorded on previous call
    // to the pwrState() function.
    if (prvEvalTick == curTick() && curTick() != 0) {
       warn("ClockedObject %s: More than one power state change request "\
             "encountered within the same simulation tick %d",
             name(), prvEvalTick);
        _currPwrState = p;
        return;
    }

    // Record stats for previous state.
    computeStats();

    _currPwrState = p;

    stats.numPwrStateTransitions++;
}

void
ClockedObject::computeStats()
{
    // Calculate time elapsed from last (valid) state change
    Tick elapsed_time = curTick() - prvEvalTick;

    stats.pwrStateResidencyTicks[_currPwrState] += elapsed_time;

    // Time spent in CLK_GATED state, this might change depending on
    // transition to other low power states in respective simulation
    // objects.
    if (_currPwrState == Enums::PwrState::CLK_GATED) {
        stats.pwrStateClkGateDist.sample(elapsed_time);
    }

    prvEvalTick = curTick();
}

std::vector<double>
ClockedObject::pwrStateWeights() const
{
    // Get residency stats
    std::vector<double> ret;
    Stats::VCounter residencies;
    stats.pwrStateResidencyTicks.value(residencies);

    // Account for current state too!
    Tick elapsed_time = curTick() - prvEvalTick;
    residencies[_currPwrState] += elapsed_time;

    ret.resize(Enums::PwrState::Num_PwrState);
    for (unsigned i = 0; i < Enums::PwrState::Num_PwrState; i++)
        ret[i] = residencies[i] / \
                     (stats.pwrStateResidencyTicks.total() + elapsed_time);

    return ret;
}


ClockedObject::ClockedObjectStats::ClockedObjectStats(ClockedObject &co)
    : Stats::Group(&co),
    clockedObject(co),
    ADD_STAT(numPwrStateTransitions,
             "Number of power state transitions"),
    ADD_STAT(pwrStateClkGateDist,
             "Distribution of time spent in the clock gated state"),
    ADD_STAT(pwrStateResidencyTicks,
             "Cumulative time (in ticks) in various power states")
{
}

void
ClockedObject::ClockedObjectStats::regStats()
{
    Stats::Group::regStats();

    using namespace Stats;

    const ClockedObjectParams *p = clockedObject.params();

    numPwrStateTransitions.flags(nozero);

    // Each sample is time in ticks
    unsigned num_bins = std::max(p->p_state_clk_gate_bins, 10U);
    pwrStateClkGateDist
        .init(p->p_state_clk_gate_min, p->p_state_clk_gate_max,
          (p->p_state_clk_gate_max / num_bins))
        .flags(pdf | nozero | nonan)
        ;

    pwrStateResidencyTicks
        .init(Enums::PwrState::Num_PwrState)
        .flags(nozero)
        ;
    for (int i = 0; i < Enums::PwrState::Num_PwrState; i++) {
        pwrStateResidencyTicks.subname(i, Enums::PwrStateStrings[i]);
    }

    numPwrStateTransitions = 0;
}

void
ClockedObject::ClockedObjectStats::preDumpStats()
{
    Stats::Group::preDumpStats();

    /**
     * For every stats dump, the power state residency and other distribution
     * stats should be computed just before the dump to ensure correct stats
     * value being reported for current dump window. It avoids things like
     * having any unreported time spent in a power state to be forwarded to the
     * next dump window which might have rather unpleasant effects (like
     * perturbing the distribution stats).
     */
    clockedObject.computeStats();
}
