Merge ktlim@zamp:/z/ktlim2/clean/m5-o3
authorKevin Lim <ktlim@umich.edu>
Sun, 4 Jun 2006 20:07:54 +0000 (16:07 -0400)
committerKevin Lim <ktlim@umich.edu>
Sun, 4 Jun 2006 20:07:54 +0000 (16:07 -0400)
into  zamp.eecs.umich.edu:/z/ktlim2/clean/newmem-merge

src/cpu/checker/o3_cpu_builder.cc:
src/cpu/o3/alpha_cpu.hh:
src/cpu/o3/alpha_cpu_impl.hh:
src/cpu/o3/alpha_dyn_inst_impl.hh:
src/cpu/o3/bpred_unit.cc:
src/cpu/o3/commit.hh:
src/cpu/o3/fetch_impl.hh:
src/cpu/o3/lsq_unit.hh:
src/cpu/o3/lsq_unit_impl.hh:
src/cpu/o3/thread_state.hh:
    Hand merge.

--HG--
rename : cpu/activity.cc => src/cpu/activity.cc
rename : cpu/activity.hh => src/cpu/activity.hh
rename : cpu/base_dyn_inst.cc => src/cpu/base_dyn_inst.cc
rename : cpu/checker/cpu.hh => src/cpu/checker/cpu.hh
rename : cpu/checker/cpu_builder.cc => src/cpu/checker/cpu_builder.cc
rename : cpu/checker/exec_context.hh => src/cpu/checker/exec_context.hh
rename : cpu/checker/o3_cpu_builder.cc => src/cpu/checker/o3_cpu_builder.cc
rename : cpu/o3/2bit_local_pred.cc => src/cpu/o3/2bit_local_pred.cc
rename : cpu/o3/2bit_local_pred.hh => src/cpu/o3/2bit_local_pred.hh
rename : cpu/o3/alpha_cpu.hh => src/cpu/o3/alpha_cpu.hh
rename : cpu/o3/alpha_cpu_builder.cc => src/cpu/o3/alpha_cpu_builder.cc
rename : cpu/o3/alpha_cpu_impl.hh => src/cpu/o3/alpha_cpu_impl.hh
rename : cpu/o3/alpha_dyn_inst.hh => src/cpu/o3/alpha_dyn_inst.hh
rename : cpu/o3/alpha_dyn_inst_impl.hh => src/cpu/o3/alpha_dyn_inst_impl.hh
rename : cpu/o3/alpha_params.hh => src/cpu/o3/alpha_params.hh
rename : cpu/o3/bpred_unit.cc => src/cpu/o3/bpred_unit.cc
rename : cpu/o3/bpred_unit.hh => src/cpu/o3/bpred_unit.hh
rename : cpu/o3/bpred_unit_impl.hh => src/cpu/o3/bpred_unit_impl.hh
rename : cpu/o3/comm.hh => src/cpu/o3/comm.hh
rename : cpu/o3/commit.hh => src/cpu/o3/commit.hh
rename : cpu/o3/commit_impl.hh => src/cpu/o3/commit_impl.hh
rename : cpu/o3/cpu.hh => src/cpu/o3/cpu.hh
rename : cpu/o3/cpu_policy.hh => src/cpu/o3/cpu_policy.hh
rename : cpu/o3/decode.hh => src/cpu/o3/decode.hh
rename : cpu/o3/decode_impl.hh => src/cpu/o3/decode_impl.hh
rename : cpu/o3/dep_graph.hh => src/cpu/o3/dep_graph.hh
rename : cpu/o3/fetch.hh => src/cpu/o3/fetch.hh
rename : cpu/o3/fetch_impl.hh => src/cpu/o3/fetch_impl.hh
rename : cpu/o3/fu_pool.cc => src/cpu/o3/fu_pool.cc
rename : cpu/o3/fu_pool.hh => src/cpu/o3/fu_pool.hh
rename : cpu/o3/iew.hh => src/cpu/o3/iew.hh
rename : cpu/o3/iew_impl.hh => src/cpu/o3/iew_impl.hh
rename : cpu/o3/inst_queue.hh => src/cpu/o3/inst_queue.hh
rename : cpu/o3/inst_queue_impl.hh => src/cpu/o3/inst_queue_impl.hh
rename : cpu/o3/lsq.hh => src/cpu/o3/lsq.hh
rename : cpu/o3/lsq_unit.hh => src/cpu/o3/lsq_unit.hh
rename : cpu/o3/lsq_unit_impl.hh => src/cpu/o3/lsq_unit_impl.hh
rename : cpu/o3/mem_dep_unit.hh => src/cpu/o3/mem_dep_unit.hh
rename : cpu/o3/mem_dep_unit_impl.hh => src/cpu/o3/mem_dep_unit_impl.hh
rename : cpu/o3/rename.hh => src/cpu/o3/rename.hh
rename : cpu/o3/rename_impl.hh => src/cpu/o3/rename_impl.hh
rename : cpu/o3/rename_map.hh => src/cpu/o3/rename_map.hh
rename : cpu/o3/rob.hh => src/cpu/o3/rob.hh
rename : cpu/o3/store_set.cc => src/cpu/o3/store_set.cc
rename : cpu/o3/store_set.hh => src/cpu/o3/store_set.hh
rename : cpu/o3/thread_state.hh => src/cpu/o3/thread_state.hh
rename : cpu/o3/tournament_pred.cc => src/cpu/o3/tournament_pred.cc
rename : cpu/o3/tournament_pred.hh => src/cpu/o3/tournament_pred.hh
rename : cpu/ozone/cpu_builder.cc => src/cpu/ozone/cpu_builder.cc
rename : cpu/ozone/ozone_impl.hh => src/cpu/ozone/ozone_impl.hh
rename : cpu/ozone/simple_impl.hh => src/cpu/ozone/simple_impl.hh
rename : cpu/ozone/simple_params.hh => src/cpu/ozone/simple_params.hh
rename : python/m5/objects/AlphaFullCPU.py => src/python/m5/objects/AlphaFullCPU.py
rename : python/m5/objects/OzoneCPU.py => src/python/m5/objects/OzoneCPU.py
extra : convert_revision : b7be30474dd03dd3970e737a9d0489aeb2ead84f

54 files changed:
1  2 
src/cpu/activity.cc
src/cpu/activity.hh
src/cpu/base_dyn_inst.cc
src/cpu/checker/cpu.hh
src/cpu/checker/cpu_builder.cc
src/cpu/checker/exec_context.hh
src/cpu/checker/o3_cpu_builder.cc
src/cpu/o3/2bit_local_pred.cc
src/cpu/o3/2bit_local_pred.hh
src/cpu/o3/alpha_cpu.hh
src/cpu/o3/alpha_cpu_builder.cc
src/cpu/o3/alpha_cpu_impl.hh
src/cpu/o3/alpha_dyn_inst.hh
src/cpu/o3/alpha_dyn_inst_impl.hh
src/cpu/o3/alpha_params.hh
src/cpu/o3/bpred_unit.cc
src/cpu/o3/bpred_unit.hh
src/cpu/o3/bpred_unit_impl.hh
src/cpu/o3/comm.hh
src/cpu/o3/commit.hh
src/cpu/o3/commit_impl.hh
src/cpu/o3/cpu.hh
src/cpu/o3/cpu_policy.hh
src/cpu/o3/decode.hh
src/cpu/o3/decode_impl.hh
src/cpu/o3/dep_graph.hh
src/cpu/o3/fetch.hh
src/cpu/o3/fetch_impl.hh
src/cpu/o3/fu_pool.cc
src/cpu/o3/fu_pool.hh
src/cpu/o3/iew.hh
src/cpu/o3/iew_impl.hh
src/cpu/o3/inst_queue.hh
src/cpu/o3/inst_queue_impl.hh
src/cpu/o3/lsq.hh
src/cpu/o3/lsq_unit.hh
src/cpu/o3/lsq_unit_impl.hh
src/cpu/o3/mem_dep_unit.hh
src/cpu/o3/mem_dep_unit_impl.hh
src/cpu/o3/rename.hh
src/cpu/o3/rename_impl.hh
src/cpu/o3/rename_map.hh
src/cpu/o3/rob.hh
src/cpu/o3/store_set.cc
src/cpu/o3/store_set.hh
src/cpu/o3/thread_state.hh
src/cpu/o3/tournament_pred.cc
src/cpu/o3/tournament_pred.hh
src/cpu/ozone/cpu_builder.cc
src/cpu/ozone/ozone_impl.hh
src/cpu/ozone/simple_impl.hh
src/cpu/ozone/simple_params.hh
src/python/m5/objects/AlphaFullCPU.py
src/python/m5/objects/OzoneCPU.py

index 6dcb6e34125d1ccf82f72c7b3df7230b8fd64b9b,0000000000000000000000000000000000000000..b0b16446cc94b5a0c7564209ea3950d41b2edeb1
mode 100644,000000..100644
--- /dev/null
@@@ -1,122 -1,0 +1,155 @@@
++/*
++ * Copyright (c) 2006 The Regents of The University of Michigan
++ * 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.
++ */
 +
 +#include "base/timebuf.hh"
 +#include "cpu/activity.hh"
 +
 +ActivityRecorder::ActivityRecorder(int num_stages, int longest_latency,
 +                                   int activity)
 +    : activityBuffer(longest_latency, 0), longestLatency(longest_latency),
 +      activityCount(activity), numStages(num_stages)
 +{
 +    stageActive = new bool[numStages];
 +    memset(stageActive, 0, numStages);
 +}
 +
 +void
 +ActivityRecorder::activity()
 +{
++    // If we've already recorded activity for this cycle, we don't
++    // want to increment the count any more.
 +    if (activityBuffer[0]) {
 +        return;
 +    }
 +
 +    activityBuffer[0] = true;
 +
 +    ++activityCount;
 +
 +    DPRINTF(Activity, "Activity: %i\n", activityCount);
 +}
 +
 +void
 +ActivityRecorder::advance()
 +{
++    // If there's a 1 in the slot that is about to be erased once the
++    // time buffer advances, then decrement the activityCount.
 +    if (activityBuffer[-longestLatency]) {
 +        --activityCount;
 +
 +        assert(activityCount >= 0);
 +
 +        DPRINTF(Activity, "Activity: %i\n", activityCount);
 +
 +        if (activityCount == 0) {
 +            DPRINTF(Activity, "No activity left!\n");
 +        }
 +    }
 +
 +    activityBuffer.advance();
 +}
 +
 +void
 +ActivityRecorder::activateStage(const int idx)
 +{
++    // Increment the activity count if this stage wasn't already active.
 +    if (!stageActive[idx]) {
 +        ++activityCount;
 +
 +        stageActive[idx] = true;
 +
 +        DPRINTF(Activity, "Activity: %i\n", activityCount);
 +    } else {
 +        DPRINTF(Activity, "Stage %i already active.\n", idx);
 +    }
 +
 +//    assert(activityCount < longestLatency + numStages + 1);
 +}
 +
 +void
 +ActivityRecorder::deactivateStage(const int idx)
 +{
++    // Decrement the activity count if this stage was active.
 +    if (stageActive[idx]) {
 +        --activityCount;
 +
 +        stageActive[idx] = false;
 +
 +        DPRINTF(Activity, "Activity: %i\n", activityCount);
 +    } else {
 +        DPRINTF(Activity, "Stage %i already inactive.\n", idx);
 +    }
 +
 +    assert(activityCount >= 0);
 +}
 +
 +void
 +ActivityRecorder::reset()
 +{
 +    activityCount = 0;
 +    memset(stageActive, 0, numStages);
 +    for (int i = 0; i < longestLatency + 1; ++i)
 +        activityBuffer.advance();
 +}
 +
 +void
 +ActivityRecorder::dump()
 +{
 +    for (int i = 0; i <= longestLatency; ++i) {
 +        cprintf("[Idx:%i %i] ", i, activityBuffer[-i]);
 +    }
 +
 +    cprintf("\n");
 +
 +    for (int i = 0; i < numStages; ++i) {
 +        cprintf("[Stage:%i %i]\n", i, stageActive[i]);
 +    }
 +
 +    cprintf("\n");
 +
 +    cprintf("Activity count: %i\n", activityCount);
 +}
 +
 +void
 +ActivityRecorder::validate()
 +{
 +    int count = 0;
 +    for (int i = 0; i <= longestLatency; ++i) {
 +        if (activityBuffer[-i]) {
 +            count++;
 +        }
 +    }
 +
 +    for (int i = 0; i < numStages; ++i) {
 +        if (stageActive[i]) {
 +            count++;
 +        }
 +    }
 +
 +    assert(count == activityCount);
 +}
index 2d53dc4bbb89a4a2b18bbd8d92614128a5bc6019,0000000000000000000000000000000000000000..2c0df5efb0797a02776c7b5023be978334c5dc96
mode 100644,000000..100644
--- /dev/null
@@@ -1,67 -1,0 +1,124 @@@
-     /** Advances the activity buffer, decrementing the activityCount if active
-      *  communication just left the time buffer, and descheduling the CPU if
-      *  there is no activity.
++/*
++ * Copyright (c) 2006 The Regents of The University of Michigan
++ * 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.
++ */
 +
 +#ifndef __CPU_ACTIVITY_HH__
 +#define __CPU_ACTIVITY_HH__
 +
 +#include "base/timebuf.hh"
 +#include "base/trace.hh"
 +
++/**
++ * ActivityRecorder helper class that informs the CPU if it can switch
++ * over to being idle or not.  It works by having a time buffer as
++ * long as any time buffer in the CPU, and the CPU and all of its
++ * stages inform the ActivityRecorder when they write to any time
++ * buffer.  The ActivityRecorder marks a 1 in the "0" slot of the time
++ * buffer any time a stage writes to a time buffer, and it advances
++ * its time buffer at the same time as all other stages.  The
++ * ActivityRecorder also records if a stage has activity to do next
++ * cycle.  The recorder keeps a count of these two.  Thus any time the
++ * count is non-zero, there is either communication still in flight,
++ * or activity that still must be done, meaning that the CPU can not
++ * idle.  If count is zero, then the CPU can safely idle as it has no
++ * more outstanding work to do.
++ */
 +class ActivityRecorder {
 +  public:
 +    ActivityRecorder(int num_stages, int longest_latency, int count);
 +
 +    /** Records that there is activity this cycle. */
 +    void activity();
++
++    /** Advances the activity buffer, decrementing the activityCount
++     *  if active communication just left the time buffer, and
++     *  determining if there is no activity.
 +     */
 +    void advance();
++
 +    /** Marks a stage as active. */
 +    void activateStage(const int idx);
++
 +    /** Deactivates a stage. */
 +    void deactivateStage(const int idx);
 +
++    /** Returns how many things are active within the recorder. */
 +    int getActivityCount() { return activityCount; }
 +
++    /** Sets the count to a starting value.  Can be used to disable
++     * the idling option.
++     */
 +    void setActivityCount(int count)
 +    { activityCount = count; }
 +
++    /** Returns if the CPU should be active. */
 +    bool active() { return activityCount; }
 +
++    /** Clears the time buffer and the activity count. */
 +    void reset();
 +
++    /** Debug function to dump the contents of the time buffer. */
 +    void dump();
 +
++    /** Debug function to ensure that the activity count matches the
++     * contents of the time buffer.
++     */
 +    void validate();
 +
 +  private:
 +    /** Time buffer that tracks if any cycles has active communication
 +     *  in them.  It should be as long as the longest communication
 +     *  latency in the system.  Each time any time buffer is written,
 +     *  the activity buffer should also be written to. The
 +     *  activityBuffer is advanced along with all the other time
 +     *  buffers, so it should have a 1 somewhere in it only if there
 +     *  is active communication in a time buffer.
 +     */
 +    TimeBuffer<bool> activityBuffer;
 +
++    /** Longest latency time buffer in the CPU. */
 +    int longestLatency;
 +
 +    /** Tracks how many stages and cycles of time buffer have
 +     *  activity. Stages increment this count when they switch to
 +     *  active, and decrement it when they switch to
 +     *  inactive. Whenever a cycle that previously had no information
 +     *  is written in the time buffer, this is incremented. When a
 +     *  cycle that had information exits the time buffer due to age,
 +     *  this count is decremented. When the count is 0, there is no
 +     *  activity in the CPU, and it can be descheduled.
 +     */
 +    int activityCount;
 +
++    /** Number of stages that can be marked as active or inactive. */
 +    int numStages;
 +
 +    /** Records which stages are active/inactive. */
 +    bool *stageActive;
 +};
 +
 +#endif // __CPU_ACTIVITY_HH__
index 7eb974d36698bc4938e4d5f05514995b4f703e36,0000000000000000000000000000000000000000..66e425d5c671e26bfb1b7c1af6fb5de7a83b5483
mode 100644,000000..100644
--- /dev/null
@@@ -1,460 -1,0 +1,462 @@@
-     assert(thread->copySrcPhysAddr || thread->misspeculating());
 +/*
 + * Copyright (c) 2004-2005 The Regents of The University of Michigan
 + * 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: Kevin Lim
 + */
 +
 +#include <iostream>
 +#include <set>
 +#include <string>
 +#include <sstream>
 +
 +#include "base/cprintf.hh"
 +#include "base/trace.hh"
 +
 +#include "arch/faults.hh"
 +#include "cpu/exetrace.hh"
 +#include "mem/request.hh"
 +
 +#include "cpu/base_dyn_inst.hh"
 +#include "cpu/o3/alpha_impl.hh"
 +#include "cpu/o3/alpha_cpu.hh"
 +//#include "cpu/ozone/simple_impl.hh"
 +//#include "cpu/ozone/ozone_impl.hh"
 +
 +using namespace std;
 +using namespace TheISA;
 +
 +#define NOHASH
 +#ifndef NOHASH
 +
 +#include "base/hashmap.hh"
 +
 +unsigned int MyHashFunc(const BaseDynInst *addr)
 +{
 +    unsigned a = (unsigned)addr;
 +    unsigned hash = (((a >> 14) ^ ((a >> 2) & 0xffff))) & 0x7FFFFFFF;
 +
 +    return hash;
 +}
 +
 +typedef m5::hash_map<const BaseDynInst *, const BaseDynInst *, MyHashFunc>
 +my_hash_t;
 +
 +my_hash_t thishash;
 +#endif
 +
 +template <class Impl>
 +BaseDynInst<Impl>::BaseDynInst(ExtMachInst machInst, Addr inst_PC,
 +                               Addr pred_PC, InstSeqNum seq_num,
 +                               FullCPU *cpu)
 +  : staticInst(machInst), traceData(NULL), cpu(cpu)/*, xc(cpu->xcBase())*/
 +{
 +    seqNum = seq_num;
 +
 +    PC = inst_PC;
 +    nextPC = PC + sizeof(MachInst);
 +    predPC = pred_PC;
 +
 +    initVars();
 +}
 +
 +template <class Impl>
 +BaseDynInst<Impl>::BaseDynInst(StaticInstPtr &_staticInst)
 +    : staticInst(_staticInst), traceData(NULL)
 +{
 +    seqNum = 0;
 +    initVars();
 +}
 +
 +template <class Impl>
 +void
 +BaseDynInst<Impl>::initVars()
 +{
 +    req = NULL;
 +    effAddr = 0;
 +    physEffAddr = 0;
 +    storeSize = 0;
 +
 +    readyRegs = 0;
 +
 +    completed = false;
 +    resultReady = false;
 +    canIssue = false;
 +    issued = false;
 +    executed = false;
 +    canCommit = false;
 +    committed = false;
 +    squashed = false;
 +    squashedInIQ = false;
 +    squashedInLSQ = false;
 +    squashedInROB = false;
 +    eaCalcDone = false;
 +    memOpDone = false;
 +    lqIdx = -1;
 +    sqIdx = -1;
 +    reachedCommit = false;
 +
 +    blockingInst = false;
 +    recoverInst = false;
 +
 +    iqEntry = false;
 +    robEntry = false;
 +
 +    serializeBefore = false;
 +    serializeAfter = false;
 +    serializeHandled = false;
 +
 +    // Eventually make this a parameter.
 +    threadNumber = 0;
 +
 +    // Also make this a parameter, or perhaps get it from xc or cpu.
 +    asid = 0;
 +
 +    // Initialize the fault to be unimplemented opcode.
 +//    fault = new UnimplementedOpcodeFault;
 +    fault = NoFault;
 +
 +    ++instcount;
 +
 +    if (instcount > 1500) {
 +        cpu->dumpInsts();
 +#ifdef DEBUG
 +        dumpSNList();
 +#endif
 +        assert(instcount <= 1500);
 +    }
 +
 +    DPRINTF(DynInst, "DynInst: [sn:%lli] Instruction created. Instcount=%i\n",
 +            seqNum, instcount);
 +
 +#ifdef DEBUG
 +    cpu->snList.insert(seqNum);
 +#endif
 +}
 +
 +template <class Impl>
 +BaseDynInst<Impl>::~BaseDynInst()
 +{
 +    if (req) {
 +        req = NULL;
 +    }
 +
 +    if (traceData) {
 +        delete traceData;
 +    }
 +
++    fault = NoFault;
++
 +    --instcount;
 +
 +    DPRINTF(DynInst, "DynInst: [sn:%lli] Instruction destroyed. Instcount=%i\n",
 +            seqNum, instcount);
 +#ifdef DEBUG
 +    cpu->snList.erase(seqNum);
 +#endif
 +}
 +
 +#ifdef DEBUG
 +template <class Impl>
 +void
 +BaseDynInst<Impl>::dumpSNList()
 +{
 +    std::set<InstSeqNum>::iterator sn_it = cpu->snList.begin();
 +
 +    int count = 0;
 +    while (sn_it != cpu->snList.end()) {
 +        cprintf("%i: [sn:%lli] not destroyed\n", count, (*sn_it));
 +        count++;
 +        sn_it++;
 +    }
 +}
 +#endif
 +
 +template <class Impl>
 +void
 +BaseDynInst<Impl>::prefetch(Addr addr, unsigned flags)
 +{
 +    // This is the "functional" implementation of prefetch.  Not much
 +    // happens here since prefetches don't affect the architectural
 +    // state.
 +/*
 +    // Generate a MemReq so we can translate the effective address.
 +    MemReqPtr req = new MemReq(addr, thread->getXCProxy(), 1, flags);
 +    req->asid = asid;
 +
 +    // Prefetches never cause faults.
 +    fault = NoFault;
 +
 +    // note this is a local, not BaseDynInst::fault
 +    Fault trans_fault = cpu->translateDataReadReq(req);
 +
 +    if (trans_fault == NoFault && !(req->flags & UNCACHEABLE)) {
 +        // It's a valid address to cacheable space.  Record key MemReq
 +        // parameters so we can generate another one just like it for
 +        // the timing access without calling translate() again (which
 +        // might mess up the TLB).
 +        effAddr = req->vaddr;
 +        physEffAddr = req->paddr;
 +        memReqFlags = req->flags;
 +    } else {
 +        // Bogus address (invalid or uncacheable space).  Mark it by
 +        // setting the eff_addr to InvalidAddr.
 +        effAddr = physEffAddr = MemReq::inval_addr;
 +    }
 +
 +    if (traceData) {
 +        traceData->setAddr(addr);
 +    }
 +*/
 +}
 +
 +template <class Impl>
 +void
 +BaseDynInst<Impl>::writeHint(Addr addr, int size, unsigned flags)
 +{
 +    // Need to create a MemReq here so we can do a translation.  This
 +    // will casue a TLB miss trap if necessary... not sure whether
 +    // that's the best thing to do or not.  We don't really need the
 +    // MemReq otherwise, since wh64 has no functional effect.
 +/*
 +    MemReqPtr req = new MemReq(addr, thread->getXCProxy(), size, flags);
 +    req->asid = asid;
 +
 +    fault = cpu->translateDataWriteReq(req);
 +
 +    if (fault == NoFault && !(req->flags & UNCACHEABLE)) {
 +        // Record key MemReq parameters so we can generate another one
 +        // just like it for the timing access without calling translate()
 +        // again (which might mess up the TLB).
 +        effAddr = req->vaddr;
 +        physEffAddr = req->paddr;
 +        memReqFlags = req->flags;
 +    } else {
 +        // ignore faults & accesses to uncacheable space... treat as no-op
 +        effAddr = physEffAddr = MemReq::inval_addr;
 +    }
 +
 +    storeSize = size;
 +    storeData = 0;
 +*/
 +}
 +
 +/**
 + * @todo Need to find a way to get the cache block size here.
 + */
 +template <class Impl>
 +Fault
 +BaseDynInst<Impl>::copySrcTranslate(Addr src)
 +{
 +/*
 +    MemReqPtr req = new MemReq(src, thread->getXCProxy(), 64);
 +    req->asid = asid;
 +
 +    // translate to physical address
 +    Fault fault = cpu->translateDataReadReq(req);
 +
 +    if (fault == NoFault) {
 +        thread->copySrcAddr = src;
 +        thread->copySrcPhysAddr = req->paddr;
 +    } else {
 +        thread->copySrcAddr = 0;
 +        thread->copySrcPhysAddr = 0;
 +    }
 +    return fault;
 +*/
 +    return NoFault;
 +}
 +
 +/**
 + * @todo Need to find a way to get the cache block size here.
 + */
 +template <class Impl>
 +Fault
 +BaseDynInst<Impl>::copy(Addr dest)
 +{
 +/*
 +    uint8_t data[64];
 +    FunctionalMemory *mem = thread->mem;
++    assert(thread->copySrcPhysAddr);
 +    MemReqPtr req = new MemReq(dest, thread->getXCProxy(), 64);
 +    req->asid = asid;
 +
 +    // translate to physical address
 +    Fault fault = cpu->translateDataWriteReq(req);
 +
 +    if (fault == NoFault) {
 +        Addr dest_addr = req->paddr;
 +        // Need to read straight from memory since we have more than 8 bytes.
 +        req->paddr = thread->copySrcPhysAddr;
 +        mem->read(req, data);
 +        req->paddr = dest_addr;
 +        mem->write(req, data);
 +    }
 +    return fault;
 +*/
 +    return NoFault;
 +}
 +
 +template <class Impl>
 +void
 +BaseDynInst<Impl>::dump()
 +{
 +    cprintf("T%d : %#08d `", threadNumber, PC);
 +    cout << staticInst->disassemble(PC);
 +    cprintf("'\n");
 +}
 +
 +template <class Impl>
 +void
 +BaseDynInst<Impl>::dump(std::string &outstring)
 +{
 +    std::ostringstream s;
 +    s << "T" << threadNumber << " : 0x" << PC << " "
 +      << staticInst->disassemble(PC);
 +
 +    outstring = s.str();
 +}
 +
 +#if 0
 +template <class Impl>
 +Fault
 +BaseDynInst<Impl>::mem_access(mem_cmd cmd, Addr addr, void *p, int nbytes)
 +{
 +    Fault fault;
 +
 +    // check alignments, even speculative this test should always pass
 +    if ((nbytes & nbytes - 1) != 0 || (addr & nbytes - 1) != 0) {
 +        for (int i = 0; i < nbytes; i++)
 +            ((char *) p)[i] = 0;
 +
 +        // I added the following because according to the comment above,
 +        // we should never get here.  The comment lies
 +#if 0
 +        panic("unaligned access. Cycle = %n", curTick);
 +#endif
 +        return NoFault;
 +    }
 +
 +    MemReqPtr req = new MemReq(addr, thread, nbytes);
 +    switch(cmd) {
 +      case Read:
 +        fault = spec_mem->read(req, (uint8_t *)p);
 +        break;
 +
 +      case Write:
 +        fault = spec_mem->write(req, (uint8_t *)p);
 +        if (fault != NoFault)
 +            break;
 +
 +        specMemWrite = true;
 +        storeSize = nbytes;
 +        switch(nbytes) {
 +          case sizeof(uint8_t):
 +            *(uint8_t)&storeData = (uint8_t *)p;
 +            break;
 +          case sizeof(uint16_t):
 +            *(uint16_t)&storeData = (uint16_t *)p;
 +            break;
 +          case sizeof(uint32_t):
 +            *(uint32_t)&storeData = (uint32_t *)p;
 +            break;
 +          case sizeof(uint64_t):
 +            *(uint64_t)&storeData = (uint64_t *)p;
 +            break;
 +        }
 +        break;
 +
 +      default:
 +        fault = genMachineCheckFault();
 +        break;
 +    }
 +
 +    trace_mem(fault, cmd, addr, p, nbytes);
 +
 +    return fault;
 +}
 +
 +#endif
 +
 +template <class Impl>
 +void
 +BaseDynInst<Impl>::markSrcRegReady()
 +{
 +    if (++readyRegs == numSrcRegs()) {
 +        canIssue = true;
 +    }
 +}
 +
 +template <class Impl>
 +void
 +BaseDynInst<Impl>::markSrcRegReady(RegIndex src_idx)
 +{
 +    ++readyRegs;
 +
 +    _readySrcRegIdx[src_idx] = true;
 +
 +    if (readyRegs == numSrcRegs()) {
 +        canIssue = true;
 +    }
 +}
 +
 +template <class Impl>
 +bool
 +BaseDynInst<Impl>::eaSrcsReady()
 +{
 +    // For now I am assuming that src registers 1..n-1 are the ones that the
 +    // EA calc depends on.  (i.e. src reg 0 is the source of the data to be
 +    // stored)
 +
 +    for (int i = 1; i < numSrcRegs(); ++i) {
 +        if (!_readySrcRegIdx[i])
 +            return false;
 +    }
 +
 +    return true;
 +}
 +
 +// Forward declaration
 +template class BaseDynInst<AlphaSimpleImpl>;
 +
 +template <>
 +int
 +BaseDynInst<AlphaSimpleImpl>::instcount = 0;
 +/*
 +// Forward declaration
 +template class BaseDynInst<SimpleImpl>;
 +
 +template <>
 +int
 +BaseDynInst<SimpleImpl>::instcount = 0;
 +
 +// Forward declaration
 +template class BaseDynInst<OzoneImpl>;
 +
 +template <>
 +int
 +BaseDynInst<OzoneImpl>::instcount = 0;
 +*/
index 7e63febb6393a66f7439a755e24a9cb2044b347f,0000000000000000000000000000000000000000..2f9689028964135f081108233fd176ff54ecaaa1
mode 100644,000000..100644
--- /dev/null
@@@ -1,354 -1,0 +1,375 @@@
-     // main simulation loop (one cycle)
 +/*
 + * Copyright (c) 2006 The Regents of The University of Michigan
 + * 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.
 + */
 +
 +#ifndef __CPU_CHECKER_CPU_HH__
 +#define __CPU_CHECKER_CPU_HH__
 +
 +#include <list>
 +#include <queue>
 +#include <map>
 +
 +#include "arch/types.hh"
 +#include "base/statistics.hh"
 +#include "config/full_system.hh"
 +#include "cpu/base.hh"
 +#include "cpu/base_dyn_inst.hh"
 +#include "cpu/cpu_exec_context.hh"
 +#include "cpu/pc_event.hh"
 +#include "cpu/static_inst.hh"
 +#include "sim/eventq.hh"
 +
 +// forward declarations
 +#if FULL_SYSTEM
 +class Processor;
 +class AlphaITB;
 +class AlphaDTB;
 +class PhysicalMemory;
 +
 +class RemoteGDB;
 +class GDBListener;
 +
 +#else
 +
 +class Process;
 +
 +#endif // FULL_SYSTEM
 +template <class>
 +class BaseDynInst;
 +class ExecContext;
 +class MemInterface;
 +class Checkpoint;
 +class Request;
 +class Sampler;
 +
++/**
++ * CheckerCPU class.  Dynamically verifies instructions as they are
++ * completed by making sure that the instruction and its results match
++ * the independent execution of the benchmark inside the checker.  The
++ * checker verifies instructions in order, regardless of the order in
++ * which instructions complete.  There are certain results that can
++ * not be verified, specifically the result of a store conditional or
++ * the values of uncached accesses.  In these cases, and with
++ * instructions marked as "IsUnverifiable", the checker assumes that
++ * the value from the main CPU's execution is correct and simply
++ * copies that value.  It provides a CheckerExecContext (see
++ * checker/exec_context.hh) that provides hooks for updating the
++ * Checker's state through any ExecContext accesses.  This allows the
++ * checker to be able to correctly verify instructions, even with
++ * external accesses to the ExecContext that change state.
++ */
 +class CheckerCPU : public BaseCPU
 +{
 +  protected:
 +    typedef TheISA::MachInst MachInst;
 +    typedef TheISA::FloatReg FloatReg;
 +    typedef TheISA::FloatRegBits FloatRegBits;
 +    typedef TheISA::MiscReg MiscReg;
 +  public:
 +    virtual void init();
 +
 +    struct Params : public BaseCPU::Params
 +    {
 +#if FULL_SYSTEM
 +        AlphaITB *itb;
 +        AlphaDTB *dtb;
 +        FunctionalMemory *mem;
 +#else
 +        Process *process;
 +#endif
 +        bool exitOnError;
 +    };
 +
 +  public:
 +    CheckerCPU(Params *p);
 +    virtual ~CheckerCPU();
 +
 +    void setMemory(MemObject *mem);
 +
 +    MemObject *memPtr;
 +
 +#if FULL_SYSTEM
 +    void setSystem(System *system);
 +
 +    System *systemPtr;
 +#endif
 +  public:
 +    // execution context
 +    CPUExecContext *cpuXC;
 +
 +    ExecContext *xcProxy;
 +
 +    AlphaITB *itb;
 +    AlphaDTB *dtb;
 +
 +#if FULL_SYSTEM
 +    Addr dbg_vtophys(Addr addr);
 +#endif
 +
 +    union Result {
 +        uint64_t integer;
 +        float fp;
 +        double dbl;
 +    };
 +
 +    Result result;
 +
 +    // current instruction
 +    MachInst machInst;
 +
 +    // Refcounted pointer to the one memory request.
 +    Request *memReq;
 +
 +    StaticInstPtr curStaticInst;
 +
 +    // number of simulated instructions
 +    Counter numInst;
 +    Counter startNumInst;
 +
 +    std::queue<int> miscRegIdxs;
 +
 +    virtual Counter totalInstructions() const
 +    {
 +        return numInst - startNumInst;
 +    }
 +
 +    // number of simulated loads
 +    Counter numLoad;
 +    Counter startNumLoad;
 +
 +    virtual void serialize(std::ostream &os);
 +    virtual void unserialize(Checkpoint *cp, const std::string &section);
 +
 +    template <class T>
 +    Fault read(Addr addr, T &data, unsigned flags);
 +
 +    template <class T>
 +    Fault write(T data, Addr addr, unsigned flags, uint64_t *res);
 +
 +    // These functions are only used in CPU models that split
 +    // effective address computation from the actual memory access.
 +    void setEA(Addr EA) { panic("SimpleCPU::setEA() not implemented\n"); }
 +    Addr getEA()      { panic("SimpleCPU::getEA() not implemented\n"); }
 +
 +    void prefetch(Addr addr, unsigned flags)
 +    {
 +        // need to do this...
 +    }
 +
 +    void writeHint(Addr addr, int size, unsigned flags)
 +    {
 +        // need to do this...
 +    }
 +
 +    Fault copySrcTranslate(Addr src);
 +
 +    Fault copy(Addr dest);
 +
 +    // The register accessor methods provide the index of the
 +    // instruction's operand (e.g., 0 or 1), not the architectural
 +    // register index, to simplify the implementation of register
 +    // renaming.  We find the architectural register index by indexing
 +    // into the instruction's own operand index table.  Note that a
 +    // raw pointer to the StaticInst is provided instead of a
 +    // ref-counted StaticInstPtr to redice overhead.  This is fine as
 +    // long as these methods don't copy the pointer into any long-term
 +    // storage (which is pretty hard to imagine they would have reason
 +    // to do).
 +
 +    uint64_t readIntReg(const StaticInst *si, int idx)
 +    {
 +        return cpuXC->readIntReg(si->srcRegIdx(idx));
 +    }
 +
 +    FloatReg readFloatReg(const StaticInst *si, int idx, int width)
 +    {
 +        int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
 +        return cpuXC->readFloatReg(reg_idx, width);
 +    }
 +
 +    FloatReg readFloatReg(const StaticInst *si, int idx)
 +    {
 +        int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
 +        return cpuXC->readFloatReg(reg_idx);
 +    }
 +
 +    FloatRegBits readFloatRegBits(const StaticInst *si, int idx, int width)
 +    {
 +        int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
 +        return cpuXC->readFloatRegBits(reg_idx, width);
 +    }
 +
 +    FloatRegBits readFloatRegBits(const StaticInst *si, int idx)
 +    {
 +        int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
 +        return cpuXC->readFloatRegBits(reg_idx);
 +    }
 +
 +    void setIntReg(const StaticInst *si, int idx, uint64_t val)
 +    {
 +        cpuXC->setIntReg(si->destRegIdx(idx), val);
 +        result.integer = val;
 +    }
 +
 +    void setFloatReg(const StaticInst *si, int idx, FloatReg val, int width)
 +    {
 +        int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
 +        cpuXC->setFloatReg(reg_idx, val, width);
 +        switch(width) {
 +          case 32:
 +            result.fp = val;
 +            break;
 +          case 64:
 +            result.dbl = val;
 +            break;
 +        };
 +    }
 +
 +    void setFloatReg(const StaticInst *si, int idx, FloatReg val)
 +    {
 +        int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
 +        cpuXC->setFloatReg(reg_idx, val);
 +        result.fp = val;
 +    }
 +
 +    void setFloatRegBits(const StaticInst *si, int idx, FloatRegBits val,
 +                         int width)
 +    {
 +        int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
 +        cpuXC->setFloatRegBits(reg_idx, val, width);
 +        result.integer = val;
 +    }
 +
 +    void setFloatRegBits(const StaticInst *si, int idx, FloatRegBits val)
 +    {
 +        int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
 +        cpuXC->setFloatRegBits(reg_idx, val);
 +        result.integer = val;
 +    }
 +
 +    uint64_t readPC() { return cpuXC->readPC(); }
 +
 +    uint64_t readNextPC() { return cpuXC->readNextPC(); }
 +
 +    void setNextPC(uint64_t val) {
 +        cpuXC->setNextPC(val);
 +    }
 +
 +    MiscReg readMiscReg(int misc_reg)
 +    {
 +        return cpuXC->readMiscReg(misc_reg);
 +    }
 +
 +    MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault)
 +    {
 +        return cpuXC->readMiscRegWithEffect(misc_reg, fault);
 +    }
 +
 +    Fault setMiscReg(int misc_reg, const MiscReg &val)
 +    {
 +        result.integer = val;
 +        miscRegIdxs.push(misc_reg);
 +        return cpuXC->setMiscReg(misc_reg, val);
 +    }
 +
 +    Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val)
 +    {
 +        miscRegIdxs.push(misc_reg);
 +        return cpuXC->setMiscRegWithEffect(misc_reg, val);
 +    }
 +
 +    void recordPCChange(uint64_t val) { changedPC = true; }
 +    void recordNextPCChange(uint64_t val) { changedNextPC = true; }
 +
 +    bool translateInstReq(Request *req);
 +    void translateDataWriteReq(Request *req);
 +    void translateDataReadReq(Request *req);
 +
 +#if FULL_SYSTEM
 +    Fault hwrei() { return cpuXC->hwrei(); }
 +    int readIntrFlag() { return cpuXC->readIntrFlag(); }
 +    void setIntrFlag(int val) { cpuXC->setIntrFlag(val); }
 +    bool inPalMode() { return cpuXC->inPalMode(); }
 +    void ev5_trap(Fault fault) { fault->invoke(xcProxy); }
 +    bool simPalCheck(int palFunc) { return cpuXC->simPalCheck(palFunc); }
 +#else
 +    // Assume that the normal CPU's call to syscall was successful.
 +    // The checker's state would have already been updated by the syscall.
 +    void syscall(uint64_t callnum) { }
 +#endif
 +
 +    void handleError()
 +    {
 +        if (exitOnError)
 +            panic("Checker found error!");
 +    }
 +    bool checkFlags(Request *req);
 +
 +    ExecContext *xcBase() { return xcProxy; }
 +    CPUExecContext *cpuXCBase() { return cpuXC; }
 +
 +    Result unverifiedResult;
 +    Request *unverifiedReq;
 +
 +    bool changedPC;
 +    bool willChangePC;
 +    uint64_t newPC;
 +    bool changedNextPC;
 +    bool exitOnError;
 +
 +    InstSeqNum youngestSN;
 +};
 +
++/**
++ * Templated Checker class.  This Checker class is templated on the
++ * DynInstPtr of the instruction type that will be verified.  Proper
++ * template instantiations of the Checker must be placed at the bottom
++ * of checker/cpu.cc.
++ */
 +template <class DynInstPtr>
 +class Checker : public CheckerCPU
 +{
 +  public:
 +    Checker(Params *p)
 +        : CheckerCPU(p)
 +    { }
 +
 +    void switchOut(Sampler *s);
 +    void takeOverFrom(BaseCPU *oldCPU);
 +
 +    void tick(DynInstPtr &inst);
 +
 +    void validateInst(DynInstPtr &inst);
 +    void validateExecution(DynInstPtr &inst);
 +    void validateState();
 +
 +    std::list<DynInstPtr> instList;
 +    typedef typename std::list<DynInstPtr>::iterator InstListIt;
 +    void dumpInsts();
 +};
 +
 +#endif // __CPU_CHECKER_CPU_HH__
index 397ccab1482b0a048614e26d8238313a7dc965f1,0000000000000000000000000000000000000000..d80daef97205e8d7071f3d85be745c59ba7bfb7f
mode 100644,000000..100644
--- /dev/null
@@@ -1,126 -1,0 +1,156 @@@
++/*
++ * Copyright (c) 2006 The Regents of The University of Michigan
++ * 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.
++ */
 +
 +#include <string>
 +
 +#include "cpu/checker/cpu.hh"
 +#include "cpu/inst_seq.hh"
 +#include "cpu/ozone/dyn_inst.hh"
 +#include "cpu/ozone/ozone_impl.hh"
 +#include "mem/base_mem.hh"
 +#include "sim/builder.hh"
 +#include "sim/process.hh"
 +#include "sim/sim_object.hh"
 +
++/**
++ * Specific non-templated derived class used for SimObject configuration.
++ */
 +class OzoneChecker : public Checker<RefCountingPtr<OzoneDynInst<OzoneImpl> > >
 +{
 +  public:
 +    OzoneChecker(Params *p)
 +        : Checker<RefCountingPtr<OzoneDynInst<OzoneImpl> > >(p)
 +    { }
 +};
 +
 +////////////////////////////////////////////////////////////////////////
 +//
 +//  CheckerCPU Simulation Object
 +//
 +BEGIN_DECLARE_SIM_OBJECT_PARAMS(OzoneChecker)
 +
 +    Param<Counter> max_insts_any_thread;
 +    Param<Counter> max_insts_all_threads;
 +    Param<Counter> max_loads_any_thread;
 +    Param<Counter> max_loads_all_threads;
 +
 +#if FULL_SYSTEM
 +    SimObjectParam<AlphaITB *> itb;
 +    SimObjectParam<AlphaDTB *> dtb;
 +    SimObjectParam<FunctionalMemory *> mem;
 +    SimObjectParam<System *> system;
 +    Param<int> cpu_id;
 +    Param<Tick> profile;
 +#else
 +    SimObjectParam<Process *> workload;
 +#endif // FULL_SYSTEM
 +    Param<int> clock;
 +    SimObjectParam<BaseMem *> icache;
 +    SimObjectParam<BaseMem *> dcache;
 +
 +    Param<bool> defer_registration;
 +    Param<bool> exitOnError;
 +    Param<bool> function_trace;
 +    Param<Tick> function_trace_start;
 +
 +END_DECLARE_SIM_OBJECT_PARAMS(OzoneChecker)
 +
 +BEGIN_INIT_SIM_OBJECT_PARAMS(OzoneChecker)
 +
 +    INIT_PARAM(max_insts_any_thread,
 +               "terminate when any thread reaches this inst count"),
 +    INIT_PARAM(max_insts_all_threads,
 +               "terminate when all threads have reached this inst count"),
 +    INIT_PARAM(max_loads_any_thread,
 +               "terminate when any thread reaches this load count"),
 +    INIT_PARAM(max_loads_all_threads,
 +               "terminate when all threads have reached this load count"),
 +
 +#if FULL_SYSTEM
 +    INIT_PARAM(itb, "Instruction TLB"),
 +    INIT_PARAM(dtb, "Data TLB"),
 +    INIT_PARAM(mem, "memory"),
 +    INIT_PARAM(system, "system object"),
 +    INIT_PARAM(cpu_id, "processor ID"),
 +    INIT_PARAM(profile, ""),
 +#else
 +    INIT_PARAM(workload, "processes to run"),
 +#endif // FULL_SYSTEM
 +
 +    INIT_PARAM(clock, "clock speed"),
 +    INIT_PARAM(icache, "L1 instruction cache object"),
 +    INIT_PARAM(dcache, "L1 data cache object"),
 +
 +    INIT_PARAM(defer_registration, "defer system registration (for sampling)"),
 +    INIT_PARAM(exitOnError, "exit on error"),
 +    INIT_PARAM(function_trace, "Enable function trace"),
 +    INIT_PARAM(function_trace_start, "Cycle to start function trace")
 +
 +END_INIT_SIM_OBJECT_PARAMS(OzoneChecker)
 +
 +
 +CREATE_SIM_OBJECT(OzoneChecker)
 +{
 +    OzoneChecker::Params *params = new OzoneChecker::Params();
 +    params->name = getInstanceName();
 +    params->numberOfThreads = 1;
 +    params->max_insts_any_thread = 0;
 +    params->max_insts_all_threads = 0;
 +    params->max_loads_any_thread = 0;
 +    params->max_loads_all_threads = 0;
 +    params->exitOnError = exitOnError;
 +    params->deferRegistration = defer_registration;
 +    params->functionTrace = function_trace;
 +    params->functionTraceStart = function_trace_start;
 +    params->clock = clock;
 +    // Hack to touch all parameters.  Consider not deriving Checker
 +    // from BaseCPU..it's not really a CPU in the end.
 +    Counter temp;
 +    temp = max_insts_any_thread;
 +    temp = max_insts_all_threads;
 +    temp = max_loads_any_thread;
 +    temp = max_loads_all_threads;
 +    BaseMem *cache = icache;
 +    cache = dcache;
 +
 +#if FULL_SYSTEM
 +    params->itb = itb;
 +    params->dtb = dtb;
 +    params->mem = mem;
 +    params->system = system;
 +    params->cpu_id = cpu_id;
 +    params->profile = profile;
 +#else
 +    params->process = workload;
 +#endif
 +
 +    OzoneChecker *cpu = new OzoneChecker(params);
 +    return cpu;
 +}
 +
 +REGISTER_SIM_OBJECT("OzoneChecker", OzoneChecker)
index 7d30e736a69440ef8766c2e2da29da432da444c2,0000000000000000000000000000000000000000..054739a6a571d78681cb96a8f096a1f37d8af9ce
mode 100644,000000..100644
--- /dev/null
@@@ -1,283 -1,0 +1,290 @@@
 +/*
 + * Copyright (c) 2006 The Regents of The University of Michigan
 + * 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.
 + */
 +
 +#ifndef __CPU_CHECKER_EXEC_CONTEXT_HH__
 +#define __CPU_CHECKER_EXEC_CONTEXT_HH__
 +
 +#include "cpu/checker/cpu.hh"
 +#include "cpu/cpu_exec_context.hh"
 +#include "cpu/exec_context.hh"
 +
 +class EndQuiesceEvent;
 +namespace Kernel {
 +    class Statistics;
 +};
 +
++/**
++ * Derived ExecContext class for use with the Checker.  The template
++ * parameter is the ExecContext class used by the specific CPU being
++ * verified.  This CheckerExecContext is then used by the main CPU in
++ * place of its usual ExecContext class.  It handles updating the
++ * checker's state any time state is updated through the ExecContext.
++ */
 +template <class XC>
 +class CheckerExecContext : public ExecContext
 +{
 +  public:
 +    CheckerExecContext(XC *actual_xc,
 +                       CheckerCPU *checker_cpu)
 +        : actualXC(actual_xc), checkerXC(checker_cpu->cpuXC),
 +          checkerCPU(checker_cpu)
 +    { }
 +
 +  private:
 +    XC *actualXC;
 +    CPUExecContext *checkerXC;
 +    CheckerCPU *checkerCPU;
 +
 +  public:
 +
 +    BaseCPU *getCpuPtr() { return actualXC->getCpuPtr(); }
 +
 +    void setCpuId(int id)
 +    {
 +        actualXC->setCpuId(id);
 +        checkerXC->setCpuId(id);
 +    }
 +
 +    int readCpuId() { return actualXC->readCpuId(); }
 +
 +    TranslatingPort *getMemPort() { return actualXC->getMemPort(); }
 +
 +#if FULL_SYSTEM
 +    System *getSystemPtr() { return actualXC->getSystemPtr(); }
 +
 +    PhysicalMemory *getPhysMemPtr() { return actualXC->getPhysMemPtr(); }
 +
 +    AlphaITB *getITBPtr() { return actualXC->getITBPtr(); }
 +
 +    AlphaDTB *getDTBPtr() { return actualXC->getDTBPtr(); }
 +
 +    Kernel::Statistics *getKernelStats() { return actualXC->getKernelStats(); }
 +#else
 +    Process *getProcessPtr() { return actualXC->getProcessPtr(); }
 +#endif
 +
 +    Status status() const { return actualXC->status(); }
 +
 +    void setStatus(Status new_status)
 +    {
 +        actualXC->setStatus(new_status);
 +        checkerXC->setStatus(new_status);
 +    }
 +
 +    /// Set the status to Active.  Optional delay indicates number of
 +    /// cycles to wait before beginning execution.
 +    void activate(int delay = 1) { actualXC->activate(delay); }
 +
 +    /// Set the status to Suspended.
 +    void suspend() { actualXC->suspend(); }
 +
 +    /// Set the status to Unallocated.
 +    void deallocate() { actualXC->deallocate(); }
 +
 +    /// Set the status to Halted.
 +    void halt() { actualXC->halt(); }
 +
 +#if FULL_SYSTEM
 +    void dumpFuncProfile() { actualXC->dumpFuncProfile(); }
 +#endif
 +
 +    void takeOverFrom(ExecContext *oldContext)
 +    {
 +        actualXC->takeOverFrom(oldContext);
 +        checkerXC->takeOverFrom(oldContext);
 +    }
 +
 +    void regStats(const std::string &name) { actualXC->regStats(name); }
 +
 +    void serialize(std::ostream &os) { actualXC->serialize(os); }
 +    void unserialize(Checkpoint *cp, const std::string &section)
 +    { actualXC->unserialize(cp, section); }
 +
 +#if FULL_SYSTEM
 +    EndQuiesceEvent *getQuiesceEvent() { return actualXC->getQuiesceEvent(); }
 +
 +    Tick readLastActivate() { return actualXC->readLastActivate(); }
 +    Tick readLastSuspend() { return actualXC->readLastSuspend(); }
 +
 +    void profileClear() { return actualXC->profileClear(); }
 +    void profileSample() { return actualXC->profileSample(); }
 +#endif
 +
 +    int getThreadNum() { return actualXC->getThreadNum(); }
 +
 +    // @todo: Do I need this?
 +    MachInst getInst() { return actualXC->getInst(); }
 +
 +    // @todo: Do I need this?
 +    void copyArchRegs(ExecContext *xc)
 +    {
 +        actualXC->copyArchRegs(xc);
 +        checkerXC->copyArchRegs(xc);
 +    }
 +
 +    void clearArchRegs()
 +    {
 +        actualXC->clearArchRegs();
 +        checkerXC->clearArchRegs();
 +    }
 +
 +    //
 +    // New accessors for new decoder.
 +    //
 +    uint64_t readIntReg(int reg_idx)
 +    { return actualXC->readIntReg(reg_idx); }
 +
 +    FloatReg readFloatReg(int reg_idx, int width)
 +    { return actualXC->readFloatReg(reg_idx, width); }
 +
 +    FloatReg readFloatReg(int reg_idx)
 +    { return actualXC->readFloatReg(reg_idx); }
 +
 +    FloatRegBits readFloatRegBits(int reg_idx, int width)
 +    { return actualXC->readFloatRegBits(reg_idx, width); }
 +
 +    FloatRegBits readFloatRegBits(int reg_idx)
 +    { return actualXC->readFloatRegBits(reg_idx); }
 +
 +    void setIntReg(int reg_idx, uint64_t val)
 +    {
 +        actualXC->setIntReg(reg_idx, val);
 +        checkerXC->setIntReg(reg_idx, val);
 +    }
 +
 +    void setFloatReg(int reg_idx, FloatReg val, int width)
 +    {
 +        actualXC->setFloatReg(reg_idx, val, width);
 +        checkerXC->setFloatReg(reg_idx, val, width);
 +    }
 +
 +    void setFloatReg(int reg_idx, FloatReg val)
 +    {
 +        actualXC->setFloatReg(reg_idx, val);
 +        checkerXC->setFloatReg(reg_idx, val);
 +    }
 +
 +    void setFloatRegBits(int reg_idx, FloatRegBits val, int width)
 +    {
 +        actualXC->setFloatRegBits(reg_idx, val, width);
 +        checkerXC->setFloatRegBits(reg_idx, val, width);
 +    }
 +
 +    void setFloatRegBits(int reg_idx, FloatRegBits val)
 +    {
 +        actualXC->setFloatRegBits(reg_idx, val);
 +        checkerXC->setFloatRegBits(reg_idx, val);
 +    }
 +
 +    uint64_t readPC() { return actualXC->readPC(); }
 +
 +    void setPC(uint64_t val)
 +    {
 +        actualXC->setPC(val);
 +        checkerXC->setPC(val);
 +        checkerCPU->recordPCChange(val);
 +    }
 +
 +    uint64_t readNextPC() { return actualXC->readNextPC(); }
 +
 +    void setNextPC(uint64_t val)
 +    {
 +        actualXC->setNextPC(val);
 +        checkerXC->setNextPC(val);
 +        checkerCPU->recordNextPCChange(val);
 +    }
 +
 +    uint64_t readNextNPC() { return actualXC->readNextNPC(); }
 +
 +    void setNextNPC(uint64_t val)
 +    {
 +        actualXC->setNextNPC(val);
 +        checkerXC->setNextNPC(val);
 +        checkerCPU->recordNextPCChange(val);
 +    }
 +
 +    MiscReg readMiscReg(int misc_reg)
 +    { return actualXC->readMiscReg(misc_reg); }
 +
 +    MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault)
 +    { return actualXC->readMiscRegWithEffect(misc_reg, fault); }
 +
 +    Fault setMiscReg(int misc_reg, const MiscReg &val)
 +    {
 +        checkerXC->setMiscReg(misc_reg, val);
 +        return actualXC->setMiscReg(misc_reg, val);
 +    }
 +
 +    Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val)
 +    {
 +        checkerXC->setMiscRegWithEffect(misc_reg, val);
 +        return actualXC->setMiscRegWithEffect(misc_reg, val);
 +    }
 +
 +    unsigned readStCondFailures()
 +    { return actualXC->readStCondFailures(); }
 +
 +    void setStCondFailures(unsigned sc_failures)
 +    {
 +        checkerXC->setStCondFailures(sc_failures);
 +        actualXC->setStCondFailures(sc_failures);
 +    }
 +#if FULL_SYSTEM
 +    bool inPalMode() { return actualXC->inPalMode(); }
 +#endif
 +
 +    // @todo: Fix this!
 +    bool misspeculating() { return actualXC->misspeculating(); }
 +
 +#if !FULL_SYSTEM
 +    IntReg getSyscallArg(int i) { return actualXC->getSyscallArg(i); }
 +
 +    // used to shift args for indirect syscall
 +    void setSyscallArg(int i, IntReg val)
 +    {
 +        checkerXC->setSyscallArg(i, val);
 +        actualXC->setSyscallArg(i, val);
 +    }
 +
 +    void setSyscallReturn(SyscallReturn return_value)
 +    {
 +        checkerXC->setSyscallReturn(return_value);
 +        actualXC->setSyscallReturn(return_value);
 +    }
 +
 +    Counter readFuncExeInst() { return actualXC->readFuncExeInst(); }
 +#endif
 +    void changeRegFileContext(RegFile::ContextParam param,
 +            RegFile::ContextVal val)
 +    {
 +        actualXC->changeRegFileContext(param, val);
 +        checkerXC->changeRegFileContext(param, val);
 +    }
 +};
 +
 +#endif // __CPU_CHECKER_EXEC_CONTEXT_HH__
index c7883b42b15bfcbea1f449dfd83221312b24945e,0000000000000000000000000000000000000000..31e945f739b4ab54e19d325ba009ef081f3e0124
mode 100644,000000..100644
--- /dev/null
@@@ -1,121 -1,0 +1,151 @@@
++/*
++ * Copyright (c) 2006 The Regents of The University of Michigan
++ * 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.
++ */
 +
 +#include <string>
 +
 +#include "cpu/checker/cpu.hh"
 +#include "cpu/inst_seq.hh"
 +#include "cpu/o3/alpha_dyn_inst.hh"
 +#include "cpu/o3/alpha_impl.hh"
 +#include "sim/builder.hh"
 +#include "sim/process.hh"
 +#include "sim/sim_object.hh"
 +
 +class MemObject;
 +
++/**
++ * Specific non-templated derived class used for SimObject configuration.
++ */
 +class O3Checker : public Checker<RefCountingPtr<AlphaDynInst<AlphaSimpleImpl> > >
 +{
 +  public:
 +    O3Checker(Params *p)
 +        : Checker<RefCountingPtr<AlphaDynInst<AlphaSimpleImpl> > >(p)
 +    { }
 +};
 +
 +////////////////////////////////////////////////////////////////////////
 +//
 +//  CheckerCPU Simulation Object
 +//
 +BEGIN_DECLARE_SIM_OBJECT_PARAMS(O3Checker)
 +
 +    Param<Counter> max_insts_any_thread;
 +    Param<Counter> max_insts_all_threads;
 +    Param<Counter> max_loads_any_thread;
 +    Param<Counter> max_loads_all_threads;
 +
 +#if FULL_SYSTEM
 +    SimObjectParam<AlphaITB *> itb;
 +    SimObjectParam<AlphaDTB *> dtb;
 +    SimObjectParam<MemObject *> mem;
 +    SimObjectParam<System *> system;
 +    Param<int> cpu_id;
 +    Param<Tick> profile;
 +#else
 +    SimObjectParam<Process *> workload;
 +#endif // FULL_SYSTEM
 +    Param<int> clock;
 +
 +    Param<bool> defer_registration;
 +    Param<bool> exitOnError;
 +    Param<bool> function_trace;
 +    Param<Tick> function_trace_start;
 +
 +END_DECLARE_SIM_OBJECT_PARAMS(O3Checker)
 +
 +BEGIN_INIT_SIM_OBJECT_PARAMS(O3Checker)
 +
 +    INIT_PARAM(max_insts_any_thread,
 +               "terminate when any thread reaches this inst count"),
 +    INIT_PARAM(max_insts_all_threads,
 +               "terminate when all threads have reached this inst count"),
 +    INIT_PARAM(max_loads_any_thread,
 +               "terminate when any thread reaches this load count"),
 +    INIT_PARAM(max_loads_all_threads,
 +               "terminate when all threads have reached this load count"),
 +
 +#if FULL_SYSTEM
 +    INIT_PARAM(itb, "Instruction TLB"),
 +    INIT_PARAM(dtb, "Data TLB"),
 +    INIT_PARAM(mem, "memory"),
 +    INIT_PARAM(system, "system object"),
 +    INIT_PARAM(cpu_id, "processor ID"),
 +    INIT_PARAM(profile, ""),
 +#else
 +    INIT_PARAM(workload, "processes to run"),
 +#endif // FULL_SYSTEM
 +
 +    INIT_PARAM(clock, "clock speed"),
 +
 +    INIT_PARAM(defer_registration, "defer system registration (for sampling)"),
 +    INIT_PARAM(exitOnError, "exit on error"),
 +    INIT_PARAM(function_trace, "Enable function trace"),
 +    INIT_PARAM(function_trace_start, "Cycle to start function trace")
 +
 +END_INIT_SIM_OBJECT_PARAMS(O3Checker)
 +
 +
 +CREATE_SIM_OBJECT(O3Checker)
 +{
 +    O3Checker::Params *params = new O3Checker::Params();
 +    params->name = getInstanceName();
 +    params->numberOfThreads = 1;
 +    params->max_insts_any_thread = 0;
 +    params->max_insts_all_threads = 0;
 +    params->max_loads_any_thread = 0;
 +    params->max_loads_all_threads = 0;
 +    params->exitOnError = exitOnError;
 +    params->deferRegistration = defer_registration;
 +    params->functionTrace = function_trace;
 +    params->functionTraceStart = function_trace_start;
 +    params->clock = clock;
 +    // Hack to touch all parameters.  Consider not deriving Checker
 +    // from BaseCPU..it's not really a CPU in the end.
 +    Counter temp;
 +    temp = max_insts_any_thread;
 +    temp = max_insts_all_threads;
 +    temp = max_loads_any_thread;
 +    temp = max_loads_all_threads;
 +
 +#if FULL_SYSTEM
 +    params->itb = itb;
 +    params->dtb = dtb;
 +    params->mem = mem;
 +    params->system = system;
 +    params->cpu_id = cpu_id;
 +    params->profile = profile;
 +#else
 +    params->process = workload;
 +#endif
 +
 +    O3Checker *cpu = new O3Checker(params);
 +    return cpu;
 +}
 +
 +REGISTER_SIM_OBJECT("O3Checker", O3Checker)
index 3d6a78bedf5bd1285f4ec01fffcee405b9bfb5b7,0000000000000000000000000000000000000000..77a45ea268798dc642c2ba361d3347bb3eef4319
mode 100644,000000..100644
--- /dev/null
@@@ -1,145 -1,0 +1,146 @@@
- DefaultBP::DefaultBP(unsigned _localPredictorSize,
-                      unsigned _localCtrBits,
-                      unsigned _instShiftAmt)
 +/*
 + * Copyright (c) 2004-2006 The Regents of The University of Michigan
 + * 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: Kevin Lim
 + */
 +
 +#include "base/intmath.hh"
 +#include "base/misc.hh"
 +#include "base/trace.hh"
 +#include "cpu/o3/2bit_local_pred.hh"
 +
- DefaultBP::reset()
++LocalBP::LocalBP(unsigned _localPredictorSize,
++                 unsigned _localCtrBits,
++                 unsigned _instShiftAmt)
 +    : localPredictorSize(_localPredictorSize),
 +      localCtrBits(_localCtrBits),
 +      instShiftAmt(_instShiftAmt)
 +{
 +    if (!isPowerOf2(localPredictorSize)) {
 +        fatal("Invalid local predictor size!\n");
 +    }
 +
 +    localPredictorSets = localPredictorSize / localCtrBits;
 +
 +    if (!isPowerOf2(localPredictorSets)) {
 +        fatal("Invalid number of local predictor sets! Check localCtrBits.\n");
 +    }
 +
 +    // Setup the index mask.
 +    indexMask = localPredictorSets - 1;
 +
 +    DPRINTF(Fetch, "Branch predictor: index mask: %#x\n", indexMask);
 +
 +    // Setup the array of counters for the local predictor.
 +    localCtrs.resize(localPredictorSets);
 +
 +    for (int i = 0; i < localPredictorSets; ++i)
 +        localCtrs[i].setBits(_localCtrBits);
 +
 +    DPRINTF(Fetch, "Branch predictor: local predictor size: %i\n",
 +            localPredictorSize);
 +
 +    DPRINTF(Fetch, "Branch predictor: local counter bits: %i\n", localCtrBits);
 +
 +    DPRINTF(Fetch, "Branch predictor: instruction shift amount: %i\n",
 +            instShiftAmt);
 +}
 +
 +void
- DefaultBP::lookup(Addr &branch_addr)
++LocalBP::reset()
 +{
 +    for (int i = 0; i < localPredictorSets; ++i) {
 +        localCtrs[i].reset();
 +    }
 +}
 +
 +bool
-     uint8_t local_prediction;
++LocalBP::lookup(Addr &branch_addr, void * &bp_history)
 +{
 +    bool taken;
-     local_prediction = localCtrs[local_predictor_idx].read();
++    uint8_t counter_val;
 +    unsigned local_predictor_idx = getLocalIndex(branch_addr);
 +
 +    DPRINTF(Fetch, "Branch predictor: Looking up index %#x\n",
 +            local_predictor_idx);
 +
-             (int)local_prediction);
++    counter_val = localCtrs[local_predictor_idx].read();
 +
 +    DPRINTF(Fetch, "Branch predictor: prediction is %i.\n",
-     taken = getPrediction(local_prediction);
++            (int)counter_val);
 +
- DefaultBP::update(Addr &branch_addr, bool taken)
++    taken = getPrediction(counter_val);
 +
 +#if 0
 +    // Speculative update.
 +    if (taken) {
 +        DPRINTF(Fetch, "Branch predictor: Branch updated as taken.\n");
 +        localCtrs[local_predictor_idx].increment();
 +    } else {
 +        DPRINTF(Fetch, "Branch predictor: Branch updated as not taken.\n");
 +        localCtrs[local_predictor_idx].decrement();
 +    }
 +#endif
 +
 +    return taken;
 +}
 +
 +void
- DefaultBP::getPrediction(uint8_t &count)
++LocalBP::update(Addr &branch_addr, bool taken, void *bp_history)
 +{
++    assert(bp_history == NULL);
 +    unsigned local_predictor_idx;
 +
 +    // Update the local predictor.
 +    local_predictor_idx = getLocalIndex(branch_addr);
 +
 +    DPRINTF(Fetch, "Branch predictor: Looking up index %#x\n",
 +            local_predictor_idx);
 +
 +    if (taken) {
 +        DPRINTF(Fetch, "Branch predictor: Branch updated as taken.\n");
 +        localCtrs[local_predictor_idx].increment();
 +    } else {
 +        DPRINTF(Fetch, "Branch predictor: Branch updated as not taken.\n");
 +        localCtrs[local_predictor_idx].decrement();
 +    }
 +}
 +
 +inline
 +bool
- DefaultBP::getLocalIndex(Addr &branch_addr)
++LocalBP::getPrediction(uint8_t &count)
 +{
 +    // Get the MSB of the count
 +    return (count >> (localCtrBits - 1));
 +}
 +
 +inline
 +unsigned
++LocalBP::getLocalIndex(Addr &branch_addr)
 +{
 +    return (branch_addr >> instShiftAmt) & indexMask;
 +}
index 6e02a49be6191724459393198475999c18064b36,0000000000000000000000000000000000000000..0a2a71d3e6701cda6e3aa1907c83dcf57ee5dbfa
mode 100644,000000..100644
--- /dev/null
@@@ -1,101 -1,0 +1,111 @@@
- class DefaultBP
 +/*
 + * Copyright (c) 2004-2006 The Regents of The University of Michigan
 + * 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: Kevin Lim
 + */
 +
 +#ifndef __CPU_O3_2BIT_LOCAL_PRED_HH__
 +#define __CPU_O3_2BIT_LOCAL_PRED_HH__
 +
 +// For Addr type.
 +#include "arch/isa_traits.hh"
 +#include "cpu/o3/sat_counter.hh"
 +
 +#include <vector>
 +
-     DefaultBP(unsigned localPredictorSize, unsigned localCtrBits,
-               unsigned instShiftAmt);
++/**
++ * Implements a local predictor that uses the PC to index into a table of
++ * counters.  Note that any time a pointer to the bp_history is given, it
++ * should be NULL using this predictor because it does not have any branch
++ * predictor state that needs to be recorded or updated; the update can be
++ * determined solely by the branch being taken or not taken.
++ */
++class LocalBP
 +{
 +  public:
 +    /**
 +     * Default branch predictor constructor.
 +     * @param localPredictorSize Size of the local predictor.
 +     * @param localCtrBits Number of bits per counter.
 +     * @param instShiftAmt Offset amount for instructions to ignore alignment.
 +     */
-     bool lookup(Addr &branch_addr);
++    LocalBP(unsigned localPredictorSize, unsigned localCtrBits,
++            unsigned instShiftAmt);
 +
 +    /**
 +     * Looks up the given address in the branch predictor and returns
 +     * a true/false value as to whether it is taken.
 +     * @param branch_addr The address of the branch to look up.
++     * @param bp_history Pointer to any bp history state.
 +     * @return Whether or not the branch is taken.
 +     */
-     void update(Addr &branch_addr, bool taken);
++    bool lookup(Addr &branch_addr, void * &bp_history);
 +
 +    /**
 +     * Updates the branch predictor with the actual result of a branch.
 +     * @param branch_addr The address of the branch to update.
 +     * @param taken Whether or not the branch was taken.
 +     */
++    void update(Addr &branch_addr, bool taken, void *bp_history);
++
++    void squash(void *bp_history)
++    { assert(bp_history == NULL); }
 +
 +    void reset();
 +
 +  private:
 +    /**
 +     *  Returns the taken/not taken prediction given the value of the
 +     *  counter.
 +     *  @param count The value of the counter.
 +     *  @return The prediction based on the counter value.
 +     */
 +    inline bool getPrediction(uint8_t &count);
 +
 +    /** Calculates the local index based on the PC. */
 +    inline unsigned getLocalIndex(Addr &PC);
 +
 +    /** Array of counters that make up the local predictor. */
 +    std::vector<SatCounter> localCtrs;
 +
 +    /** Size of the local predictor. */
 +    unsigned localPredictorSize;
 +
 +    /** Number of sets. */
 +    unsigned localPredictorSets;
 +
 +    /** Number of bits of the local predictor's counters. */
 +    unsigned localCtrBits;
 +
 +    /** Number of bits to shift the PC when calculating index. */
 +    unsigned instShiftAmt;
 +
 +    /** Mask to get index bits. */
 +    unsigned indexMask;
 +};
 +
 +#endif // __CPU_O3_2BIT_LOCAL_PRED_HH__
index 4d889866aa300c0e321096a58549a64c12c8fedd,0000000000000000000000000000000000000000..2e5c856a8f3e9dcd38e607222094e02c7f1217e4
mode 100644,000000..100644
--- /dev/null
@@@ -1,444 -1,0 +1,525 @@@
-         virtual AlphaDTB * getDTBPtr() { return cpu->dtb; }
 +/*
 + * Copyright (c) 2004-2006 The Regents of The University of Michigan
 + * 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: Kevin Lim
 + */
 +
 +#ifndef __CPU_O3_ALPHA_FULL_CPU_HH__
 +#define __CPU_O3_ALPHA_FULL_CPU_HH__
 +
 +#include "arch/isa_traits.hh"
 +#include "cpu/exec_context.hh"
 +#include "cpu/o3/cpu.hh"
 +#include "sim/byteswap.hh"
 +
 +class EndQuiesceEvent;
 +namespace Kernel {
 +    class Statistics;
 +};
 +
 +class TranslatingPort;
 +
++/**
++ * AlphaFullCPU class.  Derives from the FullO3CPU class, and
++ * implements all ISA and implementation specific functions of the
++ * CPU.  This is the CPU class that is used for the SimObjects, and is
++ * what is given to the DynInsts.  Most of its state exists in the
++ * FullO3CPU; the state is has is mainly for ISA specific
++ * functionality.
++ */
 +template <class Impl>
 +class AlphaFullCPU : public FullO3CPU<Impl>
 +{
 +  protected:
 +    typedef TheISA::IntReg IntReg;
 +    typedef TheISA::FloatReg FloatReg;
 +    typedef TheISA::FloatRegBits FloatRegBits;
 +    typedef TheISA::MiscReg MiscReg;
 +    typedef TheISA::RegFile RegFile;
 +    typedef TheISA::MiscRegFile MiscRegFile;
 +
 +  public:
 +    typedef O3ThreadState<Impl> ImplState;
 +    typedef O3ThreadState<Impl> Thread;
 +    typedef typename Impl::Params Params;
 +
 +    /** Constructs an AlphaFullCPU with the given parameters. */
 +    AlphaFullCPU(Params *params);
 +
++    /**
++     * Derived ExecContext class for use with the AlphaFullCPU.  It
++     * provides the interface for any external objects to access a
++     * single thread's state and some general CPU state.  Any time
++     * external objects try to update state through this interface,
++     * the CPU will create an event to squash all in-flight
++     * instructions in order to ensure state is maintained correctly.
++     */
 +    class AlphaXC : public ExecContext
 +    {
 +      public:
++        /** Pointer to the CPU. */
 +        AlphaFullCPU<Impl> *cpu;
 +
++        /** Pointer to the thread state that this XC corrseponds to. */
 +        O3ThreadState<Impl> *thread;
 +
++        /** Returns a pointer to this CPU. */
 +        virtual BaseCPU *getCpuPtr() { return cpu; }
 +
++        /** Sets this CPU's ID. */
 +        virtual void setCpuId(int id) { cpu->cpu_id = id; }
 +
++        /** Reads this CPU's ID. */
 +        virtual int readCpuId() { return cpu->cpu_id; }
 +
 +        virtual TranslatingPort *getMemPort() { return /*thread->port*/ NULL; }
 +
 +#if FULL_SYSTEM
++        /** Returns a pointer to the system. */
 +        virtual System *getSystemPtr() { return cpu->system; }
 +
++        /** Returns a pointer to physical memory. */
 +        virtual PhysicalMemory *getPhysMemPtr() { return cpu->physmem; }
 +
++        /** Returns a pointer to the ITB. */
 +        virtual AlphaITB *getITBPtr() { return cpu->itb; }
 +
++        /** Returns a pointer to the DTB. */
++        virtual AlphaDTB *getDTBPtr() { return cpu->dtb; }
 +
++        /** Returns a pointer to this thread's kernel statistics. */
 +        virtual Kernel::Statistics *getKernelStats()
 +        { return thread->kernelStats; }
 +#else
++        /** Returns a pointer to this thread's process. */
 +        virtual Process *getProcessPtr() { return thread->process; }
 +#endif
-         /// Set the status to Active.  Optional delay indicates number of
-         /// cycles to wait before beginning execution.
++        /** Returns this thread's status. */
 +        virtual Status status() const { return thread->status(); }
 +
++        /** Sets this thread's status. */
 +        virtual void setStatus(Status new_status)
 +        { thread->setStatus(new_status); }
 +
-         /// Set the status to Suspended.
++        /** Set the status to Active.  Optional delay indicates number of
++         * cycles to wait before beginning execution. */
 +        virtual void activate(int delay = 1);
 +
-         /// Set the status to Unallocated.
++        /** Set the status to Suspended. */
 +        virtual void suspend();
 +
-         /// Set the status to Halted.
++        /** Set the status to Unallocated. */
 +        virtual void deallocate();
 +
++        /** Set the status to Halted. */
 +        virtual void halt();
 +
 +#if FULL_SYSTEM
++        /** Dumps the function profiling information.
++         * @todo: Implement.
++         */
 +        virtual void dumpFuncProfile();
 +#endif
++        /** Takes over execution of a thread from another CPU. */
 +        virtual void takeOverFrom(ExecContext *old_context);
 +
++        /** Registers statistics associated with this XC. */
 +        virtual void regStats(const std::string &name);
 +
++        /** Serializes state. */
 +        virtual void serialize(std::ostream &os);
++        /** Unserializes state. */
 +        virtual void unserialize(Checkpoint *cp, const std::string &section);
 +
 +#if FULL_SYSTEM
++        /** Returns pointer to the quiesce event. */
 +        virtual EndQuiesceEvent *getQuiesceEvent();
 +
++        /** Reads the last tick that this thread was activated on. */
 +        virtual Tick readLastActivate();
++        /** Reads the last tick that this thread was suspended on. */
 +        virtual Tick readLastSuspend();
 +
++        /** Clears the function profiling information. */
 +        virtual void profileClear();
++        /** Samples the function profiling information. */
 +        virtual void profileSample();
 +#endif
++        /** Returns this thread's ID number. */
 +        virtual int getThreadNum() { return thread->tid; }
 +
++        /** Returns the instruction this thread is currently committing.
++         *  Only used when an instruction faults.
++         */
 +        virtual TheISA::MachInst getInst();
 +
++        /** Copies the architectural registers from another XC into this XC. */
 +        virtual void copyArchRegs(ExecContext *xc);
 +
++        /** Resets all architectural registers to 0. */
 +        virtual void clearArchRegs();
 +
++        /** Reads an integer register. */
 +        virtual uint64_t readIntReg(int reg_idx);
 +
 +        virtual FloatReg readFloatReg(int reg_idx, int width);
 +
 +        virtual FloatReg readFloatReg(int reg_idx);
 +
 +        virtual FloatRegBits readFloatRegBits(int reg_idx, int width);
 +
 +        virtual FloatRegBits readFloatRegBits(int reg_idx);
 +
++        /** Sets an integer register to a value. */
 +        virtual void setIntReg(int reg_idx, uint64_t val);
 +
 +        virtual void setFloatReg(int reg_idx, FloatReg val, int width);
 +
 +        virtual void setFloatReg(int reg_idx, FloatReg val);
 +
 +        virtual void setFloatRegBits(int reg_idx, FloatRegBits val, int width);
 +
 +        virtual void setFloatRegBits(int reg_idx, FloatRegBits val);
 +
++        /** Reads this thread's PC. */
 +        virtual uint64_t readPC()
 +        { return cpu->readPC(thread->tid); }
 +
++        /** Sets this thread's PC. */
 +        virtual void setPC(uint64_t val);
 +
++        /** Reads this thread's next PC. */
 +        virtual uint64_t readNextPC()
 +        { return cpu->readNextPC(thread->tid); }
 +
++        /** Sets this thread's next PC. */
 +        virtual void setNextPC(uint64_t val);
 +
 +        virtual uint64_t readNextNPC()
 +        {
 +            panic("Alpha has no NextNPC!");
 +            return 0;
 +        }
 +
 +        virtual void setNextNPC(uint64_t val)
 +        { panic("Alpha has no NextNPC!"); }
 +
++        /** Reads a miscellaneous register. */
 +        virtual MiscReg readMiscReg(int misc_reg)
 +        { return cpu->readMiscReg(misc_reg, thread->tid); }
 +
++        /** Reads a misc. register, including any side-effects the
++         * read might have as defined by the architecture. */
 +        virtual MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault)
 +        { return cpu->readMiscRegWithEffect(misc_reg, fault, thread->tid); }
 +
++        /** Sets a misc. register. */
 +        virtual Fault setMiscReg(int misc_reg, const MiscReg &val);
 +
++        /** Sets a misc. register, including any side-effects the
++         * write might have as defined by the architecture. */
 +        virtual Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val);
 +
++        /** Returns the number of consecutive store conditional failures. */
 +        // @todo: Figure out where these store cond failures should go.
 +        virtual unsigned readStCondFailures()
 +        { return thread->storeCondFailures; }
 +
++        /** Sets the number of consecutive store conditional failures. */
 +        virtual void setStCondFailures(unsigned sc_failures)
 +        { thread->storeCondFailures = sc_failures; }
 +
 +#if FULL_SYSTEM
++        /** Returns if the thread is currently in PAL mode, based on
++         * the PC's value. */
 +        virtual bool inPalMode()
 +        { return TheISA::PcPAL(cpu->readPC(thread->tid)); }
 +#endif
 +        // Only really makes sense for old CPU model.  Lots of code
 +        // outside the CPU still checks this function, so it will
 +        // always return false to keep everything working.
++        /** Checks if the thread is misspeculating.  Because it is
++         * very difficult to determine if the thread is
++         * misspeculating, this is set as false. */
 +        virtual bool misspeculating() { return false; }
 +
 +#if !FULL_SYSTEM
++        /** Gets a syscall argument by index. */
 +        virtual IntReg getSyscallArg(int i);
 +
++        /** Sets a syscall argument. */
 +        virtual void setSyscallArg(int i, IntReg val);
 +
++        /** Sets the syscall return value. */
 +        virtual void setSyscallReturn(SyscallReturn return_value);
 +
++        /** Executes a syscall in SE mode. */
 +        virtual void syscall(int64_t callnum)
 +        { return cpu->syscall(callnum, thread->tid); }
 +
++        /** Reads the funcExeInst counter. */
 +        virtual Counter readFuncExeInst() { return thread->funcExeInst; }
 +#endif
 +        virtual void changeRegFileContext(TheISA::RegFile::ContextParam param,
 +                                          TheISA::RegFile::ContextVal val)
 +        { panic("Not supported on Alpha!"); }
 +    };
 +
 +#if FULL_SYSTEM
 +    /** ITB pointer. */
 +    AlphaITB *itb;
 +    /** DTB pointer. */
 +    AlphaDTB *dtb;
 +#endif
 +
 +    /** Registers statistics. */
 +    void regStats();
 +
 +#if FULL_SYSTEM
 +    /** Translates instruction requestion. */
 +    Fault translateInstReq(RequestPtr &req)
 +    {
 +        return itb->translate(req);
 +    }
 +
 +    /** Translates data read request. */
 +    Fault translateDataReadReq(RequestPtr &req)
 +    {
 +        return dtb->translate(req, false);
 +    }
 +
 +    /** Translates data write request. */
 +    Fault translateDataWriteReq(RequestPtr &req)
 +    {
 +        return dtb->translate(req, true);
 +    }
 +
 +#else
 +    /** Translates instruction requestion in syscall emulation mode. */
 +    Fault translateInstReq(RequestPtr &req)
 +    {
 +        int tid = req->getThreadNum();
 +        return this->thread[tid]->process->pTable->translate(req);
 +    }
 +
 +    /** Translates data read request in syscall emulation mode. */
 +    Fault translateDataReadReq(RequestPtr &req)
 +    {
 +        int tid = req->getThreadNum();
 +        return this->thread[tid]->process->pTable->translate(req);
 +    }
 +
 +    /** Translates data write request in syscall emulation mode. */
 +    Fault translateDataWriteReq(RequestPtr &req)
 +    {
 +        int tid = req->getThreadNum();
 +        return this->thread[tid]->process->pTable->translate(req);
 +    }
 +
 +#endif
++    /** Reads a miscellaneous register. */
 +    MiscReg readMiscReg(int misc_reg, unsigned tid);
 +
++    /** Reads a misc. register, including any side effects the read
++     * might have as defined by the architecture.
++     */
 +    MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault, unsigned tid);
 +
++    /** Sets a miscellaneous register. */
 +    Fault setMiscReg(int misc_reg, const MiscReg &val, unsigned tid);
 +
++    /** Sets a misc. register, including any side effects the write
++     * might have as defined by the architecture.
++     */
 +    Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val, unsigned tid);
 +
++    /** Initiates a squash of all in-flight instructions for a given
++     * thread.  The source of the squash is an external update of
++     * state through the XC.
++     */
 +    void squashFromXC(unsigned tid);
 +
 +#if FULL_SYSTEM
++    /** Posts an interrupt. */
 +    void post_interrupt(int int_num, int index);
-     void syscall(int64_t callnum, int thread_num);
++    /** Reads the interrupt flag. */
 +    int readIntrFlag();
 +    /** Sets the interrupt flags. */
 +    void setIntrFlag(int val);
 +    /** HW return from error interrupt. */
 +    Fault hwrei(unsigned tid);
 +    /** Returns if a specific PC is a PAL mode PC. */
 +    bool inPalMode(uint64_t PC)
 +    { return AlphaISA::PcPAL(PC); }
 +
 +    /** Traps to handle given fault. */
 +    void trap(Fault fault, unsigned tid);
 +    bool simPalCheck(int palFunc, unsigned tid);
 +
 +    /** Processes any interrupts. */
 +    void processInterrupts();
 +
 +    /** Halts the CPU. */
 +    void halt() { panic("Halt not implemented!\n"); }
 +#endif
 +
 +
 +#if !FULL_SYSTEM
 +    /** Executes a syscall.
 +     * @todo: Determine if this needs to be virtual.
 +     */
++    void syscall(int64_t callnum, int tid);
 +    /** Gets a syscall argument. */
 +    IntReg getSyscallArg(int i, int tid);
 +
 +    /** Used to shift args for indirect syscall. */
 +    void setSyscallArg(int i, IntReg val, int tid);
 +
 +    /** Sets the return value of a syscall. */
 +    void setSyscallReturn(SyscallReturn return_value, int tid);
 +#endif
 +
 +    /** Read from memory function. */
 +    template <class T>
 +    Fault read(RequestPtr &req, T &data)
 +    {
 +#if 0
 +#if FULL_SYSTEM && THE_ISA == ALPHA_ISA
 +        if (req->flags & LOCKED) {
 +            req->xc->setMiscReg(TheISA::Lock_Addr_DepTag, req->paddr);
 +            req->xc->setMiscReg(TheISA::Lock_Flag_DepTag, true);
 +        }
 +#endif
 +#endif
 +        Fault error;
 +
 +#if FULL_SYSTEM
 +        // @todo: Fix this LL/SC hack.
 +        if (req->flags & LOCKED) {
 +            lockAddr = req->paddr;
 +            lockFlag = true;
 +        }
 +#endif
 +
 +        error = this->mem->read(req, data);
 +        data = gtoh(data);
 +        return error;
 +    }
 +
 +    /** CPU read function, forwards read to LSQ. */
 +    template <class T>
 +    Fault read(RequestPtr &req, T &data, int load_idx)
 +    {
 +        return this->iew.ldstQueue.read(req, data, load_idx);
 +    }
 +
 +    /** Write to memory function. */
 +    template <class T>
 +    Fault write(RequestPtr &req, T &data)
 +    {
 +#if 0
 +#if FULL_SYSTEM && THE_ISA == ALPHA_ISA
 +        ExecContext *xc;
 +
 +        // If this is a store conditional, act appropriately
 +        if (req->flags & LOCKED) {
 +            xc = req->xc;
 +
 +            if (req->flags & UNCACHEABLE) {
 +                // Don't update result register (see stq_c in isa_desc)
 +                req->result = 2;
 +                xc->setStCondFailures(0);//Needed? [RGD]
 +            } else {
 +                bool lock_flag = xc->readMiscReg(TheISA::Lock_Flag_DepTag);
 +                Addr lock_addr = xc->readMiscReg(TheISA::Lock_Addr_DepTag);
 +                req->result = lock_flag;
 +                if (!lock_flag ||
 +                    ((lock_addr & ~0xf) != (req->paddr & ~0xf))) {
 +                    xc->setMiscReg(TheISA::Lock_Flag_DepTag, false);
 +                    xc->setStCondFailures(xc->readStCondFailures() + 1);
 +                    if (((xc->readStCondFailures()) % 100000) == 0) {
 +                        std::cerr << "Warning: "
 +                                  << xc->readStCondFailures()
 +                                  << " consecutive store conditional failures "
 +                                  << "on cpu " << req->xc->readCpuId()
 +                                  << std::endl;
 +                    }
 +                    return NoFault;
 +                }
 +                else xc->setStCondFailures(0);
 +            }
 +        }
 +
 +        // Need to clear any locked flags on other proccessors for
 +        // this address.  Only do this for succsful Store Conditionals
 +        // and all other stores (WH64?).  Unsuccessful Store
 +        // Conditionals would have returned above, and wouldn't fall
 +        // through.
 +        for (int i = 0; i < this->system->execContexts.size(); i++){
 +            xc = this->system->execContexts[i];
 +            if ((xc->readMiscReg(TheISA::Lock_Addr_DepTag) & ~0xf) ==
 +                (req->paddr & ~0xf)) {
 +                xc->setMiscReg(TheISA::Lock_Flag_DepTag, false);
 +            }
 +        }
 +
 +#endif
 +#endif
 +
 +#if FULL_SYSTEM
 +        // @todo: Fix this LL/SC hack.
 +        if (req->flags & LOCKED) {
 +            if (req->flags & UNCACHEABLE) {
 +                req->result = 2;
 +            } else {
 +                if (this->lockFlag) {
 +                    req->result = 1;
 +                } else {
 +                    req->result = 0;
 +                    return NoFault;
 +                }
 +            }
 +        }
 +#endif
 +
 +        return this->mem->write(req, (T)htog(data));
 +    }
 +
 +    /** CPU write function, forwards write to LSQ. */
 +    template <class T>
 +    Fault write(RequestPtr &req, T &data, int store_idx)
 +    {
 +        return this->iew.ldstQueue.write(req, data, store_idx);
 +    }
 +
 +    Addr lockAddr;
 +
++    /** Temporary fix for the lock flag, works in the UP case. */
 +    bool lockFlag;
 +};
 +
 +#endif // __CPU_O3_ALPHA_FULL_CPU_HH__
index c91e2c7c931bc05241dd45e59640cbd5236928ea,0000000000000000000000000000000000000000..1592261de6a88d84ff944ac885e6191cfdfe574b
mode 100644,000000..100644
--- /dev/null
@@@ -1,410 -1,0 +1,413 @@@
 +/*
 + * Copyright (c) 2004-2006 The Regents of The University of Michigan
 + * 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: Kevin Lim
 + */
 +
 +#include <string>
 +
 +#include "cpu/base.hh"
 +#include "cpu/o3/alpha_cpu.hh"
 +#include "cpu/o3/alpha_impl.hh"
 +#include "cpu/o3/alpha_params.hh"
 +#include "cpu/o3/fu_pool.hh"
 +#include "sim/builder.hh"
 +
 +class DerivAlphaFullCPU : public AlphaFullCPU<AlphaSimpleImpl>
 +{
 +  public:
 +    DerivAlphaFullCPU(AlphaSimpleParams *p)
 +        : AlphaFullCPU<AlphaSimpleImpl>(p)
 +    { }
 +};
 +
 +BEGIN_DECLARE_SIM_OBJECT_PARAMS(DerivAlphaFullCPU)
 +
 +    Param<int> clock;
 +    Param<int> numThreads;
 +Param<int> activity;
 +
 +#if FULL_SYSTEM
 +SimObjectParam<System *> system;
 +Param<int> cpu_id;
 +SimObjectParam<AlphaITB *> itb;
 +SimObjectParam<AlphaDTB *> dtb;
 +#else
 +SimObjectVectorParam<Process *> workload;
 +//SimObjectParam<PageTable *> page_table;
 +#endif // FULL_SYSTEM
 +
 +SimObjectParam<MemObject *> mem;
 +
 +SimObjectParam<BaseCPU *> checker;
 +
 +Param<Counter> max_insts_any_thread;
 +Param<Counter> max_insts_all_threads;
 +Param<Counter> max_loads_any_thread;
 +Param<Counter> max_loads_all_threads;
 +
 +Param<unsigned> cachePorts;
 +
 +Param<unsigned> decodeToFetchDelay;
 +Param<unsigned> renameToFetchDelay;
 +Param<unsigned> iewToFetchDelay;
 +Param<unsigned> commitToFetchDelay;
 +Param<unsigned> fetchWidth;
 +
 +Param<unsigned> renameToDecodeDelay;
 +Param<unsigned> iewToDecodeDelay;
 +Param<unsigned> commitToDecodeDelay;
 +Param<unsigned> fetchToDecodeDelay;
 +Param<unsigned> decodeWidth;
 +
 +Param<unsigned> iewToRenameDelay;
 +Param<unsigned> commitToRenameDelay;
 +Param<unsigned> decodeToRenameDelay;
 +Param<unsigned> renameWidth;
 +
 +Param<unsigned> commitToIEWDelay;
 +Param<unsigned> renameToIEWDelay;
 +Param<unsigned> issueToExecuteDelay;
 +Param<unsigned> issueWidth;
 +Param<unsigned> executeWidth;
 +Param<unsigned> executeIntWidth;
 +Param<unsigned> executeFloatWidth;
 +Param<unsigned> executeBranchWidth;
 +Param<unsigned> executeMemoryWidth;
 +SimObjectParam<FUPool *> fuPool;
 +
 +Param<unsigned> iewToCommitDelay;
 +Param<unsigned> renameToROBDelay;
 +Param<unsigned> commitWidth;
 +Param<unsigned> squashWidth;
 +Param<Tick> trapLatency;
 +Param<Tick> fetchTrapLatency;
 +
++Param<std::string> predType;
 +Param<unsigned> localPredictorSize;
 +Param<unsigned> localCtrBits;
 +Param<unsigned> localHistoryTableSize;
 +Param<unsigned> localHistoryBits;
 +Param<unsigned> globalPredictorSize;
 +Param<unsigned> globalCtrBits;
 +Param<unsigned> globalHistoryBits;
 +Param<unsigned> choicePredictorSize;
 +Param<unsigned> choiceCtrBits;
 +
 +Param<unsigned> BTBEntries;
 +Param<unsigned> BTBTagSize;
 +
 +Param<unsigned> RASSize;
 +
 +Param<unsigned> LQEntries;
 +Param<unsigned> SQEntries;
 +Param<unsigned> LFSTSize;
 +Param<unsigned> SSITSize;
 +
 +Param<unsigned> numPhysIntRegs;
 +Param<unsigned> numPhysFloatRegs;
 +Param<unsigned> numIQEntries;
 +Param<unsigned> numROBEntries;
 +
 +Param<unsigned> smtNumFetchingThreads;
 +Param<std::string>   smtFetchPolicy;
 +Param<std::string>   smtLSQPolicy;
 +Param<unsigned> smtLSQThreshold;
 +Param<std::string>   smtIQPolicy;
 +Param<unsigned> smtIQThreshold;
 +Param<std::string>   smtROBPolicy;
 +Param<unsigned> smtROBThreshold;
 +Param<std::string>   smtCommitPolicy;
 +
 +Param<unsigned> instShiftAmt;
 +
 +Param<bool> defer_registration;
 +
 +Param<bool> function_trace;
 +Param<Tick> function_trace_start;
 +
 +END_DECLARE_SIM_OBJECT_PARAMS(DerivAlphaFullCPU)
 +
 +BEGIN_INIT_SIM_OBJECT_PARAMS(DerivAlphaFullCPU)
 +
 +    INIT_PARAM(clock, "clock speed"),
 +    INIT_PARAM(numThreads, "number of HW thread contexts"),
 +    INIT_PARAM_DFLT(activity, "Initial activity count", 0),
 +
 +#if FULL_SYSTEM
 +    INIT_PARAM(system, "System object"),
 +    INIT_PARAM(cpu_id, "processor ID"),
 +    INIT_PARAM(itb, "Instruction translation buffer"),
 +    INIT_PARAM(dtb, "Data translation buffer"),
 +#else
 +    INIT_PARAM(workload, "Processes to run"),
 +//    INIT_PARAM(page_table, "Page table"),
 +#endif // FULL_SYSTEM
 +
 +    INIT_PARAM(mem, "Memory"),
 +
 +    INIT_PARAM_DFLT(checker, "Checker CPU", NULL),
 +
 +    INIT_PARAM_DFLT(max_insts_any_thread,
 +                    "Terminate when any thread reaches this inst count",
 +                    0),
 +    INIT_PARAM_DFLT(max_insts_all_threads,
 +                    "Terminate when all threads have reached"
 +                    "this inst count",
 +                    0),
 +    INIT_PARAM_DFLT(max_loads_any_thread,
 +                    "Terminate when any thread reaches this load count",
 +                    0),
 +    INIT_PARAM_DFLT(max_loads_all_threads,
 +                    "Terminate when all threads have reached this load"
 +                    "count",
 +                    0),
 +
 +    INIT_PARAM_DFLT(cachePorts, "Cache Ports", 200),
 +
 +    INIT_PARAM(decodeToFetchDelay, "Decode to fetch delay"),
 +    INIT_PARAM(renameToFetchDelay, "Rename to fetch delay"),
 +    INIT_PARAM(iewToFetchDelay, "Issue/Execute/Writeback to fetch"
 +               "delay"),
 +    INIT_PARAM(commitToFetchDelay, "Commit to fetch delay"),
 +    INIT_PARAM(fetchWidth, "Fetch width"),
 +    INIT_PARAM(renameToDecodeDelay, "Rename to decode delay"),
 +    INIT_PARAM(iewToDecodeDelay, "Issue/Execute/Writeback to decode"
 +               "delay"),
 +    INIT_PARAM(commitToDecodeDelay, "Commit to decode delay"),
 +    INIT_PARAM(fetchToDecodeDelay, "Fetch to decode delay"),
 +    INIT_PARAM(decodeWidth, "Decode width"),
 +
 +    INIT_PARAM(iewToRenameDelay, "Issue/Execute/Writeback to rename"
 +               "delay"),
 +    INIT_PARAM(commitToRenameDelay, "Commit to rename delay"),
 +    INIT_PARAM(decodeToRenameDelay, "Decode to rename delay"),
 +    INIT_PARAM(renameWidth, "Rename width"),
 +
 +    INIT_PARAM(commitToIEWDelay, "Commit to "
 +               "Issue/Execute/Writeback delay"),
 +    INIT_PARAM(renameToIEWDelay, "Rename to "
 +               "Issue/Execute/Writeback delay"),
 +    INIT_PARAM(issueToExecuteDelay, "Issue to execute delay (internal"
 +               "to the IEW stage)"),
 +    INIT_PARAM(issueWidth, "Issue width"),
 +    INIT_PARAM(executeWidth, "Execute width"),
 +    INIT_PARAM(executeIntWidth, "Integer execute width"),
 +    INIT_PARAM(executeFloatWidth, "Floating point execute width"),
 +    INIT_PARAM(executeBranchWidth, "Branch execute width"),
 +    INIT_PARAM(executeMemoryWidth, "Memory execute width"),
 +    INIT_PARAM_DFLT(fuPool, "Functional unit pool", NULL),
 +
 +    INIT_PARAM(iewToCommitDelay, "Issue/Execute/Writeback to commit "
 +               "delay"),
 +    INIT_PARAM(renameToROBDelay, "Rename to reorder buffer delay"),
 +    INIT_PARAM(commitWidth, "Commit width"),
 +    INIT_PARAM(squashWidth, "Squash width"),
 +    INIT_PARAM_DFLT(trapLatency, "Number of cycles before the trap is handled", 6),
 +    INIT_PARAM_DFLT(fetchTrapLatency, "Number of cycles before the fetch trap is handled", 12),
 +
++    INIT_PARAM(predType, "Type of branch predictor ('local', 'tournament')"),
 +    INIT_PARAM(localPredictorSize, "Size of local predictor"),
 +    INIT_PARAM(localCtrBits, "Bits per counter"),
 +    INIT_PARAM(localHistoryTableSize, "Size of local history table"),
 +    INIT_PARAM(localHistoryBits, "Bits for the local history"),
 +    INIT_PARAM(globalPredictorSize, "Size of global predictor"),
 +    INIT_PARAM(globalCtrBits, "Bits per counter"),
 +    INIT_PARAM(globalHistoryBits, "Bits of history"),
 +    INIT_PARAM(choicePredictorSize, "Size of choice predictor"),
 +    INIT_PARAM(choiceCtrBits, "Bits of choice counters"),
 +
 +    INIT_PARAM(BTBEntries, "Number of BTB entries"),
 +    INIT_PARAM(BTBTagSize, "Size of the BTB tags, in bits"),
 +
 +    INIT_PARAM(RASSize, "RAS size"),
 +
 +    INIT_PARAM(LQEntries, "Number of load queue entries"),
 +    INIT_PARAM(SQEntries, "Number of store queue entries"),
 +    INIT_PARAM(LFSTSize, "Last fetched store table size"),
 +    INIT_PARAM(SSITSize, "Store set ID table size"),
 +
 +    INIT_PARAM(numPhysIntRegs, "Number of physical integer registers"),
 +    INIT_PARAM(numPhysFloatRegs, "Number of physical floating point "
 +               "registers"),
 +    INIT_PARAM(numIQEntries, "Number of instruction queue entries"),
 +    INIT_PARAM(numROBEntries, "Number of reorder buffer entries"),
 +
 +    INIT_PARAM_DFLT(smtNumFetchingThreads, "SMT Number of Fetching Threads", 1),
 +    INIT_PARAM_DFLT(smtFetchPolicy, "SMT Fetch Policy", "SingleThread"),
 +    INIT_PARAM_DFLT(smtLSQPolicy,   "SMT LSQ Sharing Policy",    "Partitioned"),
 +    INIT_PARAM_DFLT(smtLSQThreshold,"SMT LSQ Threshold", 100),
 +    INIT_PARAM_DFLT(smtIQPolicy,    "SMT IQ Policy",    "Partitioned"),
 +    INIT_PARAM_DFLT(smtIQThreshold, "SMT IQ Threshold", 100),
 +    INIT_PARAM_DFLT(smtROBPolicy,   "SMT ROB Sharing Policy", "Partitioned"),
 +    INIT_PARAM_DFLT(smtROBThreshold,"SMT ROB Threshold", 100),
 +    INIT_PARAM_DFLT(smtCommitPolicy,"SMT Commit Fetch Policy", "RoundRobin"),
 +
 +    INIT_PARAM(instShiftAmt, "Number of bits to shift instructions by"),
 +    INIT_PARAM(defer_registration, "defer system registration (for sampling)"),
 +
 +    INIT_PARAM(function_trace, "Enable function trace"),
 +    INIT_PARAM(function_trace_start, "Cycle to start function trace")
 +
 +END_INIT_SIM_OBJECT_PARAMS(DerivAlphaFullCPU)
 +
 +CREATE_SIM_OBJECT(DerivAlphaFullCPU)
 +{
 +    DerivAlphaFullCPU *cpu;
 +
 +#if FULL_SYSTEM
 +    // Full-system only supports a single thread for the moment.
 +    int actual_num_threads = 1;
 +#else
 +    // In non-full-system mode, we infer the number of threads from
 +    // the workload if it's not explicitly specified.
 +    int actual_num_threads =
 +        numThreads.isValid() ? numThreads : workload.size();
 +
 +    if (workload.size() == 0) {
 +        fatal("Must specify at least one workload!");
 +    }
 +
 +#endif
 +
 +    AlphaSimpleParams *params = new AlphaSimpleParams;
 +
 +    params->clock = clock;
 +
 +    params->name = getInstanceName();
 +    params->numberOfThreads = actual_num_threads;
 +    params->activity = activity;
 +
 +#if FULL_SYSTEM
 +    params->system = system;
 +    params->cpu_id = cpu_id;
 +    params->itb = itb;
 +    params->dtb = dtb;
 +#else
 +    params->workload = workload;
 +//    params->pTable = page_table;
 +#endif // FULL_SYSTEM
 +
 +    params->mem = mem;
 +
 +    params->checker = checker;
 +
 +    params->max_insts_any_thread = max_insts_any_thread;
 +    params->max_insts_all_threads = max_insts_all_threads;
 +    params->max_loads_any_thread = max_loads_any_thread;
 +    params->max_loads_all_threads = max_loads_all_threads;
 +
 +    //
 +    // Caches
 +    //
 +    params->cachePorts = cachePorts;
 +
 +    params->decodeToFetchDelay = decodeToFetchDelay;
 +    params->renameToFetchDelay = renameToFetchDelay;
 +    params->iewToFetchDelay = iewToFetchDelay;
 +    params->commitToFetchDelay = commitToFetchDelay;
 +    params->fetchWidth = fetchWidth;
 +
 +    params->renameToDecodeDelay = renameToDecodeDelay;
 +    params->iewToDecodeDelay = iewToDecodeDelay;
 +    params->commitToDecodeDelay = commitToDecodeDelay;
 +    params->fetchToDecodeDelay = fetchToDecodeDelay;
 +    params->decodeWidth = decodeWidth;
 +
 +    params->iewToRenameDelay = iewToRenameDelay;
 +    params->commitToRenameDelay = commitToRenameDelay;
 +    params->decodeToRenameDelay = decodeToRenameDelay;
 +    params->renameWidth = renameWidth;
 +
 +    params->commitToIEWDelay = commitToIEWDelay;
 +    params->renameToIEWDelay = renameToIEWDelay;
 +    params->issueToExecuteDelay = issueToExecuteDelay;
 +    params->issueWidth = issueWidth;
 +    params->executeWidth = executeWidth;
 +    params->executeIntWidth = executeIntWidth;
 +    params->executeFloatWidth = executeFloatWidth;
 +    params->executeBranchWidth = executeBranchWidth;
 +    params->executeMemoryWidth = executeMemoryWidth;
 +    params->fuPool = fuPool;
 +
 +    params->iewToCommitDelay = iewToCommitDelay;
 +    params->renameToROBDelay = renameToROBDelay;
 +    params->commitWidth = commitWidth;
 +    params->squashWidth = squashWidth;
 +    params->trapLatency = trapLatency;
 +    params->fetchTrapLatency = fetchTrapLatency;
 +
++    params->predType = predType;
 +    params->localPredictorSize = localPredictorSize;
 +    params->localCtrBits = localCtrBits;
 +    params->localHistoryTableSize = localHistoryTableSize;
 +    params->localHistoryBits = localHistoryBits;
 +    params->globalPredictorSize = globalPredictorSize;
 +    params->globalCtrBits = globalCtrBits;
 +    params->globalHistoryBits = globalHistoryBits;
 +    params->choicePredictorSize = choicePredictorSize;
 +    params->choiceCtrBits = choiceCtrBits;
 +
 +    params->BTBEntries = BTBEntries;
 +    params->BTBTagSize = BTBTagSize;
 +
 +    params->RASSize = RASSize;
 +
 +    params->LQEntries = LQEntries;
 +    params->SQEntries = SQEntries;
 +
 +    params->SSITSize = SSITSize;
 +    params->LFSTSize = LFSTSize;
 +
 +    params->numPhysIntRegs = numPhysIntRegs;
 +    params->numPhysFloatRegs = numPhysFloatRegs;
 +    params->numIQEntries = numIQEntries;
 +    params->numROBEntries = numROBEntries;
 +
 +    params->smtNumFetchingThreads = smtNumFetchingThreads;
 +    params->smtFetchPolicy = smtFetchPolicy;
 +    params->smtIQPolicy    = smtIQPolicy;
 +    params->smtLSQPolicy    = smtLSQPolicy;
 +    params->smtLSQThreshold = smtLSQThreshold;
 +    params->smtROBPolicy   = smtROBPolicy;
 +    params->smtROBThreshold = smtROBThreshold;
 +    params->smtCommitPolicy = smtCommitPolicy;
 +
 +    params->instShiftAmt = 2;
 +
 +    params->deferRegistration = defer_registration;
 +
 +    params->functionTrace = function_trace;
 +    params->functionTraceStart = function_trace_start;
 +
 +    cpu = new DerivAlphaFullCPU(params);
 +
 +    return cpu;
 +}
 +
 +REGISTER_SIM_OBJECT("DerivAlphaFullCPU", DerivAlphaFullCPU)
 +
index 6893f8c6425f35a1a75c7cec32f3afd0fc95e53e,0000000000000000000000000000000000000000..ad4401f7ed22d121894d27f031cac3a7abe3f10f
mode 100644,000000..100644
--- /dev/null
@@@ -1,809 -1,0 +1,815 @@@
-         this->thread[i]->numInst = 0;
 +/*
 + * Copyright (c) 2004-2006 The Regents of The University of Michigan
 + * 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: Kevin Lim
 + */
 +
 +#include "arch/alpha/faults.hh"
 +#include "base/cprintf.hh"
 +#include "base/statistics.hh"
 +#include "base/timebuf.hh"
 +#include "cpu/checker/exec_context.hh"
 +#include "sim/sim_events.hh"
 +#include "sim/stats.hh"
 +
 +#include "cpu/o3/alpha_cpu.hh"
 +#include "cpu/o3/alpha_params.hh"
 +#include "cpu/o3/comm.hh"
 +#include "cpu/o3/thread_state.hh"
 +
 +#if FULL_SYSTEM
 +#include "arch/alpha/osfpal.hh"
 +#include "arch/isa_traits.hh"
 +#include "cpu/quiesce_event.hh"
 +#include "kern/kernel_stats.hh"
 +#endif
 +
 +using namespace TheISA;
 +
 +template <class Impl>
 +AlphaFullCPU<Impl>::AlphaFullCPU(Params *params)
 +#if FULL_SYSTEM
 +    : FullO3CPU<Impl>(params), itb(params->itb), dtb(params->dtb)
 +#else
 +    : FullO3CPU<Impl>(params)
 +#endif
 +{
 +    DPRINTF(FullCPU, "AlphaFullCPU: Creating AlphaFullCPU object.\n");
 +
++    // Setup any thread state.
 +    this->thread.resize(this->numThreads);
 +
 +    for (int i = 0; i < this->numThreads; ++i) {
 +#if FULL_SYSTEM
++        // SMT is not supported in FS mode yet.
 +        assert(this->numThreads == 1);
 +        this->thread[i] = new Thread(this, 0, params->mem);
 +        this->thread[i]->setStatus(ExecContext::Suspended);
 +#else
 +        if (i < params->workload.size()) {
 +            DPRINTF(FullCPU, "FullCPU: Workload[%i] process is %#x",
 +                    i, this->thread[i]);
 +            this->thread[i] = new Thread(this, i, params->workload[i], i);
 +
 +            this->thread[i]->setStatus(ExecContext::Suspended);
 +            //usedTids[i] = true;
 +            //threadMap[i] = i;
 +        } else {
 +            //Allocate Empty execution context so M5 can use later
 +            //when scheduling threads to CPU
 +            Process* dummy_proc = NULL;
 +
 +            this->thread[i] = new Thread(this, i, dummy_proc, i);
 +            //usedTids[i] = false;
 +        }
 +#endif // !FULL_SYSTEM
 +
-         AlphaXC *alpha_xc_proxy = new AlphaXC;
 +        ExecContext *xc_proxy;
 +
-             xc_proxy = new CheckerExecContext<AlphaXC>(alpha_xc_proxy, this->checker);
++        // Setup the XC that will serve as the interface to the threads/CPU.
++        AlphaXC *alpha_xc = new AlphaXC;
 +
++        // If we're using a checker, then the XC should be the
++        // CheckerExecContext.
 +        if (params->checker) {
-             xc_proxy = alpha_xc_proxy;
++            xc_proxy = new CheckerExecContext<AlphaXC>(
++                alpha_xc, this->checker);
 +        } else {
-         alpha_xc_proxy->cpu = this;
-         alpha_xc_proxy->thread = this->thread[i];
++            xc_proxy = alpha_xc;
 +        }
 +
-     DPRINTF(Fault, "Reading int register through the XC!\n");
++        alpha_xc->cpu = this;
++        alpha_xc->thread = this->thread[i];
 +
 +#if FULL_SYSTEM
++        // Setup quiesce event.
 +        this->thread[i]->quiesceEvent =
 +            new EndQuiesceEvent(xc_proxy);
 +        this->thread[i]->lastActivate = 0;
 +        this->thread[i]->lastSuspend = 0;
 +#endif
++        // Give the thread the XC.
 +        this->thread[i]->xcProxy = xc_proxy;
 +
++        // Add the XC to the CPU's list of XC's.
 +        this->execContexts.push_back(xc_proxy);
 +    }
 +
 +
 +    for (int i=0; i < this->numThreads; i++) {
 +        this->thread[i]->funcExeInst = 0;
 +    }
 +
 +    // Sets CPU pointers. These must be set at this level because the CPU
 +    // pointers are defined to be the highest level of CPU class.
 +    this->fetch.setCPU(this);
 +    this->decode.setCPU(this);
 +    this->rename.setCPU(this);
 +    this->iew.setCPU(this);
 +    this->commit.setCPU(this);
 +
 +    this->rob.setCPU(this);
 +    this->regFile.setCPU(this);
 +
 +    lockAddr = 0;
 +    lockFlag = false;
 +}
 +
 +template <class Impl>
 +void
 +AlphaFullCPU<Impl>::regStats()
 +{
 +    // Register stats for everything that has stats.
 +    this->fullCPURegStats();
 +    this->fetch.regStats();
 +    this->decode.regStats();
 +    this->rename.regStats();
 +    this->iew.regStats();
 +    this->commit.regStats();
 +}
 +
 +#if FULL_SYSTEM
 +template <class Impl>
 +void
 +AlphaFullCPU<Impl>::AlphaXC::dumpFuncProfile()
 +{
 +    // Currently not supported
 +}
 +#endif
 +
 +template <class Impl>
 +void
 +AlphaFullCPU<Impl>::AlphaXC::takeOverFrom(ExecContext *old_context)
 +{
 +    // some things should already be set up
 +    assert(getMemPort() == old_context->getMemPort());
 +#if FULL_SYSTEM
 +    assert(getSystemPtr() == old_context->getSystemPtr());
 +#else
 +    assert(getProcessPtr() == old_context->getProcessPtr());
 +#endif
 +
 +    // copy over functional state
 +    setStatus(old_context->status());
 +    copyArchRegs(old_context);
 +    setCpuId(old_context->readCpuId());
++
 +#if !FULL_SYSTEM
 +    thread->funcExeInst = old_context->readFuncExeInst();
 +#else
 +    EndQuiesceEvent *other_quiesce = old_context->getQuiesceEvent();
 +    if (other_quiesce) {
 +        // Point the quiesce event's XC at this XC so that it wakes up
 +        // the proper CPU.
 +        other_quiesce->xc = this;
 +    }
 +    if (thread->quiesceEvent) {
 +        thread->quiesceEvent->xc = this;
 +    }
 +
 +    // Transfer kernel stats from one CPU to the other.
 +    thread->kernelStats = old_context->getKernelStats();
 +//    storeCondFailures = 0;
 +    cpu->lockFlag = false;
 +#endif
 +
 +    old_context->setStatus(ExecContext::Unallocated);
 +
 +    thread->inSyscall = false;
 +    thread->trapPending = false;
 +}
 +
 +template <class Impl>
 +void
 +AlphaFullCPU<Impl>::AlphaXC::activate(int delay)
 +{
 +    DPRINTF(FullCPU, "Calling activate on AlphaXC\n");
 +
 +    if (thread->status() == ExecContext::Active)
 +        return;
 +
 +#if FULL_SYSTEM
 +    thread->lastActivate = curTick;
 +#endif
 +
 +    if (thread->status() == ExecContext::Unallocated) {
 +        cpu->activateWhenReady(thread->tid);
 +        return;
 +    }
 +
 +    thread->setStatus(ExecContext::Active);
 +
 +    // status() == Suspended
 +    cpu->activateContext(thread->tid, delay);
 +}
 +
 +template <class Impl>
 +void
 +AlphaFullCPU<Impl>::AlphaXC::suspend()
 +{
 +    DPRINTF(FullCPU, "Calling suspend on AlphaXC\n");
 +
 +    if (thread->status() == ExecContext::Suspended)
 +        return;
 +
 +#if FULL_SYSTEM
 +    thread->lastActivate = curTick;
 +    thread->lastSuspend = curTick;
 +#endif
 +/*
 +#if FULL_SYSTEM
 +    // Don't change the status from active if there are pending interrupts
 +    if (cpu->check_interrupts()) {
 +        assert(status() == ExecContext::Active);
 +        return;
 +    }
 +#endif
 +*/
 +    thread->setStatus(ExecContext::Suspended);
 +    cpu->suspendContext(thread->tid);
 +}
 +
 +template <class Impl>
 +void
 +AlphaFullCPU<Impl>::AlphaXC::deallocate()
 +{
 +    DPRINTF(FullCPU, "Calling deallocate on AlphaXC\n");
 +
 +    if (thread->status() == ExecContext::Unallocated)
 +        return;
 +
 +    thread->setStatus(ExecContext::Unallocated);
 +    cpu->deallocateContext(thread->tid);
 +}
 +
 +template <class Impl>
 +void
 +AlphaFullCPU<Impl>::AlphaXC::halt()
 +{
 +    DPRINTF(FullCPU, "Calling halt on AlphaXC\n");
 +
 +    if (thread->status() == ExecContext::Halted)
 +        return;
 +
 +    thread->setStatus(ExecContext::Halted);
 +    cpu->haltContext(thread->tid);
 +}
 +
 +template <class Impl>
 +void
 +AlphaFullCPU<Impl>::AlphaXC::regStats(const std::string &name)
 +{
 +#if FULL_SYSTEM
 +    thread->kernelStats = new Kernel::Statistics(cpu->system);
 +    thread->kernelStats->regStats(name + ".kern");
 +#endif
 +}
 +
 +template <class Impl>
 +void
 +AlphaFullCPU<Impl>::AlphaXC::serialize(std::ostream &os)
 +{
 +#if FULL_SYSTEM
 +    if (thread->kernelStats)
 +        thread->kernelStats->serialize(os);
 +#endif
 +
 +}
 +
 +template <class Impl>
 +void
 +AlphaFullCPU<Impl>::AlphaXC::unserialize(Checkpoint *cp, const std::string &section)
 +{
 +#if FULL_SYSTEM
 +    if (thread->kernelStats)
 +        thread->kernelStats->unserialize(cp, section);
 +#endif
 +
 +}
 +
 +#if FULL_SYSTEM
 +template <class Impl>
 +EndQuiesceEvent *
 +AlphaFullCPU<Impl>::AlphaXC::getQuiesceEvent()
 +{
 +    return thread->quiesceEvent;
 +}
 +
 +template <class Impl>
 +Tick
 +AlphaFullCPU<Impl>::AlphaXC::readLastActivate()
 +{
 +    return thread->lastActivate;
 +}
 +
 +template <class Impl>
 +Tick
 +AlphaFullCPU<Impl>::AlphaXC::readLastSuspend()
 +{
 +    return thread->lastSuspend;
 +}
 +
 +template <class Impl>
 +void
 +AlphaFullCPU<Impl>::AlphaXC::profileClear()
 +{}
 +
 +template <class Impl>
 +void
 +AlphaFullCPU<Impl>::AlphaXC::profileSample()
 +{}
 +#endif
 +
 +template <class Impl>
 +TheISA::MachInst
 +AlphaFullCPU<Impl>::AlphaXC:: getInst()
 +{
 +    return thread->inst;
 +}
 +
 +template <class Impl>
 +void
 +AlphaFullCPU<Impl>::AlphaXC::copyArchRegs(ExecContext *xc)
 +{
 +    // This function will mess things up unless the ROB is empty and
 +    // there are no instructions in the pipeline.
 +    unsigned tid = thread->tid;
 +    PhysRegIndex renamed_reg;
 +
 +    // First loop through the integer registers.
 +    for (int i = 0; i < AlphaISA::NumIntRegs; ++i) {
 +        renamed_reg = cpu->renameMap[tid].lookup(i);
 +
 +        DPRINTF(FullCPU, "FullCPU: Copying over register %i, had data %lli, "
 +                "now has data %lli.\n",
 +                renamed_reg, cpu->readIntReg(renamed_reg),
 +                xc->readIntReg(i));
 +
 +        cpu->setIntReg(renamed_reg, xc->readIntReg(i));
 +    }
 +
 +    // Then loop through the floating point registers.
 +    for (int i = 0; i < AlphaISA::NumFloatRegs; ++i) {
 +        renamed_reg = cpu->renameMap[tid].lookup(i + AlphaISA::FP_Base_DepTag);
 +        cpu->setFloatRegBits(renamed_reg,
 +                             xc->readFloatRegBits(i));
 +    }
 +
 +    // Copy the misc regs.
 +    copyMiscRegs(xc, this);
 +
 +    // Then finally set the PC and the next PC.
 +    cpu->setPC(xc->readPC(), tid);
 +    cpu->setNextPC(xc->readNextPC(), tid);
 +#if !FULL_SYSTEM
 +    this->thread->funcExeInst = xc->readFuncExeInst();
 +#endif
 +}
 +
 +template <class Impl>
 +void
 +AlphaFullCPU<Impl>::AlphaXC::clearArchRegs()
 +{}
 +
 +template <class Impl>
 +uint64_t
 +AlphaFullCPU<Impl>::AlphaXC::readIntReg(int reg_idx)
 +{
-     DPRINTF(Fault, "Reading float register through the XC!\n");
 +    return cpu->readArchIntReg(reg_idx, thread->tid);
 +}
 +
 +template <class Impl>
 +FloatReg
 +AlphaFullCPU<Impl>::AlphaXC::readFloatReg(int reg_idx, int width)
 +{
-     DPRINTF(Fault, "Reading float register through the XC!\n");
 +    switch(width) {
 +      case 32:
 +        return cpu->readArchFloatRegSingle(reg_idx, thread->tid);
 +      case 64:
 +        return cpu->readArchFloatRegDouble(reg_idx, thread->tid);
 +      default:
 +        panic("Unsupported width!");
 +        return 0;
 +    }
 +}
 +
 +template <class Impl>
 +FloatReg
 +AlphaFullCPU<Impl>::AlphaXC::readFloatReg(int reg_idx)
 +{
-     DPRINTF(Fault, "Reading floatint register through the XC!\n");
 +    return cpu->readArchFloatRegSingle(reg_idx, thread->tid);
 +}
 +
 +template <class Impl>
 +FloatRegBits
 +AlphaFullCPU<Impl>::AlphaXC::readFloatRegBits(int reg_idx, int width)
 +{
 +    DPRINTF(Fault, "Reading floatint register through the XC!\n");
 +    return cpu->readArchFloatRegInt(reg_idx, thread->tid);
 +}
 +
 +template <class Impl>
 +FloatRegBits
 +AlphaFullCPU<Impl>::AlphaXC::readFloatRegBits(int reg_idx)
 +{
-     DPRINTF(Fault, "Setting int register through the XC!\n");
 +    return cpu->readArchFloatRegInt(reg_idx, thread->tid);
 +}
 +
 +template <class Impl>
 +void
 +AlphaFullCPU<Impl>::AlphaXC::setIntReg(int reg_idx, uint64_t val)
 +{
-     DPRINTF(Fault, "Setting float register through the XC!\n");
 +    cpu->setArchIntReg(reg_idx, val, thread->tid);
 +
++    // Squash if we're not already in a state update mode.
 +    if (!thread->trapPending && !thread->inSyscall) {
 +        cpu->squashFromXC(thread->tid);
 +    }
 +}
 +
 +template <class Impl>
 +void
 +AlphaFullCPU<Impl>::AlphaXC::setFloatReg(int reg_idx, FloatReg val, int width)
 +{
-     DPRINTF(Fault, "Setting float register through the XC!\n");
 +    switch(width) {
 +      case 32:
 +        cpu->setArchFloatRegSingle(reg_idx, val, thread->tid);
 +        break;
 +      case 64:
 +        cpu->setArchFloatRegDouble(reg_idx, val, thread->tid);
 +        break;
 +    }
 +
++    // Squash if we're not already in a state update mode.
 +    if (!thread->trapPending && !thread->inSyscall) {
 +        cpu->squashFromXC(thread->tid);
 +    }
 +}
 +
 +template <class Impl>
 +void
 +AlphaFullCPU<Impl>::AlphaXC::setFloatReg(int reg_idx, FloatReg val)
 +{
-     DPRINTF(Fault, "Setting floatint register through the XC!\n");
 +    cpu->setArchFloatRegSingle(reg_idx, val, thread->tid);
 +
 +    if (!thread->trapPending && !thread->inSyscall) {
 +        cpu->squashFromXC(thread->tid);
 +    }
 +}
 +
 +template <class Impl>
 +void
 +AlphaFullCPU<Impl>::AlphaXC::setFloatRegBits(int reg_idx, FloatRegBits val,
 +                                             int width)
 +{
 +    DPRINTF(Fault, "Setting floatint register through the XC!\n");
 +    cpu->setArchFloatRegInt(reg_idx, val, thread->tid);
 +
++    // Squash if we're not already in a state update mode.
 +    if (!thread->trapPending && !thread->inSyscall) {
 +        cpu->squashFromXC(thread->tid);
 +    }
 +}
 +
 +template <class Impl>
 +void
 +AlphaFullCPU<Impl>::AlphaXC::setFloatRegBits(int reg_idx, FloatRegBits val)
 +{
-     DPRINTF(Fault, "Setting misc register through the XC!\n");
 +    cpu->setArchFloatRegInt(reg_idx, val, thread->tid);
 +
++    // Squash if we're not already in a state update mode.
 +    if (!thread->trapPending && !thread->inSyscall) {
 +        cpu->squashFromXC(thread->tid);
 +    }
 +}
 +
 +template <class Impl>
 +void
 +AlphaFullCPU<Impl>::AlphaXC::setPC(uint64_t val)
 +{
 +    cpu->setPC(val, thread->tid);
 +
++    // Squash if we're not already in a state update mode.
 +    if (!thread->trapPending && !thread->inSyscall) {
 +        cpu->squashFromXC(thread->tid);
 +    }
 +}
 +
 +template <class Impl>
 +void
 +AlphaFullCPU<Impl>::AlphaXC::setNextPC(uint64_t val)
 +{
 +    cpu->setNextPC(val, thread->tid);
 +
++    // Squash if we're not already in a state update mode.
 +    if (!thread->trapPending && !thread->inSyscall) {
 +        cpu->squashFromXC(thread->tid);
 +    }
 +}
 +
 +template <class Impl>
 +Fault
 +AlphaFullCPU<Impl>::AlphaXC::setMiscReg(int misc_reg, const MiscReg &val)
 +{
- AlphaFullCPU<Impl>::AlphaXC::setMiscRegWithEffect(int misc_reg, const MiscReg &val)
 +    Fault ret_fault = cpu->setMiscReg(misc_reg, val, thread->tid);
 +
++    // Squash if we're not already in a state update mode.
 +    if (!thread->trapPending && !thread->inSyscall) {
 +        cpu->squashFromXC(thread->tid);
 +    }
 +
 +    return ret_fault;
 +}
 +
 +template <class Impl>
 +Fault
-     DPRINTF(Fault, "Setting misc register through the XC!\n");
++AlphaFullCPU<Impl>::AlphaXC::setMiscRegWithEffect(int misc_reg,
++                                                  const MiscReg &val)
 +{
- //    xcProxies[0]->activate();
 +    Fault ret_fault = cpu->setMiscRegWithEffect(misc_reg, val, thread->tid);
 +
++    // Squash if we're not already in a state update mode.
 +    if (!thread->trapPending && !thread->inSyscall) {
 +        cpu->squashFromXC(thread->tid);
 +    }
 +
 +    return ret_fault;
 +}
 +
 +#if !FULL_SYSTEM
 +
 +template <class Impl>
 +TheISA::IntReg
 +AlphaFullCPU<Impl>::AlphaXC::getSyscallArg(int i)
 +{
 +    return cpu->getSyscallArg(i, thread->tid);
 +}
 +
 +template <class Impl>
 +void
 +AlphaFullCPU<Impl>::AlphaXC::setSyscallArg(int i, IntReg val)
 +{
 +    cpu->setSyscallArg(i, val, thread->tid);
 +}
 +
 +template <class Impl>
 +void
 +AlphaFullCPU<Impl>::AlphaXC::setSyscallReturn(SyscallReturn return_value)
 +{
 +    cpu->setSyscallReturn(return_value, thread->tid);
 +}
 +
 +#endif // FULL_SYSTEM
 +
 +template <class Impl>
 +MiscReg
 +AlphaFullCPU<Impl>::readMiscReg(int misc_reg, unsigned tid)
 +{
 +    return this->regFile.readMiscReg(misc_reg, tid);
 +}
 +
 +template <class Impl>
 +MiscReg
 +AlphaFullCPU<Impl>::readMiscRegWithEffect(int misc_reg, Fault &fault,
 +                                          unsigned tid)
 +{
 +    return this->regFile.readMiscRegWithEffect(misc_reg, fault, tid);
 +}
 +
 +template <class Impl>
 +Fault
 +AlphaFullCPU<Impl>::setMiscReg(int misc_reg, const MiscReg &val, unsigned tid)
 +{
 +    return this->regFile.setMiscReg(misc_reg, val, tid);
 +}
 +
 +template <class Impl>
 +Fault
 +AlphaFullCPU<Impl>::setMiscRegWithEffect(int misc_reg, const MiscReg &val,
 +                                         unsigned tid)
 +{
 +    return this->regFile.setMiscRegWithEffect(misc_reg, val, tid);
 +}
 +
 +template <class Impl>
 +void
 +AlphaFullCPU<Impl>::squashFromXC(unsigned tid)
 +{
 +    this->thread[tid]->inSyscall = true;
 +    this->commit.generateXCEvent(tid);
 +}
 +
 +#if FULL_SYSTEM
 +
 +template <class Impl>
 +void
 +AlphaFullCPU<Impl>::post_interrupt(int int_num, int index)
 +{
 +    BaseCPU::post_interrupt(int_num, index);
 +
 +    if (this->thread[0]->status() == ExecContext::Suspended) {
 +        DPRINTF(IPI,"Suspended Processor awoke\n");
 +        this->execContexts[0]->activate();
 +    }
 +}
 +
 +template <class Impl>
 +int
 +AlphaFullCPU<Impl>::readIntrFlag()
 +{
 +    return this->regFile.readIntrFlag();
 +}
 +
 +template <class Impl>
 +void
 +AlphaFullCPU<Impl>::setIntrFlag(int val)
 +{
 +    this->regFile.setIntrFlag(val);
 +}
 +
 +template <class Impl>
 +Fault
 +AlphaFullCPU<Impl>::hwrei(unsigned tid)
 +{
 +    // Need to clear the lock flag upon returning from an interrupt.
 +    this->lockFlag = false;
 +
 +    this->thread[tid]->kernelStats->hwrei();
 +
 +    this->checkInterrupts = true;
 +
 +    // FIXME: XXX check for interrupts? XXX
 +    return NoFault;
 +}
 +
 +template <class Impl>
 +bool
 +AlphaFullCPU<Impl>::simPalCheck(int palFunc, unsigned tid)
 +{
 +    if (this->thread[tid]->kernelStats)
 +        this->thread[tid]->kernelStats->callpal(palFunc,
 +                                                this->execContexts[tid]);
 +
 +    switch (palFunc) {
 +      case PAL::halt:
 +        halt();
 +        if (--System::numSystemsRunning == 0)
 +            new SimExitEvent("all cpus halted");
 +        break;
 +
 +      case PAL::bpt:
 +      case PAL::bugchk:
 +        if (this->system->breakpoint())
 +            return false;
 +        break;
 +    }
 +
 +    return true;
 +}
 +
 +template <class Impl>
 +void
 +AlphaFullCPU<Impl>::trap(Fault fault, unsigned tid)
 +{
++    // Pass the thread's XC into the invoke method.
 +    fault->invoke(this->execContexts[tid]);
 +}
 +
 +template <class Impl>
 +void
 +AlphaFullCPU<Impl>::processInterrupts()
 +{
 +    // Check for interrupts here.  For now can copy the code that
 +    // exists within isa_fullsys_traits.hh.  Also assume that thread 0
 +    // is the one that handles the interrupts.
 +    // @todo: Possibly consolidate the interrupt checking code.
 +    // @todo: Allow other threads to handle interrupts.
 +
 +    // Check if there are any outstanding interrupts
 +    //Handle the interrupts
 +    int ipl = 0;
 +    int summary = 0;
 +
 +    this->checkInterrupts = false;
 +
 +    if (this->readMiscReg(IPR_ASTRR, 0))
 +        panic("asynchronous traps not implemented\n");
 +
 +    if (this->readMiscReg(IPR_SIRR, 0)) {
 +        for (int i = INTLEVEL_SOFTWARE_MIN;
 +             i < INTLEVEL_SOFTWARE_MAX; i++) {
 +            if (this->readMiscReg(IPR_SIRR, 0) & (ULL(1) << i)) {
 +                // See table 4-19 of the 21164 hardware reference
 +                ipl = (i - INTLEVEL_SOFTWARE_MIN) + 1;
 +                summary |= (ULL(1) << i);
 +            }
 +        }
 +    }
 +
 +    uint64_t interrupts = this->intr_status();
 +
 +    if (interrupts) {
 +        for (int i = INTLEVEL_EXTERNAL_MIN;
 +             i < INTLEVEL_EXTERNAL_MAX; i++) {
 +            if (interrupts & (ULL(1) << i)) {
 +                // See table 4-19 of the 21164 hardware reference
 +                ipl = i;
 +                summary |= (ULL(1) << i);
 +            }
 +        }
 +    }
 +
 +    if (ipl && ipl > this->readMiscReg(IPR_IPLR, 0)) {
 +        this->setMiscReg(IPR_ISR, summary, 0);
 +        this->setMiscReg(IPR_INTID, ipl, 0);
++        // Checker needs to know these two registers were updated.
 +        if (this->checker) {
 +            this->checker->cpuXCBase()->setMiscReg(IPR_ISR, summary);
 +            this->checker->cpuXCBase()->setMiscReg(IPR_INTID, ipl);
 +        }
 +        this->trap(Fault(new InterruptFault), 0);
 +        DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n",
 +                this->readMiscReg(IPR_IPLR, 0), ipl, summary);
 +    }
 +}
 +
 +#endif // FULL_SYSTEM
 +
 +#if !FULL_SYSTEM
 +
 +template <class Impl>
 +void
 +AlphaFullCPU<Impl>::syscall(int64_t callnum, int tid)
 +{
 +    DPRINTF(FullCPU, "AlphaFullCPU: [tid:%i] Executing syscall().\n\n", tid);
 +
 +    DPRINTF(Activity,"Activity: syscall() called.\n");
 +
 +    // Temporarily increase this by one to account for the syscall
 +    // instruction.
 +    ++(this->thread[tid]->funcExeInst);
 +
 +    // Execute the actual syscall.
 +    this->thread[tid]->syscall(callnum);
 +
 +    // Decrease funcExeInst by one as the normal commit will handle
 +    // incrementing it.
 +    --(this->thread[tid]->funcExeInst);
 +}
 +
 +template <class Impl>
 +TheISA::IntReg
 +AlphaFullCPU<Impl>::getSyscallArg(int i, int tid)
 +{
 +    return this->readArchIntReg(AlphaISA::ArgumentReg0 + i, tid);
 +}
 +
 +template <class Impl>
 +void
 +AlphaFullCPU<Impl>::setSyscallArg(int i, IntReg val, int tid)
 +{
 +    this->setArchIntReg(AlphaISA::ArgumentReg0 + i, val, tid);
 +}
 +
 +template <class Impl>
 +void
 +AlphaFullCPU<Impl>::setSyscallReturn(SyscallReturn return_value, int tid)
 +{
 +    // check for error condition.  Alpha syscall convention is to
 +    // indicate success/failure in reg a3 (r19) and put the
 +    // return value itself in the standard return value reg (v0).
 +    if (return_value.successful()) {
 +        // no error
 +        this->setArchIntReg(SyscallSuccessReg, 0, tid);
 +        this->setArchIntReg(ReturnValueReg, return_value.value(), tid);
 +    } else {
 +        // got an error, return details
 +        this->setArchIntReg(SyscallSuccessReg, (IntReg) -1, tid);
 +        this->setArchIntReg(ReturnValueReg, -return_value.value(), tid);
 +    }
 +}
 +#endif
index af28588021acdaaa86c28460f3c8cac058565a6d,0000000000000000000000000000000000000000..143ffe7e4f3d28b5e651146d58f91d1077a07b14
mode 100644,000000..100644
--- /dev/null
@@@ -1,287 -1,0 +1,295 @@@
 +/*
 + * Copyright (c) 2004-2006 The Regents of The University of Michigan
 + * 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: Kevin Lim
 + */
 +
 +#ifndef __CPU_O3_ALPHA_DYN_INST_HH__
 +#define __CPU_O3_ALPHA_DYN_INST_HH__
 +
 +#include "arch/isa_traits.hh"
 +#include "cpu/base_dyn_inst.hh"
 +#include "cpu/inst_seq.hh"
 +#include "cpu/o3/alpha_cpu.hh"
 +#include "cpu/o3/alpha_impl.hh"
 +
 +class Packet;
 +
 +/**
 + * Mostly implementation & ISA specific AlphaDynInst. As with most
 + * other classes in the new CPU model, it is templated on the Impl to
 + * allow for passing in of all types, such as the CPU type and the ISA
 + * type. The AlphaDynInst serves as the primary interface to the CPU
 + * for instructions that are executing.
 + */
 +template <class Impl>
 +class AlphaDynInst : public BaseDynInst<Impl>
 +{
 +  public:
 +    /** Typedef for the CPU. */
 +    typedef typename Impl::FullCPU FullCPU;
 +
 +    /** Binary machine instruction type. */
 +    typedef TheISA::MachInst MachInst;
 +    /** Extended machine instruction type. */
 +    typedef TheISA::ExtMachInst ExtMachInst;
 +    /** Logical register index type. */
 +    typedef TheISA::RegIndex RegIndex;
 +    /** Integer register index type. */
 +    typedef TheISA::IntReg   IntReg;
 +    typedef TheISA::FloatReg FloatReg;
 +    typedef TheISA::FloatRegBits FloatRegBits;
 +    /** Misc register index type. */
 +    typedef TheISA::MiscReg  MiscReg;
 +
 +    enum {
 +        MaxInstSrcRegs = TheISA::MaxInstSrcRegs,      //< Max source regs
 +        MaxInstDestRegs = TheISA::MaxInstDestRegs,    //< Max dest regs
 +    };
 +
 +  public:
 +    /** BaseDynInst constructor given a binary instruction. */
 +    AlphaDynInst(ExtMachInst inst, Addr PC, Addr Pred_PC, InstSeqNum seq_num,
 +                 FullCPU *cpu);
 +
 +    /** BaseDynInst constructor given a static inst pointer. */
 +    AlphaDynInst(StaticInstPtr &_staticInst);
 +
 +    /** Executes the instruction.*/
 +    Fault execute();
 +
 +    /** Initiates the access.  Only valid for memory operations. */
 +    Fault initiateAcc();
 +
 +    /** Completes the access.  Only valid for memory operations. */
 +    Fault completeAcc(Packet *pkt);
 +
 +  private:
 +    /** Initializes variables. */
 +    void initVars();
 +
 +  public:
++    /** Reads a miscellaneous register. */
 +    MiscReg readMiscReg(int misc_reg)
 +    {
 +        return this->cpu->readMiscReg(misc_reg, this->threadNumber);
 +    }
 +
++    /** Reads a misc. register, including any side-effects the read
++     * might have as defined by the architecture.
++     */
 +    MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault)
 +    {
 +        return this->cpu->readMiscRegWithEffect(misc_reg, fault,
 +                                                this->threadNumber);
 +    }
 +
++    /** Sets a misc. register. */
 +    Fault setMiscReg(int misc_reg, const MiscReg &val)
 +    {
 +        this->instResult.integer = val;
 +        return this->cpu->setMiscReg(misc_reg, val, this->threadNumber);
 +    }
 +
++    /** Sets a misc. register, including any side-effects the write
++     * might have as defined by the architecture.
++     */
 +    Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val)
 +    {
 +        return this->cpu->setMiscRegWithEffect(misc_reg, val,
 +                                               this->threadNumber);
 +    }
 +
 +#if FULL_SYSTEM
 +    /** Calls hardware return from error interrupt. */
 +    Fault hwrei();
 +    /** Reads interrupt flag. */
 +    int readIntrFlag();
 +    /** Sets interrupt flag. */
 +    void setIntrFlag(int val);
 +    /** Checks if system is in PAL mode. */
 +    bool inPalMode();
 +    /** Traps to handle specified fault. */
 +    void trap(Fault fault);
 +    bool simPalCheck(int palFunc);
 +#else
 +    /** Calls a syscall. */
 +    void syscall(int64_t callnum);
 +#endif
 +
 +  private:
 +    /** Physical register index of the destination registers of this
 +     *  instruction.
 +     */
 +    PhysRegIndex _destRegIdx[MaxInstDestRegs];
 +
 +    /** Physical register index of the source registers of this
 +     *  instruction.
 +     */
 +    PhysRegIndex _srcRegIdx[MaxInstSrcRegs];
 +
 +    /** Physical register index of the previous producers of the
 +     *  architected destinations.
 +     */
 +    PhysRegIndex _prevDestRegIdx[MaxInstDestRegs];
 +
 +  public:
 +
 +    // The register accessor methods provide the index of the
 +    // instruction's operand (e.g., 0 or 1), not the architectural
 +    // register index, to simplify the implementation of register
 +    // renaming.  We find the architectural register index by indexing
 +    // into the instruction's own operand index table.  Note that a
 +    // raw pointer to the StaticInst is provided instead of a
 +    // ref-counted StaticInstPtr to redice overhead.  This is fine as
 +    // long as these methods don't copy the pointer into any long-term
 +    // storage (which is pretty hard to imagine they would have reason
 +    // to do).
 +
 +    uint64_t readIntReg(const StaticInst *si, int idx)
 +    {
 +        return this->cpu->readIntReg(_srcRegIdx[idx]);
 +    }
 +
 +    FloatReg readFloatReg(const StaticInst *si, int idx, int width)
 +    {
 +        return this->cpu->readFloatReg(_srcRegIdx[idx], width);
 +    }
 +
 +    FloatReg readFloatReg(const StaticInst *si, int idx)
 +    {
 +        return this->cpu->readFloatReg(_srcRegIdx[idx]);
 +    }
 +
 +    FloatRegBits readFloatRegBits(const StaticInst *si, int idx, int width)
 +    {
 +        return this->cpu->readFloatRegBits(_srcRegIdx[idx], width);
 +    }
 +
 +    FloatRegBits readFloatRegBits(const StaticInst *si, int idx)
 +    {
 +        return this->cpu->readFloatRegBits(_srcRegIdx[idx]);
 +    }
 +
 +    /** @todo: Make results into arrays so they can handle multiple dest
 +     *  registers.
 +     */
 +    void setIntReg(const StaticInst *si, int idx, uint64_t val)
 +    {
 +        this->cpu->setIntReg(_destRegIdx[idx], val);
 +        BaseDynInst<Impl>::setIntReg(si, idx, val);
 +    }
 +
 +    void setFloatReg(const StaticInst *si, int idx, FloatReg val, int width)
 +    {
 +        this->cpu->setFloatReg(_destRegIdx[idx], val, width);
 +        BaseDynInst<Impl>::setFloatRegSingle(si, idx, val);
 +    }
 +
 +    void setFloatReg(const StaticInst *si, int idx, FloatReg val)
 +    {
 +        this->cpu->setFloatReg(_destRegIdx[idx], val);
 +        BaseDynInst<Impl>::setFloatRegDouble(si, idx, val);
 +    }
 +
 +    void setFloatRegBits(const StaticInst *si, int idx,
 +            FloatRegBits val, int width)
 +    {
 +        this->cpu->setFloatRegBits(_destRegIdx[idx], val, width);
 +        this->instResult.integer = val;
 +    }
 +
 +    void setFloatRegBits(const StaticInst *si, int idx, FloatRegBits val)
 +    {
 +        this->cpu->setFloatRegBits(_destRegIdx[idx], val);
 +        BaseDynInst<Impl>::setFloatRegInt(si, idx, val);
 +    }
 +
 +    /** Returns the physical register index of the i'th destination
 +     *  register.
 +     */
 +    PhysRegIndex renamedDestRegIdx(int idx) const
 +    {
 +        return _destRegIdx[idx];
 +    }
 +
 +    /** Returns the physical register index of the i'th source register. */
 +    PhysRegIndex renamedSrcRegIdx(int idx) const
 +    {
 +        return _srcRegIdx[idx];
 +    }
 +
 +    /** Returns the physical register index of the previous physical register
 +     *  that remapped to the same logical register index.
 +     */
 +    PhysRegIndex prevDestRegIdx(int idx) const
 +    {
 +        return _prevDestRegIdx[idx];
 +    }
 +
 +    /** Renames a destination register to a physical register.  Also records
 +     *  the previous physical register that the logical register mapped to.
 +     */
 +    void renameDestReg(int idx,
 +                       PhysRegIndex renamed_dest,
 +                       PhysRegIndex previous_rename)
 +    {
 +        _destRegIdx[idx] = renamed_dest;
 +        _prevDestRegIdx[idx] = previous_rename;
 +    }
 +
 +    /** Renames a source logical register to the physical register which
 +     *  has/will produce that logical register's result.
 +     *  @todo: add in whether or not the source register is ready.
 +     */
 +    void renameSrcReg(int idx, PhysRegIndex renamed_src)
 +    {
 +        _srcRegIdx[idx] = renamed_src;
 +    }
 +
 +  public:
 +    /** Calculates EA part of a memory instruction. Currently unused,
 +     * though it may be useful in the future if we want to split
 +     * memory operations into EA calculation and memory access parts.
 +     */
 +    Fault calcEA()
 +    {
 +        return this->staticInst->eaCompInst()->execute(this, this->traceData);
 +    }
 +
 +    /** Does the memory access part of a memory instruction. Currently unused,
 +     * though it may be useful in the future if we want to split
 +     * memory operations into EA calculation and memory access parts.
 +     */
 +    Fault memAccess()
 +    {
 +        return this->staticInst->memAccInst()->execute(this, this->traceData);
 +    }
 +};
 +
 +#endif // __CPU_O3_ALPHA_DYN_INST_HH__
 +
index 06755eb76b84b6a50b12ef687fd5debb4f361fdc,0000000000000000000000000000000000000000..3a0727b45f3f180c6f9408c4a6fe6d1858a010ea
mode 100644,000000..100644
--- /dev/null
@@@ -1,176 -1,0 +1,180 @@@
-     // @todo: Pretty convoluted way to avoid squashing from happening when using
-     // the XC during an instruction's execution (specifically for instructions
-     // that have sideeffects that use the XC).  Fix this.
 +/*
 + * Copyright (c) 2004-2006 The Regents of The University of Michigan
 + * 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: Kevin Lim
 + */
 +
 +#include "cpu/o3/alpha_dyn_inst.hh"
 +
 +template <class Impl>
 +AlphaDynInst<Impl>::AlphaDynInst(ExtMachInst inst, Addr PC, Addr Pred_PC,
 +                                 InstSeqNum seq_num, FullCPU *cpu)
 +    : BaseDynInst<Impl>(inst, PC, Pred_PC, seq_num, cpu)
 +{
 +    initVars();
 +}
 +
 +template <class Impl>
 +AlphaDynInst<Impl>::AlphaDynInst(StaticInstPtr &_staticInst)
 +    : BaseDynInst<Impl>(_staticInst)
 +{
 +    initVars();
 +}
 +
 +template <class Impl>
 +void
 +AlphaDynInst<Impl>::initVars()
 +{
 +    // Make sure to have the renamed register entries set to the same
 +    // as the normal register entries.  It will allow the IQ to work
 +    // without any modifications.
 +    for (int i = 0; i < this->staticInst->numDestRegs(); i++) {
 +        _destRegIdx[i] = this->staticInst->destRegIdx(i);
 +    }
 +
 +    for (int i = 0; i < this->staticInst->numSrcRegs(); i++) {
 +        _srcRegIdx[i] = this->staticInst->srcRegIdx(i);
 +        this->_readySrcRegIdx[i] = 0;
 +    }
 +}
 +
 +template <class Impl>
 +Fault
 +AlphaDynInst<Impl>::execute()
 +{
-     // @todo: Pretty convoluted way to avoid squashing from happening when using
-     // the XC during an instruction's execution (specifically for instructions
-     // that have sideeffects that use the XC).  Fix this.
++    // @todo: Pretty convoluted way to avoid squashing from happening
++    // when using the XC during an instruction's execution
++    // (specifically for instructions that have side-effects that use
++    // the XC).  Fix this.
 +    bool in_syscall = this->thread->inSyscall;
 +    this->thread->inSyscall = true;
 +
 +    this->fault = this->staticInst->execute(this, this->traceData);
 +
 +    this->thread->inSyscall = in_syscall;
 +
 +    return this->fault;
 +}
 +
 +template <class Impl>
 +Fault
 +AlphaDynInst<Impl>::initiateAcc()
 +{
++    // @todo: Pretty convoluted way to avoid squashing from happening
++    // when using the XC during an instruction's execution
++    // (specifically for instructions that have side-effects that use
++    // the XC).  Fix this.
 +    bool in_syscall = this->thread->inSyscall;
 +    this->thread->inSyscall = true;
 +
 +    this->fault = this->staticInst->initiateAcc(this, this->traceData);
 +
 +    this->thread->inSyscall = in_syscall;
 +
 +    return this->fault;
 +}
 +
 +template <class Impl>
 +Fault
 +AlphaDynInst<Impl>::completeAcc(Packet *pkt)
 +{
 +    if (this->isLoad()) {
 +        this->fault = this->staticInst->completeAcc(pkt, this,
 +                                                    this->traceData);
 +    } else if (this->isStore()) {
 +        this->fault = this->staticInst->completeAcc(pkt, this,
 +                                                    this->traceData);
 +    } else {
 +        panic("Unknown type!");
 +    }
 +
 +    return this->fault;
 +}
 +
 +#if FULL_SYSTEM
 +template <class Impl>
 +Fault
 +AlphaDynInst<Impl>::hwrei()
 +{
++    // Can only do a hwrei when in pal mode.
 +    if (!this->cpu->inPalMode(this->readPC()))
 +        return new AlphaISA::UnimplementedOpcodeFault;
 +
++    // Set the next PC based on the value of the EXC_ADDR IPR.
 +    this->setNextPC(this->cpu->readMiscReg(AlphaISA::IPR_EXC_ADDR,
 +                                           this->threadNumber));
 +
 +    // Tell CPU to clear any state it needs to if a hwrei is taken.
 +    this->cpu->hwrei(this->threadNumber);
 +
 +    // FIXME: XXX check for interrupts? XXX
 +    return NoFault;
 +}
 +
 +template <class Impl>
 +int
 +AlphaDynInst<Impl>::readIntrFlag()
 +{
 +    return this->cpu->readIntrFlag();
 +}
 +
 +template <class Impl>
 +void
 +AlphaDynInst<Impl>::setIntrFlag(int val)
 +{
 +    this->cpu->setIntrFlag(val);
 +}
 +
 +template <class Impl>
 +bool
 +AlphaDynInst<Impl>::inPalMode()
 +{
 +    return this->cpu->inPalMode(this->PC);
 +}
 +
 +template <class Impl>
 +void
 +AlphaDynInst<Impl>::trap(Fault fault)
 +{
 +    this->cpu->trap(fault, this->threadNumber);
 +}
 +
 +template <class Impl>
 +bool
 +AlphaDynInst<Impl>::simPalCheck(int palFunc)
 +{
 +    return this->cpu->simPalCheck(palFunc, this->threadNumber);
 +}
 +#else
 +template <class Impl>
 +void
 +AlphaDynInst<Impl>::syscall(int64_t callnum)
 +{
 +    this->cpu->syscall(callnum, this->threadNumber);
 +}
 +#endif
 +
index 8c6779495d58d701e380e9d8965aa1210ae57db0,0000000000000000000000000000000000000000..e48abd9edab76437e06b8101df2483726b39eb04
mode 100644,000000..100644
--- /dev/null
@@@ -1,186 -1,0 +1,187 @@@
-     // Branch predictor (BP & BTB)
 +/*
 + * Copyright (c) 2004-2006 The Regents of The University of Michigan
 + * 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: Kevin Lim
 + */
 +
 +#ifndef __CPU_O3_ALPHA_PARAMS_HH__
 +#define __CPU_O3_ALPHA_PARAMS_HH__
 +
 +#include "cpu/o3/cpu.hh"
 +
 +//Forward declarations
 +class AlphaDTB;
 +class AlphaITB;
 +class FUPool;
 +class MemObject;
 +class Process;
 +class System;
 +
 +/**
 + * This file defines the parameters that will be used for the AlphaFullCPU.
 + * This must be defined externally so that the Impl can have a params class
 + * defined that it can pass to all of the individual stages.
 + */
 +
 +class AlphaSimpleParams : public BaseFullCPU::Params
 +{
 +  public:
 +
 +#if FULL_SYSTEM
 +    AlphaITB *itb; AlphaDTB *dtb;
 +#else
 +    std::vector<Process *> workload;
 +    Process *process;
 +#endif // FULL_SYSTEM
 +
 +    //Page Table
 +//    PageTable *pTable;
 +
 +    MemObject *mem;
 +
 +    BaseCPU *checker;
 +
 +    unsigned activity;
 +
 +    //
 +    // Caches
 +    //
 +//    MemInterface *icacheInterface;
 +//    MemInterface *dcacheInterface;
 +
 +    unsigned cachePorts;
 +
 +    //
 +    // Fetch
 +    //
 +    unsigned decodeToFetchDelay;
 +    unsigned renameToFetchDelay;
 +    unsigned iewToFetchDelay;
 +    unsigned commitToFetchDelay;
 +    unsigned fetchWidth;
 +
 +    //
 +    // Decode
 +    //
 +    unsigned renameToDecodeDelay;
 +    unsigned iewToDecodeDelay;
 +    unsigned commitToDecodeDelay;
 +    unsigned fetchToDecodeDelay;
 +    unsigned decodeWidth;
 +
 +    //
 +    // Rename
 +    //
 +    unsigned iewToRenameDelay;
 +    unsigned commitToRenameDelay;
 +    unsigned decodeToRenameDelay;
 +    unsigned renameWidth;
 +
 +    //
 +    // IEW
 +    //
 +    unsigned commitToIEWDelay;
 +    unsigned renameToIEWDelay;
 +    unsigned issueToExecuteDelay;
 +    unsigned issueWidth;
 +    unsigned executeWidth;
 +    unsigned executeIntWidth;
 +    unsigned executeFloatWidth;
 +    unsigned executeBranchWidth;
 +    unsigned executeMemoryWidth;
 +    FUPool *fuPool;
 +
 +    //
 +    // Commit
 +    //
 +    unsigned iewToCommitDelay;
 +    unsigned renameToROBDelay;
 +    unsigned commitWidth;
 +    unsigned squashWidth;
 +    Tick trapLatency;
 +    Tick fetchTrapLatency;
 +
 +    //
++    // Branch predictor (BP, BTB, RAS)
 +    //
++    std::string predType;
 +    unsigned localPredictorSize;
 +    unsigned localCtrBits;
 +    unsigned localHistoryTableSize;
 +    unsigned localHistoryBits;
 +    unsigned globalPredictorSize;
 +    unsigned globalCtrBits;
 +    unsigned globalHistoryBits;
 +    unsigned choicePredictorSize;
 +    unsigned choiceCtrBits;
 +
 +    unsigned BTBEntries;
 +    unsigned BTBTagSize;
 +
 +    unsigned RASSize;
 +
 +    //
 +    // Load store queue
 +    //
 +    unsigned LQEntries;
 +    unsigned SQEntries;
 +
 +    //
 +    // Memory dependence
 +    //
 +    unsigned SSITSize;
 +    unsigned LFSTSize;
 +
 +    //
 +    // Miscellaneous
 +    //
 +    unsigned numPhysIntRegs;
 +    unsigned numPhysFloatRegs;
 +    unsigned numIQEntries;
 +    unsigned numROBEntries;
 +
 +    //SMT Parameters
 +    unsigned smtNumFetchingThreads;
 +
 +    std::string   smtFetchPolicy;
 +
 +    std::string   smtIQPolicy;
 +    unsigned smtIQThreshold;
 +
 +    std::string   smtLSQPolicy;
 +    unsigned smtLSQThreshold;
 +
 +    std::string   smtCommitPolicy;
 +
 +    std::string   smtROBPolicy;
 +    unsigned smtROBThreshold;
 +
 +    // Probably can get this from somewhere.
 +    unsigned instShiftAmt;
 +};
 +
 +#endif // __CPU_O3_ALPHA_PARAMS_HH__
index d0af5af9288bf68626626efdd5424a965cb62077,0000000000000000000000000000000000000000..b33543bdc690a51fd24680eccb1a173f59ccb83b
mode 100644,000000..100644
--- /dev/null
@@@ -1,39 -1,0 +1,39 @@@
- template class TwobitBPredUnit<AlphaSimpleImpl>;
- template class TwobitBPredUnit<OzoneImpl>;
- //template class TwobitBPredUnit<SimpleImpl>;
 +/*
 + * Copyright (c) 2004-2006 The Regents of The University of Michigan
 + * 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: Kevin Lim
 + */
 +
 +#include "cpu/o3/bpred_unit_impl.hh"
 +#include "cpu/o3/alpha_impl.hh"
 +#include "cpu/o3/alpha_dyn_inst.hh"
 +#include "cpu/ozone/ozone_impl.hh"
 +//#include "cpu/ozone/simple_impl.hh"
 +
++template class BPredUnit<AlphaSimpleImpl>;
++template class BPredUnit<OzoneImpl>;
++//template class BPredUnit<SimpleImpl>;
index 39a88a3ce112b1b737bd0e213ec4d638d4325526,0000000000000000000000000000000000000000..2c0a39565bce90eba562d4bcc807852a26581eda
mode 100644,000000..100644
--- /dev/null
@@@ -1,228 -1,0 +1,256 @@@
- class TwobitBPredUnit
 +/*
 + * Copyright (c) 2004-2005 The Regents of The University of Michigan
 + * 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: Kevin Lim
 + */
 +
 +#ifndef __CPU_O3_BPRED_UNIT_HH__
 +#define __CPU_O3_BPRED_UNIT_HH__
 +
 +// For Addr type.
 +#include "arch/isa_traits.hh"
 +#include "base/statistics.hh"
 +#include "cpu/inst_seq.hh"
 +
 +#include "cpu/o3/2bit_local_pred.hh"
 +#include "cpu/o3/btb.hh"
 +#include "cpu/o3/ras.hh"
 +#include "cpu/o3/tournament_pred.hh"
 +
 +#include <list>
 +
 +/**
 + * Basically a wrapper class to hold both the branch predictor
 + * and the BTB.
 + */
 +template<class Impl>
-   public:
++class BPredUnit
 +{
-     TwobitBPredUnit(Params *params);
++  private:
 +    typedef typename Impl::Params Params;
 +    typedef typename Impl::DynInstPtr DynInstPtr;
 +
++    enum PredType {
++        Local,
++        Tournament
++    };
++
++    PredType predictor;
++
++  public:
++
 +    /**
 +     * @param params The params object, that has the size of the BP and BTB.
 +     */
-     bool BPLookup(Addr &inst_PC)
-     { return BP.lookup(inst_PC); }
++    BPredUnit(Params *params);
 +
 +    /**
 +     * Registers statistics.
 +     */
 +    void regStats();
 +
 +    void switchOut();
 +
 +    void takeOverFrom();
 +
 +    /**
 +     * Predicts whether or not the instruction is a taken branch, and the
 +     * target of the branch if it is taken.
 +     * @param inst The branch instruction.
 +     * @param PC The predicted PC is passed back through this parameter.
 +     * @param tid The thread id.
 +     * @return Returns if the branch is taken or not.
 +     */
 +    bool predict(DynInstPtr &inst, Addr &PC, unsigned tid);
 +
++    // @todo: Rename this function.
++    void BPUncond(void * &bp_history);
++
 +    /**
 +     * Tells the branch predictor to commit any updates until the given
 +     * sequence number.
 +     * @param done_sn The sequence number to commit any older updates up until.
 +     * @param tid The thread id.
 +     */
 +    void update(const InstSeqNum &done_sn, unsigned tid);
 +
 +    /**
 +     * Squashes all outstanding updates until a given sequence number.
 +     * @param squashed_sn The sequence number to squash any younger updates up
 +     * until.
 +     * @param tid The thread id.
 +     */
 +    void squash(const InstSeqNum &squashed_sn, unsigned tid);
 +
 +    /**
 +     * Squashes all outstanding updates until a given sequence number, and
 +     * corrects that sn's update with the proper address and taken/not taken.
 +     * @param squashed_sn The sequence number to squash any younger updates up
 +     * until.
 +     * @param corr_target The correct branch target.
 +     * @param actually_taken The correct branch direction.
 +     * @param tid The thread id.
 +     */
 +    void squash(const InstSeqNum &squashed_sn, const Addr &corr_target,
 +                bool actually_taken, unsigned tid);
 +
++    /**
++     * @param bp_history Pointer to the history object.  The predictor
++     * will need to update any state and delete the object.
++     */
++    void BPSquash(void *bp_history);
++
 +    /**
 +     * Looks up a given PC in the BP to see if it is taken or not taken.
 +     * @param inst_PC The PC to look up.
++     * @param bp_history Pointer that will be set to an object that
++     * has the branch predictor state associated with the lookup.
 +     * @return Whether the branch is taken or not taken.
 +     */
-     void BPUpdate(Addr &inst_PC, bool taken)
-     { BP.update(inst_PC, taken); }
++    bool BPLookup(Addr &inst_PC, void * &bp_history);
 +
 +    /**
 +     * Looks up a given PC in the BTB to see if a matching entry exists.
 +     * @param inst_PC The PC to look up.
 +     * @return Whether the BTB contains the given PC.
 +     */
 +    bool BTBValid(Addr &inst_PC)
 +    { return BTB.valid(inst_PC, 0); }
 +
 +    /**
 +     * Looks up a given PC in the BTB to get the predicted target.
 +     * @param inst_PC The PC to look up.
 +     * @return The address of the target of the branch.
 +     */
 +    Addr BTBLookup(Addr &inst_PC)
 +    { return BTB.lookup(inst_PC, 0); }
 +
 +    /**
 +     * Updates the BP with taken/not taken information.
 +     * @param inst_PC The branch's PC that will be updated.
 +     * @param taken Whether the branch was taken or not taken.
++     * @param bp_history Pointer to the branch predictor state that is
++     * associated with the branch lookup that is being updated.
 +     * @todo Make this update flexible enough to handle a global predictor.
 +     */
-          * Makes a predictor history struct that contains a sequence number,
-          * the PC of its instruction, and whether or not it was predicted
-          * taken.
++    void BPUpdate(Addr &inst_PC, bool taken, void *bp_history);
 +
 +    /**
 +     * Updates the BTB with the target of a branch.
 +     * @param inst_PC The branch's PC that will be updated.
 +     * @param target_PC The branch's target that will be added to the BTB.
 +     */
 +    void BTBUpdate(Addr &inst_PC, Addr &target_PC)
 +    { BTB.update(inst_PC, target_PC,0); }
 +
++    void dump();
++
 +  private:
 +    struct PredictorHistory {
 +        /**
-                          const bool pred_taken, const unsigned _tid)
-             : seqNum(seq_num), PC(inst_PC), RASTarget(0), globalHistory(0),
++         * Makes a predictor history struct that contains any
++         * information needed to update the predictor, BTB, and RAS.
 +         */
 +        PredictorHistory(const InstSeqNum &seq_num, const Addr &inst_PC,
-               wasCall(0)
++                         const bool pred_taken, void *bp_history,
++                         const unsigned _tid)
++            : seqNum(seq_num), PC(inst_PC), RASTarget(0),
 +              RASIndex(0), tid(_tid), predTaken(pred_taken), usedRAS(0),
-         /** The global history at the time this entry was created. */
-         unsigned globalHistory;
++              wasCall(0), bpHistory(bp_history)
 +        { }
 +
 +        /** The sequence number for the predictor history entry. */
 +        InstSeqNum seqNum;
 +
 +        /** The PC associated with the sequence number. */
 +        Addr PC;
 +
 +        /** The RAS target (only valid if a return). */
 +        Addr RASTarget;
 +
-     /** The branch predictor. */
-     DefaultBP BP;
 +        /** The RAS index of the instruction (only valid if a call). */
 +        unsigned RASIndex;
 +
 +        /** The thread id. */
 +        unsigned tid;
 +
 +        /** Whether or not it was predicted taken. */
 +        bool predTaken;
 +
 +        /** Whether or not the RAS was used. */
 +        bool usedRAS;
 +
 +        /** Whether or not the instruction was a call. */
 +        bool wasCall;
++
++        /** Pointer to the history object passed back from the branch
++         * predictor.  It is used to update or restore state of the
++         * branch predictor.
++         */
++        void *bpHistory;
 +    };
 +
 +    typedef std::list<PredictorHistory> History;
 +
 +    /**
 +     * The per-thread predictor history. This is used to update the predictor
 +     * as instructions are committed, or restore it to the proper state after
 +     * a squash.
 +     */
 +    History predHist[Impl::MaxThreads];
 +
++    /** The local branch predictor. */
++    LocalBP *localBP;
++
++    /** The tournament branch predictor. */
++    TournamentBP *tournamentBP;
 +
 +    /** The BTB. */
 +    DefaultBTB BTB;
 +
 +    /** The per-thread return address stack. */
 +    ReturnAddrStack RAS[Impl::MaxThreads];
 +
 +    /** Stat for number of BP lookups. */
 +    Stats::Scalar<> lookups;
 +    /** Stat for number of conditional branches predicted. */
 +    Stats::Scalar<> condPredicted;
 +    /** Stat for number of conditional branches predicted incorrectly. */
 +    Stats::Scalar<> condIncorrect;
 +    /** Stat for number of BTB lookups. */
 +    Stats::Scalar<> BTBLookups;
 +    /** Stat for number of BTB hits. */
 +    Stats::Scalar<> BTBHits;
 +    /** Stat for number of times the BTB is correct. */
 +    Stats::Scalar<> BTBCorrect;
 +    /** Stat for number of times the RAS is used to get a target. */
 +    Stats::Scalar<> usedRAS;
 +    /** Stat for number of times the RAS is incorrect. */
 +    Stats::Scalar<> RASIncorrect;
 +};
 +
 +#endif // __CPU_O3_BPRED_UNIT_HH__
index cde9f28ab7134d60ce299fc16b151f2840478046,0000000000000000000000000000000000000000..0da02145bcb9f069aa6903e36393db67754ad0e7
mode 100644,000000..100644
--- /dev/null
@@@ -1,326 -1,0 +1,412 @@@
- TwobitBPredUnit<Impl>::TwobitBPredUnit(Params *params)
-   : BP(params->localPredictorSize,
-        params->localCtrBits,
-        params->instShiftAmt),
-     BTB(params->BTBEntries,
 +/*
 + * Copyright (c) 2004-2005 The Regents of The University of Michigan
 + * 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: Kevin Lim
 + */
 +
 +#include <list>
 +#include <vector>
 +
 +#include "base/trace.hh"
 +#include "base/traceflags.hh"
 +#include "cpu/o3/bpred_unit.hh"
 +
 +using namespace std;
 +
 +template<class Impl>
- TwobitBPredUnit<Impl>::regStats()
++BPredUnit<Impl>::BPredUnit(Params *params)
++  : BTB(params->BTBEntries,
 +        params->BTBTagSize,
 +        params->instShiftAmt)
 +{
++    // Setup the selected predictor.
++    if (params->predType == "local") {
++        localBP = new LocalBP(params->localPredictorSize,
++                              params->localCtrBits,
++                              params->instShiftAmt);
++        predictor = Local;
++    } else if (params->predType == "tournament") {
++        tournamentBP = new TournamentBP(params->localPredictorSize,
++                                        params->localCtrBits,
++                                        params->localHistoryTableSize,
++                                        params->localHistoryBits,
++                                        params->globalPredictorSize,
++                                        params->globalHistoryBits,
++                                        params->globalCtrBits,
++                                        params->choicePredictorSize,
++                                        params->choiceCtrBits,
++                                        params->instShiftAmt);
++        predictor = Tournament;
++    } else {
++        fatal("Invalid BP selected!");
++    }
++
 +    for (int i=0; i < Impl::MaxThreads; i++)
 +        RAS[i].init(params->RASSize);
 +}
 +
 +template <class Impl>
 +void
- TwobitBPredUnit<Impl>::switchOut()
++BPredUnit<Impl>::regStats()
 +{
 +    lookups
 +        .name(name() + ".BPredUnit.lookups")
 +        .desc("Number of BP lookups")
 +        ;
 +
 +    condPredicted
 +        .name(name() + ".BPredUnit.condPredicted")
 +        .desc("Number of conditional branches predicted")
 +        ;
 +
 +    condIncorrect
 +        .name(name() + ".BPredUnit.condIncorrect")
 +        .desc("Number of conditional branches incorrect")
 +        ;
 +
 +    BTBLookups
 +        .name(name() + ".BPredUnit.BTBLookups")
 +        .desc("Number of BTB lookups")
 +        ;
 +
 +    BTBHits
 +        .name(name() + ".BPredUnit.BTBHits")
 +        .desc("Number of BTB hits")
 +        ;
 +
 +    BTBCorrect
 +        .name(name() + ".BPredUnit.BTBCorrect")
 +        .desc("Number of correct BTB predictions (this stat may not "
 +              "work properly.")
 +        ;
 +
 +    usedRAS
 +        .name(name() + ".BPredUnit.usedRAS")
 +        .desc("Number of times the RAS was used to get a target.")
 +        ;
 +
 +    RASIncorrect
 +        .name(name() + ".BPredUnit.RASInCorrect")
 +        .desc("Number of incorrect RAS predictions.")
 +        ;
 +}
 +
 +template <class Impl>
 +void
-         predHist[i].clear();
++BPredUnit<Impl>::switchOut()
 +{
++    // Clear any state upon switch out.
 +    for (int i = 0; i < Impl::MaxThreads; ++i) {
- TwobitBPredUnit<Impl>::takeOverFrom()
++        squash(0, i);
 +    }
 +}
 +
 +template <class Impl>
 +void
- TwobitBPredUnit<Impl>::predict(DynInstPtr &inst, Addr &PC, unsigned tid)
++BPredUnit<Impl>::takeOverFrom()
 +{
++    // Can reset all predictor state, but it's not necessarily better
++    // than leaving it be.
 +/*
 +    for (int i = 0; i < Impl::MaxThreads; ++i)
 +        RAS[i].reset();
 +
 +    BP.reset();
 +    BTB.reset();
 +*/
 +}
 +
 +template <class Impl>
 +bool
-     // Once that's done, speculatively update the predictor?
++BPredUnit<Impl>::predict(DynInstPtr &inst, Addr &PC, unsigned tid)
 +{
 +    // See if branch predictor predicts taken.
 +    // If so, get its target addr either from the BTB or the RAS.
-         pred_taken = BPLookup(PC);
 +    // Save off record of branch stuff so the RAS can be fixed
 +    // up once it's done.
 +
 +    using TheISA::MachInst;
 +
 +    bool pred_taken = false;
 +    Addr target;
 +
 +    ++lookups;
 +
++    void *bp_history = NULL;
++
 +    if (inst->isUncondCtrl()) {
 +        DPRINTF(Fetch, "BranchPred: [tid:%i] Unconditional control.\n", tid);
 +        pred_taken = true;
++        // Tell the BP there was an unconditional branch.
++        BPUncond(bp_history);
 +    } else {
 +        ++condPredicted;
 +
-     PredictorHistory predict_record(inst->seqNum, PC, pred_taken, tid);
++        pred_taken = BPLookup(PC, bp_history);
 +
 +        DPRINTF(Fetch, "BranchPred: [tid:%i]: Branch predictor predicted %i "
 +                "for PC %#x\n",
 +                tid, pred_taken, inst->readPC());
 +    }
 +
-                 //If it's anything else, use the BTB to get the target addr.
++    PredictorHistory predict_record(inst->seqNum, PC, pred_taken,
++                                    bp_history, tid);
 +
 +    // Now lookup in the BTB or RAS.
 +    if (pred_taken) {
 +        if (inst->isReturn()) {
 +            ++usedRAS;
 +
 +            // If it's a function return call, then look up the address
 +            // in the RAS.
 +            target = RAS[tid].top();
 +
 +            // Record the top entry of the RAS, and its index.
 +            predict_record.usedRAS = true;
 +            predict_record.RASIndex = RAS[tid].topIdx();
 +            predict_record.RASTarget = target;
 +
 +            assert(predict_record.RASIndex < 16);
 +
 +            RAS[tid].pop();
 +
 +            DPRINTF(Fetch, "BranchPred: [tid:%i]: Instruction %#x is a return, "
 +                    "RAS predicted target: %#x, RAS index: %i.\n",
 +                    tid, inst->readPC(), target, predict_record.RASIndex);
 +        } else {
 +            ++BTBLookups;
 +
 +            if (inst->isCall()) {
 +                RAS[tid].push(PC + sizeof(MachInst));
 +
 +                // Record that it was a call so that the top RAS entry can
 +                // be popped off if the speculation is incorrect.
 +                predict_record.wasCall = true;
 +
 +                DPRINTF(Fetch, "BranchPred: [tid:%i] Instruction %#x was a call"
 +                        ", adding %#x to the RAS.\n",
 +                        tid, inst->readPC(), PC + sizeof(MachInst));
 +            }
 +
 +            if (BTB.valid(PC, tid)) {
 +                ++BTBHits;
 +
- TwobitBPredUnit<Impl>::update(const InstSeqNum &done_sn, unsigned tid)
++                // If it's not a return, use the BTB to get the target addr.
 +                target = BTB.lookup(PC, tid);
 +
 +                DPRINTF(Fetch, "BranchPred: [tid:%i]: Instruction %#x predicted"
 +                        " target is %#x.\n",
 +                        tid, inst->readPC(), target);
 +
 +            } else {
 +                DPRINTF(Fetch, "BranchPred: [tid:%i]: BTB doesn't have a "
 +                        "valid entry.\n",tid);
 +                pred_taken = false;
 +            }
 +
 +        }
 +    }
 +
 +    if (pred_taken) {
 +        // Set the PC and the instruction's predicted target.
 +        PC = target;
 +        inst->setPredTarg(target);
 +    } else {
 +        PC = PC + sizeof(MachInst);
 +        inst->setPredTarg(PC);
 +    }
 +
 +    predHist[tid].push_front(predict_record);
 +
 +    DPRINTF(Fetch, "[tid:%i] predHist.size(): %i\n", tid, predHist[tid].size());
 +
 +    return pred_taken;
 +}
 +
 +template <class Impl>
 +void
-         BP.update(predHist[tid].back().PC,
-                   predHist[tid].back().predTaken);
++BPredUnit<Impl>::update(const InstSeqNum &done_sn, unsigned tid)
 +{
 +    DPRINTF(Fetch, "BranchPred: [tid:%i]: Commiting branches until sequence"
 +            "number %lli.\n", tid, done_sn);
 +
 +    while (!predHist[tid].empty() &&
 +           predHist[tid].back().seqNum <= done_sn) {
 +        // Update the branch predictor with the correct results.
- TwobitBPredUnit<Impl>::squash(const InstSeqNum &squashed_sn, unsigned tid)
++        BPUpdate(predHist[tid].back().PC,
++                 predHist[tid].back().predTaken,
++                 predHist[tid].back().bpHistory);
 +
 +        predHist[tid].pop_back();
 +    }
 +}
 +
 +template <class Impl>
 +void
-        if (pred_hist.front().usedRAS) {
++BPredUnit<Impl>::squash(const InstSeqNum &squashed_sn, unsigned tid)
 +{
 +    History &pred_hist = predHist[tid];
 +
 +    while (!pred_hist.empty() &&
 +           pred_hist.front().seqNum > squashed_sn) {
-             DPRINTF(Fetch, "BranchPred: [tid:%i]: Removing speculative entry added "
-                     "to the RAS.\n",tid);
++        if (pred_hist.front().usedRAS) {
 +            DPRINTF(Fetch, "BranchPred: [tid:%i]: Restoring top of RAS to: %i,"
 +                    " target: %#x.\n",
 +                    tid,
 +                    pred_hist.front().RASIndex,
 +                    pred_hist.front().RASTarget);
 +
 +            RAS[tid].restore(pred_hist.front().RASIndex,
 +                             pred_hist.front().RASTarget);
 +
 +        } else if (pred_hist.front().wasCall) {
- TwobitBPredUnit<Impl>::squash(const InstSeqNum &squashed_sn,
-                               const Addr &corr_target,
-                               const bool actually_taken,
-                               unsigned tid)
++            DPRINTF(Fetch, "BranchPred: [tid:%i]: Removing speculative entry "
++                    "added to the RAS.\n",tid);
 +
 +            RAS[tid].pop();
 +        }
 +
++        // This call should delete the bpHistory.
++        BPSquash(pred_hist.front().bpHistory);
++
 +        pred_hist.pop_front();
 +    }
 +
 +}
 +
 +template <class Impl>
 +void
-     while (!pred_hist.empty() &&
-            pred_hist.front().seqNum > squashed_sn) {
-         if (pred_hist.front().usedRAS) {
-             DPRINTF(Fetch, "BranchPred: [tid:%i]: Restoring top of RAS to: %i, "
-                     "target: %#x.\n",
-                     tid,
-                     pred_hist.front().RASIndex,
-                     pred_hist.front().RASTarget);
-             RAS[tid].restore(pred_hist.front().RASIndex,
-                              pred_hist.front().RASTarget);
-         } else if (pred_hist.front().wasCall) {
-             DPRINTF(Fetch, "BranchPred: [tid:%i]: Removing speculative entry"
-                     " added to the RAS.\n", tid);
-             RAS[tid].pop();
-         }
-         pred_hist.pop_front();
-     }
++BPredUnit<Impl>::squash(const InstSeqNum &squashed_sn,
++                        const Addr &corr_target,
++                        const bool actually_taken,
++                        unsigned tid)
 +{
 +    // Now that we know that a branch was mispredicted, we need to undo
 +    // all the branches that have been seen up until this branch and
 +    // fix up everything.
 +
 +    History &pred_hist = predHist[tid];
 +
 +    ++condIncorrect;
 +
 +    DPRINTF(Fetch, "BranchPred: [tid:%i]: Squashing from sequence number %i, "
 +            "setting target to %#x.\n",
 +            tid, squashed_sn, corr_target);
 +
-         pred_hist.front().predTaken = actually_taken;
++    squash(squashed_sn, tid);
 +
 +    // If there's a squash due to a syscall, there may not be an entry
 +    // corresponding to the squash.  In that case, don't bother trying to
 +    // fix up the entry.
 +    if (!pred_hist.empty()) {
-         BP.update(pred_hist.front().PC, actually_taken);
++        assert(pred_hist.front().seqNum == squashed_sn);
 +        if (pred_hist.front().usedRAS) {
 +            ++RASIncorrect;
 +        }
 +
++        BPUpdate(pred_hist.front().PC, actually_taken,
++                 pred_hist.front().bpHistory);
 +
 +        BTB.update(pred_hist.front().PC, corr_target, tid);
 +        pred_hist.pop_front();
 +    }
 +}
++
++template <class Impl>
++void
++BPredUnit<Impl>::BPUncond(void * &bp_history)
++{
++    // Only the tournament predictor cares about unconditional branches.
++    if (predictor == Tournament) {
++        tournamentBP->uncondBr(bp_history);
++    }
++}
++
++template <class Impl>
++void
++BPredUnit<Impl>::BPSquash(void *bp_history)
++{
++    if (predictor == Local) {
++        localBP->squash(bp_history);
++    } else if (predictor == Tournament) {
++        tournamentBP->squash(bp_history);
++    } else {
++        panic("Predictor type is unexpected value!");
++    }
++}
++
++template <class Impl>
++bool
++BPredUnit<Impl>::BPLookup(Addr &inst_PC, void * &bp_history)
++{
++    if (predictor == Local) {
++        return localBP->lookup(inst_PC, bp_history);
++    } else if (predictor == Tournament) {
++        return tournamentBP->lookup(inst_PC, bp_history);
++    } else {
++        panic("Predictor type is unexpected value!");
++    }
++}
++
++template <class Impl>
++void
++BPredUnit<Impl>::BPUpdate(Addr &inst_PC, bool taken, void *bp_history)
++{
++    if (predictor == Local) {
++        localBP->update(inst_PC, taken, bp_history);
++    } else if (predictor == Tournament) {
++        tournamentBP->update(inst_PC, taken, bp_history);
++    } else {
++        panic("Predictor type is unexpected value!");
++    }
++}
++
++template <class Impl>
++void
++BPredUnit<Impl>::dump()
++{
++    typename History::iterator pred_hist_it;
++
++    for (int i = 0; i < Impl::MaxThreads; ++i) {
++        if (!predHist[i].empty()) {
++            pred_hist_it = predHist[i].begin();
++
++            cprintf("predHist[%i].size(): %i\n", i, predHist[i].size());
++
++            while (pred_hist_it != predHist[i].end()) {
++                cprintf("[sn:%lli], PC:%#x, tid:%i, predTaken:%i, "
++                        "bpHistory:%#x\n",
++                        (*pred_hist_it).seqNum, (*pred_hist_it).PC,
++                        (*pred_hist_it).tid, (*pred_hist_it).predTaken,
++                        (*pred_hist_it).bpHistory);
++                pred_hist_it++;
++            }
++
++            cprintf("\n");
++        }
++    }
++}
index 84ad5f6b18df49f35fd52246858eb919f6dc829d,0000000000000000000000000000000000000000..bf1bd08e89e920a64381a161cf67b37fb3870c5b
mode 100644,000000..100644
--- /dev/null
@@@ -1,199 -1,0 +1,198 @@@
-     // Rename can't actually tell anything to squash or send a new PC back
-     // because it doesn't do anything along those lines.  But maybe leave
-     // these fields in here to keep the stages mostly orthagonal.
 +/*
 + * Copyright (c) 2004-2006 The Regents of The University of Michigan
 + * 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: Kevin Lim
 + */
 +
 +#ifndef __CPU_O3_COMM_HH__
 +#define __CPU_O3_COMM_HH__
 +
 +#include <vector>
 +
 +#include "arch/faults.hh"
 +#include "arch/isa_traits.hh"
 +#include "cpu/inst_seq.hh"
 +#include "sim/host.hh"
 +
 +// Typedef for physical register index type. Although the Impl would be the
 +// most likely location for this, there are a few classes that need this
 +// typedef yet are not templated on the Impl. For now it will be defined here.
 +typedef short int PhysRegIndex;
 +
++/** Struct that defines the information passed from fetch to decode. */
 +template<class Impl>
 +struct DefaultFetchDefaultDecode {
 +    typedef typename Impl::DynInstPtr DynInstPtr;
 +
 +    int size;
 +
 +    DynInstPtr insts[Impl::MaxWidth];
 +    Fault fetchFault;
 +    InstSeqNum fetchFaultSN;
 +    bool clearFetchFault;
 +};
 +
++/** Struct that defines the information passed from decode to rename. */
 +template<class Impl>
 +struct DefaultDecodeDefaultRename {
 +    typedef typename Impl::DynInstPtr DynInstPtr;
 +
 +    int size;
 +
 +    DynInstPtr insts[Impl::MaxWidth];
 +};
 +
++/** Struct that defines the information passed from rename to IEW. */
 +template<class Impl>
 +struct DefaultRenameDefaultIEW {
 +    typedef typename Impl::DynInstPtr DynInstPtr;
 +
 +    int size;
 +
 +    DynInstPtr insts[Impl::MaxWidth];
 +};
 +
++/** Struct that defines the information passed from IEW to commit. */
 +template<class Impl>
 +struct DefaultIEWDefaultCommit {
 +    typedef typename Impl::DynInstPtr DynInstPtr;
 +
 +    int size;
 +
 +    DynInstPtr insts[Impl::MaxWidth];
 +
 +    bool squash[Impl::MaxThreads];
 +    bool branchMispredict[Impl::MaxThreads];
 +    bool branchTaken[Impl::MaxThreads];
 +    uint64_t mispredPC[Impl::MaxThreads];
 +    uint64_t nextPC[Impl::MaxThreads];
 +    InstSeqNum squashedSeqNum[Impl::MaxThreads];
 +
 +    bool includeSquashInst[Impl::MaxThreads];
 +};
 +
 +template<class Impl>
 +struct IssueStruct {
 +    typedef typename Impl::DynInstPtr DynInstPtr;
 +
 +    int size;
 +
 +    DynInstPtr insts[Impl::MaxWidth];
 +};
 +
++/** Struct that defines all backwards communication. */
 +template<class Impl>
 +struct TimeBufStruct {
 +    struct decodeComm {
 +        bool squash;
 +        bool predIncorrect;
 +        uint64_t branchAddr;
 +
 +        InstSeqNum doneSeqNum;
 +
 +        // @todo: Might want to package this kind of branch stuff into a single
 +        // struct as it is used pretty frequently.
 +        bool branchMispredict;
 +        bool branchTaken;
 +        uint64_t mispredPC;
 +        uint64_t nextPC;
 +
 +        unsigned branchCount;
 +    };
 +
 +    decodeComm decodeInfo[Impl::MaxThreads];
 +
-         bool squash;
-         uint64_t nextPC;
 +    struct renameComm {
 +    };
 +
 +    renameComm renameInfo[Impl::MaxThreads];
 +
 +    struct iewComm {
 +        // Also eventually include skid buffer space.
 +        bool usedIQ;
 +        unsigned freeIQEntries;
 +        bool usedLSQ;
 +        unsigned freeLSQEntries;
 +
 +        unsigned iqCount;
 +        unsigned ldstqCount;
 +
 +        unsigned dispatched;
 +        unsigned dispatchedToLSQ;
 +    };
 +
 +    iewComm iewInfo[Impl::MaxThreads];
 +
 +    struct commitComm {
 +        bool usedROB;
 +        unsigned freeROBEntries;
 +        bool emptyROB;
 +
 +        bool squash;
 +        bool robSquashing;
 +
 +        bool branchMispredict;
 +        bool branchTaken;
 +        uint64_t mispredPC;
 +        uint64_t nextPC;
 +
 +        // Represents the instruction that has either been retired or
 +        // squashed.  Similar to having a single bus that broadcasts the
 +        // retired or squashed sequence number.
 +        InstSeqNum doneSeqNum;
 +
 +        //Just in case we want to do a commit/squash on a cycle
 +        //(necessary for multiple ROBs?)
 +        bool commitInsts;
 +        InstSeqNum squashSeqNum;
 +
 +        // Communication specifically to the IQ to tell the IQ that it can
 +        // schedule a non-speculative instruction.
 +        InstSeqNum nonSpecSeqNum;
 +
 +        // Hack for now to send back an uncached access to the IEW stage.
 +        typedef typename Impl::DynInstPtr DynInstPtr;
 +        bool uncached;
 +        DynInstPtr uncachedLoad;
 +
 +        bool interruptPending;
 +        bool clearInterrupt;
 +    };
 +
 +    commitComm commitInfo[Impl::MaxThreads];
 +
 +    bool decodeBlock[Impl::MaxThreads];
 +    bool decodeUnblock[Impl::MaxThreads];
 +    bool renameBlock[Impl::MaxThreads];
 +    bool renameUnblock[Impl::MaxThreads];
 +    bool iewBlock[Impl::MaxThreads];
 +    bool iewUnblock[Impl::MaxThreads];
 +    bool commitBlock[Impl::MaxThreads];
 +    bool commitUnblock[Impl::MaxThreads];
 +};
 +
 +#endif //__CPU_O3_COMM_HH__
index ae2aa299619fc114c29135be7a3ad15638d94b37,0000000000000000000000000000000000000000..eef96b5fdc4e7d29c2904b1b5984e8e192fa4db4
mode 100644,000000..100644
--- /dev/null
@@@ -1,422 -1,0 +1,454 @@@
-     /** Sets the poitner to the IEW stage. */
 +/*
 + * Copyright (c) 2004-2006 The Regents of The University of Michigan
 + * 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: Kevin Lim
 + */
 +
 +#ifndef __CPU_O3_COMMIT_HH__
 +#define __CPU_O3_COMMIT_HH__
 +
 +#include "arch/faults.hh"
 +#include "base/statistics.hh"
 +#include "base/timebuf.hh"
 +#include "cpu/exetrace.hh"
 +#include "cpu/inst_seq.hh"
 +
 +template <class>
 +class O3ThreadState;
 +
 +/**
 + * DefaultCommit handles single threaded and SMT commit. Its width is
 + * specified by the parameters; each cycle it tries to commit that
 + * many instructions. The SMT policy decides which thread it tries to
 + * commit instructions from. Non- speculative instructions must reach
 + * the head of the ROB before they are ready to execute; once they
 + * reach the head, commit will broadcast the instruction's sequence
 + * number to the previous stages so that they can issue/ execute the
 + * instruction. Only one non-speculative instruction is handled per
 + * cycle. Commit is responsible for handling all back-end initiated
 + * redirects.  It receives the redirect, and then broadcasts it to all
 + * stages, indicating the sequence number they should squash until,
 + * and any necessary branch misprediction information as well. It
 + * priortizes redirects by instruction's age, only broadcasting a
 + * redirect if it corresponds to an instruction that should currently
 + * be in the ROB. This is done by tracking the sequence number of the
 + * youngest instruction in the ROB, which gets updated to any
 + * squashing instruction's sequence number, and only broadcasting a
 + * redirect if it corresponds to an older instruction. Commit also
 + * supports multiple cycle squashing, to model a ROB that can only
 + * remove a certain number of instructions per cycle.
 + */
 +template<class Impl>
 +class DefaultCommit
 +{
 +  public:
 +    // Typedefs from the Impl.
 +    typedef typename Impl::FullCPU FullCPU;
 +    typedef typename Impl::DynInstPtr DynInstPtr;
 +    typedef typename Impl::Params Params;
 +    typedef typename Impl::CPUPol CPUPol;
 +
 +    typedef typename CPUPol::RenameMap RenameMap;
 +    typedef typename CPUPol::ROB ROB;
 +
 +    typedef typename CPUPol::TimeStruct TimeStruct;
 +    typedef typename CPUPol::FetchStruct FetchStruct;
 +    typedef typename CPUPol::IEWStruct IEWStruct;
 +    typedef typename CPUPol::RenameStruct RenameStruct;
 +
 +    typedef typename CPUPol::Fetch Fetch;
 +    typedef typename CPUPol::IEW IEW;
 +
 +    typedef O3ThreadState<Impl> Thread;
 +
++    /** Event class used to schedule a squash due to a trap (fault or
++     * interrupt) to happen on a specific cycle.
++     */
 +    class TrapEvent : public Event {
 +      private:
 +        DefaultCommit<Impl> *commit;
 +        unsigned tid;
 +
 +      public:
 +        TrapEvent(DefaultCommit<Impl> *_commit, unsigned _tid);
 +
 +        void process();
 +        const char *description();
 +    };
 +
 +    /** Overall commit status. Used to determine if the CPU can deschedule
 +     * itself due to a lack of activity.
 +     */
 +    enum CommitStatus{
 +        Active,
 +        Inactive
 +    };
 +
 +    /** Individual thread status. */
 +    enum ThreadStatus {
 +        Running,
 +        Idle,
 +        ROBSquashing,
 +        TrapPending,
 +        FetchTrapPending
 +    };
 +
 +    /** Commit policy for SMT mode. */
 +    enum CommitPolicy {
 +        Aggressive,
 +        RoundRobin,
 +        OldestReady
 +    };
 +
 +  private:
 +    /** Overall commit status. */
 +    CommitStatus _status;
 +    /** Next commit status, to be set at the end of the cycle. */
 +    CommitStatus _nextStatus;
 +    /** Per-thread status. */
 +    ThreadStatus commitStatus[Impl::MaxThreads];
 +    /** Commit policy used in SMT mode. */
 +    CommitPolicy commitPolicy;
 +
 +  public:
 +    /** Construct a DefaultCommit with the given parameters. */
 +    DefaultCommit(Params *params);
 +
 +    /** Returns the name of the DefaultCommit. */
 +    std::string name() const;
 +
 +    /** Registers statistics. */
 +    void regStats();
 +
 +    /** Sets the CPU pointer. */
 +    void setCPU(FullCPU *cpu_ptr);
 +
 +    /** Sets the list of threads. */
 +    void setThreads(std::vector<Thread *> &threads);
 +
 +    /** Sets the main time buffer pointer, used for backwards communication. */
 +    void setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr);
 +
 +    void setFetchQueue(TimeBuffer<FetchStruct> *fq_ptr);
 +
 +    /** Sets the pointer to the queue coming from rename. */
 +    void setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr);
 +
 +    /** Sets the pointer to the queue coming from IEW. */
 +    void setIEWQueue(TimeBuffer<IEWStruct> *iq_ptr);
 +
 +    void setFetchStage(Fetch *fetch_stage);
 +
 +    Fetch *fetchStage;
 +
-      * tell the CPU if commit is active/inactive. */
++    /** Sets the pointer to the IEW stage. */
 +    void setIEWStage(IEW *iew_stage);
 +
 +    /** The pointer to the IEW stage. Used solely to ensure that
 +     * various events (traps, interrupts, syscalls) do not occur until
 +     * all stores have written back.
 +     */
 +    IEW *iewStage;
 +
 +    /** Sets pointer to list of active threads. */
 +    void setActiveThreads(std::list<unsigned> *at_ptr);
 +
 +    /** Sets pointer to the commited state rename map. */
 +    void setRenameMap(RenameMap rm_ptr[Impl::MaxThreads]);
 +
 +    /** Sets pointer to the ROB. */
 +    void setROB(ROB *rob_ptr);
 +
 +    /** Initializes stage by sending back the number of free entries. */
 +    void initStage();
 +
++    /** Initializes the switching out of commit. */
 +    void switchOut();
 +
++    /** Completes the switch out of commit. */
 +    void doSwitchOut();
 +
++    /** Takes over from another CPU's thread. */
 +    void takeOverFrom();
 +
 +    /** Ticks the commit stage, which tries to commit instructions. */
 +    void tick();
 +
 +    /** Handles any squashes that are sent from IEW, and adds instructions
 +     * to the ROB and tries to commit instructions.
 +     */
 +    void commit();
 +
 +    /** Returns the number of free ROB entries for a specific thread. */
 +    unsigned numROBFreeEntries(unsigned tid);
 +
++    /** Generates an event to schedule a squash due to a trap. */
++    void generateTrapEvent(unsigned tid);
++
++    /** Records that commit needs to initiate a squash due to an
++     * external state update through the XC.
++     */
 +    void generateXCEvent(unsigned tid);
 +
 +  private:
 +    /** Updates the overall status of commit with the nextStatus, and
-     void generateTrapEvent(unsigned tid);
++     * tell the CPU if commit is active/inactive.
++     */
 +    void updateStatus();
 +
 +    /** Sets the next status based on threads' statuses, which becomes the
 +     * current status at the end of the cycle.
 +     */
 +    void setNextStatus();
 +
 +    /** Checks if the ROB is completed with squashing. This is for the case
 +     * where the ROB can take multiple cycles to complete squashing.
 +     */
 +    bool robDoneSquashing();
 +
 +    /** Returns if any of the threads have the number of ROB entries changed
 +     * on this cycle. Used to determine if the number of free ROB entries needs
 +     * to be sent back to previous stages.
 +     */
 +    bool changedROBEntries();
 +
++    /** Squashes all in flight instructions. */
 +    void squashAll(unsigned tid);
 +
++    /** Handles squashing due to a trap. */
 +    void squashFromTrap(unsigned tid);
 +
++    /** Handles squashing due to an XC write. */
 +    void squashFromXC(unsigned tid);
 +
 +    /** Commits as many instructions as possible. */
 +    void commitInsts();
 +
 +    /** Tries to commit the head ROB instruction passed in.
 +     * @param head_inst The instruction to be committed.
 +     */
 +    bool commitHead(DynInstPtr &head_inst, unsigned inst_num);
 +
 +    /** Gets instructions from rename and inserts them into the ROB. */
 +    void getInsts();
 +
 +    /** Marks completed instructions using information sent from IEW. */
 +    void markCompletedInsts();
 +
 +    /** Gets the thread to commit, based on the SMT policy. */
 +    int getCommittingThread();
 +
 +    /** Returns the thread ID to use based on a round robin policy. */
 +    int roundRobin();
 +
 +    /** Returns the thread ID to use based on an oldest instruction policy. */
 +    int oldestReady();
 +
 +  public:
 +    /** Returns the PC of the head instruction of the ROB.
 +     * @todo: Probably remove this function as it returns only thread 0.
 +     */
 +    uint64_t readPC() { return PC[0]; }
 +
++    /** Returns the PC of a specific thread. */
 +    uint64_t readPC(unsigned tid) { return PC[tid]; }
 +
++    /** Sets the PC of a specific thread. */
 +    void setPC(uint64_t val, unsigned tid) { PC[tid] = val; }
 +
++    /** Reads the PC of a specific thread. */
 +    uint64_t readNextPC(unsigned tid) { return nextPC[tid]; }
 +
++    /** Sets the next PC of a specific thread. */
 +    void setNextPC(uint64_t val, unsigned tid) { nextPC[tid] = val; }
 +
 +  private:
 +    /** Time buffer interface. */
 +    TimeBuffer<TimeStruct> *timeBuffer;
 +
 +    /** Wire to write information heading to previous stages. */
 +    typename TimeBuffer<TimeStruct>::wire toIEW;
 +
 +    /** Wire to read information from IEW (for ROB). */
 +    typename TimeBuffer<TimeStruct>::wire robInfoFromIEW;
 +
 +    TimeBuffer<FetchStruct> *fetchQueue;
 +
 +    typename TimeBuffer<FetchStruct>::wire fromFetch;
 +
 +    /** IEW instruction queue interface. */
 +    TimeBuffer<IEWStruct> *iewQueue;
 +
 +    /** Wire to read information from IEW queue. */
 +    typename TimeBuffer<IEWStruct>::wire fromIEW;
 +
 +    /** Rename instruction queue interface, for ROB. */
 +    TimeBuffer<RenameStruct> *renameQueue;
 +
 +    /** Wire to read information from rename queue. */
 +    typename TimeBuffer<RenameStruct>::wire fromRename;
 +
 +  public:
 +    /** ROB interface. */
 +    ROB *rob;
 +
 +  private:
 +    /** Pointer to FullCPU. */
 +    FullCPU *cpu;
 +
++    /** Vector of all of the threads. */
 +    std::vector<Thread *> thread;
 +
 +    Fault fetchFault;
 +
 +    int fetchTrapWait;
 +
 +    /** Records that commit has written to the time buffer this cycle. Used for
 +     * the CPU to determine if it can deschedule itself if there is no activity.
 +     */
 +    bool wroteToTimeBuffer;
 +
 +    /** Records if the number of ROB entries has changed this cycle. If it has,
 +     * then the number of free entries must be re-broadcast.
 +     */
 +    bool changedROBNumEntries[Impl::MaxThreads];
 +
 +    /** A counter of how many threads are currently squashing. */
 +    int squashCounter;
 +
 +    /** Records if a thread has to squash this cycle due to a trap. */
 +    bool trapSquash[Impl::MaxThreads];
 +
 +    /** Records if a thread has to squash this cycle due to an XC write. */
 +    bool xcSquash[Impl::MaxThreads];
 +
 +    /** Priority List used for Commit Policy */
 +    std::list<unsigned> priority_list;
 +
 +    /** IEW to Commit delay, in ticks. */
 +    unsigned iewToCommitDelay;
 +
 +    /** Commit to IEW delay, in ticks. */
 +    unsigned commitToIEWDelay;
 +
 +    /** Rename to ROB delay, in ticks. */
 +    unsigned renameToROBDelay;
 +
 +    unsigned fetchToCommitDelay;
 +
 +    /** Rename width, in instructions.  Used so ROB knows how many
 +     *  instructions to get from the rename instruction queue.
 +     */
 +    unsigned renameWidth;
 +
 +    /** IEW width, in instructions.  Used so ROB knows how many
 +     *  instructions to get from the IEW instruction queue.
 +     */
 +    unsigned iewWidth;
 +
 +    /** Commit width, in instructions. */
 +    unsigned commitWidth;
 +
 +    /** Number of Reorder Buffers */
 +    unsigned numRobs;
 +
 +    /** Number of Active Threads */
 +    unsigned numThreads;
 +
++    /** Is a switch out pending. */
 +    bool switchPending;
++
++    /** Is commit switched out. */
 +    bool switchedOut;
 +
++    /** The latency to handle a trap.  Used when scheduling trap
++     * squash event.
++     */
 +    Tick trapLatency;
 +
 +    Tick fetchTrapLatency;
 +
 +    Tick fetchFaultTick;
 +
++    /** The commit PC of each thread.  Refers to the instruction that
++     * is currently being processed/committed.
++     */
 +    Addr PC[Impl::MaxThreads];
 +
++    /** The next PC of each thread. */
 +    Addr nextPC[Impl::MaxThreads];
 +
 +    /** The sequence number of the youngest valid instruction in the ROB. */
 +    InstSeqNum youngestSeqNum[Impl::MaxThreads];
 +
 +    /** Pointer to the list of active threads. */
 +    std::list<unsigned> *activeThreads;
 +
 +    /** Rename map interface. */
 +    RenameMap *renameMap[Impl::MaxThreads];
 +
++    /** Updates commit stats based on this instruction. */
 +    void updateComInstStats(DynInstPtr &inst);
 +
 +    /** Stat for the total number of committed instructions. */
 +    Stats::Scalar<> commitCommittedInsts;
 +    /** Stat for the total number of squashed instructions discarded by commit.
 +     */
 +    Stats::Scalar<> commitSquashedInsts;
 +    /** Stat for the total number of times commit is told to squash.
 +     * @todo: Actually increment this stat.
 +     */
 +    Stats::Scalar<> commitSquashEvents;
 +    /** Stat for the total number of times commit has had to stall due to a non-
 +     * speculative instruction reaching the head of the ROB.
 +     */
 +    Stats::Scalar<> commitNonSpecStalls;
 +    /** Stat for the total number of branch mispredicts that caused a squash. */
 +    Stats::Scalar<> branchMispredicts;
 +    /** Distribution of the number of committed instructions each cycle. */
 +    Stats::Distribution<> numCommittedDist;
 +
 +    /** Total number of instructions committed. */
 +    Stats::Vector<> statComInst;
 +    /** Total number of software prefetches committed. */
 +    Stats::Vector<> statComSwp;
 +    /** Stat for the total number of committed memory references. */
 +    Stats::Vector<> statComRefs;
 +    /** Stat for the total number of committed loads. */
 +    Stats::Vector<> statComLoads;
 +    /** Total number of committed memory barriers. */
 +    Stats::Vector<> statComMembars;
 +    /** Total number of committed branches. */
 +    Stats::Vector<> statComBranches;
 +
++    /** Number of cycles where the commit bandwidth limit is reached. */
 +    Stats::Scalar<> commitEligibleSamples;
++    /** Number of instructions not committed due to bandwidth limits. */
 +    Stats::Vector<> commitEligible;
 +};
 +
 +#endif // __CPU_O3_COMMIT_HH__
index 9efe30d24328390c4a059141cc85e9dce7a6c265,0000000000000000000000000000000000000000..f8a252b87bbcb500ef55d3903804fd2878acfa62
mode 100644,000000..100644
--- /dev/null
@@@ -1,1308 -1,0 +1,1309 @@@
 +/*
 + * Copyright (c) 2004-2006 The Regents of The University of Michigan
 + * 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: Kevin Lim
 + */
 +
 +#include <algorithm>
 +#include <string>
 +
 +#include "base/loader/symtab.hh"
 +#include "base/timebuf.hh"
 +#include "cpu/checker/cpu.hh"
 +#include "cpu/exetrace.hh"
 +#include "cpu/o3/commit.hh"
 +#include "cpu/o3/thread_state.hh"
 +
 +using namespace std;
 +
 +template <class Impl>
 +DefaultCommit<Impl>::TrapEvent::TrapEvent(DefaultCommit<Impl> *_commit,
 +                                          unsigned _tid)
 +    : Event(&mainEventQueue, CPU_Tick_Pri), commit(_commit), tid(_tid)
 +{
 +    this->setFlags(Event::AutoDelete);
 +}
 +
 +template <class Impl>
 +void
 +DefaultCommit<Impl>::TrapEvent::process()
 +{
 +    // This will get reset by commit if it was switched out at the
 +    // time of this event processing.
 +    commit->trapSquash[tid] = true;
 +}
 +
 +template <class Impl>
 +const char *
 +DefaultCommit<Impl>::TrapEvent::description()
 +{
 +    return "Trap event";
 +}
 +
 +template <class Impl>
 +DefaultCommit<Impl>::DefaultCommit(Params *params)
 +    : squashCounter(0),
 +      iewToCommitDelay(params->iewToCommitDelay),
 +      commitToIEWDelay(params->commitToIEWDelay),
 +      renameToROBDelay(params->renameToROBDelay),
 +      fetchToCommitDelay(params->commitToFetchDelay),
 +      renameWidth(params->renameWidth),
 +      iewWidth(params->executeWidth),
 +      commitWidth(params->commitWidth),
 +      numThreads(params->numberOfThreads),
 +      switchedOut(false),
 +      trapLatency(params->trapLatency),
 +      fetchTrapLatency(params->fetchTrapLatency)
 +{
 +    _status = Active;
 +    _nextStatus = Inactive;
 +    string policy = params->smtCommitPolicy;
 +
 +    //Convert string to lowercase
 +    std::transform(policy.begin(), policy.end(), policy.begin(),
 +                   (int(*)(int)) tolower);
 +
 +    //Assign commit policy
 +    if (policy == "aggressive"){
 +        commitPolicy = Aggressive;
 +
 +        DPRINTF(Commit,"Commit Policy set to Aggressive.");
 +    } else if (policy == "roundrobin"){
 +        commitPolicy = RoundRobin;
 +
 +        //Set-Up Priority List
 +        for (int tid=0; tid < numThreads; tid++) {
 +            priority_list.push_back(tid);
 +        }
 +
 +        DPRINTF(Commit,"Commit Policy set to Round Robin.");
 +    } else if (policy == "oldestready"){
 +        commitPolicy = OldestReady;
 +
 +        DPRINTF(Commit,"Commit Policy set to Oldest Ready.");
 +    } else {
 +        assert(0 && "Invalid SMT Commit Policy. Options Are: {Aggressive,"
 +               "RoundRobin,OldestReady}");
 +    }
 +
 +    for (int i=0; i < numThreads; i++) {
 +        commitStatus[i] = Idle;
 +        changedROBNumEntries[i] = false;
 +        trapSquash[i] = false;
 +        xcSquash[i] = false;
 +    }
 +
 +    fetchFaultTick = 0;
 +    fetchTrapWait = 0;
 +}
 +
 +template <class Impl>
 +std::string
 +DefaultCommit<Impl>::name() const
 +{
 +    return cpu->name() + ".commit";
 +}
 +
 +template <class Impl>
 +void
 +DefaultCommit<Impl>::regStats()
 +{
 +    using namespace Stats;
 +    commitCommittedInsts
 +        .name(name() + ".commitCommittedInsts")
 +        .desc("The number of committed instructions")
 +        .prereq(commitCommittedInsts);
 +    commitSquashedInsts
 +        .name(name() + ".commitSquashedInsts")
 +        .desc("The number of squashed insts skipped by commit")
 +        .prereq(commitSquashedInsts);
 +    commitSquashEvents
 +        .name(name() + ".commitSquashEvents")
 +        .desc("The number of times commit is told to squash")
 +        .prereq(commitSquashEvents);
 +    commitNonSpecStalls
 +        .name(name() + ".commitNonSpecStalls")
 +        .desc("The number of times commit has been forced to stall to "
 +              "communicate backwards")
 +        .prereq(commitNonSpecStalls);
 +    branchMispredicts
 +        .name(name() + ".branchMispredicts")
 +        .desc("The number of times a branch was mispredicted")
 +        .prereq(branchMispredicts);
 +    numCommittedDist
 +        .init(0,commitWidth,1)
 +        .name(name() + ".COM:committed_per_cycle")
 +        .desc("Number of insts commited each cycle")
 +        .flags(Stats::pdf)
 +        ;
 +
 +    statComInst
 +        .init(cpu->number_of_threads)
 +        .name(name() + ".COM:count")
 +        .desc("Number of instructions committed")
 +        .flags(total)
 +        ;
 +
 +    statComSwp
 +        .init(cpu->number_of_threads)
 +        .name(name() + ".COM:swp_count")
 +        .desc("Number of s/w prefetches committed")
 +        .flags(total)
 +        ;
 +
 +    statComRefs
 +        .init(cpu->number_of_threads)
 +        .name(name() +  ".COM:refs")
 +        .desc("Number of memory references committed")
 +        .flags(total)
 +        ;
 +
 +    statComLoads
 +        .init(cpu->number_of_threads)
 +        .name(name() +  ".COM:loads")
 +        .desc("Number of loads committed")
 +        .flags(total)
 +        ;
 +
 +    statComMembars
 +        .init(cpu->number_of_threads)
 +        .name(name() +  ".COM:membars")
 +        .desc("Number of memory barriers committed")
 +        .flags(total)
 +        ;
 +
 +    statComBranches
 +        .init(cpu->number_of_threads)
 +        .name(name() + ".COM:branches")
 +        .desc("Number of branches committed")
 +        .flags(total)
 +        ;
 +
 +    //
 +    //  Commit-Eligible instructions...
 +    //
 +    //  -> The number of instructions eligible to commit in those
 +    //  cycles where we reached our commit BW limit (less the number
 +    //  actually committed)
 +    //
 +    //  -> The average value is computed over ALL CYCLES... not just
 +    //  the BW limited cycles
 +    //
 +    //  -> The standard deviation is computed only over cycles where
 +    //  we reached the BW limit
 +    //
 +    commitEligible
 +        .init(cpu->number_of_threads)
 +        .name(name() + ".COM:bw_limited")
 +        .desc("number of insts not committed due to BW limits")
 +        .flags(total)
 +        ;
 +
 +    commitEligibleSamples
 +        .name(name() + ".COM:bw_lim_events")
 +        .desc("number cycles where commit BW limit reached")
 +        ;
 +}
 +
 +template <class Impl>
 +void
 +DefaultCommit<Impl>::setCPU(FullCPU *cpu_ptr)
 +{
 +    DPRINTF(Commit, "Commit: Setting CPU pointer.\n");
 +    cpu = cpu_ptr;
 +
 +    // Commit must broadcast the number of free entries it has at the start of
 +    // the simulation, so it starts as active.
 +    cpu->activateStage(FullCPU::CommitIdx);
 +
 +    trapLatency = cpu->cycles(trapLatency);
 +    fetchTrapLatency = cpu->cycles(fetchTrapLatency);
 +}
 +
 +template <class Impl>
 +void
 +DefaultCommit<Impl>::setThreads(vector<Thread *> &threads)
 +{
 +    thread = threads;
 +}
 +
 +template <class Impl>
 +void
 +DefaultCommit<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr)
 +{
 +    DPRINTF(Commit, "Commit: Setting time buffer pointer.\n");
 +    timeBuffer = tb_ptr;
 +
 +    // Setup wire to send information back to IEW.
 +    toIEW = timeBuffer->getWire(0);
 +
 +    // Setup wire to read data from IEW (for the ROB).
 +    robInfoFromIEW = timeBuffer->getWire(-iewToCommitDelay);
 +}
 +
 +template <class Impl>
 +void
 +DefaultCommit<Impl>::setFetchQueue(TimeBuffer<FetchStruct> *fq_ptr)
 +{
 +    DPRINTF(Commit, "Commit: Setting fetch queue pointer.\n");
 +    fetchQueue = fq_ptr;
 +
 +    // Setup wire to get instructions from rename (for the ROB).
 +    fromFetch = fetchQueue->getWire(-fetchToCommitDelay);
 +}
 +
 +template <class Impl>
 +void
 +DefaultCommit<Impl>::setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr)
 +{
 +    DPRINTF(Commit, "Commit: Setting rename queue pointer.\n");
 +    renameQueue = rq_ptr;
 +
 +    // Setup wire to get instructions from rename (for the ROB).
 +    fromRename = renameQueue->getWire(-renameToROBDelay);
 +}
 +
 +template <class Impl>
 +void
 +DefaultCommit<Impl>::setIEWQueue(TimeBuffer<IEWStruct> *iq_ptr)
 +{
 +    DPRINTF(Commit, "Commit: Setting IEW queue pointer.\n");
 +    iewQueue = iq_ptr;
 +
 +    // Setup wire to get instructions from IEW.
 +    fromIEW = iewQueue->getWire(-iewToCommitDelay);
 +}
 +
 +template <class Impl>
 +void
 +DefaultCommit<Impl>::setFetchStage(Fetch *fetch_stage)
 +{
 +    fetchStage = fetch_stage;
 +}
 +
 +template <class Impl>
 +void
 +DefaultCommit<Impl>::setIEWStage(IEW *iew_stage)
 +{
 +    iewStage = iew_stage;
 +}
 +
 +template<class Impl>
 +void
 +DefaultCommit<Impl>::setActiveThreads(list<unsigned> *at_ptr)
 +{
 +    DPRINTF(Commit, "Commit: Setting active threads list pointer.\n");
 +    activeThreads = at_ptr;
 +}
 +
 +template <class Impl>
 +void
 +DefaultCommit<Impl>::setRenameMap(RenameMap rm_ptr[])
 +{
 +    DPRINTF(Commit, "Setting rename map pointers.\n");
 +
 +    for (int i=0; i < numThreads; i++) {
 +        renameMap[i] = &rm_ptr[i];
 +    }
 +}
 +
 +template <class Impl>
 +void
 +DefaultCommit<Impl>::setROB(ROB *rob_ptr)
 +{
 +    DPRINTF(Commit, "Commit: Setting ROB pointer.\n");
 +    rob = rob_ptr;
 +}
 +
 +template <class Impl>
 +void
 +DefaultCommit<Impl>::initStage()
 +{
 +    rob->setActiveThreads(activeThreads);
 +    rob->resetEntries();
 +
 +    // Broadcast the number of free entries.
 +    for (int i=0; i < numThreads; i++) {
 +        toIEW->commitInfo[i].usedROB = true;
 +        toIEW->commitInfo[i].freeROBEntries = rob->numFreeEntries(i);
 +    }
 +
 +    cpu->activityThisCycle();
 +}
 +
 +template <class Impl>
 +void
 +DefaultCommit<Impl>::switchOut()
 +{
 +    switchPending = true;
 +}
 +
 +template <class Impl>
 +void
 +DefaultCommit<Impl>::doSwitchOut()
 +{
 +    switchedOut = true;
 +    switchPending = false;
 +    rob->switchOut();
 +}
 +
 +template <class Impl>
 +void
 +DefaultCommit<Impl>::takeOverFrom()
 +{
 +    switchedOut = false;
 +    _status = Active;
 +    _nextStatus = Inactive;
 +    for (int i=0; i < numThreads; i++) {
 +        commitStatus[i] = Idle;
 +        changedROBNumEntries[i] = false;
 +        trapSquash[i] = false;
 +        xcSquash[i] = false;
 +    }
 +    squashCounter = 0;
 +    rob->takeOverFrom();
 +}
 +
 +template <class Impl>
 +void
 +DefaultCommit<Impl>::updateStatus()
 +{
 +    // reset ROB changed variable
 +    list<unsigned>::iterator threads = (*activeThreads).begin();
 +    while (threads != (*activeThreads).end()) {
 +        unsigned tid = *threads++;
 +        changedROBNumEntries[tid] = false;
 +
 +        // Also check if any of the threads has a trap pending
 +        if (commitStatus[tid] == TrapPending ||
 +            commitStatus[tid] == FetchTrapPending) {
 +            _nextStatus = Active;
 +        }
 +    }
 +
 +    if (_nextStatus == Inactive && _status == Active) {
 +        DPRINTF(Activity, "Deactivating stage.\n");
 +        cpu->deactivateStage(FullCPU::CommitIdx);
 +    } else if (_nextStatus == Active && _status == Inactive) {
 +        DPRINTF(Activity, "Activating stage.\n");
 +        cpu->activateStage(FullCPU::CommitIdx);
 +    }
 +
 +    _status = _nextStatus;
 +}
 +
 +template <class Impl>
 +void
 +DefaultCommit<Impl>::setNextStatus()
 +{
 +    int squashes = 0;
 +
 +    list<unsigned>::iterator threads = (*activeThreads).begin();
 +
 +    while (threads != (*activeThreads).end()) {
 +        unsigned tid = *threads++;
 +
 +        if (commitStatus[tid] == ROBSquashing) {
 +            squashes++;
 +        }
 +    }
 +
 +    assert(squashes == squashCounter);
 +
 +    // If commit is currently squashing, then it will have activity for the
 +    // next cycle. Set its next status as active.
 +    if (squashCounter) {
 +        _nextStatus = Active;
 +    }
 +}
 +
 +template <class Impl>
 +bool
 +DefaultCommit<Impl>::changedROBEntries()
 +{
 +    list<unsigned>::iterator threads = (*activeThreads).begin();
 +
 +    while (threads != (*activeThreads).end()) {
 +        unsigned tid = *threads++;
 +
 +        if (changedROBNumEntries[tid]) {
 +            return true;
 +        }
 +    }
 +
 +    return false;
 +}
 +
 +template <class Impl>
 +unsigned
 +DefaultCommit<Impl>::numROBFreeEntries(unsigned tid)
 +{
 +    return rob->numFreeEntries(tid);
 +}
 +
 +template <class Impl>
 +void
 +DefaultCommit<Impl>::generateTrapEvent(unsigned tid)
 +{
 +    DPRINTF(Commit, "Generating trap event for [tid:%i]\n", tid);
 +
 +    TrapEvent *trap = new TrapEvent(this, tid);
 +
 +    trap->schedule(curTick + trapLatency);
 +
 +    thread[tid]->trapPending = true;
 +}
 +
 +template <class Impl>
 +void
 +DefaultCommit<Impl>::generateXCEvent(unsigned tid)
 +{
 +    DPRINTF(Commit, "Generating XC squash event for [tid:%i]\n", tid);
 +
 +    xcSquash[tid] = true;
 +}
 +
 +template <class Impl>
 +void
 +DefaultCommit<Impl>::squashAll(unsigned tid)
 +{
 +    // If we want to include the squashing instruction in the squash,
 +    // then use one older sequence number.
 +    // Hopefully this doesn't mess things up.  Basically I want to squash
 +    // all instructions of this thread.
 +    InstSeqNum squashed_inst = rob->isEmpty() ?
 +        0 : rob->readHeadInst(tid)->seqNum - 1;;
 +
 +    // All younger instructions will be squashed. Set the sequence
 +    // number as the youngest instruction in the ROB (0 in this case.
 +    // Hopefully nothing breaks.)
 +    youngestSeqNum[tid] = 0;
 +
 +    rob->squash(squashed_inst, tid);
 +    changedROBNumEntries[tid] = true;
 +
 +    // Send back the sequence number of the squashed instruction.
 +    toIEW->commitInfo[tid].doneSeqNum = squashed_inst;
 +
 +    // Send back the squash signal to tell stages that they should
 +    // squash.
 +    toIEW->commitInfo[tid].squash = true;
 +
 +    // Send back the rob squashing signal so other stages know that
 +    // the ROB is in the process of squashing.
 +    toIEW->commitInfo[tid].robSquashing = true;
 +
 +    toIEW->commitInfo[tid].branchMispredict = false;
 +
 +    toIEW->commitInfo[tid].nextPC = PC[tid];
 +}
 +
 +template <class Impl>
 +void
 +DefaultCommit<Impl>::squashFromTrap(unsigned tid)
 +{
 +    squashAll(tid);
 +
 +    DPRINTF(Commit, "Squashing from trap, restarting at PC %#x\n", PC[tid]);
 +
 +    thread[tid]->trapPending = false;
 +    thread[tid]->inSyscall = false;
 +
 +    trapSquash[tid] = false;
 +
 +    commitStatus[tid] = ROBSquashing;
 +    cpu->activityThisCycle();
 +
 +    ++squashCounter;
 +}
 +
 +template <class Impl>
 +void
 +DefaultCommit<Impl>::squashFromXC(unsigned tid)
 +{
 +    squashAll(tid);
 +
 +    DPRINTF(Commit, "Squashing from XC, restarting at PC %#x\n", PC[tid]);
 +
 +    thread[tid]->inSyscall = false;
 +    assert(!thread[tid]->trapPending);
 +
 +    commitStatus[tid] = ROBSquashing;
 +    cpu->activityThisCycle();
 +
 +    xcSquash[tid] = false;
 +
 +    ++squashCounter;
 +}
 +
 +template <class Impl>
 +void
 +DefaultCommit<Impl>::tick()
 +{
 +    wroteToTimeBuffer = false;
 +    _nextStatus = Inactive;
 +
 +    if (switchPending && rob->isEmpty() && !iewStage->hasStoresToWB()) {
 +        cpu->signalSwitched();
 +        return;
 +    }
 +
 +    list<unsigned>::iterator threads = (*activeThreads).begin();
 +
 +    // Check if any of the threads are done squashing.  Change the
 +    // status if they are done.
 +    while (threads != (*activeThreads).end()) {
 +        unsigned tid = *threads++;
 +
 +        if (commitStatus[tid] == ROBSquashing) {
 +
 +            if (rob->isDoneSquashing(tid)) {
 +                commitStatus[tid] = Running;
 +                --squashCounter;
 +            } else {
 +                DPRINTF(Commit,"[tid:%u]: Still Squashing, cannot commit any"
 +                        "insts this cycle.\n", tid);
 +            }
 +        }
 +    }
 +
 +    commit();
 +
 +    markCompletedInsts();
 +
 +    threads = (*activeThreads).begin();
 +
 +    while (threads != (*activeThreads).end()) {
 +        unsigned tid = *threads++;
 +
 +        if (!rob->isEmpty(tid) && rob->readHeadInst(tid)->readyToCommit()) {
 +            // The ROB has more instructions it can commit. Its next status
 +            // will be active.
 +            _nextStatus = Active;
 +
 +            DynInstPtr inst = rob->readHeadInst(tid);
 +
 +            DPRINTF(Commit,"[tid:%i]: Instruction [sn:%lli] PC %#x is head of"
 +                    " ROB and ready to commit\n",
 +                    tid, inst->seqNum, inst->readPC());
 +
 +        } else if (!rob->isEmpty(tid)) {
 +            DynInstPtr inst = rob->readHeadInst(tid);
 +
 +            DPRINTF(Commit,"[tid:%i]: Can't commit, Instruction [sn:%lli] PC "
 +                    "%#x is head of ROB and not ready\n",
 +                    tid, inst->seqNum, inst->readPC());
 +        }
 +
 +        DPRINTF(Commit, "[tid:%i]: ROB has %d insts & %d free entries.\n",
 +                tid, rob->countInsts(tid), rob->numFreeEntries(tid));
 +    }
 +
 +
 +    if (wroteToTimeBuffer) {
 +        DPRINTF(Activity, "Activity This Cycle.\n");
 +        cpu->activityThisCycle();
 +    }
 +
 +    updateStatus();
 +}
 +
 +template <class Impl>
 +void
 +DefaultCommit<Impl>::commit()
 +{
 +
 +    //////////////////////////////////////
 +    // Check for interrupts
 +    //////////////////////////////////////
 +
 +#if FULL_SYSTEM
 +    // Process interrupts if interrupts are enabled, not in PAL mode,
 +    // and no other traps or external squashes are currently pending.
 +    // @todo: Allow other threads to handle interrupts.
 +    if (cpu->checkInterrupts &&
 +        cpu->check_interrupts() &&
 +        !cpu->inPalMode(readPC()) &&
 +        !trapSquash[0] &&
 +        !xcSquash[0]) {
 +        // Tell fetch that there is an interrupt pending.  This will
 +        // make fetch wait until it sees a non PAL-mode PC, at which
 +        // point it stops fetching instructions.
 +        toIEW->commitInfo[0].interruptPending = true;
 +
 +        // Wait until the ROB is empty and all stores have drained in
 +        // order to enter the interrupt.
 +        if (rob->isEmpty() && !iewStage->hasStoresToWB()) {
 +            // Not sure which thread should be the one to interrupt.  For now
 +            // always do thread 0.
 +            assert(!thread[0]->inSyscall);
 +            thread[0]->inSyscall = true;
 +
 +            // CPU will handle implementation of the interrupt.
 +            cpu->processInterrupts();
 +
 +            // Now squash or record that I need to squash this cycle.
 +            commitStatus[0] = TrapPending;
 +
 +            // Exit state update mode to avoid accidental updating.
 +            thread[0]->inSyscall = false;
 +
 +            // Generate trap squash event.
 +            generateTrapEvent(0);
 +
 +            toIEW->commitInfo[0].clearInterrupt = true;
 +
 +            DPRINTF(Commit, "Interrupt detected.\n");
 +        } else {
 +            DPRINTF(Commit, "Interrupt pending, waiting for ROB to empty.\n");
 +        }
 +    }
 +#endif // FULL_SYSTEM
 +
 +    ////////////////////////////////////
 +    // Check for any possible squashes, handle them first
 +    ////////////////////////////////////
 +
 +    list<unsigned>::iterator threads = (*activeThreads).begin();
 +
 +    while (threads != (*activeThreads).end()) {
 +        unsigned tid = *threads++;
++/*
 +        if (fromFetch->fetchFault && commitStatus[0] != TrapPending) {
 +            // Record the fault.  Wait until it's empty in the ROB.
 +            // Then handle the trap.  Ignore it if there's already a
 +            // trap pending as fetch will be redirected.
 +            fetchFault = fromFetch->fetchFault;
 +            fetchFaultTick = curTick + fetchTrapLatency;
 +            commitStatus[0] = FetchTrapPending;
 +            DPRINTF(Commit, "Fault from fetch recorded.  Will trap if the "
 +                    "ROB empties without squashing the fault.\n");
 +            fetchTrapWait = 0;
 +        }
 +
 +        // Fetch may tell commit to clear the trap if it's been squashed.
 +        if (fromFetch->clearFetchFault) {
 +            DPRINTF(Commit, "Received clear fetch fault signal\n");
 +            fetchTrapWait = 0;
 +            if (commitStatus[0] == FetchTrapPending) {
 +                DPRINTF(Commit, "Clearing fault from fetch\n");
 +                commitStatus[0] = Running;
 +            }
 +        }
-         commitEligible[0]++;
++*/
 +        // Not sure which one takes priority.  I think if we have
 +        // both, that's a bad sign.
 +        if (trapSquash[tid] == true) {
 +            assert(!xcSquash[tid]);
 +            squashFromTrap(tid);
 +        } else if (xcSquash[tid] == true) {
 +            squashFromXC(tid);
 +        }
 +
 +        // Squashed sequence number must be older than youngest valid
 +        // instruction in the ROB. This prevents squashes from younger
 +        // instructions overriding squashes from older instructions.
 +        if (fromIEW->squash[tid] &&
 +            commitStatus[tid] != TrapPending &&
 +            fromIEW->squashedSeqNum[tid] <= youngestSeqNum[tid]) {
 +
 +            DPRINTF(Commit, "[tid:%i]: Squashing due to PC %#x [sn:%i]\n",
 +                    tid,
 +                    fromIEW->mispredPC[tid],
 +                    fromIEW->squashedSeqNum[tid]);
 +
 +            DPRINTF(Commit, "[tid:%i]: Redirecting to PC %#x\n",
 +                    tid,
 +                    fromIEW->nextPC[tid]);
 +
 +            commitStatus[tid] = ROBSquashing;
 +
 +            ++squashCounter;
 +
 +            // If we want to include the squashing instruction in the squash,
 +            // then use one older sequence number.
 +            InstSeqNum squashed_inst = fromIEW->squashedSeqNum[tid];
 +
 +            if (fromIEW->includeSquashInst[tid] == true)
 +                squashed_inst--;
 +
 +            // All younger instructions will be squashed. Set the sequence
 +            // number as the youngest instruction in the ROB.
 +            youngestSeqNum[tid] = squashed_inst;
 +
 +            rob->squash(squashed_inst, tid);
 +            changedROBNumEntries[tid] = true;
 +
 +            toIEW->commitInfo[tid].doneSeqNum = squashed_inst;
 +
 +            toIEW->commitInfo[tid].squash = true;
 +
 +            // Send back the rob squashing signal so other stages know that
 +            // the ROB is in the process of squashing.
 +            toIEW->commitInfo[tid].robSquashing = true;
 +
 +            toIEW->commitInfo[tid].branchMispredict =
 +                fromIEW->branchMispredict[tid];
 +
 +            toIEW->commitInfo[tid].branchTaken =
 +                fromIEW->branchTaken[tid];
 +
 +            toIEW->commitInfo[tid].nextPC = fromIEW->nextPC[tid];
 +
 +            toIEW->commitInfo[tid].mispredPC = fromIEW->mispredPC[tid];
 +
 +            if (toIEW->commitInfo[tid].branchMispredict) {
 +                ++branchMispredicts;
 +            }
 +        }
 +
 +    }
 +
 +    setNextStatus();
 +
 +    if (squashCounter != numThreads) {
 +        // If we're not currently squashing, then get instructions.
 +        getInsts();
 +
 +        // Try to commit any instructions.
 +        commitInsts();
 +    }
 +
 +    //Check for any activity
 +    threads = (*activeThreads).begin();
 +
 +    while (threads != (*activeThreads).end()) {
 +        unsigned tid = *threads++;
 +
 +        if (changedROBNumEntries[tid]) {
 +            toIEW->commitInfo[tid].usedROB = true;
 +            toIEW->commitInfo[tid].freeROBEntries = rob->numFreeEntries(tid);
 +
 +            if (rob->isEmpty(tid)) {
 +                toIEW->commitInfo[tid].emptyROB = true;
 +            }
 +
 +            wroteToTimeBuffer = true;
 +            changedROBNumEntries[tid] = false;
 +        }
 +    }
 +}
 +
 +template <class Impl>
 +void
 +DefaultCommit<Impl>::commitInsts()
 +{
 +    ////////////////////////////////////
 +    // Handle commit
 +    // Note that commit will be handled prior to putting new
 +    // instructions in the ROB so that the ROB only tries to commit
 +    // instructions it has in this current cycle, and not instructions
 +    // it is writing in during this cycle.  Can't commit and squash
 +    // things at the same time...
 +    ////////////////////////////////////
 +
 +    DPRINTF(Commit, "Trying to commit instructions in the ROB.\n");
 +
 +    unsigned num_committed = 0;
 +
 +    DynInstPtr head_inst;
 +
 +    // Commit as many instructions as possible until the commit bandwidth
 +    // limit is reached, or it becomes impossible to commit any more.
 +    while (num_committed < commitWidth) {
 +        int commit_thread = getCommittingThread();
 +
 +        if (commit_thread == -1 || !rob->isHeadReady(commit_thread))
 +            break;
 +
 +        head_inst = rob->readHeadInst(commit_thread);
 +
 +        int tid = head_inst->threadNumber;
 +
 +        assert(tid == commit_thread);
 +
 +        DPRINTF(Commit, "Trying to commit head instruction, [sn:%i] [tid:%i]\n",
 +                head_inst->seqNum, tid);
 +
 +        // If the head instruction is squashed, it is ready to retire
 +        // (be removed from the ROB) at any time.
 +        if (head_inst->isSquashed()) {
 +
 +            DPRINTF(Commit, "Retiring squashed instruction from "
 +                    "ROB.\n");
 +
 +            rob->retireHead(commit_thread);
 +
 +            ++commitSquashedInsts;
 +
 +            // Record that the number of ROB entries has changed.
 +            changedROBNumEntries[tid] = true;
 +        } else {
 +            PC[tid] = head_inst->readPC();
 +            nextPC[tid] = head_inst->readNextPC();
 +
 +            // Increment the total number of non-speculative instructions
 +            // executed.
 +            // Hack for now: it really shouldn't happen until after the
 +            // commit is deemed to be successful, but this count is needed
 +            // for syscalls.
 +            thread[tid]->funcExeInst++;
 +
 +            // Try to commit the head instruction.
 +            bool commit_success = commitHead(head_inst, num_committed);
 +
 +            if (commit_success) {
 +                ++num_committed;
 +
 +                changedROBNumEntries[tid] = true;
 +
 +                // Set the doneSeqNum to the youngest committed instruction.
 +                toIEW->commitInfo[tid].doneSeqNum = head_inst->seqNum;
 +
 +                ++commitCommittedInsts;
 +
 +                // To match the old model, don't count nops and instruction
 +                // prefetches towards the total commit count.
 +                if (!head_inst->isNop() && !head_inst->isInstPrefetch()) {
 +                    cpu->instDone(tid);
 +                }
 +
 +                PC[tid] = nextPC[tid];
 +                nextPC[tid] = nextPC[tid] + sizeof(TheISA::MachInst);
 +#if FULL_SYSTEM
 +                int count = 0;
 +                Addr oldpc;
 +                do {
 +                    // Debug statement.  Checks to make sure we're not
 +                    // currently updating state while handling PC events.
 +                    if (count == 0)
 +                        assert(!thread[tid]->inSyscall &&
 +                               !thread[tid]->trapPending);
 +                    oldpc = PC[tid];
 +                    cpu->system->pcEventQueue.service(
 +                        thread[tid]->getXCProxy());
 +                    count++;
 +                } while (oldpc != PC[tid]);
 +                if (count > 1) {
 +                    DPRINTF(Commit, "PC skip function event, stopping commit\n");
 +                    break;
 +                }
 +#endif
 +            } else {
 +                DPRINTF(Commit, "Unable to commit head instruction PC:%#x "
 +                        "[tid:%i] [sn:%i].\n",
 +                        head_inst->readPC(), tid ,head_inst->seqNum);
 +                break;
 +            }
 +        }
 +    }
 +
 +    DPRINTF(CommitRate, "%i\n", num_committed);
 +    numCommittedDist.sample(num_committed);
 +
 +    if (num_committed == commitWidth) {
++        commitEligibleSamples++;
 +    }
 +}
 +
 +template <class Impl>
 +bool
 +DefaultCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num)
 +{
 +    assert(head_inst);
 +
 +    int tid = head_inst->threadNumber;
 +
 +    // If the instruction is not executed yet, then it will need extra
 +    // handling.  Signal backwards that it should be executed.
 +    if (!head_inst->isExecuted()) {
 +        // Keep this number correct.  We have not yet actually executed
 +        // and committed this instruction.
 +        thread[tid]->funcExeInst--;
 +
 +        head_inst->reachedCommit = true;
 +
 +        if (head_inst->isNonSpeculative() ||
++            head_inst->isStoreConditional() ||
 +            head_inst->isMemBarrier() ||
 +            head_inst->isWriteBarrier()) {
 +
 +            DPRINTF(Commit, "Encountered a barrier or non-speculative "
 +                    "instruction [sn:%lli] at the head of the ROB, PC %#x.\n",
 +                    head_inst->seqNum, head_inst->readPC());
 +
 +#if !FULL_SYSTEM
 +            // Hack to make sure syscalls/memory barriers/quiesces
 +            // aren't executed until all stores write back their data.
 +            // This direct communication shouldn't be used for
 +            // anything other than this.
 +            if (inst_num > 0 || iewStage->hasStoresToWB())
 +#else
 +            if ((head_inst->isMemBarrier() || head_inst->isWriteBarrier() ||
 +                    head_inst->isQuiesce()) &&
 +                iewStage->hasStoresToWB())
 +#endif
 +            {
 +                DPRINTF(Commit, "Waiting for all stores to writeback.\n");
 +                return false;
 +            }
 +
 +            toIEW->commitInfo[tid].nonSpecSeqNum = head_inst->seqNum;
 +
 +            // Change the instruction so it won't try to commit again until
 +            // it is executed.
 +            head_inst->clearCanCommit();
 +
 +            ++commitNonSpecStalls;
 +
 +            return false;
 +        } else if (head_inst->isLoad()) {
 +            DPRINTF(Commit, "[sn:%lli]: Uncached load, PC %#x.\n",
 +                    head_inst->seqNum, head_inst->readPC());
 +
 +            // Send back the non-speculative instruction's sequence
 +            // number.  Tell the lsq to re-execute the load.
 +            toIEW->commitInfo[tid].nonSpecSeqNum = head_inst->seqNum;
 +            toIEW->commitInfo[tid].uncached = true;
 +            toIEW->commitInfo[tid].uncachedLoad = head_inst;
 +
 +            head_inst->clearCanCommit();
 +
 +            return false;
 +        } else {
 +            panic("Trying to commit un-executed instruction "
 +                  "of unknown type!\n");
 +        }
 +    }
 +
 +    if (head_inst->isThreadSync()) {
 +        // Not handled for now.
 +        panic("Thread sync instructions are not handled yet.\n");
 +    }
 +
 +    // Stores mark themselves as completed.
 +    if (!head_inst->isStore()) {
 +        head_inst->setCompleted();
 +    }
 +
 +    // Use checker prior to updating anything due to traps or PC
 +    // based events.
 +    if (cpu->checker) {
 +        cpu->checker->tick(head_inst);
 +    }
 +
 +    // Check if the instruction caused a fault.  If so, trap.
 +    Fault inst_fault = head_inst->getFault();
 +
 +    if (inst_fault != NoFault) {
 +        head_inst->setCompleted();
 +#if FULL_SYSTEM
 +        DPRINTF(Commit, "Inst [sn:%lli] PC %#x has a fault\n",
 +                head_inst->seqNum, head_inst->readPC());
 +
 +        if (iewStage->hasStoresToWB() || inst_num > 0) {
 +            DPRINTF(Commit, "Stores outstanding, fault must wait.\n");
 +            return false;
 +        }
 +
 +        if (cpu->checker && head_inst->isStore()) {
 +            cpu->checker->tick(head_inst);
 +        }
 +
 +        assert(!thread[tid]->inSyscall);
 +
 +        // Mark that we're in state update mode so that the trap's
 +        // execution doesn't generate extra squashes.
 +        thread[tid]->inSyscall = true;
 +
 +        // DTB will sometimes need the machine instruction for when
 +        // faults happen.  So we will set it here, prior to the DTB
 +        // possibly needing it for its fault.
 +        thread[tid]->setInst(
 +            static_cast<TheISA::MachInst>(head_inst->staticInst->machInst));
 +
 +        // Execute the trap.  Although it's slightly unrealistic in
 +        // terms of timing (as it doesn't wait for the full timing of
 +        // the trap event to complete before updating state), it's
 +        // needed to update the state as soon as possible.  This
 +        // prevents external agents from changing any specific state
 +        // that the trap need.
 +        cpu->trap(inst_fault, tid);
 +
 +        // Exit state update mode to avoid accidental updating.
 +        thread[tid]->inSyscall = false;
 +
 +        commitStatus[tid] = TrapPending;
 +
 +        // Generate trap squash event.
 +        generateTrapEvent(tid);
 +
 +        return false;
 +#else // !FULL_SYSTEM
 +        panic("fault (%d) detected @ PC %08p", inst_fault,
 +              head_inst->PC);
 +#endif // FULL_SYSTEM
 +    }
 +
 +    updateComInstStats(head_inst);
 +
 +    if (head_inst->traceData) {
 +        head_inst->traceData->setFetchSeq(head_inst->seqNum);
 +        head_inst->traceData->setCPSeq(thread[tid]->numInst);
 +        head_inst->traceData->finalize();
 +        head_inst->traceData = NULL;
 +    }
 +
 +    // Update the commit rename map
 +    for (int i = 0; i < head_inst->numDestRegs(); i++) {
 +        renameMap[tid]->setEntry(head_inst->destRegIdx(i),
 +                                 head_inst->renamedDestRegIdx(i));
 +    }
 +
 +    // Finally clear the head ROB entry.
 +    rob->retireHead(tid);
 +
 +    // Return true to indicate that we have committed an instruction.
 +    return true;
 +}
 +
 +template <class Impl>
 +void
 +DefaultCommit<Impl>::getInsts()
 +{
 +    // Read any renamed instructions and place them into the ROB.
 +    int insts_to_process = min((int)renameWidth, fromRename->size);
 +
 +    for (int inst_num = 0; inst_num < insts_to_process; ++inst_num)
 +    {
 +        DynInstPtr inst = fromRename->insts[inst_num];
 +        int tid = inst->threadNumber;
 +
 +        if (!inst->isSquashed() &&
 +            commitStatus[tid] != ROBSquashing) {
 +            changedROBNumEntries[tid] = true;
 +
 +            DPRINTF(Commit, "Inserting PC %#x [sn:%i] [tid:%i] into ROB.\n",
 +                    inst->readPC(), inst->seqNum, tid);
 +
 +            rob->insertInst(inst);
 +
 +            assert(rob->getThreadEntries(tid) <= rob->getMaxEntries(tid));
 +
 +            youngestSeqNum[tid] = inst->seqNum;
 +        } else {
 +            DPRINTF(Commit, "Instruction PC %#x [sn:%i] [tid:%i] was "
 +                    "squashed, skipping.\n",
 +                    inst->readPC(), inst->seqNum, tid);
 +        }
 +    }
 +}
 +
 +template <class Impl>
 +void
 +DefaultCommit<Impl>::markCompletedInsts()
 +{
 +    // Grab completed insts out of the IEW instruction queue, and mark
 +    // instructions completed within the ROB.
 +    for (int inst_num = 0;
 +         inst_num < fromIEW->size && fromIEW->insts[inst_num];
 +         ++inst_num)
 +    {
 +        if (!fromIEW->insts[inst_num]->isSquashed()) {
 +            DPRINTF(Commit, "[tid:%i]: Marking PC %#x, [sn:%lli] ready "
 +                    "within ROB.\n",
 +                    fromIEW->insts[inst_num]->threadNumber,
 +                    fromIEW->insts[inst_num]->readPC(),
 +                    fromIEW->insts[inst_num]->seqNum);
 +
 +            // Mark the instruction as ready to commit.
 +            fromIEW->insts[inst_num]->setCanCommit();
 +        }
 +    }
 +}
 +
 +template <class Impl>
 +bool
 +DefaultCommit<Impl>::robDoneSquashing()
 +{
 +    list<unsigned>::iterator threads = (*activeThreads).begin();
 +
 +    while (threads != (*activeThreads).end()) {
 +        unsigned tid = *threads++;
 +
 +        if (!rob->isDoneSquashing(tid))
 +            return false;
 +    }
 +
 +    return true;
 +}
 +
 +template <class Impl>
 +void
 +DefaultCommit<Impl>::updateComInstStats(DynInstPtr &inst)
 +{
 +    unsigned thread = inst->threadNumber;
 +
 +    //
 +    //  Pick off the software prefetches
 +    //
 +#ifdef TARGET_ALPHA
 +    if (inst->isDataPrefetch()) {
 +        statComSwp[thread]++;
 +    } else {
 +        statComInst[thread]++;
 +    }
 +#else
 +    statComInst[thread]++;
 +#endif
 +
 +    //
 +    //  Control Instructions
 +    //
 +    if (inst->isControl())
 +        statComBranches[thread]++;
 +
 +    //
 +    //  Memory references
 +    //
 +    if (inst->isMemRef()) {
 +        statComRefs[thread]++;
 +
 +        if (inst->isLoad()) {
 +            statComLoads[thread]++;
 +        }
 +    }
 +
 +    if (inst->isMemBarrier()) {
 +        statComMembars[thread]++;
 +    }
 +}
 +
 +////////////////////////////////////////
 +//                                    //
 +//  SMT COMMIT POLICY MAINTAINED HERE //
 +//                                    //
 +////////////////////////////////////////
 +template <class Impl>
 +int
 +DefaultCommit<Impl>::getCommittingThread()
 +{
 +    if (numThreads > 1) {
 +        switch (commitPolicy) {
 +
 +          case Aggressive:
 +            //If Policy is Aggressive, commit will call
 +            //this function multiple times per
 +            //cycle
 +            return oldestReady();
 +
 +          case RoundRobin:
 +            return roundRobin();
 +
 +          case OldestReady:
 +            return oldestReady();
 +
 +          default:
 +            return -1;
 +        }
 +    } else {
 +        int tid = (*activeThreads).front();
 +
 +        if (commitStatus[tid] == Running ||
 +            commitStatus[tid] == Idle ||
 +            commitStatus[tid] == FetchTrapPending) {
 +            return tid;
 +        } else {
 +            return -1;
 +        }
 +    }
 +}
 +
 +template<class Impl>
 +int
 +DefaultCommit<Impl>::roundRobin()
 +{
 +    list<unsigned>::iterator pri_iter = priority_list.begin();
 +    list<unsigned>::iterator end      = priority_list.end();
 +
 +    while (pri_iter != end) {
 +        unsigned tid = *pri_iter;
 +
 +        if (commitStatus[tid] == Running ||
 +            commitStatus[tid] == Idle) {
 +
 +            if (rob->isHeadReady(tid)) {
 +                priority_list.erase(pri_iter);
 +                priority_list.push_back(tid);
 +
 +                return tid;
 +            }
 +        }
 +
 +        pri_iter++;
 +    }
 +
 +    return -1;
 +}
 +
 +template<class Impl>
 +int
 +DefaultCommit<Impl>::oldestReady()
 +{
 +    unsigned oldest = 0;
 +    bool first = true;
 +
 +    list<unsigned>::iterator threads = (*activeThreads).begin();
 +
 +    while (threads != (*activeThreads).end()) {
 +        unsigned tid = *threads++;
 +
 +        if (!rob->isEmpty(tid) &&
 +            (commitStatus[tid] == Running ||
 +             commitStatus[tid] == Idle ||
 +             commitStatus[tid] == FetchTrapPending)) {
 +
 +            if (rob->isHeadReady(tid)) {
 +
 +                DynInstPtr head_inst = rob->readHeadInst(tid);
 +
 +                if (first) {
 +                    oldest = tid;
 +                    first = false;
 +                } else if (head_inst->seqNum < oldest) {
 +                    oldest = tid;
 +                }
 +            }
 +        }
 +    }
 +
 +    if (!first) {
 +        return oldest;
 +    } else {
 +        return -1;
 +    }
 +}
index 51fcb1adbb00587ff79de27d34f4ab1b921807b8,0000000000000000000000000000000000000000..c2c5289bf9c73c5512ea3535dc1ca8658ca9287e
mode 100644,000000..100644
--- /dev/null
@@@ -1,525 -1,0 +1,544 @@@
-     /** Check if there are any system calls pending. */
-     void checkSyscalls();
-     /** Switches out this CPU.
-      */
 +/*
 + * Copyright (c) 2004-2005 The Regents of The University of Michigan
 + * 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: Kevin Lim
 + */
 +
 +#ifndef __CPU_O3_CPU_HH__
 +#define __CPU_O3_CPU_HH__
 +
 +#include <iostream>
 +#include <list>
 +#include <queue>
 +#include <set>
 +#include <vector>
 +
 +#include "arch/isa_traits.hh"
 +#include "base/statistics.hh"
 +#include "base/timebuf.hh"
 +#include "config/full_system.hh"
 +#include "cpu/activity.hh"
 +#include "cpu/base.hh"
 +#include "cpu/cpu_exec_context.hh"
 +#include "cpu/o3/comm.hh"
 +#include "cpu/o3/cpu_policy.hh"
 +#include "cpu/o3/scoreboard.hh"
 +#include "cpu/o3/thread_state.hh"
 +#include "sim/process.hh"
 +
 +template <class>
 +class Checker;
 +class ExecContext;
 +class MemObject;
 +class Process;
 +
 +class BaseFullCPU : public BaseCPU
 +{
 +    //Stuff that's pretty ISA independent will go here.
 +  public:
 +    typedef BaseCPU::Params Params;
 +
 +    BaseFullCPU(Params *params);
 +
 +    void regStats();
 +
 +    int readCpuId() { return cpu_id; }
 +
 +  protected:
 +    int cpu_id;
 +};
 +
++/**
++ * FullO3CPU class, has each of the stages (fetch through commit)
++ * within it, as well as all of the time buffers between stages.  The
++ * tick() function for the CPU is defined here.
++ */
 +template <class Impl>
 +class FullO3CPU : public BaseFullCPU
 +{
 +  public:
 +    typedef TheISA::FloatReg FloatReg;
 +    typedef TheISA::FloatRegBits FloatRegBits;
 +
 +    // Typedefs from the Impl here.
 +    typedef typename Impl::CPUPol CPUPolicy;
 +    typedef typename Impl::Params Params;
 +    typedef typename Impl::DynInstPtr DynInstPtr;
 +
 +    typedef O3ThreadState<Impl> Thread;
 +
 +    typedef typename std::list<DynInstPtr>::iterator ListIt;
 +
 +  public:
 +    enum Status {
 +        Running,
 +        Idle,
 +        Halted,
 +        Blocked,
 +        SwitchedOut
 +    };
 +
 +    /** Overall CPU status. */
 +    Status _status;
 +
 +  private:
 +    class TickEvent : public Event
 +    {
 +      private:
 +        /** Pointer to the CPU. */
 +        FullO3CPU<Impl> *cpu;
 +
 +      public:
 +        /** Constructs a tick event. */
 +        TickEvent(FullO3CPU<Impl> *c);
 +
 +        /** Processes a tick event, calling tick() on the CPU. */
 +        void process();
 +        /** Returns the description of the tick event. */
 +        const char *description();
 +    };
 +
 +    /** The tick event used for scheduling CPU ticks. */
 +    TickEvent tickEvent;
 +
 +    /** Schedule tick event, regardless of its current state. */
 +    void scheduleTickEvent(int delay)
 +    {
 +        if (tickEvent.squashed())
 +            tickEvent.reschedule(curTick + cycles(delay));
 +        else if (!tickEvent.scheduled())
 +            tickEvent.schedule(curTick + cycles(delay));
 +    }
 +
 +    /** Unschedule tick event, regardless of its current state. */
 +    void unscheduleTickEvent()
 +    {
 +        if (tickEvent.scheduled())
 +            tickEvent.squash();
 +    }
 +
 +  public:
 +    /** Constructs a CPU with the given parameters. */
 +    FullO3CPU(Params *params);
 +    /** Destructor. */
 +    ~FullO3CPU();
 +
 +    /** Registers statistics. */
 +    void fullCPURegStats();
 +
 +    /** Ticks CPU, calling tick() on each stage, and checking the overall
 +     *  activity to see if the CPU should deschedule itself.
 +     */
 +    void tick();
 +
 +    /** Initialize the CPU */
 +    void init();
 +
 +    /** Setup CPU to insert a thread's context */
 +    void insertThread(unsigned tid);
 +
 +    /** Remove all of a thread's context from CPU */
 +    void removeThread(unsigned tid);
 +
 +    /** Count the Total Instructions Committed in the CPU. */
 +    virtual Counter totalInstructions() const
 +    {
 +        Counter total(0);
 +
 +        for (int i=0; i < thread.size(); i++)
 +            total += thread[i]->numInst;
 +
 +        return total;
 +    }
 +
 +    /** Add Thread to Active Threads List. */
 +    void activateContext(int tid, int delay);
 +
 +    /** Remove Thread from Active Threads List */
 +    void suspendContext(int tid);
 +
 +    /** Remove Thread from Active Threads List &&
 +     *  Remove Thread Context from CPU.
 +     */
 +    void deallocateContext(int tid);
 +
 +    /** Remove Thread from Active Threads List &&
 +     *  Remove Thread Context from CPU.
 +     */
 +    void haltContext(int tid);
 +
 +    /** Activate a Thread When CPU Resources are Available. */
 +    void activateWhenReady(int tid);
 +
 +    /** Add or Remove a Thread Context in the CPU. */
 +    void doContextSwitch();
 +
 +    /** Update The Order In Which We Process Threads. */
 +    void updateThreadPriority();
 +
 +    /** Executes a syscall on this cycle.
 +     *  ---------------------------------------
 +     *  Note: this is a virtual function. CPU-Specific
 +     *  functionality defined in derived classes
 +     */
 +    virtual void syscall(int tid) { panic("Unimplemented!"); }
 +
-     /** Takes over from another CPU.
-      */
++    /** Switches out this CPU. */
 +    void switchOut(Sampler *sampler);
 +
++    /** Signals to this CPU that a stage has completed switching out. */
 +    void signalSwitched();
 +
-     //
-     // New accessors for new decoder.
-     //
++    /** Takes over from another CPU. */
 +    void takeOverFrom(BaseCPU *oldCPU);
 +
 +    /** Get the current instruction sequence number, and increment it. */
 +    InstSeqNum getAndIncrementInstSeq()
 +    { return globalSeqNum++; }
 +
 +#if FULL_SYSTEM
 +    /** Check if this address is a valid instruction address. */
 +    bool validInstAddr(Addr addr) { return true; }
 +
 +    /** Check if this address is a valid data address. */
 +    bool validDataAddr(Addr addr) { return true; }
 +
 +    /** Get instruction asid. */
 +    int getInstAsid(unsigned tid)
 +    { return regFile.miscRegs[tid].getInstAsid(); }
 +
 +    /** Get data asid. */
 +    int getDataAsid(unsigned tid)
 +    { return regFile.miscRegs[tid].getDataAsid(); }
 +#else
 +    /** Get instruction asid. */
 +    int getInstAsid(unsigned tid)
 +    { return thread[tid]->asid; }
 +
 +    /** Get data asid. */
 +    int getDataAsid(unsigned tid)
 +    { return thread[tid]->asid; }
 +
 +#endif
 +
-     void setPC(Addr new_PC,unsigned tid);
++    /** Register accessors.  Index refers to the physical register index. */
 +    uint64_t readIntReg(int reg_idx);
 +
 +    FloatReg readFloatReg(int reg_idx);
 +
 +    FloatReg readFloatReg(int reg_idx, int width);
 +
 +    FloatRegBits readFloatRegBits(int reg_idx);
 +
 +    FloatRegBits readFloatRegBits(int reg_idx, int width);
 +
 +    void setIntReg(int reg_idx, uint64_t val);
 +
 +    void setFloatReg(int reg_idx, FloatReg val);
 +
 +    void setFloatReg(int reg_idx, FloatReg val, int width);
 +
 +    void setFloatRegBits(int reg_idx, FloatRegBits val);
 +
 +    void setFloatRegBits(int reg_idx, FloatRegBits val, int width);
 +
 +    uint64_t readArchIntReg(int reg_idx, unsigned tid);
 +
 +    float readArchFloatRegSingle(int reg_idx, unsigned tid);
 +
 +    double readArchFloatRegDouble(int reg_idx, unsigned tid);
 +
 +    uint64_t readArchFloatRegInt(int reg_idx, unsigned tid);
 +
++    /** Architectural register accessors.  Looks up in the commit
++     * rename table to obtain the true physical index of the
++     * architected register first, then accesses that physical
++     * register.
++     */
 +    void setArchIntReg(int reg_idx, uint64_t val, unsigned tid);
 +
 +    void setArchFloatRegSingle(int reg_idx, float val, unsigned tid);
 +
 +    void setArchFloatRegDouble(int reg_idx, double val, unsigned tid);
 +
 +    void setArchFloatRegInt(int reg_idx, uint64_t val, unsigned tid);
 +
++    /** Reads the commit PC of a specific thread. */
 +    uint64_t readPC(unsigned tid);
 +
-     void setNextPC(uint64_t val,unsigned tid);
++    /** Sets the commit PC of a specific thread. */
++    void setPC(Addr new_PC, unsigned tid);
 +
++    /** Reads the next PC of a specific thread. */
 +    uint64_t readNextPC(unsigned tid);
 +
-     /** Remove all instructions from the list. */
- //    void removeAllInsts();
++    /** Sets the next PC of a specific thread. */
++    void setNextPC(uint64_t val, unsigned tid);
 +
 +    /** Function to add instruction onto the head of the list of the
 +     *  instructions.  Used when new instructions are fetched.
 +     */
 +    ListIt addInst(DynInstPtr &inst);
 +
 +    /** Function to tell the CPU that an instruction has completed. */
 +    void instDone(unsigned tid);
 +
 +    /** Add Instructions to the CPU Remove List*/
 +    void addToRemoveList(DynInstPtr &inst);
 +
 +    /** Remove an instruction from the front end of the list.  There's
 +     *  no restriction on location of the instruction.
 +     */
 +    void removeFrontInst(DynInstPtr &inst);
 +
 +    /** Remove all instructions that are not currently in the ROB. */
 +    void removeInstsNotInROB(unsigned tid);
 +
 +    /** Remove all instructions younger than the given sequence number. */
 +    void removeInstsUntil(const InstSeqNum &seq_num,unsigned tid);
 +
++    /** Removes the instruction pointed to by the iterator. */
 +    inline void squashInstIt(const ListIt &instIt, const unsigned &tid);
 +
++    /** Cleans up all instructions on the remove list. */
 +    void cleanUpRemovedInsts();
 +
-     /** Basically a wrapper function so that instructions executed at
-      *  commit can tell the instruction queue that they have
-      *  completed.  Eventually this hack should be removed.
-      */
- //    void wakeDependents(DynInstPtr &inst);
++    /** Debug function to print all instructions on the list. */
 +    void dumpInsts();
 +
-   public:
 +  public:
 +    /** List of all the instructions in flight. */
 +    std::list<DynInstPtr> instList;
 +
 +    /** List of all the instructions that will be removed at the end of this
 +     *  cycle.
 +     */
 +    std::queue<ListIt> removeList;
 +
 +#ifdef DEBUG
++    /** Debug structure to keep track of the sequence numbers still in
++     * flight.
++     */
 +    std::set<InstSeqNum> snList;
 +#endif
 +
 +    /** Records if instructions need to be removed this cycle due to
 +     *  being retired or squashed.
 +     */
 +    bool removeInstsThisCycle;
 +
 +  protected:
 +    /** The fetch stage. */
 +    typename CPUPolicy::Fetch fetch;
 +
 +    /** The decode stage. */
 +    typename CPUPolicy::Decode decode;
 +
 +    /** The dispatch stage. */
 +    typename CPUPolicy::Rename rename;
 +
 +    /** The issue/execute/writeback stages. */
 +    typename CPUPolicy::IEW iew;
 +
 +    /** The commit stage. */
 +    typename CPUPolicy::Commit commit;
 +
 +    /** The register file. */
 +    typename CPUPolicy::RegFile regFile;
 +
 +    /** The free list. */
 +    typename CPUPolicy::FreeList freeList;
 +
 +    /** The rename map. */
 +    typename CPUPolicy::RenameMap renameMap[Impl::MaxThreads];
 +
 +    /** The commit rename map. */
 +    typename CPUPolicy::RenameMap commitRenameMap[Impl::MaxThreads];
 +
 +    /** The re-order buffer. */
 +    typename CPUPolicy::ROB rob;
 +
 +    /** Active Threads List */
 +    std::list<unsigned> activeThreads;
 +
 +    /** Integer Register Scoreboard */
 +    Scoreboard scoreboard;
 +
 +  public:
 +    /** Enum to give each stage a specific index, so when calling
 +     *  activateStage() or deactivateStage(), they can specify which stage
 +     *  is being activated/deactivated.
 +     */
 +    enum StageIdx {
 +        FetchIdx,
 +        DecodeIdx,
 +        RenameIdx,
 +        IEWIdx,
 +        CommitIdx,
 +        NumStages };
 +
 +    /** Typedefs from the Impl to get the structs that each of the
 +     *  time buffers should use.
 +     */
 +    typedef typename CPUPolicy::TimeStruct TimeStruct;
 +
 +    typedef typename CPUPolicy::FetchStruct FetchStruct;
 +
 +    typedef typename CPUPolicy::DecodeStruct DecodeStruct;
 +
 +    typedef typename CPUPolicy::RenameStruct RenameStruct;
 +
 +    typedef typename CPUPolicy::IEWStruct IEWStruct;
 +
 +    /** The main time buffer to do backwards communication. */
 +    TimeBuffer<TimeStruct> timeBuffer;
 +
 +    /** The fetch stage's instruction queue. */
 +    TimeBuffer<FetchStruct> fetchQueue;
 +
 +    /** The decode stage's instruction queue. */
 +    TimeBuffer<DecodeStruct> decodeQueue;
 +
 +    /** The rename stage's instruction queue. */
 +    TimeBuffer<RenameStruct> renameQueue;
 +
 +    /** The IEW stage's instruction queue. */
 +    TimeBuffer<IEWStruct> iewQueue;
 +
-     /** Temporary function to get pointer to exec context. */
++  private:
++    /** The activity recorder; used to tell if the CPU has any
++     * activity remaining or if it can go to idle and deschedule
++     * itself.
++     */
 +    ActivityRecorder activityRec;
 +
++  public:
++    /** Records that there was time buffer activity this cycle. */
 +    void activityThisCycle() { activityRec.activity(); }
 +
++    /** Changes a stage's status to active within the activity recorder. */
 +    void activateStage(const StageIdx idx)
 +    { activityRec.activateStage(idx); }
 +
++    /** Changes a stage's status to inactive within the activity recorder. */
 +    void deactivateStage(const StageIdx idx)
 +    { activityRec.deactivateStage(idx); }
 +
 +    /** Wakes the CPU, rescheduling the CPU if it's not already active. */
 +    void wakeCPU();
 +
 +    /** Gets a free thread id. Use if thread ids change across system. */
 +    int getFreeTid();
 +
 +  public:
-     // List of all ExecContexts.
++    /** Returns a pointer to a thread's exec context. */
 +    ExecContext *xcBase(unsigned tid)
 +    {
 +        return thread[tid]->getXCProxy();
 +    }
 +
 +    /** The global sequence number counter. */
 +    InstSeqNum globalSeqNum;
 +
++    /** Pointer to the checker, which can dynamically verify
++     * instruction results at run time.  This can be set to NULL if it
++     * is not being used.
++     */
 +    Checker<DynInstPtr> *checker;
 +
 +#if FULL_SYSTEM
 +    /** Pointer to the system. */
 +    System *system;
 +
 +    /** Pointer to the memory controller. */
 +    MemoryController *memCtrl;
 +    /** Pointer to physical memory. */
 +    PhysicalMemory *physmem;
 +#endif
 +
 +    /** Pointer to memory. */
 +    MemObject *mem;
 +
++    /** Pointer to the sampler */
 +    Sampler *sampler;
 +
++    /** Counter of how many stages have completed switching out. */
 +    int switchCount;
 +
++    /** Pointers to all of the threads in the CPU. */
 +    std::vector<Thread *> thread;
 +
 +#if 0
 +    /** Page table pointer. */
 +    PageTable *pTable;
 +#endif
 +
 +    /** Pointer to the icache interface. */
 +    MemInterface *icacheInterface;
 +    /** Pointer to the dcache interface. */
 +    MemInterface *dcacheInterface;
 +
 +    /** Whether or not the CPU should defer its registration. */
 +    bool deferRegistration;
 +
 +    /** Is there a context switch pending? */
 +    bool contextSwitch;
 +
 +    /** Threads Scheduled to Enter CPU */
 +    std::list<int> cpuWaitList;
 +
 +    /** The cycle that the CPU was last running, used for statistics. */
 +    Tick lastRunningCycle;
 +
 +    /** Number of Threads CPU can process */
 +    unsigned numThreads;
 +
 +    /** Mapping for system thread id to cpu id */
 +    std::map<unsigned,unsigned> threadMap;
 +
 +    /** Available thread ids in the cpu*/
 +    std::vector<unsigned> tids;
 +
 +    /** Stat for total number of times the CPU is descheduled. */
 +    Stats::Scalar<> timesIdled;
 +    /** Stat for total number of cycles the CPU spends descheduled. */
 +    Stats::Scalar<> idleCycles;
 +    /** Stat for the number of committed instructions per thread. */
 +    Stats::Vector<> committedInsts;
 +    /** Stat for the total number of committed instructions. */
 +    Stats::Scalar<> totalCommittedInsts;
 +    /** Stat for the CPI per thread. */
 +    Stats::Formula cpi;
 +    /** Stat for the total CPI. */
 +    Stats::Formula totalCpi;
 +    /** Stat for the IPC per thread. */
 +    Stats::Formula ipc;
 +    /** Stat for the total IPC. */
 +    Stats::Formula totalIpc;
 +};
 +
 +#endif // __CPU_O3_CPU_HH__
index 4ea4daee6b7cb7a51c3315536ee6647b83f477e3,0000000000000000000000000000000000000000..32a0adcf1de2847a9742de3ed8a9eeb8584bb54e
mode 100644,000000..100644
--- /dev/null
@@@ -1,93 -1,0 +1,119 @@@
-     typedef TwobitBPredUnit<Impl> BPredUnit;
 +/*
 + * Copyright (c) 2004-2005 The Regents of The University of Michigan
 + * 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: Kevin Lim
 + */
 +
 +#ifndef __CPU_O3_CPU_POLICY_HH__
 +#define __CPU_O3_CPU_POLICY_HH__
 +
 +#include "cpu/o3/bpred_unit.hh"
 +#include "cpu/o3/free_list.hh"
 +#include "cpu/o3/inst_queue.hh"
 +#include "cpu/o3/lsq.hh"
 +#include "cpu/o3/lsq_unit.hh"
 +#include "cpu/o3/mem_dep_unit.hh"
 +#include "cpu/o3/regfile.hh"
 +#include "cpu/o3/rename_map.hh"
 +#include "cpu/o3/rob.hh"
 +#include "cpu/o3/store_set.hh"
 +
 +#include "cpu/o3/commit.hh"
 +#include "cpu/o3/decode.hh"
 +#include "cpu/o3/fetch.hh"
 +#include "cpu/o3/iew.hh"
 +#include "cpu/o3/rename.hh"
 +
 +#include "cpu/o3/comm.hh"
 +
++/**
++ * Struct that defines the key classes to be used by the CPU.  All
++ * classes use the typedefs defined here to determine what are the
++ * classes of the other stages and communication buffers.  In order to
++ * change a structure such as the IQ, simply change the typedef here
++ * to use the desired class instead, and recompile.  In order to
++ * create a different CPU to be used simultaneously with this one, see
++ * the alpha_impl.hh file for instructions.
++ */
 +template<class Impl>
 +struct SimpleCPUPolicy
 +{
++    /** Typedef for the branch prediction unit (which includes the BP,
++     * RAS, and BTB).
++     */
++    typedef BPredUnit<Impl> BPredUnit;
++    /** Typedef for the register file.  Most classes assume a unified
++     * physical register file.
++     */
 +    typedef PhysRegFile<Impl> RegFile;
++    /** Typedef for the freelist of registers. */
 +    typedef SimpleFreeList FreeList;
++    /** Typedef for the rename map. */
 +    typedef SimpleRenameMap RenameMap;
++    /** Typedef for the ROB. */
 +    typedef ROB<Impl> ROB;
++    /** Typedef for the instruction queue/scheduler. */
 +    typedef InstructionQueue<Impl> IQ;
++    /** Typedef for the memory dependence unit. */
 +    typedef MemDepUnit<StoreSet, Impl> MemDepUnit;
++    /** Typedef for the LSQ. */
 +    typedef LSQ<Impl> LSQ;
++    /** Typedef for the thread-specific LSQ units. */
 +    typedef LSQUnit<Impl> LSQUnit;
 +
++    /** Typedef for fetch. */
 +    typedef DefaultFetch<Impl> Fetch;
++    /** Typedef for decode. */
 +    typedef DefaultDecode<Impl> Decode;
++    /** Typedef for rename. */
 +    typedef DefaultRename<Impl> Rename;
++    /** Typedef for Issue/Execute/Writeback. */
 +    typedef DefaultIEW<Impl> IEW;
++    /** Typedef for commit. */
 +    typedef DefaultCommit<Impl> Commit;
 +
 +    /** The struct for communication between fetch and decode. */
 +    typedef DefaultFetchDefaultDecode<Impl> FetchStruct;
 +
 +    /** The struct for communication between decode and rename. */
 +    typedef DefaultDecodeDefaultRename<Impl> DecodeStruct;
 +
 +    /** The struct for communication between rename and IEW. */
 +    typedef DefaultRenameDefaultIEW<Impl> RenameStruct;
 +
 +    /** The struct for communication between IEW and commit. */
 +    typedef DefaultIEWDefaultCommit<Impl> IEWStruct;
 +
 +    /** The struct for communication within the IEW stage. */
 +    typedef IssueStruct<Impl> IssueStruct;
 +
 +    /** The struct for all backwards communication. */
 +    typedef TimeBufStruct<Impl> TimeStruct;
 +
 +};
 +
 +#endif //__CPU_O3_CPU_POLICY_HH__
index 8abe1d480d642f2dab6812fb75b42314a799d1ab,0000000000000000000000000000000000000000..ff88358d6262c904b7ebdca65db8787808c7e2b1
mode 100644,000000..100644
--- /dev/null
@@@ -1,294 -1,0 +1,297 @@@
 +/*
 + * Copyright (c) 2004-2006 The Regents of The University of Michigan
 + * 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: Kevin Lim
 + */
 +
 +#ifndef __CPU_O3_DECODE_HH__
 +#define __CPU_O3_DECODE_HH__
 +
 +#include <queue>
 +
 +#include "base/statistics.hh"
 +#include "base/timebuf.hh"
 +
 +/**
 + * DefaultDecode class handles both single threaded and SMT
 + * decode. Its width is specified by the parameters; each cycles it
 + * tries to decode that many instructions. Because instructions are
 + * actually decoded when the StaticInst is created, this stage does
 + * not do much other than check any PC-relative branches.
 + */
 +template<class Impl>
 +class DefaultDecode
 +{
 +  private:
 +    // Typedefs from the Impl.
 +    typedef typename Impl::FullCPU FullCPU;
 +    typedef typename Impl::DynInstPtr DynInstPtr;
 +    typedef typename Impl::Params Params;
 +    typedef typename Impl::CPUPol CPUPol;
 +
 +    // Typedefs from the CPU policy.
 +    typedef typename CPUPol::FetchStruct FetchStruct;
 +    typedef typename CPUPol::DecodeStruct DecodeStruct;
 +    typedef typename CPUPol::TimeStruct TimeStruct;
 +
 +  public:
 +    /** Overall decode stage status. Used to determine if the CPU can
 +     * deschedule itself due to a lack of activity.
 +     */
 +    enum DecodeStatus {
 +        Active,
 +        Inactive
 +    };
 +
 +    /** Individual thread status. */
 +    enum ThreadStatus {
 +        Running,
 +        Idle,
 +        StartSquash,
 +        Squashing,
 +        Blocked,
 +        Unblocking
 +    };
 +
 +  private:
 +    /** Decode status. */
 +    DecodeStatus _status;
 +
 +    /** Per-thread status. */
 +    ThreadStatus decodeStatus[Impl::MaxThreads];
 +
 +  public:
 +    /** DefaultDecode constructor. */
 +    DefaultDecode(Params *params);
 +
 +    /** Returns the name of decode. */
 +    std::string name() const;
 +
 +    /** Registers statistics. */
 +    void regStats();
 +
 +    /** Sets CPU pointer. */
 +    void setCPU(FullCPU *cpu_ptr);
 +
 +    /** Sets the main backwards communication time buffer pointer. */
 +    void setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr);
 +
 +    /** Sets pointer to time buffer used to communicate to the next stage. */
 +    void setDecodeQueue(TimeBuffer<DecodeStruct> *dq_ptr);
 +
 +    /** Sets pointer to time buffer coming from fetch. */
 +    void setFetchQueue(TimeBuffer<FetchStruct> *fq_ptr);
 +
 +    /** Sets pointer to list of active threads. */
 +    void setActiveThreads(std::list<unsigned> *at_ptr);
 +
++    /** Switches out the decode stage. */
 +    void switchOut();
 +
++    /** Takes over from another CPU's thread. */
 +    void takeOverFrom();
++
 +    /** Ticks decode, processing all input signals and decoding as many
 +     * instructions as possible.
 +     */
 +    void tick();
 +
 +    /** Determines what to do based on decode's current status.
 +     * @param status_change decode() sets this variable if there was a status
 +     * change (ie switching from from blocking to unblocking).
 +     * @param tid Thread id to decode instructions from.
 +     */
 +    void decode(bool &status_change, unsigned tid);
 +
 +    /** Processes instructions from fetch and passes them on to rename.
 +     * Decoding of instructions actually happens when they are created in
 +     * fetch, so this function mostly checks if PC-relative branches are
 +     * correct.
 +     */
 +    void decodeInsts(unsigned tid);
 +
 +  private:
 +    /** Inserts a thread's instructions into the skid buffer, to be decoded
 +     * once decode unblocks.
 +     */
 +    void skidInsert(unsigned tid);
 +
 +    /** Returns if all of the skid buffers are empty. */
 +    bool skidsEmpty();
 +
 +    /** Updates overall decode status based on all of the threads' statuses. */
 +    void updateStatus();
 +
 +    /** Separates instructions from fetch into individual lists of instructions
 +     * sorted by thread.
 +     */
 +    void sortInsts();
 +
 +    /** Reads all stall signals from the backwards communication timebuffer. */
 +    void readStallSignals(unsigned tid);
 +
 +    /** Checks all input signals and updates decode's status appropriately. */
 +    bool checkSignalsAndUpdate(unsigned tid);
 +
 +    /** Checks all stall signals, and returns if any are true. */
 +    bool checkStall(unsigned tid) const;
 +
 +    /** Returns if there any instructions from fetch on this cycle. */
 +    inline bool fetchInstsValid();
 +
 +    /** Switches decode to blocking, and signals back that decode has
 +     * become blocked.
 +     * @return Returns true if there is a status change.
 +     */
 +    bool block(unsigned tid);
 +
 +    /** Switches decode to unblocking if the skid buffer is empty, and
 +     * signals back that decode has unblocked.
 +     * @return Returns true if there is a status change.
 +     */
 +    bool unblock(unsigned tid);
 +
 +    /** Squashes if there is a PC-relative branch that was predicted
 +     * incorrectly. Sends squash information back to fetch.
 +     */
 +    void squash(DynInstPtr &inst, unsigned tid);
 +
 +  public:
 +    /** Squashes due to commit signalling a squash. Changes status to
 +     * squashing and clears block/unblock signals as needed.
 +     */
 +    unsigned squash(unsigned tid);
 +
 +  private:
 +    // Interfaces to objects outside of decode.
 +    /** CPU interface. */
 +    FullCPU *cpu;
 +
 +    /** Time buffer interface. */
 +    TimeBuffer<TimeStruct> *timeBuffer;
 +
 +    /** Wire to get rename's output from backwards time buffer. */
 +    typename TimeBuffer<TimeStruct>::wire fromRename;
 +
 +    /** Wire to get iew's information from backwards time buffer. */
 +    typename TimeBuffer<TimeStruct>::wire fromIEW;
 +
 +    /** Wire to get commit's information from backwards time buffer. */
 +    typename TimeBuffer<TimeStruct>::wire fromCommit;
 +
 +    /** Wire to write information heading to previous stages. */
 +    // Might not be the best name as not only fetch will read it.
 +    typename TimeBuffer<TimeStruct>::wire toFetch;
 +
 +    /** Decode instruction queue. */
 +    TimeBuffer<DecodeStruct> *decodeQueue;
 +
 +    /** Wire used to write any information heading to rename. */
 +    typename TimeBuffer<DecodeStruct>::wire toRename;
 +
 +    /** Fetch instruction queue interface. */
 +    TimeBuffer<FetchStruct> *fetchQueue;
 +
 +    /** Wire to get fetch's output from fetch queue. */
 +    typename TimeBuffer<FetchStruct>::wire fromFetch;
 +
 +    /** Queue of all instructions coming from fetch this cycle. */
 +    std::queue<DynInstPtr> insts[Impl::MaxThreads];
 +
 +    /** Skid buffer between fetch and decode. */
 +    std::queue<DynInstPtr> skidBuffer[Impl::MaxThreads];
 +
 +    /** Variable that tracks if decode has written to the time buffer this
 +     * cycle. Used to tell CPU if there is activity this cycle.
 +     */
 +    bool wroteToTimeBuffer;
 +
 +    /** Source of possible stalls. */
 +    struct Stalls {
 +        bool rename;
 +        bool iew;
 +        bool commit;
 +    };
 +
 +    /** Tracks which stages are telling decode to stall. */
 +    Stalls stalls[Impl::MaxThreads];
 +
 +    /** Rename to decode delay, in ticks. */
 +    unsigned renameToDecodeDelay;
 +
 +    /** IEW to decode delay, in ticks. */
 +    unsigned iewToDecodeDelay;
 +
 +    /** Commit to decode delay, in ticks. */
 +    unsigned commitToDecodeDelay;
 +
 +    /** Fetch to decode delay, in ticks. */
 +    unsigned fetchToDecodeDelay;
 +
 +    /** The width of decode, in instructions. */
 +    unsigned decodeWidth;
 +
 +    /** Index of instructions being sent to rename. */
 +    unsigned toRenameIndex;
 +
 +    /** number of Active Threads*/
 +    unsigned numThreads;
 +
 +    /** List of active thread ids */
 +    std::list<unsigned> *activeThreads;
 +
 +    /** Number of branches in flight. */
 +    unsigned branchCount[Impl::MaxThreads];
 +
 +    /** Maximum size of the skid buffer. */
 +    unsigned skidBufferMax;
 +
 +    /** Stat for total number of idle cycles. */
 +    Stats::Scalar<> decodeIdleCycles;
 +    /** Stat for total number of blocked cycles. */
 +    Stats::Scalar<> decodeBlockedCycles;
 +    /** Stat for total number of normal running cycles. */
 +    Stats::Scalar<> decodeRunCycles;
 +    /** Stat for total number of unblocking cycles. */
 +    Stats::Scalar<> decodeUnblockCycles;
 +    /** Stat for total number of squashing cycles. */
 +    Stats::Scalar<> decodeSquashCycles;
 +    /** Stat for number of times a branch is resolved at decode. */
 +    Stats::Scalar<> decodeBranchResolved;
 +    /** Stat for number of times a branch mispredict is detected. */
 +    Stats::Scalar<> decodeBranchMispred;
 +    /** Stat for number of times decode detected a non-control instruction
 +     * incorrectly predicted as a branch.
 +     */
 +    Stats::Scalar<> decodeControlMispred;
 +    /** Stat for total number of decoded instructions. */
 +    Stats::Scalar<> decodeDecodedInsts;
 +    /** Stat for total number of squashed instructions. */
 +    Stats::Scalar<> decodeSquashedInsts;
 +};
 +
 +#endif // __CPU_O3_DECODE_HH__
index b03daff11bd59ad63d12b7fb77ed337b2af19227,0000000000000000000000000000000000000000..64b04bc3dc34c97c4153933571141f6f4798964a
mode 100644,000000..100644
--- /dev/null
@@@ -1,743 -1,0 +1,752 @@@
-     // If the decode status is blocked or unblocking then decode has not yet
-     // signalled fetch to unblock. In that case, there is no need to tell
-     // fetch to block.
-     if (decodeStatus[tid] != Blocked &&
-         decodeStatus[tid] != Unblocking) {
-         toFetch->decodeBlock[tid] = true;
-         wroteToTimeBuffer = true;
-     }
 +/*
 + * Copyright (c) 2004-2006 The Regents of The University of Michigan
 + * 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: Kevin Lim
 + */
 +
 +#include "cpu/o3/decode.hh"
 +
 +using namespace std;
 +
 +template<class Impl>
 +DefaultDecode<Impl>::DefaultDecode(Params *params)
 +    : renameToDecodeDelay(params->renameToDecodeDelay),
 +      iewToDecodeDelay(params->iewToDecodeDelay),
 +      commitToDecodeDelay(params->commitToDecodeDelay),
 +      fetchToDecodeDelay(params->fetchToDecodeDelay),
 +      decodeWidth(params->decodeWidth),
 +      numThreads(params->numberOfThreads)
 +{
 +    _status = Inactive;
 +
++    // Setup status, make sure stall signals are clear.
 +    for (int i = 0; i < numThreads; ++i) {
 +        decodeStatus[i] = Idle;
 +
 +        stalls[i].rename = false;
 +        stalls[i].iew = false;
 +        stalls[i].commit = false;
 +    }
 +
 +    // @todo: Make into a parameter
 +    skidBufferMax = (fetchToDecodeDelay * params->fetchWidth) + decodeWidth;
 +}
 +
 +template <class Impl>
 +std::string
 +DefaultDecode<Impl>::name() const
 +{
 +    return cpu->name() + ".decode";
 +}
 +
 +template <class Impl>
 +void
 +DefaultDecode<Impl>::regStats()
 +{
 +    decodeIdleCycles
 +        .name(name() + ".DECODE:IdleCycles")
 +        .desc("Number of cycles decode is idle")
 +        .prereq(decodeIdleCycles);
 +    decodeBlockedCycles
 +        .name(name() + ".DECODE:BlockedCycles")
 +        .desc("Number of cycles decode is blocked")
 +        .prereq(decodeBlockedCycles);
 +    decodeRunCycles
 +        .name(name() + ".DECODE:RunCycles")
 +        .desc("Number of cycles decode is running")
 +        .prereq(decodeRunCycles);
 +    decodeUnblockCycles
 +        .name(name() + ".DECODE:UnblockCycles")
 +        .desc("Number of cycles decode is unblocking")
 +        .prereq(decodeUnblockCycles);
 +    decodeSquashCycles
 +        .name(name() + ".DECODE:SquashCycles")
 +        .desc("Number of cycles decode is squashing")
 +        .prereq(decodeSquashCycles);
 +    decodeBranchResolved
 +        .name(name() + ".DECODE:BranchResolved")
 +        .desc("Number of times decode resolved a branch")
 +        .prereq(decodeBranchResolved);
 +    decodeBranchMispred
 +        .name(name() + ".DECODE:BranchMispred")
 +        .desc("Number of times decode detected a branch misprediction")
 +        .prereq(decodeBranchMispred);
 +    decodeControlMispred
 +        .name(name() + ".DECODE:ControlMispred")
 +        .desc("Number of times decode detected an instruction incorrectly"
 +              " predicted as a control")
 +        .prereq(decodeControlMispred);
 +    decodeDecodedInsts
 +        .name(name() + ".DECODE:DecodedInsts")
 +        .desc("Number of instructions handled by decode")
 +        .prereq(decodeDecodedInsts);
 +    decodeSquashedInsts
 +        .name(name() + ".DECODE:SquashedInsts")
 +        .desc("Number of squashed instructions handled by decode")
 +        .prereq(decodeSquashedInsts);
 +}
 +
 +template<class Impl>
 +void
 +DefaultDecode<Impl>::setCPU(FullCPU *cpu_ptr)
 +{
 +    DPRINTF(Decode, "Setting CPU pointer.\n");
 +    cpu = cpu_ptr;
 +}
 +
 +template<class Impl>
 +void
 +DefaultDecode<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr)
 +{
 +    DPRINTF(Decode, "Setting time buffer pointer.\n");
 +    timeBuffer = tb_ptr;
 +
 +    // Setup wire to write information back to fetch.
 +    toFetch = timeBuffer->getWire(0);
 +
 +    // Create wires to get information from proper places in time buffer.
 +    fromRename = timeBuffer->getWire(-renameToDecodeDelay);
 +    fromIEW = timeBuffer->getWire(-iewToDecodeDelay);
 +    fromCommit = timeBuffer->getWire(-commitToDecodeDelay);
 +}
 +
 +template<class Impl>
 +void
 +DefaultDecode<Impl>::setDecodeQueue(TimeBuffer<DecodeStruct> *dq_ptr)
 +{
 +    DPRINTF(Decode, "Setting decode queue pointer.\n");
 +    decodeQueue = dq_ptr;
 +
 +    // Setup wire to write information to proper place in decode queue.
 +    toRename = decodeQueue->getWire(0);
 +}
 +
 +template<class Impl>
 +void
 +DefaultDecode<Impl>::setFetchQueue(TimeBuffer<FetchStruct> *fq_ptr)
 +{
 +    DPRINTF(Decode, "Setting fetch queue pointer.\n");
 +    fetchQueue = fq_ptr;
 +
 +    // Setup wire to read information from fetch queue.
 +    fromFetch = fetchQueue->getWire(-fetchToDecodeDelay);
 +}
 +
 +template<class Impl>
 +void
 +DefaultDecode<Impl>::setActiveThreads(list<unsigned> *at_ptr)
 +{
 +    DPRINTF(Decode, "Setting active threads list pointer.\n");
 +    activeThreads = at_ptr;
 +}
 +
 +template <class Impl>
 +void
 +DefaultDecode<Impl>::switchOut()
 +{
++    // Decode can immediately switch out.
 +    cpu->signalSwitched();
 +}
 +
 +template <class Impl>
 +void
 +DefaultDecode<Impl>::takeOverFrom()
 +{
 +    _status = Inactive;
 +
++    // Be sure to reset state and clear out any old instructions.
 +    for (int i = 0; i < numThreads; ++i) {
 +        decodeStatus[i] = Idle;
 +
 +        stalls[i].rename = false;
 +        stalls[i].iew = false;
 +        stalls[i].commit = false;
 +        while (!insts[i].empty())
 +            insts[i].pop();
 +        while (!skidBuffer[i].empty())
 +            skidBuffer[i].pop();
 +        branchCount[i] = 0;
 +    }
 +    wroteToTimeBuffer = false;
 +}
 +
 +template<class Impl>
 +bool
 +DefaultDecode<Impl>::checkStall(unsigned tid) const
 +{
 +    bool ret_val = false;
 +
 +    if (stalls[tid].rename) {
 +        DPRINTF(Decode,"[tid:%i]: Stall fom Rename stage detected.\n", tid);
 +        ret_val = true;
 +    } else if (stalls[tid].iew) {
 +        DPRINTF(Decode,"[tid:%i]: Stall fom IEW stage detected.\n", tid);
 +        ret_val = true;
 +    } else if (stalls[tid].commit) {
 +        DPRINTF(Decode,"[tid:%i]: Stall fom Commit stage detected.\n", tid);
 +        ret_val = true;
 +    }
 +
 +    return ret_val;
 +}
 +
 +template<class Impl>
 +inline bool
 +DefaultDecode<Impl>::fetchInstsValid()
 +{
 +    return fromFetch->size > 0;
 +}
 +
 +template<class Impl>
 +bool
 +DefaultDecode<Impl>::block(unsigned tid)
 +{
 +    DPRINTF(Decode, "[tid:%u]: Blocking.\n", tid);
 +
-     toFetch->decodeInfo[tid].branchTaken = true;
 +    // Add the current inputs to the skid buffer so they can be
 +    // reprocessed when this stage unblocks.
 +    skidInsert(tid);
 +
++    // If the decode status is blocked or unblocking then decode has not yet
++    // signalled fetch to unblock. In that case, there is no need to tell
++    // fetch to block.
 +    if (decodeStatus[tid] != Blocked) {
 +        // Set the status to Blocked.
 +        decodeStatus[tid] = Blocked;
++
++        if (decodeStatus[tid] != Unblocking) {
++            toFetch->decodeBlock[tid] = true;
++            wroteToTimeBuffer = true;
++        }
++
 +        return true;
 +    }
 +
 +    return false;
 +}
 +
 +template<class Impl>
 +bool
 +DefaultDecode<Impl>::unblock(unsigned tid)
 +{
 +    // Decode is done unblocking only if the skid buffer is empty.
 +    if (skidBuffer[tid].empty()) {
 +        DPRINTF(Decode, "[tid:%u]: Done unblocking.\n", tid);
 +        toFetch->decodeUnblock[tid] = true;
 +        wroteToTimeBuffer = true;
 +
 +        decodeStatus[tid] = Running;
 +        return true;
 +    }
 +
 +    DPRINTF(Decode, "[tid:%u]: Currently unblocking.\n", tid);
 +
 +    return false;
 +}
 +
 +template<class Impl>
 +void
 +DefaultDecode<Impl>::squash(DynInstPtr &inst, unsigned tid)
 +{
 +    DPRINTF(Decode, "[tid:%i]: Squashing due to incorrect branch prediction "
 +            "detected at decode.\n", tid);
 +
++    // Send back mispredict information.
 +    toFetch->decodeInfo[tid].branchMispredict = true;
 +    toFetch->decodeInfo[tid].doneSeqNum = inst->seqNum;
 +    toFetch->decodeInfo[tid].predIncorrect = true;
 +    toFetch->decodeInfo[tid].squash = true;
 +    toFetch->decodeInfo[tid].nextPC = inst->readNextPC();
-     // Clear the skid buffer in case it has any data in it.
++    toFetch->decodeInfo[tid].branchTaken =
++        inst->readNextPC() != (inst->readPC() + sizeof(TheISA::MachInst));
 +
++    // Might have to tell fetch to unblock.
 +    if (decodeStatus[tid] == Blocked ||
 +        decodeStatus[tid] == Unblocking) {
 +        toFetch->decodeUnblock[tid] = 1;
 +    }
 +
 +    // Set status to squashing.
 +    decodeStatus[tid] = Squashing;
 +
 +    for (int i=0; i<fromFetch->size; i++) {
 +        if (fromFetch->insts[i]->threadNumber == tid &&
 +            fromFetch->insts[i]->seqNum > inst->seqNum) {
 +            fromFetch->insts[i]->squashed = true;
 +        }
 +    }
 +
++    // Clear the instruction list and skid buffer in case they have any
++    // insts in them.
 +    while (!insts[tid].empty()) {
 +        insts[tid].pop();
 +    }
 +
-     // Clear the skid buffer in case it has any data in it.
 +    while (!skidBuffer[tid].empty()) {
 +        skidBuffer[tid].pop();
 +    }
 +
 +    // Squash instructions up until this one
 +    cpu->removeInstsUntil(inst->seqNum, tid);
 +}
 +
 +template<class Impl>
 +unsigned
 +DefaultDecode<Impl>::squash(unsigned tid)
 +{
 +    DPRINTF(Decode, "[tid:%i]: Squashing.\n",tid);
 +
 +    if (decodeStatus[tid] == Blocked ||
 +        decodeStatus[tid] == Unblocking) {
 +#if !FULL_SYSTEM
 +        // In syscall emulation, we can have both a block and a squash due
 +        // to a syscall in the same cycle.  This would cause both signals to
 +        // be high.  This shouldn't happen in full system.
 +        // @todo: Determine if this still happens.
 +        if (toFetch->decodeBlock[tid]) {
 +            toFetch->decodeBlock[tid] = 0;
 +        } else {
 +            toFetch->decodeUnblock[tid] = 1;
 +        }
 +#else
 +        toFetch->decodeUnblock[tid] = 1;
 +#endif
 +    }
 +
 +    // Set status to squashing.
 +    decodeStatus[tid] = Squashing;
 +
 +    // Go through incoming instructions from fetch and squash them.
 +    unsigned squash_count = 0;
 +
 +    for (int i=0; i<fromFetch->size; i++) {
 +        if (fromFetch->insts[i]->threadNumber == tid) {
 +            fromFetch->insts[i]->squashed = true;
 +            squash_count++;
 +        }
 +    }
 +
++    // Clear the instruction list and skid buffer in case they have any
++    // insts in them.
 +    while (!insts[tid].empty()) {
 +        insts[tid].pop();
 +    }
 +
 +    while (!skidBuffer[tid].empty()) {
 +        skidBuffer[tid].pop();
 +    }
 +
 +    return squash_count;
 +}
 +
 +template<class Impl>
 +void
 +DefaultDecode<Impl>::skidInsert(unsigned tid)
 +{
 +    DynInstPtr inst = NULL;
 +
 +    while (!insts[tid].empty()) {
 +        inst = insts[tid].front();
 +
 +        insts[tid].pop();
 +
 +        assert(tid == inst->threadNumber);
 +
 +        DPRINTF(Decode,"Inserting [sn:%lli] PC:%#x into decode skidBuffer %i\n",
 +                inst->seqNum, inst->readPC(), inst->threadNumber);
 +
 +        skidBuffer[tid].push(inst);
 +    }
 +
 +    // @todo: Eventually need to enforce this by not letting a thread
 +    // fetch past its skidbuffer
 +    assert(skidBuffer[tid].size() <= skidBufferMax);
 +}
 +
 +template<class Impl>
 +bool
 +DefaultDecode<Impl>::skidsEmpty()
 +{
 +    list<unsigned>::iterator threads = (*activeThreads).begin();
 +
 +    while (threads != (*activeThreads).end()) {
 +        if (!skidBuffer[*threads++].empty())
 +            return false;
 +    }
 +
 +    return true;
 +}
 +
 +template<class Impl>
 +void
 +DefaultDecode<Impl>::updateStatus()
 +{
 +    bool any_unblocking = false;
 +
 +    list<unsigned>::iterator threads = (*activeThreads).begin();
 +
 +    threads = (*activeThreads).begin();
 +
 +    while (threads != (*activeThreads).end()) {
 +        unsigned tid = *threads++;
 +
 +        if (decodeStatus[tid] == Unblocking) {
 +            any_unblocking = true;
 +            break;
 +        }
 +    }
 +
 +    // Decode will have activity if it's unblocking.
 +    if (any_unblocking) {
 +        if (_status == Inactive) {
 +            _status = Active;
 +
 +            DPRINTF(Activity, "Activating stage.\n");
 +
 +            cpu->activateStage(FullCPU::DecodeIdx);
 +        }
 +    } else {
 +        // If it's not unblocking, then decode will not have any internal
 +        // activity.  Switch it to inactive.
 +        if (_status == Active) {
 +            _status = Inactive;
 +            DPRINTF(Activity, "Deactivating stage.\n");
 +
 +            cpu->deactivateStage(FullCPU::DecodeIdx);
 +        }
 +    }
 +}
 +
 +template <class Impl>
 +void
 +DefaultDecode<Impl>::sortInsts()
 +{
 +    int insts_from_fetch = fromFetch->size;
 +#ifdef DEBUG
 +    for (int i=0; i < numThreads; i++)
 +        assert(insts[i].empty());
 +#endif
 +    for (int i = 0; i < insts_from_fetch; ++i) {
 +        insts[fromFetch->insts[i]->threadNumber].push(fromFetch->insts[i]);
 +    }
 +}
 +
 +template<class Impl>
 +void
 +DefaultDecode<Impl>::readStallSignals(unsigned tid)
 +{
 +    if (fromRename->renameBlock[tid]) {
 +        stalls[tid].rename = true;
 +    }
 +
 +    if (fromRename->renameUnblock[tid]) {
 +        assert(stalls[tid].rename);
 +        stalls[tid].rename = false;
 +    }
 +
 +    if (fromIEW->iewBlock[tid]) {
 +        stalls[tid].iew = true;
 +    }
 +
 +    if (fromIEW->iewUnblock[tid]) {
 +        assert(stalls[tid].iew);
 +        stalls[tid].iew = false;
 +    }
 +
 +    if (fromCommit->commitBlock[tid]) {
 +        stalls[tid].commit = true;
 +    }
 +
 +    if (fromCommit->commitUnblock[tid]) {
 +        assert(stalls[tid].commit);
 +        stalls[tid].commit = false;
 +    }
 +}
 +
 +template <class Impl>
 +bool
 +DefaultDecode<Impl>::checkSignalsAndUpdate(unsigned tid)
 +{
 +    // Check if there's a squash signal, squash if there is.
 +    // Check stall signals, block if necessary.
 +    // If status was blocked
 +    //     Check if stall conditions have passed
 +    //         if so then go to unblocking
 +    // If status was Squashing
 +    //     check if squashing is not high.  Switch to running this cycle.
 +
 +    // Update the per thread stall statuses.
 +    readStallSignals(tid);
 +
 +    // Check squash signals from commit.
 +    if (fromCommit->commitInfo[tid].squash) {
 +
 +        DPRINTF(Decode, "[tid:%u]: Squashing instructions due to squash "
 +                "from commit.\n", tid);
 +
 +        squash(tid);
 +
 +        return true;
 +    }
 +
 +    // Check ROB squash signals from commit.
 +    if (fromCommit->commitInfo[tid].robSquashing) {
 +        DPRINTF(Decode, "[tid:%]: ROB is still squashing.\n",tid);
 +
 +        // Continue to squash.
 +        decodeStatus[tid] = Squashing;
 +
 +        return true;
 +    }
 +
 +    if (checkStall(tid)) {
 +        return block(tid);
 +    }
 +
 +    if (decodeStatus[tid] == Blocked) {
 +        DPRINTF(Decode, "[tid:%u]: Done blocking, switching to unblocking.\n",
 +                tid);
 +
 +        decodeStatus[tid] = Unblocking;
 +
 +        unblock(tid);
 +
 +        return true;
 +    }
 +
 +    if (decodeStatus[tid] == Squashing) {
 +        // Switch status to running if decode isn't being told to block or
 +        // squash this cycle.
 +        DPRINTF(Decode, "[tid:%u]: Done squashing, switching to running.\n",
 +                tid);
 +
 +        decodeStatus[tid] = Running;
 +
 +        return false;
 +    }
 +
 +    // If we've reached this point, we have not gotten any signals that
 +    // cause decode to change its status.  Decode remains the same as before.
 +    return false;
 +}
 +
 +template<class Impl>
 +void
 +DefaultDecode<Impl>::tick()
 +{
 +    wroteToTimeBuffer = false;
 +
 +    bool status_change = false;
 +
 +    toRenameIndex = 0;
 +
 +    list<unsigned>::iterator threads = (*activeThreads).begin();
 +
 +    sortInsts();
 +
 +    //Check stall and squash signals.
 +    while (threads != (*activeThreads).end()) {
 +    unsigned tid = *threads++;
 +
 +        DPRINTF(Decode,"Processing [tid:%i]\n",tid);
 +        status_change =  checkSignalsAndUpdate(tid) || status_change;
 +
 +        decode(status_change, tid);
 +    }
 +
 +    if (status_change) {
 +        updateStatus();
 +    }
 +
 +    if (wroteToTimeBuffer) {
 +        DPRINTF(Activity, "Activity this cycle.\n");
 +
 +        cpu->activityThisCycle();
 +    }
 +}
 +
 +template<class Impl>
 +void
 +DefaultDecode<Impl>::decode(bool &status_change, unsigned tid)
 +{
 +    // If status is Running or idle,
 +    //     call decodeInsts()
 +    // If status is Unblocking,
 +    //     buffer any instructions coming from fetch
 +    //     continue trying to empty skid buffer
 +    //     check if stall conditions have passed
 +
 +    if (decodeStatus[tid] == Blocked) {
 +        ++decodeBlockedCycles;
 +    } else if (decodeStatus[tid] == Squashing) {
 +        ++decodeSquashCycles;
 +    }
 +
 +    // Decode should try to decode as many instructions as its bandwidth
 +    // will allow, as long as it is not currently blocked.
 +    if (decodeStatus[tid] == Running ||
 +        decodeStatus[tid] == Idle) {
 +        DPRINTF(Decode, "[tid:%u] Not blocked, so attempting to run "
 +                "stage.\n",tid);
 +
 +        decodeInsts(tid);
 +    } else if (decodeStatus[tid] == Unblocking) {
 +        // Make sure that the skid buffer has something in it if the
 +        // status is unblocking.
 +        assert(!skidsEmpty());
 +
 +        // If the status was unblocking, then instructions from the skid
 +        // buffer were used.  Remove those instructions and handle
 +        // the rest of unblocking.
 +        decodeInsts(tid);
 +
 +        if (fetchInstsValid()) {
 +            // Add the current inputs to the skid buffer so they can be
 +            // reprocessed when this stage unblocks.
 +            skidInsert(tid);
 +        }
 +
 +        status_change = unblock(tid) || status_change;
 +    }
 +}
 +
 +template <class Impl>
 +void
 +DefaultDecode<Impl>::decodeInsts(unsigned tid)
 +{
 +    // Instructions can come either from the skid buffer or the list of
 +    // instructions coming from fetch, depending on decode's status.
 +    int insts_available = decodeStatus[tid] == Unblocking ?
 +        skidBuffer[tid].size() : insts[tid].size();
 +
 +    if (insts_available == 0) {
 +        DPRINTF(Decode, "[tid:%u] Nothing to do, breaking out"
 +                " early.\n",tid);
 +        // Should I change the status to idle?
 +        ++decodeIdleCycles;
 +        return;
 +    } else if (decodeStatus[tid] == Unblocking) {
 +        DPRINTF(Decode, "[tid:%u] Unblocking, removing insts from skid "
 +                "buffer.\n",tid);
 +        ++decodeUnblockCycles;
 +    } else if (decodeStatus[tid] == Running) {
 +        ++decodeRunCycles;
 +    }
 +
 +    DynInstPtr inst;
 +
 +    std::queue<DynInstPtr>
 +        &insts_to_decode = decodeStatus[tid] == Unblocking ?
 +        skidBuffer[tid] : insts[tid];
 +
 +    DPRINTF(Decode, "[tid:%u]: Sending instruction to rename.\n",tid);
 +
 +    while (insts_available > 0 && toRenameIndex < decodeWidth) {
 +        assert(!insts_to_decode.empty());
 +
 +        inst = insts_to_decode.front();
 +
 +        insts_to_decode.pop();
 +
 +        DPRINTF(Decode, "[tid:%u]: Processing instruction [sn:%lli] with "
 +                "PC %#x\n",
 +                tid, inst->seqNum, inst->readPC());
 +
 +        if (inst->isSquashed()) {
 +            DPRINTF(Decode, "[tid:%u]: Instruction %i with PC %#x is "
 +                    "squashed, skipping.\n",
 +                    tid, inst->seqNum, inst->readPC());
 +
 +            ++decodeSquashedInsts;
 +
 +            --insts_available;
 +
 +            continue;
 +        }
 +
 +        // Also check if instructions have no source registers.  Mark
 +        // them as ready to issue at any time.  Not sure if this check
 +        // should exist here or at a later stage; however it doesn't matter
 +        // too much for function correctness.
 +        if (inst->numSrcRegs() == 0) {
 +            inst->setCanIssue();
 +        }
 +
 +        // This current instruction is valid, so add it into the decode
 +        // queue.  The next instruction may not be valid, so check to
 +        // see if branches were predicted correctly.
 +        toRename->insts[toRenameIndex] = inst;
 +
 +        ++(toRename->size);
 +        ++toRenameIndex;
 +        ++decodeDecodedInsts;
 +        --insts_available;
 +
 +        // Ensure that if it was predicted as a branch, it really is a
 +        // branch.
 +        if (inst->predTaken() && !inst->isControl()) {
 +            panic("Instruction predicted as a branch!");
 +
 +            ++decodeControlMispred;
 +
 +            // Might want to set some sort of boolean and just do
 +            // a check at the end
 +            squash(inst, inst->threadNumber);
 +
 +            break;
 +        }
 +
 +        // Go ahead and compute any PC-relative branches.
 +        if (inst->isDirectCtrl() && inst->isUncondCtrl()) {
 +            ++decodeBranchResolved;
 +            inst->setNextPC(inst->branchTarget());
 +
 +            if (inst->mispredicted()) {
 +                ++decodeBranchMispred;
 +
 +                // Might want to set some sort of boolean and just do
 +                // a check at the end
 +                squash(inst, inst->threadNumber);
++                inst->setPredTarg(inst->branchTarget());
 +
 +                break;
 +            }
 +        }
 +    }
 +
 +    // If we didn't process all instructions, then we will need to block
 +    // and put all those instructions into the skid buffer.
 +    if (!insts_to_decode.empty()) {
 +        block(tid);
 +    }
 +
 +    // Record that decode has written to the time buffer for activity
 +    // tracking.
 +    if (toRenameIndex) {
 +        wroteToTimeBuffer = true;
 +    }
 +}
index f8ae38da42bab822dec0c6c31fc0e52d6451dff4,0000000000000000000000000000000000000000..b6c5f1ab1be86227395a99f7462c9d5d572bf7d0
mode 100644,000000..100644
--- /dev/null
@@@ -1,213 -1,0 +1,235 @@@
 +
 +#ifndef __CPU_O3_DEP_GRAPH_HH__
 +#define __CPU_O3_DEP_GRAPH_HH__
 +
 +#include "cpu/o3/comm.hh"
 +
++/** Node in a linked list. */
 +template <class DynInstPtr>
 +class DependencyEntry
 +{
 +  public:
 +    DependencyEntry()
 +        : inst(NULL), next(NULL)
 +    { }
 +
 +    DynInstPtr inst;
 +    //Might want to include data about what arch. register the
 +    //dependence is waiting on.
 +    DependencyEntry<DynInstPtr> *next;
 +};
 +
++/** Array of linked list that maintains the dependencies between
++ * producing instructions and consuming instructions.  Each linked
++ * list represents a single physical register, having the future
++ * producer of the register's value, and all consumers waiting on that
++ * value on the list.  The head node of each linked list represents
++ * the producing instruction of that register.  Instructions are put
++ * on the list upon reaching the IQ, and are removed from the list
++ * either when the producer completes, or the instruction is squashed.
++*/
 +template <class DynInstPtr>
 +class DependencyGraph
 +{
 +  public:
 +    typedef DependencyEntry<DynInstPtr> DepEntry;
 +
++    /** Default construction.  Must call resize() prior to use. */
 +    DependencyGraph()
 +        : numEntries(0), memAllocCounter(0), nodesTraversed(0), nodesRemoved(0)
 +    { }
 +
++    /** Resize the dependency graph to have num_entries registers. */
 +    void resize(int num_entries);
 +
++    /** Clears all of the linked lists. */
 +    void reset();
 +
++    /** Inserts an instruction to be dependent on the given index. */
 +    void insert(PhysRegIndex idx, DynInstPtr &new_inst);
 +
++    /** Sets the producing instruction of a given register. */
 +    void setInst(PhysRegIndex idx, DynInstPtr &new_inst)
 +    { dependGraph[idx].inst = new_inst; }
 +
++    /** Clears the producing instruction. */
 +    void clearInst(PhysRegIndex idx)
 +    { dependGraph[idx].inst = NULL; }
 +
++    /** Removes an instruction from a single linked list. */
 +    void remove(PhysRegIndex idx, DynInstPtr &inst_to_remove);
 +
++    /** Removes and returns the newest dependent of a specific register. */
 +    DynInstPtr pop(PhysRegIndex idx);
 +
++    /** Checks if there are any dependents on a specific register. */
 +    bool empty(PhysRegIndex idx) { return !dependGraph[idx].next; }
 +
 +    /** Debugging function to dump out the dependency graph.
 +     */
 +    void dump();
 +
 +  private:
 +    /** Array of linked lists.  Each linked list is a list of all the
 +     *  instructions that depend upon a given register.  The actual
 +     *  register's index is used to index into the graph; ie all
 +     *  instructions in flight that are dependent upon r34 will be
 +     *  in the linked list of dependGraph[34].
 +     */
 +    DepEntry *dependGraph;
 +
++    /** Number of linked lists; identical to the number of registers. */
 +    int numEntries;
 +
 +    // Debug variable, remove when done testing.
 +    unsigned memAllocCounter;
 +
 +  public:
++    // Debug variable, remove when done testing.
 +    uint64_t nodesTraversed;
++    // Debug variable, remove when done testing.
 +    uint64_t nodesRemoved;
 +};
 +
 +template <class DynInstPtr>
 +void
 +DependencyGraph<DynInstPtr>::resize(int num_entries)
 +{
 +    numEntries = num_entries;
 +    dependGraph = new DepEntry[numEntries];
 +}
 +
 +template <class DynInstPtr>
 +void
 +DependencyGraph<DynInstPtr>::reset()
 +{
 +    // Clear the dependency graph
 +    DepEntry *curr;
 +    DepEntry *prev;
 +
 +    for (int i = 0; i < numEntries; ++i) {
 +        curr = dependGraph[i].next;
 +
 +        while (curr) {
 +            memAllocCounter--;
 +
 +            prev = curr;
 +            curr = prev->next;
 +            prev->inst = NULL;
 +
 +            delete prev;
 +        }
 +
 +        if (dependGraph[i].inst) {
 +            dependGraph[i].inst = NULL;
 +        }
 +
 +        dependGraph[i].next = NULL;
 +    }
 +}
 +
 +template <class DynInstPtr>
 +void
 +DependencyGraph<DynInstPtr>::insert(PhysRegIndex idx, DynInstPtr &new_inst)
 +{
 +    //Add this new, dependent instruction at the head of the dependency
 +    //chain.
 +
 +    // First create the entry that will be added to the head of the
 +    // dependency chain.
 +    DepEntry *new_entry = new DepEntry;
 +    new_entry->next = dependGraph[idx].next;
 +    new_entry->inst = new_inst;
 +
 +    // Then actually add it to the chain.
 +    dependGraph[idx].next = new_entry;
 +
 +    ++memAllocCounter;
 +}
 +
 +
 +template <class DynInstPtr>
 +void
 +DependencyGraph<DynInstPtr>::remove(PhysRegIndex idx,
 +                                    DynInstPtr &inst_to_remove)
 +{
 +    DepEntry *prev = &dependGraph[idx];
 +    DepEntry *curr = dependGraph[idx].next;
 +
 +    // Make sure curr isn't NULL.  Because this instruction is being
 +    // removed from a dependency list, it must have been placed there at
 +    // an earlier time.  The dependency chain should not be empty,
 +    // unless the instruction dependent upon it is already ready.
 +    if (curr == NULL) {
 +        return;
 +    }
 +
 +    nodesRemoved++;
 +
 +    // Find the instruction to remove within the dependency linked list.
 +    while (curr->inst != inst_to_remove) {
 +        prev = curr;
 +        curr = curr->next;
 +        nodesTraversed++;
 +
 +        assert(curr != NULL);
 +    }
 +
 +    // Now remove this instruction from the list.
 +    prev->next = curr->next;
 +
 +    --memAllocCounter;
 +
 +    // Could push this off to the destructor of DependencyEntry
 +    curr->inst = NULL;
 +
 +    delete curr;
 +}
 +
 +template <class DynInstPtr>
 +DynInstPtr
 +DependencyGraph<DynInstPtr>::pop(PhysRegIndex idx)
 +{
 +    DepEntry *node;
 +    node = dependGraph[idx].next;
 +    DynInstPtr inst = NULL;
 +    if (node) {
 +        inst = node->inst;
 +        dependGraph[idx].next = node->next;
 +        node->inst = NULL;
 +        memAllocCounter--;
 +        delete node;
 +    }
 +    return inst;
 +}
 +
 +template <class DynInstPtr>
 +void
 +DependencyGraph<DynInstPtr>::dump()
 +{
 +    DepEntry *curr;
 +
 +    for (int i = 0; i < numEntries; ++i)
 +    {
 +        curr = &dependGraph[i];
 +
 +        if (curr->inst) {
 +            cprintf("dependGraph[%i]: producer: %#x [sn:%lli] consumer: ",
 +                    i, curr->inst->readPC(), curr->inst->seqNum);
 +        } else {
 +            cprintf("dependGraph[%i]: No producer. consumer: ", i);
 +        }
 +
 +        while (curr->next != NULL) {
 +            curr = curr->next;
 +
 +            cprintf("%#x [sn:%lli] ",
 +                    curr->inst->readPC(), curr->inst->seqNum);
 +        }
 +
 +        cprintf("\n");
 +    }
 +    cprintf("memAllocCounter: %i\n", memAllocCounter);
 +}
 +
 +#endif // __CPU_O3_DEP_GRAPH_HH__
index 3c4fc7d93d172801d9a5c28facbe832b6e432bf6,0000000000000000000000000000000000000000..23328c534bdb05fe79fc828243fcd9405bfbec1b
mode 100644,000000..100644
--- /dev/null
@@@ -1,422 -1,0 +1,439 @@@
-  * It supports the idling functionalitiy of the CPU by indicating to
 +/*
 + * Copyright (c) 2004-2006 The Regents of The University of Michigan
 + * 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: Kevin Lim
 + */
 +
 +#ifndef __CPU_O3_FETCH_HH__
 +#define __CPU_O3_FETCH_HH__
 +
 +#include "arch/utility.hh"
 +#include "base/statistics.hh"
 +#include "base/timebuf.hh"
 +#include "cpu/pc_event.hh"
 +#include "mem/packet.hh"
 +#include "mem/port.hh"
 +#include "sim/eventq.hh"
 +
 +class Sampler;
 +
 +/**
 + * DefaultFetch class handles both single threaded and SMT fetch. Its
 + * width is specified by the parameters; each cycle it tries to fetch
 + * that many instructions. It supports using a branch predictor to
 + * predict direction and targets.
++ * It supports the idling functionality of the CPU by indicating to
 + * the CPU when it is active and inactive.
 + */
 +template <class Impl>
 +class DefaultFetch
 +{
 +  public:
 +    /** Typedefs from Impl. */
 +    typedef typename Impl::CPUPol CPUPol;
 +    typedef typename Impl::DynInst DynInst;
 +    typedef typename Impl::DynInstPtr DynInstPtr;
 +    typedef typename Impl::FullCPU FullCPU;
 +    typedef typename Impl::Params Params;
 +
 +    /** Typedefs from the CPU policy. */
 +    typedef typename CPUPol::BPredUnit BPredUnit;
 +    typedef typename CPUPol::FetchStruct FetchStruct;
 +    typedef typename CPUPol::TimeStruct TimeStruct;
 +
 +    /** Typedefs from ISA. */
 +    typedef TheISA::MachInst MachInst;
 +    typedef TheISA::ExtMachInst ExtMachInst;
 +
 +    class IcachePort : public Port
 +    {
 +      protected:
 +        DefaultFetch<Impl> *fetch;
 +
 +      public:
 +        IcachePort(DefaultFetch<Impl> *_fetch)
 +            : Port(_fetch->name() + "-iport"), fetch(_fetch)
 +        { }
 +
 +      protected:
 +        virtual Tick recvAtomic(PacketPtr pkt);
 +
 +        virtual void recvFunctional(PacketPtr pkt);
 +
 +        virtual void recvStatusChange(Status status);
 +
 +        virtual void getDeviceAddressRanges(AddrRangeList &resp,
 +                                            AddrRangeList &snoop)
 +        { resp.clear(); snoop.clear(); }
 +
 +        virtual bool recvTiming(PacketPtr pkt);
 +
 +        virtual void recvRetry();
 +    };
 +
 +  public:
 +    /** Overall fetch status. Used to determine if the CPU can
 +     * deschedule itsef due to a lack of activity.
 +     */
 +    enum FetchStatus {
 +        Active,
 +        Inactive
 +    };
 +
 +    /** Individual thread status. */
 +    enum ThreadStatus {
 +        Running,
 +        Idle,
 +        Squashing,
 +        Blocked,
 +        Fetching,
 +        TrapPending,
 +        QuiescePending,
 +        SwitchOut,
 +        IcacheWaitResponse,
 +        IcacheRetry,
 +        IcacheAccessComplete
 +    };
 +
 +    /** Fetching Policy, Add new policies here.*/
 +    enum FetchPriority {
 +        SingleThread,
 +        RoundRobin,
 +        Branch,
 +        IQ,
 +        LSQ
 +    };
 +
 +  private:
 +    /** Fetch status. */
 +    FetchStatus _status;
 +
 +    /** Per-thread status. */
 +    ThreadStatus fetchStatus[Impl::MaxThreads];
 +
 +    /** Fetch policy. */
 +    FetchPriority fetchPolicy;
 +
 +    /** List that has the threads organized by priority. */
 +    std::list<unsigned> priorityList;
 +
 +  public:
 +    /** DefaultFetch constructor. */
 +    DefaultFetch(Params *params);
 +
 +    /** Returns the name of fetch. */
 +    std::string name() const;
 +
 +    /** Registers statistics. */
 +    void regStats();
 +
 +    /** Sets CPU pointer. */
 +    void setCPU(FullCPU *cpu_ptr);
 +
 +    /** Sets the main backwards communication time buffer pointer. */
 +    void setTimeBuffer(TimeBuffer<TimeStruct> *time_buffer);
 +
 +    /** Sets pointer to list of active threads. */
 +    void setActiveThreads(std::list<unsigned> *at_ptr);
 +
 +    /** Sets pointer to time buffer used to communicate to the next stage. */
 +    void setFetchQueue(TimeBuffer<FetchStruct> *fq_ptr);
 +
 +    /** Sets pointer to page table. */
 +//    void setPageTable(PageTable *pt_ptr);
 +
 +    /** Initialize stage. */
 +    void initStage();
 +
 +    /** Processes cache completion event. */
 +    void processCacheCompletion(PacketPtr pkt);
 +
++    /** Begins the switch out of the fetch stage. */
 +    void switchOut();
 +
++    /** Completes the switch out of the fetch stage. */
 +    void doSwitchOut();
 +
++    /** Takes over from another CPU's thread. */
 +    void takeOverFrom();
 +
++    /** Checks if the fetch stage is switched out. */
 +    bool isSwitchedOut() { return switchedOut; }
 +
++    /** Tells fetch to wake up from a quiesce instruction. */
 +    void wakeFromQuiesce();
 +
 +  private:
 +    /** Changes the status of this stage to active, and indicates this
 +     * to the CPU.
 +     */
 +    inline void switchToActive();
 +
 +    /** Changes the status of this stage to inactive, and indicates
 +     * this to the CPU.
 +     */
 +    inline void switchToInactive();
 +
 +    /**
 +     * Looks up in the branch predictor to see if the next PC should be
 +     * either next PC+=MachInst or a branch target.
 +     * @param next_PC Next PC variable passed in by reference.  It is
 +     * expected to be set to the current PC; it will be updated with what
 +     * the next PC will be.
 +     * @return Whether or not a branch was predicted as taken.
 +     */
 +    bool lookupAndUpdateNextPC(DynInstPtr &inst, Addr &next_PC);
 +
 +    /**
 +     * Fetches the cache line that contains fetch_PC.  Returns any
 +     * fault that happened.  Puts the data into the class variable
 +     * cacheData.
 +     * @param fetch_PC The PC address that is being fetched from.
 +     * @param ret_fault The fault reference that will be set to the result of
 +     * the icache access.
 +     * @param tid Thread id.
 +     * @return Any fault that occured.
 +     */
 +    bool fetchCacheLine(Addr fetch_PC, Fault &ret_fault, unsigned tid);
 +
 +    /** Squashes a specific thread and resets the PC. */
 +    inline void doSquash(const Addr &new_PC, unsigned tid);
 +
 +    /** Squashes a specific thread and resets the PC. Also tells the CPU to
 +     * remove any instructions between fetch and decode that should be sqaushed.
 +     */
 +    void squashFromDecode(const Addr &new_PC, const InstSeqNum &seq_num,
 +                          unsigned tid);
 +
 +    /** Checks if a thread is stalled. */
 +    bool checkStall(unsigned tid) const;
 +
 +    /** Updates overall fetch stage status; to be called at the end of each
 +     * cycle. */
 +    FetchStatus updateFetchStatus();
 +
 +  public:
 +    /** Squashes a specific thread and resets the PC. Also tells the CPU to
 +     * remove any instructions that are not in the ROB. The source of this
 +     * squash should be the commit stage.
 +     */
 +    void squash(const Addr &new_PC, unsigned tid);
 +
 +    /** Ticks the fetch stage, processing all inputs signals and fetching
 +     * as many instructions as possible.
 +     */
 +    void tick();
 +
 +    /** Checks all input signals and updates the status as necessary.
 +     *  @return: Returns if the status has changed due to input signals.
 +     */
 +    bool checkSignalsAndUpdate(unsigned tid);
 +
 +    /** Does the actual fetching of instructions and passing them on to the
 +     * next stage.
 +     * @param status_change fetch() sets this variable if there was a status
 +     * change (ie switching to IcacheMissStall).
 +     */
 +    void fetch(bool &status_change);
 +
 +    /** Align a PC to the start of an I-cache block. */
 +    Addr icacheBlockAlignPC(Addr addr)
 +    {
 +        addr = TheISA::realPCToFetchPC(addr);
 +        return (addr & ~(cacheBlkMask));
 +    }
 +
 +  private:
 +    /** Returns the appropriate thread to fetch, given the fetch policy. */
 +    int getFetchingThread(FetchPriority &fetch_priority);
 +
 +    /** Returns the appropriate thread to fetch using a round robin policy. */
 +    int roundRobin();
 +
 +    /** Returns the appropriate thread to fetch using the IQ count policy. */
 +    int iqCount();
 +
 +    /** Returns the appropriate thread to fetch using the LSQ count policy. */
 +    int lsqCount();
 +
 +    /** Returns the appropriate thread to fetch using the branch count policy. */
 +    int branchCount();
 +
 +  private:
 +    /** Pointer to the FullCPU. */
 +    FullCPU *cpu;
 +
 +    /** Time buffer interface. */
 +    TimeBuffer<TimeStruct> *timeBuffer;
 +
 +    /** Wire to get decode's information from backwards time buffer. */
 +    typename TimeBuffer<TimeStruct>::wire fromDecode;
 +
 +    /** Wire to get rename's information from backwards time buffer. */
 +    typename TimeBuffer<TimeStruct>::wire fromRename;
 +
 +    /** Wire to get iew's information from backwards time buffer. */
 +    typename TimeBuffer<TimeStruct>::wire fromIEW;
 +
 +    /** Wire to get commit's information from backwards time buffer. */
 +    typename TimeBuffer<TimeStruct>::wire fromCommit;
 +
 +    /** Internal fetch instruction queue. */
 +    TimeBuffer<FetchStruct> *fetchQueue;
 +
 +    //Might be annoying how this name is different than the queue.
 +    /** Wire used to write any information heading to decode. */
 +    typename TimeBuffer<FetchStruct>::wire toDecode;
 +
 +    MemObject *mem;
 +
 +    /** Icache interface. */
 +    IcachePort *icachePort;
 +
 +    /** BPredUnit. */
 +    BPredUnit branchPred;
 +
++    /** Per-thread fetch PC. */
 +    Addr PC[Impl::MaxThreads];
 +
++    /** Per-thread next PC. */
 +    Addr nextPC[Impl::MaxThreads];
 +
 +    /** Memory packet used to access cache. */
 +    PacketPtr memPkt[Impl::MaxThreads];
 +
 +    /** Variable that tracks if fetch has written to the time buffer this
 +     * cycle. Used to tell CPU if there is activity this cycle.
 +     */
 +    bool wroteToTimeBuffer;
 +
 +    /** Tracks how many instructions has been fetched this cycle. */
 +    int numInst;
 +
 +    /** Source of possible stalls. */
 +    struct Stalls {
 +        bool decode;
 +        bool rename;
 +        bool iew;
 +        bool commit;
 +    };
 +
 +    /** Tracks which stages are telling fetch to stall. */
 +    Stalls stalls[Impl::MaxThreads];
 +
 +    /** Decode to fetch delay, in ticks. */
 +    unsigned decodeToFetchDelay;
 +
 +    /** Rename to fetch delay, in ticks. */
 +    unsigned renameToFetchDelay;
 +
 +    /** IEW to fetch delay, in ticks. */
 +    unsigned iewToFetchDelay;
 +
 +    /** Commit to fetch delay, in ticks. */
 +    unsigned commitToFetchDelay;
 +
 +    /** The width of fetch in instructions. */
 +    unsigned fetchWidth;
 +
 +    /** Cache block size. */
 +    int cacheBlkSize;
 +
 +    /** Mask to get a cache block's address. */
 +    Addr cacheBlkMask;
 +
 +    /** The cache line being fetched. */
 +    uint8_t *cacheData[Impl::MaxThreads];
 +
 +    /** Size of instructions. */
 +    int instSize;
 +
 +    /** Icache stall statistics. */
 +    Counter lastIcacheStall[Impl::MaxThreads];
 +
 +    /** List of Active Threads */
 +    std::list<unsigned> *activeThreads;
 +
 +    /** Number of threads. */
 +    unsigned numThreads;
 +
 +    /** Number of threads that are actively fetching. */
 +    unsigned numFetchingThreads;
 +
 +    /** Thread ID being fetched. */
 +    int threadFetched;
 +
++    /** Checks if there is an interrupt pending.  If there is, fetch
++     * must stop once it is not fetching PAL instructions.
++     */
 +    bool interruptPending;
 +
++    /** Records if fetch is switched out. */
 +    bool switchedOut;
 +
 +#if !FULL_SYSTEM
 +    /** Page table pointer. */
 +//    PageTable *pTable;
 +#endif
 +
 +    // @todo: Consider making these vectors and tracking on a per thread basis.
 +    /** Stat for total number of cycles stalled due to an icache miss. */
 +    Stats::Scalar<> icacheStallCycles;
 +    /** Stat for total number of fetched instructions. */
 +    Stats::Scalar<> fetchedInsts;
 +    Stats::Scalar<> fetchedBranches;
 +    /** Stat for total number of predicted branches. */
 +    Stats::Scalar<> predictedBranches;
 +    /** Stat for total number of cycles spent fetching. */
 +    Stats::Scalar<> fetchCycles;
 +    /** Stat for total number of cycles spent squashing. */
 +    Stats::Scalar<> fetchSquashCycles;
 +    /** Stat for total number of cycles spent blocked due to other stages in
 +     * the pipeline.
 +     */
 +    Stats::Scalar<> fetchIdleCycles;
++    /** Total number of cycles spent blocked. */
 +    Stats::Scalar<> fetchBlockedCycles;
++    /** Total number of cycles spent in any other state. */
 +    Stats::Scalar<> fetchMiscStallCycles;
 +    /** Stat for total number of fetched cache lines. */
 +    Stats::Scalar<> fetchedCacheLines;
++    /** Total number of outstanding icache accesses that were dropped
++     * due to a squash.
++     */
 +    Stats::Scalar<> fetchIcacheSquashes;
 +    /** Distribution of number of instructions fetched each cycle. */
 +    Stats::Distribution<> fetchNisnDist;
++    /** Rate of how often fetch was idle. */
 +    Stats::Formula idleRate;
++    /** Number of branch fetches per cycle. */
 +    Stats::Formula branchRate;
++    /** Number of instruction fetched per cycle. */
 +    Stats::Formula fetchRate;
 +};
 +
 +#endif //__CPU_O3_FETCH_HH__
index 5d3164dbf963f8822926e6de8fd3351770276b61,0000000000000000000000000000000000000000..69c43a6a2267cc17a72087e402b1d1699e0ff9df
mode 100644,000000..100644
--- /dev/null
@@@ -1,1233 -1,0 +1,1235 @@@
-         .name(name() + ".FETCH:icacheStallCycles")
 +/*
 + * Copyright (c) 2004-2006 The Regents of The University of Michigan
 + * 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: Kevin Lim
 + */
 +
 +#include "arch/isa_traits.hh"
 +#include "arch/utility.hh"
 +#include "cpu/exetrace.hh"
 +#include "cpu/o3/fetch.hh"
 +#include "mem/packet.hh"
 +#include "mem/request.hh"
 +#include "sim/byteswap.hh"
 +#include "sim/host.hh"
 +#include "sim/root.hh"
 +
 +#if FULL_SYSTEM
 +#include "arch/tlb.hh"
 +#include "arch/vtophys.hh"
 +#include "base/remote_gdb.hh"
 +#include "mem/functional/memory_control.hh"
 +#include "mem/functional/physical.hh"
 +#include "sim/system.hh"
 +#endif // FULL_SYSTEM
 +
 +#include <algorithm>
 +
 +using namespace std;
 +using namespace TheISA;
 +
 +template<class Impl>
 +Tick
 +DefaultFetch<Impl>::IcachePort::recvAtomic(PacketPtr pkt)
 +{
 +    panic("DefaultFetch doesn't expect recvAtomic callback!");
 +    return curTick;
 +}
 +
 +template<class Impl>
 +void
 +DefaultFetch<Impl>::IcachePort::recvFunctional(PacketPtr pkt)
 +{
 +    panic("DefaultFetch doesn't expect recvFunctional callback!");
 +}
 +
 +template<class Impl>
 +void
 +DefaultFetch<Impl>::IcachePort::recvStatusChange(Status status)
 +{
 +    if (status == RangeChange)
 +        return;
 +
 +    panic("DefaultFetch doesn't expect recvStatusChange callback!");
 +}
 +
 +template<class Impl>
 +bool
 +DefaultFetch<Impl>::IcachePort::recvTiming(Packet *pkt)
 +{
 +    fetch->processCacheCompletion(pkt);
 +    return true;
 +}
 +
 +template<class Impl>
 +void
 +DefaultFetch<Impl>::IcachePort::recvRetry()
 +{
 +    panic("DefaultFetch doesn't support retry yet.");
 +    // we shouldn't get a retry unless we have a packet that we're
 +    // waiting to transmit
 +/*
 +    assert(cpu->dcache_pkt != NULL);
 +    assert(cpu->_status == DcacheRetry);
 +    Packet *tmp = cpu->dcache_pkt;
 +    if (sendTiming(tmp)) {
 +        cpu->_status = DcacheWaitResponse;
 +        cpu->dcache_pkt = NULL;
 +    }
 +*/
 +}
 +
 +template<class Impl>
 +DefaultFetch<Impl>::DefaultFetch(Params *params)
 +    : branchPred(params),
 +      decodeToFetchDelay(params->decodeToFetchDelay),
 +      renameToFetchDelay(params->renameToFetchDelay),
 +      iewToFetchDelay(params->iewToFetchDelay),
 +      commitToFetchDelay(params->commitToFetchDelay),
 +      fetchWidth(params->fetchWidth),
 +      numThreads(params->numberOfThreads),
 +      numFetchingThreads(params->smtNumFetchingThreads),
 +      interruptPending(false)
 +{
 +    if (numThreads > Impl::MaxThreads)
 +        fatal("numThreads is not a valid value\n");
 +
 +    DPRINTF(Fetch, "Fetch constructor called\n");
 +
 +    // Set fetch stage's status to inactive.
 +    _status = Inactive;
 +
 +    string policy = params->smtFetchPolicy;
 +
 +    // Convert string to lowercase
 +    std::transform(policy.begin(), policy.end(), policy.begin(),
 +                   (int(*)(int)) tolower);
 +
 +    // Figure out fetch policy
 +    if (policy == "singlethread") {
 +        fetchPolicy = SingleThread;
 +    } else if (policy == "roundrobin") {
 +        fetchPolicy = RoundRobin;
 +        DPRINTF(Fetch, "Fetch policy set to Round Robin\n");
 +    } else if (policy == "branch") {
 +        fetchPolicy = Branch;
 +        DPRINTF(Fetch, "Fetch policy set to Branch Count\n");
 +    } else if (policy == "iqcount") {
 +        fetchPolicy = IQ;
 +        DPRINTF(Fetch, "Fetch policy set to IQ count\n");
 +    } else if (policy == "lsqcount") {
 +        fetchPolicy = LSQ;
 +        DPRINTF(Fetch, "Fetch policy set to LSQ count\n");
 +    } else {
 +        fatal("Invalid Fetch Policy. Options Are: {SingleThread,"
 +              " RoundRobin,LSQcount,IQcount}\n");
 +    }
 +
 +    // Size of cache block.
 +    cacheBlkSize = 64;
 +
 +    // Create mask to get rid of offset bits.
 +    cacheBlkMask = (cacheBlkSize - 1);
 +
 +    for (int tid=0; tid < numThreads; tid++) {
 +
 +        fetchStatus[tid] = Running;
 +
 +        priorityList.push_back(tid);
 +
 +        memPkt[tid] = NULL;
 +
 +        // Create space to store a cache line.
 +        cacheData[tid] = new uint8_t[cacheBlkSize];
 +
 +        stalls[tid].decode = 0;
 +        stalls[tid].rename = 0;
 +        stalls[tid].iew = 0;
 +        stalls[tid].commit = 0;
 +    }
 +
 +    // Get the size of an instruction.
 +    instSize = sizeof(MachInst);
 +}
 +
 +template <class Impl>
 +std::string
 +DefaultFetch<Impl>::name() const
 +{
 +    return cpu->name() + ".fetch";
 +}
 +
 +template <class Impl>
 +void
 +DefaultFetch<Impl>::regStats()
 +{
 +    icacheStallCycles
-         .name(name() + ".FETCH:Insts")
++        .name(name() + ".icacheStallCycles")
 +        .desc("Number of cycles fetch is stalled on an Icache miss")
 +        .prereq(icacheStallCycles);
 +
 +    fetchedInsts
-         .name(name() + ".FETCH:Branches")
++        .name(name() + ".Insts")
 +        .desc("Number of instructions fetch has processed")
 +        .prereq(fetchedInsts);
 +
 +    fetchedBranches
-         .name(name() + ".FETCH:predictedBranches")
++        .name(name() + ".Branches")
 +        .desc("Number of branches that fetch encountered")
 +        .prereq(fetchedBranches);
 +
 +    predictedBranches
-         .name(name() + ".FETCH:Cycles")
++        .name(name() + ".predictedBranches")
 +        .desc("Number of branches that fetch has predicted taken")
 +        .prereq(predictedBranches);
 +
 +    fetchCycles
-         .name(name() + ".FETCH:SquashCycles")
++        .name(name() + ".Cycles")
 +        .desc("Number of cycles fetch has run and was not squashing or"
 +              " blocked")
 +        .prereq(fetchCycles);
 +
 +    fetchSquashCycles
-         .name(name() + ".FETCH:IdleCycles")
++        .name(name() + ".SquashCycles")
 +        .desc("Number of cycles fetch has spent squashing")
 +        .prereq(fetchSquashCycles);
 +
 +    fetchIdleCycles
-         .name(name() + ".FETCH:BlockedCycles")
++        .name(name() + ".IdleCycles")
 +        .desc("Number of cycles fetch was idle")
 +        .prereq(fetchIdleCycles);
 +
 +    fetchBlockedCycles
-         .name(name() + ".FETCH:CacheLines")
++        .name(name() + ".BlockedCycles")
 +        .desc("Number of cycles fetch has spent blocked")
 +        .prereq(fetchBlockedCycles);
 +
 +    fetchedCacheLines
-         .name(name() + ".FETCH:MiscStallCycles")
++        .name(name() + ".CacheLines")
 +        .desc("Number of cache lines fetched")
 +        .prereq(fetchedCacheLines);
 +
 +    fetchMiscStallCycles
-         .name(name() + ".FETCH:IcacheSquashes")
++        .name(name() + ".MiscStallCycles")
 +        .desc("Number of cycles fetch has spent waiting on interrupts, or "
 +              "bad addresses, or out of MSHRs")
 +        .prereq(fetchMiscStallCycles);
 +
 +    fetchIcacheSquashes
-         .name(name() + ".FETCH:rateDist")
++        .name(name() + ".IcacheSquashes")
 +        .desc("Number of outstanding Icache misses that were squashed")
 +        .prereq(fetchIcacheSquashes);
 +
 +    fetchNisnDist
 +        .init(/* base value */ 0,
 +              /* last value */ fetchWidth,
 +              /* bucket size */ 1)
-         .name(name() + ".FETCH:idleRate")
++        .name(name() + ".rateDist")
 +        .desc("Number of instructions fetched each cycle (Total)")
 +        .flags(Stats::pdf);
 +
 +    idleRate
-         .name(name() + ".FETCH:branchRate")
++        .name(name() + ".idleRate")
 +        .desc("Percent of cycles fetch was idle")
 +        .prereq(idleRate);
 +    idleRate = fetchIdleCycles * 100 / cpu->numCycles;
 +
 +    branchRate
-     branchRate = predictedBranches / cpu->numCycles;
++        .name(name() + ".branchRate")
 +        .desc("Number of branch fetches per cycle")
 +        .flags(Stats::total);
-         .name(name() + ".FETCH:rate")
++    branchRate = fetchedBranches / cpu->numCycles;
 +
 +    fetchRate
-     // Can keep track of how many cache accesses go unused due to
-     // misspeculation here.
++        .name(name() + ".rate")
 +        .desc("Number of inst fetches per cycle")
 +        .flags(Stats::total);
 +    fetchRate = fetchedInsts / cpu->numCycles;
 +
 +    branchPred.regStats();
 +}
 +
 +template<class Impl>
 +void
 +DefaultFetch<Impl>::setCPU(FullCPU *cpu_ptr)
 +{
 +    DPRINTF(Fetch, "Setting the CPU pointer.\n");
 +    cpu = cpu_ptr;
 +
 +    // Name is finally available, so create the port.
 +    icachePort = new IcachePort(this);
 +
 +    // Fetch needs to start fetching instructions at the very beginning,
 +    // so it must start up in active state.
 +    switchToActive();
 +}
 +
 +template<class Impl>
 +void
 +DefaultFetch<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *time_buffer)
 +{
 +    DPRINTF(Fetch, "Setting the time buffer pointer.\n");
 +    timeBuffer = time_buffer;
 +
 +    // Create wires to get information from proper places in time buffer.
 +    fromDecode = timeBuffer->getWire(-decodeToFetchDelay);
 +    fromRename = timeBuffer->getWire(-renameToFetchDelay);
 +    fromIEW = timeBuffer->getWire(-iewToFetchDelay);
 +    fromCommit = timeBuffer->getWire(-commitToFetchDelay);
 +}
 +
 +template<class Impl>
 +void
 +DefaultFetch<Impl>::setActiveThreads(list<unsigned> *at_ptr)
 +{
 +    DPRINTF(Fetch, "Setting active threads list pointer.\n");
 +    activeThreads = at_ptr;
 +}
 +
 +template<class Impl>
 +void
 +DefaultFetch<Impl>::setFetchQueue(TimeBuffer<FetchStruct> *fq_ptr)
 +{
 +    DPRINTF(Fetch, "Setting the fetch queue pointer.\n");
 +    fetchQueue = fq_ptr;
 +
 +    // Create wire to write information to proper place in fetch queue.
 +    toDecode = fetchQueue->getWire(0);
 +}
 +
 +#if 0
 +template<class Impl>
 +void
 +DefaultFetch<Impl>::setPageTable(PageTable *pt_ptr)
 +{
 +    DPRINTF(Fetch, "Setting the page table pointer.\n");
 +#if !FULL_SYSTEM
 +    pTable = pt_ptr;
 +#endif
 +}
 +#endif
 +
 +template<class Impl>
 +void
 +DefaultFetch<Impl>::initStage()
 +{
++    // Setup PC and nextPC with initial state.
 +    for (int tid = 0; tid < numThreads; tid++) {
 +        PC[tid] = cpu->readPC(tid);
 +        nextPC[tid] = cpu->readNextPC(tid);
 +    }
 +}
 +
 +template<class Impl>
 +void
 +DefaultFetch<Impl>::processCacheCompletion(PacketPtr pkt)
 +{
 +    unsigned tid = pkt->req->getThreadNum();
 +
 +    DPRINTF(Fetch, "[tid:%u] Waking up from cache miss.\n",tid);
 +
 +    // Only change the status if it's still waiting on the icache access
 +    // to return.
-            fetchStatus[high_pri] == Idle)
 +    if (fetchStatus[tid] != IcacheWaitResponse ||
 +        pkt != memPkt[tid] ||
 +        isSwitchedOut()) {
 +        ++fetchIcacheSquashes;
 +        delete pkt;
 +        return;
 +    }
 +
 +    // Wake up the CPU (if it went to sleep and was waiting on this completion
 +    // event).
 +    cpu->wakeCPU();
 +
 +    DPRINTF(Activity, "[tid:%u] Activating fetch due to cache completion\n",
 +            tid);
 +
 +    switchToActive();
 +
 +    // Only switch to IcacheAccessComplete if we're not stalled as well.
 +    if (checkStall(tid)) {
 +        fetchStatus[tid] = Blocked;
 +    } else {
 +        fetchStatus[tid] = IcacheAccessComplete;
 +    }
 +
 +//    memcpy(cacheData[tid], memReq[tid]->data, memReq[tid]->size);
 +
 +    // Reset the mem req to NULL.
 +    delete pkt->req;
 +    delete pkt;
 +    memPkt[tid] = NULL;
 +}
 +
 +template <class Impl>
 +void
 +DefaultFetch<Impl>::switchOut()
 +{
++    // Fetch is ready to switch out at any time.
 +    switchedOut = true;
 +    cpu->signalSwitched();
 +}
 +
 +template <class Impl>
 +void
 +DefaultFetch<Impl>::doSwitchOut()
 +{
++    // Branch predictor needs to have its state cleared.
 +    branchPred.switchOut();
 +}
 +
 +template <class Impl>
 +void
 +DefaultFetch<Impl>::takeOverFrom()
 +{
 +    // Reset all state
 +    for (int i = 0; i < Impl::MaxThreads; ++i) {
 +        stalls[i].decode = 0;
 +        stalls[i].rename = 0;
 +        stalls[i].iew = 0;
 +        stalls[i].commit = 0;
 +        PC[i] = cpu->readPC(i);
 +        nextPC[i] = cpu->readNextPC(i);
 +        fetchStatus[i] = Running;
 +    }
 +    numInst = 0;
 +    wroteToTimeBuffer = false;
 +    _status = Inactive;
 +    switchedOut = false;
 +    branchPred.takeOverFrom();
 +}
 +
 +template <class Impl>
 +void
 +DefaultFetch<Impl>::wakeFromQuiesce()
 +{
 +    DPRINTF(Fetch, "Waking up from quiesce\n");
 +    // Hopefully this is safe
++    // @todo: Allow other threads to wake from quiesce.
 +    fetchStatus[0] = Running;
 +}
 +
 +template <class Impl>
 +inline void
 +DefaultFetch<Impl>::switchToActive()
 +{
 +    if (_status == Inactive) {
 +        DPRINTF(Activity, "Activating stage.\n");
 +
 +        cpu->activateStage(FullCPU::FetchIdx);
 +
 +        _status = Active;
 +    }
 +}
 +
 +template <class Impl>
 +inline void
 +DefaultFetch<Impl>::switchToInactive()
 +{
 +    if (_status == Active) {
 +        DPRINTF(Activity, "Deactivating stage.\n");
 +
 +        cpu->deactivateStage(FullCPU::FetchIdx);
 +
 +        _status = Inactive;
 +    }
 +}
 +
 +template <class Impl>
 +bool
 +DefaultFetch<Impl>::lookupAndUpdateNextPC(DynInstPtr &inst, Addr &next_PC)
 +{
 +    // Do branch prediction check here.
 +    // A bit of a misnomer...next_PC is actually the current PC until
 +    // this function updates it.
 +    bool predict_taken;
 +
 +    if (!inst->isControl()) {
 +        next_PC = next_PC + instSize;
 +        inst->setPredTarg(next_PC);
 +        return false;
 +    }
 +
 +    predict_taken = branchPred.predict(inst, next_PC, inst->threadNumber);
 +
 +    ++fetchedBranches;
 +
 +    if (predict_taken) {
 +        ++predictedBranches;
 +    }
 +
 +    return predict_taken;
 +}
 +
 +template <class Impl>
 +bool
 +DefaultFetch<Impl>::fetchCacheLine(Addr fetch_PC, Fault &ret_fault, unsigned tid)
 +{
 +    Fault fault = NoFault;
 +
 +#if FULL_SYSTEM
 +    // Flag to say whether or not address is physical addr.
 +    unsigned flags = cpu->inPalMode(fetch_PC) ? PHYSICAL : 0;
 +#else
 +    unsigned flags = 0;
 +#endif // FULL_SYSTEM
 +
 +    if (interruptPending && flags == 0 || switchedOut) {
 +        // Hold off fetch from getting new instructions while an interrupt
 +        // is pending.
 +        return false;
 +    }
 +
 +    // Align the fetch PC so it's at the start of a cache block.
 +    fetch_PC = icacheBlockAlignPC(fetch_PC);
 +
 +    // Setup the memReq to do a read of the first instruction's address.
 +    // Set the appropriate read size and flags as well.
 +    // Build request here.
 +    RequestPtr mem_req = new Request(tid, fetch_PC, cacheBlkSize, flags,
 +                                     fetch_PC, cpu->readCpuId(), tid);
 +
 +    memPkt[tid] = NULL;
 +
 +    // Translate the instruction request.
 +//#if FULL_SYSTEM
 +    fault = cpu->translateInstReq(mem_req);
 +//#else
 +//    fault = pTable->translate(memReq[tid]);
 +//#endif
 +
 +    // In the case of faults, the fetch stage may need to stall and wait
 +    // for the ITB miss to be handled.
 +
 +    // If translation was successful, attempt to read the first
 +    // instruction.
 +    if (fault == NoFault) {
 +#if FULL_SYSTEM
 +        if (cpu->system->memctrl->badaddr(memReq[tid]->paddr) ||
 +            memReq[tid]->flags & UNCACHEABLE) {
 +            DPRINTF(Fetch, "Fetch: Bad address %#x (hopefully on a "
 +                    "misspeculating path)!",
 +                    memReq[tid]->paddr);
 +            ret_fault = TheISA::genMachineCheckFault();
 +            return false;
 +        }
 +#endif
 +
 +        // Build packet here.
 +        PacketPtr data_pkt = new Packet(mem_req,
 +                                        Packet::ReadReq, Packet::Broadcast);
 +        data_pkt->dataStatic(cacheData[tid]);
 +
 +        DPRINTF(Fetch, "Fetch: Doing instruction read.\n");
 +
 +        fetchedCacheLines++;
 +
 +        // Now do the timing access to see whether or not the instruction
 +        // exists within the cache.
 +        if (!icachePort->sendTiming(data_pkt)) {
 +            DPRINTF(Fetch, "[tid:%i] Out of MSHRs!\n", tid);
 +            ret_fault = NoFault;
 +            return false;
 +        }
 +
 +        DPRINTF(Fetch, "Doing cache access.\n");
 +
 +        lastIcacheStall[tid] = curTick;
 +
 +        DPRINTF(Activity, "[tid:%i]: Activity: Waiting on I-cache "
 +                "response.\n", tid);
 +
 +        fetchStatus[tid] = IcacheWaitResponse;
 +    }
 +
 +    ret_fault = fault;
 +    return true;
 +}
 +
 +template <class Impl>
 +inline void
 +DefaultFetch<Impl>::doSquash(const Addr &new_PC, unsigned tid)
 +{
 +    DPRINTF(Fetch, "[tid:%i]: Squashing, setting PC to: %#x.\n",
 +            tid, new_PC);
 +
 +    PC[tid] = new_PC;
 +    nextPC[tid] = new_PC + instSize;
 +
 +    // Clear the icache miss if it's outstanding.
 +    if (fetchStatus[tid] == IcacheWaitResponse) {
 +        DPRINTF(Fetch, "[tid:%i]: Squashing outstanding Icache miss.\n",
 +                tid);
 +        delete memPkt[tid];
 +        memPkt[tid] = NULL;
 +    }
 +
 +    fetchStatus[tid] = Squashing;
 +
 +    ++fetchSquashCycles;
 +}
 +
 +template<class Impl>
 +void
 +DefaultFetch<Impl>::squashFromDecode(const Addr &new_PC,
 +                                     const InstSeqNum &seq_num,
 +                                     unsigned tid)
 +{
 +    DPRINTF(Fetch, "[tid:%i]: Squashing from decode.\n",tid);
 +
 +    doSquash(new_PC, tid);
 +
 +    // Tell the CPU to remove any instructions that are in flight between
 +    // fetch and decode.
 +    cpu->removeInstsUntil(seq_num, tid);
 +}
 +
 +template<class Impl>
 +bool
 +DefaultFetch<Impl>::checkStall(unsigned tid) const
 +{
 +    bool ret_val = false;
 +
 +    if (cpu->contextSwitch) {
 +        DPRINTF(Fetch,"[tid:%i]: Stalling for a context switch.\n",tid);
 +        ret_val = true;
 +    } else if (stalls[tid].decode) {
 +        DPRINTF(Fetch,"[tid:%i]: Stall from Decode stage detected.\n",tid);
 +        ret_val = true;
 +    } else if (stalls[tid].rename) {
 +        DPRINTF(Fetch,"[tid:%i]: Stall from Rename stage detected.\n",tid);
 +        ret_val = true;
 +    } else if (stalls[tid].iew) {
 +        DPRINTF(Fetch,"[tid:%i]: Stall from IEW stage detected.\n",tid);
 +        ret_val = true;
 +    } else if (stalls[tid].commit) {
 +        DPRINTF(Fetch,"[tid:%i]: Stall from Commit stage detected.\n",tid);
 +        ret_val = true;
 +    }
 +
 +    return ret_val;
 +}
 +
 +template<class Impl>
 +typename DefaultFetch<Impl>::FetchStatus
 +DefaultFetch<Impl>::updateFetchStatus()
 +{
 +    //Check Running
 +    list<unsigned>::iterator threads = (*activeThreads).begin();
 +
 +    while (threads != (*activeThreads).end()) {
 +
 +        unsigned tid = *threads++;
 +
 +        if (fetchStatus[tid] == Running ||
 +            fetchStatus[tid] == Squashing ||
 +            fetchStatus[tid] == IcacheAccessComplete) {
 +
 +            if (_status == Inactive) {
 +                DPRINTF(Activity, "[tid:%i]: Activating stage.\n",tid);
 +
 +                if (fetchStatus[tid] == IcacheAccessComplete) {
 +                    DPRINTF(Activity, "[tid:%i]: Activating fetch due to cache"
 +                            "completion\n",tid);
 +                }
 +
 +                cpu->activateStage(FullCPU::FetchIdx);
 +            }
 +
 +            return Active;
 +        }
 +    }
 +
 +    // Stage is switching from active to inactive, notify CPU of it.
 +    if (_status == Active) {
 +        DPRINTF(Activity, "Deactivating stage.\n");
 +
 +        cpu->deactivateStage(FullCPU::FetchIdx);
 +    }
 +
 +    return Inactive;
 +}
 +
 +template <class Impl>
 +void
 +DefaultFetch<Impl>::squash(const Addr &new_PC, unsigned tid)
 +{
 +    DPRINTF(Fetch, "[tid:%u]: Squash from commit.\n",tid);
 +
 +    doSquash(new_PC, tid);
 +
 +    // Tell the CPU to remove any instructions that are not in the ROB.
 +    cpu->removeInstsNotInROB(tid);
 +}
 +
 +template <class Impl>
 +void
 +DefaultFetch<Impl>::tick()
 +{
 +    list<unsigned>::iterator threads = (*activeThreads).begin();
 +    bool status_change = false;
 +
 +    wroteToTimeBuffer = false;
 +
 +    while (threads != (*activeThreads).end()) {
 +        unsigned tid = *threads++;
 +
 +        // Check the signals for each thread to determine the proper status
 +        // for each thread.
 +        bool updated_status = checkSignalsAndUpdate(tid);
 +        status_change =  status_change || updated_status;
 +    }
 +
 +    DPRINTF(Fetch, "Running stage.\n");
 +
 +    // Reset the number of the instruction we're fetching.
 +    numInst = 0;
 +
 +    if (fromCommit->commitInfo[0].interruptPending) {
 +        interruptPending = true;
 +    }
 +    if (fromCommit->commitInfo[0].clearInterrupt) {
 +        interruptPending = false;
 +    }
 +
 +    for (threadFetched = 0; threadFetched < numFetchingThreads;
 +         threadFetched++) {
 +        // Fetch each of the actively fetching threads.
 +        fetch(status_change);
 +    }
 +
 +    // Record number of instructions fetched this cycle for distribution.
 +    fetchNisnDist.sample(numInst);
 +
 +    if (status_change) {
 +        // Change the fetch stage status if there was a status change.
 +        _status = updateFetchStatus();
 +    }
 +
 +    // If there was activity this cycle, inform the CPU of it.
 +    if (wroteToTimeBuffer || cpu->contextSwitch) {
 +        DPRINTF(Activity, "Activity this cycle.\n");
 +
 +        cpu->activityThisCycle();
 +    }
 +}
 +
 +template <class Impl>
 +bool
 +DefaultFetch<Impl>::checkSignalsAndUpdate(unsigned tid)
 +{
 +    // Update the per thread stall statuses.
 +    if (fromDecode->decodeBlock[tid]) {
 +        stalls[tid].decode = true;
 +    }
 +
 +    if (fromDecode->decodeUnblock[tid]) {
 +        assert(stalls[tid].decode);
 +        assert(!fromDecode->decodeBlock[tid]);
 +        stalls[tid].decode = false;
 +    }
 +
 +    if (fromRename->renameBlock[tid]) {
 +        stalls[tid].rename = true;
 +    }
 +
 +    if (fromRename->renameUnblock[tid]) {
 +        assert(stalls[tid].rename);
 +        assert(!fromRename->renameBlock[tid]);
 +        stalls[tid].rename = false;
 +    }
 +
 +    if (fromIEW->iewBlock[tid]) {
 +        stalls[tid].iew = true;
 +    }
 +
 +    if (fromIEW->iewUnblock[tid]) {
 +        assert(stalls[tid].iew);
 +        assert(!fromIEW->iewBlock[tid]);
 +        stalls[tid].iew = false;
 +    }
 +
 +    if (fromCommit->commitBlock[tid]) {
 +        stalls[tid].commit = true;
 +    }
 +
 +    if (fromCommit->commitUnblock[tid]) {
 +        assert(stalls[tid].commit);
 +        assert(!fromCommit->commitBlock[tid]);
 +        stalls[tid].commit = false;
 +    }
 +
 +    // Check squash signals from commit.
 +    if (fromCommit->commitInfo[tid].squash) {
 +
 +        DPRINTF(Fetch, "[tid:%u]: Squashing instructions due to squash "
 +                "from commit.\n",tid);
 +
 +        // In any case, squash.
 +        squash(fromCommit->commitInfo[tid].nextPC,tid);
 +
 +        // Also check if there's a mispredict that happened.
 +        if (fromCommit->commitInfo[tid].branchMispredict) {
 +            branchPred.squash(fromCommit->commitInfo[tid].doneSeqNum,
 +                              fromCommit->commitInfo[tid].nextPC,
 +                              fromCommit->commitInfo[tid].branchTaken,
 +                              tid);
 +        } else {
 +            branchPred.squash(fromCommit->commitInfo[tid].doneSeqNum,
 +                              tid);
 +        }
 +
 +        return true;
 +    } else if (fromCommit->commitInfo[tid].doneSeqNum) {
 +        // Update the branch predictor if it wasn't a squashed instruction
 +        // that was broadcasted.
 +        branchPred.update(fromCommit->commitInfo[tid].doneSeqNum, tid);
 +    }
 +
 +    // Check ROB squash signals from commit.
 +    if (fromCommit->commitInfo[tid].robSquashing) {
 +        DPRINTF(Fetch, "[tid:%u]: ROB is still squashing Thread %u.\n", tid);
 +
 +        // Continue to squash.
 +        fetchStatus[tid] = Squashing;
 +
 +        return true;
 +    }
 +
 +    // Check squash signals from decode.
 +    if (fromDecode->decodeInfo[tid].squash) {
 +        DPRINTF(Fetch, "[tid:%u]: Squashing instructions due to squash "
 +                "from decode.\n",tid);
 +
 +        // Update the branch predictor.
 +        if (fromDecode->decodeInfo[tid].branchMispredict) {
 +            branchPred.squash(fromDecode->decodeInfo[tid].doneSeqNum,
 +                              fromDecode->decodeInfo[tid].nextPC,
 +                              fromDecode->decodeInfo[tid].branchTaken,
 +                              tid);
 +        } else {
 +            branchPred.squash(fromDecode->decodeInfo[tid].doneSeqNum,
 +                              tid);
 +        }
 +
 +        if (fetchStatus[tid] != Squashing) {
 +            // Squash unless we're already squashing
 +            squashFromDecode(fromDecode->decodeInfo[tid].nextPC,
 +                             fromDecode->decodeInfo[tid].doneSeqNum,
 +                             tid);
 +
 +            return true;
 +        }
 +    }
 +
 +    if (checkStall(tid) && fetchStatus[tid] != IcacheWaitResponse) {
 +        DPRINTF(Fetch, "[tid:%i]: Setting to blocked\n",tid);
 +
 +        fetchStatus[tid] = Blocked;
 +
 +        return true;
 +    }
 +
 +    if (fetchStatus[tid] == Blocked ||
 +        fetchStatus[tid] == Squashing) {
 +        // Switch status to running if fetch isn't being told to block or
 +        // squash this cycle.
 +        DPRINTF(Fetch, "[tid:%i]: Done squashing, switching to running.\n",
 +                tid);
 +
 +        fetchStatus[tid] = Running;
 +
 +        return true;
 +    }
 +
 +    // If we've reached this point, we have not gotten any signals that
 +    // cause fetch to change its status.  Fetch remains the same as before.
 +    return false;
 +}
 +
 +template<class Impl>
 +void
 +DefaultFetch<Impl>::fetch(bool &status_change)
 +{
 +    //////////////////////////////////////////
 +    // Start actual fetch
 +    //////////////////////////////////////////
 +    int tid = getFetchingThread(fetchPolicy);
 +
 +    if (tid == -1) {
 +        DPRINTF(Fetch,"There are no more threads available to fetch from.\n");
 +
 +        // Breaks looping condition in tick()
 +        threadFetched = numFetchingThreads;
 +        return;
 +    }
 +
 +    // The current PC.
 +    Addr &fetch_PC = PC[tid];
 +
 +    // Fault code for memory access.
 +    Fault fault = NoFault;
 +
 +    // If returning from the delay of a cache miss, then update the status
 +    // to running, otherwise do the cache access.  Possibly move this up
 +    // to tick() function.
 +    if (fetchStatus[tid] == IcacheAccessComplete) {
 +        DPRINTF(Fetch, "[tid:%i]: Icache miss is complete.\n",
 +                tid);
 +
 +        fetchStatus[tid] = Running;
 +        status_change = true;
 +    } else if (fetchStatus[tid] == Running) {
 +        DPRINTF(Fetch, "[tid:%i]: Attempting to translate and read "
 +                "instruction, starting at PC %08p.\n",
 +                tid, fetch_PC);
 +
 +        bool fetch_success = fetchCacheLine(fetch_PC, fault, tid);
 +        if (!fetch_success) {
 +            ++fetchMiscStallCycles;
 +            return;
 +        }
 +    } else {
 +        if (fetchStatus[tid] == Idle) {
 +            ++fetchIdleCycles;
 +        } else if (fetchStatus[tid] == Blocked) {
 +            ++fetchBlockedCycles;
 +        } else if (fetchStatus[tid] == Squashing) {
 +            ++fetchSquashCycles;
 +        } else if (fetchStatus[tid] == IcacheWaitResponse) {
 +            ++icacheStallCycles;
 +        }
 +
 +        // Status is Idle, Squashing, Blocked, or IcacheWaitResponse, so
 +        // fetch should do nothing.
 +        return;
 +    }
 +
 +    ++fetchCycles;
 +
 +    // If we had a stall due to an icache miss, then return.
 +    if (fetchStatus[tid] == IcacheWaitResponse) {
 +        ++icacheStallCycles;
 +        status_change = true;
 +        return;
 +    }
 +
 +    Addr next_PC = fetch_PC;
 +    InstSeqNum inst_seq;
 +    MachInst inst;
 +    ExtMachInst ext_inst;
 +    // @todo: Fix this hack.
 +    unsigned offset = (fetch_PC & cacheBlkMask) & ~3;
 +
 +    if (fault == NoFault) {
 +        // If the read of the first instruction was successful, then grab the
 +        // instructions from the rest of the cache line and put them into the
 +        // queue heading to decode.
 +
 +        DPRINTF(Fetch, "[tid:%i]: Adding instructions to queue to "
 +                "decode.\n",tid);
 +
 +        // Need to keep track of whether or not a predicted branch
 +        // ended this fetch block.
 +        bool predicted_branch = false;
 +
 +        for (;
 +             offset < cacheBlkSize &&
 +                 numInst < fetchWidth &&
 +                 !predicted_branch;
 +             ++numInst) {
 +
 +            // Get a sequence number.
 +            inst_seq = cpu->getAndIncrementInstSeq();
 +
 +            // Make sure this is a valid index.
 +            assert(offset <= cacheBlkSize - instSize);
 +
 +            // Get the instruction from the array of the cache line.
 +            inst = gtoh(*reinterpret_cast<MachInst *>
 +                        (&cacheData[tid][offset]));
 +
 +            ext_inst = TheISA::makeExtMI(inst, fetch_PC);
 +
 +            // Create a new DynInst from the instruction fetched.
 +            DynInstPtr instruction = new DynInst(ext_inst, fetch_PC,
 +                                                 next_PC,
 +                                                 inst_seq, cpu);
 +            instruction->setThread(tid);
 +
 +            instruction->setASID(tid);
 +
 +            instruction->setState(cpu->thread[tid]);
 +
 +            DPRINTF(Fetch, "[tid:%i]: Instruction PC %#x created "
 +                    "[sn:%lli]\n",
 +                    tid, instruction->readPC(), inst_seq);
 +
 +            DPRINTF(Fetch, "[tid:%i]: Instruction is: %s\n",
 +                    tid, instruction->staticInst->disassemble(fetch_PC));
 +
 +            instruction->traceData =
 +                Trace::getInstRecord(curTick, cpu->xcBase(tid), cpu,
 +                                     instruction->staticInst,
 +                                     instruction->readPC(),tid);
 +
 +            predicted_branch = lookupAndUpdateNextPC(instruction, next_PC);
 +
 +            // Add instruction to the CPU's list of instructions.
 +            instruction->setInstListIt(cpu->addInst(instruction));
 +
 +            // Write the instruction to the first slot in the queue
 +            // that heads to decode.
 +            toDecode->insts[numInst] = instruction;
 +
 +            toDecode->size++;
 +
 +            // Increment stat of fetched instructions.
 +            ++fetchedInsts;
 +
 +            // Move to the next instruction, unless we have a branch.
 +            fetch_PC = next_PC;
 +
 +            if (instruction->isQuiesce()) {
 +                warn("%lli: Quiesce instruction encountered, halting fetch!",
 +                     curTick);
 +                fetchStatus[tid] = QuiescePending;
 +                ++numInst;
 +                status_change = true;
 +                break;
 +            }
 +
 +            offset+= instSize;
 +        }
 +    }
 +
 +    if (numInst > 0) {
 +        wroteToTimeBuffer = true;
 +    }
 +
 +    // Now that fetching is completed, update the PC to signify what the next
 +    // cycle will be.
 +    if (fault == NoFault) {
 +        DPRINTF(Fetch, "[tid:%i]: Setting PC to %08p.\n",tid, next_PC);
 +
 +        PC[tid] = next_PC;
 +        nextPC[tid] = next_PC + instSize;
 +    } else {
 +        // We shouldn't be in an icache miss and also have a fault (an ITB
 +        // miss)
 +        if (fetchStatus[tid] == IcacheWaitResponse) {
 +            panic("Fetch should have exited prior to this!");
 +        }
 +
 +        // Send the fault to commit.  This thread will not do anything
 +        // until commit handles the fault.  The only other way it can
 +        // wake up is if a squash comes along and changes the PC.
 +#if FULL_SYSTEM
 +        assert(numInst != fetchWidth);
 +        // Get a sequence number.
 +        inst_seq = cpu->getAndIncrementInstSeq();
 +        // We will use a nop in order to carry the fault.
 +        ext_inst = TheISA::NoopMachInst;
 +
 +        // Create a new DynInst from the dummy nop.
 +        DynInstPtr instruction = new DynInst(ext_inst, fetch_PC,
 +                                             next_PC,
 +                                             inst_seq, cpu);
 +        instruction->setPredTarg(next_PC + instSize);
 +        instruction->setThread(tid);
 +
 +        instruction->setASID(tid);
 +
 +        instruction->setState(cpu->thread[tid]);
 +
 +        instruction->traceData = NULL;
 +
 +        instruction->setInstListIt(cpu->addInst(instruction));
 +
 +        instruction->fault = fault;
 +
 +        toDecode->insts[numInst] = instruction;
 +        toDecode->size++;
 +
 +        DPRINTF(Fetch, "[tid:%i]: Blocked, need to handle the trap.\n",tid);
 +
 +        fetchStatus[tid] = TrapPending;
 +        status_change = true;
 +
 +        warn("%lli fault (%d) detected @ PC %08p", curTick, fault, PC[tid]);
 +#else // !FULL_SYSTEM
 +        fatal("fault (%d) detected @ PC %08p", fault, PC[tid]);
 +#endif // FULL_SYSTEM
 +    }
 +}
 +
 +
 +///////////////////////////////////////
 +//                                   //
 +//  SMT FETCH POLICY MAINTAINED HERE //
 +//                                   //
 +///////////////////////////////////////
 +template<class Impl>
 +int
 +DefaultFetch<Impl>::getFetchingThread(FetchPriority &fetch_priority)
 +{
 +    if (numThreads > 1) {
 +        switch (fetch_priority) {
 +
 +          case SingleThread:
 +            return 0;
 +
 +          case RoundRobin:
 +            return roundRobin();
 +
 +          case IQ:
 +            return iqCount();
 +
 +          case LSQ:
 +            return lsqCount();
 +
 +          case Branch:
 +            return branchCount();
 +
 +          default:
 +            return -1;
 +        }
 +    } else {
 +        int tid = *((*activeThreads).begin());
 +
 +        if (fetchStatus[tid] == Running ||
 +            fetchStatus[tid] == IcacheAccessComplete ||
 +            fetchStatus[tid] == Idle) {
 +            return tid;
 +        } else {
 +            return -1;
 +        }
 +    }
 +
 +}
 +
 +
 +template<class Impl>
 +int
 +DefaultFetch<Impl>::roundRobin()
 +{
 +    list<unsigned>::iterator pri_iter = priorityList.begin();
 +    list<unsigned>::iterator end      = priorityList.end();
 +
 +    int high_pri;
 +
 +    while (pri_iter != end) {
 +        high_pri = *pri_iter;
 +
 +        assert(high_pri <= numThreads);
 +
 +        if (fetchStatus[high_pri] == Running ||
 +            fetchStatus[high_pri] == IcacheAccessComplete ||
 +            fetchStatus[high_pri] == Idle) {
 +
 +            priorityList.erase(pri_iter);
 +            priorityList.push_back(high_pri);
 +
 +            return high_pri;
 +        }
 +
 +        pri_iter++;
 +    }
 +
 +    return -1;
 +}
 +
 +template<class Impl>
 +int
 +DefaultFetch<Impl>::iqCount()
 +{
 +    priority_queue<unsigned> PQ;
 +
 +    list<unsigned>::iterator threads = (*activeThreads).begin();
 +
 +    while (threads != (*activeThreads).end()) {
 +        unsigned tid = *threads++;
 +
 +        PQ.push(fromIEW->iewInfo[tid].iqCount);
 +    }
 +
 +    while (!PQ.empty()) {
 +
 +        unsigned high_pri = PQ.top();
 +
 +        if (fetchStatus[high_pri] == Running ||
 +            fetchStatus[high_pri] == IcacheAccessComplete ||
 +            fetchStatus[high_pri] == Idle)
 +            return high_pri;
 +        else
 +            PQ.pop();
 +
 +    }
 +
 +    return -1;
 +}
 +
 +template<class Impl>
 +int
 +DefaultFetch<Impl>::lsqCount()
 +{
 +    priority_queue<unsigned> PQ;
 +
 +
 +    list<unsigned>::iterator threads = (*activeThreads).begin();
 +
 +    while (threads != (*activeThreads).end()) {
 +        unsigned tid = *threads++;
 +
 +        PQ.push(fromIEW->iewInfo[tid].ldstqCount);
 +    }
 +
 +    while (!PQ.empty()) {
 +
 +        unsigned high_pri = PQ.top();
 +
 +        if (fetchStatus[high_pri] == Running ||
 +            fetchStatus[high_pri] == IcacheAccessComplete ||
++            fetchStatus[high_pri] == Idle)
 +            return high_pri;
 +        else
 +            PQ.pop();
 +
 +    }
 +
 +    return -1;
 +}
 +
 +template<class Impl>
 +int
 +DefaultFetch<Impl>::branchCount()
 +{
 +    list<unsigned>::iterator threads = (*activeThreads).begin();
 +
 +    return *threads;
 +}
index fb2b5c00d399fe3914ca53364ccd812455b6f879,0000000000000000000000000000000000000000..b28b5d37f7386c0cbfbf6217c21942343c270541
mode 100644,000000..100644
--- /dev/null
@@@ -1,295 -1,0 +1,297 @@@
 +/*
 + * Copyright (c) 2002-2005 The Regents of The University of Michigan
 + * 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.
 + */
 +
 +#include <sstream>
 +
 +#include "cpu/o3/fu_pool.hh"
 +#include "encumbered/cpu/full/fu_pool.hh"
 +#include "sim/builder.hh"
 +
 +using namespace std;
 +
 +////////////////////////////////////////////////////////////////////////////
 +//
 +//  A pool of function units
 +//
 +
 +inline void
 +FUPool::FUIdxQueue::addFU(int fu_idx)
 +{
 +    funcUnitsIdx.push_back(fu_idx);
 +    ++size;
 +}
 +
 +inline int
 +FUPool::FUIdxQueue::getFU()
 +{
 +    int retval = funcUnitsIdx[idx++];
 +
 +    if (idx == size)
 +        idx = 0;
 +
 +    return retval;
 +}
 +
 +FUPool::~FUPool()
 +{
 +    fuListIterator i = funcUnits.begin();
 +    fuListIterator end = funcUnits.end();
 +    for (; i != end; ++i)
 +        delete *i;
 +}
 +
 +
 +// Constructor
 +FUPool::FUPool(string name, vector<FUDesc *> paramList)
 +    : SimObject(name)
 +{
 +    numFU = 0;
 +
 +    funcUnits.clear();
 +
 +    for (int i = 0; i < Num_OpClasses; ++i) {
 +        maxOpLatencies[i] = 0;
 +        maxIssueLatencies[i] = 0;
 +    }
 +
 +    //
 +    //  Iterate through the list of FUDescData structures
 +    //
 +    for (FUDDiterator i = paramList.begin(); i != paramList.end(); ++i) {
 +
 +        //
 +        //  Don't bother with this if we're not going to create any FU's
 +        //
 +        if ((*i)->number) {
 +            //
 +            //  Create the FuncUnit object from this structure
 +            //   - add the capabilities listed in the FU's operation
 +            //     description
 +            //
 +            //  We create the first unit, then duplicate it as needed
 +            //
 +            FuncUnit *fu = new FuncUnit;
 +
 +            OPDDiterator j = (*i)->opDescList.begin();
 +            OPDDiterator end = (*i)->opDescList.end();
 +            for (; j != end; ++j) {
 +                // indicate that this pool has this capability
 +                capabilityList.set((*j)->opClass);
 +
 +                // Add each of the FU's that will have this capability to the
 +                // appropriate queue.
 +                for (int k = 0; k < (*i)->number; ++k)
 +                    fuPerCapList[(*j)->opClass].addFU(numFU + k);
 +
 +                // indicate that this FU has the capability
 +                fu->addCapability((*j)->opClass, (*j)->opLat, (*j)->issueLat);
 +
 +                if ((*j)->opLat > maxOpLatencies[(*j)->opClass])
 +                    maxOpLatencies[(*j)->opClass] = (*j)->opLat;
 +
 +                if ((*j)->issueLat > maxIssueLatencies[(*j)->opClass])
 +                    maxIssueLatencies[(*j)->opClass] = (*j)->issueLat;
 +            }
 +
 +            numFU++;
 +
 +            //  Add the appropriate number of copies of this FU to the list
 +            ostringstream s;
 +
 +            s << (*i)->name() << "(0)";
 +            fu->name = s.str();
 +            funcUnits.push_back(fu);
 +
 +            for (int c = 1; c < (*i)->number; ++c) {
 +                ostringstream s;
 +                numFU++;
 +                FuncUnit *fu2 = new FuncUnit(*fu);
 +
 +                s << (*i)->name() << "(" << c << ")";
 +                fu2->name = s.str();
 +                funcUnits.push_back(fu2);
 +            }
 +        }
 +    }
 +
 +    unitBusy.resize(numFU);
 +
 +    for (int i = 0; i < numFU; i++) {
 +        unitBusy[i] = false;
 +    }
 +}
 +
 +void
 +FUPool::annotateMemoryUnits(unsigned hit_latency)
 +{
 +    maxOpLatencies[MemReadOp] = hit_latency;
 +
 +    fuListIterator i = funcUnits.begin();
 +    fuListIterator iend = funcUnits.end();
 +    for (; i != iend; ++i) {
 +        if ((*i)->provides(MemReadOp))
 +            (*i)->opLatency(MemReadOp) = hit_latency;
 +
 +        if ((*i)->provides(MemWriteOp))
 +            (*i)->opLatency(MemWriteOp) = hit_latency;
 +    }
 +}
 +
 +int
 +FUPool::getUnit(OpClass capability)
 +{
 +    //  If this pool doesn't have the specified capability,
 +    //  return this information to the caller
 +    if (!capabilityList[capability])
 +        return -2;
 +
 +    int fu_idx = fuPerCapList[capability].getFU();
 +    int start_idx = fu_idx;
 +
 +    // Iterate through the circular queue if needed, stopping if we've reached
 +    // the first element again.
 +    while (unitBusy[fu_idx]) {
 +        fu_idx = fuPerCapList[capability].getFU();
 +        if (fu_idx == start_idx) {
 +            // No FU available
 +            return -1;
 +        }
 +    }
 +
++    assert(fu_idx < numFU);
++
 +    unitBusy[fu_idx] = true;
 +
 +    return fu_idx;
 +}
 +
 +void
 +FUPool::freeUnitNextCycle(int fu_idx)
 +{
 +    assert(unitBusy[fu_idx]);
 +    unitsToBeFreed.push_back(fu_idx);
 +}
 +
 +void
 +FUPool::processFreeUnits()
 +{
 +    while (!unitsToBeFreed.empty()) {
 +        int fu_idx = unitsToBeFreed.back();
 +        unitsToBeFreed.pop_back();
 +
 +        assert(unitBusy[fu_idx]);
 +
 +        unitBusy[fu_idx] = false;
 +    }
 +}
 +
 +void
 +FUPool::dump()
 +{
 +    cout << "Function Unit Pool (" << name() << ")\n";
 +    cout << "======================================\n";
 +    cout << "Free List:\n";
 +
 +    for (int i = 0; i < numFU; ++i) {
 +        if (unitBusy[i]) {
 +            continue;
 +        }
 +
 +        cout << "  [" << i << "] : ";
 +
 +        cout << funcUnits[i]->name << " ";
 +
 +        cout << "\n";
 +    }
 +
 +    cout << "======================================\n";
 +    cout << "Busy List:\n";
 +    for (int i = 0; i < numFU; ++i) {
 +        if (!unitBusy[i]) {
 +            continue;
 +        }
 +
 +        cout << "  [" << i << "] : ";
 +
 +        cout << funcUnits[i]->name << " ";
 +
 +        cout << "\n";
 +    }
 +}
 +
 +void
 +FUPool::switchOut()
 +{
 +}
 +
 +void
 +FUPool::takeOverFrom()
 +{
 +    for (int i = 0; i < numFU; i++) {
 +        unitBusy[i] = false;
 +    }
 +    unitsToBeFreed.clear();
 +}
 +
 +//
 +
 +////////////////////////////////////////////////////////////////////////////
 +//
 +//  The SimObjects we use to get the FU information into the simulator
 +//
 +////////////////////////////////////////////////////////////////////////////
 +
 +//
 +//    FUPool - Contails a list of FUDesc objects to make available
 +//
 +
 +//
 +//  The FuPool object
 +//
 +
 +BEGIN_DECLARE_SIM_OBJECT_PARAMS(FUPool)
 +
 +    SimObjectVectorParam<FUDesc *> FUList;
 +
 +END_DECLARE_SIM_OBJECT_PARAMS(FUPool)
 +
 +
 +BEGIN_INIT_SIM_OBJECT_PARAMS(FUPool)
 +
 +    INIT_PARAM(FUList, "list of FU's for this pool")
 +
 +END_INIT_SIM_OBJECT_PARAMS(FUPool)
 +
 +
 +CREATE_SIM_OBJECT(FUPool)
 +{
 +    return new FUPool(getInstanceName(), FUList);
 +}
 +
 +REGISTER_SIM_OBJECT("FUPool", FUPool)
 +
index f590c41497e07575cefec0784e23ac5073fb9af2,0000000000000000000000000000000000000000..1d4c766903fc4ce01a0ff0bacf3e708e663bc376
mode 100644,000000..100644
--- /dev/null
@@@ -1,162 -1,0 +1,165 @@@
 +/*
 + * Copyright (c) 2002-2005 The Regents of The University of Michigan
 + * 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.
 + */
 +
 +#ifndef __CPU_O3_FU_POOL_HH__
 +#define __CPU_O3_FU_POOL_HH__
 +
 +#include <bitset>
 +#include <list>
 +#include <string>
 +#include <vector>
 +
 +#include "base/sched_list.hh"
 +#include "cpu/op_class.hh"
 +#include "sim/sim_object.hh"
 +
 +class FUDesc;
 +class FuncUnit;
 +
 +/**
 + * Pool of FU's, specific to the new CPU model. The old FU pool had lists of
 + * free units and busy units, and whenever a FU was needed it would iterate
 + * through the free units to find a FU that provided the capability. This pool
 + * has lists of units specific to each of the capabilities, and whenever a FU
 + * is needed, it iterates through that list to find a free unit. The previous
 + * FU pool would have to be ticked each cycle to update which units became
 + * free. This FU pool lets the IEW stage handle freeing units, which frees
 + * them as their scheduled execution events complete. This limits units in this
 + * model to either have identical issue and op latencies, or 1 cycle issue
 + * latencies.
 + */
 +class FUPool : public SimObject
 +{
 +  private:
 +    /** Maximum op execution latencies, per op class. */
 +    unsigned maxOpLatencies[Num_OpClasses];
 +    /** Maximum issue latencies, per op class. */
 +    unsigned maxIssueLatencies[Num_OpClasses];
 +
 +    /** Bitvector listing capabilities of this FU pool. */
 +    std::bitset<Num_OpClasses> capabilityList;
 +
 +    /** Bitvector listing which FUs are busy. */
 +    std::vector<bool> unitBusy;
 +
 +    /** List of units to be freed at the end of this cycle. */
 +    std::vector<int> unitsToBeFreed;
 +
 +    /**
 +     * Class that implements a circular queue to hold FU indices. The hope is
 +     * that FUs that have been just used will be moved to the end of the queue
 +     * by iterating through it, thus leaving free units at the head of the
 +     * queue.
 +     */
 +    class FUIdxQueue {
 +      public:
 +        /** Constructs a circular queue of FU indices. */
 +        FUIdxQueue()
 +            : idx(0), size(0)
 +        { }
 +
 +        /** Adds a FU to the queue. */
 +        inline void addFU(int fu_idx);
 +
 +        /** Returns the index of the FU at the head of the queue, and changes
 +         *  the index to the next element.
 +         */
 +        inline int getFU();
 +
 +      private:
 +        /** Circular queue index. */
 +        int idx;
 +
 +        /** Size of the queue. */
 +        int size;
 +
 +        /** Queue of FU indices. */
 +        std::vector<int> funcUnitsIdx;
 +    };
 +
 +    /** Per op class queues of FUs that provide that capability. */
 +    FUIdxQueue fuPerCapList[Num_OpClasses];
 +
 +    /** Number of FUs. */
 +    int numFU;
 +
 +    /** Functional units. */
 +    std::vector<FuncUnit *> funcUnits;
 +
 +    typedef std::vector<FuncUnit *>::iterator fuListIterator;
 +
 +  public:
 +
 +    /** Constructs a FU pool. */
 +    FUPool(std::string name, std::vector<FUDesc *> l);
 +    ~FUPool();
 +
 +    /** Annotates units that provide memory operations. Included only because
 +     *  old FU pool provided this function.
 +     */
 +    void annotateMemoryUnits(unsigned hit_latency);
 +
 +    /**
 +     * Gets a FU providing the requested capability. Will mark the unit as busy,
 +     * but leaves the freeing of the unit up to the IEW stage.
 +     * @param capability The capability requested.
 +     * @return Returns -2 if the FU pool does not have the capability, -1 if
 +     * there is no free FU, and the FU's index otherwise.
 +     */
 +    int getUnit(OpClass capability);
 +
 +    /** Frees a FU at the end of this cycle. */
 +    void freeUnitNextCycle(int fu_idx);
 +
 +    /** Frees all FUs on the list. */
 +    void processFreeUnits();
 +
 +    /** Returns the total number of FUs. */
 +    int size() { return numFU; }
 +
 +    /** Debugging function used to dump FU information. */
 +    void dump();
 +
 +    /** Returns the operation execution latency of the given capability. */
 +    unsigned getOpLatency(OpClass capability) {
 +        return maxOpLatencies[capability];
 +    }
 +
 +    /** Returns the issue latency of the given capability. */
 +    unsigned getIssueLatency(OpClass capability) {
 +        return maxIssueLatencies[capability];
 +    }
 +
++    /** Switches out functional unit pool. */
 +    void switchOut();
++
++    /** Takes over from another CPU's thread. */
 +    void takeOverFrom();
 +};
 +
 +#endif // __CPU_O3_FU_POOL_HH__
index ae86536c92f9c3ba04ae6ed607e4e55989adfac8,0000000000000000000000000000000000000000..7e79d5311235db39c5dc0200b297eabda605ccfb
mode 100644,000000..100644
--- /dev/null
@@@ -1,484 -1,0 +1,505 @@@
 +/*
 + * Copyright (c) 2004-2006 The Regents of The University of Michigan
 + * 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: Kevin Lim
 + */
 +
 +#ifndef __CPU_O3_IEW_HH__
 +#define __CPU_O3_IEW_HH__
 +
 +#include <queue>
 +
 +#include "base/statistics.hh"
 +#include "base/timebuf.hh"
 +#include "config/full_system.hh"
 +#include "cpu/o3/comm.hh"
 +#include "cpu/o3/scoreboard.hh"
 +#include "cpu/o3/lsq.hh"
 +
 +class FUPool;
 +
 +/**
 + * DefaultIEW handles both single threaded and SMT IEW
 + * (issue/execute/writeback).  It handles the dispatching of
 + * instructions to the LSQ/IQ as part of the issue stage, and has the
 + * IQ try to issue instructions each cycle. The execute latency is
 + * actually tied into the issue latency to allow the IQ to be able to
 + * do back-to-back scheduling without having to speculatively schedule
 + * instructions. This happens by having the IQ have access to the
 + * functional units, and the IQ gets the execution latencies from the
 + * FUs when it issues instructions. Instructions reach the execute
 + * stage on the last cycle of their execution, which is when the IQ
 + * knows to wake up any dependent instructions, allowing back to back
 + * scheduling. The execute portion of IEW separates memory
 + * instructions from non-memory instructions, either telling the LSQ
 + * to execute the instruction, or executing the instruction directly.
 + * The writeback portion of IEW completes the instructions by waking
 + * up any dependents, and marking the register ready on the
 + * scoreboard.
 + */
 +template<class Impl>
 +class DefaultIEW
 +{
 +  private:
 +    //Typedefs from Impl
 +    typedef typename Impl::CPUPol CPUPol;
 +    typedef typename Impl::DynInstPtr DynInstPtr;
 +    typedef typename Impl::FullCPU FullCPU;
 +    typedef typename Impl::Params Params;
 +
 +    typedef typename CPUPol::IQ IQ;
 +    typedef typename CPUPol::RenameMap RenameMap;
 +    typedef typename CPUPol::LSQ LSQ;
 +
 +    typedef typename CPUPol::TimeStruct TimeStruct;
 +    typedef typename CPUPol::IEWStruct IEWStruct;
 +    typedef typename CPUPol::RenameStruct RenameStruct;
 +    typedef typename CPUPol::IssueStruct IssueStruct;
 +
 +    friend class Impl::FullCPU;
 +    friend class CPUPol::IQ;
 +
 +  public:
 +    /** Overall IEW stage status. Used to determine if the CPU can
 +     * deschedule itself due to a lack of activity.
 +     */
 +    enum Status {
 +        Active,
 +        Inactive
 +    };
 +
 +    /** Status for Issue, Execute, and Writeback stages. */
 +    enum StageStatus {
 +        Running,
 +        Blocked,
 +        Idle,
 +        StartSquash,
 +        Squashing,
 +        Unblocking
 +    };
 +
 +  private:
 +    /** Overall stage status. */
 +    Status _status;
 +    /** Dispatch status. */
 +    StageStatus dispatchStatus[Impl::MaxThreads];
 +    /** Execute status. */
 +    StageStatus exeStatus;
 +    /** Writeback status. */
 +    StageStatus wbStatus;
 +
 +  public:
 +    /** Constructs a DefaultIEW with the given parameters. */
 +    DefaultIEW(Params *params);
 +
 +    /** Returns the name of the DefaultIEW stage. */
 +    std::string name() const;
 +
 +    /** Registers statistics. */
 +    void regStats();
 +
 +    /** Initializes stage; sends back the number of free IQ and LSQ entries. */
 +    void initStage();
 +
 +    /** Sets CPU pointer for IEW, IQ, and LSQ. */
 +    void setCPU(FullCPU *cpu_ptr);
 +
 +    /** Sets main time buffer used for backwards communication. */
 +    void setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr);
 +
 +    /** Sets time buffer for getting instructions coming from rename. */
 +    void setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr);
 +
 +    /** Sets time buffer to pass on instructions to commit. */
 +    void setIEWQueue(TimeBuffer<IEWStruct> *iq_ptr);
 +
 +    /** Sets pointer to list of active threads. */
 +    void setActiveThreads(std::list<unsigned> *at_ptr);
 +
 +    /** Sets pointer to the scoreboard. */
 +    void setScoreboard(Scoreboard *sb_ptr);
 +
++    /** Starts switch out of IEW stage. */
 +    void switchOut();
 +
++    /** Completes switch out of IEW stage. */
 +    void doSwitchOut();
 +
++    /** Takes over from another CPU's thread. */
 +    void takeOverFrom();
 +
++    /** Returns if IEW is switched out. */
 +    bool isSwitchedOut() { return switchedOut; }
 +
 +    /** Sets page table pointer within LSQ. */
 +//    void setPageTable(PageTable *pt_ptr);
 +
 +    /** Squashes instructions in IEW for a specific thread. */
 +    void squash(unsigned tid);
 +
 +    /** Wakes all dependents of a completed instruction. */
 +    void wakeDependents(DynInstPtr &inst);
 +
 +    /** Tells memory dependence unit that a memory instruction needs to be
 +     * rescheduled. It will re-execute once replayMemInst() is called.
 +     */
 +    void rescheduleMemInst(DynInstPtr &inst);
 +
 +    /** Re-executes all rescheduled memory instructions. */
 +    void replayMemInst(DynInstPtr &inst);
 +
 +    /** Sends an instruction to commit through the time buffer. */
 +    void instToCommit(DynInstPtr &inst);
 +
 +    /** Inserts unused instructions of a thread into the skid buffer. */
 +    void skidInsert(unsigned tid);
 +
 +    /** Returns the max of the number of entries in all of the skid buffers. */
 +    int skidCount();
 +
 +    /** Returns if all of the skid buffers are empty. */
 +    bool skidsEmpty();
 +
 +    /** Updates overall IEW status based on all of the stages' statuses. */
 +    void updateStatus();
 +
 +    /** Resets entries of the IQ and the LSQ. */
 +    void resetEntries();
 +
 +    /** Tells the CPU to wakeup if it has descheduled itself due to no
 +     * activity. Used mainly by the LdWritebackEvent.
 +     */
 +    void wakeCPU();
 +
 +    /** Reports to the CPU that there is activity this cycle. */
 +    void activityThisCycle();
 +
 +    /** Tells CPU that the IEW stage is active and running. */
 +    inline void activateStage();
 +
 +    /** Tells CPU that the IEW stage is inactive and idle. */
 +    inline void deactivateStage();
 +
 +    /** Returns if the LSQ has any stores to writeback. */
 +    bool hasStoresToWB() { return ldstQueue.hasStoresToWB(); }
 +
 +  private:
 +    /** Sends commit proper information for a squash due to a branch
 +     * mispredict.
 +     */
 +    void squashDueToBranch(DynInstPtr &inst, unsigned thread_id);
 +
 +    /** Sends commit proper information for a squash due to a memory order
 +     * violation.
 +     */
 +    void squashDueToMemOrder(DynInstPtr &inst, unsigned thread_id);
 +
 +    /** Sends commit proper information for a squash due to memory becoming
 +     * blocked (younger issued instructions must be retried).
 +     */
 +    void squashDueToMemBlocked(DynInstPtr &inst, unsigned thread_id);
 +
 +    /** Sets Dispatch to blocked, and signals back to other stages to block. */
 +    void block(unsigned thread_id);
 +
 +    /** Unblocks Dispatch if the skid buffer is empty, and signals back to
 +     * other stages to unblock.
 +     */
 +    void unblock(unsigned thread_id);
 +
 +    /** Determines proper actions to take given Dispatch's status. */
 +    void dispatch(unsigned tid);
 +
 +    /** Dispatches instructions to IQ and LSQ. */
 +    void dispatchInsts(unsigned tid);
 +
 +    /** Executes instructions. In the case of memory operations, it informs the
 +     * LSQ to execute the instructions. Also handles any redirects that occur
 +     * due to the executed instructions.
 +     */
 +    void executeInsts();
 +
 +    /** Writebacks instructions. In our model, the instruction's execute()
 +     * function atomically reads registers, executes, and writes registers.
 +     * Thus this writeback only wakes up dependent instructions, and informs
 +     * the scoreboard of registers becoming ready.
 +     */
 +    void writebackInsts();
 +
 +    /** Returns the number of valid, non-squashed instructions coming from
 +     * rename to dispatch.
 +     */
 +    unsigned validInstsFromRename();
 +
 +    /** Reads the stall signals. */
 +    void readStallSignals(unsigned tid);
 +
 +    /** Checks if any of the stall conditions are currently true. */
 +    bool checkStall(unsigned tid);
 +
 +    /** Processes inputs and changes state accordingly. */
 +    void checkSignalsAndUpdate(unsigned tid);
 +
 +    /** Sorts instructions coming from rename into lists separated by thread. */
 +    void sortInsts();
 +
 +  public:
 +    /** Ticks IEW stage, causing Dispatch, the IQ, the LSQ, Execute, and
 +     * Writeback to run for one cycle.
 +     */
 +    void tick();
 +
 +  private:
++    /** Updates execution stats based on the instruction. */
 +    void updateExeInstStats(DynInstPtr &inst);
 +
 +    /** Pointer to main time buffer used for backwards communication. */
 +    TimeBuffer<TimeStruct> *timeBuffer;
 +
 +    /** Wire to write information heading to previous stages. */
 +    typename TimeBuffer<TimeStruct>::wire toFetch;
 +
 +    /** Wire to get commit's output from backwards time buffer. */
 +    typename TimeBuffer<TimeStruct>::wire fromCommit;
 +
 +    /** Wire to write information heading to previous stages. */
 +    typename TimeBuffer<TimeStruct>::wire toRename;
 +
 +    /** Rename instruction queue interface. */
 +    TimeBuffer<RenameStruct> *renameQueue;
 +
 +    /** Wire to get rename's output from rename queue. */
 +    typename TimeBuffer<RenameStruct>::wire fromRename;
 +
 +    /** Issue stage queue. */
 +    TimeBuffer<IssueStruct> issueToExecQueue;
 +
 +    /** Wire to read information from the issue stage time queue. */
 +    typename TimeBuffer<IssueStruct>::wire fromIssue;
 +
 +    /**
 +     * IEW stage time buffer.  Holds ROB indices of instructions that
 +     * can be marked as completed.
 +     */
 +    TimeBuffer<IEWStruct> *iewQueue;
 +
 +    /** Wire to write infromation heading to commit. */
 +    typename TimeBuffer<IEWStruct>::wire toCommit;
 +
 +    /** Queue of all instructions coming from rename this cycle. */
 +    std::queue<DynInstPtr> insts[Impl::MaxThreads];
 +
 +    /** Skid buffer between rename and IEW. */
 +    std::queue<DynInstPtr> skidBuffer[Impl::MaxThreads];
 +
 +    /** Scoreboard pointer. */
 +    Scoreboard* scoreboard;
 +
 +  public:
 +    /** Instruction queue. */
 +    IQ instQueue;
 +
 +    /** Load / store queue. */
 +    LSQ ldstQueue;
 +
 +    /** Pointer to the functional unit pool. */
 +    FUPool *fuPool;
 +
 +  private:
 +    /** CPU pointer. */
 +    FullCPU *cpu;
 +
 +    /** Records if IEW has written to the time buffer this cycle, so that the
 +     * CPU can deschedule itself if there is no activity.
 +     */
 +    bool wroteToTimeBuffer;
 +
 +    /** Source of possible stalls. */
 +    struct Stalls {
 +        bool commit;
 +    };
 +
 +    /** Stages that are telling IEW to stall. */
 +    Stalls stalls[Impl::MaxThreads];
 +
 +    /** Debug function to print instructions that are issued this cycle. */
 +    void printAvailableInsts();
 +
 +  public:
 +    /** Records if the LSQ needs to be updated on the next cycle, so that
 +     * IEW knows if there will be activity on the next cycle.
 +     */
 +    bool updateLSQNextCycle;
 +
 +  private:
 +    /** Records if there is a fetch redirect on this cycle for each thread. */
 +    bool fetchRedirect[Impl::MaxThreads];
 +
 +    /** Used to track if all instructions have been dispatched this cycle.
 +     * If they have not, then blocking must have occurred, and the instructions
 +     * would already be added to the skid buffer.
 +     * @todo: Fix this hack.
 +     */
 +    bool dispatchedAllInsts;
 +
 +    /** Records if the queues have been changed (inserted or issued insts),
 +     * so that IEW knows to broadcast the updated amount of free entries.
 +     */
 +    bool updatedQueues;
 +
 +    /** Commit to IEW delay, in ticks. */
 +    unsigned commitToIEWDelay;
 +
 +    /** Rename to IEW delay, in ticks. */
 +    unsigned renameToIEWDelay;
 +
 +    /**
 +     * Issue to execute delay, in ticks.  What this actually represents is
 +     * the amount of time it takes for an instruction to wake up, be
 +     * scheduled, and sent to a FU for execution.
 +     */
 +    unsigned issueToExecuteDelay;
 +
 +    /** Width of issue's read path, in instructions.  The read path is both
 +     *  the skid buffer and the rename instruction queue.
 +     *  Note to self: is this really different than issueWidth?
 +     */
 +    unsigned issueReadWidth;
 +
 +    /** Width of issue, in instructions. */
 +    unsigned issueWidth;
 +
 +    /** Width of execute, in instructions.  Might make more sense to break
 +     *  down into FP vs int.
 +     */
 +    unsigned executeWidth;
 +
 +    /** Index into queue of instructions being written back. */
 +    unsigned wbNumInst;
 +
 +    /** Cycle number within the queue of instructions being written back.
 +     * Used in case there are too many instructions writing back at the current
 +     * cycle and writesbacks need to be scheduled for the future. See comments
 +     * in instToCommit().
 +     */
 +    unsigned wbCycle;
 +
 +    /** Number of active threads. */
 +    unsigned numThreads;
 +
 +    /** Pointer to list of active threads. */
 +    std::list<unsigned> *activeThreads;
 +
 +    /** Maximum size of the skid buffer. */
 +    unsigned skidBufferMax;
 +
++    /** Is this stage switched out. */
 +    bool switchedOut;
 +
 +    /** Stat for total number of idle cycles. */
 +    Stats::Scalar<> iewIdleCycles;
 +    /** Stat for total number of squashing cycles. */
 +    Stats::Scalar<> iewSquashCycles;
 +    /** Stat for total number of blocking cycles. */
 +    Stats::Scalar<> iewBlockCycles;
 +    /** Stat for total number of unblocking cycles. */
 +    Stats::Scalar<> iewUnblockCycles;
 +    /** Stat for total number of instructions dispatched. */
 +    Stats::Scalar<> iewDispatchedInsts;
 +    /** Stat for total number of squashed instructions dispatch skips. */
 +    Stats::Scalar<> iewDispSquashedInsts;
 +    /** Stat for total number of dispatched load instructions. */
 +    Stats::Scalar<> iewDispLoadInsts;
 +    /** Stat for total number of dispatched store instructions. */
 +    Stats::Scalar<> iewDispStoreInsts;
 +    /** Stat for total number of dispatched non speculative instructions. */
 +    Stats::Scalar<> iewDispNonSpecInsts;
 +    /** Stat for number of times the IQ becomes full. */
 +    Stats::Scalar<> iewIQFullEvents;
 +    /** Stat for number of times the LSQ becomes full. */
 +    Stats::Scalar<> iewLSQFullEvents;
 +    /** Stat for total number of executed instructions. */
 +    Stats::Scalar<> iewExecutedInsts;
 +    /** Stat for total number of executed load instructions. */
 +    Stats::Vector<> iewExecLoadInsts;
 +    /** Stat for total number of executed store instructions. */
 +//    Stats::Scalar<> iewExecStoreInsts;
 +    /** Stat for total number of squashed instructions skipped at execute. */
 +    Stats::Scalar<> iewExecSquashedInsts;
 +    /** Stat for total number of memory ordering violation events. */
 +    Stats::Scalar<> memOrderViolationEvents;
 +    /** Stat for total number of incorrect predicted taken branches. */
 +    Stats::Scalar<> predictedTakenIncorrect;
 +    /** Stat for total number of incorrect predicted not taken branches. */
 +    Stats::Scalar<> predictedNotTakenIncorrect;
 +    /** Stat for total number of mispredicted branches detected at execute. */
 +    Stats::Formula branchMispredicts;
 +
++    /** Number of executed software prefetches. */
 +    Stats::Vector<> exeSwp;
++    /** Number of executed nops. */
 +    Stats::Vector<> exeNop;
++    /** Number of executed meomory references. */
 +    Stats::Vector<> exeRefs;
++    /** Number of executed branches. */
 +    Stats::Vector<> exeBranches;
 +
 +//    Stats::Vector<> issued_ops;
 +/*
 +    Stats::Vector<> stat_fu_busy;
 +    Stats::Vector2d<> stat_fuBusy;
 +    Stats::Vector<> dist_unissued;
 +    Stats::Vector2d<> stat_issued_inst_type;
 +*/
++    /** Number of instructions issued per cycle. */
 +    Stats::Formula issueRate;
++    /** Number of executed store instructions. */
 +    Stats::Formula iewExecStoreInsts;
 +//    Stats::Formula issue_op_rate;
 +//    Stats::Formula fu_busy_rate;
++    /** Number of instructions sent to commit. */
 +    Stats::Vector<> iewInstsToCommit;
++    /** Number of instructions that writeback. */
 +    Stats::Vector<> writebackCount;
++    /** Number of instructions that wake consumers. */
 +    Stats::Vector<> producerInst;
++    /** Number of instructions that wake up from producers. */
 +    Stats::Vector<> consumerInst;
++    /** Number of instructions that were delayed in writing back due
++     * to resource contention.
++     */
 +    Stats::Vector<> wbPenalized;
 +
++    /** Number of instructions per cycle written back. */
 +    Stats::Formula wbRate;
++    /** Average number of woken instructions per writeback. */
 +    Stats::Formula wbFanout;
++    /** Number of instructions per cycle delayed in writing back . */
 +    Stats::Formula wbPenalizedRate;
 +};
 +
 +#endif // __CPU_O3_IEW_HH__
index 6b61b1b0e8786182c7e828afe0b7efb37c15a388,0000000000000000000000000000000000000000..23f1015177945253765164ebececcc27c7792292
mode 100644,000000..100644
--- /dev/null
@@@ -1,1528 -1,0 +1,1537 @@@
-             producerInst[tid]++;
-             consumerInst[tid]+= dependents;
 +/*
 + * Copyright (c) 2004-2006 The Regents of The University of Michigan
 + * 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: Kevin Lim
 + */
 +
 +// @todo: Fix the instantaneous communication among all the stages within
 +// iew.  There's a clear delay between issue and execute, yet backwards
 +// communication happens simultaneously.
 +
 +#include <queue>
 +
 +#include "base/timebuf.hh"
 +#include "cpu/o3/fu_pool.hh"
 +#include "cpu/o3/iew.hh"
 +
 +using namespace std;
 +
 +template<class Impl>
 +DefaultIEW<Impl>::DefaultIEW(Params *params)
 +    : // @todo: Make this into a parameter.
 +      issueToExecQueue(5, 5),
 +      instQueue(params),
 +      ldstQueue(params),
 +      fuPool(params->fuPool),
 +      commitToIEWDelay(params->commitToIEWDelay),
 +      renameToIEWDelay(params->renameToIEWDelay),
 +      issueToExecuteDelay(params->issueToExecuteDelay),
 +      issueReadWidth(params->issueWidth),
 +      issueWidth(params->issueWidth),
 +      executeWidth(params->executeWidth),
 +      numThreads(params->numberOfThreads),
 +      switchedOut(false)
 +{
 +    _status = Active;
 +    exeStatus = Running;
 +    wbStatus = Idle;
 +
 +    // Setup wire to read instructions coming from issue.
 +    fromIssue = issueToExecQueue.getWire(-issueToExecuteDelay);
 +
 +    // Instruction queue needs the queue between issue and execute.
 +    instQueue.setIssueToExecuteQueue(&issueToExecQueue);
 +
 +    instQueue.setIEW(this);
 +    ldstQueue.setIEW(this);
 +
 +    for (int i=0; i < numThreads; i++) {
 +        dispatchStatus[i] = Running;
 +        stalls[i].commit = false;
 +        fetchRedirect[i] = false;
 +    }
 +
 +    updateLSQNextCycle = false;
 +
 +    skidBufferMax = (3 * (renameToIEWDelay * params->renameWidth)) + issueWidth;
 +}
 +
 +template <class Impl>
 +std::string
 +DefaultIEW<Impl>::name() const
 +{
 +    return cpu->name() + ".iew";
 +}
 +
 +template <class Impl>
 +void
 +DefaultIEW<Impl>::regStats()
 +{
 +    using namespace Stats;
 +
 +    instQueue.regStats();
 +
 +    iewIdleCycles
 +        .name(name() + ".iewIdleCycles")
 +        .desc("Number of cycles IEW is idle");
 +
 +    iewSquashCycles
 +        .name(name() + ".iewSquashCycles")
 +        .desc("Number of cycles IEW is squashing");
 +
 +    iewBlockCycles
 +        .name(name() + ".iewBlockCycles")
 +        .desc("Number of cycles IEW is blocking");
 +
 +    iewUnblockCycles
 +        .name(name() + ".iewUnblockCycles")
 +        .desc("Number of cycles IEW is unblocking");
 +
 +    iewDispatchedInsts
 +        .name(name() + ".iewDispatchedInsts")
 +        .desc("Number of instructions dispatched to IQ");
 +
 +    iewDispSquashedInsts
 +        .name(name() + ".iewDispSquashedInsts")
 +        .desc("Number of squashed instructions skipped by dispatch");
 +
 +    iewDispLoadInsts
 +        .name(name() + ".iewDispLoadInsts")
 +        .desc("Number of dispatched load instructions");
 +
 +    iewDispStoreInsts
 +        .name(name() + ".iewDispStoreInsts")
 +        .desc("Number of dispatched store instructions");
 +
 +    iewDispNonSpecInsts
 +        .name(name() + ".iewDispNonSpecInsts")
 +        .desc("Number of dispatched non-speculative instructions");
 +
 +    iewIQFullEvents
 +        .name(name() + ".iewIQFullEvents")
 +        .desc("Number of times the IQ has become full, causing a stall");
 +
 +    iewLSQFullEvents
 +        .name(name() + ".iewLSQFullEvents")
 +        .desc("Number of times the LSQ has become full, causing a stall");
 +
 +    iewExecutedInsts
 +        .name(name() + ".iewExecutedInsts")
 +        .desc("Number of executed instructions");
 +
 +    iewExecLoadInsts
 +        .init(cpu->number_of_threads)
 +        .name(name() + ".iewExecLoadInsts")
 +        .desc("Number of load instructions executed")
 +        .flags(total);
 +
 +    iewExecSquashedInsts
 +        .name(name() + ".iewExecSquashedInsts")
 +        .desc("Number of squashed instructions skipped in execute");
 +
 +    memOrderViolationEvents
 +        .name(name() + ".memOrderViolationEvents")
 +        .desc("Number of memory order violations");
 +
 +    predictedTakenIncorrect
 +        .name(name() + ".predictedTakenIncorrect")
 +        .desc("Number of branches that were predicted taken incorrectly");
 +
 +    predictedNotTakenIncorrect
 +        .name(name() + ".predictedNotTakenIncorrect")
 +        .desc("Number of branches that were predicted not taken incorrectly");
 +
 +    branchMispredicts
 +        .name(name() + ".branchMispredicts")
 +        .desc("Number of branch mispredicts detected at execute");
 +
 +    branchMispredicts = predictedTakenIncorrect + predictedNotTakenIncorrect;
 +
 +    exeSwp
 +        .init(cpu->number_of_threads)
 +        .name(name() + ".EXEC:swp")
 +        .desc("number of swp insts executed")
 +        .flags(total)
 +        ;
 +
 +    exeNop
 +        .init(cpu->number_of_threads)
 +        .name(name() + ".EXEC:nop")
 +        .desc("number of nop insts executed")
 +        .flags(total)
 +        ;
 +
 +    exeRefs
 +        .init(cpu->number_of_threads)
 +        .name(name() + ".EXEC:refs")
 +        .desc("number of memory reference insts executed")
 +        .flags(total)
 +        ;
 +
 +    exeBranches
 +        .init(cpu->number_of_threads)
 +        .name(name() + ".EXEC:branches")
 +        .desc("Number of branches executed")
 +        .flags(total)
 +        ;
 +
 +    issueRate
 +        .name(name() + ".EXEC:rate")
 +        .desc("Inst execution rate")
 +        .flags(total)
 +        ;
 +    issueRate = iewExecutedInsts / cpu->numCycles;
 +
 +    iewExecStoreInsts
 +        .name(name() + ".EXEC:stores")
 +        .desc("Number of stores executed")
 +        .flags(total)
 +        ;
 +    iewExecStoreInsts = exeRefs - iewExecLoadInsts;
 +/*
 +    for (int i=0; i<Num_OpClasses; ++i) {
 +        stringstream subname;
 +        subname << opClassStrings[i] << "_delay";
 +        issue_delay_dist.subname(i, subname.str());
 +    }
 +*/
 +    //
 +    //  Other stats
 +    //
 +
 +    iewInstsToCommit
 +        .init(cpu->number_of_threads)
 +        .name(name() + ".WB:sent")
 +        .desc("cumulative count of insts sent to commit")
 +        .flags(total)
 +        ;
 +
 +    writebackCount
 +        .init(cpu->number_of_threads)
 +        .name(name() + ".WB:count")
 +        .desc("cumulative count of insts written-back")
 +        .flags(total)
 +        ;
 +
 +    producerInst
 +        .init(cpu->number_of_threads)
 +        .name(name() + ".WB:producers")
 +        .desc("num instructions producing a value")
 +        .flags(total)
 +        ;
 +
 +    consumerInst
 +        .init(cpu->number_of_threads)
 +        .name(name() + ".WB:consumers")
 +        .desc("num instructions consuming a value")
 +        .flags(total)
 +        ;
 +
 +    wbPenalized
 +        .init(cpu->number_of_threads)
 +        .name(name() + ".WB:penalized")
 +        .desc("number of instrctions required to write to 'other' IQ")
 +        .flags(total)
 +        ;
 +
 +    wbPenalizedRate
 +        .name(name() + ".WB:penalized_rate")
 +        .desc ("fraction of instructions written-back that wrote to 'other' IQ")
 +        .flags(total)
 +        ;
 +
 +    wbPenalizedRate = wbPenalized / writebackCount;
 +
 +    wbFanout
 +        .name(name() + ".WB:fanout")
 +        .desc("average fanout of values written-back")
 +        .flags(total)
 +        ;
 +
 +    wbFanout = producerInst / consumerInst;
 +
 +    wbRate
 +        .name(name() + ".WB:rate")
 +        .desc("insts written-back per cycle")
 +        .flags(total)
 +        ;
 +    wbRate = writebackCount / cpu->numCycles;
 +}
 +
 +template<class Impl>
 +void
 +DefaultIEW<Impl>::initStage()
 +{
 +    for (int tid=0; tid < numThreads; tid++) {
 +        toRename->iewInfo[tid].usedIQ = true;
 +        toRename->iewInfo[tid].freeIQEntries =
 +            instQueue.numFreeEntries(tid);
 +
 +        toRename->iewInfo[tid].usedLSQ = true;
 +        toRename->iewInfo[tid].freeLSQEntries =
 +            ldstQueue.numFreeEntries(tid);
 +    }
 +}
 +
 +template<class Impl>
 +void
 +DefaultIEW<Impl>::setCPU(FullCPU *cpu_ptr)
 +{
 +    DPRINTF(IEW, "Setting CPU pointer.\n");
 +    cpu = cpu_ptr;
 +
 +    instQueue.setCPU(cpu_ptr);
 +    ldstQueue.setCPU(cpu_ptr);
 +
 +    cpu->activateStage(FullCPU::IEWIdx);
 +}
 +
 +template<class Impl>
 +void
 +DefaultIEW<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr)
 +{
 +    DPRINTF(IEW, "Setting time buffer pointer.\n");
 +    timeBuffer = tb_ptr;
 +
 +    // Setup wire to read information from time buffer, from commit.
 +    fromCommit = timeBuffer->getWire(-commitToIEWDelay);
 +
 +    // Setup wire to write information back to previous stages.
 +    toRename = timeBuffer->getWire(0);
 +
 +    toFetch = timeBuffer->getWire(0);
 +
 +    // Instruction queue also needs main time buffer.
 +    instQueue.setTimeBuffer(tb_ptr);
 +}
 +
 +template<class Impl>
 +void
 +DefaultIEW<Impl>::setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr)
 +{
 +    DPRINTF(IEW, "Setting rename queue pointer.\n");
 +    renameQueue = rq_ptr;
 +
 +    // Setup wire to read information from rename queue.
 +    fromRename = renameQueue->getWire(-renameToIEWDelay);
 +}
 +
 +template<class Impl>
 +void
 +DefaultIEW<Impl>::setIEWQueue(TimeBuffer<IEWStruct> *iq_ptr)
 +{
 +    DPRINTF(IEW, "Setting IEW queue pointer.\n");
 +    iewQueue = iq_ptr;
 +
 +    // Setup wire to write instructions to commit.
 +    toCommit = iewQueue->getWire(0);
 +}
 +
 +template<class Impl>
 +void
 +DefaultIEW<Impl>::setActiveThreads(list<unsigned> *at_ptr)
 +{
 +    DPRINTF(IEW, "Setting active threads list pointer.\n");
 +    activeThreads = at_ptr;
 +
 +    ldstQueue.setActiveThreads(at_ptr);
 +    instQueue.setActiveThreads(at_ptr);
 +}
 +
 +template<class Impl>
 +void
 +DefaultIEW<Impl>::setScoreboard(Scoreboard *sb_ptr)
 +{
 +    DPRINTF(IEW, "Setting scoreboard pointer.\n");
 +    scoreboard = sb_ptr;
 +}
 +
 +#if 0
 +template<class Impl>
 +void
 +DefaultIEW<Impl>::setPageTable(PageTable *pt_ptr)
 +{
 +    ldstQueue.setPageTable(pt_ptr);
 +}
 +#endif
 +
 +template <class Impl>
 +void
 +DefaultIEW<Impl>::switchOut()
 +{
++    // IEW is ready to switch out at any time.
 +    cpu->signalSwitched();
 +}
 +
 +template <class Impl>
 +void
 +DefaultIEW<Impl>::doSwitchOut()
 +{
++    // Clear any state.
 +    switchedOut = true;
 +
 +    instQueue.switchOut();
 +    ldstQueue.switchOut();
 +    fuPool->switchOut();
 +
 +    for (int i = 0; i < numThreads; i++) {
 +        while (!insts[i].empty())
 +            insts[i].pop();
 +        while (!skidBuffer[i].empty())
 +            skidBuffer[i].pop();
 +    }
 +}
 +
 +template <class Impl>
 +void
 +DefaultIEW<Impl>::takeOverFrom()
 +{
++    // Reset all state.
 +    _status = Active;
 +    exeStatus = Running;
 +    wbStatus = Idle;
 +    switchedOut = false;
 +
 +    instQueue.takeOverFrom();
 +    ldstQueue.takeOverFrom();
 +    fuPool->takeOverFrom();
 +
 +    initStage();
 +    cpu->activityThisCycle();
 +
 +    for (int i=0; i < numThreads; i++) {
 +        dispatchStatus[i] = Running;
 +        stalls[i].commit = false;
 +        fetchRedirect[i] = false;
 +    }
 +
 +    updateLSQNextCycle = false;
 +
 +    // @todo: Fix hardcoded number
 +    for (int i = 0; i < 6; ++i) {
 +        issueToExecQueue.advance();
 +    }
 +}
 +
 +template<class Impl>
 +void
 +DefaultIEW<Impl>::squash(unsigned tid)
 +{
 +    DPRINTF(IEW, "[tid:%i]: Squashing all instructions.\n",
 +            tid);
 +
 +    // Tell the IQ to start squashing.
 +    instQueue.squash(tid);
 +
 +    // Tell the LDSTQ to start squashing.
 +    ldstQueue.squash(fromCommit->commitInfo[tid].doneSeqNum, tid);
 +
 +    updatedQueues = true;
 +
 +    // Clear the skid buffer in case it has any data in it.
 +    while (!skidBuffer[tid].empty()) {
 +
 +        if (skidBuffer[tid].front()->isLoad() ||
 +            skidBuffer[tid].front()->isStore() ) {
 +            toRename->iewInfo[tid].dispatchedToLSQ++;
 +        }
 +
 +        toRename->iewInfo[tid].dispatched++;
 +
 +        skidBuffer[tid].pop();
 +    }
 +
 +    while (!insts[tid].empty()) {
 +        if (insts[tid].front()->isLoad() ||
 +            insts[tid].front()->isStore() ) {
 +            toRename->iewInfo[tid].dispatchedToLSQ++;
 +        }
 +
 +        toRename->iewInfo[tid].dispatched++;
 +
 +        insts[tid].pop();
 +    }
 +}
 +
 +template<class Impl>
 +void
 +DefaultIEW<Impl>::squashDueToBranch(DynInstPtr &inst, unsigned tid)
 +{
 +    DPRINTF(IEW, "[tid:%i]: Squashing from a specific instruction, PC: %#x "
 +            "[sn:%i].\n", tid, inst->readPC(), inst->seqNum);
 +
 +    toCommit->squash[tid] = true;
 +    toCommit->squashedSeqNum[tid] = inst->seqNum;
 +    toCommit->mispredPC[tid] = inst->readPC();
 +    toCommit->nextPC[tid] = inst->readNextPC();
 +    toCommit->branchMispredict[tid] = true;
 +    toCommit->branchTaken[tid] = inst->readNextPC() !=
 +        (inst->readPC() + sizeof(TheISA::MachInst));
 +
 +    toCommit->includeSquashInst[tid] = false;
 +
 +    wroteToTimeBuffer = true;
 +}
 +
 +template<class Impl>
 +void
 +DefaultIEW<Impl>::squashDueToMemOrder(DynInstPtr &inst, unsigned tid)
 +{
 +    DPRINTF(IEW, "[tid:%i]: Squashing from a specific instruction, "
 +            "PC: %#x [sn:%i].\n", tid, inst->readPC(), inst->seqNum);
 +
 +    toCommit->squash[tid] = true;
 +    toCommit->squashedSeqNum[tid] = inst->seqNum;
 +    toCommit->nextPC[tid] = inst->readNextPC();
 +
 +    toCommit->includeSquashInst[tid] = false;
 +
 +    wroteToTimeBuffer = true;
 +}
 +
 +template<class Impl>
 +void
 +DefaultIEW<Impl>::squashDueToMemBlocked(DynInstPtr &inst, unsigned tid)
 +{
 +    DPRINTF(IEW, "[tid:%i]: Memory blocked, squashing load and younger insts, "
 +            "PC: %#x [sn:%i].\n", tid, inst->readPC(), inst->seqNum);
 +
 +    toCommit->squash[tid] = true;
 +    toCommit->squashedSeqNum[tid] = inst->seqNum;
 +    toCommit->nextPC[tid] = inst->readPC();
 +
++    // Must include the broadcasted SN in the squash.
 +    toCommit->includeSquashInst[tid] = true;
 +
 +    ldstQueue.setLoadBlockedHandled(tid);
 +
 +    wroteToTimeBuffer = true;
 +}
 +
 +template<class Impl>
 +void
 +DefaultIEW<Impl>::block(unsigned tid)
 +{
 +    DPRINTF(IEW, "[tid:%u]: Blocking.\n", tid);
 +
 +    if (dispatchStatus[tid] != Blocked &&
 +        dispatchStatus[tid] != Unblocking) {
 +        toRename->iewBlock[tid] = true;
 +        wroteToTimeBuffer = true;
 +    }
 +
 +    // Add the current inputs to the skid buffer so they can be
 +    // reprocessed when this stage unblocks.
 +    skidInsert(tid);
 +
 +    dispatchStatus[tid] = Blocked;
 +}
 +
 +template<class Impl>
 +void
 +DefaultIEW<Impl>::unblock(unsigned tid)
 +{
 +    DPRINTF(IEW, "[tid:%i]: Reading instructions out of the skid "
 +            "buffer %u.\n",tid, tid);
 +
 +    // If the skid bufffer is empty, signal back to previous stages to unblock.
 +    // Also switch status to running.
 +    if (skidBuffer[tid].empty()) {
 +        toRename->iewUnblock[tid] = true;
 +        wroteToTimeBuffer = true;
 +        DPRINTF(IEW, "[tid:%i]: Done unblocking.\n",tid);
 +        dispatchStatus[tid] = Running;
 +    }
 +}
 +
 +template<class Impl>
 +void
 +DefaultIEW<Impl>::wakeDependents(DynInstPtr &inst)
 +{
 +    instQueue.wakeDependents(inst);
 +}
 +
 +template<class Impl>
 +void
 +DefaultIEW<Impl>::rescheduleMemInst(DynInstPtr &inst)
 +{
 +    instQueue.rescheduleMemInst(inst);
 +}
 +
 +template<class Impl>
 +void
 +DefaultIEW<Impl>::replayMemInst(DynInstPtr &inst)
 +{
 +    instQueue.replayMemInst(inst);
 +}
 +
 +template<class Impl>
 +void
 +DefaultIEW<Impl>::instToCommit(DynInstPtr &inst)
 +{
 +    // First check the time slot that this instruction will write
 +    // to.  If there are free write ports at the time, then go ahead
 +    // and write the instruction to that time.  If there are not,
 +    // keep looking back to see where's the first time there's a
 +    // free slot.
 +    while ((*iewQueue)[wbCycle].insts[wbNumInst]) {
 +        ++wbNumInst;
 +        if (wbNumInst == issueWidth) {
 +            ++wbCycle;
 +            wbNumInst = 0;
 +        }
 +
 +        assert(wbCycle < 5);
 +    }
 +
 +    // Add finished instruction to queue to commit.
 +    (*iewQueue)[wbCycle].insts[wbNumInst] = inst;
 +    (*iewQueue)[wbCycle].size++;
 +}
 +
 +template <class Impl>
 +unsigned
 +DefaultIEW<Impl>::validInstsFromRename()
 +{
 +    unsigned inst_count = 0;
 +
 +    for (int i=0; i<fromRename->size; i++) {
 +        if (!fromRename->insts[i]->squashed)
 +            inst_count++;
 +    }
 +
 +    return inst_count;
 +}
 +
 +template<class Impl>
 +void
 +DefaultIEW<Impl>::skidInsert(unsigned tid)
 +{
 +    DynInstPtr inst = NULL;
 +
 +    while (!insts[tid].empty()) {
 +        inst = insts[tid].front();
 +
 +        insts[tid].pop();
 +
 +        DPRINTF(Decode,"[tid:%i]: Inserting [sn:%lli] PC:%#x into "
 +                "dispatch skidBuffer %i\n",tid, inst->seqNum,
 +                inst->readPC(),tid);
 +
 +        skidBuffer[tid].push(inst);
 +    }
 +
 +    assert(skidBuffer[tid].size() <= skidBufferMax &&
 +           "Skidbuffer Exceeded Max Size");
 +}
 +
 +template<class Impl>
 +int
 +DefaultIEW<Impl>::skidCount()
 +{
 +    int max=0;
 +
 +    list<unsigned>::iterator threads = (*activeThreads).begin();
 +
 +    while (threads != (*activeThreads).end()) {
 +        unsigned thread_count = skidBuffer[*threads++].size();
 +        if (max < thread_count)
 +            max = thread_count;
 +    }
 +
 +    return max;
 +}
 +
 +template<class Impl>
 +bool
 +DefaultIEW<Impl>::skidsEmpty()
 +{
 +    list<unsigned>::iterator threads = (*activeThreads).begin();
 +
 +    while (threads != (*activeThreads).end()) {
 +        if (!skidBuffer[*threads++].empty())
 +            return false;
 +    }
 +
 +    return true;
 +}
 +
 +template <class Impl>
 +void
 +DefaultIEW<Impl>::updateStatus()
 +{
 +    bool any_unblocking = false;
 +
 +    list<unsigned>::iterator threads = (*activeThreads).begin();
 +
 +    threads = (*activeThreads).begin();
 +
 +    while (threads != (*activeThreads).end()) {
 +        unsigned tid = *threads++;
 +
 +        if (dispatchStatus[tid] == Unblocking) {
 +            any_unblocking = true;
 +            break;
 +        }
 +    }
 +
 +    // If there are no ready instructions waiting to be scheduled by the IQ,
 +    // and there's no stores waiting to write back, and dispatch is not
 +    // unblocking, then there is no internal activity for the IEW stage.
 +    if (_status == Active && !instQueue.hasReadyInsts() &&
 +        !ldstQueue.willWB() && !any_unblocking) {
 +        DPRINTF(IEW, "IEW switching to idle\n");
 +
 +        deactivateStage();
 +
 +        _status = Inactive;
 +    } else if (_status == Inactive && (instQueue.hasReadyInsts() ||
 +                                       ldstQueue.willWB() ||
 +                                       any_unblocking)) {
 +        // Otherwise there is internal activity.  Set to active.
 +        DPRINTF(IEW, "IEW switching to active\n");
 +
 +        activateStage();
 +
 +        _status = Active;
 +    }
 +}
 +
 +template <class Impl>
 +void
 +DefaultIEW<Impl>::resetEntries()
 +{
 +    instQueue.resetEntries();
 +    ldstQueue.resetEntries();
 +}
 +
 +template <class Impl>
 +void
 +DefaultIEW<Impl>::readStallSignals(unsigned tid)
 +{
 +    if (fromCommit->commitBlock[tid]) {
 +        stalls[tid].commit = true;
 +    }
 +
 +    if (fromCommit->commitUnblock[tid]) {
 +        assert(stalls[tid].commit);
 +        stalls[tid].commit = false;
 +    }
 +}
 +
 +template <class Impl>
 +bool
 +DefaultIEW<Impl>::checkStall(unsigned tid)
 +{
 +    bool ret_val(false);
 +
 +    if (stalls[tid].commit) {
 +        DPRINTF(IEW,"[tid:%i]: Stall from Commit stage detected.\n",tid);
 +        ret_val = true;
 +    } else if (instQueue.isFull(tid)) {
 +        DPRINTF(IEW,"[tid:%i]: Stall: IQ  is full.\n",tid);
 +        ret_val = true;
 +    } else if (ldstQueue.isFull(tid)) {
 +        DPRINTF(IEW,"[tid:%i]: Stall: LSQ is full\n",tid);
 +
 +        if (ldstQueue.numLoads(tid) > 0 ) {
 +
 +            DPRINTF(IEW,"[tid:%i]: LSQ oldest load: [sn:%i] \n",
 +                    tid,ldstQueue.getLoadHeadSeqNum(tid));
 +        }
 +
 +        if (ldstQueue.numStores(tid) > 0) {
 +
 +            DPRINTF(IEW,"[tid:%i]: LSQ oldest store: [sn:%i] \n",
 +                    tid,ldstQueue.getStoreHeadSeqNum(tid));
 +        }
 +
 +        ret_val = true;
 +    } else if (ldstQueue.isStalled(tid)) {
 +        DPRINTF(IEW,"[tid:%i]: Stall: LSQ stall detected.\n",tid);
 +        ret_val = true;
 +    }
 +
 +    return ret_val;
 +}
 +
 +template <class Impl>
 +void
 +DefaultIEW<Impl>::checkSignalsAndUpdate(unsigned tid)
 +{
 +    // Check if there's a squash signal, squash if there is
 +    // Check stall signals, block if there is.
 +    // If status was Blocked
 +    //     if so then go to unblocking
 +    // If status was Squashing
 +    //     check if squashing is not high.  Switch to running this cycle.
 +
 +    readStallSignals(tid);
 +
 +    if (fromCommit->commitInfo[tid].squash) {
 +        squash(tid);
 +
 +        if (dispatchStatus[tid] == Blocked ||
 +            dispatchStatus[tid] == Unblocking) {
 +            toRename->iewUnblock[tid] = true;
 +            wroteToTimeBuffer = true;
 +        }
 +
 +        dispatchStatus[tid] = Squashing;
 +
 +        fetchRedirect[tid] = false;
 +        return;
 +    }
 +
 +    if (fromCommit->commitInfo[tid].robSquashing) {
 +        DPRINTF(IEW, "[tid:%i]: ROB is still squashing.\n");
 +
 +        dispatchStatus[tid] = Squashing;
 +
 +        return;
 +    }
 +
 +    if (checkStall(tid)) {
 +        block(tid);
 +        dispatchStatus[tid] = Blocked;
 +        return;
 +    }
 +
 +    if (dispatchStatus[tid] == Blocked) {
 +        // Status from previous cycle was blocked, but there are no more stall
 +        // conditions.  Switch over to unblocking.
 +        DPRINTF(IEW, "[tid:%i]: Done blocking, switching to unblocking.\n",
 +                tid);
 +
 +        dispatchStatus[tid] = Unblocking;
 +
 +        unblock(tid);
 +
 +        return;
 +    }
 +
 +    if (dispatchStatus[tid] == Squashing) {
 +        // Switch status to running if rename isn't being told to block or
 +        // squash this cycle.
 +        DPRINTF(IEW, "[tid:%i]: Done squashing, switching to running.\n",
 +                tid);
 +
 +        dispatchStatus[tid] = Running;
 +
 +        return;
 +    }
 +}
 +
 +template <class Impl>
 +void
 +DefaultIEW<Impl>::sortInsts()
 +{
 +    int insts_from_rename = fromRename->size;
 +#ifdef DEBUG
 +    for (int i = 0; i < numThreads; i++)
 +        assert(insts[i].empty());
 +#endif
 +    for (int i = 0; i < insts_from_rename; ++i) {
 +        insts[fromRename->insts[i]->threadNumber].push(fromRename->insts[i]);
 +    }
 +}
 +
 +template <class Impl>
 +void
 +DefaultIEW<Impl>::wakeCPU()
 +{
 +    cpu->wakeCPU();
 +}
 +
 +template <class Impl>
 +void
 +DefaultIEW<Impl>::activityThisCycle()
 +{
 +    DPRINTF(Activity, "Activity this cycle.\n");
 +    cpu->activityThisCycle();
 +}
 +
 +template <class Impl>
 +inline void
 +DefaultIEW<Impl>::activateStage()
 +{
 +    DPRINTF(Activity, "Activating stage.\n");
 +    cpu->activateStage(FullCPU::IEWIdx);
 +}
 +
 +template <class Impl>
 +inline void
 +DefaultIEW<Impl>::deactivateStage()
 +{
 +    DPRINTF(Activity, "Deactivating stage.\n");
 +    cpu->deactivateStage(FullCPU::IEWIdx);
 +}
 +
 +template<class Impl>
 +void
 +DefaultIEW<Impl>::dispatch(unsigned tid)
 +{
 +    // If status is Running or idle,
 +    //     call dispatchInsts()
 +    // If status is Unblocking,
 +    //     buffer any instructions coming from rename
 +    //     continue trying to empty skid buffer
 +    //     check if stall conditions have passed
 +
 +    if (dispatchStatus[tid] == Blocked) {
 +        ++iewBlockCycles;
 +
 +    } else if (dispatchStatus[tid] == Squashing) {
 +        ++iewSquashCycles;
 +    }
 +
 +    // Dispatch should try to dispatch as many instructions as its bandwidth
 +    // will allow, as long as it is not currently blocked.
 +    if (dispatchStatus[tid] == Running ||
 +        dispatchStatus[tid] == Idle) {
 +        DPRINTF(IEW, "[tid:%i] Not blocked, so attempting to run "
 +                "dispatch.\n", tid);
 +
 +        dispatchInsts(tid);
 +    } else if (dispatchStatus[tid] == Unblocking) {
 +        // Make sure that the skid buffer has something in it if the
 +        // status is unblocking.
 +        assert(!skidsEmpty());
 +
 +        // If the status was unblocking, then instructions from the skid
 +        // buffer were used.  Remove those instructions and handle
 +        // the rest of unblocking.
 +        dispatchInsts(tid);
 +
 +        ++iewUnblockCycles;
 +
 +        if (validInstsFromRename() && dispatchedAllInsts) {
 +            // Add the current inputs to the skid buffer so they can be
 +            // reprocessed when this stage unblocks.
 +            skidInsert(tid);
 +        }
 +
 +        unblock(tid);
 +    }
 +}
 +
 +template <class Impl>
 +void
 +DefaultIEW<Impl>::dispatchInsts(unsigned tid)
 +{
 +    dispatchedAllInsts = true;
 +
 +    // Obtain instructions from skid buffer if unblocking, or queue from rename
 +    // otherwise.
 +    std::queue<DynInstPtr> &insts_to_dispatch =
 +        dispatchStatus[tid] == Unblocking ?
 +        skidBuffer[tid] : insts[tid];
 +
 +    int insts_to_add = insts_to_dispatch.size();
 +
 +    DynInstPtr inst;
 +    bool add_to_iq = false;
 +    int dis_num_inst = 0;
 +
 +    // Loop through the instructions, putting them in the instruction
 +    // queue.
 +    for ( ; dis_num_inst < insts_to_add &&
 +              dis_num_inst < issueReadWidth;
 +          ++dis_num_inst)
 +    {
 +        inst = insts_to_dispatch.front();
 +
 +        if (dispatchStatus[tid] == Unblocking) {
 +            DPRINTF(IEW, "[tid:%i]: Issue: Examining instruction from skid "
 +                    "buffer\n", tid);
 +        }
 +
 +        // Make sure there's a valid instruction there.
 +        assert(inst);
 +
 +        DPRINTF(IEW, "[tid:%i]: Issue: Adding PC %#x [sn:%lli] [tid:%i] to "
 +                "IQ.\n",
 +                tid, inst->readPC(), inst->seqNum, inst->threadNumber);
 +
 +        // Be sure to mark these instructions as ready so that the
 +        // commit stage can go ahead and execute them, and mark
 +        // them as issued so the IQ doesn't reprocess them.
 +
 +        // Check for squashed instructions.
 +        if (inst->isSquashed()) {
 +            DPRINTF(IEW, "[tid:%i]: Issue: Squashed instruction encountered, "
 +                    "not adding to IQ.\n", tid);
 +
 +            ++iewDispSquashedInsts;
 +
 +            insts_to_dispatch.pop();
 +
 +            //Tell Rename That An Instruction has been processed
 +            if (inst->isLoad() || inst->isStore()) {
 +                toRename->iewInfo[tid].dispatchedToLSQ++;
 +            }
 +            toRename->iewInfo[tid].dispatched++;
 +
 +            continue;
 +        }
 +
 +        // Check for full conditions.
 +        if (instQueue.isFull(tid)) {
 +            DPRINTF(IEW, "[tid:%i]: Issue: IQ has become full.\n", tid);
 +
 +            // Call function to start blocking.
 +            block(tid);
 +
 +            // Set unblock to false. Special case where we are using
 +            // skidbuffer (unblocking) instructions but then we still
 +            // get full in the IQ.
 +            toRename->iewUnblock[tid] = false;
 +
 +            dispatchedAllInsts = false;
 +
 +            ++iewIQFullEvents;
 +            break;
 +        } else if (ldstQueue.isFull(tid)) {
 +            DPRINTF(IEW, "[tid:%i]: Issue: LSQ has become full.\n",tid);
 +
 +            // Call function to start blocking.
 +            block(tid);
 +
 +            // Set unblock to false. Special case where we are using
 +            // skidbuffer (unblocking) instructions but then we still
 +            // get full in the IQ.
 +            toRename->iewUnblock[tid] = false;
 +
 +            dispatchedAllInsts = false;
 +
 +            ++iewLSQFullEvents;
 +            break;
 +        }
 +
 +        // Otherwise issue the instruction just fine.
 +        if (inst->isLoad()) {
 +            DPRINTF(IEW, "[tid:%i]: Issue: Memory instruction "
 +                    "encountered, adding to LSQ.\n", tid);
 +
 +            // Reserve a spot in the load store queue for this
 +            // memory access.
 +            ldstQueue.insertLoad(inst);
 +
 +            ++iewDispLoadInsts;
 +
 +            add_to_iq = true;
 +
 +            toRename->iewInfo[tid].dispatchedToLSQ++;
 +        } else if (inst->isStore()) {
 +            DPRINTF(IEW, "[tid:%i]: Issue: Memory instruction "
 +                    "encountered, adding to LSQ.\n", tid);
 +
 +            ldstQueue.insertStore(inst);
 +
 +            ++iewDispStoreInsts;
 +
 +            if (inst->isStoreConditional()) {
 +                // Store conditionals need to be set as "canCommit()"
 +                // so that commit can process them when they reach the
 +                // head of commit.
++                // @todo: This is somewhat specific to Alpha.
 +                inst->setCanCommit();
 +                instQueue.insertNonSpec(inst);
 +                add_to_iq = false;
 +
 +                ++iewDispNonSpecInsts;
 +            } else {
 +                add_to_iq = true;
 +            }
 +
 +            toRename->iewInfo[tid].dispatchedToLSQ++;
 +#if FULL_SYSTEM
 +        } else if (inst->isMemBarrier() || inst->isWriteBarrier()) {
 +            // Same as non-speculative stores.
 +            inst->setCanCommit();
 +            instQueue.insertBarrier(inst);
 +            add_to_iq = false;
 +#endif
 +        } else if (inst->isNonSpeculative()) {
 +            DPRINTF(IEW, "[tid:%i]: Issue: Nonspeculative instruction "
 +                    "encountered, skipping.\n", tid);
 +
 +            // Same as non-speculative stores.
 +            inst->setCanCommit();
 +
 +            // Specifically insert it as nonspeculative.
 +            instQueue.insertNonSpec(inst);
 +
 +            ++iewDispNonSpecInsts;
 +
 +            add_to_iq = false;
 +        } else if (inst->isNop()) {
 +            DPRINTF(IEW, "[tid:%i]: Issue: Nop instruction encountered, "
 +                    "skipping.\n", tid);
 +
 +            inst->setIssued();
 +            inst->setExecuted();
 +            inst->setCanCommit();
 +
 +            instQueue.recordProducer(inst);
 +
 +            exeNop[tid]++;
 +
 +            add_to_iq = false;
 +        } else if (inst->isExecuted()) {
 +            assert(0 && "Instruction shouldn't be executed.\n");
 +            DPRINTF(IEW, "Issue: Executed branch encountered, "
 +                    "skipping.\n");
 +
 +            inst->setIssued();
 +            inst->setCanCommit();
 +
 +            instQueue.recordProducer(inst);
 +
 +            add_to_iq = false;
 +        } else {
 +            add_to_iq = true;
 +        }
 +
 +        // If the instruction queue is not full, then add the
 +        // instruction.
 +        if (add_to_iq) {
 +            instQueue.insert(inst);
 +        }
 +
 +        insts_to_dispatch.pop();
 +
 +        toRename->iewInfo[tid].dispatched++;
 +
 +        ++iewDispatchedInsts;
 +    }
 +
 +    if (!insts_to_dispatch.empty()) {
 +        DPRINTF(IEW,"[tid:%i]: Issue: Bandwidth Full. Blocking.\n");
 +        block(tid);
 +        toRename->iewUnblock[tid] = false;
 +    }
 +
 +    if (dispatchStatus[tid] == Idle && dis_num_inst) {
 +        dispatchStatus[tid] = Running;
 +
 +        updatedQueues = true;
 +    }
 +
 +    dis_num_inst = 0;
 +}
 +
 +template <class Impl>
 +void
 +DefaultIEW<Impl>::printAvailableInsts()
 +{
 +    int inst = 0;
 +
 +    cout << "Available Instructions: ";
 +
 +    while (fromIssue->insts[inst]) {
 +
 +        if (inst%3==0) cout << "\n\t";
 +
 +        cout << "PC: " << fromIssue->insts[inst]->readPC()
 +             << " TN: " << fromIssue->insts[inst]->threadNumber
 +             << " SN: " << fromIssue->insts[inst]->seqNum << " | ";
 +
 +        inst++;
 +
 +    }
 +
 +    cout << "\n";
 +}
 +
 +template <class Impl>
 +void
 +DefaultIEW<Impl>::executeInsts()
 +{
 +    wbNumInst = 0;
 +    wbCycle = 0;
 +
 +    list<unsigned>::iterator threads = (*activeThreads).begin();
 +
 +    while (threads != (*activeThreads).end()) {
 +        unsigned tid = *threads++;
 +        fetchRedirect[tid] = false;
 +    }
 +
 +#if 0
 +    printAvailableInsts();
 +#endif
 +
 +    // Execute/writeback any instructions that are available.
 +    int insts_to_execute = fromIssue->size;
 +    int inst_num = 0;
 +    for (; inst_num < insts_to_execute;
 +          ++inst_num) {
 +
 +        DPRINTF(IEW, "Execute: Executing instructions from IQ.\n");
 +
 +        DynInstPtr inst = instQueue.getInstToExecute();
 +
 +        DPRINTF(IEW, "Execute: Processing PC %#x, [tid:%i] [sn:%i].\n",
 +                inst->readPC(), inst->threadNumber,inst->seqNum);
 +
 +        // Check if the instruction is squashed; if so then skip it
 +        if (inst->isSquashed()) {
 +            DPRINTF(IEW, "Execute: Instruction was squashed.\n");
 +
 +            // Consider this instruction executed so that commit can go
 +            // ahead and retire the instruction.
 +            inst->setExecuted();
 +
 +            // Not sure if I should set this here or just let commit try to
 +            // commit any squashed instructions.  I like the latter a bit more.
 +            inst->setCanCommit();
 +
 +            ++iewExecSquashedInsts;
 +
 +            continue;
 +        }
 +
 +        Fault fault = NoFault;
 +
 +        // Execute instruction.
 +        // Note that if the instruction faults, it will be handled
 +        // at the commit stage.
 +        if (inst->isMemRef() &&
 +            (!inst->isDataPrefetch() && !inst->isInstPrefetch())) {
 +            DPRINTF(IEW, "Execute: Calculating address for memory "
 +                    "reference.\n");
 +
 +            // Tell the LDSTQ to execute this instruction (if it is a load).
 +            if (inst->isLoad()) {
 +                // Loads will mark themselves as executed, and their writeback
 +                // event adds the instruction to the queue to commit
 +                fault = ldstQueue.executeLoad(inst);
 +            } else if (inst->isStore()) {
 +                ldstQueue.executeStore(inst);
 +
 +                // If the store had a fault then it may not have a mem req
 +                if (inst->req && !(inst->req->getFlags() & LOCKED)) {
 +                    inst->setExecuted();
 +
 +                    instToCommit(inst);
 +                }
 +
 +                // Store conditionals will mark themselves as
 +                // executed, and their writeback event will add the
 +                // instruction to the queue to commit.
 +            } else {
 +                panic("Unexpected memory type!\n");
 +            }
 +
 +        } else {
 +            inst->execute();
 +
 +            inst->setExecuted();
 +
 +            instToCommit(inst);
 +        }
 +
 +        updateExeInstStats(inst);
 +
 +        // Check if branch prediction was correct, if not then we need
 +        // to tell commit to squash in flight instructions.  Only
 +        // handle this if there hasn't already been something that
 +        // redirects fetch in this group of instructions.
 +
 +        // This probably needs to prioritize the redirects if a different
 +        // scheduler is used.  Currently the scheduler schedules the oldest
 +        // instruction first, so the branch resolution order will be correct.
 +        unsigned tid = inst->threadNumber;
 +
 +        if (!fetchRedirect[tid]) {
 +
 +            if (inst->mispredicted()) {
 +                fetchRedirect[tid] = true;
 +
 +                DPRINTF(IEW, "Execute: Branch mispredict detected.\n");
 +                DPRINTF(IEW, "Execute: Redirecting fetch to PC: %#x.\n",
 +                        inst->nextPC);
 +
 +                // If incorrect, then signal the ROB that it must be squashed.
 +                squashDueToBranch(inst, tid);
 +
 +                if (inst->predTaken()) {
 +                    predictedTakenIncorrect++;
 +                } else {
 +                    predictedNotTakenIncorrect++;
 +                }
 +            } else if (ldstQueue.violation(tid)) {
 +                fetchRedirect[tid] = true;
 +
 +                // If there was an ordering violation, then get the
 +                // DynInst that caused the violation.  Note that this
 +                // clears the violation signal.
 +                DynInstPtr violator;
 +                violator = ldstQueue.getMemDepViolator(tid);
 +
 +                DPRINTF(IEW, "LDSTQ detected a violation.  Violator PC: "
 +                        "%#x, inst PC: %#x.  Addr is: %#x.\n",
 +                        violator->readPC(), inst->readPC(), inst->physEffAddr);
 +
 +                // Tell the instruction queue that a violation has occured.
 +                instQueue.violation(inst, violator);
 +
 +                // Squash.
 +                squashDueToMemOrder(inst,tid);
 +
 +                ++memOrderViolationEvents;
 +            } else if (ldstQueue.loadBlocked(tid) &&
 +                       !ldstQueue.isLoadBlockedHandled(tid)) {
 +                fetchRedirect[tid] = true;
 +
 +                DPRINTF(IEW, "Load operation couldn't execute because the "
 +                        "memory system is blocked.  PC: %#x [sn:%lli]\n",
 +                        inst->readPC(), inst->seqNum);
 +
 +                squashDueToMemBlocked(inst, tid);
 +            }
 +        }
 +    }
 +
++    // Update and record activity if we processed any instructions.
 +    if (inst_num) {
 +        if (exeStatus == Idle) {
 +            exeStatus = Running;
 +        }
 +
 +        updatedQueues = true;
 +
 +        cpu->activityThisCycle();
 +    }
 +
 +    // Need to reset this in case a writeback event needs to write into the
 +    // iew queue.  That way the writeback event will write into the correct
 +    // spot in the queue.
 +    wbNumInst = 0;
 +}
 +
 +template <class Impl>
 +void
 +DefaultIEW<Impl>::writebackInsts()
 +{
 +    // Loop through the head of the time buffer and wake any
 +    // dependents.  These instructions are about to write back.  Also
 +    // mark scoreboard that this instruction is finally complete.
 +    // Either have IEW have direct access to scoreboard, or have this
 +    // as part of backwards communication.
 +    for (int inst_num = 0; inst_num < issueWidth &&
 +             toCommit->insts[inst_num]; inst_num++) {
 +        DynInstPtr inst = toCommit->insts[inst_num];
 +        int tid = inst->threadNumber;
 +
 +        DPRINTF(IEW, "Sending instructions to commit, PC %#x.\n",
 +                inst->readPC());
 +
 +        iewInstsToCommit[tid]++;
 +
 +        // Some instructions will be sent to commit without having
 +        // executed because they need commit to handle them.
 +        // E.g. Uncached loads have not actually executed when they
 +        // are first sent to commit.  Instead commit must tell the LSQ
 +        // when it's ready to execute the uncached load.
 +        if (!inst->isSquashed() && inst->isExecuted()) {
 +            int dependents = instQueue.wakeDependents(inst);
 +
 +            for (int i = 0; i < inst->numDestRegs(); i++) {
 +                //mark as Ready
 +                DPRINTF(IEW,"Setting Destination Register %i\n",
 +                        inst->renamedDestRegIdx(i));
 +                scoreboard->setReg(inst->renamedDestRegIdx(i));
 +            }
 +
++            if (dependents) {
++                producerInst[tid]++;
++                consumerInst[tid]+= dependents;
++            }
 +            writebackCount[tid]++;
 +        }
 +    }
 +}
 +
 +template<class Impl>
 +void
 +DefaultIEW<Impl>::tick()
 +{
 +    wbNumInst = 0;
 +    wbCycle = 0;
 +
 +    wroteToTimeBuffer = false;
 +    updatedQueues = false;
 +
 +    sortInsts();
 +
 +    // Free function units marked as being freed this cycle.
 +    fuPool->processFreeUnits();
 +
 +    list<unsigned>::iterator threads = (*activeThreads).begin();
 +
 +    // Check stall and squash signals, dispatch any instructions.
 +    while (threads != (*activeThreads).end()) {
 +           unsigned tid = *threads++;
 +
 +        DPRINTF(IEW,"Issue: Processing [tid:%i]\n",tid);
 +
 +        checkSignalsAndUpdate(tid);
 +        dispatch(tid);
 +    }
 +
 +    if (exeStatus != Squashing) {
 +        executeInsts();
 +
 +        writebackInsts();
 +
 +        // Have the instruction queue try to schedule any ready instructions.
 +        // (In actuality, this scheduling is for instructions that will
 +        // be executed next cycle.)
 +        instQueue.scheduleReadyInsts();
 +
 +        // Also should advance its own time buffers if the stage ran.
 +        // Not the best place for it, but this works (hopefully).
 +        issueToExecQueue.advance();
 +    }
 +
 +    bool broadcast_free_entries = false;
 +
 +    if (updatedQueues || exeStatus == Running || updateLSQNextCycle) {
 +        exeStatus = Idle;
 +        updateLSQNextCycle = false;
 +
 +        broadcast_free_entries = true;
 +    }
 +
 +    // Writeback any stores using any leftover bandwidth.
 +    ldstQueue.writebackStores();
 +
 +    // Check the committed load/store signals to see if there's a load
 +    // or store to commit.  Also check if it's being told to execute a
 +    // nonspeculative instruction.
 +    // This is pretty inefficient...
 +
 +    threads = (*activeThreads).begin();
 +    while (threads != (*activeThreads).end()) {
 +        unsigned tid = (*threads++);
 +
 +        DPRINTF(IEW,"Processing [tid:%i]\n",tid);
 +
++        // Update structures based on instructions committed.
 +        if (fromCommit->commitInfo[tid].doneSeqNum != 0 &&
 +            !fromCommit->commitInfo[tid].squash &&
 +            !fromCommit->commitInfo[tid].robSquashing) {
 +
 +            ldstQueue.commitStores(fromCommit->commitInfo[tid].doneSeqNum,tid);
 +
 +            ldstQueue.commitLoads(fromCommit->commitInfo[tid].doneSeqNum,tid);
 +
 +            updateLSQNextCycle = true;
 +            instQueue.commit(fromCommit->commitInfo[tid].doneSeqNum,tid);
 +        }
 +
 +        if (fromCommit->commitInfo[tid].nonSpecSeqNum != 0) {
 +
 +            //DPRINTF(IEW,"NonspecInst from thread %i",tid);
 +            if (fromCommit->commitInfo[tid].uncached) {
 +                instQueue.replayMemInst(fromCommit->commitInfo[tid].uncachedLoad);
 +            } else {
 +                instQueue.scheduleNonSpec(
 +                    fromCommit->commitInfo[tid].nonSpecSeqNum);
 +            }
 +        }
 +
 +        if (broadcast_free_entries) {
 +            toFetch->iewInfo[tid].iqCount =
 +                instQueue.getCount(tid);
 +            toFetch->iewInfo[tid].ldstqCount =
 +                ldstQueue.getCount(tid);
 +
 +            toRename->iewInfo[tid].usedIQ = true;
 +            toRename->iewInfo[tid].freeIQEntries =
 +                instQueue.numFreeEntries();
 +            toRename->iewInfo[tid].usedLSQ = true;
 +            toRename->iewInfo[tid].freeLSQEntries =
 +                ldstQueue.numFreeEntries(tid);
 +
 +            wroteToTimeBuffer = true;
 +        }
 +
 +        DPRINTF(IEW, "[tid:%i], Dispatch dispatched %i instructions.\n",
 +                tid, toRename->iewInfo[tid].dispatched);
 +    }
 +
 +    DPRINTF(IEW, "IQ has %i free entries (Can schedule: %i).  "
 +            "LSQ has %i free entries.\n",
 +            instQueue.numFreeEntries(), instQueue.hasReadyInsts(),
 +            ldstQueue.numFreeEntries());
 +
 +    updateStatus();
 +
 +    if (wroteToTimeBuffer) {
 +        DPRINTF(Activity, "Activity this cycle.\n");
 +        cpu->activityThisCycle();
 +    }
 +}
 +
 +template <class Impl>
 +void
 +DefaultIEW<Impl>::updateExeInstStats(DynInstPtr &inst)
 +{
 +    int thread_number = inst->threadNumber;
 +
 +    //
 +    //  Pick off the software prefetches
 +    //
 +#ifdef TARGET_ALPHA
 +    if (inst->isDataPrefetch())
 +        exeSwp[thread_number]++;
 +    else
 +        iewExecutedInsts++;
 +#else
 +    iewExecutedInsts++;
 +#endif
 +
 +    //
 +    //  Control operations
 +    //
 +    if (inst->isControl())
 +        exeBranches[thread_number]++;
 +
 +    //
 +    //  Memory operations
 +    //
 +    if (inst->isMemRef()) {
 +        exeRefs[thread_number]++;
 +
 +        if (inst->isLoad()) {
 +            iewExecLoadInsts[thread_number]++;
 +        }
 +    }
 +}
index 245601ccf2294a8124cd2f9ad07bcaa5b7ef0985,0000000000000000000000000000000000000000..60a713020c2a85478a5b3f5c861834d754dc16ac
mode 100644,000000..100644
--- /dev/null
@@@ -1,481 -1,0 +1,503 @@@
-      * Struct for comparing entries to be added to the priority queue.  This
-      * gives reverse ordering to the instructions in terms of sequence
-      * numbers: the instructions with smaller sequence numbers (and hence
-      * are older) will be at the top of the priority queue.
 +/*
 + * Copyright (c) 2004-2006 The Regents of The University of Michigan
 + * 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: Kevin Lim
 + */
 +
 +#ifndef __CPU_O3_INST_QUEUE_HH__
 +#define __CPU_O3_INST_QUEUE_HH__
 +
 +#include <list>
 +#include <map>
 +#include <queue>
 +#include <vector>
 +
 +#include "base/statistics.hh"
 +#include "base/timebuf.hh"
 +#include "cpu/inst_seq.hh"
 +#include "cpu/o3/dep_graph.hh"
 +#include "cpu/op_class.hh"
 +#include "sim/host.hh"
 +
 +class FUPool;
 +class MemInterface;
 +
 +/**
 + * A standard instruction queue class.  It holds ready instructions, in
 + * order, in seperate priority queues to facilitate the scheduling of
 + * instructions.  The IQ uses a separate linked list to track dependencies.
 + * Similar to the rename map and the free list, it expects that
 + * floating point registers have their indices start after the integer
 + * registers (ie with 96 int and 96 fp registers, regs 0-95 are integer
 + * and 96-191 are fp).  This remains true even for both logical and
 + * physical register indices. The IQ depends on the memory dependence unit to
 + * track when memory operations are ready in terms of ordering; register
 + * dependencies are tracked normally. Right now the IQ also handles the
 + * execution timing; this is mainly to allow back-to-back scheduling without
 + * requiring IEW to be able to peek into the IQ. At the end of the execution
 + * latency, the instruction is put into the queue to execute, where it will
 + * have the execute() function called on it.
 + * @todo: Make IQ able to handle multiple FU pools.
 + */
 +template <class Impl>
 +class InstructionQueue
 +{
 +  public:
 +    //Typedefs from the Impl.
 +    typedef typename Impl::FullCPU FullCPU;
 +    typedef typename Impl::DynInstPtr DynInstPtr;
 +    typedef typename Impl::Params Params;
 +
 +    typedef typename Impl::CPUPol::IEW IEW;
 +    typedef typename Impl::CPUPol::MemDepUnit MemDepUnit;
 +    typedef typename Impl::CPUPol::IssueStruct IssueStruct;
 +    typedef typename Impl::CPUPol::TimeStruct TimeStruct;
 +
 +    // Typedef of iterator through the list of instructions.
 +    typedef typename std::list<DynInstPtr>::iterator ListIt;
 +
 +    friend class Impl::FullCPU;
 +
 +    /** FU completion event class. */
 +    class FUCompletion : public Event {
 +      private:
 +        /** Executing instruction. */
 +        DynInstPtr inst;
 +
 +        /** Index of the FU used for executing. */
 +        int fuIdx;
 +
 +        /** Pointer back to the instruction queue. */
 +        InstructionQueue<Impl> *iqPtr;
 +
++        /** Should the FU be added to the list to be freed upon
++         * completing this event.
++         */
 +        bool freeFU;
 +
 +      public:
 +        /** Construct a FU completion event. */
 +        FUCompletion(DynInstPtr &_inst, int fu_idx,
 +                     InstructionQueue<Impl> *iq_ptr);
 +
 +        virtual void process();
 +        virtual const char *description();
 +        void setFreeFU() { freeFU = true; }
 +    };
 +
 +    /** Constructs an IQ. */
 +    InstructionQueue(Params *params);
 +
 +    /** Destructs the IQ. */
 +    ~InstructionQueue();
 +
 +    /** Returns the name of the IQ. */
 +    std::string name() const;
 +
 +    /** Registers statistics. */
 +    void regStats();
 +
++    /** Resets all instruction queue state. */
 +    void resetState();
 +
 +    /** Sets CPU pointer. */
 +    void setCPU(FullCPU *_cpu) { cpu = _cpu; }
 +
 +    /** Sets active threads list. */
 +    void setActiveThreads(std::list<unsigned> *at_ptr);
 +
 +    /** Sets the IEW pointer. */
 +    void setIEW(IEW *iew_ptr) { iewStage = iew_ptr; }
 +
 +    /** Sets the timer buffer between issue and execute. */
 +    void setIssueToExecuteQueue(TimeBuffer<IssueStruct> *i2eQueue);
 +
 +    /** Sets the global time buffer. */
 +    void setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr);
 +
++    /** Switches out the instruction queue. */
 +    void switchOut();
 +
++    /** Takes over execution from another CPU's thread. */
 +    void takeOverFrom();
 +
++    /** Returns if the IQ is switched out. */
 +    bool isSwitchedOut() { return switchedOut; }
 +
 +    /** Number of entries needed for given amount of threads. */
 +    int entryAmount(int num_threads);
 +
 +    /** Resets max entries for all threads. */
 +    void resetEntries();
 +
 +    /** Returns total number of free entries. */
 +    unsigned numFreeEntries();
 +
 +    /** Returns number of free entries for a thread. */
 +    unsigned numFreeEntries(unsigned tid);
 +
 +    /** Returns whether or not the IQ is full. */
 +    bool isFull();
 +
 +    /** Returns whether or not the IQ is full for a specific thread. */
 +    bool isFull(unsigned tid);
 +
 +    /** Returns if there are any ready instructions in the IQ. */
 +    bool hasReadyInsts();
 +
 +    /** Inserts a new instruction into the IQ. */
 +    void insert(DynInstPtr &new_inst);
 +
 +    /** Inserts a new, non-speculative instruction into the IQ. */
 +    void insertNonSpec(DynInstPtr &new_inst);
 +
 +    /** Inserts a memory or write barrier into the IQ to make sure
 +     *  loads and stores are ordered properly.
 +     */
 +    void insertBarrier(DynInstPtr &barr_inst);
 +
++    /** Returns the oldest scheduled instruction, and removes it from
++     * the list of instructions waiting to execute.
++     */
 +    DynInstPtr getInstToExecute();
 +
 +    /**
 +     * Records the instruction as the producer of a register without
 +     * adding it to the rest of the IQ.
 +     */
 +    void recordProducer(DynInstPtr &inst)
 +    { addToProducers(inst); }
 +
 +    /** Process FU completion event. */
 +    void processFUCompletion(DynInstPtr &inst, int fu_idx);
 +
 +    /**
 +     * Schedules ready instructions, adding the ready ones (oldest first) to
 +     * the queue to execute.
 +     */
 +    void scheduleReadyInsts();
 +
 +    /** Schedules a single specific non-speculative instruction. */
 +    void scheduleNonSpec(const InstSeqNum &inst);
 +
 +    /**
 +     * Commits all instructions up to and including the given sequence number,
 +     * for a specific thread.
 +     */
 +    void commit(const InstSeqNum &inst, unsigned tid = 0);
 +
 +    /** Wakes all dependents of a completed instruction. */
 +    int wakeDependents(DynInstPtr &completed_inst);
 +
 +    /** Adds a ready memory instruction to the ready list. */
 +    void addReadyMemInst(DynInstPtr &ready_inst);
 +
 +    /**
 +     * Reschedules a memory instruction. It will be ready to issue once
 +     * replayMemInst() is called.
 +     */
 +    void rescheduleMemInst(DynInstPtr &resched_inst);
 +
 +    /** Replays a memory instruction. It must be rescheduled first. */
 +    void replayMemInst(DynInstPtr &replay_inst);
 +
 +    /** Completes a memory operation. */
 +    void completeMemInst(DynInstPtr &completed_inst);
 +
 +    /** Indicates an ordering violation between a store and a load. */
 +    void violation(DynInstPtr &store, DynInstPtr &faulting_load);
 +
 +    /**
 +     * Squashes instructions for a thread. Squashing information is obtained
 +     * from the time buffer.
 +     */
 +    void squash(unsigned tid);
 +
 +    /** Returns the number of used entries for a thread. */
 +    unsigned getCount(unsigned tid) { return count[tid]; };
 +
 +    /** Debug function to print all instructions. */
 +    void printInsts();
 +
 +  private:
 +    /** Does the actual squashing. */
 +    void doSquash(unsigned tid);
 +
 +    /////////////////////////
 +    // Various pointers
 +    /////////////////////////
 +
 +    /** Pointer to the CPU. */
 +    FullCPU *cpu;
 +
 +    /** Cache interface. */
 +    MemInterface *dcacheInterface;
 +
 +    /** Pointer to IEW stage. */
 +    IEW *iewStage;
 +
 +    /** The memory dependence unit, which tracks/predicts memory dependences
 +     *  between instructions.
 +     */
 +    MemDepUnit memDepUnit[Impl::MaxThreads];
 +
 +    /** The queue to the execute stage.  Issued instructions will be written
 +     *  into it.
 +     */
 +    TimeBuffer<IssueStruct> *issueToExecuteQueue;
 +
 +    /** The backwards time buffer. */
 +    TimeBuffer<TimeStruct> *timeBuffer;
 +
 +    /** Wire to read information from timebuffer. */
 +    typename TimeBuffer<TimeStruct>::wire fromCommit;
 +
 +    /** Function unit pool. */
 +    FUPool *fuPool;
 +
 +    //////////////////////////////////////
 +    // Instruction lists, ready queues, and ordering
 +    //////////////////////////////////////
 +
 +    /** List of all the instructions in the IQ (some of which may be issued). */
 +    std::list<DynInstPtr> instList[Impl::MaxThreads];
 +
++    /** List of instructions that are ready to be executed. */
 +    std::list<DynInstPtr> instsToExecute;
 +
 +    /**
-     Stats::Vector<> fuBusy;  //cumulative fu busy
++     * Struct for comparing entries to be added to the priority queue.
++     * This gives reverse ordering to the instructions in terms of
++     * sequence numbers: the instructions with smaller sequence
++     * numbers (and hence are older) will be at the top of the
++     * priority queue.
 +     */
 +    struct pqCompare {
 +        bool operator() (const DynInstPtr &lhs, const DynInstPtr &rhs) const
 +        {
 +            return lhs->seqNum > rhs->seqNum;
 +        }
 +    };
 +
 +    typedef std::priority_queue<DynInstPtr, std::vector<DynInstPtr>, pqCompare>
 +    ReadyInstQueue;
 +
 +    /** List of ready instructions, per op class.  They are separated by op
 +     *  class to allow for easy mapping to FUs.
 +     */
 +    ReadyInstQueue readyInsts[Num_OpClasses];
 +
 +    /** List of non-speculative instructions that will be scheduled
 +     *  once the IQ gets a signal from commit.  While it's redundant to
 +     *  have the key be a part of the value (the sequence number is stored
 +     *  inside of DynInst), when these instructions are woken up only
 +     *  the sequence number will be available.  Thus it is most efficient to be
 +     *  able to search by the sequence number alone.
 +     */
 +    std::map<InstSeqNum, DynInstPtr> nonSpecInsts;
 +
 +    typedef typename std::map<InstSeqNum, DynInstPtr>::iterator NonSpecMapIt;
 +
 +    /** Entry for the list age ordering by op class. */
 +    struct ListOrderEntry {
 +        OpClass queueType;
 +        InstSeqNum oldestInst;
 +    };
 +
 +    /** List that contains the age order of the oldest instruction of each
 +     *  ready queue.  Used to select the oldest instruction available
 +     *  among op classes.
 +     *  @todo: Might be better to just move these entries around instead
 +     *  of creating new ones every time the position changes due to an
 +     *  instruction issuing.  Not sure std::list supports this.
 +     */
 +    std::list<ListOrderEntry> listOrder;
 +
 +    typedef typename std::list<ListOrderEntry>::iterator ListOrderIt;
 +
 +    /** Tracks if each ready queue is on the age order list. */
 +    bool queueOnList[Num_OpClasses];
 +
 +    /** Iterators of each ready queue.  Points to their spot in the age order
 +     *  list.
 +     */
 +    ListOrderIt readyIt[Num_OpClasses];
 +
 +    /** Add an op class to the age order list. */
 +    void addToOrderList(OpClass op_class);
 +
 +    /**
 +     * Called when the oldest instruction has been removed from a ready queue;
 +     * this places that ready queue into the proper spot in the age order list.
 +     */
 +    void moveToYoungerInst(ListOrderIt age_order_it);
 +
 +    DependencyGraph<DynInstPtr> dependGraph;
 +
 +    //////////////////////////////////////
 +    // Various parameters
 +    //////////////////////////////////////
 +
 +    /** IQ Resource Sharing Policy */
 +    enum IQPolicy {
 +        Dynamic,
 +        Partitioned,
 +        Threshold
 +    };
 +
 +    /** IQ sharing policy for SMT. */
 +    IQPolicy iqPolicy;
 +
 +    /** Number of Total Threads*/
 +    unsigned numThreads;
 +
 +    /** Pointer to list of active threads. */
 +    std::list<unsigned> *activeThreads;
 +
 +    /** Per Thread IQ count */
 +    unsigned count[Impl::MaxThreads];
 +
 +    /** Max IQ Entries Per Thread */
 +    unsigned maxEntries[Impl::MaxThreads];
 +
 +    /** Number of free IQ entries left. */
 +    unsigned freeEntries;
 +
 +    /** The number of entries in the instruction queue. */
 +    unsigned numEntries;
 +
 +    /** The total number of instructions that can be issued in one cycle. */
 +    unsigned totalWidth;
 +
 +    /** The number of physical registers in the CPU. */
 +    unsigned numPhysRegs;
 +
 +    /** The number of physical integer registers in the CPU. */
 +    unsigned numPhysIntRegs;
 +
 +    /** The number of floating point registers in the CPU. */
 +    unsigned numPhysFloatRegs;
 +
 +    /** Delay between commit stage and the IQ.
 +     *  @todo: Make there be a distinction between the delays within IEW.
 +     */
 +    unsigned commitToIEWDelay;
 +
++    /** Is the IQ switched out. */
 +    bool switchedOut;
 +
 +    /** The sequence number of the squashed instruction. */
 +    InstSeqNum squashedSeqNum[Impl::MaxThreads];
 +
 +    /** A cache of the recently woken registers.  It is 1 if the register
 +     *  has been woken up recently, and 0 if the register has been added
 +     *  to the dependency graph and has not yet received its value.  It
 +     *  is basically a secondary scoreboard, and should pretty much mirror
 +     *  the scoreboard that exists in the rename map.
 +     */
 +    std::vector<bool> regScoreboard;
 +
 +    /** Adds an instruction to the dependency graph, as a consumer. */
 +    bool addToDependents(DynInstPtr &new_inst);
 +
 +    /** Adds an instruction to the dependency graph, as a producer. */
 +    void addToProducers(DynInstPtr &new_inst);
 +
 +    /** Moves an instruction to the ready queue if it is ready. */
 +    void addIfReady(DynInstPtr &inst);
 +
 +    /** Debugging function to count how many entries are in the IQ.  It does
 +     *  a linear walk through the instructions, so do not call this function
 +     *  during normal execution.
 +     */
 +    int countInsts();
 +
 +    /** Debugging function to dump all the list sizes, as well as print
 +     *  out the list of nonspeculative instructions.  Should not be used
 +     *  in any other capacity, but it has no harmful sideaffects.
 +     */
 +    void dumpLists();
 +
 +    /** Debugging function to dump out all instructions that are in the
 +     *  IQ.
 +     */
 +    void dumpInsts();
 +
 +    /** Stat for number of instructions added. */
 +    Stats::Scalar<> iqInstsAdded;
 +    /** Stat for number of non-speculative instructions added. */
 +    Stats::Scalar<> iqNonSpecInstsAdded;
 +
 +    Stats::Scalar<> iqInstsIssued;
 +    /** Stat for number of integer instructions issued. */
 +    Stats::Scalar<> iqIntInstsIssued;
 +    /** Stat for number of floating point instructions issued. */
 +    Stats::Scalar<> iqFloatInstsIssued;
 +    /** Stat for number of branch instructions issued. */
 +    Stats::Scalar<> iqBranchInstsIssued;
 +    /** Stat for number of memory instructions issued. */
 +    Stats::Scalar<> iqMemInstsIssued;
 +    /** Stat for number of miscellaneous instructions issued. */
 +    Stats::Scalar<> iqMiscInstsIssued;
 +    /** Stat for number of squashed instructions that were ready to issue. */
 +    Stats::Scalar<> iqSquashedInstsIssued;
 +    /** Stat for number of squashed instructions examined when squashing. */
 +    Stats::Scalar<> iqSquashedInstsExamined;
 +    /** Stat for number of squashed instruction operands examined when
 +     * squashing.
 +     */
 +    Stats::Scalar<> iqSquashedOperandsExamined;
 +    /** Stat for number of non-speculative instructions removed due to a squash.
 +     */
 +    Stats::Scalar<> iqSquashedNonSpecRemoved;
 +
++    /** Distribution of number of instructions in the queue. */
 +    Stats::VectorDistribution<> queueResDist;
++    /** Distribution of the number of instructions issued. */
 +    Stats::Distribution<> numIssuedDist;
++    /** Distribution of the cycles it takes to issue an instruction. */
 +    Stats::VectorDistribution<> issueDelayDist;
 +
++    /** Number of times an instruction could not be issued because a
++     * FU was busy.
++     */
 +    Stats::Vector<> statFuBusy;
 +//    Stats::Vector<> dist_unissued;
++    /** Stat for total number issued for each instruction type. */
 +    Stats::Vector2d<> statIssuedInstType;
 +
++    /** Number of instructions issued per cycle. */
 +    Stats::Formula issueRate;
 +//    Stats::Formula issue_stores;
 +//    Stats::Formula issue_op_rate;
++    /** Number of times the FU was busy. */
++    Stats::Vector<> fuBusy;
++    /** Number of times the FU was busy per instruction issued. */
 +    Stats::Formula fuBusyRate;
 +};
 +
 +#endif //__CPU_O3_INST_QUEUE_HH__
index 34af8c641adf87633206b12b2b51bf06b13df85e,0000000000000000000000000000000000000000..2f03c6814f7ccf0d29e2144ec9921a0ca20a5885
mode 100644,000000..100644
--- /dev/null
@@@ -1,1368 -1,0 +1,1403 @@@
-     // @todo: This could break if there's multiple multi-cycle ops
-     // finishing on this cycle.  Maybe implement something like
-     // instToCommit in iew_impl.hh.
 +/*
 + * Copyright (c) 2004-2006 The Regents of The University of Michigan
 + * 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: Kevin Lim
 + */
 +
 +#include <limits>
 +#include <vector>
 +
 +#include "sim/root.hh"
 +
 +#include "cpu/o3/fu_pool.hh"
 +#include "cpu/o3/inst_queue.hh"
 +
 +using namespace std;
 +
 +template <class Impl>
 +InstructionQueue<Impl>::FUCompletion::FUCompletion(DynInstPtr &_inst,
 +                                                   int fu_idx,
 +                                                   InstructionQueue<Impl> *iq_ptr)
 +    : Event(&mainEventQueue, Stat_Event_Pri),
 +      inst(_inst), fuIdx(fu_idx), iqPtr(iq_ptr), freeFU(false)
 +{
 +    this->setFlags(Event::AutoDelete);
 +}
 +
 +template <class Impl>
 +void
 +InstructionQueue<Impl>::FUCompletion::process()
 +{
 +    iqPtr->processFUCompletion(inst, freeFU ? fuIdx : -1);
 +    inst = NULL;
 +}
 +
 +
 +template <class Impl>
 +const char *
 +InstructionQueue<Impl>::FUCompletion::description()
 +{
 +    return "Functional unit completion event";
 +}
 +
 +template <class Impl>
 +InstructionQueue<Impl>::InstructionQueue(Params *params)
 +    : fuPool(params->fuPool),
 +      numEntries(params->numIQEntries),
 +      totalWidth(params->issueWidth),
 +      numPhysIntRegs(params->numPhysIntRegs),
 +      numPhysFloatRegs(params->numPhysFloatRegs),
 +      commitToIEWDelay(params->commitToIEWDelay)
 +{
 +    assert(fuPool);
 +
 +    switchedOut = false;
 +
 +    numThreads = params->numberOfThreads;
 +
 +    // Set the number of physical registers as the number of int + float
 +    numPhysRegs = numPhysIntRegs + numPhysFloatRegs;
 +
 +    DPRINTF(IQ, "There are %i physical registers.\n", numPhysRegs);
 +
 +    //Create an entry for each physical register within the
 +    //dependency graph.
 +    dependGraph.resize(numPhysRegs);
 +
 +    // Resize the register scoreboard.
 +    regScoreboard.resize(numPhysRegs);
 +
 +    //Initialize Mem Dependence Units
 +    for (int i = 0; i < numThreads; i++) {
 +        memDepUnit[i].init(params,i);
 +        memDepUnit[i].setIQ(this);
 +    }
 +
 +    resetState();
 +
 +    string policy = params->smtIQPolicy;
 +
 +    //Convert string to lowercase
 +    std::transform(policy.begin(), policy.end(), policy.begin(),
 +                   (int(*)(int)) tolower);
 +
 +    //Figure out resource sharing policy
 +    if (policy == "dynamic") {
 +        iqPolicy = Dynamic;
 +
 +        //Set Max Entries to Total ROB Capacity
 +        for (int i = 0; i < numThreads; i++) {
 +            maxEntries[i] = numEntries;
 +        }
 +
 +    } else if (policy == "partitioned") {
 +        iqPolicy = Partitioned;
 +
 +        //@todo:make work if part_amt doesnt divide evenly.
 +        int part_amt = numEntries / numThreads;
 +
 +        //Divide ROB up evenly
 +        for (int i = 0; i < numThreads; i++) {
 +            maxEntries[i] = part_amt;
 +        }
 +
 +        DPRINTF(Fetch, "IQ sharing policy set to Partitioned:"
 +                "%i entries per thread.\n",part_amt);
 +
 +    } else if (policy == "threshold") {
 +        iqPolicy = Threshold;
 +
 +        double threshold =  (double)params->smtIQThreshold / 100;
 +
 +        int thresholdIQ = (int)((double)threshold * numEntries);
 +
 +        //Divide up by threshold amount
 +        for (int i = 0; i < numThreads; i++) {
 +            maxEntries[i] = thresholdIQ;
 +        }
 +
 +        DPRINTF(Fetch, "IQ sharing policy set to Threshold:"
 +                "%i entries per thread.\n",thresholdIQ);
 +   } else {
 +       assert(0 && "Invalid IQ Sharing Policy.Options Are:{Dynamic,"
 +              "Partitioned, Threshold}");
 +   }
 +}
 +
 +template <class Impl>
 +InstructionQueue<Impl>::~InstructionQueue()
 +{
 +    dependGraph.reset();
++#ifdef DEBUG
 +    cprintf("Nodes traversed: %i, removed: %i\n",
 +            dependGraph.nodesTraversed, dependGraph.nodesRemoved);
++#endif
 +}
 +
 +template <class Impl>
 +std::string
 +InstructionQueue<Impl>::name() const
 +{
 +    return cpu->name() + ".iq";
 +}
 +
 +template <class Impl>
 +void
 +InstructionQueue<Impl>::regStats()
 +{
 +    using namespace Stats;
 +    iqInstsAdded
 +        .name(name() + ".iqInstsAdded")
 +        .desc("Number of instructions added to the IQ (excludes non-spec)")
 +        .prereq(iqInstsAdded);
 +
 +    iqNonSpecInstsAdded
 +        .name(name() + ".iqNonSpecInstsAdded")
 +        .desc("Number of non-speculative instructions added to the IQ")
 +        .prereq(iqNonSpecInstsAdded);
 +
 +    iqInstsIssued
 +        .name(name() + ".iqInstsIssued")
 +        .desc("Number of instructions issued")
 +        .prereq(iqInstsIssued);
 +
 +    iqIntInstsIssued
 +        .name(name() + ".iqIntInstsIssued")
 +        .desc("Number of integer instructions issued")
 +        .prereq(iqIntInstsIssued);
 +
 +    iqFloatInstsIssued
 +        .name(name() + ".iqFloatInstsIssued")
 +        .desc("Number of float instructions issued")
 +        .prereq(iqFloatInstsIssued);
 +
 +    iqBranchInstsIssued
 +        .name(name() + ".iqBranchInstsIssued")
 +        .desc("Number of branch instructions issued")
 +        .prereq(iqBranchInstsIssued);
 +
 +    iqMemInstsIssued
 +        .name(name() + ".iqMemInstsIssued")
 +        .desc("Number of memory instructions issued")
 +        .prereq(iqMemInstsIssued);
 +
 +    iqMiscInstsIssued
 +        .name(name() + ".iqMiscInstsIssued")
 +        .desc("Number of miscellaneous instructions issued")
 +        .prereq(iqMiscInstsIssued);
 +
 +    iqSquashedInstsIssued
 +        .name(name() + ".iqSquashedInstsIssued")
 +        .desc("Number of squashed instructions issued")
 +        .prereq(iqSquashedInstsIssued);
 +
 +    iqSquashedInstsExamined
 +        .name(name() + ".iqSquashedInstsExamined")
 +        .desc("Number of squashed instructions iterated over during squash;"
 +              " mainly for profiling")
 +        .prereq(iqSquashedInstsExamined);
 +
 +    iqSquashedOperandsExamined
 +        .name(name() + ".iqSquashedOperandsExamined")
 +        .desc("Number of squashed operands that are examined and possibly "
 +              "removed from graph")
 +        .prereq(iqSquashedOperandsExamined);
 +
 +    iqSquashedNonSpecRemoved
 +        .name(name() + ".iqSquashedNonSpecRemoved")
 +        .desc("Number of squashed non-spec instructions that were removed")
 +        .prereq(iqSquashedNonSpecRemoved);
 +
 +    queueResDist
 +        .init(Num_OpClasses, 0, 99, 2)
 +        .name(name() + ".IQ:residence:")
 +        .desc("cycles from dispatch to issue")
 +        .flags(total | pdf | cdf )
 +        ;
 +    for (int i = 0; i < Num_OpClasses; ++i) {
 +        queueResDist.subname(i, opClassStrings[i]);
 +    }
 +    numIssuedDist
 +        .init(0,totalWidth,1)
 +        .name(name() + ".ISSUE:issued_per_cycle")
 +        .desc("Number of insts issued each cycle")
 +        .flags(pdf)
 +        ;
 +/*
 +    dist_unissued
 +        .init(Num_OpClasses+2)
 +        .name(name() + ".ISSUE:unissued_cause")
 +        .desc("Reason ready instruction not issued")
 +        .flags(pdf | dist)
 +        ;
 +    for (int i=0; i < (Num_OpClasses + 2); ++i) {
 +        dist_unissued.subname(i, unissued_names[i]);
 +    }
 +*/
 +    statIssuedInstType
 +        .init(numThreads,Num_OpClasses)
 +        .name(name() + ".ISSUE:FU_type")
 +        .desc("Type of FU issued")
 +        .flags(total | pdf | dist)
 +        ;
 +    statIssuedInstType.ysubnames(opClassStrings);
 +
 +    //
 +    //  How long did instructions for a particular FU type wait prior to issue
 +    //
 +
 +    issueDelayDist
 +        .init(Num_OpClasses,0,99,2)
 +        .name(name() + ".ISSUE:")
 +        .desc("cycles from operands ready to issue")
 +        .flags(pdf | cdf)
 +        ;
 +
 +    for (int i=0; i<Num_OpClasses; ++i) {
 +        stringstream subname;
 +        subname << opClassStrings[i] << "_delay";
 +        issueDelayDist.subname(i, subname.str());
 +    }
 +
 +    issueRate
 +        .name(name() + ".ISSUE:rate")
 +        .desc("Inst issue rate")
 +        .flags(total)
 +        ;
 +    issueRate = iqInstsIssued / cpu->numCycles;
 +/*
 +    issue_stores
 +        .name(name() + ".ISSUE:stores")
 +        .desc("Number of stores issued")
 +        .flags(total)
 +        ;
 +    issue_stores = exe_refs - exe_loads;
 +*/
 +/*
 +    issue_op_rate
 +        .name(name() + ".ISSUE:op_rate")
 +        .desc("Operation issue rate")
 +        .flags(total)
 +        ;
 +    issue_op_rate = issued_ops / numCycles;
 +*/
 +    statFuBusy
 +        .init(Num_OpClasses)
 +        .name(name() + ".ISSUE:fu_full")
 +        .desc("attempts to use FU when none available")
 +        .flags(pdf | dist)
 +        ;
 +    for (int i=0; i < Num_OpClasses; ++i) {
 +        statFuBusy.subname(i, opClassStrings[i]);
 +    }
 +
 +    fuBusy
 +        .init(numThreads)
 +        .name(name() + ".ISSUE:fu_busy_cnt")
 +        .desc("FU busy when requested")
 +        .flags(total)
 +        ;
 +
 +    fuBusyRate
 +        .name(name() + ".ISSUE:fu_busy_rate")
 +        .desc("FU busy rate (busy events/executed inst)")
 +        .flags(total)
 +        ;
 +    fuBusyRate = fuBusy / iqInstsIssued;
 +
 +    for ( int i=0; i < numThreads; i++) {
 +        // Tell mem dependence unit to reg stats as well.
 +        memDepUnit[i].regStats();
 +    }
 +}
 +
 +template <class Impl>
 +void
 +InstructionQueue<Impl>::resetState()
 +{
 +    //Initialize thread IQ counts
 +    for (int i = 0; i <numThreads; i++) {
 +        count[i] = 0;
 +        instList[i].clear();
 +    }
 +
 +    // Initialize the number of free IQ entries.
 +    freeEntries = numEntries;
 +
 +    // Note that in actuality, the registers corresponding to the logical
 +    // registers start off as ready.  However this doesn't matter for the
 +    // IQ as the instruction should have been correctly told if those
 +    // registers are ready in rename.  Thus it can all be initialized as
 +    // unready.
 +    for (int i = 0; i < numPhysRegs; ++i) {
 +        regScoreboard[i] = false;
 +    }
 +
 +    for (int i = 0; i < numThreads; ++i) {
 +        squashedSeqNum[i] = 0;
 +    }
 +
 +    for (int i = 0; i < Num_OpClasses; ++i) {
 +        while (!readyInsts[i].empty())
 +            readyInsts[i].pop();
 +        queueOnList[i] = false;
 +        readyIt[i] = listOrder.end();
 +    }
 +    nonSpecInsts.clear();
 +    listOrder.clear();
 +}
 +
 +template <class Impl>
 +void
 +InstructionQueue<Impl>::setActiveThreads(list<unsigned> *at_ptr)
 +{
 +    DPRINTF(IQ, "Setting active threads list pointer.\n");
 +    activeThreads = at_ptr;
 +}
 +
 +template <class Impl>
 +void
 +InstructionQueue<Impl>::setIssueToExecuteQueue(TimeBuffer<IssueStruct> *i2e_ptr)
 +{
 +    DPRINTF(IQ, "Set the issue to execute queue.\n");
 +    issueToExecuteQueue = i2e_ptr;
 +}
 +
 +template <class Impl>
 +void
 +InstructionQueue<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr)
 +{
 +    DPRINTF(IQ, "Set the time buffer.\n");
 +    timeBuffer = tb_ptr;
 +
 +    fromCommit = timeBuffer->getWire(-commitToIEWDelay);
 +}
 +
 +template <class Impl>
 +void
 +InstructionQueue<Impl>::switchOut()
 +{
 +    resetState();
 +    dependGraph.reset();
 +    switchedOut = true;
 +    for (int i = 0; i < numThreads; ++i) {
 +        memDepUnit[i].switchOut();
 +    }
 +}
 +
 +template <class Impl>
 +void
 +InstructionQueue<Impl>::takeOverFrom()
 +{
 +    switchedOut = false;
 +}
 +
 +template <class Impl>
 +int
 +InstructionQueue<Impl>::entryAmount(int num_threads)
 +{
 +    if (iqPolicy == Partitioned) {
 +        return numEntries / num_threads;
 +    } else {
 +        return 0;
 +    }
 +}
 +
 +
 +template <class Impl>
 +void
 +InstructionQueue<Impl>::resetEntries()
 +{
 +    if (iqPolicy != Dynamic || numThreads > 1) {
 +        int active_threads = (*activeThreads).size();
 +
 +        list<unsigned>::iterator threads  = (*activeThreads).begin();
 +        list<unsigned>::iterator list_end = (*activeThreads).end();
 +
 +        while (threads != list_end) {
 +            if (iqPolicy == Partitioned) {
 +                maxEntries[*threads++] = numEntries / active_threads;
 +            } else if(iqPolicy == Threshold && active_threads == 1) {
 +                maxEntries[*threads++] = numEntries;
 +            }
 +        }
 +    }
 +}
 +
 +template <class Impl>
 +unsigned
 +InstructionQueue<Impl>::numFreeEntries()
 +{
 +    return freeEntries;
 +}
 +
 +template <class Impl>
 +unsigned
 +InstructionQueue<Impl>::numFreeEntries(unsigned tid)
 +{
 +    return maxEntries[tid] - count[tid];
 +}
 +
 +// Might want to do something more complex if it knows how many instructions
 +// will be issued this cycle.
 +template <class Impl>
 +bool
 +InstructionQueue<Impl>::isFull()
 +{
 +    if (freeEntries == 0) {
 +        return(true);
 +    } else {
 +        return(false);
 +    }
 +}
 +
 +template <class Impl>
 +bool
 +InstructionQueue<Impl>::isFull(unsigned tid)
 +{
 +    if (numFreeEntries(tid) == 0) {
 +        return(true);
 +    } else {
 +        return(false);
 +    }
 +}
 +
 +template <class Impl>
 +bool
 +InstructionQueue<Impl>::hasReadyInsts()
 +{
 +    if (!listOrder.empty()) {
 +        return true;
 +    }
 +
 +    for (int i = 0; i < Num_OpClasses; ++i) {
 +        if (!readyInsts[i].empty()) {
 +            return true;
 +        }
 +    }
 +
 +    return false;
 +}
 +
 +template <class Impl>
 +void
 +InstructionQueue<Impl>::insert(DynInstPtr &new_inst)
 +{
 +    // Make sure the instruction is valid
 +    assert(new_inst);
 +
 +    DPRINTF(IQ, "Adding instruction [sn:%lli] PC %#x to the IQ.\n",
 +            new_inst->seqNum, new_inst->readPC());
 +
 +    assert(freeEntries != 0);
 +
 +    instList[new_inst->threadNumber].push_back(new_inst);
 +
 +    --freeEntries;
 +
 +    new_inst->setInIQ();
 +
 +    // Look through its source registers (physical regs), and mark any
 +    // dependencies.
 +    addToDependents(new_inst);
 +
 +    // Have this instruction set itself as the producer of its destination
 +    // register(s).
 +    addToProducers(new_inst);
 +
 +    if (new_inst->isMemRef()) {
 +        memDepUnit[new_inst->threadNumber].insert(new_inst);
 +    } else {
 +        addIfReady(new_inst);
 +    }
 +
 +    ++iqInstsAdded;
 +
 +    count[new_inst->threadNumber]++;
 +
 +    assert(freeEntries == (numEntries - countInsts()));
 +}
 +
 +template <class Impl>
 +void
 +InstructionQueue<Impl>::insertNonSpec(DynInstPtr &new_inst)
 +{
 +    // @todo: Clean up this code; can do it by setting inst as unable
 +    // to issue, then calling normal insert on the inst.
 +
 +    assert(new_inst);
 +
 +    nonSpecInsts[new_inst->seqNum] = new_inst;
 +
 +    DPRINTF(IQ, "Adding non-speculative instruction [sn:%lli] PC %#x "
 +            "to the IQ.\n",
 +            new_inst->seqNum, new_inst->readPC());
 +
 +    assert(freeEntries != 0);
 +
 +    instList[new_inst->threadNumber].push_back(new_inst);
 +
 +    --freeEntries;
 +
 +    new_inst->setInIQ();
 +
 +    // Have this instruction set itself as the producer of its destination
 +    // register(s).
 +    addToProducers(new_inst);
 +
 +    // If it's a memory instruction, add it to the memory dependency
 +    // unit.
 +    if (new_inst->isMemRef()) {
 +        memDepUnit[new_inst->threadNumber].insertNonSpec(new_inst);
 +    }
 +
 +    ++iqNonSpecInstsAdded;
 +
 +    count[new_inst->threadNumber]++;
 +
 +    assert(freeEntries == (numEntries - countInsts()));
 +}
 +
 +template <class Impl>
 +void
 +InstructionQueue<Impl>::insertBarrier(DynInstPtr &barr_inst)
 +{
 +    memDepUnit[barr_inst->threadNumber].insertBarrier(barr_inst);
 +
 +    insertNonSpec(barr_inst);
 +}
 +
 +template <class Impl>
 +typename Impl::DynInstPtr
 +InstructionQueue<Impl>::getInstToExecute()
 +{
 +    assert(!instsToExecute.empty());
 +    DynInstPtr inst = instsToExecute.front();
 +    instsToExecute.pop_front();
 +    return inst;
 +}
 +
 +template <class Impl>
 +void
 +InstructionQueue<Impl>::addToOrderList(OpClass op_class)
 +{
 +    assert(!readyInsts[op_class].empty());
 +
 +    ListOrderEntry queue_entry;
 +
 +    queue_entry.queueType = op_class;
 +
 +    queue_entry.oldestInst = readyInsts[op_class].top()->seqNum;
 +
 +    ListOrderIt list_it = listOrder.begin();
 +    ListOrderIt list_end_it = listOrder.end();
 +
 +    while (list_it != list_end_it) {
 +        if ((*list_it).oldestInst > queue_entry.oldestInst) {
 +            break;
 +        }
 +
 +        list_it++;
 +    }
 +
 +    readyIt[op_class] = listOrder.insert(list_it, queue_entry);
 +    queueOnList[op_class] = true;
 +}
 +
 +template <class Impl>
 +void
 +InstructionQueue<Impl>::moveToYoungerInst(ListOrderIt list_order_it)
 +{
 +    // Get iterator of next item on the list
 +    // Delete the original iterator
 +    // Determine if the next item is either the end of the list or younger
 +    // than the new instruction.  If so, then add in a new iterator right here.
 +    // If not, then move along.
 +    ListOrderEntry queue_entry;
 +    OpClass op_class = (*list_order_it).queueType;
 +    ListOrderIt next_it = list_order_it;
 +
 +    ++next_it;
 +
 +    queue_entry.queueType = op_class;
 +    queue_entry.oldestInst = readyInsts[op_class].top()->seqNum;
 +
 +    while (next_it != listOrder.end() &&
 +           (*next_it).oldestInst < queue_entry.oldestInst) {
 +        ++next_it;
 +    }
 +
 +    readyIt[op_class] = listOrder.insert(next_it, queue_entry);
 +}
 +
 +template <class Impl>
 +void
 +InstructionQueue<Impl>::processFUCompletion(DynInstPtr &inst, int fu_idx)
 +{
 +    // The CPU could have been sleeping until this op completed (*extremely*
 +    // long latency op).  Wake it if it was.  This may be overkill.
 +    if (isSwitchedOut()) {
 +        return;
 +    }
 +
 +    iewStage->wakeCPU();
 +
 +    if (fu_idx > -1)
 +        fuPool->freeUnitNextCycle(fu_idx);
 +
 +    // @todo: Ensure that these FU Completions happen at the beginning
 +    // of a cycle, otherwise they could add too many instructions to
 +    // the queue.
- //    int &size = issueToExecuteQueue->access(0)->size;
- //    issueToExecuteQueue->access(0)->insts[size++] = inst;
 +    issueToExecuteQueue->access(0)->size++;
 +    instsToExecute.push_back(inst);
- //                i2e_info->insts[exec_queue_slot++] = issuing_inst;
 +}
 +
 +// @todo: Figure out a better way to remove the squashed items from the
 +// lists.  Checking the top item of each list to see if it's squashed
 +// wastes time and forces jumps.
 +template <class Impl>
 +void
 +InstructionQueue<Impl>::scheduleReadyInsts()
 +{
 +    DPRINTF(IQ, "Attempting to schedule ready instructions from "
 +            "the IQ.\n");
 +
 +    IssueStruct *i2e_info = issueToExecuteQueue->access(0);
 +
 +    // Have iterator to head of the list
 +    // While I haven't exceeded bandwidth or reached the end of the list,
 +    // Try to get a FU that can do what this op needs.
 +    // If successful, change the oldestInst to the new top of the list, put
 +    // the queue in the proper place in the list.
 +    // Increment the iterator.
 +    // This will avoid trying to schedule a certain op class if there are no
 +    // FUs that handle it.
 +    ListOrderIt order_it = listOrder.begin();
 +    ListOrderIt order_end_it = listOrder.end();
 +    int total_issued = 0;
 +
 +    while (total_issued < totalWidth &&
 +           order_it != order_end_it) {
 +        OpClass op_class = (*order_it).queueType;
 +
 +        assert(!readyInsts[op_class].empty());
 +
 +        DynInstPtr issuing_inst = readyInsts[op_class].top();
 +
 +        assert(issuing_inst->seqNum == (*order_it).oldestInst);
 +
 +        if (issuing_inst->isSquashed()) {
 +            readyInsts[op_class].pop();
 +
 +            if (!readyInsts[op_class].empty()) {
 +                moveToYoungerInst(order_it);
 +            } else {
 +                readyIt[op_class] = listOrder.end();
 +                queueOnList[op_class] = false;
 +            }
 +
 +            listOrder.erase(order_it++);
 +
 +            ++iqSquashedInstsIssued;
 +
 +            continue;
 +        }
 +
 +        int idx = -2;
 +        int op_latency = 1;
 +        int tid = issuing_inst->threadNumber;
 +
 +        if (op_class != No_OpClass) {
 +            idx = fuPool->getUnit(op_class);
 +
 +            if (idx > -1) {
 +                op_latency = fuPool->getOpLatency(op_class);
 +            }
 +        }
 +
++        // If we have an instruction that doesn't require a FU, or a
++        // valid FU, then schedule for execution.
 +        if (idx == -2 || idx != -1) {
 +            if (op_latency == 1) {
-                     // @todo: Not sure I'm accounting for the
-                     // multi-cycle op in a pipelined FU properly, or
-                     // the number of instructions issued in one cycle.
- //                    i2e_info->insts[exec_queue_slot++] = issuing_inst;
- //                    i2e_info->size++;
 +                i2e_info->size++;
 +                instsToExecute.push_back(issuing_inst);
 +
 +                // Add the FU onto the list of FU's to be freed next
 +                // cycle if we used one.
 +                if (idx >= 0)
 +                    fuPool->freeUnitNextCycle(idx);
 +            } else {
 +                int issue_latency = fuPool->getIssueLatency(op_class);
 +                // Generate completion event for the FU
 +                FUCompletion *execution = new FUCompletion(issuing_inst,
 +                                                           idx, this);
 +
 +                execution->schedule(curTick + cpu->cycles(issue_latency - 1));
 +
 +                // @todo: Enforce that issue_latency == 1 or op_latency
 +                if (issue_latency > 1) {
++                    // If FU isn't pipelined, then it must be freed
++                    // upon the execution completing.
 +                    execution->setFreeFU();
 +                } else {
 +                    // Add the FU onto the list of FU's to be freed next cycle.
 +                    fuPool->freeUnitNextCycle(idx);
 +                }
 +            }
 +
 +            DPRINTF(IQ, "Thread %i: Issuing instruction PC %#x "
 +                    "[sn:%lli]\n",
 +                    tid, issuing_inst->readPC(),
 +                    issuing_inst->seqNum);
 +
 +            readyInsts[op_class].pop();
 +
 +            if (!readyInsts[op_class].empty()) {
 +                moveToYoungerInst(order_it);
 +            } else {
 +                readyIt[op_class] = listOrder.end();
 +                queueOnList[op_class] = false;
 +            }
 +
 +            issuing_inst->setIssued();
 +            ++total_issued;
 +
 +            if (!issuing_inst->isMemRef()) {
 +                // Memory instructions can not be freed from the IQ until they
 +                // complete.
 +                ++freeEntries;
 +                count[tid]--;
 +                issuing_inst->removeInIQ();
 +            } else {
 +                memDepUnit[tid].issue(issuing_inst);
 +            }
 +
 +            listOrder.erase(order_it++);
 +            statIssuedInstType[tid][op_class]++;
 +        } else {
 +            statFuBusy[op_class]++;
 +            fuBusy[tid]++;
 +            ++order_it;
 +        }
 +    }
 +
 +    numIssuedDist.sample(total_issued);
 +    iqInstsIssued+= total_issued;
 +
++    // If we issued any instructions, tell the CPU we had activity.
 +    if (total_issued) {
 +        cpu->activityThisCycle();
 +    } else {
 +        DPRINTF(IQ, "Not able to schedule any instructions.\n");
 +    }
 +}
 +
 +template <class Impl>
 +void
 +InstructionQueue<Impl>::scheduleNonSpec(const InstSeqNum &inst)
 +{
 +    DPRINTF(IQ, "Marking nonspeculative instruction [sn:%lli] as ready "
 +            "to execute.\n", inst);
 +
 +    NonSpecMapIt inst_it = nonSpecInsts.find(inst);
 +
 +    assert(inst_it != nonSpecInsts.end());
 +
 +    unsigned tid = (*inst_it).second->threadNumber;
 +
 +    (*inst_it).second->setCanIssue();
 +
 +    if (!(*inst_it).second->isMemRef()) {
 +        addIfReady((*inst_it).second);
 +    } else {
 +        memDepUnit[tid].nonSpecInstReady((*inst_it).second);
 +    }
 +
 +    (*inst_it).second = NULL;
 +
 +    nonSpecInsts.erase(inst_it);
 +}
 +
 +template <class Impl>
 +void
 +InstructionQueue<Impl>::commit(const InstSeqNum &inst, unsigned tid)
 +{
 +    DPRINTF(IQ, "[tid:%i]: Committing instructions older than [sn:%i]\n",
 +            tid,inst);
 +
 +    ListIt iq_it = instList[tid].begin();
 +
 +    while (iq_it != instList[tid].end() &&
 +           (*iq_it)->seqNum <= inst) {
 +        ++iq_it;
 +        instList[tid].pop_front();
 +    }
 +
 +    assert(freeEntries == (numEntries - countInsts()));
 +}
 +
 +template <class Impl>
 +int
 +InstructionQueue<Impl>::wakeDependents(DynInstPtr &completed_inst)
 +{
 +    int dependents = 0;
 +
 +    DPRINTF(IQ, "Waking dependents of completed instruction.\n");
 +
 +    assert(!completed_inst->isSquashed());
 +
 +    // Tell the memory dependence unit to wake any dependents on this
 +    // instruction if it is a memory instruction.  Also complete the memory
 +    // instruction at this point since we know it executed without issues.
 +    // @todo: Might want to rename "completeMemInst" to something that
 +    // indicates that it won't need to be replayed, and call this
 +    // earlier.  Might not be a big deal.
 +    if (completed_inst->isMemRef()) {
 +        memDepUnit[completed_inst->threadNumber].wakeDependents(completed_inst);
 +        completeMemInst(completed_inst);
 +    } else if (completed_inst->isMemBarrier() ||
 +               completed_inst->isWriteBarrier()) {
 +        memDepUnit[completed_inst->threadNumber].completeBarrier(completed_inst);
 +    }
 +
 +    for (int dest_reg_idx = 0;
 +         dest_reg_idx < completed_inst->numDestRegs();
 +         dest_reg_idx++)
 +    {
 +        PhysRegIndex dest_reg =
 +            completed_inst->renamedDestRegIdx(dest_reg_idx);
 +
 +        // Special case of uniq or control registers.  They are not
 +        // handled by the IQ and thus have no dependency graph entry.
 +        // @todo Figure out a cleaner way to handle this.
 +        if (dest_reg >= numPhysRegs) {
 +            continue;
 +        }
 +
 +        DPRINTF(IQ, "Waking any dependents on register %i.\n",
 +                (int) dest_reg);
 +
 +        //Go through the dependency chain, marking the registers as
 +        //ready within the waiting instructions.
 +        DynInstPtr dep_inst = dependGraph.pop(dest_reg);
 +
 +        while (dep_inst) {
 +            DPRINTF(IQ, "Waking up a dependent instruction, PC%#x.\n",
 +                    dep_inst->readPC());
 +
 +            // Might want to give more information to the instruction
 +            // so that it knows which of its source registers is
 +            // ready.  However that would mean that the dependency
 +            // graph entries would need to hold the src_reg_idx.
 +            dep_inst->markSrcRegReady();
 +
 +            addIfReady(dep_inst);
 +
 +            dep_inst = dependGraph.pop(dest_reg);
 +
 +            ++dependents;
 +        }
 +
 +        // Reset the head node now that all of its dependents have
 +        // been woken up.
 +        assert(dependGraph.empty(dest_reg));
 +        dependGraph.clearInst(dest_reg);
 +
 +        // Mark the scoreboard as having that register ready.
 +        regScoreboard[dest_reg] = true;
 +    }
 +    return dependents;
 +}
 +
 +template <class Impl>
 +void
 +InstructionQueue<Impl>::addReadyMemInst(DynInstPtr &ready_inst)
 +{
 +    OpClass op_class = ready_inst->opClass();
 +
 +    readyInsts[op_class].push(ready_inst);
 +
 +    // Will need to reorder the list if either a queue is not on the list,
 +    // or it has an older instruction than last time.
 +    if (!queueOnList[op_class]) {
 +        addToOrderList(op_class);
 +    } else if (readyInsts[op_class].top()->seqNum  <
 +               (*readyIt[op_class]).oldestInst) {
 +        listOrder.erase(readyIt[op_class]);
 +        addToOrderList(op_class);
 +    }
 +
 +    DPRINTF(IQ, "Instruction is ready to issue, putting it onto "
 +            "the ready list, PC %#x opclass:%i [sn:%lli].\n",
 +            ready_inst->readPC(), op_class, ready_inst->seqNum);
 +}
 +
 +template <class Impl>
 +void
 +InstructionQueue<Impl>::rescheduleMemInst(DynInstPtr &resched_inst)
 +{
 +    memDepUnit[resched_inst->threadNumber].reschedule(resched_inst);
 +}
 +
 +template <class Impl>
 +void
 +InstructionQueue<Impl>::replayMemInst(DynInstPtr &replay_inst)
 +{
 +    memDepUnit[replay_inst->threadNumber].replay(replay_inst);
 +}
 +
 +template <class Impl>
 +void
 +InstructionQueue<Impl>::completeMemInst(DynInstPtr &completed_inst)
 +{
 +    int tid = completed_inst->threadNumber;
 +
 +    DPRINTF(IQ, "Completing mem instruction PC:%#x [sn:%lli]\n",
 +            completed_inst->readPC(), completed_inst->seqNum);
 +
 +    ++freeEntries;
 +
 +    completed_inst->memOpDone = true;
 +
 +    memDepUnit[tid].completed(completed_inst);
 +
 +    count[tid]--;
 +}
 +
 +template <class Impl>
 +void
 +InstructionQueue<Impl>::violation(DynInstPtr &store,
 +                                  DynInstPtr &faulting_load)
 +{
 +    memDepUnit[store->threadNumber].violation(store, faulting_load);
 +}
 +
 +template <class Impl>
 +void
 +InstructionQueue<Impl>::squash(unsigned tid)
 +{
 +    DPRINTF(IQ, "[tid:%i]: Starting to squash instructions in "
 +            "the IQ.\n", tid);
 +
 +    // Read instruction sequence number of last instruction out of the
 +    // time buffer.
 +    squashedSeqNum[tid] = fromCommit->commitInfo[tid].doneSeqNum;
 +
 +    // Call doSquash if there are insts in the IQ
 +    if (count[tid] > 0) {
 +        doSquash(tid);
 +    }
 +
 +    // Also tell the memory dependence unit to squash.
 +    memDepUnit[tid].squash(squashedSeqNum[tid], tid);
 +}
 +
 +template <class Impl>
 +void
 +InstructionQueue<Impl>::doSquash(unsigned tid)
 +{
 +    // Start at the tail.
 +    ListIt squash_it = instList[tid].end();
 +    --squash_it;
 +
 +    DPRINTF(IQ, "[tid:%i]: Squashing until sequence number %i!\n",
 +            tid, squashedSeqNum[tid]);
 +
 +    // Squash any instructions younger than the squashed sequence number
 +    // given.
 +    while (squash_it != instList[tid].end() &&
 +           (*squash_it)->seqNum > squashedSeqNum[tid]) {
 +
 +        DynInstPtr squashed_inst = (*squash_it);
 +
 +        // Only handle the instruction if it actually is in the IQ and
 +        // hasn't already been squashed in the IQ.
 +        if (squashed_inst->threadNumber != tid ||
 +            squashed_inst->isSquashedInIQ()) {
 +            --squash_it;
 +            continue;
 +        }
 +
 +        if (!squashed_inst->isIssued() ||
 +            (squashed_inst->isMemRef() &&
 +             !squashed_inst->memOpDone)) {
 +
 +            // Remove the instruction from the dependency list.
 +            if (!squashed_inst->isNonSpeculative() &&
 +                !squashed_inst->isStoreConditional() &&
 +                !squashed_inst->isMemBarrier() &&
 +                !squashed_inst->isWriteBarrier()) {
 +
 +                for (int src_reg_idx = 0;
 +                     src_reg_idx < squashed_inst->numSrcRegs();
 +                     src_reg_idx++)
 +                {
 +                    PhysRegIndex src_reg =
 +                        squashed_inst->renamedSrcRegIdx(src_reg_idx);
 +
 +                    // Only remove it from the dependency graph if it
 +                    // was placed there in the first place.
 +
 +                    // Instead of doing a linked list traversal, we
 +                    // can just remove these squashed instructions
 +                    // either at issue time, or when the register is
 +                    // overwritten.  The only downside to this is it
 +                    // leaves more room for error.
 +
 +                    if (!squashed_inst->isReadySrcRegIdx(src_reg_idx) &&
 +                        src_reg < numPhysRegs) {
 +                        dependGraph.remove(src_reg, squashed_inst);
 +                    }
 +
 +
 +                    ++iqSquashedOperandsExamined;
 +                }
 +            } else {
 +                NonSpecMapIt ns_inst_it =
 +                    nonSpecInsts.find(squashed_inst->seqNum);
 +                assert(ns_inst_it != nonSpecInsts.end());
 +
 +                (*ns_inst_it).second = NULL;
 +
 +                nonSpecInsts.erase(ns_inst_it);
 +
 +                ++iqSquashedNonSpecRemoved;
 +            }
 +
 +            // Might want to also clear out the head of the dependency graph.
 +
 +            // Mark it as squashed within the IQ.
 +            squashed_inst->setSquashedInIQ();
 +
 +            // @todo: Remove this hack where several statuses are set so the
 +            // inst will flow through the rest of the pipeline.
 +            squashed_inst->setIssued();
 +            squashed_inst->setCanCommit();
 +            squashed_inst->removeInIQ();
 +
 +            //Update Thread IQ Count
 +            count[squashed_inst->threadNumber]--;
 +
 +            ++freeEntries;
 +
 +            DPRINTF(IQ, "[tid:%i]: Instruction [sn:%lli] PC %#x "
 +                    "squashed.\n",
 +                    tid, squashed_inst->seqNum, squashed_inst->readPC());
 +        }
 +
 +        instList[tid].erase(squash_it--);
 +        ++iqSquashedInstsExamined;
 +    }
 +}
 +
 +template <class Impl>
 +bool
 +InstructionQueue<Impl>::addToDependents(DynInstPtr &new_inst)
 +{
 +    // Loop through the instruction's source registers, adding
 +    // them to the dependency list if they are not ready.
 +    int8_t total_src_regs = new_inst->numSrcRegs();
 +    bool return_val = false;
 +
 +    for (int src_reg_idx = 0;
 +         src_reg_idx < total_src_regs;
 +         src_reg_idx++)
 +    {
 +        // Only add it to the dependency graph if it's not ready.
 +        if (!new_inst->isReadySrcRegIdx(src_reg_idx)) {
 +            PhysRegIndex src_reg = new_inst->renamedSrcRegIdx(src_reg_idx);
 +
 +            // Check the IQ's scoreboard to make sure the register
 +            // hasn't become ready while the instruction was in flight
 +            // between stages.  Only if it really isn't ready should
 +            // it be added to the dependency graph.
 +            if (src_reg >= numPhysRegs) {
 +                continue;
 +            } else if (regScoreboard[src_reg] == false) {
 +                DPRINTF(IQ, "Instruction PC %#x has src reg %i that "
 +                        "is being added to the dependency chain.\n",
 +                        new_inst->readPC(), src_reg);
 +
 +                dependGraph.insert(src_reg, new_inst);
 +
 +                // Change the return value to indicate that something
 +                // was added to the dependency graph.
 +                return_val = true;
 +            } else {
 +                DPRINTF(IQ, "Instruction PC %#x has src reg %i that "
 +                        "became ready before it reached the IQ.\n",
 +                        new_inst->readPC(), src_reg);
 +                // Mark a register ready within the instruction.
 +                new_inst->markSrcRegReady(src_reg_idx);
 +            }
 +        }
 +    }
 +
 +    return return_val;
 +}
 +
 +template <class Impl>
 +void
 +InstructionQueue<Impl>::addToProducers(DynInstPtr &new_inst)
 +{
 +    // Nothing really needs to be marked when an instruction becomes
 +    // the producer of a register's value, but for convenience a ptr
 +    // to the producing instruction will be placed in the head node of
 +    // the dependency links.
 +    int8_t total_dest_regs = new_inst->numDestRegs();
 +
 +    for (int dest_reg_idx = 0;
 +         dest_reg_idx < total_dest_regs;
 +         dest_reg_idx++)
 +    {
 +        PhysRegIndex dest_reg = new_inst->renamedDestRegIdx(dest_reg_idx);
 +
 +        // Instructions that use the misc regs will have a reg number
 +        // higher than the normal physical registers.  In this case these
 +        // registers are not renamed, and there is no need to track
 +        // dependencies as these instructions must be executed at commit.
 +        if (dest_reg >= numPhysRegs) {
 +            continue;
 +        }
 +
 +        if (!dependGraph.empty(dest_reg)) {
 +            dependGraph.dump();
 +            panic("Dependency graph %i not empty!", dest_reg);
 +        }
 +
 +        dependGraph.setInst(dest_reg, new_inst);
 +
 +        // Mark the scoreboard to say it's not yet ready.
 +        regScoreboard[dest_reg] = false;
 +    }
 +}
 +
 +template <class Impl>
 +void
 +InstructionQueue<Impl>::addIfReady(DynInstPtr &inst)
 +{
 +    // If the instruction now has all of its source registers
 +    // available, then add it to the list of ready instructions.
 +    if (inst->readyToIssue()) {
 +
 +        //Add the instruction to the proper ready list.
 +        if (inst->isMemRef()) {
 +
 +            DPRINTF(IQ, "Checking if memory instruction can issue.\n");
 +
 +            // Message to the mem dependence unit that this instruction has
 +            // its registers ready.
 +            memDepUnit[inst->threadNumber].regsReady(inst);
 +
 +            return;
 +        }
 +
 +        OpClass op_class = inst->opClass();
 +
 +        DPRINTF(IQ, "Instruction is ready to issue, putting it onto "
 +                "the ready list, PC %#x opclass:%i [sn:%lli].\n",
 +                inst->readPC(), op_class, inst->seqNum);
 +
 +        readyInsts[op_class].push(inst);
 +
 +        // Will need to reorder the list if either a queue is not on the list,
 +        // or it has an older instruction than last time.
 +        if (!queueOnList[op_class]) {
 +            addToOrderList(op_class);
 +        } else if (readyInsts[op_class].top()->seqNum  <
 +                   (*readyIt[op_class]).oldestInst) {
 +            listOrder.erase(readyIt[op_class]);
 +            addToOrderList(op_class);
 +        }
 +    }
 +}
 +
 +template <class Impl>
 +int
 +InstructionQueue<Impl>::countInsts()
 +{
 +    //ksewell:This works but definitely could use a cleaner write
 +    //with a more intuitive way of counting. Right now it's
 +    //just brute force ....
 +
 +#if 0
 +    int total_insts = 0;
 +
 +    for (int i = 0; i < numThreads; ++i) {
 +        ListIt count_it = instList[i].begin();
 +
 +        while (count_it != instList[i].end()) {
 +            if (!(*count_it)->isSquashed() && !(*count_it)->isSquashedInIQ()) {
 +                if (!(*count_it)->isIssued()) {
 +                    ++total_insts;
 +                } else if ((*count_it)->isMemRef() &&
 +                           !(*count_it)->memOpDone) {
 +                    // Loads that have not been marked as executed still count
 +                    // towards the total instructions.
 +                    ++total_insts;
 +                }
 +            }
 +
 +            ++count_it;
 +        }
 +    }
 +
 +    return total_insts;
 +#else
 +    return numEntries - freeEntries;
 +#endif
 +}
 +
 +template <class Impl>
 +void
 +InstructionQueue<Impl>::dumpLists()
 +{
 +    for (int i = 0; i < Num_OpClasses; ++i) {
 +        cprintf("Ready list %i size: %i\n", i, readyInsts[i].size());
 +
 +        cprintf("\n");
 +    }
 +
 +    cprintf("Non speculative list size: %i\n", nonSpecInsts.size());
 +
 +    NonSpecMapIt non_spec_it = nonSpecInsts.begin();
 +    NonSpecMapIt non_spec_end_it = nonSpecInsts.end();
 +
 +    cprintf("Non speculative list: ");
 +
 +    while (non_spec_it != non_spec_end_it) {
 +        cprintf("%#x [sn:%lli]", (*non_spec_it).second->readPC(),
 +                (*non_spec_it).second->seqNum);
 +        ++non_spec_it;
 +    }
 +
 +    cprintf("\n");
 +
 +    ListOrderIt list_order_it = listOrder.begin();
 +    ListOrderIt list_order_end_it = listOrder.end();
 +    int i = 1;
 +
 +    cprintf("List order: ");
 +
 +    while (list_order_it != list_order_end_it) {
 +        cprintf("%i OpClass:%i [sn:%lli] ", i, (*list_order_it).queueType,
 +                (*list_order_it).oldestInst);
 +
 +        ++list_order_it;
 +        ++i;
 +    }
 +
 +    cprintf("\n");
 +}
 +
 +
 +template <class Impl>
 +void
 +InstructionQueue<Impl>::dumpInsts()
 +{
 +    for (int i = 0; i < numThreads; ++i) {
 +        int num = 0;
 +        int valid_num = 0;
 +        ListIt inst_list_it = instList[i].begin();
 +
 +        while (inst_list_it != instList[i].end())
 +        {
 +            cprintf("Instruction:%i\n",
 +                    num);
 +            if (!(*inst_list_it)->isSquashed()) {
 +                if (!(*inst_list_it)->isIssued()) {
 +                    ++valid_num;
 +                    cprintf("Count:%i\n", valid_num);
 +                } else if ((*inst_list_it)->isMemRef() &&
 +                           !(*inst_list_it)->memOpDone) {
 +                    // Loads that have not been marked as executed
 +                    // still count towards the total instructions.
 +                    ++valid_num;
 +                    cprintf("Count:%i\n", valid_num);
 +                }
 +            }
 +
 +            cprintf("PC:%#x\n[sn:%lli]\n[tid:%i]\n"
 +                    "Issued:%i\nSquashed:%i\n",
 +                    (*inst_list_it)->readPC(),
 +                    (*inst_list_it)->seqNum,
 +                    (*inst_list_it)->threadNumber,
 +                    (*inst_list_it)->isIssued(),
 +                    (*inst_list_it)->isSquashed());
 +
 +            if ((*inst_list_it)->isMemRef()) {
 +                cprintf("MemOpDone:%i\n", (*inst_list_it)->memOpDone);
 +            }
 +
 +            cprintf("\n");
 +
 +            inst_list_it++;
 +            ++num;
 +        }
 +    }
++
++    cprintf("Insts to Execute list:\n");
++
++    int num = 0;
++    int valid_num = 0;
++    ListIt inst_list_it = instsToExecute.begin();
++
++    while (inst_list_it != instsToExecute.end())
++    {
++        cprintf("Instruction:%i\n",
++                num);
++        if (!(*inst_list_it)->isSquashed()) {
++            if (!(*inst_list_it)->isIssued()) {
++                ++valid_num;
++                cprintf("Count:%i\n", valid_num);
++            } else if ((*inst_list_it)->isMemRef() &&
++                       !(*inst_list_it)->memOpDone) {
++                // Loads that have not been marked as executed
++                // still count towards the total instructions.
++                ++valid_num;
++                cprintf("Count:%i\n", valid_num);
++            }
++        }
++
++        cprintf("PC:%#x\n[sn:%lli]\n[tid:%i]\n"
++                "Issued:%i\nSquashed:%i\n",
++                (*inst_list_it)->readPC(),
++                (*inst_list_it)->seqNum,
++                (*inst_list_it)->threadNumber,
++                (*inst_list_it)->isIssued(),
++                (*inst_list_it)->isSquashed());
++
++        if ((*inst_list_it)->isMemRef()) {
++            cprintf("MemOpDone:%i\n", (*inst_list_it)->memOpDone);
++        }
++
++        cprintf("\n");
++
++        inst_list_it++;
++        ++num;
++    }
 +}
index 51eb23cd7e772b4d5c37e86f9b6d29c148604ca5,0000000000000000000000000000000000000000..d65510c3091e3c6b94e199f71519c6d2b3153809
mode 100644,000000..100644
--- /dev/null
@@@ -1,324 -1,0 +1,323 @@@
 +/*
 + * Copyright (c) 2004-2006 The Regents of The University of Michigan
 + * 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.
 + */
 +
 +#ifndef __CPU_O3_LSQ_HH__
 +#define __CPU_O3_LSQ_HH__
 +
 +#include <map>
 +#include <queue>
 +
 +#include "config/full_system.hh"
 +#include "cpu/inst_seq.hh"
 +//#include "cpu/o3/cpu_policy.hh"
 +#include "cpu/o3/lsq_unit.hh"
 +#include "mem/port.hh"
 +//#include "mem/page_table.hh"
 +#include "sim/sim_object.hh"
 +
 +template <class Impl>
 +class LSQ {
 +  public:
 +    typedef typename Impl::Params Params;
 +    typedef typename Impl::FullCPU FullCPU;
 +    typedef typename Impl::DynInstPtr DynInstPtr;
 +    typedef typename Impl::CPUPol::IEW IEW;
 +    typedef typename Impl::CPUPol::LSQUnit LSQUnit;
 +
++    /** SMT policy. */
 +    enum LSQPolicy {
 +        Dynamic,
 +        Partitioned,
 +        Threshold
 +    };
 +
 +    /** Constructs an LSQ with the given parameters. */
 +    LSQ(Params *params);
 +
 +    /** Returns the name of the LSQ. */
 +    std::string name() const;
 +
 +    /** Sets the pointer to the list of active threads. */
 +    void setActiveThreads(std::list<unsigned> *at_ptr);
 +    /** Sets the CPU pointer. */
 +    void setCPU(FullCPU *cpu_ptr);
 +    /** Sets the IEW stage pointer. */
 +    void setIEW(IEW *iew_ptr);
 +    /** Sets the page table pointer. */
 +//    void setPageTable(PageTable *pt_ptr);
-     Fault executeLoad(int lq_idx, unsigned tid)
-     { return thread[tid].executeLoad(lq_idx); }
++    /** Switches out the LSQ. */
 +    void switchOut();
++    /** Takes over execution from another CPU's thread. */
 +    void takeOverFrom();
 +
 +    /** Number of entries needed for the given amount of threads.*/
 +    int entryAmount(int num_threads);
 +    void removeEntries(unsigned tid);
 +    /** Reset the max entries for each thread. */
 +    void resetEntries();
 +    /** Resize the max entries for a thread. */
 +    void resizeEntries(unsigned size, unsigned tid);
 +
 +    /** Ticks the LSQ. */
 +    void tick();
 +    /** Ticks a specific LSQ Unit. */
 +    void tick(unsigned tid)
 +    { thread[tid].tick(); }
 +
 +    /** Inserts a load into the LSQ. */
 +    void insertLoad(DynInstPtr &load_inst);
 +    /** Inserts a store into the LSQ. */
 +    void insertStore(DynInstPtr &store_inst);
 +
 +    /** Executes a load. */
 +    Fault executeLoad(DynInstPtr &inst);
 +
 +    /** Executes a store. */
 +    Fault executeStore(DynInstPtr &inst);
 +
 +    /**
 +     * Commits loads up until the given sequence number for a specific thread.
 +     */
 +    void commitLoads(InstSeqNum &youngest_inst, unsigned tid)
 +    { thread[tid].commitLoads(youngest_inst); }
 +
 +    /**
 +     * Commits stores up until the given sequence number for a specific thread.
 +     */
 +    void commitStores(InstSeqNum &youngest_inst, unsigned tid)
 +    { thread[tid].commitStores(youngest_inst); }
 +
 +    /**
 +     * Attempts to write back stores until all cache ports are used or the
 +     * interface becomes blocked.
 +     */
 +    void writebackStores();
 +    /** Same as above, but only for one thread. */
 +    void writebackStores(unsigned tid);
 +
 +    /**
 +     * Squash instructions from a thread until the specified sequence number.
 +     */
 +    void squash(const InstSeqNum &squashed_num, unsigned tid)
 +    { thread[tid].squash(squashed_num); }
 +
 +    /** Returns whether or not there was a memory ordering violation. */
 +    bool violation();
 +    /**
 +     * Returns whether or not there was a memory ordering violation for a
 +     * specific thread.
 +     */
 +    bool violation(unsigned tid)
 +    { return thread[tid].violation(); }
 +
 +    /** Returns if a load is blocked due to the memory system for a specific
 +     *  thread.
 +     */
 +    bool loadBlocked(unsigned tid)
 +    { return thread[tid].loadBlocked(); }
 +
 +    bool isLoadBlockedHandled(unsigned tid)
 +    { return thread[tid].isLoadBlockedHandled(); }
 +
 +    void setLoadBlockedHandled(unsigned tid)
 +    { thread[tid].setLoadBlockedHandled(); }
 +
 +    /** Gets the instruction that caused the memory ordering violation. */
 +    DynInstPtr getMemDepViolator(unsigned tid)
 +    { return thread[tid].getMemDepViolator(); }
 +
 +    /** Returns the head index of the load queue for a specific thread. */
 +    int getLoadHead(unsigned tid)
 +    { return thread[tid].getLoadHead(); }
 +
 +    /** Returns the sequence number of the head of the load queue. */
 +    InstSeqNum getLoadHeadSeqNum(unsigned tid)
 +    {
 +        return thread[tid].getLoadHeadSeqNum();
 +    }
 +
 +    /** Returns the head index of the store queue. */
 +    int getStoreHead(unsigned tid)
 +    { return thread[tid].getStoreHead(); }
 +
 +    /** Returns the sequence number of the head of the store queue. */
 +    InstSeqNum getStoreHeadSeqNum(unsigned tid)
 +    {
 +        return thread[tid].getStoreHeadSeqNum();
 +    }
 +
 +    /** Returns the number of instructions in all of the queues. */
 +    int getCount();
 +    /** Returns the number of instructions in the queues of one thread. */
 +    int getCount(unsigned tid)
 +    { return thread[tid].getCount(); }
 +
 +    /** Returns the total number of loads in the load queue. */
 +    int numLoads();
 +    /** Returns the total number of loads for a single thread. */
 +    int numLoads(unsigned tid)
 +    { return thread[tid].numLoads(); }
 +
 +    /** Returns the total number of stores in the store queue. */
 +    int numStores();
 +    /** Returns the total number of stores for a single thread. */
 +    int numStores(unsigned tid)
 +    { return thread[tid].numStores(); }
 +
 +    /** Returns the total number of loads that are ready. */
 +    int numLoadsReady();
 +    /** Returns the number of loads that are ready for a single thread. */
 +    int numLoadsReady(unsigned tid)
 +    { return thread[tid].numLoadsReady(); }
 +
 +    /** Returns the number of free entries. */
 +    unsigned numFreeEntries();
 +    /** Returns the number of free entries for a specific thread. */
 +    unsigned numFreeEntries(unsigned tid);
 +
 +    /** Returns if the LSQ is full (either LQ or SQ is full). */
 +    bool isFull();
 +    /**
 +     * Returns if the LSQ is full for a specific thread (either LQ or SQ is
 +     * full).
 +     */
 +    bool isFull(unsigned tid);
 +
 +    /** Returns if any of the LQs are full. */
 +    bool lqFull();
 +    /** Returns if the LQ of a given thread is full. */
 +    bool lqFull(unsigned tid);
 +
 +    /** Returns if any of the SQs are full. */
 +    bool sqFull();
 +    /** Returns if the SQ of a given thread is full. */
 +    bool sqFull(unsigned tid);
 +
 +    /**
 +     * Returns if the LSQ is stalled due to a memory operation that must be
 +     * replayed.
 +     */
 +    bool isStalled();
 +    /**
 +     * Returns if the LSQ of a specific thread is stalled due to a memory
 +     * operation that must be replayed.
 +     */
 +    bool isStalled(unsigned tid);
 +
 +    /** Returns whether or not there are any stores to write back to memory. */
 +    bool hasStoresToWB();
 +
 +    /** Returns whether or not a specific thread has any stores to write back
 +     * to memory.
 +     */
 +    bool hasStoresToWB(unsigned tid)
 +    { return thread[tid].hasStoresToWB(); }
 +
 +    /** Returns the number of stores a specific thread has to write back. */
 +    int  numStoresToWB(unsigned tid)
 +    { return thread[tid].numStoresToWB(); }
 +
 +    /** Returns if the LSQ will write back to memory this cycle. */
 +    bool willWB();
 +    /** Returns if the LSQ of a specific thread will write back to memory this
 +     * cycle.
 +     */
 +    bool willWB(unsigned tid)
 +    { return thread[tid].willWB(); }
 +
 +    /** Debugging function to print out all instructions. */
 +    void dumpInsts();
 +    /** Debugging function to print out instructions from a specific thread. */
 +    void dumpInsts(unsigned tid)
 +    { thread[tid].dumpInsts(); }
 +
 +    /** Executes a read operation, using the load specified at the load index. */
 +    template <class T>
 +    Fault read(RequestPtr req, T &data, int load_idx);
 +
 +    /** Executes a store operation, using the store specified at the store
 +     *   index.
 +     */
 +    template <class T>
 +    Fault write(RequestPtr req, T &data, int store_idx);
 +
 +  private:
 +    /** The LSQ policy for SMT mode. */
 +    LSQPolicy lsqPolicy;
 +
 +    /** The LSQ units for individual threads. */
 +    LSQUnit thread[Impl::MaxThreads];
 +
 +    /** The CPU pointer. */
 +    FullCPU *cpu;
 +
 +    /** The IEW stage pointer. */
 +    IEW *iewStage;
 +
 +    /** The pointer to the page table. */
 +//    PageTable *pTable;
 +
 +    /** List of Active Threads in System. */
 +    std::list<unsigned> *activeThreads;
 +
 +    /** Total Size of LQ Entries. */
 +    unsigned LQEntries;
 +    /** Total Size of SQ Entries. */
 +    unsigned SQEntries;
 +
 +    /** Max LQ Size - Used to Enforce Sharing Policies. */
 +    unsigned maxLQEntries;
 +
 +    /** Max SQ Size - Used to Enforce Sharing Policies. */
 +    unsigned maxSQEntries;
 +
 +    /** Number of Threads. */
 +    unsigned numThreads;
 +};
 +
 +template <class Impl>
 +template <class T>
 +Fault
 +LSQ<Impl>::read(RequestPtr req, T &data, int load_idx)
 +{
 +    unsigned tid = req->getThreadNum();
 +
 +    return thread[tid].read(req, data, load_idx);
 +}
 +
 +template <class Impl>
 +template <class T>
 +Fault
 +LSQ<Impl>::write(RequestPtr req, T &data, int store_idx)
 +{
 +    unsigned tid = req->getThreadNum();
 +
 +    return thread[tid].write(req, data, store_idx);
 +}
 +
 +#endif // __CPU_O3_LSQ_HH__
index b339cea2c4e5439e050c80a8ba09244434f60df6,0000000000000000000000000000000000000000..393d8947d7ba483346b9bf13b981449ae0c99ad2
mode 100644,000000..100644
--- /dev/null
@@@ -1,629 -1,0 +1,638 @@@
 +/*
 + * Copyright (c) 2004-2006 The Regents of The University of Michigan
 + * 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.
 + */
 +
 +#ifndef __CPU_O3_LSQ_UNIT_HH__
 +#define __CPU_O3_LSQ_UNIT_HH__
 +
 +#include <algorithm>
 +#include <map>
 +#include <queue>
 +
 +#include "arch/faults.hh"
 +#include "config/full_system.hh"
 +#include "base/hashmap.hh"
 +#include "cpu/inst_seq.hh"
 +#include "mem/packet.hh"
 +#include "mem/port.hh"
 +//#include "mem/page_table.hh"
 +//#include "sim/debug.hh"
 +//#include "sim/sim_object.hh"
 +
 +/**
 + * Class that implements the actual LQ and SQ for each specific
 + * thread.  Both are circular queues; load entries are freed upon
 + * committing, while store entries are freed once they writeback. The
 + * LSQUnit tracks if there are memory ordering violations, and also
 + * detects partial load to store forwarding cases (a store only has
 + * part of a load's data) that requires the load to wait until the
 + * store writes back. In the former case it holds onto the instruction
 + * until the dependence unit looks at it, and in the latter it stalls
 + * the LSQ until the store writes back. At that point the load is
 + * replayed.
 + */
 +template <class Impl>
 +class LSQUnit {
 +  protected:
 +    typedef TheISA::IntReg IntReg;
 +  public:
 +    typedef typename Impl::Params Params;
 +    typedef typename Impl::FullCPU FullCPU;
 +    typedef typename Impl::DynInstPtr DynInstPtr;
 +    typedef typename Impl::CPUPol::IEW IEW;
 +    typedef typename Impl::CPUPol::IssueStruct IssueStruct;
 +
 +  public:
 +    /** Constructs an LSQ unit. init() must be called prior to use. */
 +    LSQUnit();
 +
 +    /** Initializes the LSQ unit with the specified number of entries. */
 +    void init(Params *params, unsigned maxLQEntries,
 +              unsigned maxSQEntries, unsigned id);
 +
 +    /** Returns the name of the LSQ unit. */
 +    std::string name() const;
 +
 +    /** Sets the CPU pointer. */
 +    void setCPU(FullCPU *cpu_ptr);
 +
 +    /** Sets the IEW stage pointer. */
 +    void setIEW(IEW *iew_ptr)
 +    { iewStage = iew_ptr; }
 +
 +    /** Sets the page table pointer. */
 +//    void setPageTable(PageTable *pt_ptr);
 +
++    /** Switches out LSQ unit. */
 +    void switchOut();
 +
++    /** Takes over from another CPU's thread. */
 +    void takeOverFrom();
 +
++    /** Returns if the LSQ is switched out. */
 +    bool isSwitchedOut() { return switchedOut; }
 +
 +    /** Ticks the LSQ unit, which in this case only resets the number of
 +     * used cache ports.
 +     * @todo: Move the number of used ports up to the LSQ level so it can
 +     * be shared by all LSQ units.
 +     */
 +    void tick() { usedPorts = 0; }
 +
 +    /** Inserts an instruction. */
 +    void insert(DynInstPtr &inst);
 +    /** Inserts a load instruction. */
 +    void insertLoad(DynInstPtr &load_inst);
 +    /** Inserts a store instruction. */
 +    void insertStore(DynInstPtr &store_inst);
 +
 +    /** Executes a load instruction. */
 +    Fault executeLoad(DynInstPtr &inst);
 +
 +    Fault executeLoad(int lq_idx) { panic("Not implemented"); return NoFault; }
 +    /** Executes a store instruction. */
 +    Fault executeStore(DynInstPtr &inst);
 +
 +    /** Commits the head load. */
 +    void commitLoad();
 +    /** Commits loads older than a specific sequence number. */
 +    void commitLoads(InstSeqNum &youngest_inst);
 +
 +    /** Commits stores older than a specific sequence number. */
 +    void commitStores(InstSeqNum &youngest_inst);
 +
 +    /** Writes back stores. */
 +    void writebackStores();
 +
 +    void completeDataAccess(PacketPtr pkt);
 +
 +    void completeStoreDataAccess(DynInstPtr &inst);
 +
 +    // @todo: Include stats in the LSQ unit.
 +    //void regStats();
 +
 +    /** Clears all the entries in the LQ. */
 +    void clearLQ();
 +
 +    /** Clears all the entries in the SQ. */
 +    void clearSQ();
 +
 +    /** Resizes the LQ to a given size. */
 +    void resizeLQ(unsigned size);
 +
 +    /** Resizes the SQ to a given size. */
 +    void resizeSQ(unsigned size);
 +
 +    /** Squashes all instructions younger than a specific sequence number. */
 +    void squash(const InstSeqNum &squashed_num);
 +
 +    /** Returns if there is a memory ordering violation. Value is reset upon
 +     * call to getMemDepViolator().
 +     */
 +    bool violation() { return memDepViolator; }
 +
 +    /** Returns the memory ordering violator. */
 +    DynInstPtr getMemDepViolator();
 +
 +    /** Returns if a load became blocked due to the memory system. */
 +    bool loadBlocked()
 +    { return isLoadBlocked; }
 +
++    /** Clears the signal that a load became blocked. */
 +    void clearLoadBlocked()
 +    { isLoadBlocked = false; }
 +
++    /** Returns if the blocked load was handled. */
 +    bool isLoadBlockedHandled()
 +    { return loadBlockedHandled; }
 +
++    /** Records the blocked load as being handled. */
 +    void setLoadBlockedHandled()
 +    { loadBlockedHandled = true; }
 +
 +    /** Returns the number of free entries (min of free LQ and SQ entries). */
 +    unsigned numFreeEntries();
 +
 +    /** Returns the number of loads ready to execute. */
 +    int numLoadsReady();
 +
 +    /** Returns the number of loads in the LQ. */
 +    int numLoads() { return loads; }
 +
 +    /** Returns the number of stores in the SQ. */
 +    int numStores() { return stores; }
 +
 +    /** Returns if either the LQ or SQ is full. */
 +    bool isFull() { return lqFull() || sqFull(); }
 +
 +    /** Returns if the LQ is full. */
 +    bool lqFull() { return loads >= (LQEntries - 1); }
 +
 +    /** Returns if the SQ is full. */
 +    bool sqFull() { return stores >= (SQEntries - 1); }
 +
 +    /** Returns the number of instructions in the LSQ. */
 +    unsigned getCount() { return loads + stores; }
 +
 +    /** Returns if there are any stores to writeback. */
 +    bool hasStoresToWB() { return storesToWB; }
 +
 +    /** Returns the number of stores to writeback. */
 +    int numStoresToWB() { return storesToWB; }
 +
 +    /** Returns if the LSQ unit will writeback on this cycle. */
 +    bool willWB() { return storeQueue[storeWBIdx].canWB &&
 +                        !storeQueue[storeWBIdx].completed/* &&
 +                                                            !dcacheInterface->isBlocked()*/; }
 +
 +  private:
 +    /** Completes the store at the specified index. */
 +    void completeStore(int store_idx);
 +
 +    /** Increments the given store index (circular queue). */
 +    inline void incrStIdx(int &store_idx);
 +    /** Decrements the given store index (circular queue). */
 +    inline void decrStIdx(int &store_idx);
 +    /** Increments the given load index (circular queue). */
 +    inline void incrLdIdx(int &load_idx);
 +    /** Decrements the given load index (circular queue). */
 +    inline void decrLdIdx(int &load_idx);
 +
 +  public:
 +    /** Debugging function to dump instructions in the LSQ. */
 +    void dumpInsts();
 +
 +  private:
 +    /** Pointer to the CPU. */
 +    FullCPU *cpu;
 +
 +    /** Pointer to the IEW stage. */
 +    IEW *iewStage;
 +
 +    MemObject *mem;
 +
 +    class DcachePort : public Port
 +    {
 +      protected:
 +        FullCPU *cpu;
 +        LSQUnit *lsq;
 +
 +      public:
 +        DcachePort(FullCPU *_cpu, LSQUnit *_lsq)
 +            : Port(_lsq->name() + "-dport"), cpu(_cpu), lsq(_lsq)
 +        { }
 +
 +      protected:
 +        virtual Tick recvAtomic(PacketPtr pkt);
 +
 +        virtual void recvFunctional(PacketPtr pkt);
 +
 +        virtual void recvStatusChange(Status status);
 +
 +        virtual void getDeviceAddressRanges(AddrRangeList &resp,
 +                                            AddrRangeList &snoop)
 +        { resp.clear(); snoop.clear(); }
 +
 +        virtual bool recvTiming(PacketPtr pkt);
 +
 +        virtual void recvRetry();
 +    };
 +
 +    /** Pointer to the D-cache. */
 +    DcachePort *dcachePort;
 +
 +    /** Pointer to the page table. */
 +//    PageTable *pTable;
 +
 +  public:
 +    struct SQEntry {
 +        /** Constructs an empty store queue entry. */
 +        SQEntry()
 +            : inst(NULL), req(NULL), size(0), data(0),
 +              canWB(0), committed(0), completed(0)
 +        { }
 +
 +        /** Constructs a store queue entry for a given instruction. */
 +        SQEntry(DynInstPtr &_inst)
 +            : inst(_inst), req(NULL), size(0), data(0),
 +              canWB(0), committed(0), completed(0)
 +        { }
 +
 +        /** The store instruction. */
 +        DynInstPtr inst;
 +        /** The request for the store. */
 +        RequestPtr req;
 +        /** The size of the store. */
 +        int size;
 +        /** The store data. */
 +        IntReg data;
 +        /** Whether or not the store can writeback. */
 +        bool canWB;
 +        /** Whether or not the store is committed. */
 +        bool committed;
 +        /** Whether or not the store is completed. */
 +        bool completed;
 +    };
 +
 +  private:
 +    /** The LSQUnit thread id. */
 +    unsigned lsqID;
 +
 +    /** The store queue. */
 +    std::vector<SQEntry> storeQueue;
 +
 +    /** The load queue. */
 +    std::vector<DynInstPtr> loadQueue;
 +
 +    /** The number of LQ entries, plus a sentinel entry (circular queue).
 +     *  @todo: Consider having var that records the true number of LQ entries.
 +     */
 +    unsigned LQEntries;
 +    /** The number of SQ entries, plus a sentinel entry (circular queue).
 +     *  @todo: Consider having var that records the true number of SQ entries.
 +     */
 +    unsigned SQEntries;
 +
 +    /** The number of load instructions in the LQ. */
 +    int loads;
 +    /** The number of store instructions in the SQ. */
 +    int stores;
 +    /** The number of store instructions in the SQ waiting to writeback. */
 +    int storesToWB;
 +
 +    /** The index of the head instruction in the LQ. */
 +    int loadHead;
 +    /** The index of the tail instruction in the LQ. */
 +    int loadTail;
 +
 +    /** The index of the head instruction in the SQ. */
 +    int storeHead;
 +    /** The index of the first instruction that may be ready to be
 +     * written back, and has not yet been written back.
 +     */
 +    int storeWBIdx;
 +    /** The index of the tail instruction in the SQ. */
 +    int storeTail;
 +
 +    /// @todo Consider moving to a more advanced model with write vs read ports
 +    /** The number of cache ports available each cycle. */
 +    int cachePorts;
 +
 +    /** The number of used cache ports in this cycle. */
 +    int usedPorts;
 +
++    /** Is the LSQ switched out. */
 +    bool switchedOut;
 +
 +    //list<InstSeqNum> mshrSeqNums;
 +
 +    /** Wire to read information from the issue stage time queue. */
 +    typename TimeBuffer<IssueStruct>::wire fromIssue;
 +
 +    /** Whether or not the LSQ is stalled. */
 +    bool stalled;
 +    /** The store that causes the stall due to partial store to load
 +     * forwarding.
 +     */
 +    InstSeqNum stallingStoreIsn;
 +    /** The index of the above store. */
 +    int stallingLoadIdx;
 +
 +    /** Whether or not a load is blocked due to the memory system. */
 +    bool isLoadBlocked;
 +
++    /** Has the blocked load been handled. */
 +    bool loadBlockedHandled;
 +
++    /** The sequence number of the blocked load. */
 +    InstSeqNum blockedLoadSeqNum;
 +
 +    /** The oldest load that caused a memory ordering violation. */
 +    DynInstPtr memDepViolator;
 +
 +    // Will also need how many read/write ports the Dcache has.  Or keep track
 +    // of that in stage that is one level up, and only call executeLoad/Store
 +    // the appropriate number of times.
 +/*
 +    // total number of loads forwaded from LSQ stores
 +    Stats::Vector<> lsq_forw_loads;
 +
 +    // total number of loads ignored due to invalid addresses
 +    Stats::Vector<> inv_addr_loads;
 +
 +    // total number of software prefetches ignored due to invalid addresses
 +    Stats::Vector<> inv_addr_swpfs;
 +
 +    // total non-speculative bogus addresses seen (debug var)
 +    Counter sim_invalid_addrs;
 +    Stats::Vector<> fu_busy;  //cumulative fu busy
 +
 +    // ready loads blocked due to memory disambiguation
 +    Stats::Vector<> lsq_blocked_loads;
 +
 +    Stats::Scalar<> lsqInversion;
 +*/
 +  public:
 +    /** Executes the load at the given index. */
 +    template <class T>
 +    Fault read(Request *req, T &data, int load_idx);
 +
 +    /** Executes the store at the given index. */
 +    template <class T>
 +    Fault write(Request *req, T &data, int store_idx);
 +
 +    /** Returns the index of the head load instruction. */
 +    int getLoadHead() { return loadHead; }
 +    /** Returns the sequence number of the head load instruction. */
 +    InstSeqNum getLoadHeadSeqNum()
 +    {
 +        if (loadQueue[loadHead]) {
 +            return loadQueue[loadHead]->seqNum;
 +        } else {
 +            return 0;
 +        }
 +
 +    }
 +
 +    /** Returns the index of the head store instruction. */
 +    int getStoreHead() { return storeHead; }
 +    /** Returns the sequence number of the head store instruction. */
 +    InstSeqNum getStoreHeadSeqNum()
 +    {
 +        if (storeQueue[storeHead].inst) {
 +            return storeQueue[storeHead].inst->seqNum;
 +        } else {
 +            return 0;
 +        }
 +
 +    }
 +
 +    /** Returns whether or not the LSQ unit is stalled. */
 +    bool isStalled()  { return stalled; }
 +};
 +
 +template <class Impl>
 +template <class T>
 +Fault
 +LSQUnit<Impl>::read(Request *req, T &data, int load_idx)
 +{
 +    DynInstPtr load_inst = loadQueue[load_idx];
 +
 +    assert(load_inst);
 +
 +    assert(!load_inst->isExecuted());
 +
 +    // Make sure this isn't an uncacheable access
 +    // A bit of a hackish way to get uncached accesses to work only if they're
 +    // at the head of the LSQ and are ready to commit (at the head of the ROB
 +    // too).
 +    if (req->getFlags() & UNCACHEABLE &&
 +        (load_idx != loadHead || !load_inst->reachedCommit)) {
 +        iewStage->rescheduleMemInst(load_inst);
 +        return TheISA::genMachineCheckFault();
 +    }
 +
 +    // Check the SQ for any previous stores that might lead to forwarding
 +    int store_idx = load_inst->sqIdx;
 +
 +    int store_size = 0;
 +
 +    DPRINTF(LSQUnit, "Read called, load idx: %i, store idx: %i, "
 +            "storeHead: %i addr: %#x\n",
 +            load_idx, store_idx, storeHead, req->getPaddr());
 +
 +#if 0
 +    if (req->getFlags() & LOCKED) {
 +        cpu->lockAddr = req->getPaddr();
 +        cpu->lockFlag = true;
 +    }
 +#endif
 +
 +    while (store_idx != -1) {
 +        // End once we've reached the top of the LSQ
 +        if (store_idx == storeWBIdx) {
 +            break;
 +        }
 +
 +        // Move the index to one younger
 +        if (--store_idx < 0)
 +            store_idx += SQEntries;
 +
 +        assert(storeQueue[store_idx].inst);
 +
 +        store_size = storeQueue[store_idx].size;
 +
 +        if (store_size == 0)
 +            continue;
 +
 +        // Check if the store data is within the lower and upper bounds of
 +        // addresses that the request needs.
 +        bool store_has_lower_limit =
 +            req->getVaddr() >= storeQueue[store_idx].inst->effAddr;
 +        bool store_has_upper_limit =
 +            (req->getVaddr() + req->getSize()) <=
 +            (storeQueue[store_idx].inst->effAddr + store_size);
 +        bool lower_load_has_store_part =
 +            req->getVaddr() < (storeQueue[store_idx].inst->effAddr +
 +                           store_size);
 +        bool upper_load_has_store_part =
 +            (req->getVaddr() + req->getSize()) >
 +            storeQueue[store_idx].inst->effAddr;
 +
 +        // If the store's data has all of the data needed, we can forward.
 +        if (store_has_lower_limit && store_has_upper_limit) {
 +            // Get shift amount for offset into the store's data.
 +            int shift_amt = req->getVaddr() & (store_size - 1);
 +            // @todo: Magic number, assumes byte addressing
 +            shift_amt = shift_amt << 3;
 +
 +            // Cast this to type T?
 +            data = storeQueue[store_idx].data >> shift_amt;
 +
 +            assert(!load_inst->memData);
 +            load_inst->memData = new uint8_t[64];
 +
 +            memcpy(load_inst->memData, &data, req->getSize());
 +
 +            DPRINTF(LSQUnit, "Forwarding from store idx %i to load to "
 +                    "addr %#x, data %#x\n",
 +                    store_idx, req->getVaddr(), *(load_inst->memData));
 +/*
 +            typename LdWritebackEvent *wb =
 +                new typename LdWritebackEvent(load_inst,
 +                                              iewStage);
 +
 +            // We'll say this has a 1 cycle load-store forwarding latency
 +            // for now.
 +            // @todo: Need to make this a parameter.
 +            wb->schedule(curTick);
 +*/
 +            // Should keep track of stat for forwarded data
 +            return NoFault;
 +        } else if ((store_has_lower_limit && lower_load_has_store_part) ||
 +                   (store_has_upper_limit && upper_load_has_store_part) ||
 +                   (lower_load_has_store_part && upper_load_has_store_part)) {
 +            // This is the partial store-load forwarding case where a store
 +            // has only part of the load's data.
 +
 +            // If it's already been written back, then don't worry about
 +            // stalling on it.
 +            if (storeQueue[store_idx].completed) {
 +                continue;
 +            }
 +
 +            // Must stall load and force it to retry, so long as it's the oldest
 +            // load that needs to do so.
 +            if (!stalled ||
 +                (stalled &&
 +                 load_inst->seqNum <
 +                 loadQueue[stallingLoadIdx]->seqNum)) {
 +                stalled = true;
 +                stallingStoreIsn = storeQueue[store_idx].inst->seqNum;
 +                stallingLoadIdx = load_idx;
 +            }
 +
 +            // Tell IQ/mem dep unit that this instruction will need to be
 +            // rescheduled eventually
 +            iewStage->rescheduleMemInst(load_inst);
 +
 +            // Do not generate a writeback event as this instruction is not
 +            // complete.
 +            DPRINTF(LSQUnit, "Load-store forwarding mis-match. "
 +                    "Store idx %i to load addr %#x\n",
 +                    store_idx, req->getVaddr());
 +
 +            return NoFault;
 +        }
 +    }
 +
 +    // If there's no forwarding case, then go access memory
 +    DPRINTF(LSQUnit, "Doing functional access for inst [sn:%lli] PC %#x\n",
 +            load_inst->seqNum, load_inst->readPC());
 +
 +    assert(!load_inst->memData);
 +    load_inst->memData = new uint8_t[64];
 +
 +    ++usedPorts;
 +
 +    DPRINTF(LSQUnit, "Doing timing access for inst PC %#x\n",
 +            load_inst->readPC());
 +
 +    PacketPtr data_pkt = new Packet(req, Packet::ReadReq, Packet::Broadcast);
 +    data_pkt->dataStatic(load_inst->memData);
 +
 +    // if we have a cache, do cache access too
 +    if (!dcachePort->sendTiming(data_pkt)) {
 +        // There's an older load that's already going to squash.
 +        if (isLoadBlocked && blockedLoadSeqNum < load_inst->seqNum)
 +            return NoFault;
 +
 +        // Record that the load was blocked due to memory.  This
 +        // load will squash all instructions after it, be
 +        // refetched, and re-executed.
 +        isLoadBlocked = true;
 +        loadBlockedHandled = false;
 +        blockedLoadSeqNum = load_inst->seqNum;
 +        // No fault occurred, even though the interface is blocked.
 +        return NoFault;
 +    }
 +
 +    if (data_pkt->result != Packet::Success) {
 +        DPRINTF(LSQUnit, "LSQUnit: D-cache miss!\n");
 +        DPRINTF(Activity, "Activity: ld accessing mem miss [sn:%lli]\n",
 +                load_inst->seqNum);
 +    } else {
 +        DPRINTF(LSQUnit, "LSQUnit: D-cache hit!\n");
 +        DPRINTF(Activity, "Activity: ld accessing mem hit [sn:%lli]\n",
 +                load_inst->seqNum);
 +    }
 +
 +    return NoFault;
 +}
 +
 +template <class Impl>
 +template <class T>
 +Fault
 +LSQUnit<Impl>::write(Request *req, T &data, int store_idx)
 +{
 +    assert(storeQueue[store_idx].inst);
 +
 +    DPRINTF(LSQUnit, "Doing write to store idx %i, addr %#x data %#x"
 +            " | storeHead:%i [sn:%i]\n",
 +            store_idx, req->getPaddr(), data, storeHead,
 +            storeQueue[store_idx].inst->seqNum);
 +
 +    storeQueue[store_idx].req = req;
 +    storeQueue[store_idx].size = sizeof(T);
 +    storeQueue[store_idx].data = data;
 +
 +    // This function only writes the data to the store queue, so no fault
 +    // can happen here.
 +    return NoFault;
 +}
 +
 +#endif // __CPU_O3_LSQ_UNIT_HH__
index 3f6af3d2c7f003754338627073120c5623e127a5,0000000000000000000000000000000000000000..1ad561dc0723594f92ed28f24ebcdaddbf7e98bf
mode 100644,000000..100644
--- /dev/null
@@@ -1,866 -1,0 +1,869 @@@
-     if (lsqPtr->isSwitchedOut())
 +/*
 + * Copyright (c) 2004-2005 The Regents of The University of Michigan
 + * 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.
 + */
 +
 +#include "cpu/checker/cpu.hh"
 +#include "cpu/o3/lsq_unit.hh"
 +#include "base/str.hh"
 +#include "mem/request.hh"
 +
 +template<class Impl>
 +void
 +LSQUnit<Impl>::completeDataAccess(PacketPtr pkt)
 +{
 +/*
 +    DPRINTF(IEW, "Load writeback event [sn:%lli]\n", inst->seqNum);
 +    DPRINTF(Activity, "Activity: Ld Writeback event [sn:%lli]\n", inst->seqNum);
 +
 +    //iewStage->ldstQueue.removeMSHR(inst->threadNumber,inst->seqNum);
 +
 +    if (iewStage->isSwitchedOut()) {
 +        inst = NULL;
 +        return;
 +    } else if (inst->isSquashed()) {
 +        iewStage->wakeCPU();
 +        inst = NULL;
 +        return;
 +    }
 +
 +    iewStage->wakeCPU();
 +
 +    if (!inst->isExecuted()) {
 +        inst->setExecuted();
 +
 +        // Complete access to copy data to proper place.
 +        inst->completeAcc();
 +    }
 +
 +    // Need to insert instruction into queue to commit
 +    iewStage->instToCommit(inst);
 +
 +    iewStage->activityThisCycle();
 +
 +    inst = NULL;
 +*/
 +}
 +
 +template<class Impl>
 +void
 +LSQUnit<Impl>::completeStoreDataAccess(DynInstPtr &inst)
 +{
 +/*
 +    DPRINTF(LSQ, "Cache miss complete for store idx:%i\n", storeIdx);
 +    DPRINTF(Activity, "Activity: st writeback event idx:%i\n", storeIdx);
 +
 +    //lsqPtr->removeMSHR(lsqPtr->storeQueue[storeIdx].inst->seqNum);
 +
++    if (lsqPtr->isSwitchedOut()) {
++        if (wbEvent)
++            delete wbEvent;
++
 +        return;
++    }
 +
 +    lsqPtr->cpu->wakeCPU();
 +
 +    if (wb)
 +        lsqPtr->completeDataAccess(storeIdx);
 +    lsqPtr->completeStore(storeIdx);
 +*/
 +}
 +
 +template <class Impl>
 +Tick
 +LSQUnit<Impl>::DcachePort::recvAtomic(PacketPtr pkt)
 +{
 +    panic("O3CPU model does not work with atomic mode!");
 +    return curTick;
 +}
 +
 +template <class Impl>
 +void
 +LSQUnit<Impl>::DcachePort::recvFunctional(PacketPtr pkt)
 +{
 +    panic("O3CPU doesn't expect recvFunctional callback!");
 +}
 +
 +template <class Impl>
 +void
 +LSQUnit<Impl>::DcachePort::recvStatusChange(Status status)
 +{
 +    if (status == RangeChange)
 +        return;
 +
 +    panic("O3CPU doesn't expect recvStatusChange callback!");
 +}
 +
 +template <class Impl>
 +bool
 +LSQUnit<Impl>::DcachePort::recvTiming(PacketPtr pkt)
 +{
 +    lsq->completeDataAccess(pkt);
 +    return true;
 +}
 +
 +template <class Impl>
 +void
 +LSQUnit<Impl>::DcachePort::recvRetry()
 +{
 +    panic("Retry unsupported for now!");
 +    // we shouldn't get a retry unless we have a packet that we're
 +    // waiting to transmit
 +/*
 +    assert(cpu->dcache_pkt != NULL);
 +    assert(cpu->_status == DcacheRetry);
 +    PacketPtr tmp = cpu->dcache_pkt;
 +    if (sendTiming(tmp)) {
 +        cpu->_status = DcacheWaitResponse;
 +        cpu->dcache_pkt = NULL;
 +    }
 +*/
 +}
 +
 +template <class Impl>
 +LSQUnit<Impl>::LSQUnit()
 +    : loads(0), stores(0), storesToWB(0), stalled(false), isLoadBlocked(false),
 +      loadBlockedHandled(false)
 +{
 +}
 +
 +template<class Impl>
 +void
 +LSQUnit<Impl>::init(Params *params, unsigned maxLQEntries,
 +                    unsigned maxSQEntries, unsigned id)
 +{
 +    DPRINTF(LSQUnit, "Creating LSQUnit%i object.\n",id);
 +
 +    switchedOut = false;
 +
 +    lsqID = id;
 +
 +    // Add 1 for the sentinel entry (they are circular queues).
 +    LQEntries = maxLQEntries + 1;
 +    SQEntries = maxSQEntries + 1;
 +
 +    loadQueue.resize(LQEntries);
 +    storeQueue.resize(SQEntries);
 +
 +    loadHead = loadTail = 0;
 +
 +    storeHead = storeWBIdx = storeTail = 0;
 +
 +    usedPorts = 0;
 +    cachePorts = params->cachePorts;
 +
 +    Port *mem_dport = params->mem->getPort("");
 +    dcachePort->setPeer(mem_dport);
 +    mem_dport->setPeer(dcachePort);
 +
 +    memDepViolator = NULL;
 +
 +    blockedLoadSeqNum = 0;
 +}
 +
 +template<class Impl>
 +void
 +LSQUnit<Impl>::setCPU(FullCPU *cpu_ptr)
 +{
 +    cpu = cpu_ptr;
 +    dcachePort = new DcachePort(cpu, this);
 +}
 +
 +template<class Impl>
 +std::string
 +LSQUnit<Impl>::name() const
 +{
 +    if (Impl::MaxThreads == 1) {
 +        return iewStage->name() + ".lsq";
 +    } else {
 +        return iewStage->name() + ".lsq.thread." + to_string(lsqID);
 +    }
 +}
 +
 +template<class Impl>
 +void
 +LSQUnit<Impl>::clearLQ()
 +{
 +    loadQueue.clear();
 +}
 +
 +template<class Impl>
 +void
 +LSQUnit<Impl>::clearSQ()
 +{
 +    storeQueue.clear();
 +}
 +
 +#if 0
 +template<class Impl>
 +void
 +LSQUnit<Impl>::setPageTable(PageTable *pt_ptr)
 +{
 +    DPRINTF(LSQUnit, "Setting the page table pointer.\n");
 +    pTable = pt_ptr;
 +}
 +#endif
 +
 +template<class Impl>
 +void
 +LSQUnit<Impl>::switchOut()
 +{
 +    switchedOut = true;
 +    for (int i = 0; i < loadQueue.size(); ++i)
 +        loadQueue[i] = NULL;
 +
 +    assert(storesToWB == 0);
 +}
 +
 +template<class Impl>
 +void
 +LSQUnit<Impl>::takeOverFrom()
 +{
 +    switchedOut = false;
 +    loads = stores = storesToWB = 0;
 +
 +    loadHead = loadTail = 0;
 +
 +    storeHead = storeWBIdx = storeTail = 0;
 +
 +    usedPorts = 0;
 +
 +    memDepViolator = NULL;
 +
 +    blockedLoadSeqNum = 0;
 +
 +    stalled = false;
 +    isLoadBlocked = false;
 +    loadBlockedHandled = false;
 +}
 +
 +template<class Impl>
 +void
 +LSQUnit<Impl>::resizeLQ(unsigned size)
 +{
 +    unsigned size_plus_sentinel = size + 1;
 +    assert(size_plus_sentinel >= LQEntries);
 +
 +    if (size_plus_sentinel > LQEntries) {
 +        while (size_plus_sentinel > loadQueue.size()) {
 +            DynInstPtr dummy;
 +            loadQueue.push_back(dummy);
 +            LQEntries++;
 +        }
 +    } else {
 +        LQEntries = size_plus_sentinel;
 +    }
 +
 +}
 +
 +template<class Impl>
 +void
 +LSQUnit<Impl>::resizeSQ(unsigned size)
 +{
 +    unsigned size_plus_sentinel = size + 1;
 +    if (size_plus_sentinel > SQEntries) {
 +        while (size_plus_sentinel > storeQueue.size()) {
 +            SQEntry dummy;
 +            storeQueue.push_back(dummy);
 +            SQEntries++;
 +        }
 +    } else {
 +        SQEntries = size_plus_sentinel;
 +    }
 +}
 +
 +template <class Impl>
 +void
 +LSQUnit<Impl>::insert(DynInstPtr &inst)
 +{
 +    assert(inst->isMemRef());
 +
 +    assert(inst->isLoad() || inst->isStore());
 +
 +    if (inst->isLoad()) {
 +        insertLoad(inst);
 +    } else {
 +        insertStore(inst);
 +    }
 +
 +    inst->setInLSQ();
 +}
 +
 +template <class Impl>
 +void
 +LSQUnit<Impl>::insertLoad(DynInstPtr &load_inst)
 +{
 +    assert((loadTail + 1) % LQEntries != loadHead);
 +    assert(loads < LQEntries);
 +
 +    DPRINTF(LSQUnit, "Inserting load PC %#x, idx:%i [sn:%lli]\n",
 +            load_inst->readPC(), loadTail, load_inst->seqNum);
 +
 +    load_inst->lqIdx = loadTail;
 +
 +    if (stores == 0) {
 +        load_inst->sqIdx = -1;
 +    } else {
 +        load_inst->sqIdx = storeTail;
 +    }
 +
 +    loadQueue[loadTail] = load_inst;
 +
 +    incrLdIdx(loadTail);
 +
 +    ++loads;
 +}
 +
 +template <class Impl>
 +void
 +LSQUnit<Impl>::insertStore(DynInstPtr &store_inst)
 +{
 +    // Make sure it is not full before inserting an instruction.
 +    assert((storeTail + 1) % SQEntries != storeHead);
 +    assert(stores < SQEntries);
 +
 +    DPRINTF(LSQUnit, "Inserting store PC %#x, idx:%i [sn:%lli]\n",
 +            store_inst->readPC(), storeTail, store_inst->seqNum);
 +
 +    store_inst->sqIdx = storeTail;
 +    store_inst->lqIdx = loadTail;
 +
 +    storeQueue[storeTail] = SQEntry(store_inst);
 +
 +    incrStIdx(storeTail);
 +
 +    ++stores;
 +}
 +
 +template <class Impl>
 +typename Impl::DynInstPtr
 +LSQUnit<Impl>::getMemDepViolator()
 +{
 +    DynInstPtr temp = memDepViolator;
 +
 +    memDepViolator = NULL;
 +
 +    return temp;
 +}
 +
 +template <class Impl>
 +unsigned
 +LSQUnit<Impl>::numFreeEntries()
 +{
 +    unsigned free_lq_entries = LQEntries - loads;
 +    unsigned free_sq_entries = SQEntries - stores;
 +
 +    // Both the LQ and SQ entries have an extra dummy entry to differentiate
 +    // empty/full conditions.  Subtract 1 from the free entries.
 +    if (free_lq_entries < free_sq_entries) {
 +        return free_lq_entries - 1;
 +    } else {
 +        return free_sq_entries - 1;
 +    }
 +}
 +
 +template <class Impl>
 +int
 +LSQUnit<Impl>::numLoadsReady()
 +{
 +    int load_idx = loadHead;
 +    int retval = 0;
 +
 +    while (load_idx != loadTail) {
 +        assert(loadQueue[load_idx]);
 +
 +        if (loadQueue[load_idx]->readyToIssue()) {
 +            ++retval;
 +        }
 +    }
 +
 +    return retval;
 +}
 +
 +template <class Impl>
 +Fault
 +LSQUnit<Impl>::executeLoad(DynInstPtr &inst)
 +{
 +    // Execute a specific load.
 +    Fault load_fault = NoFault;
 +
 +    DPRINTF(LSQUnit, "Executing load PC %#x, [sn:%lli]\n",
 +            inst->readPC(),inst->seqNum);
 +
 +    load_fault = inst->initiateAcc();
 +
 +    // If the instruction faulted, then we need to send it along to commit
 +    // without the instruction completing.
 +    if (load_fault != NoFault) {
 +        // Send this instruction to commit, also make sure iew stage
 +        // realizes there is activity.
 +        iewStage->instToCommit(inst);
 +        iewStage->activityThisCycle();
 +    }
 +
 +    return load_fault;
 +}
 +
 +template <class Impl>
 +Fault
 +LSQUnit<Impl>::executeStore(DynInstPtr &store_inst)
 +{
 +    using namespace TheISA;
 +    // Make sure that a store exists.
 +    assert(stores != 0);
 +
 +    int store_idx = store_inst->sqIdx;
 +
 +    DPRINTF(LSQUnit, "Executing store PC %#x [sn:%lli]\n",
 +            store_inst->readPC(), store_inst->seqNum);
 +
 +    // Check the recently completed loads to see if any match this store's
 +    // address.  If so, then we have a memory ordering violation.
 +    int load_idx = store_inst->lqIdx;
 +
 +    Fault store_fault = store_inst->initiateAcc();
 +//    Fault store_fault = store_inst->execute();
 +
 +    if (storeQueue[store_idx].size == 0) {
 +        DPRINTF(LSQUnit,"Fault on Store PC %#x, [sn:%lli],Size = 0\n",
 +                store_inst->readPC(),store_inst->seqNum);
 +
 +        return store_fault;
 +    }
 +
 +    assert(store_fault == NoFault);
 +
 +    if (store_inst->isStoreConditional()) {
 +        // Store conditionals need to set themselves as able to
 +        // writeback if we haven't had a fault by here.
 +        storeQueue[store_idx].canWB = true;
 +
 +        ++storesToWB;
 +    }
 +
 +    if (!memDepViolator) {
 +        while (load_idx != loadTail) {
 +            // Really only need to check loads that have actually executed
 +            // It's safe to check all loads because effAddr is set to
 +            // InvalAddr when the dyn inst is created.
 +
 +            // @todo: For now this is extra conservative, detecting a
 +            // violation if the addresses match assuming all accesses
 +            // are quad word accesses.
 +
 +            // @todo: Fix this, magic number being used here
 +            if ((loadQueue[load_idx]->effAddr >> 8) ==
 +                (store_inst->effAddr >> 8)) {
 +                // A load incorrectly passed this store.  Squash and refetch.
 +                // For now return a fault to show that it was unsuccessful.
 +                memDepViolator = loadQueue[load_idx];
 +
 +                return genMachineCheckFault();
 +            }
 +
 +            incrLdIdx(load_idx);
 +        }
 +
 +        // If we've reached this point, there was no violation.
 +        memDepViolator = NULL;
 +    }
 +
 +    return store_fault;
 +}
 +
 +template <class Impl>
 +void
 +LSQUnit<Impl>::commitLoad()
 +{
 +    assert(loadQueue[loadHead]);
 +
 +    DPRINTF(LSQUnit, "Committing head load instruction, PC %#x\n",
 +            loadQueue[loadHead]->readPC());
 +
 +    loadQueue[loadHead] = NULL;
 +
 +    incrLdIdx(loadHead);
 +
 +    --loads;
 +}
 +
 +template <class Impl>
 +void
 +LSQUnit<Impl>::commitLoads(InstSeqNum &youngest_inst)
 +{
 +    assert(loads == 0 || loadQueue[loadHead]);
 +
 +    while (loads != 0 && loadQueue[loadHead]->seqNum <= youngest_inst) {
 +        commitLoad();
 +    }
 +}
 +
 +template <class Impl>
 +void
 +LSQUnit<Impl>::commitStores(InstSeqNum &youngest_inst)
 +{
 +    assert(stores == 0 || storeQueue[storeHead].inst);
 +
 +    int store_idx = storeHead;
 +
 +    while (store_idx != storeTail) {
 +        assert(storeQueue[store_idx].inst);
 +        // Mark any stores that are now committed and have not yet
 +        // been marked as able to write back.
 +        if (!storeQueue[store_idx].canWB) {
 +            if (storeQueue[store_idx].inst->seqNum > youngest_inst) {
 +                break;
 +            }
 +            DPRINTF(LSQUnit, "Marking store as able to write back, PC "
 +                    "%#x [sn:%lli]\n",
 +                    storeQueue[store_idx].inst->readPC(),
 +                    storeQueue[store_idx].inst->seqNum);
 +
 +            storeQueue[store_idx].canWB = true;
 +
 +            ++storesToWB;
 +        }
 +
 +        incrStIdx(store_idx);
 +    }
 +}
 +
 +template <class Impl>
 +void
 +LSQUnit<Impl>::writebackStores()
 +{
 +    while (storesToWB > 0 &&
 +           storeWBIdx != storeTail &&
 +           storeQueue[storeWBIdx].inst &&
 +           storeQueue[storeWBIdx].canWB &&
 +           usedPorts < cachePorts) {
 +
 +        // Store didn't write any data so no need to write it back to
 +        // memory.
 +        if (storeQueue[storeWBIdx].size == 0) {
 +            completeStore(storeWBIdx);
 +
 +            incrStIdx(storeWBIdx);
 +
 +            continue;
 +        }
 +/*
 +        if (dcacheInterface && dcacheInterface->isBlocked()) {
 +            DPRINTF(LSQUnit, "Unable to write back any more stores, cache"
 +                    " is blocked!\n");
 +            break;
 +        }
 +*/
 +        ++usedPorts;
 +
 +        if (storeQueue[storeWBIdx].inst->isDataPrefetch()) {
 +            incrStIdx(storeWBIdx);
 +
 +            continue;
 +        }
 +
 +        assert(storeQueue[storeWBIdx].req);
 +        assert(!storeQueue[storeWBIdx].committed);
 +
 +        DynInstPtr inst = storeQueue[storeWBIdx].inst;
 +
 +        Request *req = storeQueue[storeWBIdx].req;
 +        storeQueue[storeWBIdx].committed = true;
 +
 +        assert(!inst->memData);
 +        inst->memData = new uint8_t[64];
 +        memcpy(inst->memData, (uint8_t *)&storeQueue[storeWBIdx].data, req->getSize());
 +
 +        PacketPtr data_pkt = new Packet(req, Packet::WriteReq, Packet::Broadcast);
 +        data_pkt->dataStatic(inst->memData);
 +
 +        DPRINTF(LSQUnit, "D-Cache: Writing back store idx:%i PC:%#x "
 +                "to Addr:%#x, data:%#x [sn:%lli]\n",
 +                storeWBIdx, storeQueue[storeWBIdx].inst->readPC(),
 +                req->getPaddr(), *(inst->memData),
 +                storeQueue[storeWBIdx].inst->seqNum);
 +
 +        if (!dcachePort->sendTiming(data_pkt)) {
 +            // Need to handle becoming blocked on a store.
 +        } else {
 +            /*
 +            StoreCompletionEvent *store_event = new
 +                StoreCompletionEvent(storeWBIdx, NULL, this);
 +            */
 +            if (isStalled() &&
 +                storeQueue[storeWBIdx].inst->seqNum == stallingStoreIsn) {
 +                DPRINTF(LSQUnit, "Unstalling, stalling store [sn:%lli] "
 +                        "load idx:%i\n",
 +                        stallingStoreIsn, stallingLoadIdx);
 +                stalled = false;
 +                stallingStoreIsn = 0;
 +                iewStage->replayMemInst(loadQueue[stallingLoadIdx]);
 +            }
 +/*
 +            typename LdWritebackEvent *wb = NULL;
 +            if (req->flags & LOCKED) {
 +                // Stx_C should not generate a system port transaction
 +                // if it misses in the cache, but that might be hard
 +                // to accomplish without explicit cache support.
 +                wb = new typename
 +                    LdWritebackEvent(storeQueue[storeWBIdx].inst,
 +                                     iewStage);
 +                store_event->wbEvent = wb;
 +            }
 +*/
 +            if (data_pkt->result != Packet::Success) {
 +                DPRINTF(LSQUnit,"D-Cache Write Miss on idx:%i!\n",
 +                        storeWBIdx);
 +
 +                DPRINTF(Activity, "Active st accessing mem miss [sn:%lli]\n",
 +                        storeQueue[storeWBIdx].inst->seqNum);
 +
 +                //mshrSeqNums.push_back(storeQueue[storeWBIdx].inst->seqNum);
 +
 +                //DPRINTF(LSQUnit, "Added MSHR. count = %i\n",mshrSeqNums.size());
 +
 +                // @todo: Increment stat here.
 +            } else {
 +                DPRINTF(LSQUnit,"D-Cache: Write Hit on idx:%i !\n",
 +                        storeWBIdx);
 +
 +                DPRINTF(Activity, "Active st accessing mem hit [sn:%lli]\n",
 +                        storeQueue[storeWBIdx].inst->seqNum);
 +            }
 +
 +            incrStIdx(storeWBIdx);
 +        }
 +    }
 +
 +    // Not sure this should set it to 0.
 +    usedPorts = 0;
 +
 +    assert(stores >= 0 && storesToWB >= 0);
 +}
 +
 +/*template <class Impl>
 +void
 +LSQUnit<Impl>::removeMSHR(InstSeqNum seqNum)
 +{
 +    list<InstSeqNum>::iterator mshr_it = find(mshrSeqNums.begin(),
 +                                              mshrSeqNums.end(),
 +                                              seqNum);
 +
 +    if (mshr_it != mshrSeqNums.end()) {
 +        mshrSeqNums.erase(mshr_it);
 +        DPRINTF(LSQUnit, "Removing MSHR. count = %i\n",mshrSeqNums.size());
 +    }
 +}*/
 +
 +template <class Impl>
 +void
 +LSQUnit<Impl>::squash(const InstSeqNum &squashed_num)
 +{
 +    DPRINTF(LSQUnit, "Squashing until [sn:%lli]!"
 +            "(Loads:%i Stores:%i)\n", squashed_num, loads, stores);
 +
 +    int load_idx = loadTail;
 +    decrLdIdx(load_idx);
 +
 +    while (loads != 0 && loadQueue[load_idx]->seqNum > squashed_num) {
 +        DPRINTF(LSQUnit,"Load Instruction PC %#x squashed, "
 +                "[sn:%lli]\n",
 +                loadQueue[load_idx]->readPC(),
 +                loadQueue[load_idx]->seqNum);
 +
 +        if (isStalled() && load_idx == stallingLoadIdx) {
 +            stalled = false;
 +            stallingStoreIsn = 0;
 +            stallingLoadIdx = 0;
 +        }
 +
 +        // Clear the smart pointer to make sure it is decremented.
 +        loadQueue[load_idx]->squashed = true;
 +        loadQueue[load_idx] = NULL;
 +        --loads;
 +
 +        // Inefficient!
 +        loadTail = load_idx;
 +
 +        decrLdIdx(load_idx);
 +    }
 +
 +    if (isLoadBlocked) {
 +        if (squashed_num < blockedLoadSeqNum) {
 +            isLoadBlocked = false;
 +            loadBlockedHandled = false;
 +            blockedLoadSeqNum = 0;
 +        }
 +    }
 +
 +    int store_idx = storeTail;
 +    decrStIdx(store_idx);
 +
 +    while (stores != 0 &&
 +           storeQueue[store_idx].inst->seqNum > squashed_num) {
 +        // Instructions marked as can WB are already committed.
 +        if (storeQueue[store_idx].canWB) {
 +            break;
 +        }
 +
 +        DPRINTF(LSQUnit,"Store Instruction PC %#x squashed, "
 +                "idx:%i [sn:%lli]\n",
 +                storeQueue[store_idx].inst->readPC(),
 +                store_idx, storeQueue[store_idx].inst->seqNum);
 +
 +        // I don't think this can happen.  It should have been cleared
 +        // by the stalling load.
 +        if (isStalled() &&
 +            storeQueue[store_idx].inst->seqNum == stallingStoreIsn) {
 +            panic("Is stalled should have been cleared by stalling load!\n");
 +            stalled = false;
 +            stallingStoreIsn = 0;
 +        }
 +
 +        // Clear the smart pointer to make sure it is decremented.
 +        storeQueue[store_idx].inst->squashed = true;
 +        storeQueue[store_idx].inst = NULL;
 +        storeQueue[store_idx].canWB = 0;
 +
 +        storeQueue[store_idx].req = NULL;
 +        --stores;
 +
 +        // Inefficient!
 +        storeTail = store_idx;
 +
 +        decrStIdx(store_idx);
 +    }
 +}
 +
 +template <class Impl>
 +void
 +LSQUnit<Impl>::completeStore(int store_idx)
 +{
 +    assert(storeQueue[store_idx].inst);
 +    storeQueue[store_idx].completed = true;
 +    --storesToWB;
 +    // A bit conservative because a store completion may not free up entries,
 +    // but hopefully avoids two store completions in one cycle from making
 +    // the CPU tick twice.
 +    cpu->activityThisCycle();
 +
 +    if (store_idx == storeHead) {
 +        do {
 +            incrStIdx(storeHead);
 +
 +            --stores;
 +        } while (storeQueue[storeHead].completed &&
 +                 storeHead != storeTail);
 +
 +        iewStage->updateLSQNextCycle = true;
 +    }
 +
 +    DPRINTF(LSQUnit, "Completing store [sn:%lli], idx:%i, store head "
 +            "idx:%i\n",
 +            storeQueue[store_idx].inst->seqNum, store_idx, storeHead);
 +
 +    if (isStalled() &&
 +        storeQueue[store_idx].inst->seqNum == stallingStoreIsn) {
 +        DPRINTF(LSQUnit, "Unstalling, stalling store [sn:%lli] "
 +                "load idx:%i\n",
 +                stallingStoreIsn, stallingLoadIdx);
 +        stalled = false;
 +        stallingStoreIsn = 0;
 +        iewStage->replayMemInst(loadQueue[stallingLoadIdx]);
 +    }
 +
 +    storeQueue[store_idx].inst->setCompleted();
 +
 +    // Tell the checker we've completed this instruction.  Some stores
 +    // may get reported twice to the checker, but the checker can
 +    // handle that case.
 +    if (cpu->checker) {
 +        cpu->checker->tick(storeQueue[store_idx].inst);
 +    }
 +}
 +
 +template <class Impl>
 +inline void
 +LSQUnit<Impl>::incrStIdx(int &store_idx)
 +{
 +    if (++store_idx >= SQEntries)
 +        store_idx = 0;
 +}
 +
 +template <class Impl>
 +inline void
 +LSQUnit<Impl>::decrStIdx(int &store_idx)
 +{
 +    if (--store_idx < 0)
 +        store_idx += SQEntries;
 +}
 +
 +template <class Impl>
 +inline void
 +LSQUnit<Impl>::incrLdIdx(int &load_idx)
 +{
 +    if (++load_idx >= LQEntries)
 +        load_idx = 0;
 +}
 +
 +template <class Impl>
 +inline void
 +LSQUnit<Impl>::decrLdIdx(int &load_idx)
 +{
 +    if (--load_idx < 0)
 +        load_idx += LQEntries;
 +}
 +
 +template <class Impl>
 +void
 +LSQUnit<Impl>::dumpInsts()
 +{
 +    cprintf("Load store queue: Dumping instructions.\n");
 +    cprintf("Load queue size: %i\n", loads);
 +    cprintf("Load queue: ");
 +
 +    int load_idx = loadHead;
 +
 +    while (load_idx != loadTail && loadQueue[load_idx]) {
 +        cprintf("%#x ", loadQueue[load_idx]->readPC());
 +
 +        incrLdIdx(load_idx);
 +    }
 +
 +    cprintf("Store queue size: %i\n", stores);
 +    cprintf("Store queue: ");
 +
 +    int store_idx = storeHead;
 +
 +    while (store_idx != storeTail && storeQueue[store_idx].inst) {
 +        cprintf("%#x ", storeQueue[store_idx].inst->readPC());
 +
 +        incrStIdx(store_idx);
 +    }
 +
 +    cprintf("\n");
 +}
index 4d763fca213ec0fe7f157264f361c4ad6e082048,0000000000000000000000000000000000000000..e399f01332aa1ba3459bfcd324ab19f8df4db3bc
mode 100644,000000..100644
--- /dev/null
@@@ -1,253 -1,0 +1,264 @@@
 +/*
 + * Copyright (c) 2004-2006 The Regents of The University of Michigan
 + * 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: Kevin Lim
 + */
 +
 +#ifndef __CPU_O3_MEM_DEP_UNIT_HH__
 +#define __CPU_O3_MEM_DEP_UNIT_HH__
 +
 +#include <list>
 +#include <set>
 +
 +#include "base/hashmap.hh"
 +#include "base/refcnt.hh"
 +#include "base/statistics.hh"
 +#include "cpu/inst_seq.hh"
 +
 +struct SNHash {
 +    size_t operator() (const InstSeqNum &seq_num) const {
 +        unsigned a = (unsigned)seq_num;
 +        unsigned hash = (((a >> 14) ^ ((a >> 2) & 0xffff))) & 0x7FFFFFFF;
 +
 +        return hash;
 +    }
 +};
 +
 +template <class Impl>
 +class InstructionQueue;
 +
 +/**
 + * Memory dependency unit class.  This holds the memory dependence predictor.
 + * As memory operations are issued to the IQ, they are also issued to this
 + * unit, which then looks up the prediction as to what they are dependent
 + * upon.  This unit must be checked prior to a memory operation being able
 + * to issue.  Although this is templated, it's somewhat hard to make a generic
 + * memory dependence unit.  This one is mostly for store sets; it will be
 + * quite limited in what other memory dependence predictions it can also
 + * utilize.  Thus this class should be most likely be rewritten for other
 + * dependence prediction schemes.
 + */
 +template <class MemDepPred, class Impl>
 +class MemDepUnit {
 +  public:
 +    typedef typename Impl::Params Params;
 +    typedef typename Impl::DynInstPtr DynInstPtr;
 +
 +    /** Empty constructor. Must call init() prior to using in this case. */
 +    MemDepUnit() {}
 +
 +    /** Constructs a MemDepUnit with given parameters. */
 +    MemDepUnit(Params *params);
 +
 +    /** Frees up any memory allocated. */
 +    ~MemDepUnit();
 +
 +    /** Returns the name of the memory dependence unit. */
 +    std::string name() const;
 +
 +    /** Initializes the unit with parameters and a thread id. */
 +    void init(Params *params, int tid);
 +
 +    /** Registers statistics. */
 +    void regStats();
 +
++    /** Switches out the memory dependence predictor. */
 +    void switchOut();
 +
++    /** Takes over from another CPU's thread. */
 +    void takeOverFrom();
 +
 +    /** Sets the pointer to the IQ. */
 +    void setIQ(InstructionQueue<Impl> *iq_ptr);
 +
 +    /** Inserts a memory instruction. */
 +    void insert(DynInstPtr &inst);
 +
 +    /** Inserts a non-speculative memory instruction. */
 +    void insertNonSpec(DynInstPtr &inst);
 +
 +    /** Inserts a barrier instruction. */
 +    void insertBarrier(DynInstPtr &barr_inst);
 +
 +    /** Indicate that an instruction has its registers ready. */
 +    void regsReady(DynInstPtr &inst);
 +
 +    /** Indicate that a non-speculative instruction is ready. */
 +    void nonSpecInstReady(DynInstPtr &inst);
 +
 +    /** Reschedules an instruction to be re-executed. */
 +    void reschedule(DynInstPtr &inst);
 +
 +    /** Replays all instructions that have been rescheduled by moving them to
 +     *  the ready list.
 +     */
 +    void replay(DynInstPtr &inst);
 +
 +    /** Completes a memory instruction. */
 +    void completed(DynInstPtr &inst);
 +
 +    /** Completes a barrier instruction. */
 +    void completeBarrier(DynInstPtr &inst);
 +
 +    /** Wakes any dependents of a memory instruction. */
 +    void wakeDependents(DynInstPtr &inst);
 +
 +    /** Squashes all instructions up until a given sequence number for a
 +     *  specific thread.
 +     */
 +    void squash(const InstSeqNum &squashed_num, unsigned tid);
 +
 +    /** Indicates an ordering violation between a store and a younger load. */
 +    void violation(DynInstPtr &store_inst, DynInstPtr &violating_load);
 +
 +    /** Issues the given instruction */
 +    void issue(DynInstPtr &inst);
 +
 +    /** Debugging function to dump the lists of instructions. */
 +    void dumpLists();
 +
 +  private:
 +    typedef typename std::list<DynInstPtr>::iterator ListIt;
 +
 +    class MemDepEntry;
 +
 +    typedef RefCountingPtr<MemDepEntry> MemDepEntryPtr;
 +
 +    /** Memory dependence entries that track memory operations, marking
 +     *  when the instruction is ready to execute and what instructions depend
 +     *  upon it.
 +     */
 +    class MemDepEntry : public RefCounted {
 +      public:
 +        /** Constructs a memory dependence entry. */
 +        MemDepEntry(DynInstPtr &new_inst)
 +            : inst(new_inst), regsReady(false), memDepReady(false),
 +              completed(false), squashed(false)
 +        {
++#ifdef DEBUG
 +            ++memdep_count;
 +
 +            DPRINTF(MemDepUnit, "Memory dependency entry created.  "
 +                    "memdep_count=%i\n", memdep_count);
++#endif
 +        }
 +
 +        /** Frees any pointers. */
 +        ~MemDepEntry()
 +        {
 +            for (int i = 0; i < dependInsts.size(); ++i) {
 +                dependInsts[i] = NULL;
 +            }
++#ifdef DEBUG
 +            --memdep_count;
 +
 +            DPRINTF(MemDepUnit, "Memory dependency entry deleted.  "
 +                    "memdep_count=%i\n", memdep_count);
++#endif
 +        }
 +
 +        /** Returns the name of the memory dependence entry. */
 +        std::string name() const { return "memdepentry"; }
 +
 +        /** The instruction being tracked. */
 +        DynInstPtr inst;
 +
 +        /** The iterator to the instruction's location inside the list. */
 +        ListIt listIt;
 +
 +        /** A vector of any dependent instructions. */
 +        std::vector<MemDepEntryPtr> dependInsts;
 +
 +        /** If the registers are ready or not. */
 +        bool regsReady;
 +        /** If all memory dependencies have been satisfied. */
 +        bool memDepReady;
 +        /** If the instruction is completed. */
 +        bool completed;
 +        /** If the instruction is squashed. */
 +        bool squashed;
 +
 +        /** For debugging. */
++#ifdef DEBUG
 +        static int memdep_count;
 +        static int memdep_insert;
 +        static int memdep_erase;
++#endif
 +    };
 +
 +    /** Finds the memory dependence entry in the hash map. */
 +    inline MemDepEntryPtr &findInHash(const DynInstPtr &inst);
 +
 +    /** Moves an entry to the ready list. */
 +    inline void moveToReady(MemDepEntryPtr &ready_inst_entry);
 +
 +    typedef m5::hash_map<InstSeqNum, MemDepEntryPtr, SNHash> MemDepHash;
 +
 +    typedef typename MemDepHash::iterator MemDepHashIt;
 +
 +    /** A hash map of all memory dependence entries. */
 +    MemDepHash memDepHash;
 +
 +    /** A list of all instructions in the memory dependence unit. */
 +    std::list<DynInstPtr> instList[Impl::MaxThreads];
 +
 +    /** A list of all instructions that are going to be replayed. */
 +    std::list<DynInstPtr> instsToReplay;
 +
 +    /** The memory dependence predictor.  It is accessed upon new
 +     *  instructions being added to the IQ, and responds by telling
 +     *  this unit what instruction the newly added instruction is dependent
 +     *  upon.
 +     */
 +    MemDepPred depPred;
 +
++    /** Is there an outstanding load barrier that loads must wait on. */
 +    bool loadBarrier;
++    /** The sequence number of the load barrier. */
 +    InstSeqNum loadBarrierSN;
++    /** Is there an outstanding store barrier that loads must wait on. */
 +    bool storeBarrier;
++    /** The sequence number of the store barrier. */
 +    InstSeqNum storeBarrierSN;
 +
 +    /** Pointer to the IQ. */
 +    InstructionQueue<Impl> *iqPtr;
 +
 +    /** The thread id of this memory dependence unit. */
 +    int id;
 +
 +    /** Stat for number of inserted loads. */
 +    Stats::Scalar<> insertedLoads;
 +    /** Stat for number of inserted stores. */
 +    Stats::Scalar<> insertedStores;
 +    /** Stat for number of conflicting loads that had to wait for a store. */
 +    Stats::Scalar<> conflictingLoads;
 +    /** Stat for number of conflicting stores that had to wait for a store. */
 +    Stats::Scalar<> conflictingStores;
 +};
 +
 +#endif // __CPU_O3_MEM_DEP_UNIT_HH__
index a4fed4b0d9e798389e03af40291f7b604015f600,0000000000000000000000000000000000000000..50ad1e2c88369163f29e1a05314487bbf702b4b1
mode 100644,000000..100644
--- /dev/null
@@@ -1,553 -1,0 +1,557 @@@
-     // producing stores.
 +/*
 + * Copyright (c) 2004-2006 The Regents of The University of Michigan
 + * 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: Kevin Lim
 + */
 +
 +#include <map>
 +
 +#include "cpu/o3/inst_queue.hh"
 +#include "cpu/o3/mem_dep_unit.hh"
 +
 +template <class MemDepPred, class Impl>
 +MemDepUnit<MemDepPred, Impl>::MemDepUnit(Params *params)
 +    : depPred(params->SSITSize, params->LFSTSize), loadBarrier(false),
 +      loadBarrierSN(0), storeBarrier(false), storeBarrierSN(0), iqPtr(NULL)
 +{
 +    DPRINTF(MemDepUnit, "Creating MemDepUnit object.\n");
 +}
 +
 +template <class MemDepPred, class Impl>
 +MemDepUnit<MemDepPred, Impl>::~MemDepUnit()
 +{
 +    for (int tid=0; tid < Impl::MaxThreads; tid++) {
 +
 +        ListIt inst_list_it = instList[tid].begin();
 +
 +        MemDepHashIt hash_it;
 +
 +        while (!instList[tid].empty()) {
 +            hash_it = memDepHash.find((*inst_list_it)->seqNum);
 +
 +            assert(hash_it != memDepHash.end());
 +
 +            memDepHash.erase(hash_it);
 +
 +            instList[tid].erase(inst_list_it++);
 +        }
 +    }
 +
 +    assert(MemDepEntry::memdep_count == 0);
 +}
 +
 +template <class MemDepPred, class Impl>
 +std::string
 +MemDepUnit<MemDepPred, Impl>::name() const
 +{
 +    return "memdepunit";
 +}
 +
 +template <class MemDepPred, class Impl>
 +void
 +MemDepUnit<MemDepPred, Impl>::init(Params *params, int tid)
 +{
 +    DPRINTF(MemDepUnit, "Creating MemDepUnit %i object.\n",tid);
 +
 +    id = tid;
 +
 +    depPred.init(params->SSITSize, params->LFSTSize);
 +}
 +
 +template <class MemDepPred, class Impl>
 +void
 +MemDepUnit<MemDepPred, Impl>::regStats()
 +{
 +    insertedLoads
 +        .name(name() + ".memDep.insertedLoads")
 +        .desc("Number of loads inserted to the mem dependence unit.");
 +
 +    insertedStores
 +        .name(name() + ".memDep.insertedStores")
 +        .desc("Number of stores inserted to the mem dependence unit.");
 +
 +    conflictingLoads
 +        .name(name() + ".memDep.conflictingLoads")
 +        .desc("Number of conflicting loads.");
 +
 +    conflictingStores
 +        .name(name() + ".memDep.conflictingStores")
 +        .desc("Number of conflicting stores.");
 +}
 +
 +template <class MemDepPred, class Impl>
 +void
 +MemDepUnit<MemDepPred, Impl>::switchOut()
 +{
++    // Clear any state.
 +    for (int i = 0; i < Impl::MaxThreads; ++i) {
 +        instList[i].clear();
 +    }
 +    instsToReplay.clear();
 +    memDepHash.clear();
 +}
 +
 +template <class MemDepPred, class Impl>
 +void
 +MemDepUnit<MemDepPred, Impl>::takeOverFrom()
 +{
++    // Be sure to reset all state.
 +    loadBarrier = storeBarrier = false;
 +    loadBarrierSN = storeBarrierSN = 0;
 +    depPred.clear();
 +}
 +
 +template <class MemDepPred, class Impl>
 +void
 +MemDepUnit<MemDepPred, Impl>::setIQ(InstructionQueue<Impl> *iq_ptr)
 +{
 +    iqPtr = iq_ptr;
 +}
 +
 +template <class MemDepPred, class Impl>
 +void
 +MemDepUnit<MemDepPred, Impl>::insert(DynInstPtr &inst)
 +{
 +    unsigned tid = inst->threadNumber;
 +
 +    MemDepEntryPtr inst_entry = new MemDepEntry(inst);
 +
 +    // Add the MemDepEntry to the hash.
 +    memDepHash.insert(
 +        std::pair<InstSeqNum, MemDepEntryPtr>(inst->seqNum, inst_entry));
 +    MemDepEntry::memdep_insert++;
 +
 +    instList[tid].push_back(inst);
 +
 +    inst_entry->listIt = --(instList[tid].end());
 +
 +    // Check any barriers and the dependence predictor for any
++    // producing memrefs/stores.
 +    InstSeqNum producing_store;
 +    if (inst->isLoad() && loadBarrier) {
 +        producing_store = loadBarrierSN;
 +    } else if (inst->isStore() && storeBarrier) {
 +        producing_store = storeBarrierSN;
 +    } else {
 +        producing_store = depPred.checkInst(inst->readPC());
 +    }
 +
 +    MemDepEntryPtr store_entry = NULL;
 +
 +    // If there is a producing store, try to find the entry.
 +    if (producing_store != 0) {
 +        MemDepHashIt hash_it = memDepHash.find(producing_store);
 +
 +        if (hash_it != memDepHash.end()) {
 +            store_entry = (*hash_it).second;
 +        }
 +    }
 +
 +    // If no store entry, then instruction can issue as soon as the registers
 +    // are ready.
 +    if (!store_entry) {
 +        DPRINTF(MemDepUnit, "No dependency for inst PC "
 +                "%#x [sn:%lli].\n", inst->readPC(), inst->seqNum);
 +
 +        inst_entry->memDepReady = true;
 +
 +        if (inst->readyToIssue()) {
 +            inst_entry->regsReady = true;
 +
 +            moveToReady(inst_entry);
 +        }
 +    } else {
 +        // Otherwise make the instruction dependent on the store/barrier.
 +        DPRINTF(MemDepUnit, "Adding to dependency list; "
 +                "inst PC %#x is dependent on [sn:%lli].\n",
 +                inst->readPC(), producing_store);
 +
 +        if (inst->readyToIssue()) {
 +            inst_entry->regsReady = true;
 +        }
 +
 +        // Add this instruction to the list of dependents.
 +        store_entry->dependInsts.push_back(inst_entry);
 +
 +        if (inst->isLoad()) {
 +            ++conflictingLoads;
 +        } else {
 +            ++conflictingStores;
 +        }
 +    }
 +
 +    if (inst->isStore()) {
 +        DPRINTF(MemDepUnit, "Inserting store PC %#x [sn:%lli].\n",
 +                inst->readPC(), inst->seqNum);
 +
 +        depPred.insertStore(inst->readPC(), inst->seqNum, inst->threadNumber);
 +
 +        ++insertedStores;
 +    } else if (inst->isLoad()) {
 +        ++insertedLoads;
 +    } else {
 +        panic("Unknown type! (most likely a barrier).");
 +    }
 +}
 +
 +template <class MemDepPred, class Impl>
 +void
 +MemDepUnit<MemDepPred, Impl>::insertNonSpec(DynInstPtr &inst)
 +{
 +    unsigned tid = inst->threadNumber;
 +
 +    MemDepEntryPtr inst_entry = new MemDepEntry(inst);
 +
 +    // Insert the MemDepEntry into the hash.
 +    memDepHash.insert(
 +        std::pair<InstSeqNum, MemDepEntryPtr>(inst->seqNum, inst_entry));
 +    MemDepEntry::memdep_insert++;
 +
 +    // Add the instruction to the list.
 +    instList[tid].push_back(inst);
 +
 +    inst_entry->listIt = --(instList[tid].end());
 +
 +    // Might want to turn this part into an inline function or something.
 +    // It's shared between both insert functions.
 +    if (inst->isStore()) {
 +        DPRINTF(MemDepUnit, "Inserting store PC %#x [sn:%lli].\n",
 +                inst->readPC(), inst->seqNum);
 +
 +        depPred.insertStore(inst->readPC(), inst->seqNum, inst->threadNumber);
 +
 +        ++insertedStores;
 +    } else if (inst->isLoad()) {
 +        ++insertedLoads;
 +    } else {
 +        panic("Unknown type! (most likely a barrier).");
 +    }
 +}
 +
 +template <class MemDepPred, class Impl>
 +void
 +MemDepUnit<MemDepPred, Impl>::insertBarrier(DynInstPtr &barr_inst)
 +{
 +    InstSeqNum barr_sn = barr_inst->seqNum;
++    // Memory barriers block loads and stores, write barriers only stores.
 +    if (barr_inst->isMemBarrier()) {
 +        loadBarrier = true;
 +        loadBarrierSN = barr_sn;
 +        storeBarrier = true;
 +        storeBarrierSN = barr_sn;
 +        DPRINTF(MemDepUnit, "Inserted a memory barrier\n");
 +    } else if (barr_inst->isWriteBarrier()) {
 +        storeBarrier = true;
 +        storeBarrierSN = barr_sn;
 +        DPRINTF(MemDepUnit, "Inserted a write barrier\n");
 +    }
 +
 +    unsigned tid = barr_inst->threadNumber;
 +
 +    MemDepEntryPtr inst_entry = new MemDepEntry(barr_inst);
 +
 +    // Add the MemDepEntry to the hash.
 +    memDepHash.insert(
 +        std::pair<InstSeqNum, MemDepEntryPtr>(barr_sn, inst_entry));
 +    MemDepEntry::memdep_insert++;
 +
 +    // Add the instruction to the instruction list.
 +    instList[tid].push_back(barr_inst);
 +
 +    inst_entry->listIt = --(instList[tid].end());
 +}
 +
 +template <class MemDepPred, class Impl>
 +void
 +MemDepUnit<MemDepPred, Impl>::regsReady(DynInstPtr &inst)
 +{
 +    DPRINTF(MemDepUnit, "Marking registers as ready for "
 +            "instruction PC %#x [sn:%lli].\n",
 +            inst->readPC(), inst->seqNum);
 +
 +    MemDepEntryPtr inst_entry = findInHash(inst);
 +
 +    inst_entry->regsReady = true;
 +
 +    if (inst_entry->memDepReady) {
 +        DPRINTF(MemDepUnit, "Instruction has its memory "
 +                "dependencies resolved, adding it to the ready list.\n");
 +
 +        moveToReady(inst_entry);
 +    } else {
 +        DPRINTF(MemDepUnit, "Instruction still waiting on "
 +                "memory dependency.\n");
 +    }
 +}
 +
 +template <class MemDepPred, class Impl>
 +void
 +MemDepUnit<MemDepPred, Impl>::nonSpecInstReady(DynInstPtr &inst)
 +{
 +    DPRINTF(MemDepUnit, "Marking non speculative "
 +            "instruction PC %#x as ready [sn:%lli].\n",
 +            inst->readPC(), inst->seqNum);
 +
 +    MemDepEntryPtr inst_entry = findInHash(inst);
 +
 +    moveToReady(inst_entry);
 +}
 +
 +template <class MemDepPred, class Impl>
 +void
 +MemDepUnit<MemDepPred, Impl>::reschedule(DynInstPtr &inst)
 +{
 +    instsToReplay.push_back(inst);
 +}
 +
 +template <class MemDepPred, class Impl>
 +void
 +MemDepUnit<MemDepPred, Impl>::replay(DynInstPtr &inst)
 +{
 +    DynInstPtr temp_inst;
 +    bool found_inst = false;
 +
++    // For now this replay function replays all waiting memory ops.
 +    while (!instsToReplay.empty()) {
 +        temp_inst = instsToReplay.front();
 +
 +        MemDepEntryPtr inst_entry = findInHash(temp_inst);
 +
 +        DPRINTF(MemDepUnit, "Replaying mem instruction PC %#x "
 +                "[sn:%lli].\n",
 +                temp_inst->readPC(), temp_inst->seqNum);
 +
 +        moveToReady(inst_entry);
 +
 +        if (temp_inst == inst) {
 +            found_inst = true;
 +        }
 +
 +        instsToReplay.pop_front();
 +    }
 +
 +    assert(found_inst);
 +}
 +
 +template <class MemDepPred, class Impl>
 +void
 +MemDepUnit<MemDepPred, Impl>::completed(DynInstPtr &inst)
 +{
 +    DPRINTF(MemDepUnit, "Completed mem instruction PC %#x "
 +            "[sn:%lli].\n",
 +            inst->readPC(), inst->seqNum);
 +
 +    unsigned tid = inst->threadNumber;
 +
 +    // Remove the instruction from the hash and the list.
 +    MemDepHashIt hash_it = memDepHash.find(inst->seqNum);
 +
 +    assert(hash_it != memDepHash.end());
 +
 +    instList[tid].erase((*hash_it).second->listIt);
 +
 +    (*hash_it).second = NULL;
 +
 +    memDepHash.erase(hash_it);
 +    MemDepEntry::memdep_erase++;
 +}
 +
 +template <class MemDepPred, class Impl>
 +void
 +MemDepUnit<MemDepPred, Impl>::completeBarrier(DynInstPtr &inst)
 +{
 +    wakeDependents(inst);
 +    completed(inst);
 +
 +    InstSeqNum barr_sn = inst->seqNum;
 +
 +    if (inst->isMemBarrier()) {
 +        assert(loadBarrier && storeBarrier);
 +        if (loadBarrierSN == barr_sn)
 +            loadBarrier = false;
 +        if (storeBarrierSN == barr_sn)
 +            storeBarrier = false;
 +    } else if (inst->isWriteBarrier()) {
 +        assert(storeBarrier);
 +        if (storeBarrierSN == barr_sn)
 +            storeBarrier = false;
 +    }
 +}
 +
 +template <class MemDepPred, class Impl>
 +void
 +MemDepUnit<MemDepPred, Impl>::wakeDependents(DynInstPtr &inst)
 +{
 +    // Only stores and barriers have dependents.
 +    if (!inst->isStore() && !inst->isMemBarrier() && !inst->isWriteBarrier()) {
 +        return;
 +    }
 +
 +    MemDepEntryPtr inst_entry = findInHash(inst);
 +
 +    for (int i = 0; i < inst_entry->dependInsts.size(); ++i ) {
 +        MemDepEntryPtr woken_inst = inst_entry->dependInsts[i];
 +
 +        if (!woken_inst->inst) {
 +            // Potentially removed mem dep entries could be on this list
 +            continue;
 +        }
 +
 +        DPRINTF(MemDepUnit, "Waking up a dependent inst, "
 +                "[sn:%lli].\n",
 +                woken_inst->inst->seqNum);
 +
 +        if (woken_inst->regsReady && !woken_inst->squashed) {
 +            moveToReady(woken_inst);
 +        } else {
 +            woken_inst->memDepReady = true;
 +        }
 +    }
 +
 +    inst_entry->dependInsts.clear();
 +}
 +
 +template <class MemDepPred, class Impl>
 +void
 +MemDepUnit<MemDepPred, Impl>::squash(const InstSeqNum &squashed_num,
 +                                     unsigned tid)
 +{
 +    if (!instsToReplay.empty()) {
 +        ListIt replay_it = instsToReplay.begin();
 +        while (replay_it != instsToReplay.end()) {
 +            if ((*replay_it)->threadNumber == tid &&
 +                (*replay_it)->seqNum > squashed_num) {
 +                instsToReplay.erase(replay_it++);
 +            } else {
 +                ++replay_it;
 +            }
 +        }
 +    }
 +
 +    ListIt squash_it = instList[tid].end();
 +    --squash_it;
 +
 +    MemDepHashIt hash_it;
 +
 +    while (!instList[tid].empty() &&
 +           (*squash_it)->seqNum > squashed_num) {
 +
 +        DPRINTF(MemDepUnit, "Squashing inst [sn:%lli]\n",
 +                (*squash_it)->seqNum);
 +
 +        hash_it = memDepHash.find((*squash_it)->seqNum);
 +
 +        assert(hash_it != memDepHash.end());
 +
 +        (*hash_it).second->squashed = true;
 +
 +        (*hash_it).second = NULL;
 +
 +        memDepHash.erase(hash_it);
 +        MemDepEntry::memdep_erase++;
 +
 +        instList[tid].erase(squash_it--);
 +    }
 +
 +    // Tell the dependency predictor to squash as well.
 +    depPred.squash(squashed_num, tid);
 +}
 +
 +template <class MemDepPred, class Impl>
 +void
 +MemDepUnit<MemDepPred, Impl>::violation(DynInstPtr &store_inst,
 +                                        DynInstPtr &violating_load)
 +{
 +    DPRINTF(MemDepUnit, "Passing violating PCs to store sets,"
 +            " load: %#x, store: %#x\n", violating_load->readPC(),
 +            store_inst->readPC());
 +    // Tell the memory dependence unit of the violation.
 +    depPred.violation(violating_load->readPC(), store_inst->readPC());
 +}
 +
 +template <class MemDepPred, class Impl>
 +void
 +MemDepUnit<MemDepPred, Impl>::issue(DynInstPtr &inst)
 +{
 +    DPRINTF(MemDepUnit, "Issuing instruction PC %#x [sn:%lli].\n",
 +            inst->readPC(), inst->seqNum);
 +
 +    depPred.issued(inst->readPC(), inst->seqNum, inst->isStore());
 +}
 +
 +template <class MemDepPred, class Impl>
 +inline typename MemDepUnit<MemDepPred,Impl>::MemDepEntryPtr &
 +MemDepUnit<MemDepPred, Impl>::findInHash(const DynInstPtr &inst)
 +{
 +    MemDepHashIt hash_it = memDepHash.find(inst->seqNum);
 +
 +    assert(hash_it != memDepHash.end());
 +
 +    return (*hash_it).second;
 +}
 +
 +template <class MemDepPred, class Impl>
 +inline void
 +MemDepUnit<MemDepPred, Impl>::moveToReady(MemDepEntryPtr &woken_inst_entry)
 +{
 +    DPRINTF(MemDepUnit, "Adding instruction [sn:%lli] "
 +            "to the ready list.\n", woken_inst_entry->inst->seqNum);
 +
 +    assert(!woken_inst_entry->squashed);
 +
 +    iqPtr->addReadyMemInst(woken_inst_entry->inst);
 +}
 +
 +
 +template <class MemDepPred, class Impl>
 +void
 +MemDepUnit<MemDepPred, Impl>::dumpLists()
 +{
 +    for (unsigned tid=0; tid < Impl::MaxThreads; tid++) {
 +        cprintf("Instruction list %i size: %i\n",
 +                tid, instList[tid].size());
 +
 +        ListIt inst_list_it = instList[tid].begin();
 +        int num = 0;
 +
 +        while (inst_list_it != instList[tid].end()) {
 +            cprintf("Instruction:%i\nPC:%#x\n[sn:%i]\n[tid:%i]\nIssued:%i\n"
 +                    "Squashed:%i\n\n",
 +                    num, (*inst_list_it)->readPC(),
 +                    (*inst_list_it)->seqNum,
 +                    (*inst_list_it)->threadNumber,
 +                    (*inst_list_it)->isIssued(),
 +                    (*inst_list_it)->isSquashed());
 +            inst_list_it++;
 +            ++num;
 +        }
 +    }
 +
 +    cprintf("Memory dependence hash size: %i\n", memDepHash.size());
 +
 +    cprintf("Memory dependence entries: %i\n", MemDepEntry::memdep_count);
 +}
index 626d7cc758da67066e2383694efa8ea80afc8c7c,0000000000000000000000000000000000000000..42fdf6bf5d9c8d6e4520a2f50521d5e86c691425
mode 100644,000000..100644
--- /dev/null
@@@ -1,464 -1,0 +1,472 @@@
 +/*
 + * Copyright (c) 2004-2006 The Regents of The University of Michigan
 + * 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: Kevin Lim
 + */
 +
 +#ifndef __CPU_O3_RENAME_HH__
 +#define __CPU_O3_RENAME_HH__
 +
 +#include <list>
 +
 +#include "base/statistics.hh"
 +#include "base/timebuf.hh"
 +
 +/**
 + * DefaultRename handles both single threaded and SMT rename. Its
 + * width is specified by the parameters; each cycle it tries to rename
 + * that many instructions. It holds onto the rename history of all
 + * instructions with destination registers, storing the
 + * arch. register, the new physical register, and the old physical
 + * register, to allow for undoing of mappings if squashing happens, or
 + * freeing up registers upon commit. Rename handles blocking if the
 + * ROB, IQ, or LSQ is going to be full. Rename also handles barriers,
 + * and does so by stalling on the instruction until the ROB is empty
 + * and there are no instructions in flight to the ROB.
 + */
 +template<class Impl>
 +class DefaultRename
 +{
 +  public:
 +    // Typedefs from the Impl.
 +    typedef typename Impl::CPUPol CPUPol;
 +    typedef typename Impl::DynInstPtr DynInstPtr;
 +    typedef typename Impl::FullCPU FullCPU;
 +    typedef typename Impl::Params Params;
 +
 +    // Typedefs from the CPUPol
 +    typedef typename CPUPol::DecodeStruct DecodeStruct;
 +    typedef typename CPUPol::RenameStruct RenameStruct;
 +    typedef typename CPUPol::TimeStruct TimeStruct;
 +    typedef typename CPUPol::FreeList FreeList;
 +    typedef typename CPUPol::RenameMap RenameMap;
 +    // These are used only for initialization.
 +    typedef typename CPUPol::IEW IEW;
 +    typedef typename CPUPol::Commit Commit;
 +
 +    // Typedefs from the ISA.
 +    typedef TheISA::RegIndex RegIndex;
 +
 +    // A list is used to queue the instructions.  Barrier insts must
 +    // be added to the front of the list, which is the only reason for
 +    // using a list instead of a queue. (Most other stages use a
 +    // queue)
 +    typedef std::list<DynInstPtr> InstQueue;
 +
 +  public:
 +    /** Overall rename status. Used to determine if the CPU can
 +     * deschedule itself due to a lack of activity.
 +     */
 +    enum RenameStatus {
 +        Active,
 +        Inactive
 +    };
 +
 +    /** Individual thread status. */
 +    enum ThreadStatus {
 +        Running,
 +        Idle,
 +        StartSquash,
 +        Squashing,
 +        Blocked,
 +        Unblocking,
 +        SerializeStall
 +    };
 +
 +  private:
 +    /** Rename status. */
 +    RenameStatus _status;
 +
 +    /** Per-thread status. */
 +    ThreadStatus renameStatus[Impl::MaxThreads];
 +
 +  public:
 +    /** DefaultRename constructor. */
 +    DefaultRename(Params *params);
 +
 +    /** Returns the name of rename. */
 +    std::string name() const;
 +
 +    /** Registers statistics. */
 +    void regStats();
 +
 +    /** Sets CPU pointer. */
 +    void setCPU(FullCPU *cpu_ptr);
 +
 +    /** Sets the main backwards communication time buffer pointer. */
 +    void setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr);
 +
 +    /** Sets pointer to time buffer used to communicate to the next stage. */
 +    void setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr);
 +
 +    /** Sets pointer to time buffer coming from decode. */
 +    void setDecodeQueue(TimeBuffer<DecodeStruct> *dq_ptr);
 +
 +    /** Sets pointer to IEW stage. Used only for initialization. */
 +    void setIEWStage(IEW *iew_stage)
 +    { iew_ptr = iew_stage; }
 +
 +    /** Sets pointer to commit stage. Used only for initialization. */
 +    void setCommitStage(Commit *commit_stage)
 +    { commit_ptr = commit_stage; }
 +
 +  private:
 +    /** Pointer to IEW stage. Used only for initialization. */
 +    IEW *iew_ptr;
 +
 +    /** Pointer to commit stage. Used only for initialization. */
 +    Commit *commit_ptr;
 +
 +  public:
 +    /** Initializes variables for the stage. */
 +    void initStage();
 +
 +    /** Sets pointer to list of active threads. */
 +    void setActiveThreads(std::list<unsigned> *at_ptr);
 +
 +    /** Sets pointer to rename maps (per-thread structures). */
 +    void setRenameMap(RenameMap rm_ptr[Impl::MaxThreads]);
 +
 +    /** Sets pointer to the free list. */
 +    void setFreeList(FreeList *fl_ptr);
 +
 +    /** Sets pointer to the scoreboard. */
 +    void setScoreboard(Scoreboard *_scoreboard);
 +
++    /** Switches out the rename stage. */
 +    void switchOut();
 +
++    /** Completes the switch out. */
 +    void doSwitchOut();
 +
++    /** Takes over from another CPU's thread. */
 +    void takeOverFrom();
 +
 +    /** Squashes all instructions in a thread. */
 +    void squash(unsigned tid);
 +
 +    /** Ticks rename, which processes all input signals and attempts to rename
 +     * as many instructions as possible.
 +     */
 +    void tick();
 +
 +    /** Debugging function used to dump history buffer of renamings. */
 +    void dumpHistory();
 +
 +  private:
 +    /** Determines what to do based on rename's current status.
 +     * @param status_change rename() sets this variable if there was a status
 +     * change (ie switching from blocking to unblocking).
 +     * @param tid Thread id to rename instructions from.
 +     */
 +    void rename(bool &status_change, unsigned tid);
 +
 +    /** Renames instructions for the given thread. Also handles serializing
 +     * instructions.
 +     */
 +    void renameInsts(unsigned tid);
 +
 +    /** Inserts unused instructions from a given thread into the skid buffer,
 +     * to be renamed once rename unblocks.
 +     */
 +    void skidInsert(unsigned tid);
 +
 +    /** Separates instructions from decode into individual lists of instructions
 +     * sorted by thread.
 +     */
 +    void sortInsts();
 +
 +    /** Returns if all of the skid buffers are empty. */
 +    bool skidsEmpty();
 +
 +    /** Updates overall rename status based on all of the threads' statuses. */
 +    void updateStatus();
 +
 +    /** Switches rename to blocking, and signals back that rename has become
 +     * blocked.
 +     * @return Returns true if there is a status change.
 +     */
 +    bool block(unsigned tid);
 +
 +    /** Switches rename to unblocking if the skid buffer is empty, and signals
 +     * back that rename has unblocked.
 +     * @return Returns true if there is a status change.
 +     */
 +    bool unblock(unsigned tid);
 +
 +    /** Executes actual squash, removing squashed instructions. */
 +    void doSquash(unsigned tid);
 +
 +    /** Removes a committed instruction's rename history. */
 +    void removeFromHistory(InstSeqNum inst_seq_num, unsigned tid);
 +
 +    /** Renames the source registers of an instruction. */
 +    inline void renameSrcRegs(DynInstPtr &inst, unsigned tid);
 +
 +    /** Renames the destination registers of an instruction. */
 +    inline void renameDestRegs(DynInstPtr &inst, unsigned tid);
 +
 +    /** Calculates the number of free ROB entries for a specific thread. */
 +    inline int calcFreeROBEntries(unsigned tid);
 +
 +    /** Calculates the number of free IQ entries for a specific thread. */
 +    inline int calcFreeIQEntries(unsigned tid);
 +
 +    /** Calculates the number of free LSQ entries for a specific thread. */
 +    inline int calcFreeLSQEntries(unsigned tid);
 +
 +    /** Returns the number of valid instructions coming from decode. */
 +    unsigned validInsts();
 +
 +    /** Reads signals telling rename to block/unblock. */
 +    void readStallSignals(unsigned tid);
 +
 +    /** Checks if any stages are telling rename to block. */
 +    bool checkStall(unsigned tid);
 +
++    /** Gets the number of free entries for a specific thread. */
 +    void readFreeEntries(unsigned tid);
 +
++    /** Checks the signals and updates the status. */
 +    bool checkSignalsAndUpdate(unsigned tid);
 +
 +    /** Either serializes on the next instruction available in the InstQueue,
 +     * or records that it must serialize on the next instruction to enter
 +     * rename.
 +     * @param inst_list The list of younger, unprocessed instructions for the
 +     * thread that has the serializeAfter instruction.
 +     * @param tid The thread id.
 +     */
 +    void serializeAfter(InstQueue &inst_list, unsigned tid);
 +
 +    /** Holds the information for each destination register rename. It holds
 +     * the instruction's sequence number, the arch register, the old physical
 +     * register for that arch. register, and the new physical register.
 +     */
 +    struct RenameHistory {
 +        RenameHistory(InstSeqNum _instSeqNum, RegIndex _archReg,
 +                      PhysRegIndex _newPhysReg, PhysRegIndex _prevPhysReg)
 +            : instSeqNum(_instSeqNum), archReg(_archReg),
 +              newPhysReg(_newPhysReg), prevPhysReg(_prevPhysReg)
 +        {
 +        }
 +
 +        /** The sequence number of the instruction that renamed. */
 +        InstSeqNum instSeqNum;
 +        /** The architectural register index that was renamed. */
 +        RegIndex archReg;
 +        /** The new physical register that the arch. register is renamed to. */
 +        PhysRegIndex newPhysReg;
 +        /** The old physical register that the arch. register was renamed to. */
 +        PhysRegIndex prevPhysReg;
 +    };
 +
 +    /** A per-thread list of all destination register renames, used to either
 +     * undo rename mappings or free old physical registers.
 +     */
 +    std::list<RenameHistory> historyBuffer[Impl::MaxThreads];
 +
 +    /** Pointer to CPU. */
 +    FullCPU *cpu;
 +
 +    /** Pointer to main time buffer used for backwards communication. */
 +    TimeBuffer<TimeStruct> *timeBuffer;
 +
 +    /** Wire to get IEW's output from backwards time buffer. */
 +    typename TimeBuffer<TimeStruct>::wire fromIEW;
 +
 +    /** Wire to get commit's output from backwards time buffer. */
 +    typename TimeBuffer<TimeStruct>::wire fromCommit;
 +
 +    /** Wire to write infromation heading to previous stages. */
 +    typename TimeBuffer<TimeStruct>::wire toDecode;
 +
 +    /** Rename instruction queue. */
 +    TimeBuffer<RenameStruct> *renameQueue;
 +
 +    /** Wire to write any information heading to IEW. */
 +    typename TimeBuffer<RenameStruct>::wire toIEW;
 +
 +    /** Decode instruction queue interface. */
 +    TimeBuffer<DecodeStruct> *decodeQueue;
 +
 +    /** Wire to get decode's output from decode queue. */
 +    typename TimeBuffer<DecodeStruct>::wire fromDecode;
 +
 +    /** Queue of all instructions coming from decode this cycle. */
 +    InstQueue insts[Impl::MaxThreads];
 +
 +    /** Skid buffer between rename and decode. */
 +    InstQueue skidBuffer[Impl::MaxThreads];
 +
 +    /** Rename map interface. */
 +    RenameMap *renameMap[Impl::MaxThreads];
 +
 +    /** Free list interface. */
 +    FreeList *freeList;
 +
 +    /** Pointer to the list of active threads. */
 +    std::list<unsigned> *activeThreads;
 +
 +    /** Pointer to the scoreboard. */
 +    Scoreboard *scoreboard;
 +
 +    /** Count of instructions in progress that have been sent off to the IQ
 +     * and ROB, but are not yet included in their occupancy counts.
 +     */
 +    int instsInProgress[Impl::MaxThreads];
 +
 +    /** Variable that tracks if decode has written to the time buffer this
 +     * cycle. Used to tell CPU if there is activity this cycle.
 +     */
 +    bool wroteToTimeBuffer;
 +
 +    /** Structures whose free entries impact the amount of instructions that
 +     * can be renamed.
 +     */
 +    struct FreeEntries {
 +        unsigned iqEntries;
 +        unsigned lsqEntries;
 +        unsigned robEntries;
 +    };
 +
 +    /** Per-thread tracking of the number of free entries of back-end
 +     * structures.
 +     */
 +    FreeEntries freeEntries[Impl::MaxThreads];
 +
 +    /** Records if the ROB is empty. In SMT mode the ROB may be dynamically
 +     * partitioned between threads, so the ROB must tell rename when it is
 +     * empty.
 +     */
 +    bool emptyROB[Impl::MaxThreads];
 +
 +    /** Source of possible stalls. */
 +    struct Stalls {
 +        bool iew;
 +        bool commit;
 +    };
 +
 +    /** Tracks which stages are telling decode to stall. */
 +    Stalls stalls[Impl::MaxThreads];
 +
 +    /** The serialize instruction that rename has stalled on. */
 +    DynInstPtr serializeInst[Impl::MaxThreads];
 +
 +    /** Records if rename needs to serialize on the next instruction for any
 +     * thread.
 +     */
 +    bool serializeOnNextInst[Impl::MaxThreads];
 +
 +    /** Delay between iew and rename, in ticks. */
 +    int iewToRenameDelay;
 +
 +    /** Delay between decode and rename, in ticks. */
 +    int decodeToRenameDelay;
 +
 +    /** Delay between commit and rename, in ticks. */
 +    unsigned commitToRenameDelay;
 +
 +    /** Rename width, in instructions. */
 +    unsigned renameWidth;
 +
 +    /** Commit width, in instructions.  Used so rename knows how many
 +     *  instructions might have freed registers in the previous cycle.
 +     */
 +    unsigned commitWidth;
 +
 +    /** The index of the instruction in the time buffer to IEW that rename is
 +     * currently using.
 +     */
 +    unsigned toIEWIndex;
 +
 +    /** Whether or not rename needs to block this cycle. */
 +    bool blockThisCycle;
 +
 +    /** The number of threads active in rename. */
 +    unsigned numThreads;
 +
 +    /** The maximum skid buffer size. */
 +    unsigned skidBufferMax;
 +
 +    /** Enum to record the source of a structure full stall.  Can come from
 +     * either ROB, IQ, LSQ, and it is priortized in that order.
 +     */
 +    enum FullSource {
 +        ROB,
 +        IQ,
 +        LSQ,
 +        NONE
 +    };
 +
 +    /** Function used to increment the stat that corresponds to the source of
 +     * the stall.
 +     */
 +    inline void incrFullStat(const FullSource &source);
 +
 +    /** Stat for total number of cycles spent squashing. */
 +    Stats::Scalar<> renameSquashCycles;
 +    /** Stat for total number of cycles spent idle. */
 +    Stats::Scalar<> renameIdleCycles;
 +    /** Stat for total number of cycles spent blocking. */
 +    Stats::Scalar<> renameBlockCycles;
 +    /** Stat for total number of cycles spent stalling for a serializing inst. */
 +    Stats::Scalar<> renameSerializeStallCycles;
 +    /** Stat for total number of cycles spent running normally. */
 +    Stats::Scalar<> renameRunCycles;
 +    /** Stat for total number of cycles spent unblocking. */
 +    Stats::Scalar<> renameUnblockCycles;
 +    /** Stat for total number of renamed instructions. */
 +    Stats::Scalar<> renameRenamedInsts;
 +    /** Stat for total number of squashed instructions that rename discards. */
 +    Stats::Scalar<> renameSquashedInsts;
 +    /** Stat for total number of times that the ROB starts a stall in rename. */
 +    Stats::Scalar<> renameROBFullEvents;
 +    /** Stat for total number of times that the IQ starts a stall in rename. */
 +    Stats::Scalar<> renameIQFullEvents;
 +    /** Stat for total number of times that the LSQ starts a stall in rename. */
 +    Stats::Scalar<> renameLSQFullEvents;
 +    /** Stat for total number of times that rename runs out of free registers
 +     * to use to rename. */
 +    Stats::Scalar<> renameFullRegistersEvents;
 +    /** Stat for total number of renamed destination registers. */
 +    Stats::Scalar<> renameRenamedOperands;
 +    /** Stat for total number of source register rename lookups. */
 +    Stats::Scalar<> renameRenameLookups;
 +    /** Stat for total number of committed renaming mappings. */
 +    Stats::Scalar<> renameCommittedMaps;
 +    /** Stat for total number of mappings that were undone due to a squash. */
 +    Stats::Scalar<> renameUndoneMaps;
++    /** Number of serialize instructions handled. */
 +    Stats::Scalar<> renamedSerializing;
++    /** Number of instructions marked as temporarily serializing. */
 +    Stats::Scalar<> renamedTempSerializing;
++    /** Number of instructions inserted into skid buffers. */
 +    Stats::Scalar<> renameSkidInsts;
 +};
 +
 +#endif // __CPU_O3_RENAME_HH__
index 9cbe1a770c9e59a479931ccc93843eef24c1c678,0000000000000000000000000000000000000000..8e70c90f7dd25e7a966d64e2b054d0085852d009
mode 100644,000000..100644
--- /dev/null
@@@ -1,1281 -1,0 +1,1283 @@@
 +/*
 + * Copyright (c) 2004-2006 The Regents of The University of Michigan
 + * 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: Kevin Lim
 + */
 +
 +#include <list>
 +
 +#include "config/full_system.hh"
 +#include "cpu/o3/rename.hh"
 +
 +using namespace std;
 +
 +template <class Impl>
 +DefaultRename<Impl>::DefaultRename(Params *params)
 +    : iewToRenameDelay(params->iewToRenameDelay),
 +      decodeToRenameDelay(params->decodeToRenameDelay),
 +      commitToRenameDelay(params->commitToRenameDelay),
 +      renameWidth(params->renameWidth),
 +      commitWidth(params->commitWidth),
 +      numThreads(params->numberOfThreads)
 +{
 +    _status = Inactive;
 +
 +    for (int i=0; i< numThreads; i++) {
 +        renameStatus[i] = Idle;
 +
 +        freeEntries[i].iqEntries = 0;
 +        freeEntries[i].lsqEntries = 0;
 +        freeEntries[i].robEntries = 0;
 +
 +        stalls[i].iew = false;
 +        stalls[i].commit = false;
 +        serializeInst[i] = NULL;
 +
 +        instsInProgress[i] = 0;
 +
 +        emptyROB[i] = true;
 +
 +        serializeOnNextInst[i] = false;
 +    }
 +
 +    // @todo: Make into a parameter.
 +    skidBufferMax = (2 * (iewToRenameDelay * params->decodeWidth)) + renameWidth;
 +}
 +
 +template <class Impl>
 +std::string
 +DefaultRename<Impl>::name() const
 +{
 +    return cpu->name() + ".rename";
 +}
 +
 +template <class Impl>
 +void
 +DefaultRename<Impl>::regStats()
 +{
 +    renameSquashCycles
 +        .name(name() + ".RENAME:SquashCycles")
 +        .desc("Number of cycles rename is squashing")
 +        .prereq(renameSquashCycles);
 +    renameIdleCycles
 +        .name(name() + ".RENAME:IdleCycles")
 +        .desc("Number of cycles rename is idle")
 +        .prereq(renameIdleCycles);
 +    renameBlockCycles
 +        .name(name() + ".RENAME:BlockCycles")
 +        .desc("Number of cycles rename is blocking")
 +        .prereq(renameBlockCycles);
 +    renameSerializeStallCycles
 +        .name(name() + ".RENAME:serializeStallCycles")
 +        .desc("count of cycles rename stalled for serializing inst")
 +        .flags(Stats::total);
 +    renameRunCycles
 +        .name(name() + ".RENAME:RunCycles")
 +        .desc("Number of cycles rename is running")
 +        .prereq(renameIdleCycles);
 +    renameUnblockCycles
 +        .name(name() + ".RENAME:UnblockCycles")
 +        .desc("Number of cycles rename is unblocking")
 +        .prereq(renameUnblockCycles);
 +    renameRenamedInsts
 +        .name(name() + ".RENAME:RenamedInsts")
 +        .desc("Number of instructions processed by rename")
 +        .prereq(renameRenamedInsts);
 +    renameSquashedInsts
 +        .name(name() + ".RENAME:SquashedInsts")
 +        .desc("Number of squashed instructions processed by rename")
 +        .prereq(renameSquashedInsts);
 +    renameROBFullEvents
 +        .name(name() + ".RENAME:ROBFullEvents")
 +        .desc("Number of times rename has blocked due to ROB full")
 +        .prereq(renameROBFullEvents);
 +    renameIQFullEvents
 +        .name(name() + ".RENAME:IQFullEvents")
 +        .desc("Number of times rename has blocked due to IQ full")
 +        .prereq(renameIQFullEvents);
 +    renameLSQFullEvents
 +        .name(name() + ".RENAME:LSQFullEvents")
 +        .desc("Number of times rename has blocked due to LSQ full")
 +        .prereq(renameLSQFullEvents);
 +    renameFullRegistersEvents
 +        .name(name() + ".RENAME:FullRegisterEvents")
 +        .desc("Number of times there has been no free registers")
 +        .prereq(renameFullRegistersEvents);
 +    renameRenamedOperands
 +        .name(name() + ".RENAME:RenamedOperands")
 +        .desc("Number of destination operands rename has renamed")
 +        .prereq(renameRenamedOperands);
 +    renameRenameLookups
 +        .name(name() + ".RENAME:RenameLookups")
 +        .desc("Number of register rename lookups that rename has made")
 +        .prereq(renameRenameLookups);
 +    renameCommittedMaps
 +        .name(name() + ".RENAME:CommittedMaps")
 +        .desc("Number of HB maps that are committed")
 +        .prereq(renameCommittedMaps);
 +    renameUndoneMaps
 +        .name(name() + ".RENAME:UndoneMaps")
 +        .desc("Number of HB maps that are undone due to squashing")
 +        .prereq(renameUndoneMaps);
 +    renamedSerializing
 +        .name(name() + ".RENAME:serializingInsts")
 +        .desc("count of serializing insts renamed")
 +        .flags(Stats::total)
 +        ;
 +    renamedTempSerializing
 +        .name(name() + ".RENAME:tempSerializingInsts")
 +        .desc("count of temporary serializing insts renamed")
 +        .flags(Stats::total)
 +        ;
 +    renameSkidInsts
 +        .name(name() + ".RENAME:skidInsts")
 +        .desc("count of insts added to the skid buffer")
 +        .flags(Stats::total)
 +        ;
 +}
 +
 +template <class Impl>
 +void
 +DefaultRename<Impl>::setCPU(FullCPU *cpu_ptr)
 +{
 +    DPRINTF(Rename, "Setting CPU pointer.\n");
 +    cpu = cpu_ptr;
 +}
 +
 +template <class Impl>
 +void
 +DefaultRename<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr)
 +{
 +    DPRINTF(Rename, "Setting time buffer pointer.\n");
 +    timeBuffer = tb_ptr;
 +
 +    // Setup wire to read information from time buffer, from IEW stage.
 +    fromIEW = timeBuffer->getWire(-iewToRenameDelay);
 +
 +    // Setup wire to read infromation from time buffer, from commit stage.
 +    fromCommit = timeBuffer->getWire(-commitToRenameDelay);
 +
 +    // Setup wire to write information to previous stages.
 +    toDecode = timeBuffer->getWire(0);
 +}
 +
 +template <class Impl>
 +void
 +DefaultRename<Impl>::setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr)
 +{
 +    DPRINTF(Rename, "Setting rename queue pointer.\n");
 +    renameQueue = rq_ptr;
 +
 +    // Setup wire to write information to future stages.
 +    toIEW = renameQueue->getWire(0);
 +}
 +
 +template <class Impl>
 +void
 +DefaultRename<Impl>::setDecodeQueue(TimeBuffer<DecodeStruct> *dq_ptr)
 +{
 +    DPRINTF(Rename, "Setting decode queue pointer.\n");
 +    decodeQueue = dq_ptr;
 +
 +    // Setup wire to get information from decode.
 +    fromDecode = decodeQueue->getWire(-decodeToRenameDelay);
 +}
 +
 +template <class Impl>
 +void
 +DefaultRename<Impl>::initStage()
 +{
 +    // Grab the number of free entries directly from the stages.
 +    for (int tid=0; tid < numThreads; tid++) {
 +        freeEntries[tid].iqEntries = iew_ptr->instQueue.numFreeEntries(tid);
 +        freeEntries[tid].lsqEntries = iew_ptr->ldstQueue.numFreeEntries(tid);
 +        freeEntries[tid].robEntries = commit_ptr->numROBFreeEntries(tid);
 +        emptyROB[tid] = true;
 +    }
 +}
 +
 +template<class Impl>
 +void
 +DefaultRename<Impl>::setActiveThreads(list<unsigned> *at_ptr)
 +{
 +    DPRINTF(Rename, "Setting active threads list pointer.\n");
 +    activeThreads = at_ptr;
 +}
 +
 +
 +template <class Impl>
 +void
 +DefaultRename<Impl>::setRenameMap(RenameMap rm_ptr[])
 +{
 +    DPRINTF(Rename, "Setting rename map pointers.\n");
 +
 +    for (int i=0; i<numThreads; i++) {
 +        renameMap[i] = &rm_ptr[i];
 +    }
 +}
 +
 +template <class Impl>
 +void
 +DefaultRename<Impl>::setFreeList(FreeList *fl_ptr)
 +{
 +    DPRINTF(Rename, "Setting free list pointer.\n");
 +    freeList = fl_ptr;
 +}
 +
 +template<class Impl>
 +void
 +DefaultRename<Impl>::setScoreboard(Scoreboard *_scoreboard)
 +{
 +    DPRINTF(Rename, "Setting scoreboard pointer.\n");
 +    scoreboard = _scoreboard;
 +}
 +
 +template <class Impl>
 +void
 +DefaultRename<Impl>::switchOut()
 +{
++    // Rename is ready to switch out at any time.
 +    cpu->signalSwitched();
 +}
 +
 +template <class Impl>
 +void
 +DefaultRename<Impl>::doSwitchOut()
 +{
++    // Clear any state, fix up the rename map.
 +    for (int i = 0; i < numThreads; i++) {
 +        typename list<RenameHistory>::iterator hb_it = historyBuffer[i].begin();
 +
 +        while (!historyBuffer[i].empty()) {
 +            assert(hb_it != historyBuffer[i].end());
 +
 +            DPRINTF(Rename, "[tid:%u]: Removing history entry with sequence "
 +                    "number %i.\n", i, (*hb_it).instSeqNum);
 +
 +            // Tell the rename map to set the architected register to the
 +            // previous physical register that it was renamed to.
 +            renameMap[i]->setEntry(hb_it->archReg, hb_it->prevPhysReg);
 +
 +            // Put the renamed physical register back on the free list.
 +            freeList->addReg(hb_it->newPhysReg);
 +
 +            historyBuffer[i].erase(hb_it++);
 +        }
 +        insts[i].clear();
 +        skidBuffer[i].clear();
 +    }
 +}
 +
 +template <class Impl>
 +void
 +DefaultRename<Impl>::takeOverFrom()
 +{
 +    _status = Inactive;
 +    initStage();
 +
 +    // Reset all state prior to taking over from the other CPU.
 +    for (int i=0; i< numThreads; i++) {
 +        renameStatus[i] = Idle;
 +
 +        stalls[i].iew = false;
 +        stalls[i].commit = false;
 +        serializeInst[i] = NULL;
 +
 +        instsInProgress[i] = 0;
 +
 +        emptyROB[i] = true;
 +
 +        serializeOnNextInst[i] = false;
 +    }
 +}
 +
 +template <class Impl>
 +void
 +DefaultRename<Impl>::squash(unsigned tid)
 +{
 +    DPRINTF(Rename, "[tid:%u]: Squashing instructions.\n",tid);
 +
 +    // Clear the stall signal if rename was blocked or unblocking before.
 +    // If it still needs to block, the blocking should happen the next
 +    // cycle and there should be space to hold everything due to the squash.
 +    if (renameStatus[tid] == Blocked ||
 +        renameStatus[tid] == Unblocking ||
 +        renameStatus[tid] == SerializeStall) {
 +#if 0
 +        // In syscall emulation, we can have both a block and a squash due
 +        // to a syscall in the same cycle.  This would cause both signals to
 +        // be high.  This shouldn't happen in full system.
 +        if (toDecode->renameBlock[tid]) {
 +            toDecode->renameBlock[tid] = 0;
 +        } else {
 +            toDecode->renameUnblock[tid] = 1;
 +        }
 +#else
 +        toDecode->renameUnblock[tid] = 1;
 +#endif
 +        serializeInst[tid] = NULL;
 +    }
 +
 +    // Set the status to Squashing.
 +    renameStatus[tid] = Squashing;
 +
 +    // Squash any instructions from decode.
 +    unsigned squashCount = 0;
 +
 +    for (int i=0; i<fromDecode->size; i++) {
 +        if (fromDecode->insts[i]->threadNumber == tid) {
 +            fromDecode->insts[i]->squashed = true;
 +            wroteToTimeBuffer = true;
 +            squashCount++;
 +        }
 +    }
 +
 +    insts[tid].clear();
 +
 +    // Clear the skid buffer in case it has any data in it.
 +    skidBuffer[tid].clear();
 +
 +    doSquash(tid);
 +}
 +
 +template <class Impl>
 +void
 +DefaultRename<Impl>::tick()
 +{
 +    wroteToTimeBuffer = false;
 +
 +    blockThisCycle = false;
 +
 +    bool status_change = false;
 +
 +    toIEWIndex = 0;
 +
 +    sortInsts();
 +
 +    list<unsigned>::iterator threads = (*activeThreads).begin();
 +
 +    // Check stall and squash signals.
 +    while (threads != (*activeThreads).end()) {
 +        unsigned tid = *threads++;
 +
 +        DPRINTF(Rename, "Processing [tid:%i]\n", tid);
 +
 +        status_change = checkSignalsAndUpdate(tid) || status_change;
 +
 +        rename(status_change, tid);
 +    }
 +
 +    if (status_change) {
 +        updateStatus();
 +    }
 +
 +    if (wroteToTimeBuffer) {
 +        DPRINTF(Activity, "Activity this cycle.\n");
 +        cpu->activityThisCycle();
 +    }
 +
 +    threads = (*activeThreads).begin();
 +
 +    while (threads != (*activeThreads).end()) {
 +        unsigned tid = *threads++;
 +
 +        // If we committed this cycle then doneSeqNum will be > 0
 +        if (fromCommit->commitInfo[tid].doneSeqNum != 0 &&
 +            !fromCommit->commitInfo[tid].squash &&
 +            renameStatus[tid] != Squashing) {
 +
 +            removeFromHistory(fromCommit->commitInfo[tid].doneSeqNum,
 +                                  tid);
 +        }
 +    }
 +
 +    // @todo: make into updateProgress function
 +    for (int tid=0; tid < numThreads; tid++) {
 +        instsInProgress[tid] -= fromIEW->iewInfo[tid].dispatched;
 +
 +        assert(instsInProgress[tid] >=0);
 +    }
 +
 +}
 +
 +template<class Impl>
 +void
 +DefaultRename<Impl>::rename(bool &status_change, unsigned tid)
 +{
 +    // If status is Running or idle,
 +    //     call renameInsts()
 +    // If status is Unblocking,
 +    //     buffer any instructions coming from decode
 +    //     continue trying to empty skid buffer
 +    //     check if stall conditions have passed
 +
 +    if (renameStatus[tid] == Blocked) {
 +        ++renameBlockCycles;
 +    } else if (renameStatus[tid] == Squashing) {
 +        ++renameSquashCycles;
 +    } else if (renameStatus[tid] == SerializeStall) {
 +        ++renameSerializeStallCycles;
 +    }
 +
 +    if (renameStatus[tid] == Running ||
 +        renameStatus[tid] == Idle) {
 +        DPRINTF(Rename, "[tid:%u]: Not blocked, so attempting to run "
 +                "stage.\n", tid);
 +
 +        renameInsts(tid);
 +    } else if (renameStatus[tid] == Unblocking) {
 +        renameInsts(tid);
 +
 +        if (validInsts()) {
 +            // Add the current inputs to the skid buffer so they can be
 +            // reprocessed when this stage unblocks.
 +            skidInsert(tid);
 +        }
 +
 +        // If we switched over to blocking, then there's a potential for
 +        // an overall status change.
 +        status_change = unblock(tid) || status_change || blockThisCycle;
 +    }
 +}
 +
 +template <class Impl>
 +void
 +DefaultRename<Impl>::renameInsts(unsigned tid)
 +{
 +    // Instructions can be either in the skid buffer or the queue of
 +    // instructions coming from decode, depending on the status.
 +    int insts_available = renameStatus[tid] == Unblocking ?
 +        skidBuffer[tid].size() : insts[tid].size();
 +
 +    // Check the decode queue to see if instructions are available.
 +    // If there are no available instructions to rename, then do nothing.
 +    if (insts_available == 0) {
 +        DPRINTF(Rename, "[tid:%u]: Nothing to do, breaking out early.\n",
 +                tid);
 +        // Should I change status to idle?
 +        ++renameIdleCycles;
 +        return;
 +    } else if (renameStatus[tid] == Unblocking) {
 +        ++renameUnblockCycles;
 +    } else if (renameStatus[tid] == Running) {
 +        ++renameRunCycles;
 +    }
 +
 +    DynInstPtr inst;
 +
 +    // Will have to do a different calculation for the number of free
 +    // entries.
 +    int free_rob_entries = calcFreeROBEntries(tid);
 +    int free_iq_entries  = calcFreeIQEntries(tid);
 +    int free_lsq_entries = calcFreeLSQEntries(tid);
 +    int min_free_entries = free_rob_entries;
 +
 +    FullSource source = ROB;
 +
 +    if (free_iq_entries < min_free_entries) {
 +        min_free_entries = free_iq_entries;
 +        source = IQ;
 +    }
 +
 +    if (free_lsq_entries < min_free_entries) {
 +        min_free_entries = free_lsq_entries;
 +        source = LSQ;
 +    }
 +
 +    // Check if there's any space left.
 +    if (min_free_entries <= 0) {
 +        DPRINTF(Rename, "[tid:%u]: Blocking due to no free ROB/IQ/LSQ "
 +                "entries.\n"
 +                "ROB has %i free entries.\n"
 +                "IQ has %i free entries.\n"
 +                "LSQ has %i free entries.\n",
 +                tid,
 +                free_rob_entries,
 +                free_iq_entries,
 +                free_lsq_entries);
 +
 +        blockThisCycle = true;
 +
 +        block(tid);
 +
 +        incrFullStat(source);
 +
 +        return;
 +    } else if (min_free_entries < insts_available) {
 +        DPRINTF(Rename, "[tid:%u]: Will have to block this cycle."
 +                "%i insts available, but only %i insts can be "
 +                "renamed due to ROB/IQ/LSQ limits.\n",
 +                tid, insts_available, min_free_entries);
 +
 +        insts_available = min_free_entries;
 +
 +        blockThisCycle = true;
 +
 +        incrFullStat(source);
 +    }
 +
 +    InstQueue &insts_to_rename = renameStatus[tid] == Unblocking ?
 +        skidBuffer[tid] : insts[tid];
 +
 +    DPRINTF(Rename, "[tid:%u]: %i available instructions to "
 +            "send iew.\n", tid, insts_available);
 +
 +    DPRINTF(Rename, "[tid:%u]: %i insts pipelining from Rename | %i insts "
 +            "dispatched to IQ last cycle.\n",
 +            tid, instsInProgress[tid], fromIEW->iewInfo[tid].dispatched);
 +
 +    // Handle serializing the next instruction if necessary.
 +    if (serializeOnNextInst[tid]) {
 +        if (emptyROB[tid] && instsInProgress[tid] == 0) {
 +            // ROB already empty; no need to serialize.
 +            serializeOnNextInst[tid] = false;
 +        } else if (!insts_to_rename.empty()) {
 +            insts_to_rename.front()->setSerializeBefore();
 +        }
 +    }
 +
 +    int renamed_insts = 0;
 +
 +    while (insts_available > 0 &&  toIEWIndex < renameWidth) {
 +        DPRINTF(Rename, "[tid:%u]: Sending instructions to IEW.\n", tid);
 +
 +        assert(!insts_to_rename.empty());
 +
 +        inst = insts_to_rename.front();
 +
 +        insts_to_rename.pop_front();
 +
 +        if (renameStatus[tid] == Unblocking) {
 +            DPRINTF(Rename,"[tid:%u]: Removing [sn:%lli] PC:%#x from rename "
 +                    "skidBuffer\n",
 +                    tid, inst->seqNum, inst->readPC());
 +        }
 +
 +        if (inst->isSquashed()) {
 +            DPRINTF(Rename, "[tid:%u]: instruction %i with PC %#x is "
 +                    "squashed, skipping.\n",
 +                    tid, inst->seqNum, inst->threadNumber,inst->readPC());
 +
 +            ++renameSquashedInsts;
 +
 +            // Decrement how many instructions are available.
 +            --insts_available;
 +
 +            continue;
 +        }
 +
 +        DPRINTF(Rename, "[tid:%u]: Processing instruction [sn:%lli] with "
 +                "PC %#x.\n",
 +                tid, inst->seqNum, inst->readPC());
 +
 +        // Handle serializeAfter/serializeBefore instructions.
 +        // serializeAfter marks the next instruction as serializeBefore.
 +        // serializeBefore makes the instruction wait in rename until the ROB
 +        // is empty.
 +
 +        // In this model, IPR accesses are serialize before
 +        // instructions, and store conditionals are serialize after
 +        // instructions.  This is mainly due to lack of support for
 +        // out-of-order operations of either of those classes of
 +        // instructions.
 +        if ((inst->isIprAccess() || inst->isSerializeBefore()) &&
 +            !inst->isSerializeHandled()) {
 +            DPRINTF(Rename, "Serialize before instruction encountered.\n");
 +
 +            if (!inst->isTempSerializeBefore()) {
 +                renamedSerializing++;
 +                inst->setSerializeHandled();
 +            } else {
 +                renamedTempSerializing++;
 +            }
 +
 +            // Change status over to SerializeStall so that other stages know
 +            // what this is blocked on.
 +            renameStatus[tid] = SerializeStall;
 +
 +            serializeInst[tid] = inst;
 +
 +            blockThisCycle = true;
 +
 +            break;
 +        } else if ((inst->isStoreConditional() || inst->isSerializeAfter()) &&
 +                   !inst->isSerializeHandled()) {
 +            DPRINTF(Rename, "Serialize after instruction encountered.\n");
 +
 +            renamedSerializing++;
 +
 +            inst->setSerializeHandled();
 +
 +            serializeAfter(insts_to_rename, tid);
 +        }
 +
 +        // Check here to make sure there are enough destination registers
 +        // to rename to.  Otherwise block.
 +        if (renameMap[tid]->numFreeEntries() < inst->numDestRegs()) {
 +            DPRINTF(Rename, "Blocking due to lack of free "
 +                    "physical registers to rename to.\n");
 +            blockThisCycle = true;
 +
 +            ++renameFullRegistersEvents;
 +
 +            break;
 +        }
 +
 +        renameSrcRegs(inst, inst->threadNumber);
 +
 +        renameDestRegs(inst, inst->threadNumber);
 +
 +        ++renamed_insts;
 +
 +        // Put instruction in rename queue.
 +        toIEW->insts[toIEWIndex] = inst;
 +        ++(toIEW->size);
 +
 +        // Increment which instruction we're on.
 +        ++toIEWIndex;
 +
 +        // Decrement how many instructions are available.
 +        --insts_available;
 +    }
 +
 +    instsInProgress[tid] += renamed_insts;
 +    renameRenamedInsts += renamed_insts;
 +
 +    // If we wrote to the time buffer, record this.
 +    if (toIEWIndex) {
 +        wroteToTimeBuffer = true;
 +    }
 +
 +    // Check if there's any instructions left that haven't yet been renamed.
 +    // If so then block.
 +    if (insts_available) {
 +        blockThisCycle = true;
 +    }
 +
 +    if (blockThisCycle) {
 +        block(tid);
 +        toDecode->renameUnblock[tid] = false;
 +    }
 +}
 +
 +template<class Impl>
 +void
 +DefaultRename<Impl>::skidInsert(unsigned tid)
 +{
 +    DynInstPtr inst = NULL;
 +
 +    while (!insts[tid].empty()) {
 +        inst = insts[tid].front();
 +
 +        insts[tid].pop_front();
 +
 +        assert(tid == inst->threadNumber);
 +
 +        DPRINTF(Rename, "[tid:%u]: Inserting [sn:%lli] PC:%#x into Rename "
 +                "skidBuffer\n", tid, inst->seqNum, inst->readPC());
 +
 +        ++renameSkidInsts;
 +
 +        skidBuffer[tid].push_back(inst);
 +    }
 +
 +    if (skidBuffer[tid].size() > skidBufferMax)
 +        panic("Skidbuffer Exceeded Max Size");
 +}
 +
 +template <class Impl>
 +void
 +DefaultRename<Impl>::sortInsts()
 +{
 +    int insts_from_decode = fromDecode->size;
 +#ifdef DEBUG
 +    for (int i=0; i < numThreads; i++)
 +        assert(insts[i].empty());
 +#endif
 +    for (int i = 0; i < insts_from_decode; ++i) {
 +        DynInstPtr inst = fromDecode->insts[i];
 +        insts[inst->threadNumber].push_back(inst);
 +    }
 +}
 +
 +template<class Impl>
 +bool
 +DefaultRename<Impl>::skidsEmpty()
 +{
 +    list<unsigned>::iterator threads = (*activeThreads).begin();
 +
 +    while (threads != (*activeThreads).end()) {
 +        if (!skidBuffer[*threads++].empty())
 +            return false;
 +    }
 +
 +    return true;
 +}
 +
 +template<class Impl>
 +void
 +DefaultRename<Impl>::updateStatus()
 +{
 +    bool any_unblocking = false;
 +
 +    list<unsigned>::iterator threads = (*activeThreads).begin();
 +
 +    threads = (*activeThreads).begin();
 +
 +    while (threads != (*activeThreads).end()) {
 +        unsigned tid = *threads++;
 +
 +        if (renameStatus[tid] == Unblocking) {
 +            any_unblocking = true;
 +            break;
 +        }
 +    }
 +
 +    // Rename will have activity if it's unblocking.
 +    if (any_unblocking) {
 +        if (_status == Inactive) {
 +            _status = Active;
 +
 +            DPRINTF(Activity, "Activating stage.\n");
 +
 +            cpu->activateStage(FullCPU::RenameIdx);
 +        }
 +    } else {
 +        // If it's not unblocking, then rename will not have any internal
 +        // activity.  Switch it to inactive.
 +        if (_status == Active) {
 +            _status = Inactive;
 +            DPRINTF(Activity, "Deactivating stage.\n");
 +
 +            cpu->deactivateStage(FullCPU::RenameIdx);
 +        }
 +    }
 +}
 +
 +template <class Impl>
 +bool
 +DefaultRename<Impl>::block(unsigned tid)
 +{
 +    DPRINTF(Rename, "[tid:%u]: Blocking.\n", tid);
 +
 +    // Add the current inputs onto the skid buffer, so they can be
 +    // reprocessed when this stage unblocks.
 +    skidInsert(tid);
 +
 +    // Only signal backwards to block if the previous stages do not think
 +    // rename is already blocked.
 +    if (renameStatus[tid] != Blocked) {
 +        if (renameStatus[tid] != Unblocking) {
 +            toDecode->renameBlock[tid] = true;
 +            toDecode->renameUnblock[tid] = false;
 +            wroteToTimeBuffer = true;
 +        }
 +
 +        // Rename can not go from SerializeStall to Blocked, otherwise
 +        // it would not know to complete the serialize stall.
 +        if (renameStatus[tid] != SerializeStall) {
 +            // Set status to Blocked.
 +            renameStatus[tid] = Blocked;
 +            return true;
 +        }
 +    }
 +
 +    return false;
 +}
 +
 +template <class Impl>
 +bool
 +DefaultRename<Impl>::unblock(unsigned tid)
 +{
 +    DPRINTF(Rename, "[tid:%u]: Trying to unblock.\n", tid);
 +
 +    // Rename is done unblocking if the skid buffer is empty.
 +    if (skidBuffer[tid].empty() && renameStatus[tid] != SerializeStall) {
 +
 +        DPRINTF(Rename, "[tid:%u]: Done unblocking.\n", tid);
 +
 +        toDecode->renameUnblock[tid] = true;
 +        wroteToTimeBuffer = true;
 +
 +        renameStatus[tid] = Running;
 +        return true;
 +    }
 +
 +    return false;
 +}
 +
 +template <class Impl>
 +void
 +DefaultRename<Impl>::doSquash(unsigned tid)
 +{
 +    typename list<RenameHistory>::iterator hb_it = historyBuffer[tid].begin();
 +
 +    InstSeqNum squashed_seq_num = fromCommit->commitInfo[tid].doneSeqNum;
 +
 +    // After a syscall squashes everything, the history buffer may be empty
 +    // but the ROB may still be squashing instructions.
 +    if (historyBuffer[tid].empty()) {
 +        return;
 +    }
 +
 +    // Go through the most recent instructions, undoing the mappings
 +    // they did and freeing up the registers.
 +    while (!historyBuffer[tid].empty() &&
 +           (*hb_it).instSeqNum > squashed_seq_num) {
 +        assert(hb_it != historyBuffer[tid].end());
 +
 +        DPRINTF(Rename, "[tid:%u]: Removing history entry with sequence "
 +                "number %i.\n", tid, (*hb_it).instSeqNum);
 +
 +        // Tell the rename map to set the architected register to the
 +        // previous physical register that it was renamed to.
 +        renameMap[tid]->setEntry(hb_it->archReg, hb_it->prevPhysReg);
 +
 +        // Put the renamed physical register back on the free list.
 +        freeList->addReg(hb_it->newPhysReg);
 +
 +        historyBuffer[tid].erase(hb_it++);
 +
 +        ++renameUndoneMaps;
 +    }
 +}
 +
 +template<class Impl>
 +void
 +DefaultRename<Impl>::removeFromHistory(InstSeqNum inst_seq_num, unsigned tid)
 +{
 +    DPRINTF(Rename, "[tid:%u]: Removing a committed instruction from the "
 +            "history buffer %u (size=%i), until [sn:%lli].\n",
 +            tid, tid, historyBuffer[tid].size(), inst_seq_num);
 +
 +    typename list<RenameHistory>::iterator hb_it = historyBuffer[tid].end();
 +
 +    --hb_it;
 +
 +    if (historyBuffer[tid].empty()) {
 +        DPRINTF(Rename, "[tid:%u]: History buffer is empty.\n", tid);
 +        return;
 +    } else if (hb_it->instSeqNum > inst_seq_num) {
 +        DPRINTF(Rename, "[tid:%u]: Old sequence number encountered.  Ensure "
 +                "that a syscall happened recently.\n", tid);
 +        return;
 +    }
 +
 +    // Commit all the renames up until (and including) the committed sequence
 +    // number. Some or even all of the committed instructions may not have
 +    // rename histories if they did not have destination registers that were
 +    // renamed.
 +    while (!historyBuffer[tid].empty() &&
 +           hb_it != historyBuffer[tid].end() &&
 +           (*hb_it).instSeqNum <= inst_seq_num) {
 +
 +        DPRINTF(Rename, "[tid:%u]: Freeing up older rename of reg %i, "
 +                "[sn:%lli].\n",
 +                tid, (*hb_it).prevPhysReg, (*hb_it).instSeqNum);
 +
 +        freeList->addReg((*hb_it).prevPhysReg);
 +        ++renameCommittedMaps;
 +
 +        historyBuffer[tid].erase(hb_it--);
 +    }
 +}
 +
 +template <class Impl>
 +inline void
 +DefaultRename<Impl>::renameSrcRegs(DynInstPtr &inst,unsigned tid)
 +{
 +    assert(renameMap[tid] != 0);
 +
 +    unsigned num_src_regs = inst->numSrcRegs();
 +
 +    // Get the architectual register numbers from the source and
 +    // destination operands, and redirect them to the right register.
 +    // Will need to mark dependencies though.
 +    for (int src_idx = 0; src_idx < num_src_regs; src_idx++) {
 +        RegIndex src_reg = inst->srcRegIdx(src_idx);
 +
 +        // Look up the source registers to get the phys. register they've
 +        // been renamed to, and set the sources to those registers.
 +        PhysRegIndex renamed_reg = renameMap[tid]->lookup(src_reg);
 +
 +        DPRINTF(Rename, "[tid:%u]: Looking up arch reg %i, got "
 +                "physical reg %i.\n", tid, (int)src_reg,
 +                (int)renamed_reg);
 +
 +        inst->renameSrcReg(src_idx, renamed_reg);
 +
 +        // See if the register is ready or not.
 +        if (scoreboard->getReg(renamed_reg) == true) {
 +            DPRINTF(Rename, "[tid:%u]: Register is ready.\n", tid);
 +
 +            inst->markSrcRegReady(src_idx);
 +        }
 +
 +        ++renameRenameLookups;
 +    }
 +}
 +
 +template <class Impl>
 +inline void
 +DefaultRename<Impl>::renameDestRegs(DynInstPtr &inst,unsigned tid)
 +{
 +    typename RenameMap::RenameInfo rename_result;
 +
 +    unsigned num_dest_regs = inst->numDestRegs();
 +
 +    // Rename the destination registers.
 +    for (int dest_idx = 0; dest_idx < num_dest_regs; dest_idx++) {
 +        RegIndex dest_reg = inst->destRegIdx(dest_idx);
 +
 +        // Get the physical register that the destination will be
 +        // renamed to.
 +        rename_result = renameMap[tid]->rename(dest_reg);
 +
 +        //Mark Scoreboard entry as not ready
 +        scoreboard->unsetReg(rename_result.first);
 +
 +        DPRINTF(Rename, "[tid:%u]: Renaming arch reg %i to physical "
 +                "reg %i.\n", tid, (int)dest_reg,
 +                (int)rename_result.first);
 +
 +        // Record the rename information so that a history can be kept.
 +        RenameHistory hb_entry(inst->seqNum, dest_reg,
 +                               rename_result.first,
 +                               rename_result.second);
 +
 +        historyBuffer[tid].push_front(hb_entry);
 +
 +        DPRINTF(Rename, "[tid:%u]: Adding instruction to history buffer, "
 +                "[sn:%lli].\n",tid,
 +                (*historyBuffer[tid].begin()).instSeqNum);
 +
 +        // Tell the instruction to rename the appropriate destination
 +        // register (dest_idx) to the new physical register
 +        // (rename_result.first), and record the previous physical
 +        // register that the same logical register was renamed to
 +        // (rename_result.second).
 +        inst->renameDestReg(dest_idx,
 +                            rename_result.first,
 +                            rename_result.second);
 +
 +        ++renameRenamedOperands;
 +    }
 +}
 +
 +template <class Impl>
 +inline int
 +DefaultRename<Impl>::calcFreeROBEntries(unsigned tid)
 +{
 +    int num_free = freeEntries[tid].robEntries -
 +                  (instsInProgress[tid] - fromIEW->iewInfo[tid].dispatched);
 +
 +    //DPRINTF(Rename,"[tid:%i]: %i rob free\n",tid,num_free);
 +
 +    return num_free;
 +}
 +
 +template <class Impl>
 +inline int
 +DefaultRename<Impl>::calcFreeIQEntries(unsigned tid)
 +{
 +    int num_free = freeEntries[tid].iqEntries -
 +                  (instsInProgress[tid] - fromIEW->iewInfo[tid].dispatched);
 +
 +    //DPRINTF(Rename,"[tid:%i]: %i iq free\n",tid,num_free);
 +
 +    return num_free;
 +}
 +
 +template <class Impl>
 +inline int
 +DefaultRename<Impl>::calcFreeLSQEntries(unsigned tid)
 +{
 +    int num_free = freeEntries[tid].lsqEntries -
 +                  (instsInProgress[tid] - fromIEW->iewInfo[tid].dispatchedToLSQ);
 +
 +    //DPRINTF(Rename,"[tid:%i]: %i lsq free\n",tid,num_free);
 +
 +    return num_free;
 +}
 +
 +template <class Impl>
 +unsigned
 +DefaultRename<Impl>::validInsts()
 +{
 +    unsigned inst_count = 0;
 +
 +    for (int i=0; i<fromDecode->size; i++) {
 +        if (!fromDecode->insts[i]->squashed)
 +            inst_count++;
 +    }
 +
 +    return inst_count;
 +}
 +
 +template <class Impl>
 +void
 +DefaultRename<Impl>::readStallSignals(unsigned tid)
 +{
 +    if (fromIEW->iewBlock[tid]) {
 +        stalls[tid].iew = true;
 +    }
 +
 +    if (fromIEW->iewUnblock[tid]) {
 +        assert(stalls[tid].iew);
 +        stalls[tid].iew = false;
 +    }
 +
 +    if (fromCommit->commitBlock[tid]) {
 +        stalls[tid].commit = true;
 +    }
 +
 +    if (fromCommit->commitUnblock[tid]) {
 +        assert(stalls[tid].commit);
 +        stalls[tid].commit = false;
 +    }
 +}
 +
 +template <class Impl>
 +bool
 +DefaultRename<Impl>::checkStall(unsigned tid)
 +{
 +    bool ret_val = false;
 +
 +    if (stalls[tid].iew) {
 +        DPRINTF(Rename,"[tid:%i]: Stall from IEW stage detected.\n", tid);
 +        ret_val = true;
 +    } else if (stalls[tid].commit) {
 +        DPRINTF(Rename,"[tid:%i]: Stall from Commit stage detected.\n", tid);
 +        ret_val = true;
 +    } else if (calcFreeROBEntries(tid) <= 0) {
 +        DPRINTF(Rename,"[tid:%i]: Stall: ROB has 0 free entries.\n", tid);
 +        ret_val = true;
 +    } else if (calcFreeIQEntries(tid) <= 0) {
 +        DPRINTF(Rename,"[tid:%i]: Stall: IQ has 0 free entries.\n", tid);
 +        ret_val = true;
 +    } else if (calcFreeLSQEntries(tid) <= 0) {
 +        DPRINTF(Rename,"[tid:%i]: Stall: LSQ has 0 free entries.\n", tid);
 +        ret_val = true;
 +    } else if (renameMap[tid]->numFreeEntries() <= 0) {
 +        DPRINTF(Rename,"[tid:%i]: Stall: RenameMap has 0 free entries.\n", tid);
 +        ret_val = true;
 +    } else if (renameStatus[tid] == SerializeStall &&
 +               (!emptyROB[tid] || instsInProgress[tid])) {
 +        DPRINTF(Rename,"[tid:%i]: Stall: Serialize stall and ROB is not "
 +                "empty.\n",
 +                tid);
 +        ret_val = true;
 +    }
 +
 +    return ret_val;
 +}
 +
 +template <class Impl>
 +void
 +DefaultRename<Impl>::readFreeEntries(unsigned tid)
 +{
 +    bool updated = false;
 +    if (fromIEW->iewInfo[tid].usedIQ) {
 +        freeEntries[tid].iqEntries =
 +            fromIEW->iewInfo[tid].freeIQEntries;
 +        updated = true;
 +    }
 +
 +    if (fromIEW->iewInfo[tid].usedLSQ) {
 +        freeEntries[tid].lsqEntries =
 +            fromIEW->iewInfo[tid].freeLSQEntries;
 +        updated = true;
 +    }
 +
 +    if (fromCommit->commitInfo[tid].usedROB) {
 +        freeEntries[tid].robEntries =
 +            fromCommit->commitInfo[tid].freeROBEntries;
 +        emptyROB[tid] = fromCommit->commitInfo[tid].emptyROB;
 +        updated = true;
 +    }
 +
 +    DPRINTF(Rename, "[tid:%i]: Free IQ: %i, Free ROB: %i, Free LSQ: %i\n",
 +            tid,
 +            freeEntries[tid].iqEntries,
 +            freeEntries[tid].robEntries,
 +            freeEntries[tid].lsqEntries);
 +
 +    DPRINTF(Rename, "[tid:%i]: %i instructions not yet in ROB\n",
 +            tid, instsInProgress[tid]);
 +}
 +
 +template <class Impl>
 +bool
 +DefaultRename<Impl>::checkSignalsAndUpdate(unsigned tid)
 +{
 +    // Check if there's a squash signal, squash if there is
 +    // Check stall signals, block if necessary.
 +    // If status was blocked
 +    //     check if stall conditions have passed
 +    //         if so then go to unblocking
 +    // If status was Squashing
 +    //     check if squashing is not high.  Switch to running this cycle.
 +    // If status was serialize stall
 +    //     check if ROB is empty and no insts are in flight to the ROB
 +
 +    readFreeEntries(tid);
 +    readStallSignals(tid);
 +
 +    if (fromCommit->commitInfo[tid].squash) {
 +        DPRINTF(Rename, "[tid:%u]: Squashing instructions due to squash from "
 +                "commit.\n", tid);
 +
 +        squash(tid);
 +
 +        return true;
 +    }
 +
 +    if (fromCommit->commitInfo[tid].robSquashing) {
 +        DPRINTF(Rename, "[tid:%u]: ROB is still squashing.\n", tid);
 +
 +        renameStatus[tid] = Squashing;
 +
 +        return true;
 +    }
 +
 +    if (checkStall(tid)) {
 +        return block(tid);
 +    }
 +
 +    if (renameStatus[tid] == Blocked) {
 +        DPRINTF(Rename, "[tid:%u]: Done blocking, switching to unblocking.\n",
 +                tid);
 +
 +        renameStatus[tid] = Unblocking;
 +
 +        unblock(tid);
 +
 +        return true;
 +    }
 +
 +    if (renameStatus[tid] == Squashing) {
 +        // Switch status to running if rename isn't being told to block or
 +        // squash this cycle.
 +        DPRINTF(Rename, "[tid:%u]: Done squashing, switching to running.\n",
 +                tid);
 +
 +        renameStatus[tid] = Running;
 +
 +        return false;
 +    }
 +
 +    if (renameStatus[tid] == SerializeStall) {
 +        // Stall ends once the ROB is free.
 +        DPRINTF(Rename, "[tid:%u]: Done with serialize stall, switching to "
 +                "unblocking.\n", tid);
 +
 +        DynInstPtr serial_inst = serializeInst[tid];
 +
 +        renameStatus[tid] = Unblocking;
 +
 +        unblock(tid);
 +
 +        DPRINTF(Rename, "[tid:%u]: Processing instruction [%lli] with "
 +                "PC %#x.\n",
 +                tid, serial_inst->seqNum, serial_inst->readPC());
 +
 +        // Put instruction into queue here.
 +        serial_inst->clearSerializeBefore();
 +
 +        if (!skidBuffer[tid].empty()) {
 +            skidBuffer[tid].push_front(serial_inst);
 +        } else {
 +            insts[tid].push_front(serial_inst);
 +        }
 +
 +        DPRINTF(Rename, "[tid:%u]: Instruction must be processed by rename."
 +                " Adding to front of list.", tid);
 +
 +        serializeInst[tid] = NULL;
 +
 +        return true;
 +    }
 +
 +    // If we've reached this point, we have not gotten any signals that
 +    // cause rename to change its status.  Rename remains the same as before.
 +    return false;
 +}
 +
 +template<class Impl>
 +void
 +DefaultRename<Impl>::serializeAfter(InstQueue &inst_list,
 +                                   unsigned tid)
 +{
 +    if (inst_list.empty()) {
 +        // Mark a bit to say that I must serialize on the next instruction.
 +        serializeOnNextInst[tid] = true;
 +        return;
 +    }
 +
 +    // Set the next instruction as serializing.
 +    inst_list.front()->setSerializeBefore();
 +}
 +
 +template <class Impl>
 +inline void
 +DefaultRename<Impl>::incrFullStat(const FullSource &source)
 +{
 +    switch (source) {
 +      case ROB:
 +        ++renameROBFullEvents;
 +        break;
 +      case IQ:
 +        ++renameIQFullEvents;
 +        break;
 +      case LSQ:
 +        ++renameLSQFullEvents;
 +        break;
 +      default:
 +        panic("Rename full stall stat should be incremented for a reason!");
 +        break;
 +    }
 +}
 +
 +template <class Impl>
 +void
 +DefaultRename<Impl>::dumpHistory()
 +{
 +    typename list<RenameHistory>::iterator buf_it;
 +
 +    for (int i = 0; i < numThreads; i++) {
 +
 +        buf_it = historyBuffer[i].begin();
 +
 +        while (buf_it != historyBuffer[i].end()) {
 +            cprintf("Seq num: %i\nArch reg: %i New phys reg: %i Old phys "
 +                    "reg: %i\n", (*buf_it).instSeqNum, (int)(*buf_it).archReg,
 +                    (int)(*buf_it).newPhysReg, (int)(*buf_it).prevPhysReg);
 +
 +            buf_it++;
 +        }
 +    }
 +}
index 0edb8068454ab0c32e3283b9467e57548f798db9,0000000000000000000000000000000000000000..c4c90c99a0eb40182fe3f34b2701b5828bbf847a
mode 100644,000000..100644
--- /dev/null
@@@ -1,167 -1,0 +1,168 @@@
-     //Constructor
-      SimpleRenameMap() {};
 +/*
 + * Copyright (c) 2004-2005 The Regents of The University of Michigan
 + * 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: Kevin Lim
 + */
 +
 +// Todo:  Create destructor.
 +// Have it so that there's a more meaningful name given to the variable
 +// that marks the beginning of the FP registers.
 +
 +#ifndef __CPU_O3_RENAME_MAP_HH__
 +#define __CPU_O3_RENAME_MAP_HH__
 +
 +#include <iostream>
 +#include <utility>
 +#include <vector>
 +
 +#include "cpu/o3/free_list.hh"
 +//For RegIndex
 +#include "arch/isa_traits.hh"
 +
 +class SimpleRenameMap
 +{
 +  protected:
 +    typedef TheISA::RegIndex RegIndex;
 +  public:
 +    /**
 +     * Pair of a logical register and a physical register.  Tells the
 +     * previous mapping of a logical register to a physical register.
 +     * Used to roll back the rename map to a previous state.
 +     */
 +    typedef std::pair<RegIndex, PhysRegIndex> UnmapInfo;
 +
 +    /**
 +     * Pair of a physical register and a physical register.  Used to
 +     * return the physical register that a logical register has been
 +     * renamed to, and the previous physical register that the same
 +     * logical register was previously mapped to.
 +     */
 +    typedef std::pair<PhysRegIndex, PhysRegIndex> RenameInfo;
 +
 +  public:
-     //Change this to private
++    /** Default constructor.  init() must be called prior to use. */
++    SimpleRenameMap() {};
 +
 +    /** Destructor. */
 +    ~SimpleRenameMap();
 +
++    /** Initializes rename map with given parameters. */
 +    void init(unsigned _numLogicalIntRegs,
 +              unsigned _numPhysicalIntRegs,
 +              PhysRegIndex &_int_reg_start,
 +
 +              unsigned _numLogicalFloatRegs,
 +              unsigned _numPhysicalFloatRegs,
 +              PhysRegIndex &_float_reg_start,
 +
 +              unsigned _numMiscRegs,
 +
 +              RegIndex _intZeroReg,
 +              RegIndex _floatZeroReg,
 +
 +              int id,
 +              bool bindRegs);
 +
++    /** Sets the free list used with this rename map. */
 +    void setFreeList(SimpleFreeList *fl_ptr);
 +
 +    //Tell rename map to get a free physical register for a given
 +    //architected register.  Not sure it should have a return value,
 +    //but perhaps it should have some sort of fault in case there are
 +    //no free registers.
 +    RenameInfo rename(RegIndex arch_reg);
 +
 +    PhysRegIndex lookup(RegIndex phys_reg);
 +
 +    /**
 +     * Marks the given register as ready, meaning that its value has been
 +     * calculated and written to the register file.
 +     * @param ready_reg The index of the physical register that is now ready.
 +     */
 +    void setEntry(RegIndex arch_reg, PhysRegIndex renamed_reg);
 +
 +    int numFreeEntries();
 +
 +  private:
 +    /** Rename Map ID  */
 +    int id;
 +
 +    /** Number of logical integer registers. */
 +    int numLogicalIntRegs;
 +
 +    /** Number of physical integer registers. */
 +    int numPhysicalIntRegs;
 +
 +    /** Number of logical floating point registers. */
 +    int numLogicalFloatRegs;
 +
 +    /** Number of physical floating point registers. */
 +    int numPhysicalFloatRegs;
 +
 +    /** Number of miscellaneous registers. */
 +    int numMiscRegs;
 +
 +    /** Number of logical integer + float registers. */
 +    int numLogicalRegs;
 +
 +    /** Number of physical integer + float registers. */
 +    int numPhysicalRegs;
 +
 +    /** The integer zero register.  This implementation assumes it is always
 +     *  zero and never can be anything else.
 +     */
 +    RegIndex intZeroReg;
 +
 +    /** The floating point zero register.  This implementation assumes it is
 +     *  always zero and never can be anything else.
 +     */
 +    RegIndex floatZeroReg;
 +
 +    class RenameEntry
 +    {
 +      public:
 +        PhysRegIndex physical_reg;
 +        bool valid;
 +
 +        RenameEntry()
 +            : physical_reg(0), valid(false)
 +        { }
 +    };
 +
 +  private:
 +    /** Integer rename map. */
 +    std::vector<RenameEntry> intRenameMap;
 +
 +    /** Floating point rename map. */
 +    std::vector<RenameEntry> floatRenameMap;
 +
 +  private:
 +    /** Free list interface. */
 +    SimpleFreeList *freeList;
 +};
 +
 +#endif //__CPU_O3_RENAME_MAP_HH__
index 3786a03556db41ba28b63c8150a27c752778c948,0000000000000000000000000000000000000000..6d1402531fe235da57c56da5df7a5b28f70ac7b0
mode 100644,000000..100644
--- /dev/null
@@@ -1,316 -1,0 +1,319 @@@
 +/*
 + * Copyright (c) 2004-2006 The Regents of The University of Michigan
 + * 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: Kevin Lim
 + */
 +
 +#ifndef __CPU_O3_ROB_HH__
 +#define __CPU_O3_ROB_HH__
 +
 +#include <string>
 +#include <utility>
 +#include <vector>
 +
 +/**
 + * ROB class.  The ROB is largely what drives squashing.
 + */
 +template <class Impl>
 +class ROB
 +{
 +  protected:
 +    typedef TheISA::RegIndex RegIndex;
 +  public:
 +    //Typedefs from the Impl.
 +    typedef typename Impl::FullCPU FullCPU;
 +    typedef typename Impl::DynInstPtr DynInstPtr;
 +
 +    typedef std::pair<RegIndex, PhysRegIndex> UnmapInfo;
 +    typedef typename std::list<DynInstPtr>::iterator InstIt;
 +
 +    /** Possible ROB statuses. */
 +    enum Status {
 +        Running,
 +        Idle,
 +        ROBSquashing
 +    };
 +
 +    /** SMT ROB Sharing Policy */
 +    enum ROBPolicy{
 +        Dynamic,
 +        Partitioned,
 +        Threshold
 +    };
 +
 +  private:
 +    /** Per-thread ROB status. */
 +    Status robStatus[Impl::MaxThreads];
 +
 +    /** ROB resource sharing policy for SMT mode. */
 +    ROBPolicy robPolicy;
 +
 +  public:
 +    /** ROB constructor.
 +     *  @param _numEntries      Number of entries in ROB.
 +     *  @param _squashWidth     Number of instructions that can be squashed in a
 +     *                          single cycle.
 +     *  @param _smtROBPolicy    ROB Partitioning Scheme for SMT.
 +     *  @param _smtROBThreshold Max Resources(by %) a thread can have in the ROB.
 +     *  @param _numThreads      The number of active threads.
 +     */
 +    ROB(unsigned _numEntries, unsigned _squashWidth, std::string smtROBPolicy,
 +        unsigned _smtROBThreshold, unsigned _numThreads);
 +
 +    std::string name() const;
 +
 +    /** Function to set the CPU pointer, necessary due to which object the ROB
 +     *  is created within.
 +     *  @param cpu_ptr Pointer to the implementation specific full CPU object.
 +     */
 +    void setCPU(FullCPU *cpu_ptr);
 +
 +    /** Sets pointer to the list of active threads.
 +     *  @param at_ptr Pointer to the list of active threads.
 +     */
 +    void setActiveThreads(std::list<unsigned>* at_ptr);
 +
++    /** Switches out the ROB. */
 +    void switchOut();
 +
++    /** Takes over another CPU's thread. */
 +    void takeOverFrom();
 +
 +    /** Function to insert an instruction into the ROB. Note that whatever
 +     *  calls this function must ensure that there is enough space within the
 +     *  ROB for the new instruction.
 +     *  @param inst The instruction being inserted into the ROB.
 +     */
 +    void insertInst(DynInstPtr &inst);
 +
 +    /** Returns pointer to the head instruction within the ROB.  There is
 +     *  no guarantee as to the return value if the ROB is empty.
 +     *  @retval Pointer to the DynInst that is at the head of the ROB.
 +     */
 +//    DynInstPtr readHeadInst();
 +
 +    /** Returns a pointer to the head instruction of a specific thread within
 +     *  the ROB.
 +     *  @return Pointer to the DynInst that is at the head of the ROB.
 +     */
 +    DynInstPtr readHeadInst(unsigned tid);
 +
 +    /** Returns pointer to the tail instruction within the ROB.  There is
 +     *  no guarantee as to the return value if the ROB is empty.
 +     *  @retval Pointer to the DynInst that is at the tail of the ROB.
 +     */
 +//    DynInstPtr readTailInst();
 +
 +    /** Returns a pointer to the tail instruction of a specific thread within
 +     *  the ROB.
 +     *  @return Pointer to the DynInst that is at the tail of the ROB.
 +     */
 +    DynInstPtr readTailInst(unsigned tid);
 +
 +    /** Retires the head instruction, removing it from the ROB. */
 +//    void retireHead();
 +
 +    /** Retires the head instruction of a specific thread, removing it from the
 +     *  ROB.
 +     */
 +    void retireHead(unsigned tid);
 +
 +    /** Is the oldest instruction across all threads ready. */
 +//    bool isHeadReady();
 +
 +    /** Is the oldest instruction across a particular thread ready. */
 +    bool isHeadReady(unsigned tid);
 +
 +    /** Is there any commitable head instruction across all threads ready. */
 +    bool canCommit();
 +
 +    /** Re-adjust ROB partitioning. */
 +    void resetEntries();
 +
 +    /** Number of entries needed For 'num_threads' amount of threads. */
 +    int entryAmount(int num_threads);
 +
 +    /** Returns the number of total free entries in the ROB. */
 +    unsigned numFreeEntries();
 +
 +    /** Returns the number of free entries in a specific ROB paritition. */
 +    unsigned numFreeEntries(unsigned tid);
 +
 +    /** Returns the maximum number of entries for a specific thread. */
 +    unsigned getMaxEntries(unsigned tid)
 +    { return maxEntries[tid]; }
 +
 +    /** Returns the number of entries being used by a specific thread. */
 +    unsigned getThreadEntries(unsigned tid)
 +    { return threadEntries[tid]; }
 +
 +    /** Returns if the ROB is full. */
 +    bool isFull()
 +    { return numInstsInROB == numEntries; }
 +
 +    /** Returns if a specific thread's partition is full. */
 +    bool isFull(unsigned tid)
 +    { return threadEntries[tid] == numEntries; }
 +
 +    /** Returns if the ROB is empty. */
 +    bool isEmpty()
 +    { return numInstsInROB == 0; }
 +
 +    /** Returns if a specific thread's partition is empty. */
 +    bool isEmpty(unsigned tid)
 +    { return threadEntries[tid] == 0; }
 +
 +    /** Executes the squash, marking squashed instructions. */
 +    void doSquash(unsigned tid);
 +
 +    /** Squashes all instructions younger than the given sequence number for
 +     *  the specific thread.
 +     */
 +    void squash(InstSeqNum squash_num, unsigned tid);
 +
 +    /** Updates the head instruction with the new oldest instruction. */
 +    void updateHead();
 +
 +    /** Updates the tail instruction with the new youngest instruction. */
 +    void updateTail();
 +
 +    /** Reads the PC of the oldest head instruction. */
 +//    uint64_t readHeadPC();
 +
 +    /** Reads the PC of the head instruction of a specific thread. */
 +//    uint64_t readHeadPC(unsigned tid);
 +
 +    /** Reads the next PC of the oldest head instruction. */
 +//    uint64_t readHeadNextPC();
 +
 +    /** Reads the next PC of the head instruction of a specific thread. */
 +//    uint64_t readHeadNextPC(unsigned tid);
 +
 +    /** Reads the sequence number of the oldest head instruction. */
 +//    InstSeqNum readHeadSeqNum();
 +
 +    /** Reads the sequence number of the head instruction of a specific thread.
 +     */
 +//    InstSeqNum readHeadSeqNum(unsigned tid);
 +
 +    /** Reads the PC of the youngest tail instruction. */
 +//    uint64_t readTailPC();
 +
 +    /** Reads the PC of the tail instruction of a specific thread. */
 +//    uint64_t readTailPC(unsigned tid);
 +
 +    /** Reads the sequence number of the youngest tail instruction. */
 +//    InstSeqNum readTailSeqNum();
 +
 +    /** Reads the sequence number of tail instruction of a specific thread. */
 +//    InstSeqNum readTailSeqNum(unsigned tid);
 +
 +    /** Checks if the ROB is still in the process of squashing instructions.
 +     *  @retval Whether or not the ROB is done squashing.
 +     */
 +    bool isDoneSquashing(unsigned tid) const
 +    { return doneSquashing[tid]; }
 +
 +    /** Checks if the ROB is still in the process of squashing instructions for
 +     *  any thread.
 +     */
 +    bool isDoneSquashing();
 +
 +    /** This is more of a debugging function than anything.  Use
 +     *  numInstsInROB to get the instructions in the ROB unless you are
 +     *  double checking that variable.
 +     */
 +    int countInsts();
 +
 +    /** This is more of a debugging function than anything.  Use
 +     *  threadEntries to get the instructions in the ROB unless you are
 +     *  double checking that variable.
 +     */
 +    int countInsts(unsigned tid);
 +
 +  private:
 +    /** Pointer to the CPU. */
 +    FullCPU *cpu;
 +
 +    /** Active Threads in CPU */
 +    std::list<unsigned>* activeThreads;
 +
 +    /** Number of instructions in the ROB. */
 +    unsigned numEntries;
 +
 +    /** Entries Per Thread */
 +    unsigned threadEntries[Impl::MaxThreads];
 +
 +    /** Max Insts a Thread Can Have in the ROB */
 +    unsigned maxEntries[Impl::MaxThreads];
 +
 +    /** ROB List of Instructions */
 +    std::list<DynInstPtr> instList[Impl::MaxThreads];
 +
 +    /** Number of instructions that can be squashed in a single cycle. */
 +    unsigned squashWidth;
 +
 +  public:
 +    /** Iterator pointing to the instruction which is the last instruction
 +     *  in the ROB.  This may at times be invalid (ie when the ROB is empty),
 +     *  however it should never be incorrect.
 +     */
 +    InstIt tail;
 +
 +    /** Iterator pointing to the instruction which is the first instruction in
 +     *  in the ROB*/
 +    InstIt head;
 +
 +  private:
 +    /** Iterator used for walking through the list of instructions when
 +     *  squashing.  Used so that there is persistent state between cycles;
 +     *  when squashing, the instructions are marked as squashed but not
 +     *  immediately removed, meaning the tail iterator remains the same before
 +     *  and after a squash.
 +     *  This will always be set to cpu->instList.end() if it is invalid.
 +     */
 +    InstIt squashIt[Impl::MaxThreads];
 +
 +  public:
 +    /** Number of instructions in the ROB. */
 +    int numInstsInROB;
 +
++    /** Dummy instruction returned if there are no insts left. */
 +    DynInstPtr dummyInst;
 +
 +  private:
 +    /** The sequence number of the squashed instruction. */
 +    InstSeqNum squashedSeqNum;
 +
 +    /** Is the ROB done squashing. */
 +    bool doneSquashing[Impl::MaxThreads];
 +
 +    /** Number of active threads. */
 +    unsigned numThreads;
 +};
 +
 +#endif //__CPU_O3_ROB_HH__
index 720d5da53239cd2907f8daab24814e6e988a5f5e,0000000000000000000000000000000000000000..0023cee3697a62294f6861b61c2640a51e22a5ef
mode 100644,000000..100644
--- /dev/null
@@@ -1,322 -1,0 +1,347 @@@
 +/*
 + * Copyright (c) 2004-2006 The Regents of The University of Michigan
 + * 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: Kevin Lim
 + */
 +
++#include "base/intmath.hh"
 +#include "base/trace.hh"
 +#include "cpu/o3/store_set.hh"
 +
 +StoreSet::StoreSet(int _SSIT_size, int _LFST_size)
 +    : SSITSize(_SSIT_size), LFSTSize(_LFST_size)
 +{
 +    DPRINTF(StoreSet, "StoreSet: Creating store set object.\n");
 +    DPRINTF(StoreSet, "StoreSet: SSIT size: %i, LFST size: %i.\n",
 +            SSITSize, LFSTSize);
 +
++    if (!isPowerOf2(SSITSize)) {
++        fatal("Invalid SSIT size!\n");
++    }
++
 +    SSIT.resize(SSITSize);
 +
 +    validSSIT.resize(SSITSize);
 +
 +    for (int i = 0; i < SSITSize; ++i)
 +        validSSIT[i] = false;
 +
++    if (!isPowerOf2(LFSTSize)) {
++        fatal("Invalid LFST size!\n");
++    }
++
 +    LFST.resize(LFSTSize);
 +
 +    validLFST.resize(LFSTSize);
 +
 +    for (int i = 0; i < LFSTSize; ++i) {
 +        validLFST[i] = false;
 +        LFST[i] = 0;
 +    }
 +
 +    indexMask = SSITSize - 1;
 +
 +    offsetBits = 2;
 +}
 +
 +StoreSet::~StoreSet()
 +{
 +}
 +
 +void
 +StoreSet::init(int _SSIT_size, int _LFST_size)
 +{
 +    SSITSize = _SSIT_size;
 +    LFSTSize = _LFST_size;
 +
 +    DPRINTF(StoreSet, "StoreSet: Creating store set object.\n");
 +    DPRINTF(StoreSet, "StoreSet: SSIT size: %i, LFST size: %i.\n",
 +            SSITSize, LFSTSize);
 +
 +    SSIT.resize(SSITSize);
 +
 +    validSSIT.resize(SSITSize);
 +
 +    for (int i = 0; i < SSITSize; ++i)
 +        validSSIT[i] = false;
 +
 +    LFST.resize(LFSTSize);
 +
 +    validLFST.resize(LFSTSize);
 +
 +    for (int i = 0; i < LFSTSize; ++i) {
 +        validLFST[i] = false;
 +        LFST[i] = 0;
 +    }
 +
 +    indexMask = SSITSize - 1;
 +
 +    offsetBits = 2;
 +}
 +
 +
 +void
 +StoreSet::violation(Addr store_PC, Addr load_PC)
 +{
 +    int load_index = calcIndex(load_PC);
 +    int store_index = calcIndex(store_PC);
 +
 +    assert(load_index < SSITSize && store_index < SSITSize);
 +
 +    bool valid_load_SSID = validSSIT[load_index];
 +    bool valid_store_SSID = validSSIT[store_index];
 +
 +    if (!valid_load_SSID && !valid_store_SSID) {
 +        // Calculate a new SSID here.
 +        SSID new_set = calcSSID(load_PC);
 +
 +        validSSIT[load_index] = true;
 +
 +        SSIT[load_index] = new_set;
 +
 +        validSSIT[store_index] = true;
 +
 +        SSIT[store_index] = new_set;
 +
 +        assert(new_set < LFSTSize);
 +
 +        DPRINTF(StoreSet, "StoreSet: Neither load nor store had a valid "
 +                "storeset, creating a new one: %i for load %#x, store %#x\n",
 +                new_set, load_PC, store_PC);
 +    } else if (valid_load_SSID && !valid_store_SSID) {
 +        SSID load_SSID = SSIT[load_index];
 +
 +        validSSIT[store_index] = true;
 +
 +        SSIT[store_index] = load_SSID;
 +
 +        assert(load_SSID < LFSTSize);
 +
 +        DPRINTF(StoreSet, "StoreSet: Load had a valid store set.  Adding "
 +                "store to that set: %i for load %#x, store %#x\n",
 +                load_SSID, load_PC, store_PC);
 +    } else if (!valid_load_SSID && valid_store_SSID) {
 +        SSID store_SSID = SSIT[store_index];
 +
 +        validSSIT[load_index] = true;
 +
 +        SSIT[load_index] = store_SSID;
 +
 +        DPRINTF(StoreSet, "StoreSet: Store had a valid store set: %i for "
 +                "load %#x, store %#x\n",
 +                store_SSID, load_PC, store_PC);
 +    } else {
 +        SSID load_SSID = SSIT[load_index];
 +        SSID store_SSID = SSIT[store_index];
 +
 +        assert(load_SSID < LFSTSize && store_SSID < LFSTSize);
 +
 +        // The store set with the lower number wins
 +        if (store_SSID > load_SSID) {
 +            SSIT[store_index] = load_SSID;
 +
 +            DPRINTF(StoreSet, "StoreSet: Load had smaller store set: %i; "
 +                    "for load %#x, store %#x\n",
 +                    load_SSID, load_PC, store_PC);
 +        } else {
 +            SSIT[load_index] = store_SSID;
 +
 +            DPRINTF(StoreSet, "StoreSet: Store had smaller store set: %i; "
 +                    "for load %#x, store %#x\n",
 +                    store_SSID, load_PC, store_PC);
 +        }
 +    }
 +}
 +
 +void
 +StoreSet::insertLoad(Addr load_PC, InstSeqNum load_seq_num)
 +{
 +    // Does nothing.
 +    return;
 +}
 +
 +void
 +StoreSet::insertStore(Addr store_PC, InstSeqNum store_seq_num,
 +                      unsigned tid)
 +{
 +    int index = calcIndex(store_PC);
 +
 +    int store_SSID;
 +
 +    assert(index < SSITSize);
 +
 +    if (!validSSIT[index]) {
 +        // Do nothing if there's no valid entry.
 +        return;
 +    } else {
 +        store_SSID = SSIT[index];
 +
 +        assert(store_SSID < LFSTSize);
 +
 +        // Update the last store that was fetched with the current one.
 +        LFST[store_SSID] = store_seq_num;
 +
 +        validLFST[store_SSID] = 1;
 +
 +        storeList[store_seq_num] = store_SSID;
 +
 +        DPRINTF(StoreSet, "Store %#x updated the LFST, SSID: %i\n",
 +                store_PC, store_SSID);
 +    }
 +}
 +
 +InstSeqNum
 +StoreSet::checkInst(Addr PC)
 +{
 +    int index = calcIndex(PC);
 +
 +    int inst_SSID;
 +
 +    assert(index < SSITSize);
 +
 +    if (!validSSIT[index]) {
 +        DPRINTF(StoreSet, "Inst %#x with index %i had no SSID\n",
 +                PC, index);
 +
 +        // Return 0 if there's no valid entry.
 +        return 0;
 +    } else {
 +        inst_SSID = SSIT[index];
 +
 +        assert(inst_SSID < LFSTSize);
 +
 +        if (!validLFST[inst_SSID]) {
 +
 +            DPRINTF(StoreSet, "Inst %#x with index %i and SSID %i had no "
 +                    "dependency\n", PC, index, inst_SSID);
 +
 +            return 0;
 +        } else {
 +            DPRINTF(StoreSet, "Inst %#x with index %i and SSID %i had LFST "
 +                    "inum of %i\n", PC, index, inst_SSID, LFST[inst_SSID]);
 +
 +            return LFST[inst_SSID];
 +        }
 +    }
 +}
 +
 +void
 +StoreSet::issued(Addr issued_PC, InstSeqNum issued_seq_num, bool is_store)
 +{
 +    // This only is updated upon a store being issued.
 +    if (!is_store) {
 +        return;
 +    }
 +
 +    int index = calcIndex(issued_PC);
 +
 +    int store_SSID;
 +
 +    assert(index < SSITSize);
 +
 +    SeqNumMapIt store_list_it = storeList.find(issued_seq_num);
 +
 +    if (store_list_it != storeList.end()) {
 +        storeList.erase(store_list_it);
 +    }
 +
 +    // Make sure the SSIT still has a valid entry for the issued store.
 +    if (!validSSIT[index]) {
 +        return;
 +    }
 +
 +    store_SSID = SSIT[index];
 +
 +    assert(store_SSID < LFSTSize);
 +
 +    // If the last fetched store in the store set refers to the store that
 +    // was just issued, then invalidate the entry.
 +    if (validLFST[store_SSID] && LFST[store_SSID] == issued_seq_num) {
 +        DPRINTF(StoreSet, "StoreSet: store invalidated itself in LFST.\n");
 +        validLFST[store_SSID] = false;
 +    }
 +}
 +
 +void
 +StoreSet::squash(InstSeqNum squashed_num, unsigned tid)
 +{
 +    DPRINTF(StoreSet, "StoreSet: Squashing until inum %i\n",
 +            squashed_num);
 +
 +    int idx;
 +    SeqNumMapIt store_list_it = storeList.begin();
 +
 +    //@todo:Fix to only delete from correct thread
 +    while (!storeList.empty()) {
 +        idx = (*store_list_it).second;
 +
 +        if ((*store_list_it).first <= squashed_num) {
 +            break;
 +        }
 +
 +        bool younger = LFST[idx] > squashed_num;
 +
 +        if (validLFST[idx] && younger) {
 +            DPRINTF(StoreSet, "Squashed [sn:%lli]\n", LFST[idx]);
 +            validLFST[idx] = false;
 +
 +            storeList.erase(store_list_it++);
 +        } else if (!validLFST[idx] && younger) {
 +            storeList.erase(store_list_it++);
 +        }
 +    }
 +}
 +
 +void
 +StoreSet::clear()
 +{
 +    for (int i = 0; i < SSITSize; ++i) {
 +        validSSIT[i] = false;
 +    }
 +
 +    for (int i = 0; i < LFSTSize; ++i) {
 +        validLFST[i] = false;
 +    }
 +
 +    storeList.clear();
 +}
++
++void
++StoreSet::dump()
++{
++    cprintf("storeList.size(): %i\n", storeList.size());
++    SeqNumMapIt store_list_it = storeList.begin();
++
++    int num = 0;
++
++    while (store_list_it != storeList.end()) {
++        cprintf("%i: [sn:%lli] SSID:%i\n",
++                num, (*store_list_it).first, (*store_list_it).second);
++        num++;
++        store_list_it++;
++    }
++}
index 64255c51a749902058cbd11f2ae1f96ef727079e,0000000000000000000000000000000000000000..f5a44a1ac4bea4b83f1f773f8c3fc6e4009bba88
mode 100644,000000..100644
--- /dev/null
@@@ -1,107 -1,0 +1,147 @@@
 +/*
 + * Copyright (c) 2004-2005 The Regents of The University of Michigan
 + * 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: Kevin Lim
 + */
 +
 +#ifndef __CPU_O3_STORE_SET_HH__
 +#define __CPU_O3_STORE_SET_HH__
 +
 +#include <list>
 +#include <map>
 +#include <utility>
 +#include <vector>
 +
 +#include "arch/isa_traits.hh"
 +#include "cpu/inst_seq.hh"
 +
 +struct ltseqnum {
 +    bool operator()(const InstSeqNum &lhs, const InstSeqNum &rhs) const
 +    {
 +        return lhs > rhs;
 +    }
 +};
 +
++/**
++ * Implements a store set predictor for determining if memory
++ * instructions are dependent upon each other.  See paper "Memory
++ * Dependence Prediction using Store Sets" by Chrysos and Emer.  SSID
++ * stands for Store Set ID, SSIT stands for Store Set ID Table, and
++ * LFST is Last Fetched Store Table.
++ */
 +class StoreSet
 +{
 +  public:
 +    typedef unsigned SSID;
 +
 +  public:
++    /** Default constructor.  init() must be called prior to use. */
 +    StoreSet() { };
 +
++    /** Creates store set predictor with given table sizes. */
 +    StoreSet(int SSIT_size, int LFST_size);
 +
++    /** Default destructor. */
 +    ~StoreSet();
 +
++    /** Initializes the store set predictor with the given table sizes. */
 +    void init(int SSIT_size, int LFST_size);
 +
++    /** Records a memory ordering violation between the younger load
++     * and the older store. */
 +    void violation(Addr store_PC, Addr load_PC);
 +
++    /** Inserts a load into the store set predictor.  This does nothing but
++     * is included in case other predictors require a similar function.
++     */
 +    void insertLoad(Addr load_PC, InstSeqNum load_seq_num);
 +
++    /** Inserts a store into the store set predictor.  Updates the
++     * LFST if the store has a valid SSID. */
 +    void insertStore(Addr store_PC, InstSeqNum store_seq_num,
 +                     unsigned tid);
 +
++    /** Checks if the instruction with the given PC is dependent upon
++     * any store.  @return Returns the sequence number of the store
++     * instruction this PC is dependent upon.  Returns 0 if none.
++     */
 +    InstSeqNum checkInst(Addr PC);
 +
++    /** Records this PC/sequence number as issued. */
 +    void issued(Addr issued_PC, InstSeqNum issued_seq_num, bool is_store);
 +
++    /** Squashes for a specific thread until the given sequence number. */
 +    void squash(InstSeqNum squashed_num, unsigned tid);
 +
++    /** Resets all tables. */
 +    void clear();
 +
++    /** Debug function to dump the contents of the store list. */
++    void dump();
++
 +  private:
++    /** Calculates the index into the SSIT based on the PC. */
 +    inline int calcIndex(Addr PC)
 +    { return (PC >> offsetBits) & indexMask; }
 +
++    /** Calculates a Store Set ID based on the PC. */
 +    inline SSID calcSSID(Addr PC)
 +    { return ((PC ^ (PC >> 10)) % LFSTSize); }
 +
++    /** The Store Set ID Table. */
 +    std::vector<SSID> SSIT;
 +
++    /** Bit vector to tell if the SSIT has a valid entry. */
 +    std::vector<bool> validSSIT;
 +
++    /** Last Fetched Store Table. */
 +    std::vector<InstSeqNum> LFST;
 +
++    /** Bit vector to tell if the LFST has a valid entry. */
 +    std::vector<bool> validLFST;
 +
++    /** Map of stores that have been inserted into the store set, but
++     * not yet issued or squashed.
++     */
 +    std::map<InstSeqNum, int, ltseqnum> storeList;
 +
 +    typedef std::map<InstSeqNum, int, ltseqnum>::iterator SeqNumMapIt;
 +
++    /** Store Set ID Table size, in entries. */
 +    int SSITSize;
 +
++    /** Last Fetched Store Table size, in entries. */
 +    int LFSTSize;
 +
++    /** Mask to obtain the index. */
 +    int indexMask;
 +
 +    // HACK: Hardcoded for now.
 +    int offsetBits;
 +};
 +
 +#endif // __CPU_O3_STORE_SET_HH__
index 9101eafb934a03dfd33c2323b76d48ddffe8b502,0000000000000000000000000000000000000000..dfb1530d07bcb0bb8b2b1aa41829c8bf91b43c4f
mode 100644,000000..100644
--- /dev/null
@@@ -1,112 -1,0 +1,133 @@@
-     // Current instruction
 +/*
 + * Copyright (c) 2006 The Regents of The University of Michigan
 + * 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.
 + */
 +
 +#ifndef __CPU_O3_THREAD_STATE_HH__
 +#define __CPU_O3_THREAD_STATE_HH__
 +
 +#include "arch/faults.hh"
 +#include "arch/isa_traits.hh"
 +#include "cpu/exec_context.hh"
 +#include "cpu/thread_state.hh"
 +
 +class Event;
 +class Process;
 +
 +#if FULL_SYSTEM
 +class EndQuiesceEvent;
 +class FunctionProfile;
 +class ProfileNode;
 +#else
 +class FunctionalMemory;
 +class Process;
 +#endif
 +
 +/**
 + * Class that has various thread state, such as the status, the
 + * current instruction being processed, whether or not the thread has
 + * a trap pending or is being externally updated, the ExecContext
 + * proxy pointer, etc.  It also handles anything related to a specific
 + * thread's process, such as syscalls and checking valid addresses.
 + */
 +template <class Impl>
 +struct O3ThreadState : public ThreadState {
 +    typedef ExecContext::Status Status;
 +    typedef typename Impl::FullCPU FullCPU;
 +
++    /** Current status of the thread. */
 +    Status _status;
 +
++    /** Current instruction the thread is committing.  Only set and
++     * used for DTB faults currently.
++     */
 +    TheISA::MachInst inst;
++
 +  private:
++    /** Pointer to the CPU. */
 +    FullCPU *cpu;
 +  public:
-     bool misspeculating() { return false; }
++    /** Whether or not the thread is currently in syscall mode, and
++     * thus able to be externally updated without squashing.
++     */
 +    bool inSyscall;
 +
++    /** Whether or not the thread is currently waiting on a trap, and
++     * thus able to be externally updated without squashing.
++     */
 +    bool trapPending;
 +
 +#if FULL_SYSTEM
 +    O3ThreadState(FullCPU *_cpu, int _thread_num, FunctionalMemory *_mem)
 +        : ThreadState(-1, _thread_num, _mem),
 +          inSyscall(0), trapPending(0)
 +    { }
 +#else
 +    O3ThreadState(FullCPU *_cpu, int _thread_num, Process *_process, int _asid)
 +        : ThreadState(-1, _thread_num, NULL, _process, _asid),
 +          cpu(_cpu), inSyscall(0), trapPending(0)
 +    { }
 +
 +    O3ThreadState(FullCPU *_cpu, int _thread_num, FunctionalMemory *_mem,
 +                  int _asid)
 +        : ThreadState(-1, _thread_num, _mem, NULL, _asid),
 +          cpu(_cpu), inSyscall(0), trapPending(0)
 +    { }
 +#endif
 +
++    /** Pointer to the ExecContext of this thread.  @todo: Don't call
++     this a proxy.*/
 +    ExecContext *xcProxy;
 +
++    /** Returns a pointer to the XC of this thread. */
 +    ExecContext *getXCProxy() { return xcProxy; }
 +
++    /** Returns the status of this thread. */
 +    Status status() const { return _status; }
 +
++    /** Sets the status of this thread. */
 +    void setStatus(Status new_status) { _status = new_status; }
 +
++    /** Sets the current instruction being committed. */
 +    void setInst(TheISA::MachInst _inst) { inst = _inst; }
 +
++    /** Reads the number of instructions functionally executed and
++     * committed.
++     */
 +    Counter readFuncExeInst() { return funcExeInst; }
 +
++    /** Sets the total number of instructions functionally executed
++     * and committed.
++     */
 +    void setFuncExeInst(Counter new_val) { funcExeInst = new_val; }
 +
 +#if !FULL_SYSTEM
++    /** Handles the syscall. */
 +    void syscall(int64_t callnum) { process->syscall(callnum, xcProxy); }
 +#endif
 +};
 +
 +#endif // __CPU_O3_THREAD_STATE_HH__
index 361ef4770556c2c16f09d901deaec7ca9b12d92e,0000000000000000000000000000000000000000..7cf78dcb1cd374c0560e66d02d9f40d913565624
mode 100644,000000..100644
--- /dev/null
@@@ -1,257 -1,0 +1,293 @@@
-  * Copyright (c) 2004-2005 The Regents of The University of Michigan
 +/*
-     //Should do checks here to make sure sizes are correct (powers of 2)
++ * Copyright (c) 2004-2006 The Regents of The University of Michigan
 + * 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: Kevin Lim
 + */
 +
++#include "base/intmath.hh"
 +#include "cpu/o3/tournament_pred.hh"
 +
 +TournamentBP::TournamentBP(unsigned _localPredictorSize,
 +                           unsigned _localCtrBits,
 +                           unsigned _localHistoryTableSize,
 +                           unsigned _localHistoryBits,
 +                           unsigned _globalPredictorSize,
 +                           unsigned _globalCtrBits,
 +                           unsigned _globalHistoryBits,
 +                           unsigned _choicePredictorSize,
 +                           unsigned _choiceCtrBits,
 +                           unsigned _instShiftAmt)
 +    : localPredictorSize(_localPredictorSize),
 +      localCtrBits(_localCtrBits),
 +      localHistoryTableSize(_localHistoryTableSize),
 +      localHistoryBits(_localHistoryBits),
 +      globalPredictorSize(_globalPredictorSize),
 +      globalCtrBits(_globalCtrBits),
 +      globalHistoryBits(_globalHistoryBits),
 +      choicePredictorSize(_globalPredictorSize),
 +      choiceCtrBits(_choiceCtrBits),
 +      instShiftAmt(_instShiftAmt)
 +{
- TournamentBP::updateHistoriesTaken(unsigned local_history_idx)
++    if (!isPowerOf2(localPredictorSize)) {
++        fatal("Invalid local predictor size!\n");
++    }
 +
 +    //Setup the array of counters for the local predictor
 +    localCtrs.resize(localPredictorSize);
 +
 +    for (int i = 0; i < localPredictorSize; ++i)
 +        localCtrs[i].setBits(localCtrBits);
 +
++    if (!isPowerOf2(localHistoryTableSize)) {
++        fatal("Invalid local history table size!\n");
++    }
++
 +    //Setup the history table for the local table
 +    localHistoryTable.resize(localHistoryTableSize);
 +
 +    for (int i = 0; i < localHistoryTableSize; ++i)
 +        localHistoryTable[i] = 0;
 +
 +    // Setup the local history mask
 +    localHistoryMask = (1 << localHistoryBits) - 1;
 +
++    if (!isPowerOf2(globalPredictorSize)) {
++        fatal("Invalid global predictor size!\n");
++    }
++
 +    //Setup the array of counters for the global predictor
 +    globalCtrs.resize(globalPredictorSize);
 +
 +    for (int i = 0; i < globalPredictorSize; ++i)
 +        globalCtrs[i].setBits(globalCtrBits);
 +
 +    //Clear the global history
 +    globalHistory = 0;
 +    // Setup the global history mask
 +    globalHistoryMask = (1 << globalHistoryBits) - 1;
 +
++    if (!isPowerOf2(choicePredictorSize)) {
++        fatal("Invalid choice predictor size!\n");
++    }
++
 +    //Setup the array of counters for the choice predictor
 +    choiceCtrs.resize(choicePredictorSize);
 +
 +    for (int i = 0; i < choicePredictorSize; ++i)
 +        choiceCtrs[i].setBits(choiceCtrBits);
 +
++    // @todo: Allow for different thresholds between the predictors.
 +    threshold = (1 << (localCtrBits - 1)) - 1;
 +    threshold = threshold / 2;
 +}
 +
 +inline
 +unsigned
 +TournamentBP::calcLocHistIdx(Addr &branch_addr)
 +{
++    // Get low order bits after removing instruction offset.
 +    return (branch_addr >> instShiftAmt) & (localHistoryTableSize - 1);
 +}
 +
 +inline
 +void
-     localHistoryTable[local_history_idx] =
-         (localHistoryTable[local_history_idx] << 1) | 1;
++TournamentBP::updateGlobalHistTaken()
 +{
 +    globalHistory = (globalHistory << 1) | 1;
 +    globalHistory = globalHistory & globalHistoryMask;
- TournamentBP::updateHistoriesNotTaken(unsigned local_history_idx)
 +}
 +
 +inline
 +void
- TournamentBP::lookup(Addr &branch_addr)
++TournamentBP::updateGlobalHistNotTaken()
 +{
 +    globalHistory = (globalHistory << 1);
 +    globalHistory = globalHistory & globalHistoryMask;
++}
 +
++inline
++void
++TournamentBP::updateLocalHistTaken(unsigned local_history_idx)
++{
++    localHistoryTable[local_history_idx] =
++        (localHistoryTable[local_history_idx] << 1) | 1;
++}
++
++inline
++void
++TournamentBP::updateLocalHistNotTaken(unsigned local_history_idx)
++{
 +    localHistoryTable[local_history_idx] =
 +        (localHistoryTable[local_history_idx] << 1);
 +}
 +
 +bool
-     uint8_t local_prediction;
++TournamentBP::lookup(Addr &branch_addr, void * &bp_history)
 +{
-     uint8_t global_prediction;
-     uint8_t choice_prediction;
++    bool local_prediction;
 +    unsigned local_history_idx;
 +    unsigned local_predictor_idx;
 +
-     local_prediction = localCtrs[local_predictor_idx].read();
++    bool global_prediction;
++    bool choice_prediction;
 +
 +    //Lookup in the local predictor to get its branch prediction
 +    local_history_idx = calcLocHistIdx(branch_addr);
 +    local_predictor_idx = localHistoryTable[local_history_idx]
 +        & localHistoryMask;
-     global_prediction = globalCtrs[globalHistory].read();
++    local_prediction = localCtrs[local_predictor_idx].read() > threshold;
 +
 +    //Lookup in the global predictor to get its branch prediction
-     choice_prediction = choiceCtrs[globalHistory].read();
-     //@todo Put a threshold value in for the three predictors that can
-     // be set through the constructor (so this isn't hard coded).
-     //Also should put some of this code into functions.
-     if (choice_prediction > threshold) {
-         if (global_prediction > threshold) {
-             updateHistoriesTaken(local_history_idx);
-             assert(globalHistory < globalPredictorSize &&
-                    local_history_idx < localPredictorSize);
-             globalCtrs[globalHistory].increment();
-             localCtrs[local_history_idx].increment();
++    global_prediction = globalCtrs[globalHistory].read() > threshold;
 +
 +    //Lookup in the choice predictor to see which one to use
-             updateHistoriesNotTaken(local_history_idx);
-             assert(globalHistory < globalPredictorSize &&
-                    local_history_idx < localPredictorSize);
-             globalCtrs[globalHistory].decrement();
-             localCtrs[local_history_idx].decrement();
++    choice_prediction = choiceCtrs[globalHistory].read() > threshold;
++
++    // Create BPHistory and pass it back to be recorded.
++    BPHistory *history = new BPHistory;
++    history->globalHistory = globalHistory;
++    history->localPredTaken = local_prediction;
++    history->globalPredTaken = global_prediction;
++    history->globalUsed = choice_prediction;
++    bp_history = (void *)history;
++
++    assert(globalHistory < globalPredictorSize &&
++           local_history_idx < localPredictorSize);
++
++    // Commented code is for doing speculative update of counters and
++    // all histories.
++    if (choice_prediction) {
++        if (global_prediction) {
++//            updateHistoriesTaken(local_history_idx);
++//            globalCtrs[globalHistory].increment();
++//            localCtrs[local_history_idx].increment();
++            updateGlobalHistTaken();
 +            return true;
 +        } else {
-         if (local_prediction > threshold) {
-             updateHistoriesTaken(local_history_idx);
-             assert(globalHistory < globalPredictorSize &&
-                    local_history_idx < localPredictorSize);
-             globalCtrs[globalHistory].increment();
-             localCtrs[local_history_idx].increment();
++//            updateHistoriesNotTaken(local_history_idx);
++//            globalCtrs[globalHistory].decrement();
++//            localCtrs[local_history_idx].decrement();
++            updateGlobalHistNotTaken();
 +            return false;
 +        }
 +    } else {
-             updateHistoriesNotTaken(local_history_idx);
-             assert(globalHistory < globalPredictorSize &&
-                    local_history_idx < localPredictorSize);
-             globalCtrs[globalHistory].decrement();
-             localCtrs[local_history_idx].decrement();
++        if (local_prediction) {
++//            updateHistoriesTaken(local_history_idx);
++//            globalCtrs[globalHistory].increment();
++//            localCtrs[local_history_idx].increment();
++            updateGlobalHistTaken();
 +            return true;
 +        } else {
- // Update the branch predictor if it predicted a branch wrong.
++//            updateHistoriesNotTaken(local_history_idx);
++//            globalCtrs[globalHistory].decrement();
++//            localCtrs[local_history_idx].decrement();
++            updateGlobalHistNotTaken();
 +            return false;
 +        }
 +    }
 +}
 +
- TournamentBP::update(Addr &branch_addr, unsigned correct_gh, bool taken)
 +void
-     uint8_t local_prediction;
++TournamentBP::uncondBr(void * &bp_history)
 +{
++    // Create BPHistory and pass it back to be recorded.
++    BPHistory *history = new BPHistory;
++    history->globalHistory = globalHistory;
++    history->localPredTaken = true;
++    history->globalPredTaken = true;
++    bp_history = static_cast<void *>(history);
++
++    updateGlobalHistTaken();
++}
 +
-     bool local_pred_taken;
++void
++TournamentBP::update(Addr &branch_addr, bool taken, void *bp_history)
++{
 +    unsigned local_history_idx;
 +    unsigned local_predictor_idx;
-     uint8_t global_prediction;
-     bool global_pred_taken;
-     // Load the correct global history into the register.
-     globalHistory = correct_gh;
-     // Get the local predictor's current prediction, remove the incorrect
-     // update, and update the local predictor
++    unsigned local_predictor_hist;
 +
-     local_predictor_idx = localHistoryTable[local_history_idx];
-     local_predictor_idx = (local_predictor_idx >> 1) & localHistoryMask;
-     local_prediction = localCtrs[local_predictor_idx].read();
-     local_pred_taken = local_prediction > threshold;
-     //Get the global predictor's current prediction, and update the
-     //global predictor
-     global_prediction = globalCtrs[globalHistory].read();
-     global_pred_taken = global_prediction > threshold;
-     //Update the choice predictor to tell it which one was correct
-     if (local_pred_taken != global_pred_taken) {
-         //If the local prediction matches the actual outcome, decerement
-         //the counter.  Otherwise increment the counter.
-         if (local_pred_taken == taken) {
-             choiceCtrs[globalHistory].decrement();
-         } else {
-             choiceCtrs[globalHistory].increment();
++    // Get the local predictor's current prediction
 +    local_history_idx = calcLocHistIdx(branch_addr);
-     if (taken) {
-         assert(globalHistory < globalPredictorSize &&
-                local_predictor_idx < localPredictorSize);
++    local_predictor_hist = localHistoryTable[local_history_idx];
++    local_predictor_idx = local_predictor_hist & localHistoryMask;
++
++    // Update the choice predictor to tell it which one was correct if
++    // there was a prediction.
++    if (bp_history) {
++        BPHistory *history = static_cast<BPHistory *>(bp_history);
++        if (history->localPredTaken != history->globalPredTaken) {
++            // If the local prediction matches the actual outcome,
++            // decerement the counter.  Otherwise increment the
++            // counter.
++            if (history->localPredTaken == taken) {
++                choiceCtrs[globalHistory].decrement();
++            } else if (history->globalPredTaken == taken){
++                choiceCtrs[globalHistory].increment();
++            }
 +        }
++
++        // We're done with this history, now delete it.
++        delete history;
 +    }
 +
-         globalHistory = (globalHistory << 1) | 1;
-         globalHistory = globalHistory & globalHistoryMask;
-         localHistoryTable[local_history_idx] |= 1;
++    assert(globalHistory < globalPredictorSize &&
++           local_predictor_idx < localPredictorSize);
 +
++    // Update the counters and local history with the proper
++    // resolution of the branch.  Global history is updated
++    // speculatively and restored upon squash() calls, so it does not
++    // need to be updated.
++    if (taken) {
 +        localCtrs[local_predictor_idx].increment();
 +        globalCtrs[globalHistory].increment();
 +
-         assert(globalHistory < globalPredictorSize &&
-                local_predictor_idx < localPredictorSize);
++        updateLocalHistTaken(local_history_idx);
 +    } else {
-         globalHistory = (globalHistory << 1);
-         globalHistory = globalHistory & globalHistoryMask;
-         localHistoryTable[local_history_idx] &= ~1;
 +        localCtrs[local_predictor_idx].decrement();
 +        globalCtrs[globalHistory].decrement();
 +
++        updateLocalHistNotTaken(local_history_idx);
 +    }
 +}
++
++void
++TournamentBP::squash(void *bp_history)
++{
++    BPHistory *history = static_cast<BPHistory *>(bp_history);
++
++    // Restore global history to state prior to this branch.
++    globalHistory = history->globalHistory;
++
++    // Delete this BPHistory now that we're done with it.
++    delete history;
++}
++
++#ifdef DEBUG
++int
++TournamentBP::BPHistory::newCount = 0;
++#endif
index e1660009099ab27d6f9ee143776627ca6eebaa8e,0000000000000000000000000000000000000000..92402adc6dc8e5ca8cb6b66bd31adff2fad696dc
mode 100644,000000..100644
--- /dev/null
@@@ -1,146 -1,0 +1,218 @@@
-  * Copyright (c) 2004-2005 The Regents of The University of Michigan
 +/*
-      * a true/false value as to whether it is taken.
++ * Copyright (c) 2004-2006 The Regents of The University of Michigan
 + * 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: Kevin Lim
 + */
 +
 +#ifndef __CPU_O3_TOURNAMENT_PRED_HH__
 +#define __CPU_O3_TOURNAMENT_PRED_HH__
 +
 +// For Addr type.
 +#include "arch/isa_traits.hh"
 +#include "cpu/o3/sat_counter.hh"
 +#include <vector>
 +
++/**
++ * Implements a tournament branch predictor, hopefully identical to the one
++ * used in the 21264.  It has a local predictor, which uses a local history
++ * table to index into a table of counters, and a global predictor, which
++ * uses a global history to index into a table of counters.  A choice
++ * predictor chooses between the two.  Only the global history register
++ * is speculatively updated, the rest are updated upon branches committing
++ * or misspeculating.
++ */
 +class TournamentBP
 +{
 +  public:
 +    /**
 +     * Default branch predictor constructor.
 +     */
 +    TournamentBP(unsigned localPredictorSize,
 +                 unsigned localCtrBits,
 +                 unsigned localHistoryTableSize,
 +                 unsigned localHistoryBits,
 +                 unsigned globalPredictorSize,
 +                 unsigned globalHistoryBits,
 +                 unsigned globalCtrBits,
 +                 unsigned choicePredictorSize,
 +                 unsigned choiceCtrBits,
 +                 unsigned instShiftAmt);
 +
 +    /**
 +     * Looks up the given address in the branch predictor and returns
-     bool lookup(Addr &branch_addr);
++     * a true/false value as to whether it is taken.  Also creates a
++     * BPHistory object to store any state it will need on squash/update.
 +     * @param branch_addr The address of the branch to look up.
++     * @param bp_history Pointer that will be set to the BPHistory object.
 +     * @return Whether or not the branch is taken.
 +     */
-     void update(Addr &branch_addr, unsigned global_history, bool taken);
++    bool lookup(Addr &branch_addr, void * &bp_history);
++
++    /**
++     * Records that there was an unconditional branch, and modifies
++     * the bp history to point to an object that has the previous
++     * global history stored in it.
++     * @param bp_history Pointer that will be set to the BPHistory object.
++     */
++    void uncondBr(void * &bp_history);
 +
 +    /**
 +     * Updates the branch predictor with the actual result of a branch.
 +     * @param branch_addr The address of the branch to update.
 +     * @param taken Whether or not the branch was taken.
++     * @param bp_history Pointer to the BPHistory object that was created
++     * when the branch was predicted.
++     */
++    void update(Addr &branch_addr, bool taken, void *bp_history);
++
++    /**
++     * Restores the global branch history on a squash.
++     * @param bp_history Pointer to the BPHistory object that has the
++     * previous global branch history in it.
 +     */
++    void squash(void *bp_history);
 +
++    /** Returns the global history. */
 +    inline unsigned readGlobalHist() { return globalHistory; }
 +
 +  private:
-     inline void updateHistoriesTaken(unsigned local_history_idx);
++    /**
++     * Returns if the branch should be taken or not, given a counter
++     * value.
++     * @param count The counter value.
++     */
 +    inline bool getPrediction(uint8_t &count);
 +
++    /**
++     * Returns the local history index, given a branch address.
++     * @param branch_addr The branch's PC address.
++     */
 +    inline unsigned calcLocHistIdx(Addr &branch_addr);
 +
-     inline void updateHistoriesNotTaken(unsigned local_history_idx);
++    /** Updates global history as taken. */
++    inline void updateGlobalHistTaken();
 +
++    /** Updates global history as not taken. */
++    inline void updateGlobalHistNotTaken();
++
++    /**
++     * Updates local histories as taken.
++     * @param local_history_idx The local history table entry that
++     * will be updated.
++     */
++    inline void updateLocalHistTaken(unsigned local_history_idx);
++
++    /**
++     * Updates local histories as not taken.
++     * @param local_history_idx The local history table entry that
++     * will be updated.
++     */
++    inline void updateLocalHistNotTaken(unsigned local_history_idx);
++
++    /**
++     * The branch history information that is created upon predicting
++     * a branch.  It will be passed back upon updating and squashing,
++     * when the BP can use this information to update/restore its
++     * state properly.
++     */
++    struct BPHistory {
++#ifdef DEBUG
++        BPHistory()
++        { newCount++; }
++        ~BPHistory()
++        { newCount--; }
++
++        static int newCount;
++#endif
++        unsigned globalHistory;
++        bool localPredTaken;
++        bool globalPredTaken;
++        bool globalUsed;
++    };
 +
 +    /** Local counters. */
 +    std::vector<SatCounter> localCtrs;
 +
 +    /** Size of the local predictor. */
 +    unsigned localPredictorSize;
 +
 +    /** Number of bits of the local predictor's counters. */
 +    unsigned localCtrBits;
 +
 +    /** Array of local history table entries. */
 +    std::vector<unsigned> localHistoryTable;
 +
 +    /** Size of the local history table. */
 +    unsigned localHistoryTableSize;
 +
 +    /** Number of bits for each entry of the local history table.
 +     *  @todo Doesn't this come from the size of the local predictor?
 +     */
 +    unsigned localHistoryBits;
 +
 +    /** Mask to get the proper local history. */
 +    unsigned localHistoryMask;
 +
 +    /** Array of counters that make up the global predictor. */
 +    std::vector<SatCounter> globalCtrs;
 +
 +    /** Size of the global predictor. */
 +    unsigned globalPredictorSize;
 +
 +    /** Number of bits of the global predictor's counters. */
 +    unsigned globalCtrBits;
 +
 +    /** Global history register. */
 +    unsigned globalHistory;
 +
 +    /** Number of bits for the global history. */
 +    unsigned globalHistoryBits;
 +
 +    /** Mask to get the proper global history. */
 +    unsigned globalHistoryMask;
 +
 +    /** Array of counters that make up the choice predictor. */
 +    std::vector<SatCounter> choiceCtrs;
 +
 +    /** Size of the choice predictor (identical to the global predictor). */
 +    unsigned choicePredictorSize;
 +
 +    /** Number of bits of the choice predictor's counters. */
 +    unsigned choiceCtrBits;
 +
 +    /** Number of bits to shift the instruction over to get rid of the word
 +     *  offset.
 +     */
 +    unsigned instShiftAmt;
 +
 +    /** Threshold for the counter value; above the threshold is taken,
 +     *  equal to or below the threshold is not taken.
 +     */
 +    unsigned threshold;
 +};
 +
 +#endif // __CPU_O3_TOURNAMENT_PRED_HH__
index 64aa49c7149fe6dcd62e43f9fd1a7cd130f67a93,0000000000000000000000000000000000000000..1ab7a4c299389a59bbf5af4516031891aae73b9f
mode 100644,000000..100644
--- /dev/null
@@@ -1,830 -1,0 +1,861 @@@
++/*
++ * Copyright (c) 2006 The Regents of The University of Michigan
++ * 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.
++ */
 +
 +#include <string>
 +
 +#include "cpu/checker/cpu.hh"
 +#include "cpu/inst_seq.hh"
 +#include "cpu/ozone/cpu.hh"
 +#include "cpu/ozone/ozone_impl.hh"
 +#include "cpu/ozone/simple_impl.hh"
 +#include "cpu/ozone/simple_params.hh"
 +#include "mem/cache/base_cache.hh"
 +#include "sim/builder.hh"
 +#include "sim/process.hh"
 +#include "sim/sim_object.hh"
 +
 +class DerivOzoneCPU : public OzoneCPU<OzoneImpl>
 +{
 +  public:
 +    DerivOzoneCPU(SimpleParams *p)
 +        : OzoneCPU<OzoneImpl>(p)
 +    { }
 +};
 +
 +class SimpleOzoneCPU : public OzoneCPU<SimpleImpl>
 +{
 +  public:
 +    SimpleOzoneCPU(SimpleParams *p)
 +        : OzoneCPU<SimpleImpl>(p)
 +    { }
 +};
 +
 +
 +////////////////////////////////////////////////////////////////////////
 +//
 +//  OzoneCPU Simulation Object
 +//
 +
 +BEGIN_DECLARE_SIM_OBJECT_PARAMS(DerivOzoneCPU)
 +
 +    Param<int> clock;
 +    Param<int> numThreads;
 +
 +#if FULL_SYSTEM
 +SimObjectParam<System *> system;
 +Param<int> cpu_id;
 +SimObjectParam<AlphaITB *> itb;
 +SimObjectParam<AlphaDTB *> dtb;
 +#else
 +SimObjectVectorParam<Process *> workload;
 +//SimObjectParam<PageTable *> page_table;
 +#endif // FULL_SYSTEM
 +
 +SimObjectParam<FunctionalMemory *> mem;
 +
 +SimObjectParam<BaseCPU *> checker;
 +
 +Param<Counter> max_insts_any_thread;
 +Param<Counter> max_insts_all_threads;
 +Param<Counter> max_loads_any_thread;
 +Param<Counter> max_loads_all_threads;
 +
 +SimObjectParam<BaseCache *> icache;
 +SimObjectParam<BaseCache *> dcache;
 +
 +Param<unsigned> cachePorts;
 +Param<unsigned> width;
 +Param<unsigned> frontEndWidth;
 +Param<unsigned> backEndWidth;
 +Param<unsigned> backEndSquashLatency;
 +Param<unsigned> backEndLatency;
 +Param<unsigned> maxInstBufferSize;
 +Param<unsigned> numPhysicalRegs;
 +Param<unsigned> maxOutstandingMemOps;
 +
 +Param<unsigned> decodeToFetchDelay;
 +Param<unsigned> renameToFetchDelay;
 +Param<unsigned> iewToFetchDelay;
 +Param<unsigned> commitToFetchDelay;
 +Param<unsigned> fetchWidth;
 +
 +Param<unsigned> renameToDecodeDelay;
 +Param<unsigned> iewToDecodeDelay;
 +Param<unsigned> commitToDecodeDelay;
 +Param<unsigned> fetchToDecodeDelay;
 +Param<unsigned> decodeWidth;
 +
 +Param<unsigned> iewToRenameDelay;
 +Param<unsigned> commitToRenameDelay;
 +Param<unsigned> decodeToRenameDelay;
 +Param<unsigned> renameWidth;
 +
 +Param<unsigned> commitToIEWDelay;
 +Param<unsigned> renameToIEWDelay;
 +Param<unsigned> issueToExecuteDelay;
 +Param<unsigned> issueWidth;
 +Param<unsigned> executeWidth;
 +Param<unsigned> executeIntWidth;
 +Param<unsigned> executeFloatWidth;
 +Param<unsigned> executeBranchWidth;
 +Param<unsigned> executeMemoryWidth;
 +
 +Param<unsigned> iewToCommitDelay;
 +Param<unsigned> renameToROBDelay;
 +Param<unsigned> commitWidth;
 +Param<unsigned> squashWidth;
 +
++Param<std::string> predType;
 +Param<unsigned> localPredictorSize;
 +Param<unsigned> localCtrBits;
 +Param<unsigned> localHistoryTableSize;
 +Param<unsigned> localHistoryBits;
 +Param<unsigned> globalPredictorSize;
 +Param<unsigned> globalCtrBits;
 +Param<unsigned> globalHistoryBits;
 +Param<unsigned> choicePredictorSize;
 +Param<unsigned> choiceCtrBits;
 +
 +Param<unsigned> BTBEntries;
 +Param<unsigned> BTBTagSize;
 +
 +Param<unsigned> RASSize;
 +
 +Param<unsigned> LQEntries;
 +Param<unsigned> SQEntries;
 +Param<unsigned> LFSTSize;
 +Param<unsigned> SSITSize;
 +
 +Param<unsigned> numPhysIntRegs;
 +Param<unsigned> numPhysFloatRegs;
 +Param<unsigned> numIQEntries;
 +Param<unsigned> numROBEntries;
 +
 +Param<bool> decoupledFrontEnd;
 +Param<int> dispatchWidth;
 +Param<int> wbWidth;
 +
 +Param<unsigned> smtNumFetchingThreads;
 +Param<std::string>   smtFetchPolicy;
 +Param<std::string>   smtLSQPolicy;
 +Param<unsigned> smtLSQThreshold;
 +Param<std::string>   smtIQPolicy;
 +Param<unsigned> smtIQThreshold;
 +Param<std::string>   smtROBPolicy;
 +Param<unsigned> smtROBThreshold;
 +Param<std::string>   smtCommitPolicy;
 +
 +Param<unsigned> instShiftAmt;
 +
 +Param<bool> defer_registration;
 +
 +Param<bool> function_trace;
 +Param<Tick> function_trace_start;
 +
 +END_DECLARE_SIM_OBJECT_PARAMS(DerivOzoneCPU)
 +
 +BEGIN_INIT_SIM_OBJECT_PARAMS(DerivOzoneCPU)
 +
 +    INIT_PARAM(clock, "clock speed"),
 +    INIT_PARAM(numThreads, "number of HW thread contexts"),
 +
 +#if FULL_SYSTEM
 +    INIT_PARAM(system, "System object"),
 +    INIT_PARAM(cpu_id, "processor ID"),
 +    INIT_PARAM(itb, "Instruction translation buffer"),
 +    INIT_PARAM(dtb, "Data translation buffer"),
 +#else
 +    INIT_PARAM(workload, "Processes to run"),
 +//    INIT_PARAM(page_table, "Page table"),
 +#endif // FULL_SYSTEM
 +
 +    INIT_PARAM_DFLT(mem, "Memory", NULL),
 +
 +    INIT_PARAM_DFLT(checker, "Checker CPU", NULL),
 +
 +    INIT_PARAM_DFLT(max_insts_any_thread,
 +                    "Terminate when any thread reaches this inst count",
 +                    0),
 +    INIT_PARAM_DFLT(max_insts_all_threads,
 +                    "Terminate when all threads have reached"
 +                    "this inst count",
 +                    0),
 +    INIT_PARAM_DFLT(max_loads_any_thread,
 +                    "Terminate when any thread reaches this load count",
 +                    0),
 +    INIT_PARAM_DFLT(max_loads_all_threads,
 +                    "Terminate when all threads have reached this load"
 +                    "count",
 +                    0),
 +
 +    INIT_PARAM_DFLT(icache, "L1 instruction cache", NULL),
 +    INIT_PARAM_DFLT(dcache, "L1 data cache", NULL),
 +
 +    INIT_PARAM_DFLT(cachePorts, "Cache Ports", 200),
 +    INIT_PARAM_DFLT(width, "Width", 1),
 +    INIT_PARAM_DFLT(frontEndWidth, "Front end width", 1),
 +    INIT_PARAM_DFLT(backEndWidth, "Back end width", 1),
 +    INIT_PARAM_DFLT(backEndSquashLatency, "Back end squash latency", 1),
 +    INIT_PARAM_DFLT(backEndLatency, "Back end latency", 1),
 +    INIT_PARAM_DFLT(maxInstBufferSize, "Maximum instruction buffer size", 16),
 +    INIT_PARAM(numPhysicalRegs, "Number of physical registers"),
 +    INIT_PARAM_DFLT(maxOutstandingMemOps, "Maximum outstanding memory operations", 4),
 +
 +    INIT_PARAM(decodeToFetchDelay, "Decode to fetch delay"),
 +    INIT_PARAM(renameToFetchDelay, "Rename to fetch delay"),
 +    INIT_PARAM(iewToFetchDelay, "Issue/Execute/Writeback to fetch"
 +               "delay"),
 +    INIT_PARAM(commitToFetchDelay, "Commit to fetch delay"),
 +    INIT_PARAM(fetchWidth, "Fetch width"),
 +    INIT_PARAM(renameToDecodeDelay, "Rename to decode delay"),
 +    INIT_PARAM(iewToDecodeDelay, "Issue/Execute/Writeback to decode"
 +               "delay"),
 +    INIT_PARAM(commitToDecodeDelay, "Commit to decode delay"),
 +    INIT_PARAM(fetchToDecodeDelay, "Fetch to decode delay"),
 +    INIT_PARAM(decodeWidth, "Decode width"),
 +
 +    INIT_PARAM(iewToRenameDelay, "Issue/Execute/Writeback to rename"
 +               "delay"),
 +    INIT_PARAM(commitToRenameDelay, "Commit to rename delay"),
 +    INIT_PARAM(decodeToRenameDelay, "Decode to rename delay"),
 +    INIT_PARAM(renameWidth, "Rename width"),
 +
 +    INIT_PARAM(commitToIEWDelay, "Commit to "
 +               "Issue/Execute/Writeback delay"),
 +    INIT_PARAM(renameToIEWDelay, "Rename to "
 +               "Issue/Execute/Writeback delay"),
 +    INIT_PARAM(issueToExecuteDelay, "Issue to execute delay (internal"
 +               "to the IEW stage)"),
 +    INIT_PARAM(issueWidth, "Issue width"),
 +    INIT_PARAM(executeWidth, "Execute width"),
 +    INIT_PARAM(executeIntWidth, "Integer execute width"),
 +    INIT_PARAM(executeFloatWidth, "Floating point execute width"),
 +    INIT_PARAM(executeBranchWidth, "Branch execute width"),
 +    INIT_PARAM(executeMemoryWidth, "Memory execute width"),
 +
 +    INIT_PARAM(iewToCommitDelay, "Issue/Execute/Writeback to commit "
 +               "delay"),
 +    INIT_PARAM(renameToROBDelay, "Rename to reorder buffer delay"),
 +    INIT_PARAM(commitWidth, "Commit width"),
 +    INIT_PARAM(squashWidth, "Squash width"),
 +
++    INIT_PARAM(predType, "Type of branch predictor ('local', 'tournament')"),
 +    INIT_PARAM(localPredictorSize, "Size of local predictor"),
 +    INIT_PARAM(localCtrBits, "Bits per counter"),
 +    INIT_PARAM(localHistoryTableSize, "Size of local history table"),
 +    INIT_PARAM(localHistoryBits, "Bits for the local history"),
 +    INIT_PARAM(globalPredictorSize, "Size of global predictor"),
 +    INIT_PARAM(globalCtrBits, "Bits per counter"),
 +    INIT_PARAM(globalHistoryBits, "Bits of history"),
 +    INIT_PARAM(choicePredictorSize, "Size of choice predictor"),
 +    INIT_PARAM(choiceCtrBits, "Bits of choice counters"),
 +
 +    INIT_PARAM(BTBEntries, "Number of BTB entries"),
 +    INIT_PARAM(BTBTagSize, "Size of the BTB tags, in bits"),
 +
 +    INIT_PARAM(RASSize, "RAS size"),
 +
 +    INIT_PARAM(LQEntries, "Number of load queue entries"),
 +    INIT_PARAM(SQEntries, "Number of store queue entries"),
 +    INIT_PARAM(LFSTSize, "Last fetched store table size"),
 +    INIT_PARAM(SSITSize, "Store set ID table size"),
 +
 +    INIT_PARAM(numPhysIntRegs, "Number of physical integer registers"),
 +    INIT_PARAM(numPhysFloatRegs, "Number of physical floating point "
 +               "registers"),
 +    INIT_PARAM(numIQEntries, "Number of instruction queue entries"),
 +    INIT_PARAM(numROBEntries, "Number of reorder buffer entries"),
 +
 +    INIT_PARAM_DFLT(decoupledFrontEnd, "Decoupled front end", true),
 +    INIT_PARAM_DFLT(dispatchWidth, "Dispatch width", 0),
 +    INIT_PARAM_DFLT(wbWidth, "Writeback width", 0),
 +
 +    INIT_PARAM_DFLT(smtNumFetchingThreads, "SMT Number of Fetching Threads", 1),
 +    INIT_PARAM_DFLT(smtFetchPolicy, "SMT Fetch Policy", "SingleThread"),
 +    INIT_PARAM_DFLT(smtLSQPolicy,   "SMT LSQ Sharing Policy",    "Partitioned"),
 +    INIT_PARAM_DFLT(smtLSQThreshold,"SMT LSQ Threshold", 100),
 +    INIT_PARAM_DFLT(smtIQPolicy,    "SMT IQ Policy",    "Partitioned"),
 +    INIT_PARAM_DFLT(smtIQThreshold, "SMT IQ Threshold", 100),
 +    INIT_PARAM_DFLT(smtROBPolicy,   "SMT ROB Sharing Policy", "Partitioned"),
 +    INIT_PARAM_DFLT(smtROBThreshold,"SMT ROB Threshold", 100),
 +    INIT_PARAM_DFLT(smtCommitPolicy,"SMT Commit Fetch Policy", "RoundRobin"),
 +
 +    INIT_PARAM(instShiftAmt, "Number of bits to shift instructions by"),
 +    INIT_PARAM(defer_registration, "defer system registration (for sampling)"),
 +
 +    INIT_PARAM(function_trace, "Enable function trace"),
 +    INIT_PARAM(function_trace_start, "Cycle to start function trace")
 +
 +END_INIT_SIM_OBJECT_PARAMS(DerivOzoneCPU)
 +
 +CREATE_SIM_OBJECT(DerivOzoneCPU)
 +{
 +    DerivOzoneCPU *cpu;
 +
 +#if FULL_SYSTEM
 +    // Full-system only supports a single thread for the moment.
 +    int actual_num_threads = 1;
 +#else
 +    // In non-full-system mode, we infer the number of threads from
 +    // the workload if it's not explicitly specified.
 +    int actual_num_threads =
 +        numThreads.isValid() ? numThreads : workload.size();
 +
 +    if (workload.size() == 0) {
 +        fatal("Must specify at least one workload!");
 +    }
 +
 +#endif
 +
 +    SimpleParams *params = new SimpleParams;
 +
 +    params->clock = clock;
 +
 +    params->name = getInstanceName();
 +    params->numberOfThreads = actual_num_threads;
 +
 +#if FULL_SYSTEM
 +    params->system = system;
 +    params->cpu_id = cpu_id;
 +    params->itb = itb;
 +    params->dtb = dtb;
 +#else
 +    params->workload = workload;
 +//    params->pTable = page_table;
 +#endif // FULL_SYSTEM
 +
 +    params->mem = mem;
 +    params->checker = checker;
 +    params->max_insts_any_thread = max_insts_any_thread;
 +    params->max_insts_all_threads = max_insts_all_threads;
 +    params->max_loads_any_thread = max_loads_any_thread;
 +    params->max_loads_all_threads = max_loads_all_threads;
 +
 +    //
 +    // Caches
 +    //
 +    params->icacheInterface = icache ? icache->getInterface() : NULL;
 +    params->dcacheInterface = dcache ? dcache->getInterface() : NULL;
 +    params->cachePorts = cachePorts;
 +
 +    params->width = width;
 +    params->frontEndWidth = frontEndWidth;
 +    params->backEndWidth = backEndWidth;
 +    params->backEndSquashLatency = backEndSquashLatency;
 +    params->backEndLatency = backEndLatency;
 +    params->maxInstBufferSize = maxInstBufferSize;
 +    params->numPhysicalRegs = numPhysIntRegs + numPhysFloatRegs;
 +    params->maxOutstandingMemOps = maxOutstandingMemOps;
 +
 +    params->decodeToFetchDelay = decodeToFetchDelay;
 +    params->renameToFetchDelay = renameToFetchDelay;
 +    params->iewToFetchDelay = iewToFetchDelay;
 +    params->commitToFetchDelay = commitToFetchDelay;
 +    params->fetchWidth = fetchWidth;
 +
 +    params->renameToDecodeDelay = renameToDecodeDelay;
 +    params->iewToDecodeDelay = iewToDecodeDelay;
 +    params->commitToDecodeDelay = commitToDecodeDelay;
 +    params->fetchToDecodeDelay = fetchToDecodeDelay;
 +    params->decodeWidth = decodeWidth;
 +
 +    params->iewToRenameDelay = iewToRenameDelay;
 +    params->commitToRenameDelay = commitToRenameDelay;
 +    params->decodeToRenameDelay = decodeToRenameDelay;
 +    params->renameWidth = renameWidth;
 +
 +    params->commitToIEWDelay = commitToIEWDelay;
 +    params->renameToIEWDelay = renameToIEWDelay;
 +    params->issueToExecuteDelay = issueToExecuteDelay;
 +    params->issueWidth = issueWidth;
 +    params->executeWidth = executeWidth;
 +    params->executeIntWidth = executeIntWidth;
 +    params->executeFloatWidth = executeFloatWidth;
 +    params->executeBranchWidth = executeBranchWidth;
 +    params->executeMemoryWidth = executeMemoryWidth;
 +
 +    params->iewToCommitDelay = iewToCommitDelay;
 +    params->renameToROBDelay = renameToROBDelay;
 +    params->commitWidth = commitWidth;
 +    params->squashWidth = squashWidth;
 +
++    params->predType = predType;
 +    params->localPredictorSize = localPredictorSize;
 +    params->localCtrBits = localCtrBits;
 +    params->localHistoryTableSize = localHistoryTableSize;
 +    params->localHistoryBits = localHistoryBits;
 +    params->globalPredictorSize = globalPredictorSize;
 +    params->globalCtrBits = globalCtrBits;
 +    params->globalHistoryBits = globalHistoryBits;
 +    params->choicePredictorSize = choicePredictorSize;
 +    params->choiceCtrBits = choiceCtrBits;
 +
 +    params->BTBEntries = BTBEntries;
 +    params->BTBTagSize = BTBTagSize;
 +
 +    params->RASSize = RASSize;
 +
 +    params->LQEntries = LQEntries;
 +    params->SQEntries = SQEntries;
 +
 +    params->SSITSize = SSITSize;
 +    params->LFSTSize = LFSTSize;
 +
 +    params->numPhysIntRegs = numPhysIntRegs;
 +    params->numPhysFloatRegs = numPhysFloatRegs;
 +    params->numIQEntries = numIQEntries;
 +    params->numROBEntries = numROBEntries;
 +
 +    params->decoupledFrontEnd = decoupledFrontEnd;
 +    params->dispatchWidth = dispatchWidth;
 +    params->wbWidth = wbWidth;
 +
 +    params->smtNumFetchingThreads = smtNumFetchingThreads;
 +    params->smtFetchPolicy = smtFetchPolicy;
 +    params->smtIQPolicy    = smtIQPolicy;
 +    params->smtLSQPolicy    = smtLSQPolicy;
 +    params->smtLSQThreshold = smtLSQThreshold;
 +    params->smtROBPolicy   = smtROBPolicy;
 +    params->smtROBThreshold = smtROBThreshold;
 +    params->smtCommitPolicy = smtCommitPolicy;
 +
 +    params->instShiftAmt = 2;
 +
 +    params->deferRegistration = defer_registration;
 +
 +    params->functionTrace = function_trace;
 +    params->functionTraceStart = function_trace_start;
 +
 +    cpu = new DerivOzoneCPU(params);
 +
 +    return cpu;
 +}
 +
 +REGISTER_SIM_OBJECT("DerivOzoneCPU", DerivOzoneCPU)
 +
 +
 +
 +////////////////////////////////////////////////////////////////////////
 +//
 +//  OzoneCPU Simulation Object
 +//
 +
 +BEGIN_DECLARE_SIM_OBJECT_PARAMS(SimpleOzoneCPU)
 +
 +    Param<int> clock;
 +    Param<int> numThreads;
 +
 +#if FULL_SYSTEM
 +SimObjectParam<System *> system;
 +Param<int> cpu_id;
 +SimObjectParam<AlphaITB *> itb;
 +SimObjectParam<AlphaDTB *> dtb;
 +#else
 +SimObjectVectorParam<Process *> workload;
 +//SimObjectParam<PageTable *> page_table;
 +#endif // FULL_SYSTEM
 +
 +SimObjectParam<FunctionalMemory *> mem;
 +
 +SimObjectParam<BaseCPU *> checker;
 +
 +Param<Counter> max_insts_any_thread;
 +Param<Counter> max_insts_all_threads;
 +Param<Counter> max_loads_any_thread;
 +Param<Counter> max_loads_all_threads;
 +
 +SimObjectParam<BaseCache *> icache;
 +SimObjectParam<BaseCache *> dcache;
 +
 +Param<unsigned> cachePorts;
 +Param<unsigned> width;
 +Param<unsigned> frontEndWidth;
 +Param<unsigned> backEndWidth;
 +Param<unsigned> backEndSquashLatency;
 +Param<unsigned> backEndLatency;
 +Param<unsigned> maxInstBufferSize;
 +Param<unsigned> numPhysicalRegs;
 +
 +Param<unsigned> decodeToFetchDelay;
 +Param<unsigned> renameToFetchDelay;
 +Param<unsigned> iewToFetchDelay;
 +Param<unsigned> commitToFetchDelay;
 +Param<unsigned> fetchWidth;
 +
 +Param<unsigned> renameToDecodeDelay;
 +Param<unsigned> iewToDecodeDelay;
 +Param<unsigned> commitToDecodeDelay;
 +Param<unsigned> fetchToDecodeDelay;
 +Param<unsigned> decodeWidth;
 +
 +Param<unsigned> iewToRenameDelay;
 +Param<unsigned> commitToRenameDelay;
 +Param<unsigned> decodeToRenameDelay;
 +Param<unsigned> renameWidth;
 +
 +Param<unsigned> commitToIEWDelay;
 +Param<unsigned> renameToIEWDelay;
 +Param<unsigned> issueToExecuteDelay;
 +Param<unsigned> issueWidth;
 +Param<unsigned> executeWidth;
 +Param<unsigned> executeIntWidth;
 +Param<unsigned> executeFloatWidth;
 +Param<unsigned> executeBranchWidth;
 +Param<unsigned> executeMemoryWidth;
 +
 +Param<unsigned> iewToCommitDelay;
 +Param<unsigned> renameToROBDelay;
 +Param<unsigned> commitWidth;
 +Param<unsigned> squashWidth;
 +
++Param<std::string> predType;
 +Param<unsigned> localPredictorSize;
 +Param<unsigned> localCtrBits;
 +Param<unsigned> localHistoryTableSize;
 +Param<unsigned> localHistoryBits;
 +Param<unsigned> globalPredictorSize;
 +Param<unsigned> globalCtrBits;
 +Param<unsigned> globalHistoryBits;
 +Param<unsigned> choicePredictorSize;
 +Param<unsigned> choiceCtrBits;
 +
 +Param<unsigned> BTBEntries;
 +Param<unsigned> BTBTagSize;
 +
 +Param<unsigned> RASSize;
 +
 +Param<unsigned> LQEntries;
 +Param<unsigned> SQEntries;
 +Param<unsigned> LFSTSize;
 +Param<unsigned> SSITSize;
 +
 +Param<unsigned> numPhysIntRegs;
 +Param<unsigned> numPhysFloatRegs;
 +Param<unsigned> numIQEntries;
 +Param<unsigned> numROBEntries;
 +
 +Param<bool> decoupledFrontEnd;
 +Param<int> dispatchWidth;
 +Param<int> wbWidth;
 +
 +Param<unsigned> smtNumFetchingThreads;
 +Param<std::string>   smtFetchPolicy;
 +Param<std::string>   smtLSQPolicy;
 +Param<unsigned> smtLSQThreshold;
 +Param<std::string>   smtIQPolicy;
 +Param<unsigned> smtIQThreshold;
 +Param<std::string>   smtROBPolicy;
 +Param<unsigned> smtROBThreshold;
 +Param<std::string>   smtCommitPolicy;
 +
 +Param<unsigned> instShiftAmt;
 +
 +Param<bool> defer_registration;
 +
 +Param<bool> function_trace;
 +Param<Tick> function_trace_start;
 +
 +END_DECLARE_SIM_OBJECT_PARAMS(SimpleOzoneCPU)
 +
 +BEGIN_INIT_SIM_OBJECT_PARAMS(SimpleOzoneCPU)
 +
 +    INIT_PARAM(clock, "clock speed"),
 +    INIT_PARAM(numThreads, "number of HW thread contexts"),
 +
 +#if FULL_SYSTEM
 +    INIT_PARAM(system, "System object"),
 +    INIT_PARAM(cpu_id, "processor ID"),
 +    INIT_PARAM(itb, "Instruction translation buffer"),
 +    INIT_PARAM(dtb, "Data translation buffer"),
 +#else
 +    INIT_PARAM(workload, "Processes to run"),
 +//    INIT_PARAM(page_table, "Page table"),
 +#endif // FULL_SYSTEM
 +
 +    INIT_PARAM_DFLT(mem, "Memory", NULL),
 +
 +    INIT_PARAM_DFLT(checker, "Checker CPU", NULL),
 +
 +    INIT_PARAM_DFLT(max_insts_any_thread,
 +                    "Terminate when any thread reaches this inst count",
 +                    0),
 +    INIT_PARAM_DFLT(max_insts_all_threads,
 +                    "Terminate when all threads have reached"
 +                    "this inst count",
 +                    0),
 +    INIT_PARAM_DFLT(max_loads_any_thread,
 +                    "Terminate when any thread reaches this load count",
 +                    0),
 +    INIT_PARAM_DFLT(max_loads_all_threads,
 +                    "Terminate when all threads have reached this load"
 +                    "count",
 +                    0),
 +
 +    INIT_PARAM_DFLT(icache, "L1 instruction cache", NULL),
 +    INIT_PARAM_DFLT(dcache, "L1 data cache", NULL),
 +
 +    INIT_PARAM_DFLT(cachePorts, "Cache Ports", 200),
 +    INIT_PARAM_DFLT(width, "Width", 1),
 +    INIT_PARAM_DFLT(frontEndWidth, "Front end width", 1),
 +    INIT_PARAM_DFLT(backEndWidth, "Back end width", 1),
 +    INIT_PARAM_DFLT(backEndSquashLatency, "Back end squash latency", 1),
 +    INIT_PARAM_DFLT(backEndLatency, "Back end latency", 1),
 +    INIT_PARAM_DFLT(maxInstBufferSize, "Maximum instruction buffer size", 16),
 +    INIT_PARAM(numPhysicalRegs, "Number of physical registers"),
 +
 +    INIT_PARAM(decodeToFetchDelay, "Decode to fetch delay"),
 +    INIT_PARAM(renameToFetchDelay, "Rename to fetch delay"),
 +    INIT_PARAM(iewToFetchDelay, "Issue/Execute/Writeback to fetch"
 +               "delay"),
 +    INIT_PARAM(commitToFetchDelay, "Commit to fetch delay"),
 +    INIT_PARAM(fetchWidth, "Fetch width"),
 +    INIT_PARAM(renameToDecodeDelay, "Rename to decode delay"),
 +    INIT_PARAM(iewToDecodeDelay, "Issue/Execute/Writeback to decode"
 +               "delay"),
 +    INIT_PARAM(commitToDecodeDelay, "Commit to decode delay"),
 +    INIT_PARAM(fetchToDecodeDelay, "Fetch to decode delay"),
 +    INIT_PARAM(decodeWidth, "Decode width"),
 +
 +    INIT_PARAM(iewToRenameDelay, "Issue/Execute/Writeback to rename"
 +               "delay"),
 +    INIT_PARAM(commitToRenameDelay, "Commit to rename delay"),
 +    INIT_PARAM(decodeToRenameDelay, "Decode to rename delay"),
 +    INIT_PARAM(renameWidth, "Rename width"),
 +
 +    INIT_PARAM(commitToIEWDelay, "Commit to "
 +               "Issue/Execute/Writeback delay"),
 +    INIT_PARAM(renameToIEWDelay, "Rename to "
 +               "Issue/Execute/Writeback delay"),
 +    INIT_PARAM(issueToExecuteDelay, "Issue to execute delay (internal"
 +               "to the IEW stage)"),
 +    INIT_PARAM(issueWidth, "Issue width"),
 +    INIT_PARAM(executeWidth, "Execute width"),
 +    INIT_PARAM(executeIntWidth, "Integer execute width"),
 +    INIT_PARAM(executeFloatWidth, "Floating point execute width"),
 +    INIT_PARAM(executeBranchWidth, "Branch execute width"),
 +    INIT_PARAM(executeMemoryWidth, "Memory execute width"),
 +
 +    INIT_PARAM(iewToCommitDelay, "Issue/Execute/Writeback to commit "
 +               "delay"),
 +    INIT_PARAM(renameToROBDelay, "Rename to reorder buffer delay"),
 +    INIT_PARAM(commitWidth, "Commit width"),
 +    INIT_PARAM(squashWidth, "Squash width"),
 +
++    INIT_PARAM(predType, "Type of branch predictor ('local', 'tournament')"),
 +    INIT_PARAM(localPredictorSize, "Size of local predictor"),
 +    INIT_PARAM(localCtrBits, "Bits per counter"),
 +    INIT_PARAM(localHistoryTableSize, "Size of local history table"),
 +    INIT_PARAM(localHistoryBits, "Bits for the local history"),
 +    INIT_PARAM(globalPredictorSize, "Size of global predictor"),
 +    INIT_PARAM(globalCtrBits, "Bits per counter"),
 +    INIT_PARAM(globalHistoryBits, "Bits of history"),
 +    INIT_PARAM(choicePredictorSize, "Size of choice predictor"),
 +    INIT_PARAM(choiceCtrBits, "Bits of choice counters"),
 +
 +    INIT_PARAM(BTBEntries, "Number of BTB entries"),
 +    INIT_PARAM(BTBTagSize, "Size of the BTB tags, in bits"),
 +
 +    INIT_PARAM(RASSize, "RAS size"),
 +
 +    INIT_PARAM(LQEntries, "Number of load queue entries"),
 +    INIT_PARAM(SQEntries, "Number of store queue entries"),
 +    INIT_PARAM(LFSTSize, "Last fetched store table size"),
 +    INIT_PARAM(SSITSize, "Store set ID table size"),
 +
 +    INIT_PARAM(numPhysIntRegs, "Number of physical integer registers"),
 +    INIT_PARAM(numPhysFloatRegs, "Number of physical floating point "
 +               "registers"),
 +    INIT_PARAM(numIQEntries, "Number of instruction queue entries"),
 +    INIT_PARAM(numROBEntries, "Number of reorder buffer entries"),
 +
 +    INIT_PARAM_DFLT(decoupledFrontEnd, "Decoupled front end", true),
 +    INIT_PARAM_DFLT(dispatchWidth, "Dispatch width", 0),
 +    INIT_PARAM_DFLT(wbWidth, "Writeback width", 0),
 +
 +    INIT_PARAM_DFLT(smtNumFetchingThreads, "SMT Number of Fetching Threads", 1),
 +    INIT_PARAM_DFLT(smtFetchPolicy, "SMT Fetch Policy", "SingleThread"),
 +    INIT_PARAM_DFLT(smtLSQPolicy,   "SMT LSQ Sharing Policy",    "Partitioned"),
 +    INIT_PARAM_DFLT(smtLSQThreshold,"SMT LSQ Threshold", 100),
 +    INIT_PARAM_DFLT(smtIQPolicy,    "SMT IQ Policy",    "Partitioned"),
 +    INIT_PARAM_DFLT(smtIQThreshold, "SMT IQ Threshold", 100),
 +    INIT_PARAM_DFLT(smtROBPolicy,   "SMT ROB Sharing Policy", "Partitioned"),
 +    INIT_PARAM_DFLT(smtROBThreshold,"SMT ROB Threshold", 100),
 +    INIT_PARAM_DFLT(smtCommitPolicy,"SMT Commit Fetch Policy", "RoundRobin"),
 +
 +    INIT_PARAM(instShiftAmt, "Number of bits to shift instructions by"),
 +    INIT_PARAM(defer_registration, "defer system registration (for sampling)"),
 +
 +    INIT_PARAM(function_trace, "Enable function trace"),
 +    INIT_PARAM(function_trace_start, "Cycle to start function trace")
 +
 +END_INIT_SIM_OBJECT_PARAMS(SimpleOzoneCPU)
 +
 +CREATE_SIM_OBJECT(SimpleOzoneCPU)
 +{
 +    SimpleOzoneCPU *cpu;
 +
 +#if FULL_SYSTEM
 +    // Full-system only supports a single thread for the moment.
 +    int actual_num_threads = 1;
 +#else
 +    // In non-full-system mode, we infer the number of threads from
 +    // the workload if it's not explicitly specified.
 +    int actual_num_threads =
 +        numThreads.isValid() ? numThreads : workload.size();
 +
 +    if (workload.size() == 0) {
 +        fatal("Must specify at least one workload!");
 +    }
 +
 +#endif
 +
 +    SimpleParams *params = new SimpleParams;
 +
 +    params->clock = clock;
 +
 +    params->name = getInstanceName();
 +    params->numberOfThreads = actual_num_threads;
 +
 +#if FULL_SYSTEM
 +    params->system = system;
 +    params->cpu_id = cpu_id;
 +    params->itb = itb;
 +    params->dtb = dtb;
 +#else
 +    params->workload = workload;
 +//    params->pTable = page_table;
 +#endif // FULL_SYSTEM
 +
 +    params->mem = mem;
 +    params->checker = checker;
 +    params->max_insts_any_thread = max_insts_any_thread;
 +    params->max_insts_all_threads = max_insts_all_threads;
 +    params->max_loads_any_thread = max_loads_any_thread;
 +    params->max_loads_all_threads = max_loads_all_threads;
 +
 +    //
 +    // Caches
 +    //
 +    params->icacheInterface = icache ? icache->getInterface() : NULL;
 +    params->dcacheInterface = dcache ? dcache->getInterface() : NULL;
 +    params->cachePorts = cachePorts;
 +
 +    params->width = width;
 +    params->frontEndWidth = frontEndWidth;
 +    params->backEndWidth = backEndWidth;
 +    params->backEndSquashLatency = backEndSquashLatency;
 +    params->backEndLatency = backEndLatency;
 +    params->maxInstBufferSize = maxInstBufferSize;
 +    params->numPhysicalRegs = numPhysIntRegs + numPhysFloatRegs;
 +
 +    params->decodeToFetchDelay = decodeToFetchDelay;
 +    params->renameToFetchDelay = renameToFetchDelay;
 +    params->iewToFetchDelay = iewToFetchDelay;
 +    params->commitToFetchDelay = commitToFetchDelay;
 +    params->fetchWidth = fetchWidth;
 +
 +    params->renameToDecodeDelay = renameToDecodeDelay;
 +    params->iewToDecodeDelay = iewToDecodeDelay;
 +    params->commitToDecodeDelay = commitToDecodeDelay;
 +    params->fetchToDecodeDelay = fetchToDecodeDelay;
 +    params->decodeWidth = decodeWidth;
 +
 +    params->iewToRenameDelay = iewToRenameDelay;
 +    params->commitToRenameDelay = commitToRenameDelay;
 +    params->decodeToRenameDelay = decodeToRenameDelay;
 +    params->renameWidth = renameWidth;
 +
 +    params->commitToIEWDelay = commitToIEWDelay;
 +    params->renameToIEWDelay = renameToIEWDelay;
 +    params->issueToExecuteDelay = issueToExecuteDelay;
 +    params->issueWidth = issueWidth;
 +    params->executeWidth = executeWidth;
 +    params->executeIntWidth = executeIntWidth;
 +    params->executeFloatWidth = executeFloatWidth;
 +    params->executeBranchWidth = executeBranchWidth;
 +    params->executeMemoryWidth = executeMemoryWidth;
 +
 +    params->iewToCommitDelay = iewToCommitDelay;
 +    params->renameToROBDelay = renameToROBDelay;
 +    params->commitWidth = commitWidth;
 +    params->squashWidth = squashWidth;
 +
++    params->predType = predType;
 +    params->localPredictorSize = localPredictorSize;
 +    params->localCtrBits = localCtrBits;
 +    params->localHistoryTableSize = localHistoryTableSize;
 +    params->localHistoryBits = localHistoryBits;
 +    params->globalPredictorSize = globalPredictorSize;
 +    params->globalCtrBits = globalCtrBits;
 +    params->globalHistoryBits = globalHistoryBits;
 +    params->choicePredictorSize = choicePredictorSize;
 +    params->choiceCtrBits = choiceCtrBits;
 +
 +    params->BTBEntries = BTBEntries;
 +    params->BTBTagSize = BTBTagSize;
 +
 +    params->RASSize = RASSize;
 +
 +    params->LQEntries = LQEntries;
 +    params->SQEntries = SQEntries;
 +
 +    params->SSITSize = SSITSize;
 +    params->LFSTSize = LFSTSize;
 +
 +    params->numPhysIntRegs = numPhysIntRegs;
 +    params->numPhysFloatRegs = numPhysFloatRegs;
 +    params->numIQEntries = numIQEntries;
 +    params->numROBEntries = numROBEntries;
 +
 +    params->decoupledFrontEnd = decoupledFrontEnd;
 +    params->dispatchWidth = dispatchWidth;
 +    params->wbWidth = wbWidth;
 +
 +    params->smtNumFetchingThreads = smtNumFetchingThreads;
 +    params->smtFetchPolicy = smtFetchPolicy;
 +    params->smtIQPolicy    = smtIQPolicy;
 +    params->smtLSQPolicy    = smtLSQPolicy;
 +    params->smtLSQThreshold = smtLSQThreshold;
 +    params->smtROBPolicy   = smtROBPolicy;
 +    params->smtROBThreshold = smtROBThreshold;
 +    params->smtCommitPolicy = smtCommitPolicy;
 +
 +    params->instShiftAmt = 2;
 +
 +    params->deferRegistration = defer_registration;
 +
 +    params->functionTrace = function_trace;
 +    params->functionTraceStart = function_trace_start;
 +
 +    cpu = new SimpleOzoneCPU(params);
 +
 +    return cpu;
 +}
 +
 +REGISTER_SIM_OBJECT("SimpleOzoneCPU", SimpleOzoneCPU)
 +
index d8c54597764dc944b6b3cd143ca0718905bd5e58,0000000000000000000000000000000000000000..4e0dbc0e168082cbd5d8917d816a5eef47d074de
mode 100644,000000..100644
--- /dev/null
@@@ -1,73 -1,0 +1,73 @@@
-     typedef TwobitBPredUnit<OzoneImpl> BranchPred;
 +/*
 + * Copyright (c) 2006 The Regents of The University of Michigan
 + * 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.
 + */
 +
 +#ifndef __CPU_OZONE_OZONE_IMPL_HH__
 +#define __CPU_OZONE_OZONE_IMPL_HH__
 +
 +#include "arch/alpha/isa_traits.hh"
 +#include "cpu/o3/bpred_unit.hh"
 +#include "cpu/ozone/front_end.hh"
 +#include "cpu/ozone/inst_queue.hh"
 +#include "cpu/ozone/lw_lsq.hh"
 +#include "cpu/ozone/lw_back_end.hh"
 +#include "cpu/ozone/null_predictor.hh"
 +#include "cpu/ozone/dyn_inst.hh"
 +#include "cpu/ozone/simple_params.hh"
 +
 +template <class Impl>
 +class OzoneCPU;
 +
 +template <class Impl>
 +class OzoneDynInst;
 +
 +struct OzoneImpl {
 +    typedef SimpleParams Params;
 +    typedef OzoneCPU<OzoneImpl> OzoneCPU;
 +    typedef OzoneCPU FullCPU;
 +
 +    // Would like to put these into their own area.
 +//    typedef NullPredictor BranchPred;
++    typedef BPredUnit<OzoneImpl> BranchPred;
 +    typedef FrontEnd<OzoneImpl> FrontEnd;
 +    // Will need IQ, LSQ eventually
 +    typedef LWBackEnd<OzoneImpl> BackEnd;
 +
 +    typedef InstQueue<OzoneImpl> InstQueue;
 +    typedef OzoneLWLSQ<OzoneImpl> LdstQueue;
 +
 +    typedef OzoneDynInst<OzoneImpl> DynInst;
 +    typedef RefCountingPtr<DynInst> DynInstPtr;
 +
 +    typedef uint64_t IssueStruct;
 +
 +    enum {
 +        MaxThreads = 1
 +    };
 +};
 +
 +#endif // __CPU_OZONE_OZONE_IMPL_HH__
index 961bf2ea92d3645d98a53a1c39e520d40baf2308,0000000000000000000000000000000000000000..26845271aaf6a418471708eb8c875282bf9acfc2
mode 100644,000000..100644
--- /dev/null
@@@ -1,69 -1,0 +1,69 @@@
-     typedef TwobitBPredUnit<SimpleImpl> BranchPred;
 +/*
 + * Copyright (c) 2006 The Regents of The University of Michigan
 + * 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.
 + */
 +
 +#ifndef __CPU_OZONE_SIMPLE_IMPL_HH__
 +#define __CPU_OZONE_SIMPLE_IMPL_HH__
 +
 +#include "arch/isa_traits.hh"
 +#include "cpu/o3/bpred_unit.hh"
 +#include "cpu/ozone/cpu.hh"
 +#include "cpu/ozone/front_end.hh"
 +#include "cpu/ozone/inorder_back_end.hh"
 +#include "cpu/ozone/null_predictor.hh"
 +#include "cpu/ozone/dyn_inst.hh"
 +#include "cpu/ozone/simple_params.hh"
 +
 +//template <class Impl>
 +//class OzoneCPU;
 +
 +template <class Impl>
 +class OzoneDynInst;
 +
 +struct SimpleImpl {
 +    typedef SimpleParams Params;
 +    typedef OzoneCPU<SimpleImpl> OzoneCPU;
 +    typedef OzoneCPU FullCPU;
 +
 +    // Would like to put these into their own area.
 +//    typedef NullPredictor BranchPred;
++    typedef BPredUnit<SimpleImpl> BranchPred;
 +    typedef FrontEnd<SimpleImpl> FrontEnd;
 +    // Will need IQ, LSQ eventually
 +    typedef InorderBackEnd<SimpleImpl> BackEnd;
 +
 +    typedef OzoneDynInst<SimpleImpl> DynInst;
 +    typedef RefCountingPtr<DynInst> DynInstPtr;
 +
 +    typedef uint64_t IssueStruct;
 +
 +    enum {
 +        MaxThreads = 1
 +    };
 +};
 +
 +#endif // __CPU_OZONE_SIMPLE_IMPL_HH__
index 647da1781e8aab2bafdec460d927bbba3c01df29,0000000000000000000000000000000000000000..7b5c6f67bf444865f8f5210a21fffeb71a607b0a
mode 100644,000000..100644
--- /dev/null
@@@ -1,165 -1,0 +1,191 @@@
++/*
++ * Copyright (c) 2006 The Regents of The University of Michigan
++ * 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.
++ */
 +
 +#ifndef __CPU_OZONE_SIMPLE_PARAMS_HH__
 +#define __CPU_OZONE_SIMPLE_PARAMS_HH__
 +
 +#include "cpu/ozone/cpu.hh"
 +
 +//Forward declarations
 +class AlphaDTB;
 +class AlphaITB;
 +class FUPool;
 +class FunctionalMemory;
 +class MemInterface;
 +class PageTable;
 +class Process;
 +class System;
 +
 +/**
 + * This file defines the parameters that will be used for the OzoneCPU.
 + * This must be defined externally so that the Impl can have a params class
 + * defined that it can pass to all of the individual stages.
 + */
 +
 +class SimpleParams : public BaseCPU::Params
 +{
 +  public:
 +
 +#if FULL_SYSTEM
 +    AlphaITB *itb; AlphaDTB *dtb;
 +#else
 +    std::vector<Process *> workload;
- //    Process *process;
 +#endif // FULL_SYSTEM
 +
 +    //Page Table
 +    PageTable *pTable;
 +
 +    FunctionalMemory *mem;
 +
 +    //
 +    // Caches
 +    //
 +    MemInterface *icacheInterface;
 +    MemInterface *dcacheInterface;
 +
 +    unsigned cachePorts;
 +    unsigned width;
 +    unsigned frontEndWidth;
 +    unsigned backEndWidth;
 +    unsigned backEndSquashLatency;
 +    unsigned backEndLatency;
 +    unsigned maxInstBufferSize;
 +    unsigned numPhysicalRegs;
 +    unsigned maxOutstandingMemOps;
 +    //
 +    // Fetch
 +    //
 +    unsigned decodeToFetchDelay;
 +    unsigned renameToFetchDelay;
 +    unsigned iewToFetchDelay;
 +    unsigned commitToFetchDelay;
 +    unsigned fetchWidth;
 +
 +    //
 +    // Decode
 +    //
 +    unsigned renameToDecodeDelay;
 +    unsigned iewToDecodeDelay;
 +    unsigned commitToDecodeDelay;
 +    unsigned fetchToDecodeDelay;
 +    unsigned decodeWidth;
 +
 +    //
 +    // Rename
 +    //
 +    unsigned iewToRenameDelay;
 +    unsigned commitToRenameDelay;
 +    unsigned decodeToRenameDelay;
 +    unsigned renameWidth;
 +
 +    //
 +    // IEW
 +    //
 +    unsigned commitToIEWDelay;
 +    unsigned renameToIEWDelay;
 +    unsigned issueToExecuteDelay;
 +    unsigned issueWidth;
 +    unsigned executeWidth;
 +    unsigned executeIntWidth;
 +    unsigned executeFloatWidth;
 +    unsigned executeBranchWidth;
 +    unsigned executeMemoryWidth;
 +    FUPool *fuPool;
 +
 +    //
 +    // Commit
 +    //
 +    unsigned iewToCommitDelay;
 +    unsigned renameToROBDelay;
 +    unsigned commitWidth;
 +    unsigned squashWidth;
 +
 +    //
 +    // Branch predictor (BP & BTB)
 +    //
++    std::string predType;
 +    unsigned localPredictorSize;
 +    unsigned localCtrBits;
 +    unsigned localHistoryTableSize;
 +    unsigned localHistoryBits;
 +    unsigned globalPredictorSize;
 +    unsigned globalCtrBits;
 +    unsigned globalHistoryBits;
 +    unsigned choicePredictorSize;
 +    unsigned choiceCtrBits;
 +
 +    unsigned BTBEntries;
 +    unsigned BTBTagSize;
 +
 +    unsigned RASSize;
 +
 +    //
 +    // Load store queue
 +    //
 +    unsigned LQEntries;
 +    unsigned SQEntries;
 +
 +    //
 +    // Memory dependence
 +    //
 +    unsigned SSITSize;
 +    unsigned LFSTSize;
 +
 +    //
 +    // Miscellaneous
 +    //
 +    unsigned numPhysIntRegs;
 +    unsigned numPhysFloatRegs;
 +    unsigned numIQEntries;
 +    unsigned numROBEntries;
 +
 +    bool decoupledFrontEnd;
 +    int dispatchWidth;
 +    int wbWidth;
 +
 +    //SMT Parameters
 +    unsigned smtNumFetchingThreads;
 +
 +    std::string   smtFetchPolicy;
 +
 +    std::string   smtIQPolicy;
 +    unsigned smtIQThreshold;
 +
 +    std::string   smtLSQPolicy;
 +    unsigned smtLSQThreshold;
 +
 +    std::string   smtCommitPolicy;
 +
 +    std::string   smtROBPolicy;
 +    unsigned smtROBThreshold;
 +
 +    // Probably can get this from somewhere.
 +    unsigned instShiftAmt;
 +};
 +
 +#endif // __CPU_OZONE_SIMPLE_PARAMS_HH__
index d719bf783c196a0747d3f9dbd688374ddc1fff13,0000000000000000000000000000000000000000..043c3c08f6a0702fdf2d976a5ebb40db3637b55b
mode 100644,000000..100644
--- /dev/null
@@@ -1,99 -1,0 +1,100 @@@
 +from m5 import *
 +from BaseCPU import BaseCPU
 +
 +class DerivAlphaFullCPU(BaseCPU):
 +    type = 'DerivAlphaFullCPU'
 +    activity = Param.Unsigned("Initial count")
 +    numThreads = Param.Unsigned("number of HW thread contexts")
 +
 +    if not build_env['FULL_SYSTEM']:
 +        mem = Param.FunctionalMemory(NULL, "memory")
 +
 +    checker = Param.BaseCPU(NULL, "checker")
 +
 +    cachePorts = Param.Unsigned("Cache Ports")
 +
 +    decodeToFetchDelay = Param.Unsigned("Decode to fetch delay")
 +    renameToFetchDelay = Param.Unsigned("Rename to fetch delay")
 +    iewToFetchDelay = Param.Unsigned("Issue/Execute/Writeback to fetch "
 +               "delay")
 +    commitToFetchDelay = Param.Unsigned("Commit to fetch delay")
 +    fetchWidth = Param.Unsigned("Fetch width")
 +
 +    renameToDecodeDelay = Param.Unsigned("Rename to decode delay")
 +    iewToDecodeDelay = Param.Unsigned("Issue/Execute/Writeback to decode "
 +               "delay")
 +    commitToDecodeDelay = Param.Unsigned("Commit to decode delay")
 +    fetchToDecodeDelay = Param.Unsigned("Fetch to decode delay")
 +    decodeWidth = Param.Unsigned("Decode width")
 +
 +    iewToRenameDelay = Param.Unsigned("Issue/Execute/Writeback to rename "
 +               "delay")
 +    commitToRenameDelay = Param.Unsigned("Commit to rename delay")
 +    decodeToRenameDelay = Param.Unsigned("Decode to rename delay")
 +    renameWidth = Param.Unsigned("Rename width")
 +
 +    commitToIEWDelay = Param.Unsigned("Commit to "
 +               "Issue/Execute/Writeback delay")
 +    renameToIEWDelay = Param.Unsigned("Rename to "
 +               "Issue/Execute/Writeback delay")
 +    issueToExecuteDelay = Param.Unsigned("Issue to execute delay (internal "
 +              "to the IEW stage)")
 +    issueWidth = Param.Unsigned("Issue width")
 +    executeWidth = Param.Unsigned("Execute width")
 +    executeIntWidth = Param.Unsigned("Integer execute width")
 +    executeFloatWidth = Param.Unsigned("Floating point execute width")
 +    executeBranchWidth = Param.Unsigned("Branch execute width")
 +    executeMemoryWidth = Param.Unsigned("Memory execute width")
 +    fuPool = Param.FUPool(NULL, "Functional Unit pool")
 +
 +    iewToCommitDelay = Param.Unsigned("Issue/Execute/Writeback to commit "
 +               "delay")
 +    renameToROBDelay = Param.Unsigned("Rename to reorder buffer delay")
 +    commitWidth = Param.Unsigned("Commit width")
 +    squashWidth = Param.Unsigned("Squash width")
 +    trapLatency = Param.Tick("Trap latency")
 +    fetchTrapLatency = Param.Tick("Fetch trap latency")
 +
++    predType = Param.String("Branch predictor type ('local', 'tournament')")
 +    localPredictorSize = Param.Unsigned("Size of local predictor")
 +    localCtrBits = Param.Unsigned("Bits per counter")
 +    localHistoryTableSize = Param.Unsigned("Size of local history table")
 +    localHistoryBits = Param.Unsigned("Bits for the local history")
 +    globalPredictorSize = Param.Unsigned("Size of global predictor")
 +    globalCtrBits = Param.Unsigned("Bits per counter")
 +    globalHistoryBits = Param.Unsigned("Bits of history")
 +    choicePredictorSize = Param.Unsigned("Size of choice predictor")
 +    choiceCtrBits = Param.Unsigned("Bits of choice counters")
 +
 +    BTBEntries = Param.Unsigned("Number of BTB entries")
 +    BTBTagSize = Param.Unsigned("Size of the BTB tags, in bits")
 +
 +    RASSize = Param.Unsigned("RAS size")
 +
 +    LQEntries = Param.Unsigned("Number of load queue entries")
 +    SQEntries = Param.Unsigned("Number of store queue entries")
 +    LFSTSize = Param.Unsigned("Last fetched store table size")
 +    SSITSize = Param.Unsigned("Store set ID table size")
 +
 +    numRobs = Param.Unsigned("Number of Reorder Buffers");
 +
 +    numPhysIntRegs = Param.Unsigned("Number of physical integer registers")
 +    numPhysFloatRegs = Param.Unsigned("Number of physical floating point "
 +               "registers")
 +    numIQEntries = Param.Unsigned("Number of instruction queue entries")
 +    numROBEntries = Param.Unsigned("Number of reorder buffer entries")
 +
 +    instShiftAmt = Param.Unsigned("Number of bits to shift instructions by")
 +
 +    function_trace = Param.Bool(False, "Enable function trace")
 +    function_trace_start = Param.Tick(0, "Cycle to start function trace")
 +
 +    smtNumFetchingThreads = Param.Unsigned("SMT Number of Fetching Threads")
 +    smtFetchPolicy = Param.String("SMT Fetch policy")
 +    smtLSQPolicy    = Param.String("SMT LSQ Sharing Policy")
 +    smtLSQThreshold = Param.String("SMT LSQ Threshold Sharing Parameter")
 +    smtIQPolicy    = Param.String("SMT IQ Sharing Policy")
 +    smtIQThreshold = Param.String("SMT IQ Threshold Sharing Parameter")
 +    smtROBPolicy   = Param.String("SMT ROB Sharing Policy")
 +    smtROBThreshold = Param.String("SMT ROB Threshold Sharing Parameter")
 +    smtCommitPolicy = Param.String("SMT Commit Policy")
index 3fca61e280d09a25b1276f99d1585dbf7d2d3c15,0000000000000000000000000000000000000000..ea8b6b537f235120851e266a37c9044ed126434c
mode 100644,000000..100644
--- /dev/null
@@@ -1,89 -1,0 +1,90 @@@
 +from m5 import *
 +from BaseCPU import BaseCPU
 +
 +class DerivOzoneCPU(BaseCPU):
 +    type = 'DerivOzoneCPU'
 +
 +    numThreads = Param.Unsigned("number of HW thread contexts")
 +
 +    if not build_env['FULL_SYSTEM']:
 +        mem = Param.FunctionalMemory(NULL, "memory")
 +
 +    checker = Param.BaseCPU("Checker CPU")
 +
 +    width = Param.Unsigned("Width")
 +    frontEndWidth = Param.Unsigned("Front end width")
 +    backEndWidth = Param.Unsigned("Back end width")
 +    backEndSquashLatency = Param.Unsigned("Back end squash latency")
 +    backEndLatency = Param.Unsigned("Back end latency")
 +    maxInstBufferSize = Param.Unsigned("Maximum instruction buffer size")
 +    maxOutstandingMemOps = Param.Unsigned("Maximum number of outstanding memory operations")
 +    decodeToFetchDelay = Param.Unsigned("Decode to fetch delay")
 +    renameToFetchDelay = Param.Unsigned("Rename to fetch delay")
 +    iewToFetchDelay = Param.Unsigned("Issue/Execute/Writeback to fetch "
 +               "delay")
 +    commitToFetchDelay = Param.Unsigned("Commit to fetch delay")
 +    fetchWidth = Param.Unsigned("Fetch width")
 +
 +    renameToDecodeDelay = Param.Unsigned("Rename to decode delay")
 +    iewToDecodeDelay = Param.Unsigned("Issue/Execute/Writeback to decode "
 +               "delay")
 +    commitToDecodeDelay = Param.Unsigned("Commit to decode delay")
 +    fetchToDecodeDelay = Param.Unsigned("Fetch to decode delay")
 +    decodeWidth = Param.Unsigned("Decode width")
 +
 +    iewToRenameDelay = Param.Unsigned("Issue/Execute/Writeback to rename "
 +               "delay")
 +    commitToRenameDelay = Param.Unsigned("Commit to rename delay")
 +    decodeToRenameDelay = Param.Unsigned("Decode to rename delay")
 +    renameWidth = Param.Unsigned("Rename width")
 +
 +    commitToIEWDelay = Param.Unsigned("Commit to "
 +               "Issue/Execute/Writeback delay")
 +    renameToIEWDelay = Param.Unsigned("Rename to "
 +               "Issue/Execute/Writeback delay")
 +    issueToExecuteDelay = Param.Unsigned("Issue to execute delay (internal "
 +              "to the IEW stage)")
 +    issueWidth = Param.Unsigned("Issue width")
 +    executeWidth = Param.Unsigned("Execute width")
 +    executeIntWidth = Param.Unsigned("Integer execute width")
 +    executeFloatWidth = Param.Unsigned("Floating point execute width")
 +    executeBranchWidth = Param.Unsigned("Branch execute width")
 +    executeMemoryWidth = Param.Unsigned("Memory execute width")
 +
 +    iewToCommitDelay = Param.Unsigned("Issue/Execute/Writeback to commit "
 +               "delay")
 +    renameToROBDelay = Param.Unsigned("Rename to reorder buffer delay")
 +    commitWidth = Param.Unsigned("Commit width")
 +    squashWidth = Param.Unsigned("Squash width")
 +
++    predType = Param.String("Type of branch predictor ('local', 'tournament')")
 +    localPredictorSize = Param.Unsigned("Size of local predictor")
 +    localCtrBits = Param.Unsigned("Bits per counter")
 +    localHistoryTableSize = Param.Unsigned("Size of local history table")
 +    localHistoryBits = Param.Unsigned("Bits for the local history")
 +    globalPredictorSize = Param.Unsigned("Size of global predictor")
 +    globalCtrBits = Param.Unsigned("Bits per counter")
 +    globalHistoryBits = Param.Unsigned("Bits of history")
 +    choicePredictorSize = Param.Unsigned("Size of choice predictor")
 +    choiceCtrBits = Param.Unsigned("Bits of choice counters")
 +
 +    BTBEntries = Param.Unsigned("Number of BTB entries")
 +    BTBTagSize = Param.Unsigned("Size of the BTB tags, in bits")
 +
 +    RASSize = Param.Unsigned("RAS size")
 +
 +    LQEntries = Param.Unsigned("Number of load queue entries")
 +    SQEntries = Param.Unsigned("Number of store queue entries")
 +    LFSTSize = Param.Unsigned("Last fetched store table size")
 +    SSITSize = Param.Unsigned("Store set ID table size")
 +
 +    numPhysIntRegs = Param.Unsigned("Number of physical integer registers")
 +    numPhysFloatRegs = Param.Unsigned("Number of physical floating point "
 +               "registers")
 +    numIQEntries = Param.Unsigned("Number of instruction queue entries")
 +    numROBEntries = Param.Unsigned("Number of reorder buffer entries")
 +
 +    instShiftAmt = Param.Unsigned("Number of bits to shift instructions by")
 +
 +    function_trace = Param.Bool(False, "Enable function trace")
 +    function_trace_start = Param.Tick(0, "Cycle to start function trace")