Fix the system clock at 1THz making 1 simulation tick = 1 ps
[gem5.git] / cpu / exec_context.cc
index c81d172a85be6d8192e01fd3786a0aa219577630..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 "base_cpu.hh"
-#include "exec_context.hh"
+#include "cpu/base.hh"
+#include "cpu/exec_context.hh"
 
-#ifdef FULL_SYSTEM
-#include "system.hh"
+#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 "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,
-                         FunctionalMemory *_mem, int _cpu_id)
-    : kernelStats(this, _cpu), cpu(_cpu), thread_num(_thread_num), mem(_mem),
-      itb(_itb), dtb(_dtb), cpu_id(_cpu_id), system(_sys),
-      memCtrl(_sys->memCtrl), physmem(_sys->physmem)
+                         AlphaITB *_itb, AlphaDTB *_dtb,
+                         FunctionalMemory *_mem)
+    : _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),
+      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));
-    _status = Active;
-    func_exe_insn = 0;
-    storeCondFailures = 0;
-    system->registerExecContext(this);
+
+    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,
                          Process *_process, int _asid)
-    : cpu(_cpu), thread_num(_thread_num), process(_process), asid (_asid)
+    : _status(ExecContext::Unallocated),
+      cpu(_cpu), thread_num(_thread_num), cpu_id(-1),
+      process(_process), mem(process->getMemory()), asid(_asid),
+      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_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
 
-    // Register with process object. Our 'active' will be set by the
-    // process iff we're the initial context.  Others are reserved for
-    // dynamically created threads.
-    process->registerExecContext(this);
+void
+ExecContext::takeOverFrom(ExecContext *oldContext)
+{
+    // some things should already be set up
+    assert(mem == oldContext->mem);
+#if FULL_SYSTEM
+    assert(system == oldContext->system);
+#else
+    assert(process == oldContext->process);
+#endif
 
-    mem = process->getMemory();
+    // copy over functional state
+    _status = oldContext->_status;
+    regs = oldContext->regs;
+    cpu_id = oldContext->cpu_id;
+    func_exe_inst = oldContext->func_exe_inst;
 
-    func_exe_insn = 0;
     storeCondFailures = 0;
+
+    oldContext->_status = ExecContext::Unallocated;
 }
 
-ExecContext::ExecContext(BaseCPU *_cpu, int _thread_num,
-                         FunctionalMemory *_mem, int _asid)
-    : cpu(_cpu), thread_num(_thread_num), process(NULL), mem(_mem),
-      asid(_asid)
+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_inst);
+    SERIALIZE_SCALAR(inst);
+
+#if FULL_SYSTEM
+    kernelStats->serialize(os);
+#endif
 }
+
+
+void
+ExecContext::unserialize(Checkpoint *cp, const std::string &section)
+{
+    UNSERIALIZE_ENUM(_status);
+    regs.unserialize(cp, section);
+    // thread_num and cpu_id are deterministic from the config
+    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)
 {
-#ifdef FULL_SYSTEM
-    if (status() == new_status)
+    if (status() == Active)
         return;
 
+    _status = Active;
+    cpu->activateContext(thread_num, delay);
+}
+
+void
+ExecContext::suspend()
+{
+    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();
+    _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
 }