cpu: remove unnecessary data ptr from O3 internal read() funcs
[gem5.git] / src / sim / pseudo_inst.cc
index 52c7502a1b197156a8aff29a5ea1fbe7a02055d9..67c47ce778e338be516ecfe60af4a84f669d1a7e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2012 ARM Limited
+ * Copyright (c) 2010-2012, 2015 ARM Limited
  * All rights reserved
  *
  * The license below extends only to copyright in the software and shall
@@ -52,6 +52,7 @@
 #include "arch/kernel_stats.hh"
 #include "arch/utility.hh"
 #include "arch/vtophys.hh"
+#include "arch/pseudo_inst.hh"
 #include "base/debug.hh"
 #include "base/output.hh"
 #include "config/the_isa.hh"
 #include "cpu/quiesce_event.hh"
 #include "cpu/thread_context.hh"
 #include "debug/Loader.hh"
+#include "debug/PseudoInst.hh"
 #include "debug/Quiesce.hh"
 #include "debug/WorkItems.hh"
+#include "dev/net/dist_iface.hh"
 #include "params/BaseCPU.hh"
 #include "sim/full_system.hh"
+#include "sim/initparam_keys.hh"
+#include "sim/process.hh"
 #include "sim/pseudo_inst.hh"
 #include "sim/serialize.hh"
 #include "sim/sim_events.hh"
@@ -90,13 +95,17 @@ pseudoInst(ThreadContext *tc, uint8_t func, uint8_t subfunc)
 {
     uint64_t args[4];
 
+    DPRINTF(PseudoInst, "PseudoInst::pseudoInst(%i, %i)\n", func, subfunc);
+
     // We need to do this in a slightly convoluted way since
     // getArgument() might have side-effects on arg_num. We could have
     // used the Argument class, but due to the possible side effects
     // from getArgument, it'd most likely break.
     int arg_num(0);
-    for (int i = 0; i < sizeof(args) / sizeof(*args); ++i)
-        args[arg_num++] = getArgument(tc, arg_num, sizeof(uint64_t), false);
+    for (int i = 0; i < sizeof(args) / sizeof(*args); ++i) {
+        args[arg_num] = getArgument(tc, arg_num, sizeof(uint64_t), false);
+        ++arg_num;
+    }
 
     switch (func) {
       case 0x00: // arm_func
@@ -129,8 +138,12 @@ pseudoInst(ThreadContext *tc, uint8_t func, uint8_t subfunc)
         m5exit(tc, args[0]);
         break;
 
+      case 0x22:
+        m5fail(tc, args[0], args[1]);
+        break;
+
       case 0x30: // initparam_func
-        return initParam(tc);
+        return initParam(tc, args[0], args[1]);
 
       case 0x31: // loadsymbol_func
         loadsymbol(tc);
@@ -189,6 +202,15 @@ pseudoInst(ThreadContext *tc, uint8_t func, uint8_t subfunc)
         warn("Unimplemented m5 op (0x%x)\n", func);
         break;
 
+      /* SE mode functions */
+      case 0x60: // syscall_func
+        m5Syscall(tc);
+        break;
+
+      case 0x61: // pagefault_func
+        m5PageFault(tc);
+        break;
+
       default:
         warn("Unhandled m5 op: 0x%x\n", func);
         break;
@@ -200,6 +222,7 @@ pseudoInst(ThreadContext *tc, uint8_t func, uint8_t subfunc)
 void
 arm(ThreadContext *tc)
 {
+    DPRINTF(PseudoInst, "PseudoInst::arm()\n");
     if (!FullSystem)
         panicFsOnlyPseudoInst("arm");
 
@@ -210,6 +233,7 @@ arm(ThreadContext *tc)
 void
 quiesce(ThreadContext *tc)
 {
+    DPRINTF(PseudoInst, "PseudoInst::quiesce()\n");
     if (!FullSystem)
         panicFsOnlyPseudoInst("quiesce");
 
@@ -226,6 +250,7 @@ quiesce(ThreadContext *tc)
 void
 quiesceSkip(ThreadContext *tc)
 {
+    DPRINTF(PseudoInst, "PseudoInst::quiesceSkip()\n");
     if (!FullSystem)
         panicFsOnlyPseudoInst("quiesceSkip");
 
@@ -251,12 +276,13 @@ quiesceSkip(ThreadContext *tc)
 void
 quiesceNs(ThreadContext *tc, uint64_t ns)
 {
+    DPRINTF(PseudoInst, "PseudoInst::quiesceNs(%i)\n", ns);
     if (!FullSystem)
         panicFsOnlyPseudoInst("quiesceNs");
 
     BaseCPU *cpu = tc->getCpuPtr();
 
-    if (!cpu->params()->do_quiesce || ns == 0)
+    if (!cpu->params()->do_quiesce)
         return;
 
     EndQuiesceEvent *quiesceEvent = tc->getQuiesceEvent();
@@ -276,12 +302,13 @@ quiesceNs(ThreadContext *tc, uint64_t ns)
 void
 quiesceCycles(ThreadContext *tc, uint64_t cycles)
 {
+    DPRINTF(PseudoInst, "PseudoInst::quiesceCycles(%i)\n", cycles);
     if (!FullSystem)
         panicFsOnlyPseudoInst("quiesceCycles");
 
     BaseCPU *cpu = tc->getCpuPtr();
 
-    if (!cpu->params()->do_quiesce || cycles == 0)
+    if (!cpu->params()->do_quiesce)
         return;
 
     EndQuiesceEvent *quiesceEvent = tc->getQuiesceEvent();
@@ -301,6 +328,7 @@ quiesceCycles(ThreadContext *tc, uint64_t cycles)
 uint64_t
 quiesceTime(ThreadContext *tc)
 {
+    DPRINTF(PseudoInst, "PseudoInst::quiesceTime()\n");
     if (!FullSystem) {
         panicFsOnlyPseudoInst("quiesceTime");
         return 0;
@@ -313,12 +341,14 @@ quiesceTime(ThreadContext *tc)
 uint64_t
 rpns(ThreadContext *tc)
 {
+    DPRINTF(PseudoInst, "PseudoInst::rpns()\n");
     return curTick() / SimClock::Int::ns;
 }
 
 void
 wakeCPU(ThreadContext *tc, uint64_t cpuid)
 {
+    DPRINTF(PseudoInst, "PseudoInst::wakeCPU(%i)\n", cpuid);
     System *sys = tc->getSystemPtr();
     ThreadContext *other_tc = sys->threadContexts[cpuid];
     if (other_tc->status() == ThreadContext::Suspended)
@@ -328,20 +358,25 @@ wakeCPU(ThreadContext *tc, uint64_t cpuid)
 void
 m5exit(ThreadContext *tc, Tick delay)
 {
-    Tick when = curTick() + delay * SimClock::Int::ns;
-    exitSimLoop("m5_exit instruction encountered", 0, when);
+    DPRINTF(PseudoInst, "PseudoInst::m5exit(%i)\n", delay);
+    if (DistIface::readyToExit(delay)) {
+        Tick when = curTick() + delay * SimClock::Int::ns;
+        exitSimLoop("m5_exit instruction encountered", 0, when, 0, true);
+    }
 }
 
 void
 m5fail(ThreadContext *tc, Tick delay, uint64_t code)
 {
+    DPRINTF(PseudoInst, "PseudoInst::m5fail(%i, %i)\n", delay, code);
     Tick when = curTick() + delay * SimClock::Int::ns;
-    exitSimLoop("m5_fail instruction encountered", code, when);
+    exitSimLoop("m5_fail instruction encountered", code, when, 0, true);
 }
 
 void
 loadsymbol(ThreadContext *tc)
 {
+    DPRINTF(PseudoInst, "PseudoInst::loadsymbol()\n");
     if (!FullSystem)
         panicFsOnlyPseudoInst("loadsymbol");
 
@@ -393,6 +428,8 @@ loadsymbol(ThreadContext *tc)
 void
 addsymbol(ThreadContext *tc, Addr addr, Addr symbolAddr)
 {
+    DPRINTF(PseudoInst, "PseudoInst::addsymbol(0x%x, 0x%x)\n",
+            addr, symbolAddr);
     if (!FullSystem)
         panicFsOnlyPseudoInst("addSymbol");
 
@@ -407,20 +444,54 @@ addsymbol(ThreadContext *tc, Addr addr, Addr symbolAddr)
 }
 
 uint64_t
-initParam(ThreadContext *tc)
+initParam(ThreadContext *tc, uint64_t key_str1, uint64_t key_str2)
 {
+    DPRINTF(PseudoInst, "PseudoInst::initParam() key:%s%s\n", (char *)&key_str1,
+            (char *)&key_str2);
     if (!FullSystem) {
         panicFsOnlyPseudoInst("initParam");
         return 0;
     }
 
-    return tc->getCpuPtr()->system->init_param;
+    // The key parameter string is passed in via two 64-bit registers. We copy
+    // out the characters from the 64-bit integer variables here and concatenate
+    // them in the key_str character buffer
+    const int len = 2 * sizeof(uint64_t) + 1;
+    char key_str[len];
+    memset(key_str, '\0', len);
+    if (key_str1 == 0) {
+        assert(key_str2 == 0);
+    } else {
+        strncpy(key_str, (char *)&key_str1, sizeof(uint64_t));
+    }
+
+    if (strlen(key_str) == sizeof(uint64_t)) {
+        strncpy(key_str + sizeof(uint64_t), (char *)&key_str2,
+                sizeof(uint64_t));
+    } else {
+        assert(key_str2 == 0);
+    }
+
+    // Compare the key parameter with the known values to select the return
+    // value
+    uint64_t val;
+    if (strcmp(key_str, InitParamKey::DEFAULT) == 0) {
+        val = tc->getCpuPtr()->system->init_param;
+    } else if (strcmp(key_str, InitParamKey::DIST_RANK) == 0) {
+        val = DistIface::rankParam();
+    } else if (strcmp(key_str, InitParamKey::DIST_SIZE) == 0) {
+        val = DistIface::sizeParam();
+    } else {
+        panic("Unknown key for initparam pseudo instruction:\"%s\"", key_str);
+    }
+    return val;
 }
 
 
 void
 resetstats(ThreadContext *tc, Tick delay, Tick period)
 {
+    DPRINTF(PseudoInst, "PseudoInst::resetstats(%i, %i)\n", delay, period);
     if (!tc->getCpuPtr()->params()->do_statistics_insts)
         return;
 
@@ -434,6 +505,7 @@ resetstats(ThreadContext *tc, Tick delay, Tick period)
 void
 dumpstats(ThreadContext *tc, Tick delay, Tick period)
 {
+    DPRINTF(PseudoInst, "PseudoInst::dumpstats(%i, %i)\n", delay, period);
     if (!tc->getCpuPtr()->params()->do_statistics_insts)
         return;
 
@@ -447,6 +519,7 @@ dumpstats(ThreadContext *tc, Tick delay, Tick period)
 void
 dumpresetstats(ThreadContext *tc, Tick delay, Tick period)
 {
+    DPRINTF(PseudoInst, "PseudoInst::dumpresetstats(%i, %i)\n", delay, period);
     if (!tc->getCpuPtr()->params()->do_statistics_insts)
         return;
 
@@ -460,18 +533,22 @@ dumpresetstats(ThreadContext *tc, Tick delay, Tick period)
 void
 m5checkpoint(ThreadContext *tc, Tick delay, Tick period)
 {
+    DPRINTF(PseudoInst, "PseudoInst::m5checkpoint(%i, %i)\n", delay, period);
     if (!tc->getCpuPtr()->params()->do_checkpoint_insts)
         return;
 
-    Tick when = curTick() + delay * SimClock::Int::ns;
-    Tick repeat = period * SimClock::Int::ns;
-
-    exitSimLoop("checkpoint", 0, when, repeat);
+    if (DistIface::readyToCkpt(delay, period)) {
+        Tick when = curTick() + delay * SimClock::Int::ns;
+        Tick repeat = period * SimClock::Int::ns;
+        exitSimLoop("checkpoint", 0, when, repeat);
+    }
 }
 
 uint64_t
 readfile(ThreadContext *tc, Addr vaddr, uint64_t len, uint64_t offset)
 {
+    DPRINTF(PseudoInst, "PseudoInst::readfile(0x%x, 0x%x, 0x%x)\n",
+            vaddr, len, offset);
     if (!FullSystem) {
         panicFsOnlyPseudoInst("readfile");
         return 0;
@@ -513,6 +590,8 @@ uint64_t
 writefile(ThreadContext *tc, Addr vaddr, uint64_t len, uint64_t offset,
             Addr filename_addr)
 {
+    DPRINTF(PseudoInst, "PseudoInst::writefile(0x%x, 0x%x, 0x%x, 0x%x)\n",
+            vaddr, len, offset, filename_addr);
     ostream *os;
 
     // copy out target filename
@@ -523,13 +602,13 @@ writefile(ThreadContext *tc, Addr vaddr, uint64_t len, uint64_t offset,
 
     if (offset == 0) {
         // create a new file (truncate)
-        os = simout.create(filename, true);
+        os = simout.create(filename, true, true);
     } else {
         // do not truncate file if offset is non-zero
         // (ios::in flag is required as well to keep the existing data
         //  intact, otherwise existing data will be zeroed out.)
         os = simout.openFile(simout.directory() + filename,
-                            ios::in | ios::out | ios::binary);
+                            ios::in | ios::out | ios::binary, true);
     }
     if (!os)
         panic("could not open file %s\n", filename);
@@ -554,12 +633,14 @@ writefile(ThreadContext *tc, Addr vaddr, uint64_t len, uint64_t offset,
 void
 debugbreak(ThreadContext *tc)
 {
+    DPRINTF(PseudoInst, "PseudoInst::debugbreak()\n");
     Debug::breakpoint();
 }
 
 void
 switchcpu(ThreadContext *tc)
 {
+    DPRINTF(PseudoInst, "PseudoInst::switchcpu()\n");
     exitSimLoop("switchcpu");
 }
 
@@ -571,13 +652,19 @@ switchcpu(ThreadContext *tc)
 void
 workbegin(ThreadContext *tc, uint64_t workid, uint64_t threadid)
 {
-    tc->getCpuPtr()->workItemBegin();
+    DPRINTF(PseudoInst, "PseudoInst::workbegin(%i, %i)\n", workid, threadid);
     System *sys = tc->getSystemPtr();
     const System::Params *params = sys->params();
-    sys->workItemBegin(threadid, workid);
 
-    DPRINTF(WorkItems, "Work Begin workid: %d, threadid %d\n", workid, 
+    if (params->exit_on_work_items) {
+        exitSimLoop("workbegin", static_cast<int>(workid));
+        return;
+    }
+
+    DPRINTF(WorkItems, "Work Begin workid: %d, threadid %d\n", workid,
             threadid);
+    tc->getCpuPtr()->workItemBegin();
+    sys->workItemBegin(threadid, workid);
 
     //
     // If specified, determine if this is the specific work item the user
@@ -628,12 +715,18 @@ workbegin(ThreadContext *tc, uint64_t workid, uint64_t threadid)
 void
 workend(ThreadContext *tc, uint64_t workid, uint64_t threadid)
 {
-    tc->getCpuPtr()->workItemEnd();
+    DPRINTF(PseudoInst, "PseudoInst::workend(%i, %i)\n", workid, threadid);
     System *sys = tc->getSystemPtr();
     const System::Params *params = sys->params();
-    sys->workItemEnd(threadid, workid);
+
+    if (params->exit_on_work_items) {
+        exitSimLoop("workend", static_cast<int>(workid));
+        return;
+    }
 
     DPRINTF(WorkItems, "Work End workid: %d, threadid %d\n", workid, threadid);
+    tc->getCpuPtr()->workItemEnd();
+    sys->workItemEnd(threadid, workid);
 
     //
     // If specified, determine if this is the specific work item the user