arch: cpu: Rename *FloatRegBits* to *FloatReg*.
[gem5.git] / src / cpu / checker / cpu_impl.hh
index 7a99feb06beb870c35b54d41adb7f8ac2a2608fe..86f022d41d751ae1d39265cf699c3a8639924b0e 100644 (file)
@@ -1,5 +1,6 @@
 /*
- * Copyright (c) 2011 ARM Limited
+ * Copyright (c) 2011, 2016 ARM Limited
+ * Copyright (c) 2013 Advanced Micro Devices, Inc.
  * All rights reserved
  *
  * The license below extends only to copyright in the software and shall
  *          Geoffrey Blake
  */
 
+#ifndef __CPU_CHECKER_CPU_IMPL_HH__
+#define __CPU_CHECKER_CPU_IMPL_HH__
+
 #include <list>
 #include <string>
 
+#include "arch/isa_traits.hh"
 #include "arch/vtophys.hh"
 #include "base/refcnt.hh"
 #include "config/the_isa.hh"
 #include "cpu/base_dyn_inst.hh"
 #include "cpu/exetrace.hh"
+#include "cpu/reg_class.hh"
 #include "cpu/simple_thread.hh"
 #include "cpu/static_inst.hh"
 #include "cpu/thread_context.hh"
@@ -63,12 +69,12 @@ using namespace TheISA;
 
 template <class Impl>
 void
-Checker<Impl>::advancePC(Fault fault)
+Checker<Impl>::advancePC(const Fault &fault)
 {
     if (fault != NoFault) {
         curMacroStaticInst = StaticInst::nullStaticInstPtr;
         fault->invoke(tc, curStaticInst);
-        predecoder.reset();
+        thread->decoder.reset();
     } else {
         if (curStaticInst) {
             if (curStaticInst->isLastMicroop())
@@ -112,13 +118,13 @@ Checker<Impl>::handlePendingInt()
               "a non-interuptable instruction!", curTick());
     }
     boundaryInst = NULL;
-    predecoder.reset();
+    thread->decoder.reset();
     curMacroStaticInst = StaticInst::nullStaticInstPtr;
 }
 
 template <class Impl>
 void
-Checker<Impl>::verify(DynInstPtr &completed_inst)
+Checker<Impl>::verify(const DynInstPtr &completed_inst)
 {
     DynInstPtr inst;
 
@@ -201,9 +207,9 @@ Checker<Impl>::verify(DynInstPtr &completed_inst)
 
         // maintain $r0 semantics
         thread->setIntReg(ZeroReg, 0);
-#ifdef TARGET_ALPHA
-        thread->setFloatRegDouble(ZeroReg, 0.0);
-#endif // TARGET_ALPHA
+#if THE_ISA == ALPHA_ISA
+        thread->setFloatReg(ZeroReg, 0);
+#endif
 
         // Check if any recent PC changes match up with anything we
         // expect to happen.  This is mostly to check if traps or
@@ -224,11 +230,6 @@ Checker<Impl>::verify(DynInstPtr &completed_inst)
             }
             changedPC = false;
         }
-        if (changedNextPC) {
-            DPRINTF(Checker, "Changed NextPC recently to %#x\n",
-                    thread->nextInstAddr());
-            changedNextPC = false;
-        }
 
         // Try to fetch the instruction
         uint64_t fetchOffset = 0;
@@ -238,19 +239,22 @@ Checker<Impl>::verify(DynInstPtr &completed_inst)
             Addr fetch_PC = thread->instAddr();
             fetch_PC = (fetch_PC & PCMask) + fetchOffset;
 
+            MachInst machInst;
+
             // If not in the middle of a macro instruction
             if (!curMacroStaticInst) {
                 // set up memory request for instruction fetch
-                memReq = new Request(unverifiedInst->threadNumber, fetch_PC,
-                                     sizeof(MachInst),
-                                     0,
-                                     fetch_PC, thread->contextId(),
-                                     unverifiedInst->threadNumber);
-                memReq->setVirt(0, fetch_PC, sizeof(MachInst),
-                                Request::INST_FETCH, thread->instAddr());
+                auto mem_req = std::make_shared<Request>(
+                    unverifiedInst->threadNumber, fetch_PC,
+                    sizeof(MachInst), 0, masterId, fetch_PC,
+                    thread->contextId());
 
+                mem_req->setVirt(0, fetch_PC, sizeof(MachInst),
+                                 Request::INST_FETCH, masterId,
+                                 thread->instAddr());
 
-                fault = itb->translateFunctional(memReq, tc, BaseTLB::Execute);
+                fault = itb->translateFunctional(
+                    mem_req, tc, BaseTLB::Execute);
 
                 if (fault != NoFault) {
                     if (unverifiedInst->getFault() == NoFault) {
@@ -267,7 +271,6 @@ Checker<Impl>::verify(DynInstPtr &completed_inst)
                         advancePC(NoFault);
 
                         // Give up on an ITB fault..
-                        delete memReq;
                         unverifiedInst = NULL;
                         return;
                     } else {
@@ -275,19 +278,15 @@ Checker<Impl>::verify(DynInstPtr &completed_inst)
                         // the fault and see if our results match the CPU on
                         // the next tick().
                         fault = unverifiedInst->getFault();
-                        delete memReq;
                         break;
                     }
                 } else {
-                    PacketPtr pkt = new Packet(memReq,
-                                               MemCmd::ReadReq,
-                                               Packet::Broadcast);
+                    PacketPtr pkt = new Packet(mem_req, MemCmd::ReadReq);
 
                     pkt->dataStatic(&machInst);
                     icachePort->sendFunctional(pkt);
                     machInst = gtoh(machInst);
 
-                    delete memReq;
                     delete pkt;
                 }
             }
@@ -301,25 +300,20 @@ Checker<Impl>::verify(DynInstPtr &completed_inst)
                         microcodeRom.fetchMicroop(pcState.microPC(), NULL);
                 } else if (!curMacroStaticInst) {
                     //We're not in the middle of a macro instruction
-                    StaticInstPtr instPtr = NULL;
+                    StaticInstPtr instPtr = nullptr;
 
                     //Predecode, ie bundle up an ExtMachInst
-                    predecoder.setTC(thread->getTC());
                     //If more fetch data is needed, pass it in.
                     Addr fetchPC = (pcState.instAddr() & PCMask) + fetchOffset;
-                    predecoder.moreBytes(pcState, fetchPC, machInst);
+                    thread->decoder.moreBytes(pcState, fetchPC, machInst);
 
                     //If an instruction is ready, decode it.
                     //Otherwise, we'll have to fetch beyond the
                     //MachInst at the current pc.
-                    if (predecoder.extMachInstReady()) {
+                    if (thread->decoder.instReady()) {
                         fetchDone = true;
-                        ExtMachInst newMachInst =
-                            predecoder.getExtMachInst(pcState);
+                        instPtr = thread->decoder.decode(pcState);
                         thread->pcState(pcState);
-                        instPtr = thread->decoder.decode(newMachInst,
-                                                         pcState.instAddr());
-                        machInst = newMachInst;
                     } else {
                         fetchDone = false;
                         fetchOffset += sizeof(TheISA::MachInst);
@@ -342,8 +336,8 @@ Checker<Impl>::verify(DynInstPtr &completed_inst)
                 }
             }
         }
-        // reset predecoder on Checker
-        predecoder.reset();
+        // reset decoder on Checker
+        thread->decoder.reset();
 
         // Check Checker and CPU get same instruction, and record
         // any faults the CPU may have had.
@@ -399,11 +393,13 @@ Checker<Impl>::verify(DynInstPtr &completed_inst)
 
         // Take any faults here
         if (fault != NoFault) {
-            fault->invoke(tc, curStaticInst);
-            willChangePC = true;
-            newPCState = thread->pcState();
-            DPRINTF(Checker, "Fault, PC is now %s\n", newPCState);
-            curMacroStaticInst = StaticInst::nullStaticInstPtr;
+            if (FullSystem) {
+                fault->invoke(tc, curStaticInst);
+                willChangePC = true;
+                newPCState = thread->pcState();
+                DPRINTF(Checker, "Fault, PC is now %s\n", newPCState);
+                curMacroStaticInst = StaticInst::nullStaticInstPtr;
+            }
         } else {
            advancePC(fault);
         }
@@ -411,7 +407,7 @@ Checker<Impl>::verify(DynInstPtr &completed_inst)
         if (FullSystem) {
             // @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.
+            // not be true, but in the O3 case this may be true.
             Addr oldpc;
             int count = 0;
             do {
@@ -460,7 +456,7 @@ Checker<Impl>::takeOverFrom(BaseCPU *oldCPU)
 
 template <class Impl>
 void
-Checker<Impl>::validateInst(DynInstPtr &inst)
+Checker<Impl>::validateInst(const DynInstPtr &inst)
 {
     if (inst->instAddr() != thread->instAddr()) {
         warn("%lli: PCs do not match! Inst: %s, checker: %s",
@@ -473,42 +469,43 @@ Checker<Impl>::validateInst(DynInstPtr &inst)
         }
     }
 
-    MachInst mi = static_cast<MachInst>(inst->staticInst->machInst);
-
-    if (mi != machInst) {
-        panic("%lli: Binary instructions do not match! Inst: %#x, "
-             "checker: %#x",
-             curTick(), mi, machInst);
-        handleError(inst);
+    if (curStaticInst != inst->staticInst) {
+        warn("%lli: StaticInstPtrs don't match. (%s, %s).\n", curTick(),
+                curStaticInst->getName(), inst->staticInst->getName());
     }
 }
 
 template <class Impl>
 void
-Checker<Impl>::validateExecution(DynInstPtr &inst)
+Checker<Impl>::validateExecution(const DynInstPtr &inst)
 {
-    uint64_t checker_val;
-    uint64_t inst_val;
+    InstResult checker_val;
+    InstResult inst_val;
     int idx = -1;
     bool result_mismatch = false;
+    bool scalar_mismatch = false;
+    bool vector_mismatch = false;
 
     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, 0, idx);
+        copyResult(inst, InstResult(0ul, InstResult::ResultType::Scalar), idx);
     } else if (inst->numDestRegs() > 0 && !result.empty()) {
         DPRINTF(Checker, "Dest regs %d, number of checker dest regs %d\n",
                          inst->numDestRegs(), result.size());
         for (int i = 0; i < inst->numDestRegs() && !result.empty(); i++) {
-            result.front().get(checker_val);
+            checker_val = result.front();
             result.pop();
-            inst_val = 0;
-            inst->template popResult<uint64_t>(inst_val);
+            inst_val = inst->popResult(
+                    InstResult(0ul, InstResult::ResultType::Scalar));
             if (checker_val != inst_val) {
                 result_mismatch = true;
                 idx = i;
-                break;
+                scalar_mismatch = checker_val.isScalar();
+                vector_mismatch = checker_val.isVector();
+                panic_if(!(scalar_mismatch || vector_mismatch),
+                        "Unknown type of result\n");
             }
         }
     } // Checker CPU checks all the saved results in the dyninst passed by
@@ -518,9 +515,12 @@ Checker<Impl>::validateExecution(DynInstPtr &inst)
       // this is ok and not a bug.  May be worthwhile to try and correct this.
 
     if (result_mismatch) {
-        warn("%lli: Instruction results do not match! (Values may not "
-             "actually be integers) Inst: %#x, checker: %#x",
-             curTick(), inst_val, checker_val);
+        if (scalar_mismatch) {
+            warn("%lli: Instruction results (%i) do not match! (Values may"
+                 " not actually be integers) Inst: %#x, checker: %#x",
+                 curTick(), idx, inst_val.asIntegerNoAssert(),
+                 checker_val.asInteger());
+        }
 
         // It's useful to verify load values from memory, but in MP
         // systems the value obtained at execute may be different than
@@ -578,12 +578,12 @@ Checker<Impl>::validateState()
              "registers from main CPU", curTick(), unverifiedInst->instAddr());
 
         // Terribly convoluted way to make sure O3 model does not implode
-        bool inSyscall = unverifiedInst->thread->inSyscall;
-        unverifiedInst->thread->inSyscall = true;
+        bool no_squash_from_TC = unverifiedInst->thread->noSquashFromTC;
+        unverifiedInst->thread->noSquashFromTC = true;
 
         // Heavy-weight copying of all registers
         thread->copyArchRegs(unverifiedInst->tcBase());
-        unverifiedInst->thread->inSyscall = inSyscall;
+        unverifiedInst->thread->noSquashFromTC = no_squash_from_TC;
 
         // Set curStaticInst to unverifiedInst->staticInst
         curStaticInst = unverifiedInst->staticInst;
@@ -595,41 +595,84 @@ Checker<Impl>::validateState()
 
 template <class Impl>
 void
-Checker<Impl>::copyResult(DynInstPtr &inst, uint64_t mismatch_val,
-                          int start_idx)
+Checker<Impl>::copyResult(const DynInstPtr &inst,
+                          const InstResult& mismatch_val, int start_idx)
 {
     // We've already popped one dest off the queue,
     // so do the fix-up then start with the next dest reg;
     if (start_idx >= 0) {
-        RegIndex idx = inst->destRegIdx(start_idx);
-        if (idx < TheISA::FP_Base_DepTag) {
-            thread->setIntReg(idx, mismatch_val);
-        } else if (idx < TheISA::Ctrl_Base_DepTag) {
-            thread->setFloatRegBits(idx, mismatch_val);
-        } else if (idx < TheISA::Max_DepTag) {
-            thread->setMiscReg(idx - TheISA::Ctrl_Base_DepTag,
-                               mismatch_val);
+        const RegId& idx = inst->destRegIdx(start_idx);
+        switch (idx.classValue()) {
+          case IntRegClass:
+            panic_if(!mismatch_val.isScalar(), "Unexpected type of result");
+            thread->setIntReg(idx.index(), mismatch_val.asInteger());
+            break;
+          case FloatRegClass:
+            panic_if(!mismatch_val.isScalar(), "Unexpected type of result");
+            thread->setFloatReg(idx.index(), mismatch_val.asInteger());
+            break;
+          case VecRegClass:
+            panic_if(!mismatch_val.isVector(), "Unexpected type of result");
+            thread->setVecReg(idx, mismatch_val.asVector());
+            break;
+          case VecElemClass:
+            panic_if(!mismatch_val.isVecElem(),
+                     "Unexpected type of result");
+            thread->setVecElem(idx, mismatch_val.asVectorElem());
+            break;
+          case CCRegClass:
+            panic_if(!mismatch_val.isScalar(), "Unexpected type of result");
+            thread->setCCReg(idx.index(), mismatch_val.asInteger());
+            break;
+          case MiscRegClass:
+            panic_if(!mismatch_val.isScalar(), "Unexpected type of result");
+            thread->setMiscReg(idx.index(), mismatch_val.asInteger());
+            break;
+          default:
+            panic("Unknown register class: %d", (int)idx.classValue());
         }
     }
     start_idx++;
-    uint64_t res = 0;
+    InstResult res;
     for (int i = start_idx; i < inst->numDestRegs(); i++) {
-        RegIndex idx = inst->destRegIdx(i);
-        inst->template popResult<uint64_t>(res);
-        if (idx < TheISA::FP_Base_DepTag) {
-            thread->setIntReg(idx, res);
-        } else if (idx < TheISA::Ctrl_Base_DepTag) {
-            thread->setFloatRegBits(idx, res);
-        } else if (idx < TheISA::Max_DepTag) {
+        const RegId& idx = inst->destRegIdx(i);
+        res = inst->popResult();
+        switch (idx.classValue()) {
+          case IntRegClass:
+            panic_if(!res.isScalar(), "Unexpected type of result");
+            thread->setIntReg(idx.index(), res.asInteger());
+            break;
+          case FloatRegClass:
+            panic_if(!res.isScalar(), "Unexpected type of result");
+            thread->setFloatReg(idx.index(), res.asInteger());
+            break;
+          case VecRegClass:
+            panic_if(!res.isVector(), "Unexpected type of result");
+            thread->setVecReg(idx, res.asVector());
+            break;
+          case VecElemClass:
+            panic_if(!res.isVecElem(), "Unexpected type of result");
+            thread->setVecElem(idx, res.asVectorElem());
+            break;
+          case CCRegClass:
+            panic_if(!res.isScalar(), "Unexpected type of result");
+            thread->setCCReg(idx.index(), res.asInteger());
+            break;
+          case MiscRegClass:
+            panic_if(res.isValid(), "MiscReg expecting invalid result");
             // Try to get the proper misc register index for ARM here...
-            thread->setMiscReg(idx - TheISA::Ctrl_Base_DepTag, res);
-        } // else Register is out of range...
+            thread->setMiscReg(idx.index(), 0);
+            break;
+            // else Register is out of range...
+          default:
+            panic("Unknown register class: %d", (int)idx.classValue());
+        }
     }
 }
 
 template <class Impl>
 void
-Checker<Impl>::dumpAndExit(DynInstPtr &inst)
+Checker<Impl>::dumpAndExit(const DynInstPtr &inst)
 {
     cprintf("Error detected, instruction information:\n");
     cprintf("PC:%s, nextPC:%#x\n[sn:%lli]\n[tid:%i]\n"
@@ -672,3 +715,5 @@ Checker<Impl>::dumpInsts()
     }
 
 }
+
+#endif//__CPU_CHECKER_CPU_IMPL_HH__