undo simple CPU changes
[gem5.git] / cpu / simple_cpu / simple_cpu.cc
index bf4cbfbe2690bdb2216dc2f150f1e43ce74dbb3e..d48f936638eb3bc86972c8f36aab579816b7aedf 100644 (file)
 using namespace std;
 
 SimpleCPU::TickEvent::TickEvent(SimpleCPU *c)
-    : Event(&mainEventQueue, CPU_Tick_Pri), cpu(c)
+    : Event(&mainEventQueue, CPU_Tick_Pri), cpu(c), multiplier(1)
 {
 }
 
 void
 SimpleCPU::TickEvent::process()
 {
-    cpu->tick();
+    int count = multiplier;
+    do {
+        cpu->tick();
+    } while (--count > 0 && cpu->status() == Running);
 }
 
 const char *
@@ -120,11 +123,12 @@ SimpleCPU::SimpleCPU(const string &_name,
                      FunctionalMemory *mem,
                      MemInterface *icache_interface,
                      MemInterface *dcache_interface,
-                     bool _def_reg, Tick freq)
-    : BaseCPU(_name, /* number_of_threads */ 1,
+                     bool _def_reg, Tick freq,
+                     bool _function_trace, Tick _function_trace_start)
+    : BaseCPU(_name, /* number_of_threads */ 1, _def_reg,
               max_insts_any_thread, max_insts_all_threads,
               max_loads_any_thread, max_loads_all_threads,
-              _system, freq),
+              _system, freq, _function_trace, _function_trace_start),
 #else
 SimpleCPU::SimpleCPU(const string &_name, Process *_process,
                      Counter max_insts_any_thread,
@@ -133,13 +137,14 @@ SimpleCPU::SimpleCPU(const string &_name, Process *_process,
                      Counter max_loads_all_threads,
                      MemInterface *icache_interface,
                      MemInterface *dcache_interface,
-                     bool _def_reg)
-    : BaseCPU(_name, /* number_of_threads */ 1,
+                     bool _def_reg,
+                     bool _function_trace, Tick _function_trace_start)
+    : BaseCPU(_name, /* number_of_threads */ 1, _def_reg,
               max_insts_any_thread, max_insts_all_threads,
-              max_loads_any_thread, max_loads_all_threads),
+              max_loads_any_thread, max_loads_all_threads,
+              _function_trace, _function_trace_start),
 #endif
-      tickEvent(this), xc(NULL), defer_registration(_def_reg),
-      cacheCompletionEvent(this)
+      tickEvent(this), xc(NULL), cacheCompletionEvent(this)
 {
     _status = Idle;
 #ifdef FULL_SYSTEM
@@ -173,13 +178,6 @@ SimpleCPU::~SimpleCPU()
 {
 }
 
-void SimpleCPU::init()
-{
-    if (!defer_registration) {
-        this->registerExecContexts();
-    }
-}
-
 void
 SimpleCPU::switchOut()
 {
@@ -269,6 +267,11 @@ SimpleCPU::regStats()
         .desc("Number of memory references")
         ;
 
+    notIdleFraction
+        .name(name() + ".not_idle_fraction")
+        .desc("Percentage of non-idle cycles")
+        ;
+
     idleFraction
         .name(name() + ".idle_fraction")
         .desc("Percentage of idle cycles")
@@ -330,16 +333,30 @@ change_thread_state(int thread_number, int activate, int priority)
 Fault
 SimpleCPU::copySrcTranslate(Addr src)
 {
-    memReq->reset(src, (dcacheInterface) ?
-                  dcacheInterface->getBlockSize()
-                  : 64);
+    static bool no_warn = true;
+    int blk_size = (dcacheInterface) ? dcacheInterface->getBlockSize() : 64;
+    // Only support block sizes of 64 atm.
+    assert(blk_size == 64);
+    int offset = src & (blk_size - 1);
+
+    // Make sure block doesn't span page
+    if (no_warn &&
+        (src & TheISA::PageMask) != ((src + blk_size) & TheISA::PageMask) &&
+        (src >> 40) != 0xfffffc) {
+        warn("Copied block source spans pages %x.", src);
+        no_warn = false;
+    }
+
+    memReq->reset(src & ~(blk_size - 1), blk_size);
 
     // translate to physical address
     Fault fault = xc->translateDataReadReq(memReq);
 
+    assert(fault != Alignment_Fault);
+
     if (fault == No_Fault) {
         xc->copySrcAddr = src;
-        xc->copySrcPhysAddr = memReq->paddr;
+        xc->copySrcPhysAddr = memReq->paddr + offset;
     } else {
         xc->copySrcAddr = 0;
         xc->copySrcPhysAddr = 0;
@@ -350,19 +367,44 @@ SimpleCPU::copySrcTranslate(Addr src)
 Fault
 SimpleCPU::copy(Addr dest)
 {
+    static bool no_warn = true;
     int blk_size = (dcacheInterface) ? dcacheInterface->getBlockSize() : 64;
+    // Only support block sizes of 64 atm.
+    assert(blk_size == 64);
     uint8_t data[blk_size];
-    assert(xc->copySrcPhysAddr);
-    memReq->reset(dest, blk_size);
+    //assert(xc->copySrcAddr);
+    int offset = dest & (blk_size - 1);
+
+    // Make sure block doesn't span page
+    if (no_warn &&
+        (dest & TheISA::PageMask) != ((dest + blk_size) & TheISA::PageMask) &&
+        (dest >> 40) != 0xfffffc) {
+        no_warn = false;
+        warn("Copied block destination spans pages %x. ", dest);
+    }
+
+    memReq->reset(dest & ~(blk_size -1), blk_size);
     // translate to physical address
     Fault fault = xc->translateDataWriteReq(memReq);
+
+    assert(fault != Alignment_Fault);
+
     if (fault == No_Fault) {
-        Addr dest_addr = memReq->paddr;
+        Addr dest_addr = memReq->paddr + offset;
         // Need to read straight from memory since we have more than 8 bytes.
         memReq->paddr = xc->copySrcPhysAddr;
         xc->mem->read(memReq, data);
         memReq->paddr = dest_addr;
         xc->mem->write(memReq, data);
+        if (dcacheInterface) {
+            memReq->cmd = Copy;
+            memReq->completionEvent = NULL;
+            memReq->paddr = xc->copySrcPhysAddr;
+            memReq->dest = dest_addr;
+            memReq->size = 64;
+            memReq->time = curTick;
+            dcacheInterface->access(memReq);
+        }
     }
     return fault;
 }
@@ -406,7 +448,7 @@ SimpleCPU::read(Addr addr, T &data, unsigned flags)
     }
 
     if (!dcacheInterface && (memReq->flags & UNCACHEABLE))
-        Stats::recordEvent("Uncached Read");
+        recordEvent("Uncached Read");
 
     return fault;
 }
@@ -494,7 +536,7 @@ SimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
         *res = memReq->result;
 
     if (!dcacheInterface && (memReq->flags & UNCACHEABLE))
-        Stats::recordEvent("Uncached Write");
+        recordEvent("Uncached Write");
 
     return fault;
 }
@@ -602,13 +644,11 @@ SimpleCPU::tick()
     Fault fault = No_Fault;
 
 #ifdef FULL_SYSTEM
-    if (AlphaISA::check_interrupts &&
-        xc->cpu->check_interrupts() &&
-        !PC_PAL(xc->regs.pc) &&
+    if (checkInterrupts && check_interrupts() && !xc->inPalMode() &&
         status() != IcacheMissComplete) {
         int ipl = 0;
         int summary = 0;
-        AlphaISA::check_interrupts = 0;
+        checkInterrupts = false;
         IntReg *ipr = xc->regs.ipr;
 
         if (xc->regs.ipr[TheISA::IPR_SIRR]) {
@@ -725,9 +765,8 @@ SimpleCPU::tick()
         fault = si->execute(this, traceData);
 
 #ifdef FULL_SYSTEM
-        SWContext *ctx = xc->swCtx;
-        if (ctx)
-            ctx->process(xc, si.get());
+        if (xc->fnbin)
+            xc->execute(si.get());
 #endif
 
         if (si->isMemRef()) {
@@ -742,6 +781,8 @@ SimpleCPU::tick()
         if (traceData)
             traceData->finalize();
 
+        traceFunctions(xc->regs.pc);
+
     }  // if (fault == No_Fault)
 
     if (fault != No_Fault) {
@@ -799,6 +840,9 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(SimpleCPU)
     SimObjectParam<BaseMem *> dcache;
 
     Param<bool> defer_registration;
+    Param<int> multiplier;
+    Param<bool> function_trace;
+    Param<Tick> function_trace_start;
 
 END_DECLARE_SIM_OBJECT_PARAMS(SimpleCPU)
 
@@ -830,7 +874,11 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(SimpleCPU)
     INIT_PARAM_DFLT(icache, "L1 instruction cache object", NULL),
     INIT_PARAM_DFLT(dcache, "L1 data cache object", NULL),
     INIT_PARAM_DFLT(defer_registration, "defer registration with system "
-                    "(for sampling)", false)
+                    "(for sampling)", false),
+
+    INIT_PARAM_DFLT(multiplier, "clock multiplier", 1),
+    INIT_PARAM_DFLT(function_trace, "Enable function trace", false),
+    INIT_PARAM_DFLT(function_trace_start, "Cycle to start function trace", 0)
 
 END_INIT_SIM_OBJECT_PARAMS(SimpleCPU)
 
@@ -849,7 +897,8 @@ CREATE_SIM_OBJECT(SimpleCPU)
                         (icache) ? icache->getInterface() : NULL,
                         (dcache) ? dcache->getInterface() : NULL,
                         defer_registration,
-                        ticksPerSecond * mult);
+                        ticksPerSecond * mult,
+                        function_trace, function_trace_start);
 #else
 
     cpu = new SimpleCPU(getInstanceName(), workload,
@@ -857,10 +906,13 @@ CREATE_SIM_OBJECT(SimpleCPU)
                         max_loads_any_thread, max_loads_all_threads,
                         (icache) ? icache->getInterface() : NULL,
                         (dcache) ? dcache->getInterface() : NULL,
-                        defer_registration);
+                        defer_registration,
+                        function_trace, function_trace_start);
 
 #endif // FULL_SYSTEM
 
+    cpu->setTickMultiplier(multiplier);
+
     return cpu;
 }