Skip to content
Snippets Groups Projects
Commit e0e95faa authored by Tobias Friemel's avatar Tobias Friemel
Browse files

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
parent b41eec3f
No related branches found
No related tags found
No related merge requests found
Showing
with 122 additions and 242 deletions
......@@ -76,6 +76,11 @@
#endif
#endif
// FAIL*
// don't use unordered map with aspect c++ compiler
#undef HAVE_STD_UNORDERED_MAP
#undef HAVE_STD_TR1_UNORDERED_MAP
// set a default value of 0
#ifndef HAVE_STD_UNORDERED_MAP
#define HAVE_STD_UNORDERED_MAP 0
......
......@@ -81,6 +81,9 @@
#include "sim/stats.hh"
#include "sim/system.hh"
#include "sal/SALInst.hpp"
#include "config/FailConfig.hpp"
using namespace std;
using namespace TheISA;
......@@ -329,6 +332,10 @@ BaseSimpleCPU::checkForInterrupts()
Fault interrupt = interrupts->getInterrupt(tc);
if (interrupt != NoFault) {
// FAIL*
#ifdef CONFIG_EVENT_INTERRUPT
fail::simulator.onInterrupt(dynamic_cast<ArmFault*>(interrupt.get())->offset(), false);
#endif
fetchOffset = 0;
interrupts->updateIntrInfo(tc);
interrupt->invoke(tc);
......
......@@ -62,6 +62,9 @@
#include "mem/packet_access.hh"
#include "sim/system.hh"
#include "config/FailConfig.hpp"
#include "sal/SALInst.hpp"
using namespace std;
AbstractMemory::AbstractMemory(const Params *p) :
......@@ -400,6 +403,10 @@ AbstractMemory::access(PacketPtr pkt)
bytesRead[pkt->req->masterId()] += pkt->getSize();
if (pkt->req->isInstFetch())
bytesInstRead[pkt->req->masterId()] += pkt->getSize();
// FAIL*
#ifdef CONFIG_EVENT_MEMREAD
fail::simulator.onMemoryAccess(pkt->getAddr(), pkt->getSize(), false, 0);
#endif
} else if (pkt->isWrite()) {
if (writeOK(pkt)) {
if (pmemAddr)
......@@ -408,6 +415,10 @@ AbstractMemory::access(PacketPtr pkt)
TRACE_PACKET("Write");
numWrites[pkt->req->masterId()]++;
bytesWritten[pkt->req->masterId()] += pkt->getSize();
// FAIL*
#ifdef CONFIG_EVENT_MEMWRITE
fail::simulator.onMemoryAccess(pkt->getAddr(), pkt->getSize(), true, 0);
#endif
}
} else if (pkt->isInvalidate()) {
// no need to do anything
......@@ -432,11 +443,19 @@ AbstractMemory::functionalAccess(PacketPtr pkt)
if (pmemAddr)
memcpy(pkt->getPtr<uint8_t>(), hostAddr, pkt->getSize());
TRACE_PACKET("Read");
// FAIL*
#ifdef CONFIG_EVENT_MEMREAD
fail::simulator.onMemoryAccess(pkt->getAddr(), pkt->getSize(), false, 0);
#endif
pkt->makeResponse();
} else if (pkt->isWrite()) {
if (pmemAddr)
memcpy(hostAddr, pkt->getPtr<uint8_t>(), pkt->getSize());
TRACE_PACKET("Write");
// FAIL*
#ifdef CONFIG_EVENT_MEMWRITE
fail::simulator.onMemoryAccess(pkt->getAddr(), pkt->getSize(), true, 0);
#endif
pkt->makeResponse();
} else if (pkt->isPrint()) {
Packet::PrintReqState *prs =
......
......@@ -37,6 +37,8 @@
#include "sim/full_system.hh"
#include "sim/root.hh"
#include "sal/SALInst.hpp"
Root *Root::_root = NULL;
/*
......@@ -126,6 +128,14 @@ Root::loadState(Checkpoint *cp)
timeSyncEnable(params()->time_sync_enable);
}
// FAIL*
void
Root::startup()
{
fail::simulator.startup();
}
void
Root::serialize(std::ostream &os)
{
......
......@@ -112,6 +112,9 @@ class Root : public SimObject
*/
void initState();
// FAIL*
void startup();
virtual void serialize(std::ostream &os);
virtual void unserialize(Checkpoint *cp, const std::string &section);
......
......@@ -18,7 +18,6 @@ elseif(BUILD_GEM5)
SimulatorController.cc
perf/BreakpointBuffer.cc
gem5/Gem5Controller.cc
gem5/Gem5PCEvents.cc
)
elseif(BUILD_OVP)
set(SRCS
......
#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);
}
#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__
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 {
......
#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);
}
#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__
#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();
std::ofstream file(path.c_str());
root->serialize(file);
file.close();*/
return false; // TODO
connector.save(path);
return true;
}
void Gem5Controller::restore(const std::string &path)
{
connector.restore(path);
}
// TODO: Implement reboot
void Gem5Controller::reboot()
{
......
#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__
#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__
#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);
}
#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')
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment