Merge zizzer.eecs.umich.edu:/z/m5/Bitkeeper/m5
[gem5.git] / cpu / base.cc
index 38431006e52376a4b067e22a0dc69f7e832cc3e0..5a7ecf152686af934836360331029498b380eaa1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002-2004 The Regents of The University of Michigan
+ * Copyright (c) 2002-2005 The Regents of The University of Michigan
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -36,6 +36,7 @@
 #include "base/output.hh"
 #include "cpu/base.hh"
 #include "cpu/exec_context.hh"
+#include "cpu/profile.hh"
 #include "cpu/sampler/sampler.hh"
 #include "sim/param.hh"
 #include "sim/sim_events.hh"
@@ -51,7 +52,7 @@ vector<BaseCPU *> BaseCPU::cpuList;
 // been initialized
 int maxThreadsPerCPU = 1;
 
-#ifdef FULL_SYSTEM
+#if FULL_SYSTEM
 BaseCPU::BaseCPU(Params *p)
     : SimObject(p->name), clock(p->clock), checkInterrupts(true),
       params(p), number_of_threads(p->numberOfThreads), system(p->system)
@@ -122,7 +123,7 @@ BaseCPU::BaseCPU(Params *p)
                 p->max_loads_all_threads, *counter);
     }
 
-#ifdef FULL_SYSTEM
+#if FULL_SYSTEM
     memset(interrupts, 0, sizeof(interrupts));
     intstatus = 0;
 #endif
@@ -142,8 +143,19 @@ BaseCPU::BaseCPU(Params *p)
             e->schedule(p->functionTraceStart);
         }
     }
+#if FULL_SYSTEM
+    profileEvent = NULL;
+    if (params->profile)
+        profileEvent = new ProfileEvent(this, params->profile);
+#endif
 }
 
+BaseCPU::Params::Params()
+{
+#if FULL_SYSTEM
+    profile = false;
+#endif
+}
 
 void
 BaseCPU::enableFunctionTrace()
@@ -162,6 +174,16 @@ BaseCPU::init()
         registerExecContexts();
 }
 
+void
+BaseCPU::startup()
+{
+#if FULL_SYSTEM
+    if (!params->deferRegistration && profileEvent)
+        profileEvent->schedule(curTick);
+#endif
+}
+
+
 void
 BaseCPU::regStats()
 {
@@ -189,15 +211,15 @@ BaseCPU::registerExecContexts()
 {
     for (int i = 0; i < execContexts.size(); ++i) {
         ExecContext *xc = execContexts[i];
-        int cpu_id;
+#if FULL_SYSTEM
+        int id = params->cpu_id;
+        if (id != -1)
+            id += i;
 
-#ifdef FULL_SYSTEM
-        cpu_id = system->registerExecContext(xc);
+        xc->cpu_id = system->registerExecContext(xc, id);
 #else
-        cpu_id = xc->process->registerExecContext(xc);
+        xc->cpu_id = xc->process->registerExecContext(xc);
 #endif
-
-        xc->cpu_id = cpu_id;
     }
 }
 
@@ -219,7 +241,7 @@ BaseCPU::takeOverFrom(BaseCPU *oldCPU)
 
         newXC->takeOverFrom(oldXC);
         assert(newXC->cpu_id == oldXC->cpu_id);
-#ifdef FULL_SYSTEM
+#if FULL_SYSTEM
         system->replaceExecContext(newXC, newXC->cpu_id);
 #else
         assert(newXC->process == oldXC->process);
@@ -227,21 +249,43 @@ BaseCPU::takeOverFrom(BaseCPU *oldCPU)
 #endif
     }
 
-#ifdef FULL_SYSTEM
-    for (int i = 0; i < NumInterruptLevels; ++i)
+#if FULL_SYSTEM
+    for (int i = 0; i < TheISA::NumInterruptLevels; ++i)
         interrupts[i] = oldCPU->interrupts[i];
     intstatus = oldCPU->intstatus;
+
+    for (int i = 0; i < execContexts.size(); ++i)
+        if (execContexts[i]->profile)
+            execContexts[i]->profile->clear();
+
+    if (profileEvent)
+        profileEvent->schedule(curTick);
 #endif
 }
 
 
-#ifdef FULL_SYSTEM
+#if FULL_SYSTEM
+BaseCPU::ProfileEvent::ProfileEvent(BaseCPU *_cpu, int _interval)
+    : Event(&mainEventQueue), cpu(_cpu), interval(_interval)
+{ }
+
+void
+BaseCPU::ProfileEvent::process()
+{
+    for (int i = 0, size = cpu->execContexts.size(); i < size; ++i) {
+        ExecContext *xc = cpu->execContexts[i];
+        xc->profile->sample(xc->profileNode, xc->profilePC);
+    }
+
+    schedule(curTick + interval);
+}
+
 void
 BaseCPU::post_interrupt(int int_num, int index)
 {
     DPRINTF(Interrupt, "Interrupt %d:%d posted\n", int_num, index);
 
-    if (int_num < 0 || int_num >= NumInterruptLevels)
+    if (int_num < 0 || int_num >= TheISA::NumInterruptLevels)
         panic("int_num out of bounds\n");
 
     if (index < 0 || index >= sizeof(uint64_t) * 8)
@@ -257,7 +301,7 @@ BaseCPU::clear_interrupt(int int_num, int index)
 {
     DPRINTF(Interrupt, "Interrupt %d:%d cleared\n", int_num, index);
 
-    if (int_num < 0 || int_num >= NumInterruptLevels)
+    if (int_num < 0 || int_num >= TheISA::NumInterruptLevels)
         panic("int_num out of bounds\n");
 
     if (index < 0 || index >= sizeof(uint64_t) * 8)
@@ -281,14 +325,14 @@ BaseCPU::clear_interrupts()
 void
 BaseCPU::serialize(std::ostream &os)
 {
-    SERIALIZE_ARRAY(interrupts, NumInterruptLevels);
+    SERIALIZE_ARRAY(interrupts, TheISA::NumInterruptLevels);
     SERIALIZE_SCALAR(intstatus);
 }
 
 void
 BaseCPU::unserialize(Checkpoint *cp, const std::string &section)
 {
-    UNSERIALIZE_ARRAY(interrupts, NumInterruptLevels);
+    UNSERIALIZE_ARRAY(interrupts, TheISA::NumInterruptLevels);
     UNSERIALIZE_SCALAR(intstatus);
 }