/*
 * 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/resources/resource_list.hh"
#include "cpu/inorder/inorder_dyn_inst.hh"
#include "cpu/inorder/pipeline_traits.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)
{
    int stNum = 0;
    int stPri = 0;
    // Get Pointer to Instuction's Schedule
    ResSchedule *inst_sched = &inst->resSched;

    //
    // Stage 0
    // ---------------------------------------
    inst_sched->push(new ScheduleEntry(stNum, stPri, FetchSeq, FetchSeqUnit::AssignNextPC));
    stPri++;

    inst_sched->push(new ScheduleEntry(stNum, stPri, ITLB, TLBUnit::FetchLookup));
    stPri++;

    inst_sched->push(new ScheduleEntry(stNum, stPri, ICache, CacheUnit::InitiateFetch));
    stPri++;

    // Reset Priority / Update Next Stage Number
    stNum++;
    stPri = 0;

    //
    // Stage 1
    // ---------------------------------------
    inst_sched->push(new ScheduleEntry(stNum, stPri, ICache, CacheUnit::CompleteFetch));
    stPri++;

    inst_sched->push(new ScheduleEntry(stNum, stPri, Decode, DecodeUnit::DecodeInst));
    stPri++;

    inst_sched->push(new ScheduleEntry(stNum, stPri, BPred, BranchPredictor::PredictBranch));
    stPri++;

    inst_sched->push(new ScheduleEntry(stNum, stPri, FetchSeq, FetchSeqUnit::UpdateTargetPC));
    stPri++;

    int fetch_buff_num = FetchBuff + inst->readTid();

    inst_sched->push(new ScheduleEntry(stNum, stPri, fetch_buff_num, InstBuffer::ScheduleOrBypass));

    // Reset Priority / Update Next Stage Number
    stNum++;
    stPri = 0;

    //
    // Stage 2
    // ---------------------------------------
    // Reset Priority / Update Next Stage Number
    stNum++;
    stPri = 0;
}

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

    std::string name = inst->staticInst->getName();

    int stNum = BackEndStartStage;
    int stPri = 0;

    // Get Pointer to Instuction's Schedule
    ResSchedule *inst_sched = &inst->resSched;

    //
    // Stage 3
    // ---------------------------------------
    // Set When Source Registers Should be read - Stage 4
    for (int idx=0; idx < inst->numSrcRegs(); idx++) {
        inst_sched->push(new ScheduleEntry(stNum, stPri, RegManager, UseDefUnit::ReadSrcReg, idx));
    }
    stPri++;

    // Reset Priority / Update Next Stage Number
    stPri = 0;
    stNum++;

    //
    // Stage 4
    // ---------------------------------------
    if (inst->isMemRef()) {
        inst_sched->push(new ScheduleEntry(stNum, stPri, AGEN, AGENUnit::GenerateAddr));
    }

    // Reset Priority / Update Next Stage Number
    stPri = 0;
    stNum++;

    //
    // Stage 5
    // ---------------------------------------
    // Execution Unit
    if (!inst->isNonSpeculative() && !inst->isMemRef()) {
        //if (inst->opClass() == IntMultOp || inst->opClass() == IntDivOp) {
            //inst_sched->push(new ScheduleEntry(stNum, stPri++, MDU, MultDivUnit::MultDiv));
            //} else {
            inst_sched->push(new ScheduleEntry(stNum, stPri, ExecUnit, ExecutionUnit::ExecuteInst));
            //}
    }
    stPri++;

    // DCache Initiate Access
    if (inst->isMemRef()) {
        inst_sched->push(new ScheduleEntry(stNum, stPri, DTLB, TLBUnit::DataLookup));
        stPri++;

        if (inst->isLoad()) {
            inst_sched->push(new ScheduleEntry(stNum, stPri, DCache, CacheUnit::InitiateReadData));
        } else if (inst->isStore()) {
            inst_sched->push(new ScheduleEntry(stNum, stPri, DCache, CacheUnit::InitiateWriteData));
        }
    }

    // Reset Priority / Update Next Stage Number
    stPri = 0;
    stNum++;

    //
    // Stage 6
    // ---------------------------------------
    // DCache Complete Access
    if (inst->isMemRef()) {
        if (inst->isLoad()) {
            inst_sched->push(new ScheduleEntry(stNum, stPri, DCache, CacheUnit::CompleteReadData));
        } else if (inst->isStore()) {
            inst_sched->push(new ScheduleEntry(stNum, stPri, DCache, CacheUnit::CompleteWriteData));
        }
    }

    // Reset Priority / Update Next Stage Number
    stPri = 0;
    stNum++;

    //
    // Stage 7
    // ---------------------------------------
    // Reset Priority / Update Next Stage Number
    stPri = 0;
    stNum++;

    //
    // Stage 8
    // ---------------------------------------
    // NonSpeculative Execution
    if (inst->isNonSpeculative() ) {
        if (inst->isMemRef())
            fatal("Schedule doesnt handle Non-Speculative Memory Instructions.\n");

        inst_sched->push(new ScheduleEntry(stNum, stPri, ExecUnit, ExecutionUnit::ExecuteInst));
        stPri++;
    }

    // Write Back to Register File
    for (int idx=0; idx < inst->numDestRegs(); idx++) {
        inst_sched->push(new ScheduleEntry(stNum, stPri, RegManager, UseDefUnit::WriteDestReg, idx));
        stPri++;
    }

    // Graduate Instructions
    inst_sched->push(new ScheduleEntry(stNum, stPri, Grad, GraduationUnit::GraduateInst));
    stPri++;

    // Reset Priority / Update Next Stage Number
    stPri = 0;
    stNum++;

    return true;
}

};
