From 2c3c7df5fc13ce69358be96d68899ae730c9ac98 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Tue, 15 Oct 2019 16:57:07 -0700 Subject: [PATCH] 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 Maintainer: Giacomo Travaglini Tested-by: kokoro --- src/arch/arm/fastmodel/iris/thread_context.cc | 86 +++++++++++++++++++ src/arch/arm/fastmodel/iris/thread_context.hh | 16 +++- 2 files changed, 100 insertions(+), 2 deletions(-) diff --git a/src/arch/arm/fastmodel/iris/thread_context.cc b/src/arch/arm/fastmodel/iris/thread_context.cc index 43be17142..1380cf3bf 100644 --- a/src/arch/arm/fastmodel/iris/thread_context.cc +++ b/src/arch/arm/fastmodel/iris/thread_context.cc @@ -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( + 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 diff --git a/src/arch/arm/fastmodel/iris/thread_context.hh b/src/arch/arm/fastmodel/iris/thread_context.hh index acb325cdb..bdf12ef8b 100644 --- a/src/arch/arm/fastmodel/iris/thread_context.hh +++ b/src/arch/arm/fastmodel/iris/thread_context.hh @@ -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; } -- 2.30.2