fastmodel: Implement inst count events in the IRIS thread contexts.
These use the IRIS stepping API. Change-Id: Ib45744cb0928fece664187e4df6b25b064b19f0e Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/22115 Reviewed-by: Giacomo Travaglini <giacomo.travaglini@arm.com> Maintainer: Giacomo Travaglini <giacomo.travaglini@arm.com> Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
@@ -68,6 +68,35 @@ ThreadContext::extractResourceMap(
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ThreadContext::maintainStepping()
|
||||
{
|
||||
Tick now = 0;
|
||||
|
||||
while (true) {
|
||||
if (comInstEventQueue.empty()) {
|
||||
// Set to 0 to deactivate stepping.
|
||||
call().step_setup(_instId, 0, "instruction");
|
||||
break;
|
||||
}
|
||||
|
||||
Tick next = comInstEventQueue.nextTick();
|
||||
if (!now)
|
||||
now = getCurrentInstCount();
|
||||
|
||||
if (next <= now) {
|
||||
comInstEventQueue.serviceEvents(now);
|
||||
// Start over now that comInstEventQueue has likely changed.
|
||||
continue;
|
||||
}
|
||||
|
||||
// Set to the number of instructions still to step through.
|
||||
Tick remaining = next - now;
|
||||
call().step_setup(_instId, remaining, "instruction");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
iris::IrisErrorCode
|
||||
ThreadContext::instanceRegistryChanged(
|
||||
uint64_t esId, const iris::IrisValueMap &fields, uint64_t time,
|
||||
@@ -107,11 +136,34 @@ ThreadContext::phaseInitLeave(
|
||||
return iris::E_ok;
|
||||
}
|
||||
|
||||
iris::IrisErrorCode
|
||||
ThreadContext::simulationTimeEvent(
|
||||
uint64_t esId, const iris::IrisValueMap &fields, uint64_t time,
|
||||
uint64_t sInstId, bool syncEc, std::string &error_message_out)
|
||||
{
|
||||
if (fields.at("RUNNING").getAsBool()) {
|
||||
// If this is just simulation time starting up, don't do anything.
|
||||
return iris::E_ok;
|
||||
}
|
||||
|
||||
// If simulation time has stopped for any reason, IRIS helpfully clears
|
||||
// all stepping counters and we need to set them back. We might also need
|
||||
// to service events based on the current number of executed instructions.
|
||||
maintainStepping();
|
||||
|
||||
// Restart simulation time to make sure things progress once we give
|
||||
// control back.
|
||||
call().simulationTime_run(iris::IrisInstIdSimulationEngine);
|
||||
|
||||
return iris::E_ok;
|
||||
}
|
||||
|
||||
ThreadContext::ThreadContext(
|
||||
BaseCPU *cpu, int id, System *system,
|
||||
iris::IrisConnectionInterface *iris_if, const std::string &iris_path) :
|
||||
_cpu(cpu), _threadId(id), _system(system), _irisPath(iris_path),
|
||||
_instId(iris::IRIS_UINT64_MAX), _status(Active),
|
||||
comInstEventQueue("instruction-based event queue"),
|
||||
client(iris_if, "client." + iris_path)
|
||||
{
|
||||
iris::InstanceInfo info;
|
||||
@@ -148,6 +200,17 @@ ThreadContext::ThreadContext(
|
||||
call().eventStream_create(
|
||||
iris::IrisInstIdSimulationEngine, initEventStreamId,
|
||||
evSrcInfo.evSrcId, client.getInstId());
|
||||
|
||||
client.registerEventCallback<Self, &Self::simulationTimeEvent>(
|
||||
this, "ec_IRIS_SIMULATION_TIME_EVENT",
|
||||
"Handle simulation time stopping for breakpoints or stepping",
|
||||
"Iris::ThreadContext");
|
||||
call().event_getEventSource(iris::IrisInstIdSimulationEngine, evSrcInfo,
|
||||
"IRIS_SIMULATION_TIME_EVENT");
|
||||
timeEventStreamId = iris::IRIS_UINT64_MAX;
|
||||
call().eventStream_create(
|
||||
iris::IrisInstIdSimulationEngine, timeEventStreamId,
|
||||
evSrcInfo.evSrcId, client.getInstId());
|
||||
}
|
||||
|
||||
ThreadContext::~ThreadContext()
|
||||
@@ -161,6 +224,29 @@ ThreadContext::~ThreadContext()
|
||||
iris::IrisInstIdGlobalInstance, regEventStreamId);
|
||||
regEventStreamId = iris::IRIS_UINT64_MAX;
|
||||
client.unregisterEventCallback("ec_IRIS_INSTANCE_REGISTRY_CHANGED");
|
||||
|
||||
call().eventStream_destroy(
|
||||
iris::IrisInstIdGlobalInstance, timeEventStreamId);
|
||||
timeEventStreamId = iris::IRIS_UINT64_MAX;
|
||||
client.unregisterEventCallback("ec_IRIS_SIMULATION_TIME_EVENT");
|
||||
}
|
||||
|
||||
void
|
||||
ThreadContext::scheduleInstCountEvent(Event *event, Tick count)
|
||||
{
|
||||
Tick now = getCurrentInstCount();
|
||||
comInstEventQueue.schedule(event, count);
|
||||
if (count <= now)
|
||||
call().simulationTime_stop(iris::IrisInstIdSimulationEngine);
|
||||
else
|
||||
maintainStepping();
|
||||
}
|
||||
|
||||
void
|
||||
ThreadContext::descheduleInstCountEvent(Event *event)
|
||||
{
|
||||
comInstEventQueue.deschedule(event);
|
||||
maintainStepping();
|
||||
}
|
||||
|
||||
Tick
|
||||
|
||||
@@ -73,15 +73,27 @@ class ThreadContext : public ::ThreadContext
|
||||
ResourceIds intRegIds;
|
||||
|
||||
|
||||
// A queue to keep track of instruction count based events.
|
||||
EventQueue comInstEventQueue;
|
||||
// A helper function to maintain the IRIS step count. This makes sure the
|
||||
// step count is correct even after IRIS resets it for us, and also handles
|
||||
// events which are supposed to happen at the current instruction count.
|
||||
void maintainStepping();
|
||||
|
||||
|
||||
iris::IrisErrorCode instanceRegistryChanged(
|
||||
uint64_t esId, const iris::IrisValueMap &fields, uint64_t time,
|
||||
uint64_t sInstId, bool syncEc, std::string &error_message_out);
|
||||
iris::IrisErrorCode phaseInitLeave(
|
||||
uint64_t esId, const iris::IrisValueMap &fields, uint64_t time,
|
||||
uint64_t sInstId, bool syncEc, std::string &error_message_out);
|
||||
iris::IrisErrorCode simulationTimeEvent(
|
||||
uint64_t esId, const iris::IrisValueMap &fields, uint64_t time,
|
||||
uint64_t sInstId, bool syncEc, std::string &error_message_out);
|
||||
|
||||
iris::EventStreamId regEventStreamId;
|
||||
iris::EventStreamId initEventStreamId;
|
||||
iris::EventStreamId timeEventStreamId;
|
||||
|
||||
mutable iris::IrisInstance client;
|
||||
iris::IrisCppAdapter &call() const { return client.irisCall(); }
|
||||
@@ -96,8 +108,8 @@ class ThreadContext : public ::ThreadContext
|
||||
bool schedule(PCEvent *e) override { return false; }
|
||||
bool remove(PCEvent *e) override { return false; }
|
||||
|
||||
void scheduleInstCountEvent(Event *event, Tick count) override {}
|
||||
void descheduleInstCountEvent(Event *event) override {}
|
||||
void scheduleInstCountEvent(Event *event, Tick count) override;
|
||||
void descheduleInstCountEvent(Event *event) override;
|
||||
Tick getCurrentInstCount() override;
|
||||
|
||||
::BaseCPU *getCpuPtr() override { return _cpu; }
|
||||
|
||||
Reference in New Issue
Block a user