Adjustments for the AlphaTLB changing to AlphaISA::TLB and changing register file...
[gem5.git] / src / cpu / ozone / cpu_impl.hh
index ccb1c8418de5db679791bc3001ced929bcf6e767..b34b061d954f3bf618686edbf02acdd43a17f6d2 100644 (file)
@@ -35,6 +35,7 @@
 #include "arch/isa_traits.hh" // For MachInst
 #include "base/trace.hh"
 #include "cpu/base.hh"
+#include "cpu/simple_thread.hh"
 #include "cpu/thread_context.hh"
 #include "cpu/exetrace.hh"
 #include "cpu/ozone/cpu.hh"
 #include "arch/faults.hh"
 #include "arch/alpha/osfpal.hh"
 #include "arch/alpha/tlb.hh"
+#include "arch/alpha/types.hh"
 #include "arch/vtophys.hh"
 #include "base/callback.hh"
-//#include "base/remote_gdb.hh"
 #include "cpu/profile.hh"
 #include "kern/kernel_stats.hh"
+#include "mem/physical.hh"
 #include "sim/faults.hh"
 #include "sim/sim_events.hh"
 #include "sim/sim_exit.hh"
 
 using namespace TheISA;
 
-template <class Impl>
-template<typename T>
-void
-OzoneCPU<Impl>::trace_data(T data) {
-    if (traceData) {
-        traceData->setData(data);
-    }
-}
-
 template <class Impl>
 OzoneCPU<Impl>::TickEvent::TickEvent(OzoneCPU *c, int w)
     : Event(&mainEventQueue, CPU_Tick_Pri), cpu(c), width(w)
@@ -125,6 +118,8 @@ OzoneCPU<Impl>::OzoneCPU(Params *p)
         panic("Checker enabled but not compiled in!");
 #endif
     } else {
+        // If checker is not being used, then the xcProxy points
+        // directly to the CPU's ExecContext.
         checker = NULL;
         thread.tc = &ozoneTC;
         tc = &ozoneTC;
@@ -137,7 +132,7 @@ OzoneCPU<Impl>::OzoneCPU(Params *p)
 
     thread.setStatus(ThreadContext::Suspended);
 #if FULL_SYSTEM
-    /***** All thread state stuff *****/
+    // Setup thread state stuff.
     thread.cpu = this;
     thread.setTid(0);
 
@@ -186,12 +181,15 @@ OzoneCPU<Impl>::OzoneCPU(Params *p)
     frontEnd->setBackEnd(backEnd);
     backEnd->setFrontEnd(frontEnd);
 
-    decoupledFrontEnd = p->decoupledFrontEnd;
-
     globalSeqNum = 1;
 
+#if FULL_SYSTEM
     checkInterrupts = false;
+#endif
+
+    lockFlag = 0;
 
+    // Setup rename table, initializing all values to ready.
     for (int i = 0; i < TheISA::TotalNumRegs; ++i) {
         thread.renameTable[i] = new DynInst(this);
         thread.renameTable[i]->setResultReady();
@@ -232,8 +230,6 @@ OzoneCPU<Impl>::OzoneCPU(Params *p)
     thread.setVirtPort(virt_port);
 #endif
 
-    lockFlag = 0;
-
     DPRINTF(OzoneCPU, "OzoneCPU: Created Ozone cpu object.\n");
 }
 
@@ -246,6 +242,7 @@ template <class Impl>
 void
 OzoneCPU<Impl>::switchOut()
 {
+    BaseCPU::switchOut();
     switchCount = 0;
     // Front end needs state from back end, so switch out the back end first.
     backEnd->switchOut();
@@ -256,6 +253,8 @@ template <class Impl>
 void
 OzoneCPU<Impl>::signalSwitched()
 {
+    // Only complete the switchout when both the front end and back
+    // end have signalled they are ready to switch.
     if (++switchCount == 2) {
         backEnd->doSwitchOut();
         frontEnd->doSwitchOut();
@@ -265,6 +264,17 @@ OzoneCPU<Impl>::signalSwitched()
 #endif
 
         _status = SwitchedOut;
+#ifndef NDEBUG
+        // Loop through all registers
+        for (int i = 0; i < AlphaISA::TotalNumRegs; ++i) {
+            assert(thread.renameTable[i] == frontEnd->renameTable[i]);
+
+            assert(thread.renameTable[i] == backEnd->renameTable[i]);
+
+            DPRINTF(OzoneCPU, "Checking if register %i matches.\n", i);
+        }
+#endif
+
         if (tickEvent.scheduled())
             tickEvent.squash();
     }
@@ -277,13 +287,25 @@ OzoneCPU<Impl>::takeOverFrom(BaseCPU *oldCPU)
 {
     BaseCPU::takeOverFrom(oldCPU);
 
+    thread.trapPending = false;
+    thread.inSyscall = false;
+
     backEnd->takeOverFrom();
     frontEnd->takeOverFrom();
+    frontEnd->renameTable.copyFrom(thread.renameTable);
+    backEnd->renameTable.copyFrom(thread.renameTable);
     assert(!tickEvent.scheduled());
 
+#ifndef NDEBUG
+    // Check rename table.
+    for (int i = 0; i < TheISA::TotalNumRegs; ++i) {
+        assert(thread.renameTable[i]->isResultReady());
+    }
+#endif
+
     // @todo: Fix hardcoded number
     // Clear out any old information in time buffer.
-    for (int i = 0; i < 6; ++i) {
+    for (int i = 0; i < 15; ++i) {
         comm.advance();
     }
 
@@ -315,6 +337,10 @@ OzoneCPU<Impl>::activateContext(int thread_num, int delay)
     notIdleFraction++;
     scheduleTickEvent(delay);
     _status = Running;
+#if FULL_SYSTEM
+    if (thread.quiesceEvent && thread.quiesceEvent->scheduled())
+        thread.quiesceEvent->deschedule();
+#endif
     thread.setStatus(ThreadContext::Active);
     frontEnd->wakeFromQuiesce();
 }
@@ -335,7 +361,7 @@ OzoneCPU<Impl>::suspendContext(int thread_num)
 
 template <class Impl>
 void
-OzoneCPU<Impl>::deallocateContext(int thread_num)
+OzoneCPU<Impl>::deallocateContext(int thread_num, int delay)
 {
     // for now, these are equivalent
     suspendContext(thread_num);
@@ -392,7 +418,7 @@ template <class Impl>
 void
 OzoneCPU<Impl>::resetStats()
 {
-    startNumInst = numInst;
+//    startNumInst = numInst;
     notIdleFraction = (_status != Idle);
 }
 
@@ -418,6 +444,18 @@ OzoneCPU<Impl>::init()
     thread.inSyscall = false;
 }
 
+template <class Impl>
+Port *
+OzoneCPU<Impl>::getPort(const std::string &if_name, int idx)
+{
+    if (if_name == "dcache_port")
+        return backEnd->getDcachePort();
+    else if (if_name == "icache_port")
+        return frontEnd->getIcachePort();
+    else
+        panic("No Such Port\n");
+}
+
 template <class Impl>
 void
 OzoneCPU<Impl>::serialize(std::ostream &os)
@@ -428,6 +466,15 @@ OzoneCPU<Impl>::serialize(std::ostream &os)
     ozoneTC.serialize(os);
     nameOut(os, csprintf("%s.tickEvent", name()));
     tickEvent.serialize(os);
+
+    // Use SimpleThread's ability to checkpoint to make it easier to
+    // write out the registers.  Also make this static so it doesn't
+    // get instantiated multiple times (causes a panic in statistics).
+    static SimpleThread temp;
+
+    nameOut(os, csprintf("%s.xc.0", name()));
+    temp.copyTC(thread.getTC());
+    temp.serialize(os);
 }
 
 template <class Impl>
@@ -438,6 +485,15 @@ OzoneCPU<Impl>::unserialize(Checkpoint *cp, const std::string &section)
     UNSERIALIZE_ENUM(_status);
     ozoneTC.unserialize(cp, csprintf("%s.tc", section));
     tickEvent.unserialize(cp, csprintf("%s.tickEvent", section));
+
+    // Use SimpleThread's ability to checkpoint to make it easier to
+    // read in the registers.  Also make this static so it doesn't
+    // get instantiated multiple times (causes a panic in statistics).
+    static SimpleThread temp;
+
+    temp.copyTC(thread.getTC());
+    temp.unserialize(cp, csprintf("%s.xc.0", section));
+    thread.getTC()->copyArchRegs(temp.getTC());
 }
 
 template <class Impl>
@@ -692,11 +748,13 @@ OzoneCPU<Impl>::processInterrupts()
     if (ipl && ipl > thread.readMiscReg(IPR_IPLR)) {
         thread.setMiscReg(IPR_ISR, summary);
         thread.setMiscReg(IPR_INTID, ipl);
+#if USE_CHECKER
         // @todo: Make this more transparent
         if (checker) {
             checker->threadBase()->setMiscReg(IPR_ISR, summary);
             checker->threadBase()->setMiscReg(IPR_INTID, ipl);
         }
+#endif
         Fault fault = new InterruptFault;
         fault->invoke(thread.getTC());
         DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n",
@@ -780,9 +838,9 @@ OzoneCPU<Impl>::OzoneTC::suspend()
 /// Set the status to Unallocated.
 template <class Impl>
 void
-OzoneCPU<Impl>::OzoneTC::deallocate()
+OzoneCPU<Impl>::OzoneTC::deallocate(int delay)
 {
-    cpu->deallocateContext(thread->readTid());
+    cpu->deallocateContext(thread->readTid(), delay);
 }
 
 /// Set the status to Halted.
@@ -797,7 +855,9 @@ OzoneCPU<Impl>::OzoneTC::halt()
 template <class Impl>
 void
 OzoneCPU<Impl>::OzoneTC::dumpFuncProfile()
-{ }
+{
+    thread->dumpFuncProfile();
+}
 #endif
 
 template <class Impl>
@@ -816,6 +876,7 @@ OzoneCPU<Impl>::OzoneTC::takeOverFrom(ThreadContext *old_context)
     copyArchRegs(old_context);
     setCpuId(old_context->readCpuId());
 
+    thread->setInst(old_context->getInst());
 #if !FULL_SYSTEM
     setFuncExeInst(old_context->readFuncExeInst());
 #else
@@ -829,6 +890,7 @@ OzoneCPU<Impl>::OzoneTC::takeOverFrom(ThreadContext *old_context)
         thread->quiesceEvent->tc = this;
     }
 
+    // Copy kernel stats pointer from old context.
     thread->kernelStats = old_context->getKernelStats();
 //    storeCondFailures = 0;
     cpu->lockFlag = false;
@@ -850,7 +912,11 @@ OzoneCPU<Impl>::OzoneTC::regStats(const std::string &name)
 template <class Impl>
 void
 OzoneCPU<Impl>::OzoneTC::serialize(std::ostream &os)
-{ }
+{
+    // Once serialization is added, serialize the quiesce event and
+    // kernel stats.  Will need to make sure there aren't multiple
+    // things that serialize them.
+}
 
 template <class Impl>
 void
@@ -883,16 +949,14 @@ template <class Impl>
 void
 OzoneCPU<Impl>::OzoneTC::profileClear()
 {
-    if (thread->profile)
-        thread->profile->clear();
+    thread->profileClear();
 }
 
 template <class Impl>
 void
 OzoneCPU<Impl>::OzoneTC::profileSample()
 {
-    if (thread->profile)
-        thread->profile->sample(thread->profileNode, thread->profilePC);
+    thread->profileSample();
 }
 #endif
 
@@ -903,7 +967,6 @@ OzoneCPU<Impl>::OzoneTC::getThreadNum()
     return thread->readTid();
 }
 
-// Also somewhat obnoxious.  Really only used for the TLB fault.
 template <class Impl>
 TheISA::MachInst
 OzoneCPU<Impl>::OzoneTC::getInst()
@@ -921,14 +984,20 @@ OzoneCPU<Impl>::OzoneTC::copyArchRegs(ThreadContext *tc)
     cpu->frontEnd->setPC(thread->PC);
     cpu->frontEnd->setNextPC(thread->nextPC);
 
-    for (int i = 0; i < TheISA::TotalNumRegs; ++i) {
-        if (i < TheISA::FP_Base_DepTag) {
-            thread->renameTable[i]->setIntResult(tc->readIntReg(i));
-        } else if (i < (TheISA::FP_Base_DepTag + TheISA::NumFloatRegs)) {
-            int fp_idx = i - TheISA::FP_Base_DepTag;
-            thread->renameTable[i]->setDoubleResult(
-                tc->readFloatReg(fp_idx, 64));
-        }
+    // First loop through the integer registers.
+    for (int i = 0; i < TheISA::NumIntRegs; ++i) {
+/*        DPRINTF(OzoneCPU, "Copying over register %i, had data %lli, "
+                "now has data %lli.\n",
+                i, thread->renameTable[i]->readIntResult(),
+                tc->readIntReg(i));
+*/
+        thread->renameTable[i]->setIntResult(tc->readIntReg(i));
+    }
+
+    // Then loop through the floating point registers.
+    for (int i = 0; i < TheISA::NumFloatRegs; ++i) {
+        int fp_idx = i + TheISA::FP_Base_DepTag;
+        thread->renameTable[fp_idx]->setIntResult(tc->readFloatRegBits(i));
     }
 
 #if !FULL_SYSTEM
@@ -1087,37 +1156,31 @@ OzoneCPU<Impl>::OzoneTC::readMiscReg(int misc_reg)
 
 template <class Impl>
 TheISA::MiscReg
-OzoneCPU<Impl>::OzoneTC::readMiscRegWithEffect(int misc_reg, Fault &fault)
+OzoneCPU<Impl>::OzoneTC::readMiscRegWithEffect(int misc_reg)
 {
-    return thread->miscRegFile.readRegWithEffect(misc_reg,
-                                                 fault, this);
+    return thread->miscRegFile.readRegWithEffect(misc_reg, this);
 }
 
 template <class Impl>
-Fault
+void
 OzoneCPU<Impl>::OzoneTC::setMiscReg(int misc_reg, const MiscReg &val)
 {
     // Needs to setup a squash event unless we're in syscall mode
-    Fault ret_fault = thread->miscRegFile.setReg(misc_reg, val);
+    thread->miscRegFile.setReg(misc_reg, val);
 
     if (!thread->inSyscall) {
         cpu->squashFromTC();
     }
-
-    return ret_fault;
 }
 
 template <class Impl>
-Fault
+void
 OzoneCPU<Impl>::OzoneTC::setMiscRegWithEffect(int misc_reg, const MiscReg &val)
 {
     // Needs to setup a squash event unless we're in syscall mode
-    Fault ret_fault = thread->miscRegFile.setRegWithEffect(misc_reg, val,
-                                                           this);
+    thread->miscRegFile.setRegWithEffect(misc_reg, val, this);
 
     if (!thread->inSyscall) {
         cpu->squashFromTC();
     }
-
-    return ret_fault;
 }