diff --git a/simulators/gem5/src/cpu/simple/atomic.cc b/simulators/gem5/src/cpu/simple/atomic.cc index dba5a4c1..0b23bfb3 100644 --- a/simulators/gem5/src/cpu/simple/atomic.cc +++ b/simulators/gem5/src/cpu/simple/atomic.cc @@ -289,21 +289,21 @@ AtomicSimpleCPU::readMem(Addr addr, uint8_t * data, } dcache_access = true; - // FAIL* - #ifdef CONFIG_EVENT_TRAP - if(pkt.isError()) { - fail::ConcreteCPU* cpu = &fail::simulator.getCPU(cpuId()); - fail::simulator.onTrap(cpu, 0); - } - #endif + // FAIL* + #ifdef CONFIG_EVENT_TRAP + if(pkt.isError()) { + fail::ConcreteCPU* cpu = &fail::simulator.getCPU(cpuId()); + fail::simulator.onTrap(cpu, 0); + } + #endif assert(!pkt.isError()); - // FAIL* - #ifdef CONFIG_EVENT_MEMREAD - fail::ConcreteCPU* cpu = &fail::simulator.getCPU(cpuId()); - fail::simulator.onMemoryAccess(cpu, pkt.getAddr(), pkt.getSize(), false, instAddr()); - #endif + // FAIL* + #ifdef CONFIG_EVENT_MEMREAD + fail::ConcreteCPU* cpu = &fail::simulator.getCPU(cpuId()); + fail::simulator.onMemoryAccess(cpu, pkt.getAddr(), pkt.getSize(), false, instAddr()); + #endif if (req->isLLSC()) { TheISA::handleLockedRead(thread, req); @@ -404,22 +404,22 @@ AtomicSimpleCPU::writeMem(uint8_t *data, unsigned size, dcache_latency += dcachePort.sendAtomic(&pkt); } dcache_access = true; - - // FAIL* - #ifdef CONFIG_EVENT_TRAP - if(pkt.isError()) { - fail::ConcreteCPU* cpu = &fail::simulator.getCPU(cpuId()); - fail::simulator.onTrap(cpu, 0); - } - #endif + + // FAIL* + #ifdef CONFIG_EVENT_TRAP + if(pkt.isError()) { + fail::ConcreteCPU* cpu = &fail::simulator.getCPU(cpuId()); + fail::simulator.onTrap(cpu, 0); + } + #endif assert(!pkt.isError()); - // FAIL* - #ifdef CONFIG_EVENT_MEMWRITE - fail::ConcreteCPU* cpu = &fail::simulator.getCPU(cpuId()); - fail::simulator.onMemoryAccess(cpu, pkt.getAddr(), pkt.getSize(), true, instAddr()); - #endif + // FAIL* + #ifdef CONFIG_EVENT_MEMWRITE + fail::ConcreteCPU* cpu = &fail::simulator.getCPU(cpuId()); + fail::simulator.onMemoryAccess(cpu, pkt.getAddr(), pkt.getSize(), true, instAddr()); + #endif if (req->isSwap()) { assert(res); @@ -486,6 +486,18 @@ AtomicSimpleCPU::tick() bool needToFetch = !isRomMicroPC(pcState.microPC()) && !curMacroStaticInst; if (needToFetch) { + //DanceOS + #if defined(CONFIG_EVENT_BREAKPOINTS) || defined(CONFIG_EVENT_BREAKPOINTS_RANGE) + fail::ConcreteCPU* cpu = &fail::simulator.getCPU(cpuId()); + fail::simulator.setMnemonic("This feature is not implemented for gem5."); + fail::simulator.onBreakpoint(cpu, instAddr(), -1); + #endif + + //DanceOS + if(fail::simulator.isRestoreRequest()) { + fail::simulator.onRestore(); + } + setupFetchRequest(&ifetch_req); fault = thread->itb->translateAtomic(&ifetch_req, tc, BaseTLB::Execute); @@ -513,22 +525,22 @@ AtomicSimpleCPU::tick() else icache_latency = icachePort.sendAtomic(&ifetch_pkt); - // FAIL* - #ifdef CONFIG_EVENT_TRAP + // FAIL* + #ifdef CONFIG_EVENT_TRAP if(ifetch_pkt.isError()) - { - fail::ConcreteCPU* cpu = &fail::simulator.getCPU(cpuId()); - fail::simulator.onTrap(cpu, 0); - } - #endif - - assert(!ifetch_pkt.isError()); + { + fail::ConcreteCPU* cpu = &fail::simulator.getCPU(cpuId()); + fail::simulator.onTrap(cpu, 0); + } + #endif - // FAIL* - #ifdef CONFIG_EVENT_MEMREAD - fail::ConcreteCPU* cpu = &fail::simulator.getCPU(cpuId()); - fail::simulator.onMemoryAccess(cpu, ifetch_pkt.getAddr(), ifetch_pkt.getSize(), false, instAddr()); - #endif + assert(!ifetch_pkt.isError()); + + // FAIL* + #ifdef CONFIG_EVENT_MEMREAD + fail::ConcreteCPU* cpu = &fail::simulator.getCPU(cpuId()); + fail::simulator.onMemoryAccess(cpu, ifetch_pkt.getAddr(), ifetch_pkt.getSize(), false, instAddr()); + #endif // ifetch_req is initialized to read the instruction directly // into the CPU object's inst field. diff --git a/simulators/gem5/src/cpu/simple/base.cc b/simulators/gem5/src/cpu/simple/base.cc index 2b8e16ee..5bb8a653 100644 --- a/simulators/gem5/src/cpu/simple/base.cc +++ b/simulators/gem5/src/cpu/simple/base.cc @@ -401,13 +401,6 @@ BaseSimpleCPU::preExecute() //fetch beyond the MachInst at the current pc. instPtr = decoder->decode(pcState); - // FAIL* - #if defined(CONFIG_EVENT_BREAKPOINTS) || defined(CONFIG_EVENT_BREAKPOINTS_RANGE) - fail::ConcreteCPU* cpu = &fail::simulator.getCPU(cpuId()); - fail::simulator.setMnemonic(instPtr->getName()); - fail::simulator.onBreakpoint(cpu, instAddr(), -1); - #endif - if (instPtr) { stayAtPC = false; thread->pcState(pcState); diff --git a/simulators/gem5/src/sim/serialize.cc b/simulators/gem5/src/sim/serialize.cc index 30655e69..584e1594 100644 --- a/simulators/gem5/src/sim/serialize.cc +++ b/simulators/gem5/src/sim/serialize.cc @@ -512,6 +512,13 @@ Serializable::unserializeGlobals(Checkpoint *cp) globals.unserialize(cp, globals.name()); } +//DanceOS +void +Serializable::loadStateAll(Checkpoint *cp) +{ + SimObject::loadStateAll(cp); +} + void debug_serialize(const string &cpt_dir) { diff --git a/simulators/gem5/src/sim/serialize.hh b/simulators/gem5/src/sim/serialize.hh index 46e546be..6efa28ff 100644 --- a/simulators/gem5/src/sim/serialize.hh +++ b/simulators/gem5/src/sim/serialize.hh @@ -170,6 +170,7 @@ class Serializable static int ckptPrevCount; static void serializeAll(const std::string &cpt_dir); static void unserializeGlobals(Checkpoint *cp); + static void loadStateAll(Checkpoint *cp); //DanceOS }; // diff --git a/simulators/gem5/src/sim/sim_object.cc b/simulators/gem5/src/sim/sim_object.cc index 95bc6bf8..2761e6c4 100644 --- a/simulators/gem5/src/sim/sim_object.cc +++ b/simulators/gem5/src/sim/sim_object.cc @@ -130,6 +130,21 @@ SimObject::serializeAll(ostream &os) } } +//DanceOS +// static function: loadState all SimObjects. +// +void +SimObject::loadStateAll(Checkpoint *cp) +{ + SimObjectList::iterator ri = simObjectList.begin(); + SimObjectList::iterator rend = simObjectList.end(); + + for (; ri != rend; ++ri) { + SimObject *obj = *ri; + obj->loadState(cp); + } +} + #ifdef DEBUG // diff --git a/simulators/gem5/src/sim/sim_object.hh b/simulators/gem5/src/sim/sim_object.hh index 4388ff58..18f2daa0 100644 --- a/simulators/gem5/src/sim/sim_object.hh +++ b/simulators/gem5/src/sim/sim_object.hh @@ -139,6 +139,7 @@ class SimObject : public EventManager, public Serializable // static: call nameOut() & serialize() on all SimObjects static void serializeAll(std::ostream &); + static void loadStateAll(Checkpoint *cp); //DanceOS // Methods to drain objects in order to take checkpoints // Or switch from timing -> atomic memory model diff --git a/src/core/sal/gem5/Gem5Controller.cc b/src/core/sal/gem5/Gem5Controller.cc index 0975eee2..5a83f434 100644 --- a/src/core/sal/gem5/Gem5Controller.cc +++ b/src/core/sal/gem5/Gem5Controller.cc @@ -15,6 +15,9 @@ void Gem5Controller::startup() m_System = GetSystemObject(); m_Mem = new Gem5MemoryManager(m_System); + restore_request = false; + restore_path = ""; + int numCtxs = GetNumberOfContexts(m_System); for (int i = 0; i < numCtxs; i++) { ConcreteCPU* cpu = new ConcreteCPU(GetCPUId(m_System, i), m_System); @@ -53,13 +56,53 @@ bool Gem5Controller::save(const std::string &path) } } -void Gem5Controller::restore(const std::string &path) +void Gem5Controller::restore(const std::string& path) { - // FIXME: not working currently - Root* root = Root::root(); - Checkpoint cp(path); + clearListeners(); + restore_request = true; + restore_path = path; + m_CurrFlow = m_Flows.getCurrent(); + m_Flows.resume(); +} +void Gem5Controller::onRestore() +{ + /* Get the instance of the root-object from gem5 + * The root object seems to be the root of a tree + * that contains all the simulation objects, e.g. + * cpu, memory etc. + * gem5/src/sim/root.cc,root.hh + * */ + Root* root = Root::root(); + /* Checkpoint is a class of gem5 that is used to + * manage the built-in save and restore function + * of gem5. + * gem5/src/sim/serialize.cc,serialize.hh + * */ + Checkpoint cp(restore_path); + /* Set some global variables from checkpoint. + * gem5/src/sim/serialize.cc,serialize.hh + * */ + Serializable::unserializeGlobals(&cp); + /* loadStateAll(Checkpoint *cp) is a self-implemented + * function that calls loadState() for all simulation + * objects. (without the root object). + * gem5/src/sim/serialize.cc,serialize.hh + * gem5/src/sim/sim_object.cc,sim_object.hh + * */ + Serializable::loadStateAll(&cp); + /* Call loadState() on the root-object. + * gem5/src/sim/root.cc,root.hh + * */ root->loadState(&cp); + + restore_request = false; + m_Flows.toggle(m_CurrFlow); +} + +bool Gem5Controller::isRestoreRequest() +{ + return restore_request; } // TODO: Implement reboot diff --git a/src/core/sal/gem5/Gem5Controller.hpp b/src/core/sal/gem5/Gem5Controller.hpp index 70bdf38a..0f19aace 100644 --- a/src/core/sal/gem5/Gem5Controller.hpp +++ b/src/core/sal/gem5/Gem5Controller.hpp @@ -22,16 +22,21 @@ namespace fail { class Gem5Controller : public SimulatorController { private: System* m_System; //!< the gem5 system object + ExperimentFlow* m_CurrFlow; //!< Stores the current flow for save/restore-operations #if defined(CONFIG_EVENT_BREAKPOINTS) ||\ defined(CONFIG_EVENT_BREAKPOINTS_RANGE) std::string m_Mnemonic; //!< mnemonic of the instr. (only with BPs) #endif + bool restore_request; + std::string restore_path; public: void startup(); ~Gem5Controller(); bool save(const std::string &path); void restore(const std::string &path); + void onRestore(); + bool isRestoreRequest(); void reboot(); #if defined(CONFIG_EVENT_BREAKPOINTS) ||\ defined(CONFIG_EVENT_BREAKPOINTS_RANGE)