Split off instantiation into separate CC files for each of the models. This makes...
authorKevin Lim <ktlim@umich.edu>
Sun, 18 Jun 2006 01:39:25 +0000 (21:39 -0400)
committerKevin Lim <ktlim@umich.edu>
Sun, 18 Jun 2006 01:39:25 +0000 (21:39 -0400)
src/cpu/SConscript:
    Split off instantiations into separate CC files.  This makes it easier to split them per CPU model.
src/cpu/base_dyn_inst_impl.hh:
    Move instantations out of impl.hh file and into a cc file.
src/cpu/checker/cpu_impl.hh:
    Move instantiations over to .cc files inside each CPU's directory.  Makes it easier to only use what's actually included.
src/cpu/o3/bpred_unit.cc:
    Pull Ozone instantiations out of this .cc file; put them into the ozone's CC file.
src/cpu/o3/checker_builder.cc:
    Instantiate Checker for O3 CPU.
src/cpu/ozone/checker_builder.cc:
    Instantiate Checker for Ozone CPU.

--HG--
rename : src/cpu/base_dyn_inst.cc => src/cpu/base_dyn_inst_impl.hh
rename : src/cpu/checker/cpu.cc => src/cpu/checker/cpu_impl.hh
rename : src/cpu/checker/o3_builder.cc => src/cpu/o3/checker_builder.cc
rename : src/cpu/checker/ozone_builder.cc => src/cpu/ozone/checker_builder.cc
extra : convert_revision : 4e5f928b165379c06d31071c544ea46cf0b8fa71

14 files changed:
src/cpu/SConscript
src/cpu/base_dyn_inst.cc [deleted file]
src/cpu/base_dyn_inst_impl.hh [new file with mode: 0644]
src/cpu/checker/cpu.cc [deleted file]
src/cpu/checker/cpu_impl.hh [new file with mode: 0644]
src/cpu/checker/o3_builder.cc [deleted file]
src/cpu/checker/ozone_builder.cc [deleted file]
src/cpu/o3/base_dyn_inst.cc [new file with mode: 0644]
src/cpu/o3/bpred_unit.cc
src/cpu/o3/checker_builder.cc [new file with mode: 0644]
src/cpu/ozone/bpred_unit.cc [new file with mode: 0644]
src/cpu/ozone/checker_builder.cc [new file with mode: 0644]
src/cpu/ozone/ozone_base_dyn_inst.cc [new file with mode: 0644]
src/cpu/ozone/simple_base_dyn_inst.cc [new file with mode: 0644]

index 608625ed4a1c7921091b28c1183bf903d1d54d88..ab3c1f1d28b96a5b25ffdab240a1a495ae551639 100644 (file)
@@ -122,11 +122,11 @@ if 'FastCPU' in env['CPU_MODELS']:
 
 if 'AlphaO3CPU' in env['CPU_MODELS']:
     sources += Split('''
-        base_dyn_inst.cc
         o3/2bit_local_pred.cc
         o3/alpha_dyn_inst.cc
         o3/alpha_cpu.cc
         o3/alpha_cpu_builder.cc
+        o3/base_dyn_inst.cc
         o3/bpred_unit.cc
         o3/btb.cc
         o3/commit.cc
@@ -149,7 +149,7 @@ if 'AlphaO3CPU' in env['CPU_MODELS']:
         o3/tournament_pred.cc
         ''')
     if 'CheckerCPU' in env['CPU_MODELS']:
-        sources += Split('checker/o3_builder.cc')
+        sources += Split('o3/checker_builder.cc')
 
 if 'OzoneSimpleCPU' in env['CPU_MODELS']:
     sources += Split('''
@@ -161,18 +161,19 @@ if 'OzoneSimpleCPU' in env['CPU_MODELS']:
         ozone/inst_queue.cc
         ozone/rename_table.cc
         ''')
-    if 'CheckerCPU' in env['CPU_MODELS']:
-        sources += Split('checker/ozone_builder.cc')
 
 if 'OzoneCPU' in env['CPU_MODELS']:
     sources += Split('''
+        ozone/base_dyn_inst.cc
+        ozone/bpred_unit.cc
         ozone/lsq_unit.cc
         ozone/lw_back_end.cc
         ozone/lw_lsq.cc
         ''')
+    if 'CheckerCPU' in env['CPU_MODELS']:
+        sources += Split('ozone/checker_builder.cc')
 
 if 'CheckerCPU' in env['CPU_MODELS']:
-    sources += Split('checker/cpu.cc')
     checker_supports = False
     for i in CheckerSupportedCPUList:
         if i in env['CPU_MODELS']:
diff --git a/src/cpu/base_dyn_inst.cc b/src/cpu/base_dyn_inst.cc
deleted file mode 100644 (file)
index 5e2a639..0000000
+++ /dev/null
@@ -1,325 +0,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 <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,
-                               ImplCPU *cpu)
-  : staticInst(machInst), traceData(NULL), cpu(cpu)
-{
-    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;
-    memData = NULL;
-    effAddr = 0;
-    physEffAddr = 0;
-
-    readyRegs = 0;
-
-    instResult.integer = 0;
-
-    status.reset();
-
-    eaCalcDone = false;
-    memOpDone = false;
-
-    lqIdx = -1;
-    sqIdx = -1;
-
-    // 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 NoFault.
-    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) {
-        delete req;
-    }
-
-    if (memData) {
-        delete [] memData;
-    }
-
-    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)
-{
-    // Not currently supported.
-}
-
-/**
- * @todo Need to find a way to get the cache block size here.
- */
-template <class Impl>
-Fault
-BaseDynInst<Impl>::copySrcTranslate(Addr src)
-{
-    // Not currently supported.
-    return NoFault;
-}
-
-/**
- * @todo Need to find a way to get the cache block size here.
- */
-template <class Impl>
-Fault
-BaseDynInst<Impl>::copy(Addr dest)
-{
-    // Not currently supported.
-    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();
-}
-
-template <class Impl>
-void
-BaseDynInst<Impl>::markSrcRegReady()
-{
-    if (++readyRegs == numSrcRegs()) {
-        status.set(CanIssue);
-    }
-}
-
-template <class Impl>
-void
-BaseDynInst<Impl>::markSrcRegReady(RegIndex src_idx)
-{
-    _readySrcRegIdx[src_idx] = true;
-
-    markSrcRegReady();
-}
-
-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;
-*/
diff --git a/src/cpu/base_dyn_inst_impl.hh b/src/cpu/base_dyn_inst_impl.hh
new file mode 100644 (file)
index 0000000..91424fa
--- /dev/null
@@ -0,0 +1,299 @@
+/*
+ * 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 <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"
+
+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,
+                               ImplCPU *cpu)
+  : staticInst(machInst), traceData(NULL), cpu(cpu)
+{
+    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;
+    memData = NULL;
+    effAddr = 0;
+    physEffAddr = 0;
+
+    readyRegs = 0;
+
+    instResult.integer = 0;
+
+    status.reset();
+
+    eaCalcDone = false;
+    memOpDone = false;
+
+    lqIdx = -1;
+    sqIdx = -1;
+
+    // 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 NoFault.
+    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) {
+        delete req;
+    }
+
+    if (memData) {
+        delete [] memData;
+    }
+
+    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)
+{
+    // Not currently supported.
+}
+
+/**
+ * @todo Need to find a way to get the cache block size here.
+ */
+template <class Impl>
+Fault
+BaseDynInst<Impl>::copySrcTranslate(Addr src)
+{
+    // Not currently supported.
+    return NoFault;
+}
+
+/**
+ * @todo Need to find a way to get the cache block size here.
+ */
+template <class Impl>
+Fault
+BaseDynInst<Impl>::copy(Addr dest)
+{
+    // Not currently supported.
+    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();
+}
+
+template <class Impl>
+void
+BaseDynInst<Impl>::markSrcRegReady()
+{
+    if (++readyRegs == numSrcRegs()) {
+        status.set(CanIssue);
+    }
+}
+
+template <class Impl>
+void
+BaseDynInst<Impl>::markSrcRegReady(RegIndex src_idx)
+{
+    _readySrcRegIdx[src_idx] = true;
+
+    markSrcRegReady();
+}
+
+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;
+}
diff --git a/src/cpu/checker/cpu.cc b/src/cpu/checker/cpu.cc
deleted file mode 100644 (file)
index 45c57d2..0000000
+++ /dev/null
@@ -1,834 +0,0 @@
-/*
- * 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.
- *
- * Authors: Kevin Lim
- */
-
-#include <list>
-#include <string>
-
-#include "base/refcnt.hh"
-#include "cpu/base.hh"
-#include "cpu/base_dyn_inst.hh"
-#include "cpu/checker/cpu.hh"
-#include "cpu/simple_thread.hh"
-#include "cpu/thread_context.hh"
-#include "cpu/static_inst.hh"
-#include "mem/packet_impl.hh"
-#include "sim/byteswap.hh"
-#include "sim/sim_object.hh"
-#include "sim/stats.hh"
-
-#include "cpu/o3/alpha_dyn_inst.hh"
-#include "cpu/o3/alpha_impl.hh"
-
-//#include "cpu/ozone/dyn_inst.hh"
-//#include "cpu/ozone/ozone_impl.hh"
-//#include "cpu/ozone/simple_impl.hh"
-
-#if FULL_SYSTEM
-#include "sim/system.hh"
-#include "arch/vtophys.hh"
-#endif // FULL_SYSTEM
-
-using namespace std;
-//The CheckerCPU does alpha only
-using namespace AlphaISA;
-
-void
-CheckerCPU::init()
-{
-}
-
-CheckerCPU::CheckerCPU(Params *p)
-    : BaseCPU(p), thread(NULL), tc(NULL)
-{
-    memReq = NULL;
-
-    numInst = 0;
-    startNumInst = 0;
-    numLoad = 0;
-    startNumLoad = 0;
-    youngestSN = 0;
-
-    changedPC = willChangePC = changedNextPC = false;
-
-    exitOnError = p->exitOnError;
-    warnOnlyOnLoadError = p->warnOnlyOnLoadError;
-#if FULL_SYSTEM
-    itb = p->itb;
-    dtb = p->dtb;
-    systemPtr = NULL;
-#else
-    process = p->process;
-#endif
-
-    result.integer = 0;
-}
-
-CheckerCPU::~CheckerCPU()
-{
-}
-
-void
-CheckerCPU::setMemory(MemObject *mem)
-{
-#if !FULL_SYSTEM
-    memPtr = mem;
-    thread = new SimpleThread(this, /* thread_num */ 0, process,
-                              /* asid */ 0, mem);
-
-    thread->setStatus(ThreadContext::Suspended);
-    tc = thread->getTC();
-    threadContexts.push_back(tc);
-#endif
-}
-
-void
-CheckerCPU::setSystem(System *system)
-{
-#if FULL_SYSTEM
-    systemPtr = system;
-
-    thread = new SimpleThread(this, 0, systemPtr, itb, dtb, false);
-
-    thread->setStatus(ThreadContext::Suspended);
-    tc = thread->getTC();
-    threadContexts.push_back(tc);
-    delete thread->kernelStats;
-    thread->kernelStats = NULL;
-#endif
-}
-
-void
-CheckerCPU::setIcachePort(Port *icache_port)
-{
-    icachePort = icache_port;
-}
-
-void
-CheckerCPU::setDcachePort(Port *dcache_port)
-{
-    dcachePort = dcache_port;
-}
-
-void
-CheckerCPU::serialize(ostream &os)
-{
-/*
-    BaseCPU::serialize(os);
-    SERIALIZE_SCALAR(inst);
-    nameOut(os, csprintf("%s.xc", name()));
-    thread->serialize(os);
-    cacheCompletionEvent.serialize(os);
-*/
-}
-
-void
-CheckerCPU::unserialize(Checkpoint *cp, const string &section)
-{
-/*
-    BaseCPU::unserialize(cp, section);
-    UNSERIALIZE_SCALAR(inst);
-    thread->unserialize(cp, csprintf("%s.xc", section));
-*/
-}
-
-Fault
-CheckerCPU::copySrcTranslate(Addr src)
-{
-    panic("Unimplemented!");
-}
-
-Fault
-CheckerCPU::copy(Addr dest)
-{
-    panic("Unimplemented!");
-}
-
-template <class T>
-Fault
-CheckerCPU::read(Addr addr, T &data, unsigned flags)
-{
-    // need to fill in CPU & thread IDs here
-    memReq = new Request();
-
-    memReq->setVirt(0, addr, sizeof(T), flags, thread->readPC());
-
-    // translate to physical address
-    translateDataReadReq(memReq);
-
-    Packet *pkt = new Packet(memReq, Packet::ReadReq, Packet::Broadcast);
-
-    pkt->dataStatic(&data);
-
-    if (!(memReq->getFlags() & UNCACHEABLE)) {
-        // Access memory to see if we have the same data
-        dcachePort->sendFunctional(pkt);
-    } else {
-        // Assume the data is correct if it's an uncached access
-        memcpy(&data, &unverifiedResult.integer, sizeof(T));
-    }
-
-    delete pkt;
-
-    return NoFault;
-}
-
-#ifndef DOXYGEN_SHOULD_SKIP_THIS
-
-template
-Fault
-CheckerCPU::read(Addr addr, uint64_t &data, unsigned flags);
-
-template
-Fault
-CheckerCPU::read(Addr addr, uint32_t &data, unsigned flags);
-
-template
-Fault
-CheckerCPU::read(Addr addr, uint16_t &data, unsigned flags);
-
-template
-Fault
-CheckerCPU::read(Addr addr, uint8_t &data, unsigned flags);
-
-#endif //DOXYGEN_SHOULD_SKIP_THIS
-
-template<>
-Fault
-CheckerCPU::read(Addr addr, double &data, unsigned flags)
-{
-    return read(addr, *(uint64_t*)&data, flags);
-}
-
-template<>
-Fault
-CheckerCPU::read(Addr addr, float &data, unsigned flags)
-{
-    return read(addr, *(uint32_t*)&data, flags);
-}
-
-template<>
-Fault
-CheckerCPU::read(Addr addr, int32_t &data, unsigned flags)
-{
-    return read(addr, (uint32_t&)data, flags);
-}
-
-template <class T>
-Fault
-CheckerCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
-{
-    // need to fill in CPU & thread IDs here
-    memReq = new Request();
-
-    memReq->setVirt(0, addr, sizeof(T), flags, thread->readPC());
-
-    // translate to physical address
-    thread->translateDataWriteReq(memReq);
-
-    // Can compare the write data and result only if it's cacheable,
-    // not a store conditional, or is a store conditional that
-    // succeeded.
-    // @todo: Verify that actual memory matches up with these values.
-    // Right now it only verifies that the instruction data is the
-    // same as what was in the request that got sent to memory; there
-    // is no verification that it is the same as what is in memory.
-    // This is because the LSQ would have to be snooped in the CPU to
-    // verify this data.
-    if (unverifiedReq &&
-        !(unverifiedReq->getFlags() & UNCACHEABLE) &&
-        (!(unverifiedReq->getFlags() & LOCKED) ||
-         ((unverifiedReq->getFlags() & LOCKED) &&
-          unverifiedReq->getScResult() == 1))) {
-        T inst_data;
-/*
-        // This code would work if the LSQ allowed for snooping.
-        Packet *pkt = new Packet(memReq, Packet::ReadReq, Packet::Broadcast);
-        pkt.dataStatic(&inst_data);
-
-        dcachePort->sendFunctional(pkt);
-
-        delete pkt;
-*/
-        memcpy(&inst_data, unverifiedMemData, sizeof(T));
-
-        if (data != inst_data) {
-            warn("%lli: Store value does not match value in memory! "
-                 "Instruction: %#x, memory: %#x",
-                 curTick, inst_data, data);
-            handleError();
-        }
-    }
-
-    // Assume the result was the same as the one passed in.  This checker
-    // doesn't check if the SC should succeed or fail, it just checks the
-    // value.
-    if (res && unverifiedReq->scResultValid())
-        *res = unverifiedReq->getScResult();
-
-    return NoFault;
-}
-
-
-#ifndef DOXYGEN_SHOULD_SKIP_THIS
-template
-Fault
-CheckerCPU::write(uint64_t data, Addr addr, unsigned flags, uint64_t *res);
-
-template
-Fault
-CheckerCPU::write(uint32_t data, Addr addr, unsigned flags, uint64_t *res);
-
-template
-Fault
-CheckerCPU::write(uint16_t data, Addr addr, unsigned flags, uint64_t *res);
-
-template
-Fault
-CheckerCPU::write(uint8_t data, Addr addr, unsigned flags, uint64_t *res);
-
-#endif //DOXYGEN_SHOULD_SKIP_THIS
-
-template<>
-Fault
-CheckerCPU::write(double data, Addr addr, unsigned flags, uint64_t *res)
-{
-    return write(*(uint64_t*)&data, addr, flags, res);
-}
-
-template<>
-Fault
-CheckerCPU::write(float data, Addr addr, unsigned flags, uint64_t *res)
-{
-    return write(*(uint32_t*)&data, addr, flags, res);
-}
-
-template<>
-Fault
-CheckerCPU::write(int32_t data, Addr addr, unsigned flags, uint64_t *res)
-{
-    return write((uint32_t)data, addr, flags, res);
-}
-
-
-#if FULL_SYSTEM
-Addr
-CheckerCPU::dbg_vtophys(Addr addr)
-{
-    return vtophys(tc, addr);
-}
-#endif // FULL_SYSTEM
-
-bool
-CheckerCPU::translateInstReq(Request *req)
-{
-#if FULL_SYSTEM
-    return (thread->translateInstReq(req) == NoFault);
-#else
-    thread->translateInstReq(req);
-    return true;
-#endif
-}
-
-void
-CheckerCPU::translateDataReadReq(Request *req)
-{
-    thread->translateDataReadReq(req);
-
-    if (req->getVaddr() != unverifiedReq->getVaddr()) {
-        warn("%lli: Request virtual addresses do not match! Inst: %#x, "
-             "checker: %#x",
-             curTick, unverifiedReq->getVaddr(), req->getVaddr());
-        handleError();
-    }
-    req->setPaddr(unverifiedReq->getPaddr());
-
-    if (checkFlags(req)) {
-        warn("%lli: Request flags do not match! Inst: %#x, checker: %#x",
-             curTick, unverifiedReq->getFlags(), req->getFlags());
-        handleError();
-    }
-}
-
-void
-CheckerCPU::translateDataWriteReq(Request *req)
-{
-    thread->translateDataWriteReq(req);
-
-    if (req->getVaddr() != unverifiedReq->getVaddr()) {
-        warn("%lli: Request virtual addresses do not match! Inst: %#x, "
-             "checker: %#x",
-             curTick, unverifiedReq->getVaddr(), req->getVaddr());
-        handleError();
-    }
-    req->setPaddr(unverifiedReq->getPaddr());
-
-    if (checkFlags(req)) {
-        warn("%lli: Request flags do not match! Inst: %#x, checker: %#x",
-             curTick, unverifiedReq->getFlags(), req->getFlags());
-        handleError();
-    }
-}
-
-bool
-CheckerCPU::checkFlags(Request *req)
-{
-    // Remove any dynamic flags that don't have to do with the request itself.
-    unsigned flags = unverifiedReq->getFlags();
-    unsigned mask = LOCKED | PHYSICAL | VPTE | ALTMODE | UNCACHEABLE | NO_FAULT;
-    flags = flags & (mask);
-    if (flags == req->getFlags()) {
-        return false;
-    } else {
-        return true;
-    }
-}
-
-void
-CheckerCPU::dumpAndExit()
-{
-    warn("%lli: Checker PC:%#x, next PC:%#x",
-         curTick, thread->readPC(), thread->readNextPC());
-    panic("Checker found an error!");
-}
-
-template <class DynInstPtr>
-void
-Checker<DynInstPtr>::verify(DynInstPtr &completed_inst)
-{
-    DynInstPtr inst;
-
-    // Either check this instruction, or add it to a list of
-    // instructions waiting to be checked.  Instructions must be
-    // checked in program order, so if a store has committed yet not
-    // completed, there may be some instructions that are waiting
-    // behind it that have completed and must be checked.
-    if (!instList.empty()) {
-        if (youngestSN < completed_inst->seqNum) {
-            DPRINTF(Checker, "Adding instruction [sn:%lli] PC:%#x to list.\n",
-                    completed_inst->seqNum, completed_inst->readPC());
-            instList.push_back(completed_inst);
-            youngestSN = completed_inst->seqNum;
-        }
-
-        if (!instList.front()->isCompleted()) {
-            return;
-        } else {
-            inst = instList.front();
-            instList.pop_front();
-        }
-    } else {
-        if (!completed_inst->isCompleted()) {
-            if (youngestSN < completed_inst->seqNum) {
-                DPRINTF(Checker, "Adding instruction [sn:%lli] PC:%#x to list.\n",
-                        completed_inst->seqNum, completed_inst->readPC());
-                instList.push_back(completed_inst);
-                youngestSN = completed_inst->seqNum;
-            }
-            return;
-        } else {
-            if (youngestSN < completed_inst->seqNum) {
-                inst = completed_inst;
-                youngestSN = completed_inst->seqNum;
-            } else {
-                return;
-            }
-        }
-    }
-
-    // Try to check all instructions that are completed, ending if we
-    // run out of instructions to check or if an instruction is not
-    // yet completed.
-    while (1) {
-        DPRINTF(Checker, "Processing instruction [sn:%lli] PC:%#x.\n",
-                inst->seqNum, inst->readPC());
-        unverifiedResult.integer = inst->readIntResult();
-        unverifiedReq = inst->req;
-        unverifiedMemData = inst->memData;
-        numCycles++;
-
-        Fault fault = NoFault;
-
-        // maintain $r0 semantics
-        thread->setIntReg(ZeroReg, 0);
-#ifdef TARGET_ALPHA
-        thread->setFloatRegDouble(ZeroReg, 0.0);
-#endif // TARGET_ALPHA
-
-        // Check if any recent PC changes match up with anything we
-        // expect to happen.  This is mostly to check if traps or
-        // PC-based events have occurred in both the checker and CPU.
-        if (changedPC) {
-            DPRINTF(Checker, "Changed PC recently to %#x\n",
-                    thread->readPC());
-            if (willChangePC) {
-                if (newPC == thread->readPC()) {
-                    DPRINTF(Checker, "Changed PC matches expected PC\n");
-                } else {
-                    warn("%lli: Changed PC does not match expected PC, "
-                         "changed: %#x, expected: %#x",
-                         curTick, thread->readPC(), newPC);
-                    CheckerCPU::handleError();
-                }
-                willChangePC = false;
-            }
-            changedPC = false;
-        }
-        if (changedNextPC) {
-            DPRINTF(Checker, "Changed NextPC recently to %#x\n",
-                    thread->readNextPC());
-            changedNextPC = false;
-        }
-
-        // Try to fetch the instruction
-
-#if FULL_SYSTEM
-#define IFETCH_FLAGS(pc)       ((pc) & 1) ? PHYSICAL : 0
-#else
-#define IFETCH_FLAGS(pc)       0
-#endif
-
-        uint64_t fetch_PC = thread->readPC() & ~3;
-
-        // set up memory request for instruction fetch
-        memReq = new Request(inst->threadNumber, fetch_PC,
-                             sizeof(uint32_t),
-                             IFETCH_FLAGS(thread->readPC()),
-                             fetch_PC, thread->readCpuId(), inst->threadNumber);
-
-        bool succeeded = translateInstReq(memReq);
-
-        if (!succeeded) {
-            if (inst->getFault() == NoFault) {
-                // In this case the instruction was not a dummy
-                // instruction carrying an ITB fault.  In the single
-                // threaded case the ITB should still be able to
-                // translate this instruction; in the SMT case it's
-                // possible that its ITB entry was kicked out.
-                warn("%lli: Instruction PC %#x was not found in the ITB!",
-                     curTick, thread->readPC());
-                handleError(inst);
-
-                // go to the next instruction
-                thread->setPC(thread->readNextPC());
-                thread->setNextPC(thread->readNextPC() + sizeof(MachInst));
-
-                return;
-            } else {
-                // The instruction is carrying an ITB fault.  Handle
-                // the fault and see if our results match the CPU on
-                // the next tick().
-                fault = inst->getFault();
-            }
-        }
-
-        if (fault == NoFault) {
-            Packet *pkt = new Packet(memReq, Packet::ReadReq,
-                                     Packet::Broadcast);
-
-            pkt->dataStatic(&machInst);
-
-            icachePort->sendFunctional(pkt);
-
-            delete pkt;
-
-            // keep an instruction count
-            numInst++;
-
-            // decode the instruction
-            machInst = gtoh(machInst);
-            // Checks that the instruction matches what we expected it to be.
-            // Checks both the machine instruction and the PC.
-            validateInst(inst);
-
-            curStaticInst = StaticInst::decode(makeExtMI(machInst,
-                                                         thread->readPC()));
-
-#if FULL_SYSTEM
-            thread->setInst(machInst);
-#endif // FULL_SYSTEM
-
-            fault = inst->getFault();
-        }
-
-        // Discard fetch's memReq.
-        delete memReq;
-        memReq = NULL;
-
-        // Either the instruction was a fault and we should process the fault,
-        // or we should just go ahead execute the instruction.  This assumes
-        // that the instruction is properly marked as a fault.
-        if (fault == NoFault) {
-
-            thread->funcExeInst++;
-
-            fault = curStaticInst->execute(this, NULL);
-
-            // Checks to make sure instrution results are correct.
-            validateExecution(inst);
-
-            if (curStaticInst->isLoad()) {
-                ++numLoad;
-            }
-        }
-
-        if (fault != NoFault) {
-#if FULL_SYSTEM
-            fault->invoke(tc);
-            willChangePC = true;
-            newPC = thread->readPC();
-            DPRINTF(Checker, "Fault, PC is now %#x\n", newPC);
-#else // !FULL_SYSTEM
-            fatal("fault (%d) detected @ PC 0x%08p", fault, thread->readPC());
-#endif // FULL_SYSTEM
-        } else {
-#if THE_ISA != MIPS_ISA
-            // go to the next instruction
-            thread->setPC(thread->readNextPC());
-            thread->setNextPC(thread->readNextPC() + sizeof(MachInst));
-#else
-            // go to the next instruction
-            thread->setPC(thread->readNextPC());
-            thread->setNextPC(thread->readNextNPC());
-            thread->setNextNPC(thread->readNextNPC() + sizeof(MachInst));
-#endif
-
-        }
-
-#if FULL_SYSTEM
-        // @todo: Determine if these should happen only if the
-        // instruction hasn't faulted.  In the SimpleCPU case this may
-        // not be true, but in the O3 or Ozone case this may be true.
-        Addr oldpc;
-        int count = 0;
-        do {
-            oldpc = thread->readPC();
-            system->pcEventQueue.service(tc);
-            count++;
-        } while (oldpc != thread->readPC());
-        if (count > 1) {
-            willChangePC = true;
-            newPC = thread->readPC();
-            DPRINTF(Checker, "PC Event, PC is now %#x\n", newPC);
-        }
-#endif
-
-        // @todo:  Optionally can check all registers. (Or just those
-        // that have been modified).
-        validateState();
-
-        if (memReq) {
-            delete memReq;
-            memReq = NULL;
-        }
-
-        // Continue verifying instructions if there's another completed
-        // instruction waiting to be verified.
-        if (instList.empty()) {
-            break;
-        } else if (instList.front()->isCompleted()) {
-            inst = instList.front();
-            instList.pop_front();
-        } else {
-            break;
-        }
-    }
-}
-
-template <class DynInstPtr>
-void
-Checker<DynInstPtr>::switchOut(Sampler *s)
-{
-    instList.clear();
-}
-
-template <class DynInstPtr>
-void
-Checker<DynInstPtr>::takeOverFrom(BaseCPU *oldCPU)
-{
-}
-
-template <class DynInstPtr>
-void
-Checker<DynInstPtr>::validateInst(DynInstPtr &inst)
-{
-    if (inst->readPC() != thread->readPC()) {
-        warn("%lli: PCs do not match! Inst: %#x, checker: %#x",
-             curTick, inst->readPC(), thread->readPC());
-        if (changedPC) {
-            warn("%lli: Changed PCs recently, may not be an error",
-                 curTick);
-        } else {
-            handleError(inst);
-        }
-    }
-
-    MachInst mi = static_cast<MachInst>(inst->staticInst->machInst);
-
-    if (mi != machInst) {
-        warn("%lli: Binary instructions do not match! Inst: %#x, "
-             "checker: %#x",
-             curTick, mi, machInst);
-        handleError(inst);
-    }
-}
-
-template <class DynInstPtr>
-void
-Checker<DynInstPtr>::validateExecution(DynInstPtr &inst)
-{
-    bool result_mismatch = false;
-    if (inst->numDestRegs()) {
-        // @todo: Support more destination registers.
-        if (inst->isUnverifiable()) {
-            // Unverifiable instructions assume they were executed
-            // properly by the CPU. Grab the result from the
-            // instruction and write it to the register.
-            copyResult(inst);
-        } else if (result.integer != inst->readIntResult()) {
-            result_mismatch = true;
-        }
-    }
-
-    if (result_mismatch) {
-        warn("%lli: Instruction results do not match! (Values may not "
-             "actually be integers) Inst: %#x, checker: %#x",
-             curTick, inst->readIntResult(), result.integer);
-
-        // It's useful to verify load values from memory, but in MP
-        // systems the value obtained at execute may be different than
-        // the value obtained at completion.  Similarly DMA can
-        // present the same problem on even UP systems.  Thus there is
-        // the option to only warn on loads having a result error.
-        if (inst->isLoad() && warnOnlyOnLoadError) {
-            copyResult(inst);
-        } else {
-            handleError(inst);
-        }
-    }
-
-    if (inst->readNextPC() != thread->readNextPC()) {
-        warn("%lli: Instruction next PCs do not match! Inst: %#x, "
-             "checker: %#x",
-             curTick, inst->readNextPC(), thread->readNextPC());
-        handleError(inst);
-    }
-
-    // Checking side effect registers can be difficult if they are not
-    // checked simultaneously with the execution of the instruction.
-    // This is because other valid instructions may have modified
-    // these registers in the meantime, and their values are not
-    // stored within the DynInst.
-    while (!miscRegIdxs.empty()) {
-        int misc_reg_idx = miscRegIdxs.front();
-        miscRegIdxs.pop();
-
-        if (inst->tcBase()->readMiscReg(misc_reg_idx) !=
-            thread->readMiscReg(misc_reg_idx)) {
-            warn("%lli: Misc reg idx %i (side effect) does not match! "
-                 "Inst: %#x, checker: %#x",
-                 curTick, misc_reg_idx,
-                 inst->tcBase()->readMiscReg(misc_reg_idx),
-                 thread->readMiscReg(misc_reg_idx));
-            handleError(inst);
-        }
-    }
-}
-
-template <class DynInstPtr>
-void
-Checker<DynInstPtr>::validateState()
-{
-}
-
-template <class DynInstPtr>
-void
-Checker<DynInstPtr>::copyResult(DynInstPtr &inst)
-{
-    RegIndex idx = inst->destRegIdx(0);
-    if (idx < TheISA::FP_Base_DepTag) {
-        thread->setIntReg(idx, inst->readIntResult());
-    } else if (idx < TheISA::Fpcr_DepTag) {
-        thread->setFloatRegBits(idx, inst->readIntResult());
-    } else {
-        thread->setMiscReg(idx, inst->readIntResult());
-    }
-}
-
-template <class DynInstPtr>
-void
-Checker<DynInstPtr>::dumpAndExit(DynInstPtr &inst)
-{
-    cprintf("Error detected, instruction information:\n");
-    cprintf("PC:%#x, nextPC:%#x\n[sn:%lli]\n[tid:%i]\n"
-            "Completed:%i\n",
-            inst->readPC(),
-            inst->readNextPC(),
-            inst->seqNum,
-            inst->threadNumber,
-            inst->isCompleted());
-    inst->dump();
-    CheckerCPU::dumpAndExit();
-}
-
-template <class DynInstPtr>
-void
-Checker<DynInstPtr>::dumpInsts()
-{
-    int num = 0;
-
-    InstListIt inst_list_it = --(instList.end());
-
-    cprintf("Inst list size: %i\n", instList.size());
-
-    while (inst_list_it != instList.end())
-    {
-        cprintf("Instruction:%i\n",
-                num);
-
-        cprintf("PC:%#x\n[sn:%lli]\n[tid:%i]\n"
-                "Completed:%i\n",
-                (*inst_list_it)->readPC(),
-                (*inst_list_it)->seqNum,
-                (*inst_list_it)->threadNumber,
-                (*inst_list_it)->isCompleted());
-
-        cprintf("\n");
-
-        inst_list_it--;
-        ++num;
-    }
-
-}
-
-//template
-//class Checker<RefCountingPtr<OzoneDynInst<OzoneImpl> > >;
-// Manually instantiate checker
-template
-class Checker<RefCountingPtr<AlphaDynInst<AlphaSimpleImpl> > >;
diff --git a/src/cpu/checker/cpu_impl.hh b/src/cpu/checker/cpu_impl.hh
new file mode 100644 (file)
index 0000000..5091c7c
--- /dev/null
@@ -0,0 +1,822 @@
+/*
+ * 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.
+ *
+ * Authors: Kevin Lim
+ */
+
+#include <list>
+#include <string>
+
+#include "base/refcnt.hh"
+#include "cpu/base.hh"
+#include "cpu/base_dyn_inst.hh"
+#include "cpu/checker/cpu.hh"
+#include "cpu/simple_thread.hh"
+#include "cpu/thread_context.hh"
+#include "cpu/static_inst.hh"
+#include "mem/packet_impl.hh"
+#include "sim/byteswap.hh"
+#include "sim/sim_object.hh"
+#include "sim/stats.hh"
+
+#if FULL_SYSTEM
+#include "sim/system.hh"
+#include "arch/vtophys.hh"
+#include "kern/kernel_stats.hh"
+#endif // FULL_SYSTEM
+
+using namespace std;
+//The CheckerCPU does alpha only
+using namespace AlphaISA;
+
+void
+CheckerCPU::init()
+{
+}
+
+CheckerCPU::CheckerCPU(Params *p)
+    : BaseCPU(p), thread(NULL), tc(NULL)
+{
+    memReq = NULL;
+
+    numInst = 0;
+    startNumInst = 0;
+    numLoad = 0;
+    startNumLoad = 0;
+    youngestSN = 0;
+
+    changedPC = willChangePC = changedNextPC = false;
+
+    exitOnError = p->exitOnError;
+    warnOnlyOnLoadError = p->warnOnlyOnLoadError;
+#if FULL_SYSTEM
+    itb = p->itb;
+    dtb = p->dtb;
+    systemPtr = NULL;
+#else
+    process = p->process;
+#endif
+
+    result.integer = 0;
+}
+
+CheckerCPU::~CheckerCPU()
+{
+}
+
+void
+CheckerCPU::setMemory(MemObject *mem)
+{
+#if !FULL_SYSTEM
+    memPtr = mem;
+    thread = new SimpleThread(this, /* thread_num */ 0, process,
+                              /* asid */ 0, mem);
+
+    thread->setStatus(ThreadContext::Suspended);
+    tc = thread->getTC();
+    threadContexts.push_back(tc);
+#endif
+}
+
+void
+CheckerCPU::setSystem(System *system)
+{
+#if FULL_SYSTEM
+    systemPtr = system;
+
+    thread = new SimpleThread(this, 0, systemPtr, itb, dtb, false);
+
+    thread->setStatus(ThreadContext::Suspended);
+    tc = thread->getTC();
+    threadContexts.push_back(tc);
+    delete thread->kernelStats;
+    thread->kernelStats = NULL;
+#endif
+}
+
+void
+CheckerCPU::setIcachePort(Port *icache_port)
+{
+    icachePort = icache_port;
+}
+
+void
+CheckerCPU::setDcachePort(Port *dcache_port)
+{
+    dcachePort = dcache_port;
+}
+
+void
+CheckerCPU::serialize(ostream &os)
+{
+/*
+    BaseCPU::serialize(os);
+    SERIALIZE_SCALAR(inst);
+    nameOut(os, csprintf("%s.xc", name()));
+    thread->serialize(os);
+    cacheCompletionEvent.serialize(os);
+*/
+}
+
+void
+CheckerCPU::unserialize(Checkpoint *cp, const string &section)
+{
+/*
+    BaseCPU::unserialize(cp, section);
+    UNSERIALIZE_SCALAR(inst);
+    thread->unserialize(cp, csprintf("%s.xc", section));
+*/
+}
+
+Fault
+CheckerCPU::copySrcTranslate(Addr src)
+{
+    panic("Unimplemented!");
+}
+
+Fault
+CheckerCPU::copy(Addr dest)
+{
+    panic("Unimplemented!");
+}
+
+template <class T>
+Fault
+CheckerCPU::read(Addr addr, T &data, unsigned flags)
+{
+    // need to fill in CPU & thread IDs here
+    memReq = new Request();
+
+    memReq->setVirt(0, addr, sizeof(T), flags, thread->readPC());
+
+    // translate to physical address
+    translateDataReadReq(memReq);
+
+    Packet *pkt = new Packet(memReq, Packet::ReadReq, Packet::Broadcast);
+
+    pkt->dataStatic(&data);
+
+    if (!(memReq->getFlags() & UNCACHEABLE)) {
+        // Access memory to see if we have the same data
+        dcachePort->sendFunctional(pkt);
+    } else {
+        // Assume the data is correct if it's an uncached access
+        memcpy(&data, &unverifiedResult.integer, sizeof(T));
+    }
+
+    delete pkt;
+
+    return NoFault;
+}
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+template
+Fault
+CheckerCPU::read(Addr addr, uint64_t &data, unsigned flags);
+
+template
+Fault
+CheckerCPU::read(Addr addr, uint32_t &data, unsigned flags);
+
+template
+Fault
+CheckerCPU::read(Addr addr, uint16_t &data, unsigned flags);
+
+template
+Fault
+CheckerCPU::read(Addr addr, uint8_t &data, unsigned flags);
+
+#endif //DOXYGEN_SHOULD_SKIP_THIS
+
+template<>
+Fault
+CheckerCPU::read(Addr addr, double &data, unsigned flags)
+{
+    return read(addr, *(uint64_t*)&data, flags);
+}
+
+template<>
+Fault
+CheckerCPU::read(Addr addr, float &data, unsigned flags)
+{
+    return read(addr, *(uint32_t*)&data, flags);
+}
+
+template<>
+Fault
+CheckerCPU::read(Addr addr, int32_t &data, unsigned flags)
+{
+    return read(addr, (uint32_t&)data, flags);
+}
+
+template <class T>
+Fault
+CheckerCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
+{
+    // need to fill in CPU & thread IDs here
+    memReq = new Request();
+
+    memReq->setVirt(0, addr, sizeof(T), flags, thread->readPC());
+
+    // translate to physical address
+    thread->translateDataWriteReq(memReq);
+
+    // Can compare the write data and result only if it's cacheable,
+    // not a store conditional, or is a store conditional that
+    // succeeded.
+    // @todo: Verify that actual memory matches up with these values.
+    // Right now it only verifies that the instruction data is the
+    // same as what was in the request that got sent to memory; there
+    // is no verification that it is the same as what is in memory.
+    // This is because the LSQ would have to be snooped in the CPU to
+    // verify this data.
+    if (unverifiedReq &&
+        !(unverifiedReq->getFlags() & UNCACHEABLE) &&
+        (!(unverifiedReq->getFlags() & LOCKED) ||
+         ((unverifiedReq->getFlags() & LOCKED) &&
+          unverifiedReq->getScResult() == 1))) {
+        T inst_data;
+/*
+        // This code would work if the LSQ allowed for snooping.
+        Packet *pkt = new Packet(memReq, Packet::ReadReq, Packet::Broadcast);
+        pkt.dataStatic(&inst_data);
+
+        dcachePort->sendFunctional(pkt);
+
+        delete pkt;
+*/
+        memcpy(&inst_data, unverifiedMemData, sizeof(T));
+
+        if (data != inst_data) {
+            warn("%lli: Store value does not match value in memory! "
+                 "Instruction: %#x, memory: %#x",
+                 curTick, inst_data, data);
+            handleError();
+        }
+    }
+
+    // Assume the result was the same as the one passed in.  This checker
+    // doesn't check if the SC should succeed or fail, it just checks the
+    // value.
+    if (res && unverifiedReq->scResultValid())
+        *res = unverifiedReq->getScResult();
+
+    return NoFault;
+}
+
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+template
+Fault
+CheckerCPU::write(uint64_t data, Addr addr, unsigned flags, uint64_t *res);
+
+template
+Fault
+CheckerCPU::write(uint32_t data, Addr addr, unsigned flags, uint64_t *res);
+
+template
+Fault
+CheckerCPU::write(uint16_t data, Addr addr, unsigned flags, uint64_t *res);
+
+template
+Fault
+CheckerCPU::write(uint8_t data, Addr addr, unsigned flags, uint64_t *res);
+
+#endif //DOXYGEN_SHOULD_SKIP_THIS
+
+template<>
+Fault
+CheckerCPU::write(double data, Addr addr, unsigned flags, uint64_t *res)
+{
+    return write(*(uint64_t*)&data, addr, flags, res);
+}
+
+template<>
+Fault
+CheckerCPU::write(float data, Addr addr, unsigned flags, uint64_t *res)
+{
+    return write(*(uint32_t*)&data, addr, flags, res);
+}
+
+template<>
+Fault
+CheckerCPU::write(int32_t data, Addr addr, unsigned flags, uint64_t *res)
+{
+    return write((uint32_t)data, addr, flags, res);
+}
+
+
+#if FULL_SYSTEM
+Addr
+CheckerCPU::dbg_vtophys(Addr addr)
+{
+    return vtophys(tc, addr);
+}
+#endif // FULL_SYSTEM
+
+bool
+CheckerCPU::translateInstReq(Request *req)
+{
+#if FULL_SYSTEM
+    return (thread->translateInstReq(req) == NoFault);
+#else
+    thread->translateInstReq(req);
+    return true;
+#endif
+}
+
+void
+CheckerCPU::translateDataReadReq(Request *req)
+{
+    thread->translateDataReadReq(req);
+
+    if (req->getVaddr() != unverifiedReq->getVaddr()) {
+        warn("%lli: Request virtual addresses do not match! Inst: %#x, "
+             "checker: %#x",
+             curTick, unverifiedReq->getVaddr(), req->getVaddr());
+        handleError();
+    }
+    req->setPaddr(unverifiedReq->getPaddr());
+
+    if (checkFlags(req)) {
+        warn("%lli: Request flags do not match! Inst: %#x, checker: %#x",
+             curTick, unverifiedReq->getFlags(), req->getFlags());
+        handleError();
+    }
+}
+
+void
+CheckerCPU::translateDataWriteReq(Request *req)
+{
+    thread->translateDataWriteReq(req);
+
+    if (req->getVaddr() != unverifiedReq->getVaddr()) {
+        warn("%lli: Request virtual addresses do not match! Inst: %#x, "
+             "checker: %#x",
+             curTick, unverifiedReq->getVaddr(), req->getVaddr());
+        handleError();
+    }
+    req->setPaddr(unverifiedReq->getPaddr());
+
+    if (checkFlags(req)) {
+        warn("%lli: Request flags do not match! Inst: %#x, checker: %#x",
+             curTick, unverifiedReq->getFlags(), req->getFlags());
+        handleError();
+    }
+}
+
+bool
+CheckerCPU::checkFlags(Request *req)
+{
+    // Remove any dynamic flags that don't have to do with the request itself.
+    unsigned flags = unverifiedReq->getFlags();
+    unsigned mask = LOCKED | PHYSICAL | VPTE | ALTMODE | UNCACHEABLE | NO_FAULT;
+    flags = flags & (mask);
+    if (flags == req->getFlags()) {
+        return false;
+    } else {
+        return true;
+    }
+}
+
+void
+CheckerCPU::dumpAndExit()
+{
+    warn("%lli: Checker PC:%#x, next PC:%#x",
+         curTick, thread->readPC(), thread->readNextPC());
+    panic("Checker found an error!");
+}
+
+template <class DynInstPtr>
+void
+Checker<DynInstPtr>::verify(DynInstPtr &completed_inst)
+{
+    DynInstPtr inst;
+
+    // Either check this instruction, or add it to a list of
+    // instructions waiting to be checked.  Instructions must be
+    // checked in program order, so if a store has committed yet not
+    // completed, there may be some instructions that are waiting
+    // behind it that have completed and must be checked.
+    if (!instList.empty()) {
+        if (youngestSN < completed_inst->seqNum) {
+            DPRINTF(Checker, "Adding instruction [sn:%lli] PC:%#x to list.\n",
+                    completed_inst->seqNum, completed_inst->readPC());
+            instList.push_back(completed_inst);
+            youngestSN = completed_inst->seqNum;
+        }
+
+        if (!instList.front()->isCompleted()) {
+            return;
+        } else {
+            inst = instList.front();
+            instList.pop_front();
+        }
+    } else {
+        if (!completed_inst->isCompleted()) {
+            if (youngestSN < completed_inst->seqNum) {
+                DPRINTF(Checker, "Adding instruction [sn:%lli] PC:%#x to list.\n",
+                        completed_inst->seqNum, completed_inst->readPC());
+                instList.push_back(completed_inst);
+                youngestSN = completed_inst->seqNum;
+            }
+            return;
+        } else {
+            if (youngestSN < completed_inst->seqNum) {
+                inst = completed_inst;
+                youngestSN = completed_inst->seqNum;
+            } else {
+                return;
+            }
+        }
+    }
+
+    // Try to check all instructions that are completed, ending if we
+    // run out of instructions to check or if an instruction is not
+    // yet completed.
+    while (1) {
+        DPRINTF(Checker, "Processing instruction [sn:%lli] PC:%#x.\n",
+                inst->seqNum, inst->readPC());
+        unverifiedResult.integer = inst->readIntResult();
+        unverifiedReq = inst->req;
+        unverifiedMemData = inst->memData;
+        numCycles++;
+
+        Fault fault = NoFault;
+
+        // maintain $r0 semantics
+        thread->setIntReg(ZeroReg, 0);
+#ifdef TARGET_ALPHA
+        thread->setFloatRegDouble(ZeroReg, 0.0);
+#endif // TARGET_ALPHA
+
+        // Check if any recent PC changes match up with anything we
+        // expect to happen.  This is mostly to check if traps or
+        // PC-based events have occurred in both the checker and CPU.
+        if (changedPC) {
+            DPRINTF(Checker, "Changed PC recently to %#x\n",
+                    thread->readPC());
+            if (willChangePC) {
+                if (newPC == thread->readPC()) {
+                    DPRINTF(Checker, "Changed PC matches expected PC\n");
+                } else {
+                    warn("%lli: Changed PC does not match expected PC, "
+                         "changed: %#x, expected: %#x",
+                         curTick, thread->readPC(), newPC);
+                    CheckerCPU::handleError();
+                }
+                willChangePC = false;
+            }
+            changedPC = false;
+        }
+        if (changedNextPC) {
+            DPRINTF(Checker, "Changed NextPC recently to %#x\n",
+                    thread->readNextPC());
+            changedNextPC = false;
+        }
+
+        // Try to fetch the instruction
+
+#if FULL_SYSTEM
+#define IFETCH_FLAGS(pc)       ((pc) & 1) ? PHYSICAL : 0
+#else
+#define IFETCH_FLAGS(pc)       0
+#endif
+
+        uint64_t fetch_PC = thread->readPC() & ~3;
+
+        // set up memory request for instruction fetch
+        memReq = new Request(inst->threadNumber, fetch_PC,
+                             sizeof(uint32_t),
+                             IFETCH_FLAGS(thread->readPC()),
+                             fetch_PC, thread->readCpuId(), inst->threadNumber);
+
+        bool succeeded = translateInstReq(memReq);
+
+        if (!succeeded) {
+            if (inst->getFault() == NoFault) {
+                // In this case the instruction was not a dummy
+                // instruction carrying an ITB fault.  In the single
+                // threaded case the ITB should still be able to
+                // translate this instruction; in the SMT case it's
+                // possible that its ITB entry was kicked out.
+                warn("%lli: Instruction PC %#x was not found in the ITB!",
+                     curTick, thread->readPC());
+                handleError(inst);
+
+                // go to the next instruction
+                thread->setPC(thread->readNextPC());
+                thread->setNextPC(thread->readNextPC() + sizeof(MachInst));
+
+                return;
+            } else {
+                // The instruction is carrying an ITB fault.  Handle
+                // the fault and see if our results match the CPU on
+                // the next tick().
+                fault = inst->getFault();
+            }
+        }
+
+        if (fault == NoFault) {
+            Packet *pkt = new Packet(memReq, Packet::ReadReq,
+                                     Packet::Broadcast);
+
+            pkt->dataStatic(&machInst);
+
+            icachePort->sendFunctional(pkt);
+
+            delete pkt;
+
+            // keep an instruction count
+            numInst++;
+
+            // decode the instruction
+            machInst = gtoh(machInst);
+            // Checks that the instruction matches what we expected it to be.
+            // Checks both the machine instruction and the PC.
+            validateInst(inst);
+
+            curStaticInst = StaticInst::decode(makeExtMI(machInst,
+                                                         thread->readPC()));
+
+#if FULL_SYSTEM
+            thread->setInst(machInst);
+#endif // FULL_SYSTEM
+
+            fault = inst->getFault();
+        }
+
+        // Discard fetch's memReq.
+        delete memReq;
+        memReq = NULL;
+
+        // Either the instruction was a fault and we should process the fault,
+        // or we should just go ahead execute the instruction.  This assumes
+        // that the instruction is properly marked as a fault.
+        if (fault == NoFault) {
+
+            thread->funcExeInst++;
+
+            fault = curStaticInst->execute(this, NULL);
+
+            // Checks to make sure instrution results are correct.
+            validateExecution(inst);
+
+            if (curStaticInst->isLoad()) {
+                ++numLoad;
+            }
+        }
+
+        if (fault != NoFault) {
+#if FULL_SYSTEM
+            fault->invoke(tc);
+            willChangePC = true;
+            newPC = thread->readPC();
+            DPRINTF(Checker, "Fault, PC is now %#x\n", newPC);
+#else // !FULL_SYSTEM
+            fatal("fault (%d) detected @ PC 0x%08p", fault, thread->readPC());
+#endif // FULL_SYSTEM
+        } else {
+#if THE_ISA != MIPS_ISA
+            // go to the next instruction
+            thread->setPC(thread->readNextPC());
+            thread->setNextPC(thread->readNextPC() + sizeof(MachInst));
+#else
+            // go to the next instruction
+            thread->setPC(thread->readNextPC());
+            thread->setNextPC(thread->readNextNPC());
+            thread->setNextNPC(thread->readNextNPC() + sizeof(MachInst));
+#endif
+
+        }
+
+#if FULL_SYSTEM
+        // @todo: Determine if these should happen only if the
+        // instruction hasn't faulted.  In the SimpleCPU case this may
+        // not be true, but in the O3 or Ozone case this may be true.
+        Addr oldpc;
+        int count = 0;
+        do {
+            oldpc = thread->readPC();
+            system->pcEventQueue.service(tc);
+            count++;
+        } while (oldpc != thread->readPC());
+        if (count > 1) {
+            willChangePC = true;
+            newPC = thread->readPC();
+            DPRINTF(Checker, "PC Event, PC is now %#x\n", newPC);
+        }
+#endif
+
+        // @todo:  Optionally can check all registers. (Or just those
+        // that have been modified).
+        validateState();
+
+        if (memReq) {
+            delete memReq;
+            memReq = NULL;
+        }
+
+        // Continue verifying instructions if there's another completed
+        // instruction waiting to be verified.
+        if (instList.empty()) {
+            break;
+        } else if (instList.front()->isCompleted()) {
+            inst = instList.front();
+            instList.pop_front();
+        } else {
+            break;
+        }
+    }
+}
+
+template <class DynInstPtr>
+void
+Checker<DynInstPtr>::switchOut(Sampler *s)
+{
+    instList.clear();
+}
+
+template <class DynInstPtr>
+void
+Checker<DynInstPtr>::takeOverFrom(BaseCPU *oldCPU)
+{
+}
+
+template <class DynInstPtr>
+void
+Checker<DynInstPtr>::validateInst(DynInstPtr &inst)
+{
+    if (inst->readPC() != thread->readPC()) {
+        warn("%lli: PCs do not match! Inst: %#x, checker: %#x",
+             curTick, inst->readPC(), thread->readPC());
+        if (changedPC) {
+            warn("%lli: Changed PCs recently, may not be an error",
+                 curTick);
+        } else {
+            handleError(inst);
+        }
+    }
+
+    MachInst mi = static_cast<MachInst>(inst->staticInst->machInst);
+
+    if (mi != machInst) {
+        warn("%lli: Binary instructions do not match! Inst: %#x, "
+             "checker: %#x",
+             curTick, mi, machInst);
+        handleError(inst);
+    }
+}
+
+template <class DynInstPtr>
+void
+Checker<DynInstPtr>::validateExecution(DynInstPtr &inst)
+{
+    bool result_mismatch = false;
+    if (inst->numDestRegs()) {
+        // @todo: Support more destination registers.
+        if (inst->isUnverifiable()) {
+            // Unverifiable instructions assume they were executed
+            // properly by the CPU. Grab the result from the
+            // instruction and write it to the register.
+            copyResult(inst);
+        } else if (result.integer != inst->readIntResult()) {
+            result_mismatch = true;
+        }
+    }
+
+    if (result_mismatch) {
+        warn("%lli: Instruction results do not match! (Values may not "
+             "actually be integers) Inst: %#x, checker: %#x",
+             curTick, inst->readIntResult(), result.integer);
+
+        // It's useful to verify load values from memory, but in MP
+        // systems the value obtained at execute may be different than
+        // the value obtained at completion.  Similarly DMA can
+        // present the same problem on even UP systems.  Thus there is
+        // the option to only warn on loads having a result error.
+        if (inst->isLoad() && warnOnlyOnLoadError) {
+            copyResult(inst);
+        } else {
+            handleError(inst);
+        }
+    }
+
+    if (inst->readNextPC() != thread->readNextPC()) {
+        warn("%lli: Instruction next PCs do not match! Inst: %#x, "
+             "checker: %#x",
+             curTick, inst->readNextPC(), thread->readNextPC());
+        handleError(inst);
+    }
+
+    // Checking side effect registers can be difficult if they are not
+    // checked simultaneously with the execution of the instruction.
+    // This is because other valid instructions may have modified
+    // these registers in the meantime, and their values are not
+    // stored within the DynInst.
+    while (!miscRegIdxs.empty()) {
+        int misc_reg_idx = miscRegIdxs.front();
+        miscRegIdxs.pop();
+
+        if (inst->tcBase()->readMiscReg(misc_reg_idx) !=
+            thread->readMiscReg(misc_reg_idx)) {
+            warn("%lli: Misc reg idx %i (side effect) does not match! "
+                 "Inst: %#x, checker: %#x",
+                 curTick, misc_reg_idx,
+                 inst->tcBase()->readMiscReg(misc_reg_idx),
+                 thread->readMiscReg(misc_reg_idx));
+            handleError(inst);
+        }
+    }
+}
+
+template <class DynInstPtr>
+void
+Checker<DynInstPtr>::validateState()
+{
+}
+
+template <class DynInstPtr>
+void
+Checker<DynInstPtr>::copyResult(DynInstPtr &inst)
+{
+    RegIndex idx = inst->destRegIdx(0);
+    if (idx < TheISA::FP_Base_DepTag) {
+        thread->setIntReg(idx, inst->readIntResult());
+    } else if (idx < TheISA::Fpcr_DepTag) {
+        thread->setFloatRegBits(idx, inst->readIntResult());
+    } else {
+        thread->setMiscReg(idx, inst->readIntResult());
+    }
+}
+
+template <class DynInstPtr>
+void
+Checker<DynInstPtr>::dumpAndExit(DynInstPtr &inst)
+{
+    cprintf("Error detected, instruction information:\n");
+    cprintf("PC:%#x, nextPC:%#x\n[sn:%lli]\n[tid:%i]\n"
+            "Completed:%i\n",
+            inst->readPC(),
+            inst->readNextPC(),
+            inst->seqNum,
+            inst->threadNumber,
+            inst->isCompleted());
+    inst->dump();
+    CheckerCPU::dumpAndExit();
+}
+
+template <class DynInstPtr>
+void
+Checker<DynInstPtr>::dumpInsts()
+{
+    int num = 0;
+
+    InstListIt inst_list_it = --(instList.end());
+
+    cprintf("Inst list size: %i\n", instList.size());
+
+    while (inst_list_it != instList.end())
+    {
+        cprintf("Instruction:%i\n",
+                num);
+
+        cprintf("PC:%#x\n[sn:%lli]\n[tid:%i]\n"
+                "Completed:%i\n",
+                (*inst_list_it)->readPC(),
+                (*inst_list_it)->seqNum,
+                (*inst_list_it)->threadNumber,
+                (*inst_list_it)->isCompleted());
+
+        cprintf("\n");
+
+        inst_list_it--;
+        ++num;
+    }
+
+}
diff --git a/src/cpu/checker/o3_builder.cc b/src/cpu/checker/o3_builder.cc
deleted file mode 100644 (file)
index 534a5e2..0000000
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * 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.
- *
- * Authors: Kevin Lim
- */
-
-#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<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> warnOnlyOnLoadError;
-    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(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_DFLT(warnOnlyOnLoadError, "warn, but don't exit, if a load "
-                    "result errors", false),
-    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->warnOnlyOnLoadError = warnOnlyOnLoadError;
-    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->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)
diff --git a/src/cpu/checker/ozone_builder.cc b/src/cpu/checker/ozone_builder.cc
deleted file mode 100644 (file)
index 3c43ab5..0000000
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * 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.
- *
- * Authors: Kevin Lim
- */
-
-#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> warnOnlyOnLoadError;
-    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_DFLT(warnOnlyOnLoadError, "warn, but don't exit, if a load "
-                    "result errors", false),
-    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->warnOnlyOnLoadError = warnOnlyOnLoadError;
-    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)
diff --git a/src/cpu/o3/base_dyn_inst.cc b/src/cpu/o3/base_dyn_inst.cc
new file mode 100644 (file)
index 0000000..1f7540d
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ *
+ * Authors: Kevin Lim
+ */
+
+#include "cpu/base_dyn_inst_impl.hh"
+#include "cpu/o3/alpha_cpu.hh"
+#include "cpu/o3/alpha_impl.hh"
+
+// Explicit instantiation
+template class BaseDynInst<AlphaSimpleImpl>;
+
+template <>
+int
+BaseDynInst<AlphaSimpleImpl>::instcount = 0;
index 2944387045a4e7c74d6a4cb26c8033ba084930de..c35c0a0aa95a46f7c88df69da08d7629e59fe41e 100644 (file)
@@ -31,9 +31,5 @@
 #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>;
diff --git a/src/cpu/o3/checker_builder.cc b/src/cpu/o3/checker_builder.cc
new file mode 100644 (file)
index 0000000..58c40d0
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ * 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.
+ *
+ * Authors: Kevin Lim
+ */
+
+#include <string>
+
+#include "cpu/checker/cpu_impl.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;
+
+template
+class Checker<RefCountingPtr<AlphaDynInst<AlphaSimpleImpl> > >;
+
+/**
+ * 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<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> warnOnlyOnLoadError;
+    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(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_DFLT(warnOnlyOnLoadError, "warn, but don't exit, if a load "
+                    "result errors", false),
+    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->warnOnlyOnLoadError = warnOnlyOnLoadError;
+    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->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)
diff --git a/src/cpu/ozone/bpred_unit.cc b/src/cpu/ozone/bpred_unit.cc
new file mode 100644 (file)
index 0000000..835324c
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * 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/ozone/ozone_impl.hh"
+#include "cpu/ozone/simple_impl.hh"
+
+template class BPredUnit<OzoneImpl>;
+template class BPredUnit<SimpleImpl>;
diff --git a/src/cpu/ozone/checker_builder.cc b/src/cpu/ozone/checker_builder.cc
new file mode 100644 (file)
index 0000000..f6786f2
--- /dev/null
@@ -0,0 +1,165 @@
+/*
+ * 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.
+ *
+ * Authors: Kevin Lim
+ */
+
+#include <string>
+
+#include "cpu/checker/cpu_impl.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"
+
+template
+class Checker<RefCountingPtr<OzoneDynInst<OzoneImpl> > >;
+
+/**
+ * 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> warnOnlyOnLoadError;
+    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_DFLT(warnOnlyOnLoadError, "warn, but don't exit, if a load "
+                    "result errors", false),
+    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->warnOnlyOnLoadError = warnOnlyOnLoadError;
+    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)
diff --git a/src/cpu/ozone/ozone_base_dyn_inst.cc b/src/cpu/ozone/ozone_base_dyn_inst.cc
new file mode 100644 (file)
index 0000000..5a3a69d
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ *
+ * Authors: Kevin Lim
+ */
+
+#include "cpu/base_dyn_inst_impl.hh"
+#include "cpu/ozone/ozone_impl.hh"
+
+// Explicit instantiation
+template class BaseDynInst<OzoneImpl>;
+
+template <>
+int
+BaseDynInst<OzoneImpl>::instcount = 0;
diff --git a/src/cpu/ozone/simple_base_dyn_inst.cc b/src/cpu/ozone/simple_base_dyn_inst.cc
new file mode 100644 (file)
index 0000000..fdaeaf5
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ *
+ * Authors: Kevin Lim
+ */
+
+#include "cpu/base_dyn_inst_impl.hh"
+#include "cpu/ozone/simple_impl.hh"
+
+// Explicit instantiation
+template class BaseDynInst<SimpleImpl>;
+
+template <>
+int
+BaseDynInst<SimpleImpl>::instcount = 0;