cpu: Delegate comInstEventQueue methods to the ThreadContexts.
These then just use the comInstEventQueue array from the CPU, but soon they will actually be self contained and allow the thread context to use whatever mechanism it wants. Also, now that the thread contexts need to exist before instruction count based events can be scheduled, setting up max instruction based events needs to happen in init after the CPU subclasses have had a chance to set up the threadContexts vector. Change-Id: I34bb401633d277a60be74e30d5a478a149b972ea Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/22108 Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com> Maintainer: Andreas Sandberg <andreas.sandberg@arm.com> Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
@@ -162,43 +162,6 @@ BaseCPU::BaseCPU(Params *p, bool is_checker)
|
||||
comInstEventQueue[tid] =
|
||||
new EventQueue("instruction-based event queue");
|
||||
|
||||
//
|
||||
// set up instruction-count-based termination events, if any
|
||||
//
|
||||
if (p->max_insts_any_thread != 0) {
|
||||
const char *cause = "a thread reached the max instruction count";
|
||||
for (ThreadID tid = 0; tid < numThreads; ++tid)
|
||||
scheduleInstStop(tid, p->max_insts_any_thread, cause);
|
||||
}
|
||||
|
||||
// Set up instruction-count-based termination events for SimPoints
|
||||
// Typically, there are more than one action points.
|
||||
// Simulation.py is responsible to take the necessary actions upon
|
||||
// exitting the simulation loop.
|
||||
if (!p->simpoint_start_insts.empty()) {
|
||||
const char *cause = "simpoint starting point found";
|
||||
for (size_t i = 0; i < p->simpoint_start_insts.size(); ++i)
|
||||
scheduleInstStop(0, p->simpoint_start_insts[i], cause);
|
||||
}
|
||||
|
||||
if (p->max_insts_all_threads != 0) {
|
||||
const char *cause = "all threads reached the max instruction count";
|
||||
|
||||
// allocate & initialize shared downcounter: each event will
|
||||
// decrement this when triggered; simulation will terminate
|
||||
// when counter reaches 0
|
||||
int *counter = new int;
|
||||
*counter = numThreads;
|
||||
for (ThreadID tid = 0; tid < numThreads; ++tid) {
|
||||
Event *event = new CountedExitEvent(cause, *counter);
|
||||
scheduleInstCountEvent(tid, event, p->max_insts_all_threads);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// set up instruction-count-based termination events, if any
|
||||
//
|
||||
|
||||
functionTracingEnabled = false;
|
||||
if (p->function_trace) {
|
||||
const string fname = csprintf("ftrace.%s", name());
|
||||
@@ -323,6 +286,39 @@ BaseCPU::mwaitAtomic(ThreadID tid, ThreadContext *tc, BaseTLB *dtb)
|
||||
void
|
||||
BaseCPU::init()
|
||||
{
|
||||
// Set up instruction-count-based termination events, if any. This needs
|
||||
// to happen after threadContexts has been constructed.
|
||||
if (params()->max_insts_any_thread != 0) {
|
||||
const char *cause = "a thread reached the max instruction count";
|
||||
for (ThreadID tid = 0; tid < numThreads; ++tid)
|
||||
scheduleInstStop(tid, params()->max_insts_any_thread, cause);
|
||||
}
|
||||
|
||||
// Set up instruction-count-based termination events for SimPoints
|
||||
// Typically, there are more than one action points.
|
||||
// Simulation.py is responsible to take the necessary actions upon
|
||||
// exitting the simulation loop.
|
||||
if (!params()->simpoint_start_insts.empty()) {
|
||||
const char *cause = "simpoint starting point found";
|
||||
for (size_t i = 0; i < params()->simpoint_start_insts.size(); ++i)
|
||||
scheduleInstStop(0, params()->simpoint_start_insts[i], cause);
|
||||
}
|
||||
|
||||
if (params()->max_insts_all_threads != 0) {
|
||||
const char *cause = "all threads reached the max instruction count";
|
||||
|
||||
// allocate & initialize shared downcounter: each event will
|
||||
// decrement this when triggered; simulation will terminate
|
||||
// when counter reaches 0
|
||||
int *counter = new int;
|
||||
*counter = numThreads;
|
||||
for (ThreadID tid = 0; tid < numThreads; ++tid) {
|
||||
Event *event = new CountedExitEvent(cause, *counter);
|
||||
scheduleInstCountEvent(
|
||||
tid, event, params()->max_insts_all_threads);
|
||||
}
|
||||
}
|
||||
|
||||
if (!params()->switched_out) {
|
||||
registerThreadContexts();
|
||||
|
||||
@@ -735,7 +731,7 @@ BaseCPU::scheduleInstStop(ThreadID tid, Counter insts, const char *cause)
|
||||
Tick
|
||||
BaseCPU::getCurrentInstCount(ThreadID tid)
|
||||
{
|
||||
return comInstEventQueue[tid]->getCurTick();
|
||||
return threadContexts[tid]->getCurrentInstCount();
|
||||
}
|
||||
|
||||
AddressMonitor::AddressMonitor() {
|
||||
|
||||
@@ -468,26 +468,25 @@ class BaseCPU : public ClockedObject
|
||||
Tick
|
||||
nextInstEventCount(ThreadID tid)
|
||||
{
|
||||
return comInstEventQueue[tid]->empty() ?
|
||||
MaxTick : comInstEventQueue[tid]->nextTick();
|
||||
return threadContexts[tid]->nextInstEventCount();
|
||||
}
|
||||
|
||||
void
|
||||
serviceInstCountEvents(ThreadID tid, Tick count)
|
||||
{
|
||||
comInstEventQueue[tid]->serviceEvents(count);
|
||||
threadContexts[tid]->serviceInstCountEvents(count);
|
||||
}
|
||||
|
||||
void
|
||||
scheduleInstCountEvent(ThreadID tid, Event *event, Tick count)
|
||||
{
|
||||
comInstEventQueue[tid]->schedule(event, count);
|
||||
threadContexts[tid]->scheduleInstCountEvent(event, count);
|
||||
}
|
||||
|
||||
void
|
||||
descheduleInstCountEvent(ThreadID tid, Event *event)
|
||||
{
|
||||
comInstEventQueue[tid]->deschedule(event);
|
||||
threadContexts[tid]->descheduleInstCountEvent(event);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
@@ -55,6 +55,41 @@
|
||||
#include "params/BaseCPU.hh"
|
||||
#include "sim/full_system.hh"
|
||||
|
||||
Tick
|
||||
ThreadContext::nextInstEventCount()
|
||||
{
|
||||
auto *queue = getCpuPtr()->comInstEventQueue[threadId()];
|
||||
return queue->empty() ? MaxTick : queue->nextTick();
|
||||
}
|
||||
|
||||
void
|
||||
ThreadContext::serviceInstCountEvents(Tick count)
|
||||
{
|
||||
auto *queue = getCpuPtr()->comInstEventQueue[threadId()];
|
||||
queue->serviceEvents(count);
|
||||
}
|
||||
|
||||
void
|
||||
ThreadContext::scheduleInstCountEvent(Event *event, Tick count)
|
||||
{
|
||||
auto *queue = getCpuPtr()->comInstEventQueue[threadId()];
|
||||
return queue->schedule(event, count);
|
||||
}
|
||||
|
||||
void
|
||||
ThreadContext::descheduleInstCountEvent(Event *event)
|
||||
{
|
||||
auto *queue = getCpuPtr()->comInstEventQueue[threadId()];
|
||||
queue->deschedule(event);
|
||||
}
|
||||
|
||||
Tick
|
||||
ThreadContext::getCurrentInstCount()
|
||||
{
|
||||
auto *queue = getCpuPtr()->comInstEventQueue[threadId()];
|
||||
return queue->getCurTick();
|
||||
}
|
||||
|
||||
void
|
||||
ThreadContext::compare(ThreadContext *one, ThreadContext *two)
|
||||
{
|
||||
|
||||
@@ -192,6 +192,12 @@ class ThreadContext : public PCEventScope
|
||||
|
||||
virtual EndQuiesceEvent *getQuiesceEvent() = 0;
|
||||
|
||||
virtual Tick nextInstEventCount();
|
||||
virtual void serviceInstCountEvents(Tick count);
|
||||
virtual void scheduleInstCountEvent(Event *event, Tick count);
|
||||
virtual void descheduleInstCountEvent(Event *event);
|
||||
virtual Tick getCurrentInstCount();
|
||||
|
||||
// Not necessarily the best location for these...
|
||||
// Having an extra function just to read these is obnoxious
|
||||
virtual Tick readLastActivate() = 0;
|
||||
|
||||
Reference in New Issue
Block a user