Fix the system clock at 1THz making 1 simulation tick = 1 ps
[gem5.git] / cpu / exec_context.cc
index b869a8c4d8b898e3b6bdfd09c61c356b2761840c..9bed3ba471be7662f650fb5421323e1eed6eab91 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003 The Regents of The University of Michigan
+ * Copyright (c) 2001-2005 The Regents of The University of Michigan
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
 
 #include <string>
 
-#include "cpu/base_cpu.hh"
+#include "cpu/base.hh"
 #include "cpu/exec_context.hh"
 
-#ifdef FULL_SYSTEM
+#if FULL_SYSTEM
+#include "base/callback.hh"
+#include "base/cprintf.hh"
+#include "base/output.hh"
+#include "cpu/profile.hh"
+#include "kern/kernel_stats.hh"
+#include "sim/serialize.hh"
+#include "sim/sim_exit.hh"
 #include "sim/system.hh"
+#include "targetarch/stacktrace.hh"
 #else
-#include "sim/prog.hh"
+#include "sim/process.hh"
 #endif
 
 using namespace std;
 
 // constructor
-#ifdef FULL_SYSTEM
+#if FULL_SYSTEM
 ExecContext::ExecContext(BaseCPU *_cpu, int _thread_num, System *_sys,
-                         AlphaItb *_itb, AlphaDtb *_dtb,
+                         AlphaITB *_itb, AlphaDTB *_dtb,
                          FunctionalMemory *_mem)
-    : _status(ExecContext::Unallocated),
-      kernelStats(this, _cpu), cpu(_cpu), thread_num(_thread_num),
+    : _status(ExecContext::Unallocated), cpu(_cpu), thread_num(_thread_num),
       cpu_id(-1), mem(_mem), itb(_itb), dtb(_dtb), system(_sys),
-      memCtrl(_sys->memCtrl), physmem(_sys->physmem),
-      func_exe_insn(0), storeCondFailures(0)
+      memctrl(_sys->memctrl), physmem(_sys->physmem),
+      kernelBinning(system->kernelBinning), bin(kernelBinning->bin),
+      fnbin(kernelBinning->fnbin), profile(NULL),
+      func_exe_inst(0), storeCondFailures(0)
 {
+    kernelStats = new Kernel::Statistics(this);
     memset(&regs, 0, sizeof(RegFile));
+
+    if (cpu->params->profile) {
+        profile = new FunctionProfile(system->kernelSymtab);
+        Callback *cb =
+            new MakeCallback<ExecContext, &ExecContext::dumpFuncProfile>(this);
+        registerExitCallback(cb);
+    }
+
+    // let's fill with a dummy node for now so we don't get a segfault
+    // on the first cycle when there's no node available.
+    static ProfileNode dummyNode;
+    profileNode = &dummyNode;
+    profilePC = 3;
 }
 #else
 ExecContext::ExecContext(BaseCPU *_cpu, int _thread_num,
@@ -58,25 +81,42 @@ ExecContext::ExecContext(BaseCPU *_cpu, int _thread_num,
     : _status(ExecContext::Unallocated),
       cpu(_cpu), thread_num(_thread_num), cpu_id(-1),
       process(_process), mem(process->getMemory()), asid(_asid),
-      func_exe_insn(0), storeCondFailures(0)
+      func_exe_inst(0), storeCondFailures(0)
 {
+    memset(&regs, 0, sizeof(RegFile));
 }
 
 ExecContext::ExecContext(BaseCPU *_cpu, int _thread_num,
                          FunctionalMemory *_mem, int _asid)
     : cpu(_cpu), thread_num(_thread_num), process(0), mem(_mem), asid(_asid),
-      func_exe_insn(0), storeCondFailures(0)
+      func_exe_inst(0), storeCondFailures(0)
 {
+    memset(&regs, 0, sizeof(RegFile));
 }
 #endif
 
+ExecContext::~ExecContext()
+{
+#if FULL_SYSTEM
+    delete kernelStats;
+#endif
+}
+
+#if FULL_SYSTEM
+void
+ExecContext::dumpFuncProfile()
+{
+    std::ostream *os = simout.create(csprintf("profile.%s.dat", cpu->name()));
+    profile->dump(this, *os);
+}
+#endif
 
 void
 ExecContext::takeOverFrom(ExecContext *oldContext)
 {
     // some things should already be set up
     assert(mem == oldContext->mem);
-#ifdef FULL_SYSTEM
+#if FULL_SYSTEM
     assert(system == oldContext->system);
 #else
     assert(process == oldContext->process);
@@ -84,61 +124,111 @@ ExecContext::takeOverFrom(ExecContext *oldContext)
 
     // copy over functional state
     _status = oldContext->_status;
-#ifdef FULL_SYSTEM
-    kernelStats = oldContext->kernelStats;
-#endif
     regs = oldContext->regs;
     cpu_id = oldContext->cpu_id;
-    func_exe_insn = oldContext->func_exe_insn;
+    func_exe_inst = oldContext->func_exe_inst;
 
     storeCondFailures = 0;
 
     oldContext->_status = ExecContext::Unallocated;
 }
 
-
 void
 ExecContext::serialize(ostream &os)
 {
     SERIALIZE_ENUM(_status);
     regs.serialize(os);
     // thread_num and cpu_id are deterministic from the config
-    SERIALIZE_SCALAR(func_exe_insn);
+    SERIALIZE_SCALAR(func_exe_inst);
+    SERIALIZE_SCALAR(inst);
+
+#if FULL_SYSTEM
+    kernelStats->serialize(os);
+#endif
 }
 
 
 void
-ExecContext::unserialize(const IniFile *db, const std::string &section)
+ExecContext::unserialize(Checkpoint *cp, const std::string &section)
 {
     UNSERIALIZE_ENUM(_status);
-    regs.unserialize(db, section);
+    regs.unserialize(cp, section);
     // thread_num and cpu_id are deterministic from the config
-    UNSERIALIZE_SCALAR(func_exe_insn);
+    UNSERIALIZE_SCALAR(func_exe_inst);
+    UNSERIALIZE_SCALAR(inst);
+
+#if FULL_SYSTEM
+    kernelStats->unserialize(cp, section);
+#endif
 }
 
 
 void
-ExecContext::setStatus(Status new_status)
+ExecContext::activate(int delay)
+{
+    if (status() == Active)
+        return;
+
+    _status = Active;
+    cpu->activateContext(thread_num, delay);
+}
+
+void
+ExecContext::suspend()
 {
-#ifdef FULL_SYSTEM
-    if (status() == new_status)
+    if (status() == Suspended)
         return;
 
+#if FULL_SYSTEM
     // Don't change the status from active if there are pending interrupts
-    if (new_status == Suspended && cpu->check_interrupts()) {
+    if (cpu->check_interrupts()) {
         assert(status() == Active);
         return;
     }
 #endif
 
-    _status = new_status;
-    cpu->execCtxStatusChg(thread_num);
+    _status = Suspended;
+    cpu->suspendContext(thread_num);
+}
+
+void
+ExecContext::deallocate()
+{
+    if (status() == Unallocated)
+        return;
+
+    _status = Unallocated;
+    cpu->deallocateContext(thread_num);
 }
 
+void
+ExecContext::halt()
+{
+    if (status() == Halted)
+        return;
+
+    _status = Halted;
+    cpu->haltContext(thread_num);
+}
+
+
 void
 ExecContext::regStats(const string &name)
 {
-#ifdef FULL_SYSTEM
-    kernelStats.regStats(name + ".kern");
+#if FULL_SYSTEM
+    kernelStats->regStats(name + ".kern");
+#endif
+}
+
+void
+ExecContext::trap(Fault fault)
+{
+    //TheISA::trap(fault);    //One possible way to do it...
+
+    /** @todo: Going to hack it for now.  Do a true fixup later. */
+#if FULL_SYSTEM
+    ev5_trap(fault);
+#else
+    fatal("fault (%d) detected @ PC 0x%08p", fault, readPC());
 #endif
 }