/*
 * Copyright (c) 2007 MIPS Technologies, Inc.
 * All rights reserved.
 *
 * 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: Korey Sewell
 *
 */

#include "cpu/inorder/pipeline_traits.hh"
#include "cpu/inorder/inorder_dyn_inst.hh"
#include "cpu/inorder/resources/resource_list.hh"

using namespace std;

namespace ThePipeline {

//@TODO: create my own Instruction Schedule Class
//that operates as a Priority QUEUE
int getNextPriority(DynInstPtr &inst, int stage_num)
{
    int cur_pri = 20;

    /*
    std::priority_queue<ScheduleEntry*, std::vector<ScheduleEntry*>,
        entryCompare>::iterator sked_it = inst->resSched.begin();

    std::priority_queue<ScheduleEntry*, std::vector<ScheduleEntry*>,
        entryCompare>::iterator sked_end = inst->resSched.end();

    while (sked_it != sked_end) {

        if (sked_it.top()->stageNum == stage_num) {
            cur_pri = sked_it.top()->priority;
        }

        sked_it++;
    }
    */

    return cur_pri;
}

void createFrontEndSchedule(DynInstPtr &inst)
{
    InstStage *I = inst->addStage();
    InstStage *E = inst->addStage();

    I->needs(FetchSeq, FetchSeqUnit::AssignNextPC);
    I->needs(ICache, CacheUnit::InitiateFetch);

    E->needs(ICache, CacheUnit::CompleteFetch);
    E->needs(Decode, DecodeUnit::DecodeInst);
    E->needs(BPred, BranchPredictor::PredictBranch);
    E->needs(FetchSeq, FetchSeqUnit::UpdateTargetPC);
}

bool createBackEndSchedule(DynInstPtr &inst)
{
    if (!inst->staticInst) {
        return false;
    }

    InstStage *E = inst->currentStage();
    InstStage *M = inst->addStage();
    InstStage *A = inst->addStage();
    InstStage *W = inst->addStage();

    for (int idx=0; idx < inst->numSrcRegs(); idx++) {
        if (!idx || !inst->isStore()) {
            E->needs(RegManager, UseDefUnit::ReadSrcReg, idx);
        }
    }


    if ( inst->isNonSpeculative() ) {
        // skip execution of non speculative insts until later
    } else if ( inst->isMemRef() ) {
        if ( inst->isLoad() ) {
            E->needs(AGEN, AGENUnit::GenerateAddr);
            E->needs(DCache, CacheUnit::InitiateReadData);
        }
    } else if (inst->opClass() == IntMultOp || inst->opClass() == IntDivOp) {
        E->needs(MDU, MultDivUnit::StartMultDiv);
    } else {
        E->needs(ExecUnit, ExecutionUnit::ExecuteInst);
    }

    if (inst->opClass() == IntMultOp || inst->opClass() == IntDivOp) {
        M->needs(MDU, MultDivUnit::EndMultDiv);
    }

    if ( inst->isLoad() ) {
        M->needs(DCache, CacheUnit::CompleteReadData);
    } else if ( inst->isStore() ) {
        M->needs(RegManager, UseDefUnit::ReadSrcReg, 1);
        M->needs(AGEN, AGENUnit::GenerateAddr);
        M->needs(DCache, CacheUnit::InitiateWriteData);
    }

    if ( inst->isStore() ) {
        A->needs(DCache, CacheUnit::CompleteWriteData);
    }

    if ( inst->isNonSpeculative() ) {
        if ( inst->isMemRef() ) fatal("Non-Speculative Memory Instruction");
        W->needs(ExecUnit, ExecutionUnit::ExecuteInst);
    }

    for (int idx=0; idx < inst->numDestRegs(); idx++) {
        W->needs(RegManager, UseDefUnit::WriteDestReg, idx);
    }

    W->needs(Grad, GraduationUnit::GraduateInst);

    return true;
}

InstStage::InstStage(DynInstPtr inst, int stage_num)
{
    stageNum = stage_num;
    nextTaskPriority = 0;
    instSched = &inst->resSched;
}

};
