Added single stepping for gem5, which is necessary to periodically check for events like interrupts.
git-svn-id: https://www4.informatik.uni-erlangen.de/i4svn/danceos/trunk/devel/fail@1734 8c4709b5-6ec9-48aa-a5cd-a96041d1645a
This commit is contained in:
@ -18,7 +18,7 @@ elseif(BUILD_GEM5)
|
|||||||
SimulatorController.cc
|
SimulatorController.cc
|
||||||
perf/BreakpointBuffer.cc
|
perf/BreakpointBuffer.cc
|
||||||
gem5/Gem5Controller.cc
|
gem5/Gem5Controller.cc
|
||||||
gem5/Gem5PCEvent.cc
|
gem5/Gem5PCEvents.cc
|
||||||
)
|
)
|
||||||
elseif(BUILD_OVP)
|
elseif(BUILD_OVP)
|
||||||
set(SRCS
|
set(SRCS
|
||||||
|
|||||||
@ -1,16 +1,116 @@
|
|||||||
#include "FailGem5Device.hh"
|
#include "FailGem5Device.hpp"
|
||||||
|
|
||||||
#include "debug/Fail.hh"
|
#include "debug/Fail.hh"
|
||||||
|
#include "sim/system.hh"
|
||||||
|
#include "arch/arm/decoder.hh"
|
||||||
|
#include "cpu/simple/base.hh"
|
||||||
|
|
||||||
#include "../SALInst.hpp"
|
#include "../SALInst.hpp"
|
||||||
|
#include "Gem5PCEvents.hpp"
|
||||||
|
|
||||||
|
#include <bitset>
|
||||||
|
|
||||||
FailGem5Device::FailGem5Device(Params *p)
|
FailGem5Device::FailGem5Device(Params *p)
|
||||||
: BasicPioDevice(p)
|
: BasicPioDevice(p)
|
||||||
{
|
{
|
||||||
pioSize = 0x60;
|
pioSize = 0x60;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FailGem5Device::startup()
|
||||||
|
{
|
||||||
|
// TODO: Find a better way/position to start single stepping.
|
||||||
|
// It's not possible to fetch the instruction at Adress 0x0
|
||||||
|
m_BreakpointNotTaken = new Gem5InstructionEvent(this, &sys->pcEventQueue, 0x80000000);
|
||||||
fail::simulator.startup();
|
fail::simulator.startup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FailGem5Device::activateSingleStepMode()
|
||||||
|
{
|
||||||
|
setNextBreakpoints(sys->getThreadContext(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
void FailGem5Device::deactivateSingleStepMode()
|
||||||
|
{
|
||||||
|
clearBreakpoints();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FailGem5Device::setNextBreakpoints(ThreadContext *tc)
|
||||||
|
{
|
||||||
|
clearBreakpoints();
|
||||||
|
|
||||||
|
// Get the instruction at the current program counter
|
||||||
|
MachInst inst;
|
||||||
|
PCState pc = tc->pcState();
|
||||||
|
tc->getVirtProxy().readBlob(pc.pc(), (uint8_t*)&inst, sizeof(MachInst));
|
||||||
|
|
||||||
|
// Decode the instruction
|
||||||
|
ArmISA::Decoder* decoder = tc->getDecoderPtr();
|
||||||
|
BaseSimpleCPU* cpu = dynamic_cast<BaseSimpleCPU*>(tc->getCpuPtr());
|
||||||
|
Addr fetchPC = (pc.pc() & cpu->PCMask) + cpu->fetchOffset;
|
||||||
|
decoder->moreBytes(pc, fetchPC, inst);
|
||||||
|
StaticInstPtr si = decoder->decode(pc);
|
||||||
|
|
||||||
|
// Set breakpoints
|
||||||
|
// First breakpoint is always the next pc
|
||||||
|
// FIXME: Doesn't work properly in Thumb or Thumb2 mode
|
||||||
|
m_BreakpointNotTaken = new Gem5InstructionEvent(this, &sys->pcEventQueue, pc.npc());
|
||||||
|
|
||||||
|
// Second breakpoint will only be set if there is a possible change in control flow
|
||||||
|
DPRINTF(Fail, "Instruction Name: %s\n", si->getName());
|
||||||
|
|
||||||
|
if(si->getName().compare("bx") == 0)
|
||||||
|
{
|
||||||
|
DPRINTF(Fail, "BX instruction\n");
|
||||||
|
Addr target = tc->readIntReg(si->machInst.rm);
|
||||||
|
m_BreakpointTaken = new Gem5InstructionEvent(this, &sys->pcEventQueue, target);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for a pop instruction with the pc as target
|
||||||
|
if(si->getName().compare("ldmstm") == 0)
|
||||||
|
{
|
||||||
|
std::bitset<16> regs(si->machInst.regList);
|
||||||
|
if(regs.test(15)) // Bit 15 = pc
|
||||||
|
{
|
||||||
|
DPRINTF(Fail, "LDMSTM with pc as target\n");
|
||||||
|
Addr mem = tc->readIntReg(si->machInst.rn) + 4*(regs.count()-1);
|
||||||
|
|
||||||
|
Addr target;
|
||||||
|
tc->getVirtProxy().readBlob(mem, (uint8_t*)&target, sizeof(Addr));
|
||||||
|
DPRINTF(Fail, "Value loaded into pc: %x\n", target);
|
||||||
|
|
||||||
|
m_BreakpointTaken = new Gem5InstructionEvent(this, &sys->pcEventQueue, target);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PCState bpc;
|
||||||
|
if(si->hasBranchTarget(pc, tc, bpc))
|
||||||
|
{
|
||||||
|
DPRINTF(Fail, "Immediate branch\n");
|
||||||
|
if (bpc.pc() != pc.npc())
|
||||||
|
{
|
||||||
|
m_BreakpointTaken = new Gem5InstructionEvent(this, &sys->pcEventQueue, bpc.pc());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FailGem5Device::clearBreakpoints()
|
||||||
|
{
|
||||||
|
if(m_BreakpointTaken)
|
||||||
|
{
|
||||||
|
delete m_BreakpointTaken;
|
||||||
|
m_BreakpointTaken = 0;
|
||||||
|
}
|
||||||
|
if(m_BreakpointNotTaken)
|
||||||
|
{
|
||||||
|
delete m_BreakpointNotTaken;
|
||||||
|
m_BreakpointNotTaken = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Tick FailGem5Device::read(PacketPtr pkt)
|
Tick FailGem5Device::read(PacketPtr pkt)
|
||||||
{
|
{
|
||||||
return pioDelay;
|
return pioDelay;
|
||||||
|
|||||||
@ -1,19 +0,0 @@
|
|||||||
#ifndef __FAILGEM5_DEVICE_HH__
|
|
||||||
#define __FAILGEM5_DEVICE_HH__
|
|
||||||
|
|
||||||
#include "dev/io_device.hh"
|
|
||||||
#include "params/FailGem5Device.hh"
|
|
||||||
|
|
||||||
class FailGem5Device : public BasicPioDevice
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
typedef FailGem5DeviceParams Params;
|
|
||||||
|
|
||||||
FailGem5Device(Params *p);
|
|
||||||
|
|
||||||
virtual Tick read(PacketPtr pkt);
|
|
||||||
|
|
||||||
virtual Tick write(PacketPtr pkt);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // __FAILGEM5_DEVICE_HH__
|
|
||||||
32
src/core/sal/gem5/FailGem5Device.hpp
Normal file
32
src/core/sal/gem5/FailGem5Device.hpp
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#ifndef __FAILGEM5_DEVICE_HH__
|
||||||
|
#define __FAILGEM5_DEVICE_HH__
|
||||||
|
|
||||||
|
#include "dev/io_device.hh"
|
||||||
|
#include "params/FailGem5Device.hh"
|
||||||
|
#include "cpu/thread_context.hh"
|
||||||
|
|
||||||
|
class Gem5InstructionEvent;
|
||||||
|
|
||||||
|
class FailGem5Device : public BasicPioDevice
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef FailGem5DeviceParams Params;
|
||||||
|
FailGem5Device(Params *p);
|
||||||
|
|
||||||
|
void setNextBreakpoints(ThreadContext *tc);
|
||||||
|
|
||||||
|
virtual void startup();
|
||||||
|
virtual Tick read(PacketPtr pkt);
|
||||||
|
virtual Tick write(PacketPtr pkt);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Gem5InstructionEvent* m_BreakpointTaken;
|
||||||
|
Gem5InstructionEvent* m_BreakpointNotTaken;
|
||||||
|
|
||||||
|
void activateSingleStepMode();
|
||||||
|
void deactivateSingleStepMode();
|
||||||
|
void clearBreakpoints();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // __FAILGEM5_DEVICE_HH__
|
||||||
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
#if defined(BUILD_GEM5) && defined(CONFIG_EVENT_BREAKPOINTS)
|
#if defined(BUILD_GEM5) && defined(CONFIG_EVENT_BREAKPOINTS)
|
||||||
|
|
||||||
#include "Gem5PCEvent.hh"
|
#include "Gem5PCEvents.hpp"
|
||||||
#include "sim/system.hh"
|
#include "sim/system.hh"
|
||||||
|
|
||||||
aspect Gem5Listener
|
aspect Gem5Listener
|
||||||
@ -14,12 +14,12 @@ aspect Gem5Listener
|
|||||||
advice "fail::BPSingleListener" : slice class
|
advice "fail::BPSingleListener" : slice class
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
Gem5PCEvent* m_Breakpoint;
|
Gem5BreakpointEvent* m_Breakpoint;
|
||||||
public:
|
public:
|
||||||
virtual bool onAddition()
|
virtual bool onAddition()
|
||||||
{
|
{
|
||||||
System* sys = *System::systemList.begin();
|
System* sys = *System::systemList.begin();
|
||||||
m_Breakpoint = new Gem5PCEvent(&sys->pcEventQueue, this->m_WatchInstrPtr);
|
m_Breakpoint = new Gem5BreakpointEvent(&sys->pcEventQueue, this->m_WatchInstrPtr);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +0,0 @@
|
|||||||
#include "Gem5PCEvent.hh"
|
|
||||||
#include "../SALInst.hpp"
|
|
||||||
|
|
||||||
void Gem5PCEvent::process(ThreadContext *tc)
|
|
||||||
{
|
|
||||||
fail::simulator.onBreakpoint(this->evpc, fail::ANY_ADDR);
|
|
||||||
}
|
|
||||||
@ -1,14 +0,0 @@
|
|||||||
#ifndef __GEM5_PCEVENT_HPP__
|
|
||||||
#define __GEM5_PCEVENT_HPP__
|
|
||||||
|
|
||||||
#include "cpu/pc_event.hh"
|
|
||||||
|
|
||||||
class Gem5PCEvent : public PCEvent
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Gem5PCEvent(PCEventQueue* queue, Addr ip)
|
|
||||||
: PCEvent(queue, "Fail Breakpoint", ip) {}
|
|
||||||
virtual void process(ThreadContext *tc);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // __GEM5_PCEVENT_HPP__
|
|
||||||
14
src/core/sal/gem5/Gem5PCEvents.cc
Normal file
14
src/core/sal/gem5/Gem5PCEvents.cc
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#include "Gem5PCEvents.hpp"
|
||||||
|
#include "../SALInst.hpp"
|
||||||
|
|
||||||
|
#include "cpu/thread_context.hh"
|
||||||
|
|
||||||
|
void Gem5BreakpointEvent::process(ThreadContext *tc)
|
||||||
|
{
|
||||||
|
fail::simulator.onBreakpoint(this->evpc, fail::ANY_ADDR);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Gem5InstructionEvent::process(ThreadContext *tc)
|
||||||
|
{
|
||||||
|
m_FailDevice->setNextBreakpoints(tc);
|
||||||
|
}
|
||||||
27
src/core/sal/gem5/Gem5PCEvents.hpp
Normal file
27
src/core/sal/gem5/Gem5PCEvents.hpp
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#ifndef __GEM5_PCEVENTS_HPP__
|
||||||
|
#define __GEM5_PCEVENTS_HPP__
|
||||||
|
|
||||||
|
#include "cpu/pc_event.hh"
|
||||||
|
|
||||||
|
#include "FailGem5Device.hpp"
|
||||||
|
|
||||||
|
class Gem5BreakpointEvent : public PCEvent
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Gem5BreakpointEvent(PCEventQueue* queue, Addr ip)
|
||||||
|
: PCEvent(queue, "Fail breakpoint event", ip) {}
|
||||||
|
virtual void process(ThreadContext *tc);
|
||||||
|
};
|
||||||
|
|
||||||
|
class Gem5InstructionEvent : public PCEvent
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Gem5InstructionEvent(FailGem5Device* device, PCEventQueue* queue, Addr ip)
|
||||||
|
: PCEvent(queue, "Fail instruction event", ip), m_FailDevice(device) {}
|
||||||
|
virtual void process(ThreadContext *tc);
|
||||||
|
|
||||||
|
private:
|
||||||
|
FailGem5Device* m_FailDevice;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // __GEM5_PCEVENTS_HPP__
|
||||||
Reference in New Issue
Block a user