CPU: Implement translateTiming which defers to translateAtomic, and convert the timin...
[gem5.git] / src / cpu / simple / base.cc
index 877dc5bd494cb9a1204f1ea996ef7c6fd3e12016..9372ff43d40ee5eabef9bfccc41b695726e7a198 100644 (file)
@@ -47,7 +47,6 @@
 #include "cpu/static_inst.hh"
 #include "cpu/thread_context.hh"
 #include "mem/packet.hh"
-#include "sim/builder.hh"
 #include "sim/byteswap.hh"
 #include "sim/debug.hh"
 #include "sim/host.hh"
 #include "mem/mem_object.hh"
 #endif // FULL_SYSTEM
 
+#include "params/BaseSimpleCPU.hh"
+
 using namespace std;
 using namespace TheISA;
 
-BaseSimpleCPU::BaseSimpleCPU(Params *p)
-    : BaseCPU(p), thread(NULL), predecoder(NULL)
+BaseSimpleCPU::BaseSimpleCPU(BaseSimpleCPUParams *p)
+    : BaseCPU(p), traceData(NULL), thread(NULL), predecoder(NULL)
 {
 #if FULL_SYSTEM
     thread = new SimpleThread(this, 0, p->system, p->itb, p->dtb);
 #else
-    thread = new SimpleThread(this, /* thread_num */ 0, p->process,
-            /* asid */ 0);
+    thread = new SimpleThread(this, /* thread_num */ 0, p->workload[0],
+            p->itb, p->dtb, /* asid */ 0);
 #endif // !FULL_SYSTEM
 
-    thread->setStatus(ThreadContext::Suspended);
+    thread->setStatus(ThreadContext::Unallocated);
 
     tc = thread->getTC();
 
@@ -91,6 +92,10 @@ BaseSimpleCPU::BaseSimpleCPU(Params *p)
     lastDcacheStall = 0;
 
     threadContexts.push_back(tc);
+
+
+    fetchOffset = 0;
+    stayAtPC = false;
 }
 
 BaseSimpleCPU::~BaseSimpleCPU()
@@ -171,12 +176,13 @@ void
 BaseSimpleCPU::resetStats()
 {
 //    startNumInst = numInst;
-    // notIdleFraction = (_status != Idle);
+     notIdleFraction = (_status != Idle);
 }
 
 void
 BaseSimpleCPU::serialize(ostream &os)
 {
+    SERIALIZE_ENUM(_status);
     BaseCPU::serialize(os);
 //    SERIALIZE_SCALAR(inst);
     nameOut(os, csprintf("%s.xc.0", name()));
@@ -186,6 +192,7 @@ BaseSimpleCPU::serialize(ostream &os)
 void
 BaseSimpleCPU::unserialize(Checkpoint *cp, const string &section)
 {
+    UNSERIALIZE_ENUM(_status);
     BaseCPU::unserialize(cp, section);
 //    UNSERIALIZE_SCALAR(inst);
     thread->unserialize(cp, csprintf("%s.xc.0", section));
@@ -296,14 +303,13 @@ BaseSimpleCPU::dbg_vtophys(Addr addr)
 
 #if FULL_SYSTEM
 void
-BaseSimpleCPU::post_interrupt(int int_num, int index)
+BaseSimpleCPU::wakeup()
 {
-    BaseCPU::post_interrupt(int_num, index);
+    if (thread->status() != ThreadContext::Suspended)
+        return;
 
-    if (thread->status() == ThreadContext::Suspended) {
-                DPRINTF(Quiesce,"Suspended Processor awoke\n");
-        thread->activate();
-    }
+    DPRINTF(Quiesce,"Suspended Processor awoke\n");
+    thread->activate();
 }
 #endif // FULL_SYSTEM
 
@@ -311,11 +317,12 @@ void
 BaseSimpleCPU::checkForInterrupts()
 {
 #if FULL_SYSTEM
-    if (check_interrupts(tc)) {
-        Fault interrupt = interrupts.getInterrupt(tc);
+    if (checkInterrupts(tc)) {
+        Fault interrupt = interrupts->getInterrupt(tc);
 
         if (interrupt != NoFault) {
-            interrupts.updateIntrInfo(tc);
+            predecoder.reset();
+            interrupts->updateIntrInfo(tc);
             interrupt->invoke(tc);
         }
     }
@@ -323,25 +330,22 @@ BaseSimpleCPU::checkForInterrupts()
 }
 
 
-Fault
+void
 BaseSimpleCPU::setupFetchRequest(Request *req)
 {
+    Addr threadPC = thread->readPC();
+
     // set up memory request for instruction fetch
 #if ISA_HAS_DELAY_SLOT
-    DPRINTF(Fetch,"Fetch: PC:%08p NPC:%08p NNPC:%08p\n",thread->readPC(),
+    DPRINTF(Fetch,"Fetch: PC:%08p NPC:%08p NNPC:%08p\n",threadPC,
             thread->readNextPC(),thread->readNextNPC());
 #else
-    DPRINTF(Fetch,"Fetch: PC:%08p NPC:%08p",thread->readPC(),
+    DPRINTF(Fetch,"Fetch: PC:%08p NPC:%08p\n",threadPC,
             thread->readNextPC());
 #endif
 
-    req->setVirt(0, thread->readPC() & ~3, sizeof(MachInst),
-                 (FULL_SYSTEM && (thread->readPC() & 1)) ? PHYSICAL : 0,
-                 thread->readPC());
-
-    Fault fault = thread->translateInstReq(req);
-
-    return fault;
+    Addr fetchPC = (threadPC & PCMask) + fetchOffset;
+    req->setVirt(0, fetchPC, sizeof(MachInst), 0, threadPC);
 }
 
 
@@ -354,56 +358,69 @@ BaseSimpleCPU::preExecute()
     thread->setFloatReg(ZeroReg, 0.0);
 #endif // ALPHA_ISA
 
-    // keep an instruction count
-    numInst++;
-    numInsts++;
-
-    thread->funcExeInst++;
-
     // check for instruction-count-based events
     comInstEventQueue[0]->serviceEvents(numInst);
 
     // decode the instruction
     inst = gtoh(inst);
-    //If we're not in the middle of a macro instruction
-    if (!curMacroStaticInst) {
+
+    MicroPC upc = thread->readMicroPC();
+
+    if (isRomMicroPC(upc)) {
+        stayAtPC = false;
+        curStaticInst = microcodeRom.fetchMicroop(upc, curMacroStaticInst);
+    } else if (!curMacroStaticInst) {
+        //We're not in the middle of a macro instruction
         StaticInstPtr instPtr = NULL;
 
         //Predecode, ie bundle up an ExtMachInst
         //This should go away once the constructor can be set up properly
         predecoder.setTC(thread->getTC());
         //If more fetch data is needed, pass it in.
-        if(predecoder.needMoreBytes())
-            predecoder.moreBytes(thread->readPC(), 0, inst);
-        else
-            predecoder.process();
-        //If an instruction is ready, decode it
-        if (predecoder.extMachInstReady())
-            instPtr = StaticInst::decode(predecoder.getExtMachInst());
+        Addr fetchPC = (thread->readPC() & PCMask) + fetchOffset;
+        //if(predecoder.needMoreBytes())
+            predecoder.moreBytes(thread->readPC(), fetchPC, inst);
+        //else
+        //    predecoder.process();
+
+        //If an instruction is ready, decode it. Otherwise, we'll have to
+        //fetch beyond the MachInst at the current pc.
+        if (predecoder.extMachInstReady()) {
+#if THE_ISA == X86_ISA
+            thread->setNextPC(thread->readPC() + predecoder.getInstSize());
+#endif // X86_ISA
+            stayAtPC = false;
+            instPtr = StaticInst::decode(predecoder.getExtMachInst(),
+                                         thread->readPC());
+        } else {
+            stayAtPC = true;
+            fetchOffset += sizeof(MachInst);
+        }
 
         //If we decoded an instruction and it's microcoded, start pulling
         //out micro ops
-        if (instPtr && instPtr->isMacroOp()) {
+        if (instPtr && instPtr->isMacroop()) {
             curMacroStaticInst = instPtr;
-            curStaticInst = curMacroStaticInst->
-                fetchMicroOp(thread->readMicroPC());
+            curStaticInst = curMacroStaticInst->fetchMicroop(upc);
         } else {
             curStaticInst = instPtr;
         }
     } else {
         //Read the next micro op from the macro op
-        curStaticInst = curMacroStaticInst->
-            fetchMicroOp(thread->readMicroPC());
+        curStaticInst = curMacroStaticInst->fetchMicroop(upc);
     }
 
     //If we decoded an instruction this "tick", record information about it.
     if(curStaticInst)
     {
-        traceData = Trace::getInstRecord(curTick, tc, curStaticInst,
-                                         thread->readPC());
+#if TRACING_ON
+        traceData = tracer->getInstRecord(curTick, tc,
+                curStaticInst, thread->readPC(),
+                curMacroStaticInst, thread->readMicroPC());
 
         DPRINTF(Decode,"Decode: Decoded %s instruction: 0x%x\n",
                 curStaticInst->getName(), curStaticInst->machInst);
+#endif // TRACING_ON
 
 #if FULL_SYSTEM
         thread->setInst(inst);
@@ -415,11 +432,10 @@ void
 BaseSimpleCPU::postExecute()
 {
 #if FULL_SYSTEM
-    if (thread->profile) {
+    if (thread->profile && curStaticInst) {
         bool usermode = TheISA::inUserMode(tc);
         thread->profilePC = usermode ? 1 : thread->readPC();
-        StaticInstPtr si(inst);
-        ProfileNode *node = thread->profile->consume(tc, si);
+        ProfileNode *node = thread->profile->consume(tc, curStaticInst);
         if (node)
             thread->profileNode = node;
     }
@@ -447,24 +463,26 @@ BaseSimpleCPU::postExecute()
 void
 BaseSimpleCPU::advancePC(Fault fault)
 {
+    //Since we're moving to a new pc, zero out the offset
+    fetchOffset = 0;
     if (fault != NoFault) {
         curMacroStaticInst = StaticInst::nullStaticInstPtr;
+        predecoder.reset();
         fault->invoke(tc);
-        thread->setMicroPC(0);
-        thread->setNextMicroPC(1);
-    } else if (predecoder.needMoreBytes()) {
+    } else {
         //If we're at the last micro op for this instruction
-        if (curStaticInst && curStaticInst->isLastMicroOp()) {
-            //We should be working with a macro op
-            assert(curMacroStaticInst);
+        if (curStaticInst && curStaticInst->isLastMicroop()) {
+            //We should be working with a macro op or be in the ROM
+            assert(curMacroStaticInst ||
+                    isRomMicroPC(thread->readMicroPC()));
             //Close out this macro op, and clean up the
             //microcode state
             curMacroStaticInst = StaticInst::nullStaticInstPtr;
-            thread->setMicroPC(0);
-            thread->setNextMicroPC(1);
+            thread->setMicroPC(normalMicroPC(0));
+            thread->setNextMicroPC(normalMicroPC(1));
         }
         //If we're still in a macro op
-        if (curMacroStaticInst) {
+        if (curMacroStaticInst || isRomMicroPC(thread->readMicroPC())) {
             //Advance the micro pc
             thread->setMicroPC(thread->readNextMicroPC());
             //Advance the "next" micro pc. Note that there are no delay
@@ -478,13 +496,39 @@ BaseSimpleCPU::advancePC(Fault fault)
             assert(thread->readNextPC() != thread->readNextNPC());
         }
     }
-
-#if FULL_SYSTEM
-    Addr oldpc;
-    do {
-        oldpc = thread->readPC();
-        system->pcEventQueue.service(tc);
-    } while (oldpc != thread->readPC());
-#endif
 }
 
+/*Fault
+BaseSimpleCPU::CacheOp(uint8_t Op, Addr EffAddr)
+{
+    // translate to physical address
+    Fault fault = NoFault;
+    int CacheID = Op & 0x3; // Lower 3 bits identify Cache
+    int CacheOP = Op >> 2; // Upper 3 bits identify Cache Operation
+    if(CacheID > 1)
+      {
+        warn("CacheOps not implemented for secondary/tertiary caches\n");
+      }
+    else
+      {
+        switch(CacheOP)
+          { // Fill Packet Type
+          case 0: warn("Invalidate Cache Op\n");
+            break;
+          case 1: warn("Index Load Tag Cache Op\n");
+            break;
+          case 2: warn("Index Store Tag Cache Op\n");
+            break;
+          case 4: warn("Hit Invalidate Cache Op\n");
+            break;
+          case 5: warn("Fill/Hit Writeback Invalidate Cache Op\n");
+            break;
+          case 6: warn("Hit Writeback\n");
+            break;
+          case 7: warn("Fetch & Lock Cache Op\n");
+            break;
+          default: warn("Unimplemented Cache Op\n");
+          }
+      }
+    return fault;
+}*/