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:
Adrian Böckenkamp
2013-04-04 17:30:10 +02:00
parent 84559fe467
commit 08febe5819
14 changed files with 252 additions and 123 deletions

View File

@ -3,5 +3,37 @@ if(BUILD_GEM5)
message(STATUS "[${PROJECT_NAME}] Building gem5 variant ...")
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)

View File

@ -1,43 +1,17 @@
#include "Gem5ArmCPU.hpp"
#include "Gem5Wrapper.hpp"
namespace fail {
regdata_t Gem5ArmCPU::getRegisterContent(Register* reg) const
{
switch (reg->getType()) {
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;
return GetRegisterContent(m_System, m_Id, reg->getType(), reg->getIndex());
}
void Gem5ArmCPU::setRegisterContent(Register* reg, regdata_t value)
{
switch (reg->getType()) {
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?
SetRegisterContent(m_System, m_Id, reg->getType(), reg->getIndex(), value);
}
} // end-of-namespace: fail

View File

@ -4,7 +4,8 @@
#include "../arm/ArmArchitecture.hpp"
#include "../arm/ArmCPUState.hpp"
#include "sim/system.hh"
// gem5 forward declarations:
class System;
namespace fail {
@ -17,6 +18,9 @@ namespace fail {
* while \c ArmCPUState encapsulates the CPU state (e.g. register \a content).
*/
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:
/**
* Creates a new gem5 CPU for ARM based targets.
@ -60,9 +64,6 @@ public:
* @return the unique ID of \c this CPU object
*/
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

View 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__

View File

@ -6,15 +6,20 @@
#ifndef __GEM5_CONFIG_HPP__
#define __GEM5_CONFIG_HPP__
#include "base/types.hh"
#include <stdint.h>
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
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 int timer_t; //!< type of timer IDs
typedef uint64_t register_data_t; //!< register data type (gem5 always uses 64 bit for registers)
typedef int timer_t; //!< type of timer IDs
} // end-of-namespace: fail

View File

@ -1,3 +1,4 @@
#if 0
#include "Gem5Connector.hpp"
#include "base/trace.hh"
@ -23,3 +24,5 @@ void Gem5Connector::restore(const std::string &path)
root->loadState(&cp);
}
#endif

View File

@ -1,3 +1,6 @@
#if 0
// TODO: Incorporate this code into Gem5Controller.{hpp,cc}
#ifndef __GEM5_CONNECTOR_HPP__
#define __GEM5_CONNECTOR_HPP__
@ -17,3 +20,4 @@ public:
extern Gem5Connector connector;
#endif // __GEM5_CONNECTOR_HPP__
#endif

View File

@ -1,9 +1,9 @@
#include "Gem5Controller.hpp"
#include "Gem5Connector.hpp"
//#include "Gem5Connector.hpp"
#include "../Listener.hpp"
#include "sim/system.hh"
#include "Gem5Wrapper.hpp"
namespace fail {
@ -11,11 +11,12 @@ void Gem5Controller::startup()
{
// 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.
System* sys = System::systemList.front();
m_Mem = new Gem5MemoryManager(sys);
m_System = GetSystemObject();
m_Mem = new Gem5MemoryManager(m_System);
for (int i = 0; i < sys->numContexts(); i++) {
ConcreteCPU* cpu = new ConcreteCPU(sys->getThreadContext(i)->cpuId(), System::systemList.front());
int numCtxs = GetNumberOfContexts(m_System);
for (int i = 0; i < numCtxs; i++) {
ConcreteCPU* cpu = new ConcreteCPU(GetCPUId(m_System, i), m_System);
addCPU(cpu);
}
@ -35,14 +36,14 @@ Gem5Controller::~Gem5Controller()
bool Gem5Controller::save(const std::string &path)
{
connector.save(path); // FIXME: not working?!
// connector.save(path); // FIXME: not working?!
return true;
}
void Gem5Controller::restore(const std::string &path)
{
connector.restore(path); // FIXME: not working?!
// connector.restore(path); // FIXME: not working?!
}
// TODO: Implement reboot

View File

@ -4,7 +4,8 @@
#include "../SimulatorController.hpp"
#include "Gem5Memory.hpp"
#include "sim/system.hh"
// gem5 forward declarations:
class System;
namespace fail {
@ -14,6 +15,8 @@ namespace fail {
* Gem5-specific implementation of a SimulatorController.
*/
class Gem5Controller : public SimulatorController {
private:
System* m_System; //!< the gem5 system object
public:
void startup();
~Gem5Controller();

View File

@ -6,19 +6,6 @@
#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 {
advice "fail::BPSingleListener" : slice class {
private:
@ -26,18 +13,13 @@ aspect Gem5Listener {
public:
virtual bool onAddition()
{
System* sys = *System::systemList.begin();
m_Breakpoint = new Gem5Breakpoint(&sys->pcEventQueue, this->m_WatchInstrPtr);
m_Breakpoint = OnBreakpointAddition(Gem5Breakpoint* bp, address_t watchInstrPtr)
return true;
}
virtual void onDeletion()
{
if (m_Breakpoint) {
delete m_Breakpoint;
m_Breakpoint = 0;
}
OnBreakpointDeletion(m_Breakpoint);
m_Breakpoint = 0;
}
};
};

View File

@ -2,12 +2,10 @@
#define __GEM5_MEMORY_HPP__
#include "../Memory.hpp"
#include "Gem5Wrapper.hpp"
#include "sim/system.hh"
#include "mem/packet.hh"
#include "mem/physical.hh"
//class System;
// gem5 forward declarations:
class System;
namespace fail {
@ -17,56 +15,30 @@ namespace fail {
* MemoryManager to provide access to gem5's memory pool.
*/
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:
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

View 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

View 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__

View File

@ -25,4 +25,4 @@ if (len(gStaticLibs)>0):
DebugFlag('FailState')
CompoundFlag('Fail', ['FailState'])
Source('Gem5Connector.cc')
Source('Gem5Wrapper.cc')