arch, cpu: Add support for flattening misc register indexes.
[gem5.git] / src / cpu / inorder / cpu.cc
index f67691d0ade38b756d23a623b622e8556f854761..5a02f94d9bcc969b8ca0fcf80ab666860596aea8 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2012 ARM Limited
+ * Copyright (c) 2013 Advanced Micro Devices, Inc.
  * All rights reserved
  *
  * The license below extends only to copyright in the software and shall
@@ -59,6 +60,7 @@
 #include "cpu/base.hh"
 #include "cpu/exetrace.hh"
 #include "cpu/quiesce_event.hh"
+#include "cpu/reg_class.hh"
 #include "cpu/simple_thread.hh"
 #include "cpu/thread_context.hh"
 #include "debug/Activity.hh"
@@ -84,7 +86,7 @@ using namespace ThePipeline;
 
 InOrderCPU::CachePort::CachePort(CacheUnit *_cacheUnit,
                                  const std::string& name) :
-    CpuPort(_cacheUnit->name() + name, _cacheUnit->cpu),
+    MasterPort(_cacheUnit->name() + name, _cacheUnit->cpu),
     cacheUnit(_cacheUnit)
 { }
 
@@ -209,10 +211,10 @@ InOrderCPU::CPUEvent::description() const
 }
 
 void
-InOrderCPU::CPUEvent::scheduleEvent(int delay)
+InOrderCPU::CPUEvent::scheduleEvent(Cycles delay)
 {
     assert(!scheduled() || squashed());
-    cpu->reschedule(this, cpu->nextCycle(curTick() + cpu->ticks(delay)), true);
+    cpu->reschedule(this, cpu->clockEdge(delay), true);
 }
 
 void
@@ -230,6 +232,7 @@ InOrderCPU::InOrderCPU(Params *params)
       tickEvent(this),
       stageWidth(params->stageWidth),
       resPool(new ResourcePool(this, params)),
+      isa(numThreads, NULL),
       timeBuffer(2 , 2),
       dataPort(resPool->getDataUnit(), ".dcache_port"),
       instPort(resPool->getInstUnit(), ".icache_port"),
@@ -241,7 +244,6 @@ InOrderCPU::InOrderCPU(Params *params)
       resReqCount(0),
 #endif // DEBUG
       drainCount(0),
-      deferRegistration(false/*params->deferRegistration*/),
       stageTracing(params->stageTracing),
       lastRunningCycle(0),
       instsPerSwitch(0)
@@ -280,6 +282,7 @@ InOrderCPU::InOrderCPU(Params *params)
     }
 
     for (ThreadID tid = 0; tid < numThreads; ++tid) {
+        isa[tid] = params->isa[tid];
         pc[tid].set(0);
         lastCommittedPC[tid].set(0);
 
@@ -290,7 +293,7 @@ InOrderCPU::InOrderCPU(Params *params)
         } else {
             if (tid < (ThreadID)params->workload.size()) {
                 DPRINTF(InOrderCPU, "Workload[%i] process is %#x\n",
-                        tid, params->workload[tid]->prog_fname);
+                        tid, params->workload[tid]->progName());
                 thread[tid] =
                     new Thread(this, tid, params->workload[tid]);
             } else {
@@ -358,7 +361,10 @@ InOrderCPU::InOrderCPU(Params *params)
 
         memset(intRegs[tid], 0, sizeof(intRegs[tid]));
         memset(floatRegs.i[tid], 0, sizeof(floatRegs.i[tid]));
-        isa[tid].clear();
+#ifdef ISA_HAS_CC_REGS
+        memset(ccRegs[tid], 0, sizeof(ccRegs[tid]));
+#endif
+        isa[tid]->clear();
 
         // Define dummy instructions and resource requests to be used.
         dummyInst[tid] = new InOrderDynInst(this, 
@@ -384,7 +390,7 @@ InOrderCPU::InOrderCPU(Params *params)
     }
 
     // InOrderCPU always requires an interrupt controller.
-    if (!params->defer_registration && !interrupts) {
+    if (!params->switched_out && !interrupts) {
         fatal("InOrderCPU %s has no interrupt controller.\n"
               "Ensure createInterruptController() is called.\n", name());
     }
@@ -401,13 +407,13 @@ InOrderCPU::InOrderCPU(Params *params)
     frontEndSked = createFrontEndSked();
     faultSked = createFaultSked();
 
-    lastRunningCycle = curTick();
+    lastRunningCycle = curCycle();
 
     lockAddr = 0;
     lockFlag = false;
     
     // Schedule First Tick Event, CPU will reschedule itself from here on out.
-    scheduleTickEvent(0);
+    scheduleTickEvent(Cycles(0));
 }
 
 InOrderCPU::~InOrderCPU()
@@ -761,17 +767,17 @@ InOrderCPU::tick()
     if (!tickEvent.scheduled()) {
         if (_status == SwitchedOut) {
             // increment stat
-            lastRunningCycle = curTick();
+            lastRunningCycle = curCycle();
         } else if (!activityRec.active()) {
             DPRINTF(InOrderCPU, "sleeping CPU.\n");
-            lastRunningCycle = curTick();
+            lastRunningCycle = curCycle();
             timesIdled++;
         } else {
             //Tick next_tick = curTick() + cycles(1);
             //tickEvent.schedule(next_tick);
-            schedule(&tickEvent, nextCycle(curTick() + 1));
+            schedule(&tickEvent, clockEdge(Cycles(1)));
             DPRINTF(InOrderCPU, "Scheduled CPU for next tick @ %i.\n", 
-                    nextCycle(curTick() + 1));
+                    clockEdge(Cycles(1)));
         }
     }
 
@@ -786,28 +792,37 @@ InOrderCPU::init()
     BaseCPU::init();
 
     for (ThreadID tid = 0; tid < numThreads; ++tid) {
-        // Set inSyscall so that the CPU doesn't squash when initially
+        // Set noSquashFromTC so that the CPU doesn't squash when initially
         // setting up registers.
-        thread[tid]->inSyscall = true;
+        thread[tid]->noSquashFromTC = true;
         // Initialise the ThreadContext's memory proxies
         thread[tid]->initMemProxies(thread[tid]->getTC());
     }
 
-    if (FullSystem && !params()->defer_registration) {
+    if (FullSystem && !params()->switched_out) {
         for (ThreadID tid = 0; tid < numThreads; tid++) {
             ThreadContext *src_tc = threadContexts[tid];
             TheISA::initCPU(src_tc, src_tc->contextId());
         }
     }
 
-    // Clear inSyscall.
+    // Clear noSquashFromTC.
     for (ThreadID tid = 0; tid < numThreads; ++tid)
-        thread[tid]->inSyscall = false;
+        thread[tid]->noSquashFromTC = false;
 
     // Call Initializiation Routine for Resource Pool
     resPool->init();
 }
 
+void
+InOrderCPU::verifyMemoryMode() const
+{
+    if (!system->isTimingMode()) {
+        fatal("The in-order CPU requires the memory system to be in "
+              "'timing' mode.\n");
+    }
+}
+
 Fault
 InOrderCPU::hwrei(ThreadID tid)
 {
@@ -877,7 +892,7 @@ InOrderCPU::checkForInterrupts()
                 // Schedule Squash Through-out Resource Pool
                 resPool->scheduleEvent(
                     (InOrderCPU::CPUEventType)ResourcePool::SquashAll,
-                    dummyTrapInst[tid], 0);
+                    dummyTrapInst[tid], Cycles(0));
 
                 // Finally, Setup Trap to happen at end of cycle
                 trapContext(interrupt, tid, dummyTrapInst[tid]);
@@ -912,7 +927,8 @@ InOrderCPU::processInterrupts(Fault interrupt)
 }
 
 void
-InOrderCPU::trapContext(Fault fault, ThreadID tid, DynInstPtr inst, int delay)
+InOrderCPU::trapContext(Fault fault, ThreadID tid, DynInstPtr inst,
+                        Cycles delay)
 {
     scheduleCpuEvent(Trap, fault, tid, inst, delay);
     trapPending[tid] = true;
@@ -926,7 +942,8 @@ InOrderCPU::trap(Fault fault, ThreadID tid, DynInstPtr inst)
 }
 
 void 
-InOrderCPU::squashFromMemStall(DynInstPtr inst, ThreadID tid, int delay)
+InOrderCPU::squashFromMemStall(DynInstPtr inst, ThreadID tid,
+                               Cycles delay)
 {
     scheduleCpuEvent(SquashFromMemStall, NoFault, tid, inst, delay);
 }
@@ -954,25 +971,21 @@ InOrderCPU::squashDueToMemStall(int stage_num, InstSeqNum seq_num,
 void
 InOrderCPU::scheduleCpuEvent(CPUEventType c_event, Fault fault,
                              ThreadID tid, DynInstPtr inst, 
-                             unsigned delay, CPUEventPri event_pri)
+                             Cycles delay, CPUEventPri event_pri)
 {
     CPUEvent *cpu_event = new CPUEvent(this, c_event, fault, tid, inst,
                                        event_pri);
 
-    Tick sked_tick = nextCycle(curTick() + ticks(delay));
-    if (delay >= 0) {
-        DPRINTF(InOrderCPU, "Scheduling CPU Event (%s) for cycle %i, [tid:%i].\n",
-                eventNames[c_event], curTick() + delay, tid);
-        schedule(cpu_event, sked_tick);
-    } else {
-        cpu_event->process();
-        cpuEventRemoveList.push(cpu_event);
-    }
+    Tick sked_tick = clockEdge(delay);
+    DPRINTF(InOrderCPU, "Scheduling CPU Event (%s) for cycle %i, [tid:%i].\n",
+            eventNames[c_event], curTick() + delay, tid);
+    schedule(cpu_event, sked_tick);
 
     // Broadcast event to the Resource Pool
     // Need to reset tid just in case this is a dummy instruction
     inst->setTid(tid);        
-    resPool->scheduleEvent(c_event, inst, 0, 0, tid);
+    // @todo: Is this really right? Should the delay not be passed on?
+    resPool->scheduleEvent(c_event, inst, Cycles(0), 0, tid);
 }
 
 bool
@@ -1076,7 +1089,7 @@ InOrderCPU::activateThreadInPipeline(ThreadID tid)
 }
 
 void
-InOrderCPU::deactivateContext(ThreadID tid, int delay)
+InOrderCPU::deactivateContext(ThreadID tid, Cycles delay)
 {
     DPRINTF(InOrderCPU,"[tid:%i]: Deactivating ...\n", tid);
 
@@ -1158,7 +1171,7 @@ InOrderCPU::tickThreadStats()
 }
 
 void
-InOrderCPU::activateContext(ThreadID tid, int delay)
+InOrderCPU::activateContext(ThreadID tid, Cycles delay)
 {
     DPRINTF(InOrderCPU,"[tid:%i]: Activating ...\n", tid);
 
@@ -1173,7 +1186,7 @@ InOrderCPU::activateContext(ThreadID tid, int delay)
 }
 
 void
-InOrderCPU::activateNextReadyContext(int delay)
+InOrderCPU::activateNextReadyContext(Cycles delay)
 {
     DPRINTF(InOrderCPU,"Activating next ready thread\n");
 
@@ -1247,18 +1260,24 @@ InOrderCPU::getPipeStage(int stage_num)
 
 
 RegIndex
-InOrderCPU::flattenRegIdx(RegIndex reg_idx, RegType &reg_type, ThreadID tid)
-{
-    if (reg_idx < FP_Base_DepTag) {
-        reg_type = IntType;
-        return isa[tid].flattenIntIndex(reg_idx);
-    } else if (reg_idx < Ctrl_Base_DepTag) {
-        reg_type = FloatType;
-        reg_idx -= FP_Base_DepTag;
-        return isa[tid].flattenFloatIndex(reg_idx);
-    } else {
-        reg_type = MiscType;
-        return reg_idx - TheISA::Ctrl_Base_DepTag;
+InOrderCPU::flattenRegIdx(RegIndex reg_idx, RegClass &reg_type, ThreadID tid)
+{
+    RegIndex rel_idx;
+
+    reg_type = regIdxToClass(reg_idx, &rel_idx);
+
+    switch (reg_type) {
+      case IntRegClass:
+        return isa[tid]->flattenIntIndex(rel_idx);
+
+      case FloatRegClass:
+        return isa[tid]->flattenFloatIndex(rel_idx);
+
+      case MiscRegClass:
+        return rel_idx;
+
+      default:
+        panic("register %d out of range\n", reg_idx);
     }
 }
 
@@ -1289,6 +1308,19 @@ InOrderCPU::readFloatRegBits(RegIndex reg_idx, ThreadID tid)
     return floatRegs.i[tid][reg_idx];
 }
 
+CCReg
+InOrderCPU::readCCReg(RegIndex reg_idx, ThreadID tid)
+{
+#ifdef ISA_HAS_CC_REGS
+    DPRINTF(CCRegs, "[tid:%i]: Reading CC. Reg %i as %x\n",
+            tid, reg_idx, ccRegs[tid][reg_idx]);
+
+    return ccRegs[tid][reg_idx];
+#else
+    panic("readCCReg: ISA does not have CC regs\n");
+#endif
+}
+
 void
 InOrderCPU::setIntReg(RegIndex reg_idx, uint64_t val, ThreadID tid)
 {
@@ -1328,6 +1360,18 @@ InOrderCPU::setFloatRegBits(RegIndex reg_idx, FloatRegBits val, ThreadID tid)
             floatRegs.f[tid][reg_idx]);
 }
 
+void
+InOrderCPU::setCCReg(RegIndex reg_idx, CCReg val, ThreadID tid)
+{
+#ifdef ISA_HAS_CC_REGS
+    DPRINTF(CCRegs, "[tid:%i]: Setting CC. Reg %i to %x\n",
+            tid, reg_idx, val);
+    ccRegs[tid][reg_idx] = val;
+#else
+    panic("readCCReg: ISA does not have CC regs\n");
+#endif
+}
+
 uint64_t
 InOrderCPU::readRegOtherThread(unsigned reg_idx, ThreadID tid)
 {
@@ -1336,18 +1380,25 @@ InOrderCPU::readRegOtherThread(unsigned reg_idx, ThreadID tid)
         tid = TheISA::getTargetThread(tcBase(tid));
     }
 
-    if (reg_idx < FP_Base_DepTag) {                   
+    RegIndex rel_idx;
+
+    switch (regIdxToClass(reg_idx, &rel_idx)) {
+      case IntRegClass:
         // Integer Register File
-        return readIntReg(reg_idx, tid);
-    } else if (reg_idx < Ctrl_Base_DepTag) {          
+        return readIntReg(rel_idx, tid);
+
+      case FloatRegClass:
         // Float Register File
-        reg_idx -= FP_Base_DepTag;
-        return readFloatRegBits(reg_idx, tid);
-    } else {
-        reg_idx -= Ctrl_Base_DepTag;
-        return readMiscReg(reg_idx, tid);  // Misc. Register File
+        return readFloatRegBits(rel_idx, tid);
+
+      case MiscRegClass:
+        return readMiscReg(rel_idx, tid);  // Misc. Register File
+
+      default:
+        panic("register %d out of range\n", reg_idx);
     }
 }
+
 void
 InOrderCPU::setRegOtherThread(unsigned reg_idx, const MiscReg &val,
                               ThreadID tid)
@@ -1357,39 +1408,49 @@ InOrderCPU::setRegOtherThread(unsigned reg_idx, const MiscReg &val,
         tid = TheISA::getTargetThread(tcBase(tid));
     }
 
-    if (reg_idx < FP_Base_DepTag) {            // Integer Register File
-        setIntReg(reg_idx, val, tid);
-    } else if (reg_idx < Ctrl_Base_DepTag) {   // Float Register File
-        reg_idx -= FP_Base_DepTag;
-        setFloatRegBits(reg_idx, val, tid);
-    } else {
-        reg_idx -= Ctrl_Base_DepTag;
-        setMiscReg(reg_idx, val, tid); // Misc. Register File
+    RegIndex rel_idx;
+
+    switch (regIdxToClass(reg_idx, &rel_idx)) {
+      case IntRegClass:
+        setIntReg(rel_idx, val, tid);
+        break;
+
+      case FloatRegClass:
+        setFloatRegBits(rel_idx, val, tid);
+        break;
+
+      case CCRegClass:
+        setCCReg(rel_idx, val, tid);
+        break;
+
+      case MiscRegClass:
+        setMiscReg(rel_idx, val, tid); // Misc. Register File
+        break;
     }
 }
 
 MiscReg
 InOrderCPU::readMiscRegNoEffect(int misc_reg, ThreadID tid)
 {
-    return isa[tid].readMiscRegNoEffect(misc_reg);
+    return isa[tid]->readMiscRegNoEffect(misc_reg);
 }
 
 MiscReg
 InOrderCPU::readMiscReg(int misc_reg, ThreadID tid)
 {
-    return isa[tid].readMiscReg(misc_reg, tcBase(tid));
+    return isa[tid]->readMiscReg(misc_reg, tcBase(tid));
 }
 
 void
 InOrderCPU::setMiscRegNoEffect(int misc_reg, const MiscReg &val, ThreadID tid)
 {
-    isa[tid].setMiscRegNoEffect(misc_reg, val);
+    isa[tid]->setMiscRegNoEffect(misc_reg, val);
 }
 
 void
 InOrderCPU::setMiscReg(int misc_reg, const MiscReg &val, ThreadID tid)
 {
-    isa[tid].setMiscReg(misc_reg, val, tcBase(tid));
+    isa[tid]->setMiscReg(misc_reg, val, tcBase(tid));
 }
 
 
@@ -1696,7 +1757,9 @@ InOrderCPU::wakeCPU()
 
     DPRINTF(Activity, "Waking up CPU\n");
 
-    Tick extra_cycles = tickToCycles((curTick() - 1) - lastRunningCycle);
+    Tick extra_cycles = curCycle() - lastRunningCycle;
+    if (extra_cycles != 0)
+        --extra_cycles;
 
     idleCycles += extra_cycles;    
     for (int stage_num = 0; stage_num < NumStages; stage_num++) {
@@ -1705,7 +1768,7 @@ InOrderCPU::wakeCPU()
 
     numCycles += extra_cycles;
 
-    schedule(&tickEvent, nextCycle(curTick()));
+    schedule(&tickEvent, clockEdge());
 }
 
 // Lots of copied full system code...place into BaseCPU class?
@@ -1722,7 +1785,8 @@ InOrderCPU::wakeup()
 }
 
 void
-InOrderCPU::syscallContext(Fault fault, ThreadID tid, DynInstPtr inst, int delay)
+InOrderCPU::syscallContext(Fault fault, ThreadID tid, DynInstPtr inst,
+                           Cycles delay)
 {
     // Syscall must be non-speculative, so squash from last stage
     unsigned squash_stage = NumStages - 1;
@@ -1733,7 +1797,8 @@ InOrderCPU::syscallContext(Fault fault, ThreadID tid, DynInstPtr inst, int delay
 
     // Schedule Squash Through-out Resource Pool
     resPool->scheduleEvent(
-        (InOrderCPU::CPUEventType)ResourcePool::SquashAll, inst, 0);
+        (InOrderCPU::CPUEventType)ResourcePool::SquashAll, inst,
+        Cycles(0));
     scheduleCpuEvent(Syscall, fault, tid, inst, delay, Syscall_Pri);
 }