/*
 * Copyright (c) 2013-2014 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 "cpu/minor/func_unit.hh"

#include <iomanip>
#include <sstream>
#include <typeinfo>

#include "base/named.hh"
#include "base/trace.hh"
#include "debug/MinorTiming.hh"
#include "enums/OpClass.hh"

namespace gem5
{

MinorOpClassSet::MinorOpClassSet(const MinorOpClassSetParams &params) :
    SimObject(params),
    opClasses(params.opClasses),
    /* Initialise to true for an empty list so that 'fully capable' is
     *  the default */
    capabilityList(Num_OpClasses, (opClasses.empty() ? true : false))
{
    for (unsigned int i = 0; i < opClasses.size(); i++)
        capabilityList[opClasses[i]->opClass] = true;
}

MinorFUTiming::MinorFUTiming(
    const MinorFUTimingParams &params) :
    SimObject(params),
    mask(params.mask),
    match(params.match),
    description(params.description),
    suppress(params.suppress),
    extraCommitLat(params.extraCommitLat),
    extraCommitLatExpr(params.extraCommitLatExpr),
    extraAssumedLat(params.extraAssumedLat),
    srcRegsRelativeLats(params.srcRegsRelativeLats),
    opClasses(params.opClasses)
{ }

GEM5_DEPRECATED_NAMESPACE(Minor, minor);
namespace minor
{

void
QueuedInst::reportData(std::ostream &os) const
{
    inst->reportData(os);
}

FUPipeline::FUPipeline(const std::string &name, const MinorFU &description_,
    ClockedObject &timeSource_) :
    FUPipelineBase(name, "insts", description_.opLat),
    description(description_),
    timeSource(timeSource_),
    nextInsertCycle(Cycles(0))
{
    /* Issue latencies are set to 1 in calls to addCapability here.
     * Issue latencies are associated with the pipeline as a whole,
     * rather than instruction classes in Minor */

    /* All pipelines should be able to execute No_OpClass instructions */
    addCapability(No_OpClass, description.opLat, 1);

    /* Add the capabilities listed in the MinorFU for this functional unit */
    for (unsigned int i = 0; i < description.opClasses->opClasses.size();
         i++)
    {
        addCapability(description.opClasses->opClasses[i]->opClass,
            description.opLat, 1);
    }

    for (unsigned int i = 0; i < description.timings.size(); i++) {
        MinorFUTiming &timing = *(description.timings[i]);

        if (debug::MinorTiming) {
            std::ostringstream lats;

            unsigned int num_lats = timing.srcRegsRelativeLats.size();
            unsigned int j = 0;
            while (j < num_lats) {
                lats << timing.srcRegsRelativeLats[j];

                j++;
                if (j != num_lats)
                    lats << ',';
            }

            DPRINTFS(MinorTiming, static_cast<Named *>(this),
                "Adding extra timing decode pattern %d to FU"
                " mask: %016x match: %016x srcRegLatencies: %s\n",
                i, timing.mask, timing.match, lats.str());
        }
    }

    const std::vector<unsigned> &cant_forward =
        description.cantForwardFromFUIndices;

    /* Setup the bit vector cantForward... with the set indices
     *  specified in the parameters */
    for (auto i = cant_forward.begin(); i != cant_forward.end(); ++i) {
        cantForwardFromFUIndices.resize((*i) + 1, false);
        cantForwardFromFUIndices[*i] = true;
    }
}

Cycles
FUPipeline::cyclesBeforeInsert()
{
    if (nextInsertCycle == 0 || timeSource.curCycle() > nextInsertCycle)
        return Cycles(0);
    else
        return nextInsertCycle - timeSource.curCycle();
}

bool
FUPipeline::canInsert() const
{
    return nextInsertCycle == 0 || timeSource.curCycle() >= nextInsertCycle;
}

void
FUPipeline::advance()
{
    bool was_stalled = stalled;

    /* If an instruction was pushed into the pipeline, set the delay before
     *  the next instruction can follow */
    if (alreadyPushed()) {
        if (nextInsertCycle <= timeSource.curCycle()) {
            nextInsertCycle = timeSource.curCycle() + description.issueLat;
        }
    } else if (was_stalled && nextInsertCycle != 0) {
        /* Don't count stalled cycles as part of the issue latency */
        ++nextInsertCycle;
    }
    FUPipelineBase::advance();
}

MinorFUTiming *
FUPipeline::findTiming(const StaticInstPtr &inst)
{
    /*
     * This will only work on ISAs with an instruction format with a fixed size
     * which can be categorized using bit masks. This is really only supported
     * on ARM and is a bit of a hack.
     */
    uint64_t mach_inst = inst->getEMI();

    const std::vector<MinorFUTiming *> &timings =
        description.timings;
    unsigned int num_timings = timings.size();

    for (unsigned int i = 0; i < num_timings; i++) {
        MinorFUTiming &timing = *timings[i];

        if (timing.provides(inst->opClass()) &&
            (mach_inst & timing.mask) == timing.match)
        {
            DPRINTFS(MinorTiming, static_cast<Named *>(this),
                "Found extra timing match (pattern %d '%s')"
                " %s %16x (type %s)\n",
                i, timing.description, inst->disassemble(0), mach_inst,
                typeid(inst).name());

            return &timing;
        }
    }

    if (num_timings != 0) {
        DPRINTFS(MinorTiming, static_cast<Named *>(this),
            "No extra timing info. found for inst: %s"
            " mach_inst: %16x\n",
            inst->disassemble(0), mach_inst);
    }

    return NULL;
}

} // namespace minor
} // namespace gem5
