/*
 * 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.
 *
 * Authors: Akash Bagdia
 *          David Guillen Fandos
 */

#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)
{
    // 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;

    numPwrStateTransitions++;
}

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

    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) {
        pwrStateClkGateDist.sample(elapsed_time);
    }

    prvEvalTick = curTick();
}

std::vector<double>
ClockedObject::pwrStateWeights() const
{
    // Get residency stats
    std::vector<double> ret;
    Stats::VCounter residencies;
    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] / \
                     (pwrStateResidencyTicks.total() + elapsed_time);

    return ret;
}

void
ClockedObject::regStats()
{
    SimObject::regStats();

    using namespace Stats;

    numPwrStateTransitions
        .name(params()->name + ".numPwrStateTransitions")
        .desc("Number of power state transitions")
        .flags(nozero)
        ;

    // Each sample is time in ticks
    unsigned num_bins = std::max(params()->p_state_clk_gate_bins, 10U);
    pwrStateClkGateDist
        .init(params()->p_state_clk_gate_min, params()->p_state_clk_gate_max,
          (params()->p_state_clk_gate_max / num_bins))
        .name(params()->name + ".pwrStateClkGateDist")
        .desc("Distribution of time spent in the clock gated state")
        .flags(pdf | nozero | nonan)
        ;

    pwrStateResidencyTicks
        .init(Enums::PwrState::Num_PwrState)
        .name(params()->name + ".pwrStateResidencyTicks")
        .desc("Cumulative time (in ticks) in various power states")
        .flags(nozero)
        ;
    for (int i = 0; i < Enums::PwrState::Num_PwrState; i++) {
        pwrStateResidencyTicks.subname(i, Enums::PwrStateStrings[i]);
    }

    numPwrStateTransitions = 0;

    /**
     * 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).
     */
    registerDumpCallback(new ClockedObjectDumpCallback(this));
}
