m5: added work completed monitoring support
authorBrad Beckmann <Brad.Beckmann@amd.com>
Mon, 7 Feb 2011 06:14:19 +0000 (22:14 -0800)
committerBrad Beckmann <Brad.Beckmann@amd.com>
Mon, 7 Feb 2011 06:14:19 +0000 (22:14 -0800)
15 files changed:
configs/common/FSConfig.py
configs/common/Options.py
configs/example/fs.py
configs/example/ruby_fs.py
src/arch/x86/isa/decoder/two_byte_opcodes.isa
src/cpu/base.cc
src/cpu/base.hh
src/sim/SConscript
src/sim/System.py
src/sim/pseudo_inst.cc
src/sim/pseudo_inst.hh
src/sim/system.cc
src/sim/system.hh
util/m5/m5op_x86.S
util/m5/m5ops.h

index 9b94e7ffa93b2bab6241af18b918ebedc554c426..e94818312ee3c5372435292818ce953264bc68a8 100644 (file)
@@ -405,7 +405,8 @@ def makeX86System(mem_mode, numCPUs = 1, mdesc = None, self = None, Ruby = False
     for i in range(3, 15):
         assignISAInt(i, i)
 
-def makeLinuxX86System(mem_mode, numCPUs = 1, mdesc = None, Ruby = False):
+def makeLinuxX86System(mem_mode, options, mdesc = None, Ruby = False):
+    numCPUs = options.num_cpus
     self = LinuxX86System()
 
     # Build up the x86 system and then specialize it for Linux
@@ -415,6 +416,22 @@ def makeLinuxX86System(mem_mode, numCPUs = 1, mdesc = None, Ruby = False):
     # just to avoid corner cases.
     assert(self.physmem.range.second.getValue() >= 0x200000)
 
+    # set work count options
+    if options.work_item_id != None:
+        self.work_item_id = options.work_item_id
+    if options.work_begin_cpu_id_exit != None:
+        self.work_begin_cpu_id_exit = options.work_begin_cpu_id_exit
+    if options.work_end_exit_count != None:
+        self.work_end_exit_count = options.work_end_exit_count
+    if options.work_end_checkpoint_count != None:
+        self.work_end_ckpt_count = options.work_end_checkpoint_count
+    if options.work_begin_exit_count != None:
+        self.work_begin_exit_count = options.work_begin_exit_count
+    if options.work_begin_checkpoint_count != None:
+        self.work_begin_ckpt_count = options.work_begin_checkpoint_count
+    if options.work_cpus_checkpoint_count != None:
+        self.work_cpus_ckpt_count = options.work_cpus_checkpoint_count
+
     # Mark the first megabyte of memory as reserved
     self.e820_table.entries.append(X86E820Entry(
                 addr = 0,
index 42e1585d78be5b1d0d837ca5a03ed98e853ee64a..7605c7d0de44dfe17e420f81cdac35fcca47f22f 100644 (file)
@@ -54,6 +54,14 @@ parser.add_option("-m", "--maxtick", type="int", default=m5.MaxTick,
 parser.add_option("--maxtime", type="float")
 parser.add_option("--maxinsts", type="int")
 parser.add_option("--prog_intvl", type="int")
+parser.add_option("--work-item-id", action="store", type="int",
+                  help="the specific work id for exit & checkpointing")
+parser.add_option("--work-begin-cpu-id-exit", action="store", type="int",
+                  help="exit when work starts on the specified cpu")
+parser.add_option("--work-end-exit-count", action="store", type="int",
+                  help="exit at specified work end count")
+parser.add_option("--work-begin-exit-count", action="store", type="int",
+                  help="exit at specified work begin count")
 
 
 # Checkpointing options
@@ -69,6 +77,12 @@ parser.add_option("-r", "--checkpoint-restore", action="store", type="int",
     help="restore from checkpoint <N>")
 parser.add_option("--checkpoint-at-end", action="store_true",
                   help="take a checkpoint at end of run")
+parser.add_option("--work-begin-checkpoint-count", action="store", type="int",
+                  help="checkpoint at specified work begin count")
+parser.add_option("--work-end-checkpoint-count", action="store", type="int",
+                  help="checkpoint at specified work end count")
+parser.add_option("--work-cpus-checkpoint-count", action="store", type="int",
+                  help="checkpoint and exit when active cpu count is reached")
 
 
 # CPU Switching - default switch model goes from a checkpoint
index 1a052e28228444c913d28bc99ad5c3649b8d208e..a097c41380a08c170461372636b6facb27f1bc8d 100644 (file)
@@ -131,7 +131,7 @@ elif buildEnv['TARGET_ISA'] == "mips":
 elif buildEnv['TARGET_ISA'] == "sparc":
     test_sys = makeSparcSystem(test_mem_mode, bm[0])
 elif buildEnv['TARGET_ISA'] == "x86":
-    test_sys = makeLinuxX86System(test_mem_mode, np, bm[0])
+    test_sys = makeLinuxX86System(test_mem_mode, options, bm[0])
 elif buildEnv['TARGET_ISA'] == "arm":
     test_sys = makeLinuxArmSystem(test_mem_mode, bm[0],
             bare_metal=options.bare_metal, machine_type=options.machine_type)
index 721315c9f20baa3867abfcac051eebd7d85d843e..6f35f02cd193a4a83149f9bb74b6f696e28adf1a 100644 (file)
@@ -116,7 +116,7 @@ if buildEnv['TARGET_ISA'] == "alpha":
                                      system.piobus,
                                      system.dma_devices)
 elif buildEnv['TARGET_ISA'] == "x86":
-    system = makeLinuxX86System(test_mem_mode, options.num_cpus, bm[0], True)
+    system = makeLinuxX86System(test_mem_mode, options, bm[0], True)
     system.ruby = Ruby.create_system(options,
                                      system,
                                      system.piobus)
index 1dc32122ecda0a3b9416408f1b8ea8b62059162b..11cd6eeb132b0b7764e7ab1887642d80ce4aeaf0 100644 (file)
                         0x59: m5reserved5({{
                             warn("M5 reserved opcode 5 ignored.\n");
                         }}, IsNonSpeculative);
+                        0x5a: m5_work_begin({{
+                            PseudoInst::workbegin(xc->tcBase(), Rdi, Rsi);
+                        }}, IsNonSpeculative);
+                        0x5b: m5_work_end({{
+                            PseudoInst::workend(xc->tcBase(), Rdi, Rsi);
+                        }}, IsNonSpeculative);
                         default: Inst::UD2();
                     }
                 }
index b7decaec13e77914c871d377061a7c833af437c9..17ae65793721ea97ee0bdd9fd1685c7262f581f8 100644 (file)
@@ -255,6 +255,16 @@ BaseCPU::regStats()
         .desc("number of cpu cycles simulated")
         ;
 
+    numWorkItemsStarted
+        .name(name() + ".numWorkItemsStarted")
+        .desc("number of work items this cpu started")
+        ;
+
+    numWorkItemsCompleted
+        .name(name() + ".numWorkItemsCompleted")
+        .desc("number of work items this cpu completed")
+        ;
+
     int size = threadContexts.size();
     if (size > 1) {
         for (int i = 0; i < size; ++i) {
index bea15aa0800b205e830b3487206ae1802fec735c..a56f3db24c36400b325550049ab145838b3c63b8 100644 (file)
@@ -104,6 +104,8 @@ class BaseCPU : public MemObject
     inline Tick ticks(int numCycles) const { return clock * numCycles; }
     inline Tick curCycle() const { return curTick() / clock; }
     inline Tick tickToCycles(Tick val) const { return val / clock; }
+    inline void workItemBegin() { numWorkItemsStarted++; }
+    inline void workItemEnd() { numWorkItemsCompleted++; }
     // @todo remove me after debugging with legion done
     Tick instCount() { return instCnt; }
 
@@ -317,6 +319,8 @@ class BaseCPU : public MemObject
   public:
     // Number of CPU cycles simulated
     Stats::Scalar numCycles;
+    Stats::Scalar numWorkItemsStarted;
+    Stats::Scalar numWorkItemsCompleted;
 };
 
 #endif // __CPU_BASE_HH__
index f959870cdbc6c55307bfb510b9ef6fa434d1578c..5c22e328ec68722fd31b447c909188390067fbb8 100644 (file)
@@ -78,3 +78,4 @@ TraceFlag('TLB')
 TraceFlag('Thread')
 TraceFlag('Timer')
 TraceFlag('VtoPhys')
+TraceFlag('WorkItems')
index e2d5b279bfc8ca014c1bc482ab18df079c8af55e..fd707c353079c7ec7e3ef9f0c290fdffe2464684 100644 (file)
@@ -47,6 +47,20 @@ class System(SimObject):
     physmem = Param.PhysicalMemory(Parent.any, "physical memory")
     mem_mode = Param.MemoryMode('atomic', "The mode the memory system is in")
 
+    work_item_id = Param.Int(-1, "specific work item id")
+    work_begin_cpu_id_exit = Param.Int(-1,
+        "work started on specific id, now exit simulation")
+    work_begin_ckpt_count = Param.Counter(0,
+        "create checkpoint when work items begin count value is reached")
+    work_begin_exit_count = Param.Counter(0,
+        "exit simulation when work items begin count value is reached")
+    work_end_ckpt_count = Param.Counter(0,
+        "create checkpoint when work items end count value is reached")
+    work_end_exit_count = Param.Counter(0,
+        "exit simulation when work items end count value is reached")
+    work_cpus_ckpt_count = Param.Counter(0,
+        "create checkpoint when active cpu count value is reached")
+
     if buildEnv['FULL_SYSTEM']:
         abstract = True
         boot_cpu_frequency = Param.Frequency(Self.cpu[0].clock.frequency,
index 9ee473014bc17fcfd445de18b32df80593f3e21a..f3b10f6d2179032c4ad7e1411a8b03643f2a2eb8 100644 (file)
@@ -328,4 +328,121 @@ switchcpu(ThreadContext *tc)
     exitSimLoop("switchcpu");
 }
 
+//
+// This function is executed when annotated work items begin.  Depending on 
+// what the user specified at the command line, the simulation may exit and/or
+// take a checkpoint when a certain work item begins.
+//
+void
+workbegin(ThreadContext *tc, uint64_t workid, uint64_t threadid)
+{
+    tc->getCpuPtr()->workItemBegin();
+    System *sys = tc->getSystemPtr();
+
+    DPRINTF(WorkItems, "Work Begin workid: %d, threadid %d\n", workid, 
+            threadid);
+
+    //
+    // If specified, determine if this is the specific work item the user
+    // identified
+    //
+    if (sys->params()->work_item_id == -1 || 
+        sys->params()->work_item_id == workid) {
+
+        uint64_t systemWorkBeginCount = sys->incWorkItemsBegin();
+        int cpuId = tc->getCpuPtr()->cpuId();
+
+        if (sys->params()->work_cpus_ckpt_count != 0 &&
+            sys->markWorkItem(cpuId) >= sys->params()->work_cpus_ckpt_count) {
+            //
+            // If active cpus equals checkpoint count, create checkpoint
+            //
+            Event *event = new SimLoopExitEvent("checkpoint", 0);
+            mainEventQueue.schedule(event, curTick());
+        }
+
+        if (systemWorkBeginCount == sys->params()->work_begin_ckpt_count) {
+            //
+            // Note: the string specified as the cause of the exit event must
+            // exactly equal "checkpoint" inorder to create a checkpoint
+            //
+            Event *event = new SimLoopExitEvent("checkpoint", 0);
+            mainEventQueue.schedule(event, curTick());
+        }
+
+        if (systemWorkBeginCount == sys->params()->work_begin_exit_count) {
+            //
+            // If a certain number of work items started, exit simulation
+            //
+            Event *event = new SimLoopExitEvent("work started count reach", 0);
+            mainEventQueue.schedule(event, curTick());
+        }
+
+        if (tc->getCpuPtr()->cpuId() == sys->params()->work_begin_cpu_id_exit) {
+            //
+            // If work started on the specific cpu id specified, exit simulation
+            //
+            Event *event = new SimLoopExitEvent("work started on specific cpu",
+                                                0);
+
+            mainEventQueue.schedule(event, curTick() + 1);
+        }
+    }
+}
+
+//
+// This function is executed when annotated work items end.  Depending on 
+// what the user specified at the command line, the simulation may exit and/or
+// take a checkpoint when a certain work item ends.
+//
+void
+workend(ThreadContext *tc, uint64_t workid, uint64_t threadid)
+{
+    tc->getCpuPtr()->workItemEnd();
+    System *sys = tc->getSystemPtr();
+
+    DPRINTF(WorkItems, "Work End workid: %d, threadid %d\n", workid, threadid);
+
+    //
+    // If specified, determine if this is the specific work item the user
+    // identified
+    //
+    if (sys->params()->work_item_id == -1 || 
+        sys->params()->work_item_id == workid) {
+
+        uint64_t systemWorkEndCount = sys->incWorkItemsEnd();
+        int cpuId = tc->getCpuPtr()->cpuId();
+
+        if (sys->params()->work_cpus_ckpt_count != 0 &&
+            sys->markWorkItem(cpuId) >= sys->params()->work_cpus_ckpt_count) {
+            //
+            // If active cpus equals checkpoint count, create checkpoint
+            //
+            Event *event = new SimLoopExitEvent("checkpoint", 0);
+            mainEventQueue.schedule(event, curTick());
+        }
+
+        if (sys->params()->work_end_ckpt_count != 0 &&
+            systemWorkEndCount == sys->params()->work_end_ckpt_count) {
+            //
+            // If total work items completed equals checkpoint count, create
+            // checkpoint
+            //
+            Event *event = new SimLoopExitEvent("checkpoint", 0);
+            mainEventQueue.schedule(event, curTick());
+        }
+
+        if (sys->params()->work_end_exit_count != 0 &&
+            systemWorkEndCount == sys->params()->work_end_exit_count) {
+            //
+            // If total work items completed equals exit count, exit simulation
+            //
+            Event *event = new SimLoopExitEvent("work items exit count reached",
+                                                0);
+
+            mainEventQueue.schedule(event, curTick());
+        }
+    }
+}
+
 } // namespace PseudoInst
index 2f96711551143236d2caf05d4d05d60fc54d5048..296b1556b6122d0d53678a96abaae062edee8036 100644 (file)
@@ -63,5 +63,7 @@ void dumpresetstats(ThreadContext *tc, Tick delay, Tick period);
 void m5checkpoint(ThreadContext *tc, Tick delay, Tick period);
 void debugbreak(ThreadContext *tc);
 void switchcpu(ThreadContext *tc);
+void workbegin(ThreadContext *tc, uint64_t workid, uint64_t threadid);
+void workend(ThreadContext *tc, uint64_t workid, uint64_t threadid);
 
 } // namespace PseudoInst
index 68b02272eb9bc37e889030396ff6b1eec32686f5..e9fd727f1f0ae34c28f6cf74f181830d2376d4c5 100644 (file)
@@ -72,7 +72,10 @@ System::System(Params *p)
       pagePtr(0),
       nextPID(0),
 #endif
-      memoryMode(p->mem_mode), _params(p),
+      memoryMode(p->mem_mode),
+      workItemsBegin(0),
+      workItemsEnd(0),
+      _params(p),
       totalNumInsts(0), 
       instEventQueue("system instruction-based event queue")
 {
@@ -144,6 +147,8 @@ System::System(Params *p)
 
     // increment the number of running systms
     numSystemsRunning++;
+
+    activeCpus.clear();
 }
 
 System::~System()
@@ -218,6 +223,8 @@ System::registerThreadContext(ThreadContext *tc, int assigned)
         remoteGDB[id] = rgdb;
     }
 
+    activeCpus.push_back(false);
+
     return id;
 }
 
index 6c4f3e9ed09b2b2b986688b953983c9b20fc9def..0be16247fd8a911291b060af5f51cd0fbec108bd 100644 (file)
@@ -161,6 +161,48 @@ class System : public SimObject
 
   protected:
     Enums::MemoryMode memoryMode;
+    uint64_t workItemsBegin;
+    uint64_t workItemsEnd;
+    std::vector<bool> activeCpus;
+
+  public:
+    /**
+     * Called by pseudo_inst to track the number of work items started by this
+     * system.
+     */
+    uint64_t 
+    incWorkItemsBegin()
+    {
+        return ++workItemsBegin;
+    }
+
+    /**
+     * Called by pseudo_inst to track the number of work items completed by
+     * this system.
+     */
+    uint64_t 
+    incWorkItemsEnd()
+    {
+        return ++workItemsEnd;
+    }
+
+    /**
+     * Called by pseudo_inst to mark the cpus actively executing work items.
+     * Returns the total number of cpus that have executed work item begin or
+     * ends.
+     */
+    int 
+    markWorkItem(int index)
+    {
+        int count = 0;
+        assert(index < activeCpus.size());
+        activeCpus[index] = true;
+        for (std::vector<bool>::iterator i = activeCpus.begin(); 
+             i < activeCpus.end(); i++) {
+            if (*i) count++;
+        }
+        return count;
+    }
 
 #if FULL_SYSTEM
     /**
index 91e07a1f18039beb6c871ec84d55cfd544b1c3b7..5f746459fe7801f4bd2ce844b268deff17226fe5 100644 (file)
@@ -59,3 +59,5 @@ TWO_BYTE_OP(m5_debugbreak, debugbreak_func)
 TWO_BYTE_OP(m5_switchcpu, switchcpu_func)
 TWO_BYTE_OP(m5_addsymbol, addsymbol_func)
 TWO_BYTE_OP(m5_panic, panic_func)
+TWO_BYTE_OP(m5_work_begin, work_begin_func)
+TWO_BYTE_OP(m5_work_end, work_end_func)
index 7f26fd4d866f5f3bfdc0d47b2d440fefb30025e4..bc2ae06be927d996f84db7dc1e7df19c6f227642 100644 (file)
@@ -57,6 +57,9 @@
 #define reserved4_func          0x58 // Reserved for user
 #define reserved5_func          0x59 // Reserved for user
 
+#define work_begin_func          0x5a
+#define work_end_func            0x5b
+
 // These operations are for critical path annotation
 #define annotate_func     0x55
 #define an_bsm            0x1