From 6e91bb9dcb276780b2474d73ca4f0a0ece17aca7 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Tue, 22 Oct 2019 21:42:51 -0700 Subject: fastmodel: Implement PC based events. These use the IRIS breakpoint API to stop the models at the appropriate points. There seems to be a slightly wonky interaction between breakpoints and stepping, where if you stop at a breakpoint and then step, you might end up moving forward more than the number of requested instructions. Change-Id: I31f13a120cfc1ad2ec3669ee8befd6d21b328bb2 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/22122 Reviewed-by: Giacomo Travaglini Maintainer: Giacomo Travaglini Tested-by: kokoro --- src/arch/arm/fastmodel/iris/thread_context.cc | 102 ++++++++++++++++++++++++++ src/arch/arm/fastmodel/iris/thread_context.hh | 37 +++++++++- 2 files changed, 137 insertions(+), 2 deletions(-) diff --git a/src/arch/arm/fastmodel/iris/thread_context.cc b/src/arch/arm/fastmodel/iris/thread_context.cc index 00c41ba9c..872136615 100644 --- a/src/arch/arm/fastmodel/iris/thread_context.cc +++ b/src/arch/arm/fastmodel/iris/thread_context.cc @@ -29,6 +29,8 @@ #include "arch/arm/fastmodel/iris/thread_context.hh" +#include + #include "iris/detail/IrisCppAdapter.h" #include "iris/detail/IrisObjects.h" #include "mem/fs_translating_port_proxy.hh" @@ -48,6 +50,19 @@ ThreadContext::initFromIrisInstance(const ResourceMap &resources) call().memory_getMemorySpaces(_instId, memorySpaces); call().memory_getUsefulAddressTranslations(_instId, translations); + + typedef ThreadContext Self; + iris::EventSourceInfo evSrcInfo; + + client.registerEventCallback( + this, "ec_IRIS_BREAKPOINT_HIT", + "Handle hitting a breakpoint", "Iris::ThreadContext"); + call().event_getEventSource(_instId, evSrcInfo, "IRIS_BREAKPOINT_HIT"); + call().eventStream_create(_instId, breakpointEventStreamId, + evSrcInfo.evSrcId, client.getInstId()); + + for (auto it = bps.begin(); it != bps.end(); it++) + installBp(it); } iris::ResourceId @@ -102,6 +117,47 @@ ThreadContext::maintainStepping() } } +ThreadContext::BpInfoIt +ThreadContext::getOrAllocBp(Addr pc) +{ + auto pc_it = bps.find(pc); + + if (pc_it != bps.end()) + return pc_it; + + auto res = bps.emplace(std::make_pair(pc, new BpInfo(pc))); + panic_if(!res.second, "Inserting breakpoint failed."); + return res.first; +} + +void +ThreadContext::installBp(BpInfoIt it) +{ + BpId id; + // Hard code address space 5 for now. + call().breakpoint_set_code(_instId, id, it->second->pc, 5, 0, true); + it->second->id = id; +} + +void +ThreadContext::uninstallBp(BpInfoIt it) +{ + call().breakpoint_delete(_instId, it->second->id); + it->second->clearId(); +} + +void +ThreadContext::delBp(BpInfoIt it) +{ + panic_if(!it->second->empty(), + "BP info still had events associated with it."); + + if (it->second->validId()) + uninstallBp(it); + + bps.erase(it); +} + iris::IrisErrorCode ThreadContext::instanceRegistryChanged( uint64_t esId, const iris::IrisValueMap &fields, uint64_t time, @@ -163,6 +219,26 @@ ThreadContext::simulationTimeEvent( return iris::E_ok; } +iris::IrisErrorCode +ThreadContext::breakpointHit( + uint64_t esId, const iris::IrisValueMap &fields, uint64_t time, + uint64_t sInstId, bool syncEc, std::string &error_message_out) +{ + Addr pc = fields.at("PC").getU64(); + + auto it = getOrAllocBp(pc); + + auto e_it = it->second->events.begin(); + while (e_it != it->second->events.end()) { + PCEvent *e = *e_it; + // Advance e_it here since e might remove itself from the list. + e_it++; + e->process(this); + } + + return iris::E_ok; +} + ThreadContext::ThreadContext( BaseCPU *cpu, int id, System *system, ::BaseTLB *dtb, ::BaseTLB *itb, iris::IrisConnectionInterface *iris_if, const std::string &iris_path) : @@ -216,6 +292,8 @@ ThreadContext::ThreadContext( call().eventStream_create( iris::IrisInstIdSimulationEngine, timeEventStreamId, evSrcInfo.evSrcId, client.getInstId()); + + breakpointEventStreamId = iris::IRIS_UINT64_MAX; } ThreadContext::~ThreadContext() @@ -236,6 +314,30 @@ ThreadContext::~ThreadContext() client.unregisterEventCallback("ec_IRIS_SIMULATION_TIME_EVENT"); } +bool +ThreadContext::schedule(PCEvent *e) +{ + auto it = getOrAllocBp(e->pc()); + it->second->events.push_back(e); + + if (_instId != iris::IRIS_UINT64_MAX && !it->second->validId()) + installBp(it); + + return true; +} + +bool +ThreadContext::remove(PCEvent *e) +{ + auto it = getOrAllocBp(e->pc()); + it->second->events.remove(e); + + if (it->second->empty()) + delBp(it); + + return true; +} + bool ThreadContext::translateAddress(Addr &paddr, iris::MemorySpaceId p_space, Addr vaddr, iris::MemorySpaceId v_space) diff --git a/src/arch/arm/fastmodel/iris/thread_context.hh b/src/arch/arm/fastmodel/iris/thread_context.hh index 8d2070a02..4175e9363 100644 --- a/src/arch/arm/fastmodel/iris/thread_context.hh +++ b/src/arch/arm/fastmodel/iris/thread_context.hh @@ -30,6 +30,8 @@ #ifndef __ARCH_ARM_FASTMODEL_IRIS_THREAD_CONTEXT_HH__ #define __ARCH_ARM_FASTMODEL_IRIS_THREAD_CONTEXT_HH__ +#include +#include #include #include "cpu/base.hh" @@ -91,6 +93,33 @@ class ThreadContext : public ::ThreadContext void maintainStepping(); + using BpId = uint64_t; + struct BpInfo + { + Addr pc; + BpId id; + std::list events; + + BpInfo(Addr _pc) : pc(_pc), id(iris::IRIS_UINT64_MAX) {} + + bool empty() const { return events.empty(); } + bool validId() const { return id != iris::IRIS_UINT64_MAX; } + void clearId() { id = iris::IRIS_UINT64_MAX; } + }; + + using BpInfoPtr = std::unique_ptr; + using BpInfoMap = std::map; + using BpInfoIt = BpInfoMap::iterator; + + BpInfoMap bps; + + BpInfoIt getOrAllocBp(Addr pc); + + void installBp(BpInfoIt it); + void uninstallBp(BpInfoIt it); + void delBp(BpInfoIt it); + + iris::IrisErrorCode instanceRegistryChanged( uint64_t esId, const iris::IrisValueMap &fields, uint64_t time, uint64_t sInstId, bool syncEc, std::string &error_message_out); @@ -100,10 +129,14 @@ class ThreadContext : public ::ThreadContext iris::IrisErrorCode simulationTimeEvent( uint64_t esId, const iris::IrisValueMap &fields, uint64_t time, uint64_t sInstId, bool syncEc, std::string &error_message_out); + iris::IrisErrorCode breakpointHit( + 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; + iris::EventStreamId breakpointEventStreamId; mutable iris::IrisInstance client; iris::IrisCppAdapter &call() const { return client.irisCall(); } @@ -121,8 +154,8 @@ class ThreadContext : public ::ThreadContext virtual bool translateAddress(Addr &paddr, Addr vaddr) = 0; - bool schedule(PCEvent *e) override { return false; } - bool remove(PCEvent *e) override { return false; } + bool schedule(PCEvent *e) override; + bool remove(PCEvent *e) override; void scheduleInstCountEvent(Event *event, Tick count) override; void descheduleInstCountEvent(Event *event) override; -- cgit v1.2.3