From 08febe581950f2d90467c11fc3a80e28c4cf8b65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrian=20B=C3=B6ckenkamp?= Date: Thu, 4 Apr 2013 17:30:10 +0200 Subject: [PATCH] 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 --- cmake/gem5.cmake | 34 ++++++++- src/core/sal/gem5/Gem5ArmCPU.cc | 34 ++------- src/core/sal/gem5/Gem5ArmCPU.hpp | 9 +-- src/core/sal/gem5/Gem5Breakpoint.hpp | 18 +++++ src/core/sal/gem5/Gem5Config.hpp | 13 ++-- src/core/sal/gem5/Gem5Connector.cc | 3 + src/core/sal/gem5/Gem5Connector.hpp | 4 ++ src/core/sal/gem5/Gem5Controller.cc | 17 ++--- src/core/sal/gem5/Gem5Controller.hpp | 5 +- src/core/sal/gem5/Gem5Listener.ah | 24 +------ src/core/sal/gem5/Gem5Memory.hpp | 78 +++++++-------------- src/core/sal/gem5/Gem5Wrapper.cc | 101 +++++++++++++++++++++++++++ src/core/sal/gem5/Gem5Wrapper.hpp | 33 +++++++++ src/core/sal/gem5/SConscript | 2 +- 14 files changed, 252 insertions(+), 123 deletions(-) create mode 100644 src/core/sal/gem5/Gem5Breakpoint.hpp create mode 100644 src/core/sal/gem5/Gem5Wrapper.cc create mode 100644 src/core/sal/gem5/Gem5Wrapper.hpp diff --git a/cmake/gem5.cmake b/cmake/gem5.cmake index 9acfdc40..e782f985 100644 --- a/cmake/gem5.cmake +++ b/cmake/gem5.cmake @@ -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) diff --git a/src/core/sal/gem5/Gem5ArmCPU.cc b/src/core/sal/gem5/Gem5ArmCPU.cc index 7a14d2fd..481a38b8 100644 --- a/src/core/sal/gem5/Gem5ArmCPU.cc +++ b/src/core/sal/gem5/Gem5ArmCPU.cc @@ -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 diff --git a/src/core/sal/gem5/Gem5ArmCPU.hpp b/src/core/sal/gem5/Gem5ArmCPU.hpp index 9aea6268..26215502 100644 --- a/src/core/sal/gem5/Gem5ArmCPU.hpp +++ b/src/core/sal/gem5/Gem5ArmCPU.hpp @@ -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 diff --git a/src/core/sal/gem5/Gem5Breakpoint.hpp b/src/core/sal/gem5/Gem5Breakpoint.hpp new file mode 100644 index 00000000..93da9e2f --- /dev/null +++ b/src/core/sal/gem5/Gem5Breakpoint.hpp @@ -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__ diff --git a/src/core/sal/gem5/Gem5Config.hpp b/src/core/sal/gem5/Gem5Config.hpp index 373a5f62..3e700860 100644 --- a/src/core/sal/gem5/Gem5Config.hpp +++ b/src/core/sal/gem5/Gem5Config.hpp @@ -6,15 +6,20 @@ #ifndef __GEM5_CONFIG_HPP__ #define __GEM5_CONFIG_HPP__ -#include "base/types.hh" +#include 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 diff --git a/src/core/sal/gem5/Gem5Connector.cc b/src/core/sal/gem5/Gem5Connector.cc index 642a594d..81ef19ba 100644 --- a/src/core/sal/gem5/Gem5Connector.cc +++ b/src/core/sal/gem5/Gem5Connector.cc @@ -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 diff --git a/src/core/sal/gem5/Gem5Connector.hpp b/src/core/sal/gem5/Gem5Connector.hpp index 5aa42988..25631223 100644 --- a/src/core/sal/gem5/Gem5Connector.hpp +++ b/src/core/sal/gem5/Gem5Connector.hpp @@ -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 diff --git a/src/core/sal/gem5/Gem5Controller.cc b/src/core/sal/gem5/Gem5Controller.cc index 36421a7d..e5b2a1af 100644 --- a/src/core/sal/gem5/Gem5Controller.cc +++ b/src/core/sal/gem5/Gem5Controller.cc @@ -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 diff --git a/src/core/sal/gem5/Gem5Controller.hpp b/src/core/sal/gem5/Gem5Controller.hpp index 2bdb117e..c4c664f0 100644 --- a/src/core/sal/gem5/Gem5Controller.hpp +++ b/src/core/sal/gem5/Gem5Controller.hpp @@ -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(); diff --git a/src/core/sal/gem5/Gem5Listener.ah b/src/core/sal/gem5/Gem5Listener.ah index 193c3bf7..e69a0d74 100644 --- a/src/core/sal/gem5/Gem5Listener.ah +++ b/src/core/sal/gem5/Gem5Listener.ah @@ -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; } }; }; diff --git a/src/core/sal/gem5/Gem5Memory.hpp b/src/core/sal/gem5/Gem5Memory.hpp index bad87f4e..750d9abf 100644 --- a/src/core/sal/gem5/Gem5Memory.hpp +++ b/src/core/sal/gem5/Gem5Memory.hpp @@ -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 diff --git a/src/core/sal/gem5/Gem5Wrapper.cc b/src/core/sal/gem5/Gem5Wrapper.cc new file mode 100644 index 00000000..f0848531 --- /dev/null +++ b/src/core/sal/gem5/Gem5Wrapper.cc @@ -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(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 diff --git a/src/core/sal/gem5/Gem5Wrapper.hpp b/src/core/sal/gem5/Gem5Wrapper.hpp new file mode 100644 index 00000000..141a87b6 --- /dev/null +++ b/src/core/sal/gem5/Gem5Wrapper.hpp @@ -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__ diff --git a/src/core/sal/gem5/SConscript b/src/core/sal/gem5/SConscript index 4b157810..74238e8e 100644 --- a/src/core/sal/gem5/SConscript +++ b/src/core/sal/gem5/SConscript @@ -25,4 +25,4 @@ if (len(gStaticLibs)>0): DebugFlag('FailState') CompoundFlag('Fail', ['FailState']) -Source('Gem5Connector.cc') +Source('Gem5Wrapper.cc')