X86: Add a .serializing directive that makes a macroop serializing.
[gem5.git] / src / cpu / ozone / front_end_impl.hh
index 1b120460a24f274d8c41140dfdfdb82215f023a3..88413692761484b4dcf82403c931f4a75139530a 100644 (file)
  * Authors: Kevin Lim
  */
 
-#include "config/use_checker.hh"
-
-#include "arch/faults.hh"
+#include "sim/faults.hh"
 #include "arch/isa_traits.hh"
 #include "arch/utility.hh"
 #include "base/statistics.hh"
+#include "config/the_isa.hh"
+#include "config/use_checker.hh"
 #include "cpu/thread_context.hh"
 #include "cpu/exetrace.hh"
 #include "cpu/ozone/front_end.hh"
@@ -59,7 +59,7 @@ template<class Impl>
 void
 FrontEnd<Impl>::IcachePort::recvFunctional(PacketPtr pkt)
 {
-    panic("FrontEnd doesn't expect recvFunctional callback!");
+    warn("FrontEnd doesn't update state from functional calls");
 }
 
 template<class Impl>
@@ -74,7 +74,7 @@ FrontEnd<Impl>::IcachePort::recvStatusChange(Status status)
 
 template<class Impl>
 bool
-FrontEnd<Impl>::IcachePort::recvTiming(Packet *pkt)
+FrontEnd<Impl>::IcachePort::recvTiming(PacketPtr pkt)
 {
     fe->processCacheCompletion(pkt);
     return true;
@@ -91,9 +91,10 @@ template <class Impl>
 FrontEnd<Impl>::FrontEnd(Params *params)
     : branchPred(params),
       icachePort(this),
-      mem(params->mem),
+      numInstsReady(params->frontEndLatency, 0),
       instBufferSize(0),
       maxInstBufferSize(params->maxInstBufferSize),
+      latency(params->frontEndLatency),
       width(params->frontEndWidth),
       freeRegs(params->numPhysicalRegs),
       numPhysRegs(params->numPhysicalRegs),
@@ -326,6 +327,18 @@ FrontEnd<Impl>::tick()
     if (switchedOut)
         return;
 
+    for (int insts_to_queue = numInstsReady[-latency];
+         !instBuffer.empty() && insts_to_queue;
+         --insts_to_queue)
+    {
+        DPRINTF(FE, "Transferring instruction [sn:%lli] to the feBuffer\n",
+                instBuffer.front()->seqNum);
+        feBuffer.push_back(instBuffer.front());
+        instBuffer.pop_front();
+    }
+
+    numInstsReady.advance();
+
     // @todo: Maybe I want to just have direct communication...
     if (fromCommit->doneSeqNum) {
         branchPred.update(fromCommit->doneSeqNum, 0);
@@ -339,8 +352,8 @@ FrontEnd<Impl>::tick()
         cacheBlkValid = true;
 
         status = Running;
-        if (barrierInst)
-            status = SerializeBlocked;
+//        if (barrierInst)
+//            status = SerializeBlocked;
         if (freeRegs <= 0)
             status = RenameBlocked;
         checkBE();
@@ -414,11 +427,12 @@ FrontEnd<Impl>::tick()
         // latency
         instBuffer.push_back(inst);
         ++instBufferSize;
+        numInstsReady[0]++;
         ++num_inst;
 
 #if FULL_SYSTEM
         if (inst->isQuiesce()) {
-            warn("%lli: Quiesce instruction encountered, halting fetch!", curTick);
+//            warn("%lli: Quiesce instruction encountered, halting fetch!", curTick);
             status = QuiescePending;
             break;
         }
@@ -448,15 +462,10 @@ Fault
 FrontEnd<Impl>::fetchCacheLine()
 {
     // Read a cache line, based on the current PC.
-#if FULL_SYSTEM
-    // Flag to say whether or not address is physical addr.
-    unsigned flags = cpu->inPalMode(PC) ? PHYSICAL : 0;
-#else
-    unsigned flags = 0;
-#endif // FULL_SYSTEM
     Fault fault = NoFault;
 
-    if (interruptPending && flags == 0) {
+    //AlphaDep
+    if (interruptPending && (PC & 0x3)) {
         return fault;
     }
 
@@ -467,18 +476,18 @@ FrontEnd<Impl>::fetchCacheLine()
 
     // Setup the memReq to do a read of the first isntruction's address.
     // Set the appropriate read size and flags as well.
-    memReq = new Request(0, fetch_PC, cacheBlkSize, flags,
-                         fetch_PC, cpu->readCpuId(), 0);
+    memReq = new Request(0, fetch_PC, cacheBlkSize, 0,
+                         PC, cpu->thread->contextId());
 
     // Translate the instruction request.
-    fault = cpu->translateInstReq(memReq, thread);
+    fault = cpu->itb->translateAtomic(memReq, thread, false, true);
 
     // Now do the timing access to see whether or not the instruction
     // exists within the cache.
     if (fault == NoFault) {
 #if 0
         if (cpu->system->memctrl->badaddr(memReq->paddr) ||
-            memReq->flags & UNCACHEABLE) {
+            memReq->isUncacheable()) {
             DPRINTF(FE, "Fetch: Bad address %#x (hopefully on a "
                     "misspeculating path!",
                     memReq->paddr);
@@ -572,10 +581,10 @@ FrontEnd<Impl>::processBarriers(DynInstPtr &inst)
 
         // Change status over to SerializeBlocked so that other stages know
         // what this is blocked on.
-        status = SerializeBlocked;
+//        status = SerializeBlocked;
 
-        barrierInst = inst;
-        return true;
+//        barrierInst = inst;
+//        return true;
     } else if ((inst->isStoreConditional() || inst->isSerializeAfter())
                && !inst->isSerializeHandled()) {
         DPRINTF(FE, "Serialize after instruction encountered.\n");
@@ -620,6 +629,7 @@ FrontEnd<Impl>::handleFault(Fault &fault)
     instruction->fault = fault;
     instruction->setCanIssue();
     instBuffer.push_back(instruction);
+    numInstsReady[0]++;
     ++instBufferSize;
 }
 
@@ -649,6 +659,21 @@ FrontEnd<Impl>::squash(const InstSeqNum &squash_num, const Addr &next_PC,
         freeRegs+= inst->numDestRegs();
     }
 
+    while (!feBuffer.empty() &&
+           feBuffer.back()->seqNum > squash_num) {
+        DynInstPtr inst = feBuffer.back();
+
+        DPRINTF(FE, "Squashing instruction [sn:%lli] PC %#x\n",
+                inst->seqNum, inst->readPC());
+
+        inst->clearDependents();
+
+        feBuffer.pop_back();
+        --instBufferSize;
+
+        freeRegs+= inst->numDestRegs();
+    }
+
     // Copy over rename table from the back end.
     renameTable.copyFrom(backEnd->renameTable);
 
@@ -666,12 +691,12 @@ FrontEnd<Impl>::squash(const InstSeqNum &squash_num, const Addr &next_PC,
         DPRINTF(FE, "Squashing outstanding Icache access.\n");
         memReq = NULL;
     }
-
+/*
     if (status == SerializeBlocked) {
         assert(barrierInst->seqNum > squash_num);
         barrierInst = NULL;
     }
-
+*/
     // Unless this squash originated from the front end, we're probably
     // in running mode now.
     // Actually might want to make this latency dependent.
@@ -683,13 +708,22 @@ template <class Impl>
 typename Impl::DynInstPtr
 FrontEnd<Impl>::getInst()
 {
-    if (instBufferSize == 0) {
+    if (feBuffer.empty()) {
         return NULL;
     }
 
-    DynInstPtr inst = instBuffer.front();
+    DynInstPtr inst = feBuffer.front();
+
+    if (inst->isSerializeBefore() || inst->isIprAccess()) {
+        DPRINTF(FE, "Back end is getting a serialize before inst\n");
+        if (!backEnd->robEmpty()) {
+            DPRINTF(FE, "Rob is not empty yet, not returning inst\n");
+            return NULL;
+        }
+        inst->clearSerializeBefore();
+    }
 
-    instBuffer.pop_front();
+    feBuffer.pop_front();
 
     --instBufferSize;
 
@@ -784,11 +818,11 @@ FrontEnd<Impl>::updateStatus()
     }
 
     if (status == BEBlocked && !be_block) {
-        if (barrierInst) {
-            status = SerializeBlocked;
-        } else {
+//        if (barrierInst) {
+//            status = SerializeBlocked;
+//        } else {
             status = Running;
-        }
+//        }
         ret_val = true;
     }
     return ret_val;
@@ -810,6 +844,7 @@ template <class Impl>
 typename Impl::DynInstPtr
 FrontEnd<Impl>::getInstFromCacheline()
 {
+/*
     if (status == SerializeComplete) {
         DynInstPtr inst = barrierInst;
         status = Running;
@@ -817,7 +852,7 @@ FrontEnd<Impl>::getInstFromCacheline()
         inst->clearSerializeBefore();
         return inst;
     }
-
+*/
     InstSeqNum inst_seq;
     MachInst inst;
     // @todo: Fix this magic number used here to handle word offset (and
@@ -842,7 +877,11 @@ FrontEnd<Impl>::getInstFromCacheline()
     // Get the instruction from the array of the cache line.
     inst = htog(*reinterpret_cast<MachInst *>(&cacheData[offset]));
 
+#if THE_ISA == ALPHA_ISA
     ExtMachInst decode_inst = TheISA::makeExtMI(inst, PC);
+#elif THE_ISA == SPARC_ISA
+    ExtMachInst decode_inst = TheISA::makeExtMI(inst, tc);
+#endif
 
     // Create a new DynInst from the instruction fetched.
     DynInstPtr instruction = new DynInst(decode_inst, PC, PC+sizeof(MachInst),
@@ -932,6 +971,7 @@ FrontEnd<Impl>::doSwitchOut()
     squash(0, 0);
     instBuffer.clear();
     instBufferSize = 0;
+    feBuffer.clear();
     status = Idle;
 }