gem5 build system improved
Encapsulated gem5-specific code into wrapper functions to separate the build process (Fail: CMake, gem5: scons). Added some gem5-related FIXMEs. Another CMake related FIXME added. +some cosmetics. Change-Id: Id84b480127b1f13aed6a0ee97f3583f410d531c5
This commit is contained in:
@ -3,5 +3,37 @@ if(BUILD_GEM5)
|
|||||||
message(STATUS "[${PROJECT_NAME}] Building gem5 variant ...")
|
message(STATUS "[${PROJECT_NAME}] Building gem5 variant ...")
|
||||||
SET(VARIANT gem5)
|
SET(VARIANT gem5)
|
||||||
|
|
||||||
#set(gem5_src_dir ${PROJECT_SOURCE_DIR}/simulators/gem5)
|
set(gem5_src_dir ${PROJECT_SOURCE_DIR}/simulators/gem5)
|
||||||
|
set(gem5_wrapper ${PROJECT_SOURCE_DIR}/src/core/sal/gem5)
|
||||||
|
set(gem5_build_config build/ARM/gem5.debug)
|
||||||
|
set(core_count 9)
|
||||||
|
|
||||||
|
# FIXMEs:
|
||||||
|
# - incremental builds working?
|
||||||
|
# - dependency for modified .cc files not correctly checked
|
||||||
|
# - core_count should be derived from the parent make -jX parameter
|
||||||
|
# - make gem5_build_config configurable in CMake
|
||||||
|
# (alternative: gem5_build_config is set based on the CMake build
|
||||||
|
# config, e.g., "Debug" or "Release")
|
||||||
|
|
||||||
|
# Enable ExternalProject CMake module
|
||||||
|
include(ExternalProject)
|
||||||
|
|
||||||
|
# Use cmake's external project feature to build gem5 (and link FailGem5)
|
||||||
|
ExternalProject_Add(
|
||||||
|
FailGem5_binary_external # the (unique) name of this custom target (= external project)
|
||||||
|
# Disable update, patch and configure step:
|
||||||
|
UPDATE_COMMAND ""
|
||||||
|
PATCH_COMMAND ""
|
||||||
|
CONFIGURE_COMMAND ""
|
||||||
|
SOURCE_DIR ${gem5_src_dir}
|
||||||
|
BINARY_DIR ${gem5_src_dir}
|
||||||
|
# Build gem5 using scons build system:
|
||||||
|
BUILD_COMMAND scons EXTRAS=${gem5_wrapper} ${gem5_build_config} -j${core_count}
|
||||||
|
# Disable install step (for now)
|
||||||
|
INSTALL_COMMAND ""
|
||||||
|
)
|
||||||
|
|
||||||
|
# Build "fail" library first (will be statically linked to gem5)
|
||||||
|
add_dependencies(FailGem5_binary_external fail)
|
||||||
endif(BUILD_GEM5)
|
endif(BUILD_GEM5)
|
||||||
|
|||||||
@ -1,43 +1,17 @@
|
|||||||
#include "Gem5ArmCPU.hpp"
|
#include "Gem5ArmCPU.hpp"
|
||||||
|
|
||||||
|
#include "Gem5Wrapper.hpp"
|
||||||
|
|
||||||
namespace fail {
|
namespace fail {
|
||||||
|
|
||||||
regdata_t Gem5ArmCPU::getRegisterContent(Register* reg) const
|
regdata_t Gem5ArmCPU::getRegisterContent(Register* reg) const
|
||||||
{
|
{
|
||||||
switch (reg->getType()) {
|
return GetRegisterContent(m_System, m_Id, reg->getType(), reg->getIndex());
|
||||||
case RT_GP:
|
|
||||||
if (reg->getIndex() == 15) {
|
|
||||||
return m_System->getThreadContext(m_Id)->pcState().pc();
|
|
||||||
}
|
|
||||||
return m_System->getThreadContext(m_Id)->readIntReg(reg->getIndex());
|
|
||||||
case RT_FP:
|
|
||||||
return m_System->getThreadContext(m_Id)->readFloatReg(reg->getIndex());
|
|
||||||
case RT_ST:
|
|
||||||
return m_System->getThreadContext(m_Id)->readMiscReg(reg->getIndex());
|
|
||||||
case RT_IP:
|
|
||||||
return m_System->getThreadContext(m_Id)->pcState().pc();
|
|
||||||
}
|
|
||||||
|
|
||||||
// This shouldn't be reached if a valid register is passed
|
|
||||||
// TODO: assertion?
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Gem5ArmCPU::setRegisterContent(Register* reg, regdata_t value)
|
void Gem5ArmCPU::setRegisterContent(Register* reg, regdata_t value)
|
||||||
{
|
{
|
||||||
switch (reg->getType()) {
|
SetRegisterContent(m_System, m_Id, reg->getType(), reg->getIndex(), value);
|
||||||
case RT_GP:
|
|
||||||
m_System->getThreadContext(m_Id)->setIntReg(reg->getIndex(), value);
|
|
||||||
break;
|
|
||||||
case RT_FP:
|
|
||||||
m_System->getThreadContext(m_Id)->setFloatReg(reg->getIndex(), value);
|
|
||||||
break;
|
|
||||||
case RT_ST:
|
|
||||||
return m_System->getThreadContext(m_Id)->setMiscReg(reg->getIndex(), value);
|
|
||||||
case RT_IP:
|
|
||||||
return setRegisterContent(getRegister(RI_IP), value);
|
|
||||||
}
|
|
||||||
// TODO: assertion?
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // end-of-namespace: fail
|
} // end-of-namespace: fail
|
||||||
|
|||||||
@ -4,7 +4,8 @@
|
|||||||
#include "../arm/ArmArchitecture.hpp"
|
#include "../arm/ArmArchitecture.hpp"
|
||||||
#include "../arm/ArmCPUState.hpp"
|
#include "../arm/ArmCPUState.hpp"
|
||||||
|
|
||||||
#include "sim/system.hh"
|
// gem5 forward declarations:
|
||||||
|
class System;
|
||||||
|
|
||||||
namespace fail {
|
namespace fail {
|
||||||
|
|
||||||
@ -17,6 +18,9 @@ namespace fail {
|
|||||||
* while \c ArmCPUState encapsulates the CPU state (e.g. register \a content).
|
* while \c ArmCPUState encapsulates the CPU state (e.g. register \a content).
|
||||||
*/
|
*/
|
||||||
class Gem5ArmCPU : public ArmArchitecture, public ArmCPUState {
|
class Gem5ArmCPU : public ArmArchitecture, public ArmCPUState {
|
||||||
|
private:
|
||||||
|
unsigned int m_Id; //!< the unique ID of this CPU
|
||||||
|
System* m_System; //!< the gem5 system object
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* Creates a new gem5 CPU for ARM based targets.
|
* Creates a new gem5 CPU for ARM based targets.
|
||||||
@ -60,9 +64,6 @@ public:
|
|||||||
* @return the unique ID of \c this CPU object
|
* @return the unique ID of \c this CPU object
|
||||||
*/
|
*/
|
||||||
unsigned int getId() const { return m_Id; }
|
unsigned int getId() const { return m_Id; }
|
||||||
private:
|
|
||||||
unsigned int m_Id; //!< the unique ID of this CPU
|
|
||||||
System* m_System; //!< the gem5 system object
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef Gem5ArmCPU ConcreteCPU; //!< the concrete CPU type for ARM + gem5
|
typedef Gem5ArmCPU ConcreteCPU; //!< the concrete CPU type for ARM + gem5
|
||||||
|
|||||||
18
src/core/sal/gem5/Gem5Breakpoint.hpp
Normal file
18
src/core/sal/gem5/Gem5Breakpoint.hpp
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#ifndef __GEM5_BREAKPOINT_HPP__
|
||||||
|
#define __GEM5_BREAKPOINT_HPP__
|
||||||
|
|
||||||
|
#include "../SALConfig.hpp"
|
||||||
|
#include "cpu/pc_event.hh"
|
||||||
|
|
||||||
|
namespace fail {
|
||||||
|
|
||||||
|
class Gem5Breakpoint : public PCEvent {
|
||||||
|
public:
|
||||||
|
Gem5Breakpoint(PCEventQueue* queue, Addr ip)
|
||||||
|
: PCEvent(queue, "Fail* experiment breakpoint", ip) { }
|
||||||
|
virtual void process(ThreadContext *tc);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // end-of-namespace: fail
|
||||||
|
|
||||||
|
#endif // __GEM5_BREAKPOINT_HPP__
|
||||||
@ -6,15 +6,20 @@
|
|||||||
#ifndef __GEM5_CONFIG_HPP__
|
#ifndef __GEM5_CONFIG_HPP__
|
||||||
#define __GEM5_CONFIG_HPP__
|
#define __GEM5_CONFIG_HPP__
|
||||||
|
|
||||||
#include "base/types.hh"
|
#include <stdint.h>
|
||||||
|
|
||||||
namespace fail {
|
namespace fail {
|
||||||
|
|
||||||
typedef Addr guest_address_t; //!< the guest memory address type
|
/**
|
||||||
|
* The guest memory address type
|
||||||
|
*
|
||||||
|
* @note Keep this sync with src/base/types.hh:68 ("typedef uint64_t Addr;")
|
||||||
|
*/
|
||||||
|
typedef uint64_t guest_address_t;
|
||||||
// TODO: Set Host Address Type
|
// TODO: Set Host Address Type
|
||||||
typedef void* host_address_t; //!< the host memory address type
|
typedef void* host_address_t; //!< the host memory address type
|
||||||
typedef uint64_t register_data_t; //!< register data type (gem5 always uses 64 bit for registers)
|
typedef uint64_t register_data_t; //!< register data type (gem5 always uses 64 bit for registers)
|
||||||
typedef int timer_t; //!< type of timer IDs
|
typedef int timer_t; //!< type of timer IDs
|
||||||
|
|
||||||
} // end-of-namespace: fail
|
} // end-of-namespace: fail
|
||||||
|
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
#if 0
|
||||||
#include "Gem5Connector.hpp"
|
#include "Gem5Connector.hpp"
|
||||||
|
|
||||||
#include "base/trace.hh"
|
#include "base/trace.hh"
|
||||||
@ -23,3 +24,5 @@ void Gem5Connector::restore(const std::string &path)
|
|||||||
|
|
||||||
root->loadState(&cp);
|
root->loadState(&cp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|||||||
@ -1,3 +1,6 @@
|
|||||||
|
#if 0
|
||||||
|
// TODO: Incorporate this code into Gem5Controller.{hpp,cc}
|
||||||
|
|
||||||
#ifndef __GEM5_CONNECTOR_HPP__
|
#ifndef __GEM5_CONNECTOR_HPP__
|
||||||
#define __GEM5_CONNECTOR_HPP__
|
#define __GEM5_CONNECTOR_HPP__
|
||||||
|
|
||||||
@ -17,3 +20,4 @@ public:
|
|||||||
extern Gem5Connector connector;
|
extern Gem5Connector connector;
|
||||||
|
|
||||||
#endif // __GEM5_CONNECTOR_HPP__
|
#endif // __GEM5_CONNECTOR_HPP__
|
||||||
|
#endif
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
#include "Gem5Controller.hpp"
|
#include "Gem5Controller.hpp"
|
||||||
#include "Gem5Connector.hpp"
|
//#include "Gem5Connector.hpp"
|
||||||
|
|
||||||
#include "../Listener.hpp"
|
#include "../Listener.hpp"
|
||||||
|
|
||||||
#include "sim/system.hh"
|
#include "Gem5Wrapper.hpp"
|
||||||
|
|
||||||
namespace fail {
|
namespace fail {
|
||||||
|
|
||||||
@ -11,11 +11,12 @@ void Gem5Controller::startup()
|
|||||||
{
|
{
|
||||||
// Assuming there is only one defined system should be sufficient for most cases. More systems
|
// Assuming there is only one defined system should be sufficient for most cases. More systems
|
||||||
// are only used for switching cpu model or caches during a simulation run.
|
// are only used for switching cpu model or caches during a simulation run.
|
||||||
System* sys = System::systemList.front();
|
m_System = GetSystemObject();
|
||||||
m_Mem = new Gem5MemoryManager(sys);
|
m_Mem = new Gem5MemoryManager(m_System);
|
||||||
|
|
||||||
for (int i = 0; i < sys->numContexts(); i++) {
|
int numCtxs = GetNumberOfContexts(m_System);
|
||||||
ConcreteCPU* cpu = new ConcreteCPU(sys->getThreadContext(i)->cpuId(), System::systemList.front());
|
for (int i = 0; i < numCtxs; i++) {
|
||||||
|
ConcreteCPU* cpu = new ConcreteCPU(GetCPUId(m_System, i), m_System);
|
||||||
addCPU(cpu);
|
addCPU(cpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -35,14 +36,14 @@ Gem5Controller::~Gem5Controller()
|
|||||||
|
|
||||||
bool Gem5Controller::save(const std::string &path)
|
bool Gem5Controller::save(const std::string &path)
|
||||||
{
|
{
|
||||||
connector.save(path); // FIXME: not working?!
|
// connector.save(path); // FIXME: not working?!
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Gem5Controller::restore(const std::string &path)
|
void Gem5Controller::restore(const std::string &path)
|
||||||
{
|
{
|
||||||
connector.restore(path); // FIXME: not working?!
|
// connector.restore(path); // FIXME: not working?!
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Implement reboot
|
// TODO: Implement reboot
|
||||||
|
|||||||
@ -4,7 +4,8 @@
|
|||||||
#include "../SimulatorController.hpp"
|
#include "../SimulatorController.hpp"
|
||||||
#include "Gem5Memory.hpp"
|
#include "Gem5Memory.hpp"
|
||||||
|
|
||||||
#include "sim/system.hh"
|
// gem5 forward declarations:
|
||||||
|
class System;
|
||||||
|
|
||||||
namespace fail {
|
namespace fail {
|
||||||
|
|
||||||
@ -14,6 +15,8 @@ namespace fail {
|
|||||||
* Gem5-specific implementation of a SimulatorController.
|
* Gem5-specific implementation of a SimulatorController.
|
||||||
*/
|
*/
|
||||||
class Gem5Controller : public SimulatorController {
|
class Gem5Controller : public SimulatorController {
|
||||||
|
private:
|
||||||
|
System* m_System; //!< the gem5 system object
|
||||||
public:
|
public:
|
||||||
void startup();
|
void startup();
|
||||||
~Gem5Controller();
|
~Gem5Controller();
|
||||||
|
|||||||
@ -6,19 +6,6 @@
|
|||||||
|
|
||||||
#if defined(BUILD_GEM5) && defined(CONFIG_EVENT_BREAKPOINTS) && !defined(CONFIG_EVENT_BREAKPOINTS_RANGE)
|
#if defined(BUILD_GEM5) && defined(CONFIG_EVENT_BREAKPOINTS) && !defined(CONFIG_EVENT_BREAKPOINTS_RANGE)
|
||||||
|
|
||||||
#include "../SALInst.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(&fail::simulator.getCPU(tc->cpuId()), this->evpc, fail::ANY_ADDR); }
|
|
||||||
};
|
|
||||||
|
|
||||||
aspect Gem5Listener {
|
aspect Gem5Listener {
|
||||||
advice "fail::BPSingleListener" : slice class {
|
advice "fail::BPSingleListener" : slice class {
|
||||||
private:
|
private:
|
||||||
@ -26,18 +13,13 @@ aspect Gem5Listener {
|
|||||||
public:
|
public:
|
||||||
virtual bool onAddition()
|
virtual bool onAddition()
|
||||||
{
|
{
|
||||||
System* sys = *System::systemList.begin();
|
m_Breakpoint = OnBreakpointAddition(Gem5Breakpoint* bp, address_t watchInstrPtr)
|
||||||
m_Breakpoint = new Gem5Breakpoint(&sys->pcEventQueue, this->m_WatchInstrPtr);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void onDeletion()
|
virtual void onDeletion()
|
||||||
{
|
{
|
||||||
if (m_Breakpoint) {
|
OnBreakpointDeletion(m_Breakpoint);
|
||||||
delete m_Breakpoint;
|
m_Breakpoint = 0;
|
||||||
m_Breakpoint = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@ -2,12 +2,10 @@
|
|||||||
#define __GEM5_MEMORY_HPP__
|
#define __GEM5_MEMORY_HPP__
|
||||||
|
|
||||||
#include "../Memory.hpp"
|
#include "../Memory.hpp"
|
||||||
|
#include "Gem5Wrapper.hpp"
|
||||||
|
|
||||||
#include "sim/system.hh"
|
// gem5 forward declarations:
|
||||||
#include "mem/packet.hh"
|
class System;
|
||||||
#include "mem/physical.hh"
|
|
||||||
|
|
||||||
//class System;
|
|
||||||
|
|
||||||
namespace fail {
|
namespace fail {
|
||||||
|
|
||||||
@ -17,56 +15,30 @@ namespace fail {
|
|||||||
* MemoryManager to provide access to gem5's memory pool.
|
* MemoryManager to provide access to gem5's memory pool.
|
||||||
*/
|
*/
|
||||||
class Gem5MemoryManager : public MemoryManager {
|
class Gem5MemoryManager : public MemoryManager {
|
||||||
public:
|
|
||||||
Gem5MemoryManager(System* system) : m_System(system), m_Mem(&system->getPhysMem()) { }
|
|
||||||
|
|
||||||
size_t getPoolSize() const { return m_Mem->totalSize(); }
|
|
||||||
host_address_t getStartAddr() const { return 0; }
|
|
||||||
|
|
||||||
byte_t getByte(guest_address_t addr)
|
|
||||||
{
|
|
||||||
Request req(addr, 1, Request::PHYSICAL, 0);
|
|
||||||
|
|
||||||
Packet pkt(&req, MemCmd::ReadReq);
|
|
||||||
byte_t data;
|
|
||||||
pkt.dataStatic(&data);
|
|
||||||
|
|
||||||
m_Mem->functionalAccess(&pkt);
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
void getBytes(guest_address_t addr, size_t cnt, void *dest)
|
|
||||||
{
|
|
||||||
Request req(addr, cnt, Request::PHYSICAL, 0);
|
|
||||||
|
|
||||||
Packet pkt(&req, MemCmd::ReadReq);
|
|
||||||
pkt.dataStatic(dest);
|
|
||||||
|
|
||||||
m_Mem->functionalAccess(&pkt);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setByte(guest_address_t addr, byte_t data)
|
|
||||||
{
|
|
||||||
Request req(addr, 1, Request::PHYSICAL, 0);
|
|
||||||
|
|
||||||
Packet pkt(&req, MemCmd::WriteReq);
|
|
||||||
pkt.dataStatic(&data);
|
|
||||||
|
|
||||||
m_Mem->functionalAccess(&pkt);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setBytes(guest_address_t addr, size_t cnt, void const *src)
|
|
||||||
{
|
|
||||||
Request req(addr, cnt, Request::PHYSICAL, 0);
|
|
||||||
|
|
||||||
Packet pkt(&req, MemCmd::WriteReq);
|
|
||||||
pkt.dataStatic(src);
|
|
||||||
|
|
||||||
m_Mem->functionalAccess(&pkt);
|
|
||||||
}
|
|
||||||
private:
|
private:
|
||||||
System* m_System;
|
System* m_System;
|
||||||
PhysicalMemory* m_Mem;
|
public:
|
||||||
|
Gem5MemoryManager(System* sys) : m_System(sys) { }
|
||||||
|
size_t getPoolSize() const { return GetPoolSize(m_System); }
|
||||||
|
host_address_t getStartAddr() const { return 0; }
|
||||||
|
byte_t getByte(guest_address_t addr)
|
||||||
|
{
|
||||||
|
byte_t data;
|
||||||
|
ReadMemory(m_System, addr, 1, &data);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
void getBytes(guest_address_t addr, size_t cnt, void *dest)
|
||||||
|
{
|
||||||
|
ReadMemory(m_System, addr, cnt, dest);
|
||||||
|
}
|
||||||
|
void setByte(guest_address_t addr, byte_t data)
|
||||||
|
{
|
||||||
|
WriteMemory(m_System, addr, 1, &data);
|
||||||
|
}
|
||||||
|
void setBytes(guest_address_t addr, size_t cnt, void const *src)
|
||||||
|
{
|
||||||
|
WriteMemory(m_System, addr, cnt, src);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end-of-namespace: fail
|
} // end-of-namespace: fail
|
||||||
|
|||||||
101
src/core/sal/gem5/Gem5Wrapper.cc
Normal file
101
src/core/sal/gem5/Gem5Wrapper.cc
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
#include "../SALInst.hpp"
|
||||||
|
#include "Gem5Wrapper.hpp"
|
||||||
|
#include "Gem5Breakpoint.hpp"
|
||||||
|
|
||||||
|
#include "sim/system.hh"
|
||||||
|
#include "mem/packet.hh"
|
||||||
|
#include "mem/physical.hh"
|
||||||
|
|
||||||
|
namespace fail {
|
||||||
|
|
||||||
|
// Register-/Memory-related:
|
||||||
|
regdata_t GetRegisterContent(System* sys, unsigned int id, RegisterType type, size_t idx)
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
case RT_GP:
|
||||||
|
if (idx == 15) {
|
||||||
|
return sys->getThreadContext(id)->pcState().pc();
|
||||||
|
}
|
||||||
|
return sys->getThreadContext(id)->readIntReg(idx);
|
||||||
|
case RT_FP: return sys->getThreadContext(id)->readFloatReg(idx); // FIXME: correct?! (FP <-> Float?!)
|
||||||
|
case RT_ST: return sys->getThreadContext(id)->readMiscReg(idx);
|
||||||
|
case RT_IP: return sys->getThreadContext(id)->pcState().pc();
|
||||||
|
}
|
||||||
|
// This shouldn't be reached if a valid register is passed
|
||||||
|
assert(false && "FATAL ERROR: invalid register type (should never be reached)!");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetRegisterContent(System* sys, unsigned int id, RegisterType type, size_t idx,
|
||||||
|
regdata_t value)
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
case RT_GP: sys->getThreadContext(id)->setIntReg(idx, value); break;
|
||||||
|
case RT_FP: sys->getThreadContext(id)->setFloatReg(idx, value); break; // FIXME: correct?! (FP <-> Float?!)
|
||||||
|
case RT_ST: sys->getThreadContext(id)->setMiscReg(idx, value); break;
|
||||||
|
case RT_IP: sys->getThreadContext(id)->pcState().pc(static_cast<Addr>(value)); break;
|
||||||
|
}
|
||||||
|
// This shouldn't be reached if a valid register is passed
|
||||||
|
assert(false && "FATAL ERROR: invalid register type (should never be reached)!");
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReadMemory(System* sys, guest_address_t addr, size_t cnt, void *dest)
|
||||||
|
{
|
||||||
|
Request req(addr, cnt, Request::PHYSICAL, 0);
|
||||||
|
|
||||||
|
Packet pkt(&req, MemCmd::ReadReq);
|
||||||
|
pkt.dataStatic(dest);
|
||||||
|
|
||||||
|
sys->getPhysMem().functionalAccess(&pkt);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteMemory(System* sys, guest_address_t addr, size_t cnt, void const *src)
|
||||||
|
{
|
||||||
|
Request req(addr, cnt, Request::PHYSICAL, 0);
|
||||||
|
|
||||||
|
Packet pkt(&req, MemCmd::WriteReq);
|
||||||
|
pkt.dataStatic(src);
|
||||||
|
|
||||||
|
sys->getPhysMem().functionalAccess(&pkt);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t GetPoolSize(System* sys) { return sys->getPhysMem().totalSize(); }
|
||||||
|
|
||||||
|
// Breakpoint-related:
|
||||||
|
void Gem5Breakpoint::process(ThreadContext *tc)
|
||||||
|
{
|
||||||
|
fail::simulator.onBreakpoint(&fail::simulator.getCPU(tc->cpuId()), this->evpc, fail::ANY_ADDR);
|
||||||
|
}
|
||||||
|
|
||||||
|
Gem5Breakpoint* OnBreakpointAddition(address_t watchInstrPtr)
|
||||||
|
{
|
||||||
|
System* sys = *System::systemList.begin();
|
||||||
|
// FIXME: begin() vs. front() (see Gem5Controller::startup())
|
||||||
|
// FIXME: Provide "sys" using the simulator-inst?
|
||||||
|
return new Gem5Breakpoint(&sys->pcEventQueue, watchInstrPtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnBreakpointDeletion(Gem5Breakpoint* bp)
|
||||||
|
{
|
||||||
|
if (bp) {
|
||||||
|
delete bp; // TODO: required?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Controller-related:
|
||||||
|
unsigned int GetCPUId(System* sys, int context)
|
||||||
|
{
|
||||||
|
return sys->getThreadContext(context)->cpuId();
|
||||||
|
}
|
||||||
|
|
||||||
|
System* GetSystemObject()
|
||||||
|
{
|
||||||
|
return System::systemList.front();
|
||||||
|
}
|
||||||
|
|
||||||
|
int GetNumberOfContexts(System* sys)
|
||||||
|
{
|
||||||
|
return sys->numContexts();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // end-of-namespace: fail
|
||||||
33
src/core/sal/gem5/Gem5Wrapper.hpp
Normal file
33
src/core/sal/gem5/Gem5Wrapper.hpp
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#ifndef __GEM5_WRAPPER_HPP__
|
||||||
|
#define __GEM5_WRAPPER_HPP__
|
||||||
|
|
||||||
|
#include "../Register.hpp"
|
||||||
|
#include "../SALConfig.hpp"
|
||||||
|
|
||||||
|
// gem5 forward declarations:
|
||||||
|
class System;
|
||||||
|
|
||||||
|
namespace fail {
|
||||||
|
|
||||||
|
class Gem5Breakpoint;
|
||||||
|
|
||||||
|
// Register-/Memory-related:
|
||||||
|
regdata_t GetRegisterContent(System* sys, unsigned int id, RegisterType type, size_t idx);
|
||||||
|
void SetRegisterContent(System* sys, unsigned int id, RegisterType type, size_t idx,
|
||||||
|
regdata_t value);
|
||||||
|
void WriteMemory(System* sys, guest_address_t addr, size_t cnt, void const *src);
|
||||||
|
void ReadMemory(System* sys, guest_address_t addr, size_t cnt, void *dest);
|
||||||
|
size_t GetPoolSize(System* sys);
|
||||||
|
|
||||||
|
// Breakpoint-related:
|
||||||
|
Gem5Breakpoint* OnBreakpointAddition(address_t watchInstrPtr);
|
||||||
|
void OnBreakpointDeletion(Gem5Breakpoint* bp);
|
||||||
|
|
||||||
|
// Controller-related:
|
||||||
|
unsigned int GetCPUId(System* sys, int context);
|
||||||
|
System* GetSystemObject();
|
||||||
|
int GetNumberOfContexts(System* sys);
|
||||||
|
|
||||||
|
} // end-of-namespace: fail
|
||||||
|
|
||||||
|
#endif // __GEM5_WRAPPER_HPP__
|
||||||
@ -25,4 +25,4 @@ if (len(gStaticLibs)>0):
|
|||||||
DebugFlag('FailState')
|
DebugFlag('FailState')
|
||||||
CompoundFlag('Fail', ['FailState'])
|
CompoundFlag('Fail', ['FailState'])
|
||||||
|
|
||||||
Source('Gem5Connector.cc')
|
Source('Gem5Wrapper.cc')
|
||||||
|
|||||||
Reference in New Issue
Block a user