Restructured the gem5 backend:
- FailGem5Device is gone. - There are now changes directly made to the gem5 source. - Gem5Connector is a helper class that is compiled inside the gem5 context to workaround problems with gem5 header in fail. Things that are working: - BPSingleListener - MemAccessListener - Save and restore simulator state git-svn-id: https://www4.informatik.uni-erlangen.de/i4svn/danceos/trunk/devel/fail@1820 8c4709b5-6ec9-48aa-a5cd-a96041d1645a
This commit is contained in:
@ -18,7 +18,6 @@ elseif(BUILD_GEM5)
|
||||
SimulatorController.cc
|
||||
perf/BreakpointBuffer.cc
|
||||
gem5/Gem5Controller.cc
|
||||
gem5/Gem5PCEvents.cc
|
||||
)
|
||||
elseif(BUILD_OVP)
|
||||
set(SRCS
|
||||
|
||||
@ -1,127 +0,0 @@
|
||||
#include "FailGem5Device.hpp"
|
||||
|
||||
#include "debug/Fail.hh"
|
||||
#include "sim/system.hh"
|
||||
#include "arch/arm/decoder.hh"
|
||||
#include "cpu/simple/base.hh"
|
||||
|
||||
#include "../SALInst.hpp"
|
||||
#include "Gem5PCEvents.hpp"
|
||||
|
||||
#include <bitset>
|
||||
|
||||
FailGem5Device::FailGem5Device(Params *p)
|
||||
: BasicPioDevice(p)
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
return pioDelay;
|
||||
}
|
||||
|
||||
Tick FailGem5Device::write(PacketPtr pkt)
|
||||
{
|
||||
return pioDelay;
|
||||
}
|
||||
|
||||
FailGem5Device* FailGem5DeviceParams::create()
|
||||
{
|
||||
return new FailGem5Device(this);
|
||||
}
|
||||
@ -1,32 +0,0 @@
|
||||
#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__
|
||||
@ -1,5 +0,0 @@
|
||||
from Device import BasicPioDevice
|
||||
|
||||
class FailGem5Device(BasicPioDevice):
|
||||
type = 'FailGem5Device'
|
||||
|
||||
@ -7,7 +7,6 @@
|
||||
#define __GEM5_CONFIG_HPP__
|
||||
|
||||
#include "base/types.hh"
|
||||
//#include "arch/arm/registers.hh"
|
||||
|
||||
namespace fail {
|
||||
|
||||
|
||||
25
src/core/sal/gem5/Gem5Connector.cc
Normal file
25
src/core/sal/gem5/Gem5Connector.cc
Normal file
@ -0,0 +1,25 @@
|
||||
#include "Gem5Connector.hpp"
|
||||
|
||||
#include "base/trace.hh"
|
||||
#include "debug/FailState.hh"
|
||||
#include "sim/root.hh"
|
||||
|
||||
Gem5Connector connector;
|
||||
|
||||
void Gem5Connector::save(const std::string &path)
|
||||
{
|
||||
DPRINTF(FailState, "Saving state to %s.\n", path);
|
||||
|
||||
Root* root = Root::root();
|
||||
root->Serializable::serializeAll(path);
|
||||
}
|
||||
|
||||
void Gem5Connector::restore(const std::string &path)
|
||||
{
|
||||
DPRINTF(FailState, "Restoring state from %s.\n", path);
|
||||
|
||||
Root* root = Root::root();
|
||||
Checkpoint cp(path);
|
||||
|
||||
root->loadState(&cp);
|
||||
}
|
||||
20
src/core/sal/gem5/Gem5Connector.hpp
Normal file
20
src/core/sal/gem5/Gem5Connector.hpp
Normal file
@ -0,0 +1,20 @@
|
||||
#ifndef __GEM5_CONNECTOR_HPP__
|
||||
#define __GEM5_CONNECTOR_HPP__
|
||||
|
||||
#include <string>
|
||||
|
||||
/**
|
||||
* \class Gem5Connector
|
||||
* This class will be compiled inside the gem5 context and provides the
|
||||
* Gem5Controller a way to call gem5 functions.
|
||||
*/
|
||||
class Gem5Connector
|
||||
{
|
||||
public:
|
||||
void save(const std::string &path);
|
||||
void restore(const std::string &path);
|
||||
};
|
||||
|
||||
extern Gem5Connector connector;
|
||||
|
||||
#endif // __GEM5_CONNECTOR_HPP__
|
||||
@ -1,35 +1,23 @@
|
||||
#include "Gem5Controller.hpp"
|
||||
|
||||
#include <fstream>
|
||||
#include "Gem5Connector.hpp"
|
||||
|
||||
#include "../Listener.hpp"
|
||||
|
||||
#include "sim/core.hh"
|
||||
#include "sim/sim_exit.hh"
|
||||
//#include "sim/root.hh"
|
||||
|
||||
namespace fail {
|
||||
|
||||
bool Gem5Controller::save(const std::string &path)
|
||||
{
|
||||
// Takes a snapshot in the m5out dir
|
||||
Tick when = curTick() + 1;
|
||||
exitSimLoop("checkpoint", 0, when, 0);
|
||||
|
||||
// This could be a version to take snapshots with a specified name
|
||||
/*Root* root = Root::root();
|
||||
connector.save(path);
|
||||
|
||||
std::ofstream file(path.c_str());
|
||||
root->serialize(file);
|
||||
file.close();*/
|
||||
return false; // TODO
|
||||
return true;
|
||||
}
|
||||
|
||||
void Gem5Controller::restore(const std::string &path)
|
||||
{
|
||||
|
||||
connector.restore(path);
|
||||
}
|
||||
|
||||
// TODO: Implement reboot
|
||||
void Gem5Controller::reboot()
|
||||
{
|
||||
|
||||
|
||||
@ -1,12 +1,14 @@
|
||||
#ifndef __GEM5_CONTROLLER_HPP__
|
||||
#define __GEM5_CONTROLLER_HPP__
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "../SimulatorController.hpp"
|
||||
|
||||
namespace fail {
|
||||
|
||||
/**
|
||||
* \class Gem5Controller
|
||||
* gem5-specific implementation of a SimulatorController.
|
||||
*/
|
||||
class Gem5Controller : public SimulatorController {
|
||||
public:
|
||||
void onBreakpoint(address_t instrPtr, address_t address_space);
|
||||
@ -18,4 +20,4 @@ public:
|
||||
|
||||
} // end-of-namespace: fail
|
||||
|
||||
#endif // __GEM_CONTROLLER_HPP__
|
||||
#endif // __GEM5_CONTROLLER_HPP__
|
||||
|
||||
@ -1,25 +1,30 @@
|
||||
#ifndef __GEM5LISTENER_AH__
|
||||
#define __GEM5LISTENER_AH__
|
||||
#ifndef __GEM5_LISTENER_AH__
|
||||
#define __GEM5_LISTENER_AH__
|
||||
|
||||
#include "config/VariantConfig.hpp"
|
||||
#include "config/FailConfig.hpp"
|
||||
#include "../SALInst.hpp"
|
||||
|
||||
#if defined(BUILD_GEM5) && defined(CONFIG_EVENT_BREAKPOINTS)
|
||||
|
||||
#include "Gem5PCEvents.hpp"
|
||||
#include "sim/system.hh"
|
||||
#include "cpu/pc_event.hh"
|
||||
|
||||
class Gem5Breakpoint : public PCEvent
|
||||
{
|
||||
public:
|
||||
Gem5Breakpoint(PCEventQueue* queue, Addr ip)
|
||||
: PCEvent(queue, "Fail* experiment breakpoint", ip) {}
|
||||
virtual void process(ThreadContext *tc) { fail::simulator.onBreakpoint(this->evpc, fail::ANY_ADDR); }
|
||||
};
|
||||
|
||||
aspect Gem5Listener
|
||||
{
|
||||
advice "fail::BPSingleListener" : slice class
|
||||
{
|
||||
private:
|
||||
Gem5BreakpointEvent* m_Breakpoint;
|
||||
Gem5Breakpoint* m_Breakpoint;
|
||||
public:
|
||||
virtual bool onAddition()
|
||||
{
|
||||
System* sys = *System::systemList.begin();
|
||||
m_Breakpoint = new Gem5BreakpointEvent(&sys->pcEventQueue, this->m_WatchInstrPtr);
|
||||
m_Breakpoint = new Gem5Breakpoint(&sys->pcEventQueue, this->m_WatchInstrPtr);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -35,5 +40,5 @@ aspect Gem5Listener
|
||||
};
|
||||
};
|
||||
|
||||
#endif // BUILD_GEM5 && CONFIG_EVENT_BREAKPOINTS
|
||||
#endif // __GEM5LISTENER_AH__
|
||||
#endif // __GEM5_LISTENER_AH__
|
||||
|
||||
|
||||
@ -1,14 +0,0 @@
|
||||
#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);
|
||||
}
|
||||
@ -1,27 +0,0 @@
|
||||
#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__
|
||||
@ -6,6 +6,8 @@ if env['TARGET_ISA'] == 'no':
|
||||
env.Prepend(CPPPATH=Dir('../../../../../src/core/'))
|
||||
env.Prepend(CPPPATH=Dir('../../../../../build/src/core/'))
|
||||
|
||||
env.Append(CXXFLAGS = '-Wno-deprecated')
|
||||
|
||||
env.Prepend(LIBPATH=Dir('../../../../../build/lib/'))
|
||||
gStaticLibs = ['-lfail-sal', '-lfail-hsc-simple', '-lfail-comm', '-lfail-cpn', '-lfail-efw', '-lfail-util', '-lpcl']
|
||||
|
||||
@ -20,6 +22,7 @@ if (len(gStaticLibs)>0):
|
||||
env.Append(LINKCOM = ' $GEN_LIB_BUILD_STATIC')
|
||||
|
||||
|
||||
SimObject('FailGem5Device.py')
|
||||
Source('FailGem5Device.cc')
|
||||
DebugFlag('Fail')
|
||||
DebugFlag('FailState')
|
||||
CompoundFlag('Fail', ['FailState'])
|
||||
|
||||
Source('Gem5Connector.cc')
|
||||
|
||||
Reference in New Issue
Block a user