/*
 * Copyright (c) 2017, 2019-2020 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/power_domain.hh"

#include <unordered_map>

#include "base/trace.hh"
#include "debug/PowerDomain.hh"

namespace gem5
{

PowerDomain::PowerDomain(const PowerDomainParams &p) :
    PowerState(p),
    leaders(p.leaders),
    pwrStateUpdateEvent(*this),
    stats(*this)
{
    // Check if there is at least one leader
    fatal_if(leaders.empty(), "No leaders registered in %s!)", name());

    // Go over the leaders and register this power domain with them
    for (auto leader : leaders) {
        leader->setControlledDomain(this);
    }

    // We will assume a power domain to start in the most performant p-state
    // This will be corrected during startup()
    leaderTargetState = enums::PwrState::ON;
    _currState = enums::PwrState::ON;
}

void
PowerDomain::addFollower(PowerState* pwr_obj)
{
    DPRINTF(PowerDomain, "%s is a follower in %s\n", pwr_obj->name(), name());
    followers.push_back(pwr_obj);
}

void
PowerDomain::startup()
{
    DPRINTF(PowerDomain, "Checks at startup\n");
    // Check if the leaders and followers have the correct power states.
    DPRINTF(PowerDomain, "Checking power state of leaders & followers\n");
    for (const auto &objs : { leaders, followers }) {
        for (const auto &obj : objs) {
            const auto & states = obj->getPossibleStates();
            auto it = states.find(enums::PwrState::ON);
            fatal_if(it == states.end(),
                     "%s in %s does not have the required power states to be "
                     "part of a PowerDomain i.e. the ON state!", obj->name(),
                     name());
        }
    }

    // Now all objects have been checked for the minimally required power
    // states, calculate the possible power states for the domain. This is the
    // intersection between the possible power states of the followers and
    // leaders.
    calculatePossiblePwrStates();

    // Check that there is no objects which is both a leader and a
    // follower.
    DPRINTF(PowerDomain, "Checking for double entries\n");
    for (auto follower : followers) {
        for (auto leader : leaders) {
            fatal_if(leader == follower, "%s is both a leader and follower"
                     " in %s\n!", leader->name(), name());
        }
    }
    // Record the power states of the leaders and followers
    DPRINTF(PowerDomain, "Recording the current power states in domain\n");
    for (auto leader : leaders) {
        enums::PwrState pws = leader->get();
        fatal_if(pws == enums::PwrState::UNDEFINED,
                 "%s is in the UNDEFINED power state, not acceptable as "
                 "leader!", leader->name());
    }

    // Calculate the power state of the domain, only looking at leader
    leaderTargetState = calculatePowerDomainState();
    // Set the power states of the followers, based upon leaderTargetState.
    setFollowerPowerStates();
}

bool
PowerDomain::isPossiblePwrState(enums::PwrState p_state)
{
    for (const auto &objs : { leaders, followers }) {
        for (const auto &obj : objs) {
            const auto &obj_states = obj->getPossibleStates();
            if (obj_states.find(p_state) == obj_states.end()) {
                return false;
            }
        }
    }
    return true;
}

void
PowerDomain::calculatePossiblePwrStates()
{
    assert(possibleStates.empty());
    for (auto p_state: leaders[0]->getPossibleStates()) {
        if (isPossiblePwrState(p_state)) {
            possibleStates.emplace(p_state);
            DPRINTF(PowerDomain, "%u/%s is a p-state\n", p_state,
                    enums::PwrStateStrings[p_state]);
        }
    }
}

enums::PwrState
PowerDomain::calculatePowerDomainState(
    const std::vector<enums::PwrState> &f_states)
{
    DPRINTF(PowerDomain, "Calculating the power state\n");
    enums::PwrState most_perf_state = enums::PwrState::Num_PwrState;
    std::string most_perf_leader;
    for (auto leader : leaders) {
        enums::PwrState pw = leader->get();
        if (pw < most_perf_state) {
            most_perf_state = pw;
            most_perf_leader = leader->name();
        }
    }
    assert(most_perf_state != enums::PwrState::Num_PwrState);
    DPRINTF(PowerDomain, "Most performant leader is %s, at %u\n",
                          most_perf_leader, most_perf_state);

    // If asked to check the power states of the followers (f_states contains
    // the power states of the followers)
    if (!f_states.empty()) {
        for (enums::PwrState f_pw : f_states ) {
            // Ignore UNDEFINED state of follower, at startup the followers
            // might be in the UNDEFINED state, PowerDomain will pull them up
            if ((f_pw != enums::PwrState::UNDEFINED) &&
                (f_pw  < most_perf_state)) {
                most_perf_state = f_pw;
            }
        }
        DPRINTF(PowerDomain, "Most performant state, including followers "
                             "is %u\n", most_perf_state);
    }
    return most_perf_state;
}

void
PowerDomain::setFollowerPowerStates()
{
    // Loop over all followers and tell them to change their power state so
    // they match that of the power domain (or a more performant power state)
    std::vector<enums::PwrState> matched_states;
    for (auto follower : followers) {
        enums::PwrState actual_pws =
            follower->matchPwrState(leaderTargetState);
        matched_states.push_back(actual_pws);
        assert(actual_pws <= leaderTargetState);
        DPRINTF(PowerDomain, "%u matched domain power state (%u) with %u\n",
                             follower->name(), leaderTargetState,
                             actual_pws);
    }
    // Now the power states of the follower have been changed recalculate the
    // power state of the domain as a whole, including followers
    enums::PwrState new_power_state =
        calculatePowerDomainState(matched_states);
    if (new_power_state != _currState) {
        // Change in power state of the domain, so update. Updates in power
        // state need to happen via set() so it can propagate to
        // overarching power domains (if there are any).
        DPRINTF(PowerDomain, "Updated power domain state to %u\n",
                             new_power_state);
        set(new_power_state);
    }
}

void
PowerDomain::pwrStateChangeCallback(enums::PwrState new_pwr_state,
                                    PowerState* leader)
{
    DPRINTF(PowerDomain, "PwrState update to %u by %s\n", new_pwr_state,
            leader->name());

    enums::PwrState old_target_state = leaderTargetState;
    // Calculate the power state of the domain, based on the leaders
    if (new_pwr_state < _currState) {
        // The power state of the power domain always needs to match that of
        // the most performant leader so no need to go over the other leaders
        // The power state need to be changed via a the PwrStateCall() so any
        // overarching power domains get informed
        leaderTargetState = new_pwr_state;
    } else {
        // Need to calculate the newly required power state, based on the
        // leaders only and change to that state.
        leaderTargetState = calculatePowerDomainState();
    }
    if (old_target_state!= leaderTargetState) {
        // The followers will try to match that power state requested by the
        // leaders in in the update event, based upon the actual power state,
        // we will 'officially' change the power state of the domain by calling
        // set()
        schedule(pwrStateUpdateEvent, curTick() + updateLatency);
        DPRINTF(PowerDomain, "TargetState change from %u to %u, followers will"
                "be updated in %u ticks\n", old_target_state,
                leaderTargetState, updateLatency);
        stats.numLeaderCallsChangingState++;
    }
    stats.numLeaderCalls++;
}

PowerDomain::PowerDomainStats::PowerDomainStats(PowerDomain &pd)
    : statistics::Group(&pd),
    ADD_STAT(numLeaderCalls, statistics::units::Count::get(),
             "Number of calls by leaders to change power domain state"),
    ADD_STAT(numLeaderCallsChangingState, statistics::units::Count::get(),
             "Number of calls by leader to change power domain state actually "
             "resulting in a power state change")
{
}

void
PowerDomain::PowerDomainStats::regStats()
{
    statistics::Group::regStats();

    numLeaderCalls
        .flags(statistics::nozero)
        ;
    numLeaderCallsChangingState
        .flags(statistics::nozero)
        ;
}

} // namespace gem5
