summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/arch/x86/isa/decoder/two_byte_opcodes.isa6
-rw-r--r--src/cpu/base.cc10
-rw-r--r--src/cpu/base.hh4
-rw-r--r--src/sim/SConscript1
-rw-r--r--src/sim/System.py14
-rw-r--r--src/sim/pseudo_inst.cc117
-rw-r--r--src/sim/pseudo_inst.hh2
-rw-r--r--src/sim/system.cc9
-rw-r--r--src/sim/system.hh42
9 files changed, 204 insertions, 1 deletions
diff --git a/src/arch/x86/isa/decoder/two_byte_opcodes.isa b/src/arch/x86/isa/decoder/two_byte_opcodes.isa
index 1dc32122e..11cd6eeb1 100644
--- a/src/arch/x86/isa/decoder/two_byte_opcodes.isa
+++ b/src/arch/x86/isa/decoder/two_byte_opcodes.isa
@@ -216,6 +216,12 @@
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();
}
}
diff --git a/src/cpu/base.cc b/src/cpu/base.cc
index b7decaec1..17ae65793 100644
--- a/src/cpu/base.cc
+++ b/src/cpu/base.cc
@@ -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) {
diff --git a/src/cpu/base.hh b/src/cpu/base.hh
index bea15aa08..a56f3db24 100644
--- a/src/cpu/base.hh
+++ b/src/cpu/base.hh
@@ -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__
diff --git a/src/sim/SConscript b/src/sim/SConscript
index f959870cd..5c22e328e 100644
--- a/src/sim/SConscript
+++ b/src/sim/SConscript
@@ -78,3 +78,4 @@ TraceFlag('TLB')
TraceFlag('Thread')
TraceFlag('Timer')
TraceFlag('VtoPhys')
+TraceFlag('WorkItems')
diff --git a/src/sim/System.py b/src/sim/System.py
index e2d5b279b..fd707c353 100644
--- a/src/sim/System.py
+++ b/src/sim/System.py
@@ -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,
diff --git a/src/sim/pseudo_inst.cc b/src/sim/pseudo_inst.cc
index 9ee473014..f3b10f6d2 100644
--- a/src/sim/pseudo_inst.cc
+++ b/src/sim/pseudo_inst.cc
@@ -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
diff --git a/src/sim/pseudo_inst.hh b/src/sim/pseudo_inst.hh
index 2f9671155..296b1556b 100644
--- a/src/sim/pseudo_inst.hh
+++ b/src/sim/pseudo_inst.hh
@@ -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
diff --git a/src/sim/system.cc b/src/sim/system.cc
index 68b02272e..e9fd727f1 100644
--- a/src/sim/system.cc
+++ b/src/sim/system.cc
@@ -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;
}
diff --git a/src/sim/system.hh b/src/sim/system.hh
index 6c4f3e9ed..0be16247f 100644
--- a/src/sim/system.hh
+++ b/src/sim/system.hh
@@ -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
/**