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:
Gabe Black
2019-10-22 21:42:51 -07:00
parent 62d75e7105
commit 6e91bb9dcb
2 changed files with 137 additions and 2 deletions

View File

@@ -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)

View File

@@ -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;