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 <giacomo.travaglini@arm.com> Maintainer: Giacomo Travaglini <giacomo.travaglini@arm.com> Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
@@ -29,6 +29,8 @@
|
||||
|
||||
#include "arch/arm/fastmodel/iris/thread_context.hh"
|
||||
|
||||
#include <utility>
|
||||
|
||||
#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<Self, &Self::breakpointHit>(
|
||||
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)
|
||||
|
||||
@@ -30,6 +30,8 @@
|
||||
#ifndef __ARCH_ARM_FASTMODEL_IRIS_THREAD_CONTEXT_HH__
|
||||
#define __ARCH_ARM_FASTMODEL_IRIS_THREAD_CONTEXT_HH__
|
||||
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
||||
#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<PCEvent *> 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<BpInfo>;
|
||||
using BpInfoMap = std::map<Addr, BpInfoPtr>;
|
||||
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;
|
||||
|
||||
Reference in New Issue
Block a user