12SN/A/* 210905Sandreas.sandberg@arm.com * Copyright (c) 2015 ARM Limited 310905Sandreas.sandberg@arm.com * All rights reserved 410905Sandreas.sandberg@arm.com * 510905Sandreas.sandberg@arm.com * The license below extends only to copyright in the software and shall 610905Sandreas.sandberg@arm.com * not be construed as granting a license to any other intellectual 710905Sandreas.sandberg@arm.com * property including but not limited to intellectual property relating 810905Sandreas.sandberg@arm.com * to a hardware implementation of the functionality of the software 910905Sandreas.sandberg@arm.com * licensed hereunder. You may use the software subject to the license 1010905Sandreas.sandberg@arm.com * terms below provided that you ensure that this notice is replicated 1110905Sandreas.sandberg@arm.com * unmodified and in its entirety in all distributions of the software, 1210905Sandreas.sandberg@arm.com * modified or unmodified, in source code or in binary form. 1310905Sandreas.sandberg@arm.com * 141762SN/A * Copyright (c) 2002-2005 The Regents of The University of Michigan 159983Sstever@gmail.com * Copyright (c) 2013 Advanced Micro Devices, Inc. 169983Sstever@gmail.com * Copyright (c) 2013 Mark D. Hill and David A. Wood 172SN/A * All rights reserved. 182SN/A * 192SN/A * Redistribution and use in source and binary forms, with or without 202SN/A * modification, are permitted provided that the following conditions are 212SN/A * met: redistributions of source code must retain the above copyright 222SN/A * notice, this list of conditions and the following disclaimer; 232SN/A * redistributions in binary form must reproduce the above copyright 242SN/A * notice, this list of conditions and the following disclaimer in the 252SN/A * documentation and/or other materials provided with the distribution; 262SN/A * neither the name of the copyright holders nor the names of its 272SN/A * contributors may be used to endorse or promote products derived from 282SN/A * this software without specific prior written permission. 292SN/A * 302SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 312SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 322SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 332SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 342SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 352SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 362SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 372SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 382SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 392SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 402SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 412665Ssaidi@eecs.umich.edu * 422760Sbinkertn@umich.edu * Authors: Nathan Binkert 432760Sbinkertn@umich.edu * Erik Hallnor 442665Ssaidi@eecs.umich.edu * Steve Reinhardt 4510905Sandreas.sandberg@arm.com * Andreas Sandberg 462SN/A */ 472SN/A 4811793Sbrandon.potter@amd.com#include "sim/serialize.hh" 4911793Sbrandon.potter@amd.com 508229Snate@binkert.org#include <sys/stat.h> 512SN/A#include <sys/time.h> 52363SN/A#include <sys/types.h> 532SN/A 548229Snate@binkert.org#include <cerrno> 552SN/A#include <fstream> 562SN/A#include <list> 572SN/A#include <string> 582SN/A#include <vector> 592SN/A 60363SN/A#include "base/inifile.hh" 611388SN/A#include "base/output.hh" 62363SN/A#include "base/trace.hh" 6310905Sandreas.sandberg@arm.com#include "debug/Checkpoint.hh" 6456SN/A#include "sim/eventq.hh" 6556SN/A#include "sim/sim_events.hh" 661638SN/A#include "sim/sim_exit.hh" 6756SN/A#include "sim/sim_object.hh" 682SN/A 692356SN/A// For stat reset hack 702356SN/A#include "sim/stat_control.hh" 712356SN/A 722SN/Ausing namespace std; 732SN/A 742287SN/Aint Serializable::ckptMaxCount = 0; 752287SN/Aint Serializable::ckptCount = 0; 762287SN/Aint Serializable::ckptPrevCount = -1; 7710905Sandreas.sandberg@arm.comstd::stack<std::string> Serializable::path; 782SN/A 79395SN/A///////////////////////////// 80395SN/A 81395SN/A/// Container for serializing global variables (not associated with 82395SN/A/// any serialized object). 83395SN/Aclass Globals : public Serializable 842SN/A{ 85395SN/A public: 8610905Sandreas.sandberg@arm.com Globals() 8710905Sandreas.sandberg@arm.com : unserializedCurTick(0) {} 8810905Sandreas.sandberg@arm.com 8911168Sandreas.hansson@arm.com void serialize(CheckpointOut &cp) const override; 9011168Sandreas.hansson@arm.com void unserialize(CheckpointIn &cp) override; 9110905Sandreas.sandberg@arm.com 9210905Sandreas.sandberg@arm.com Tick unserializedCurTick; 93395SN/A}; 942SN/A 95395SN/A/// The one and only instance of the Globals class. 96395SN/AGlobals globals; 972SN/A 9811077SCurtis.Dunham@arm.com/// The version tags for this build of the simulator, to be stored in the 9911077SCurtis.Dunham@arm.com/// Globals section during serialization and compared upon unserialization. 10011077SCurtis.Dunham@arm.comextern std::set<std::string> version_tags; 10111077SCurtis.Dunham@arm.com 10210905Sandreas.sandberg@arm.comvoid 10310905Sandreas.sandberg@arm.comGlobals::serialize(CheckpointOut &cp) const 1042SN/A{ 10510905Sandreas.sandberg@arm.com paramOut(cp, "curTick", curTick()); 10611077SCurtis.Dunham@arm.com SERIALIZE_CONTAINER(version_tags); 1072SN/A} 1082SN/A 1092SN/Avoid 11010905Sandreas.sandberg@arm.comGlobals::unserialize(CheckpointIn &cp) 1112SN/A{ 11210905Sandreas.sandberg@arm.com paramIn(cp, "curTick", unserializedCurTick); 11311077SCurtis.Dunham@arm.com 11411077SCurtis.Dunham@arm.com const std::string §ion(Serializable::currentSection()); 11511077SCurtis.Dunham@arm.com std::string str; 11611077SCurtis.Dunham@arm.com if (!cp.find(section, "version_tags", str)) { 11711077SCurtis.Dunham@arm.com warn("**********************************************************\n"); 11811077SCurtis.Dunham@arm.com warn("!!!! Checkpoint uses an old versioning scheme. !!!!\n"); 11911077SCurtis.Dunham@arm.com warn("Run the checkpoint upgrader (util/cpt_upgrader.py) on your " 12011077SCurtis.Dunham@arm.com "checkpoint\n"); 12111077SCurtis.Dunham@arm.com warn("**********************************************************\n"); 12211077SCurtis.Dunham@arm.com return; 12311077SCurtis.Dunham@arm.com } 12411077SCurtis.Dunham@arm.com 12511077SCurtis.Dunham@arm.com std::set<std::string> cpt_tags; 12611077SCurtis.Dunham@arm.com arrayParamIn(cp, "version_tags", cpt_tags); // UNSERIALIZE_CONTAINER 12711077SCurtis.Dunham@arm.com 12811077SCurtis.Dunham@arm.com bool err = false; 12911077SCurtis.Dunham@arm.com for (const auto& t : version_tags) { 13011077SCurtis.Dunham@arm.com if (cpt_tags.find(t) == cpt_tags.end()) { 13111077SCurtis.Dunham@arm.com // checkpoint is missing tag that this binary has 13211077SCurtis.Dunham@arm.com if (!err) { 13311077SCurtis.Dunham@arm.com warn("*****************************************************\n"); 13411077SCurtis.Dunham@arm.com warn("!!!! Checkpoint is missing the following version tags:\n"); 13511077SCurtis.Dunham@arm.com err = true; 13611077SCurtis.Dunham@arm.com } 13711077SCurtis.Dunham@arm.com warn(" %s\n", t); 13811077SCurtis.Dunham@arm.com } 13911077SCurtis.Dunham@arm.com } 14011077SCurtis.Dunham@arm.com if (err) { 14111077SCurtis.Dunham@arm.com warn("You might experience some issues when restoring and should run " 14211077SCurtis.Dunham@arm.com "the checkpoint upgrader (util/cpt_upgrader.py) on your " 14311077SCurtis.Dunham@arm.com "checkpoint\n"); 14411077SCurtis.Dunham@arm.com warn("**********************************************************\n"); 14511077SCurtis.Dunham@arm.com } 14611077SCurtis.Dunham@arm.com 14711077SCurtis.Dunham@arm.com err = false; 14811077SCurtis.Dunham@arm.com for (const auto& t : cpt_tags) { 14911077SCurtis.Dunham@arm.com if (version_tags.find(t) == version_tags.end()) { 15011077SCurtis.Dunham@arm.com // gem5 binary is missing tag that this checkpoint has 15111077SCurtis.Dunham@arm.com if (!err) { 15211077SCurtis.Dunham@arm.com warn("*****************************************************\n"); 15311077SCurtis.Dunham@arm.com warn("!!!! gem5 is missing the following version tags:\n"); 15411077SCurtis.Dunham@arm.com err = true; 15511077SCurtis.Dunham@arm.com } 15611077SCurtis.Dunham@arm.com warn(" %s\n", t); 15711077SCurtis.Dunham@arm.com } 15811077SCurtis.Dunham@arm.com } 15911077SCurtis.Dunham@arm.com if (err) { 16011077SCurtis.Dunham@arm.com warn("Running a checkpoint with incompatible version tags is not " 16111077SCurtis.Dunham@arm.com "supported. While it might work, you may experience incorrect " 16211077SCurtis.Dunham@arm.com "behavior or crashes.\n"); 16311077SCurtis.Dunham@arm.com warn("**********************************************************\n"); 16411077SCurtis.Dunham@arm.com } 1652SN/A} 1662SN/A 1675739Snate@binkert.orgSerializable::Serializable() 1685739Snate@binkert.org{ 1695739Snate@binkert.org} 1705739Snate@binkert.org 1715739Snate@binkert.orgSerializable::~Serializable() 1725739Snate@binkert.org{ 1735739Snate@binkert.org} 1745739Snate@binkert.org 1755739Snate@binkert.orgvoid 17610905Sandreas.sandberg@arm.comSerializable::serializeSection(CheckpointOut &cp, const char *name) const 1775739Snate@binkert.org{ 17810905Sandreas.sandberg@arm.com Serializable::ScopedCheckpointSection sec(cp, name); 17910905Sandreas.sandberg@arm.com serialize(cp); 1805739Snate@binkert.org} 1815739Snate@binkert.org 1825739Snate@binkert.orgvoid 18310905Sandreas.sandberg@arm.comSerializable::unserializeSection(CheckpointIn &cp, const char *name) 18410905Sandreas.sandberg@arm.com{ 18510905Sandreas.sandberg@arm.com Serializable::ScopedCheckpointSection sec(cp, name); 18610905Sandreas.sandberg@arm.com unserialize(cp); 1875739Snate@binkert.org} 1885739Snate@binkert.org 1892SN/Avoid 1906225Snate@binkert.orgSerializable::serializeAll(const string &cpt_dir) 1912SN/A{ 19210905Sandreas.sandberg@arm.com string dir = CheckpointIn::setDir(cpt_dir); 193363SN/A if (mkdir(dir.c_str(), 0775) == -1 && errno != EEXIST) 194449SN/A fatal("couldn't mkdir %s\n", dir); 195363SN/A 19610905Sandreas.sandberg@arm.com string cpt_file = dir + CheckpointIn::baseFilename; 197395SN/A ofstream outstream(cpt_file.c_str()); 1982SN/A time_t t = time(NULL); 1995581Ssaidi@eecs.umich.edu if (!outstream.is_open()) 2005581Ssaidi@eecs.umich.edu fatal("Unable to open file %s for writing\n", cpt_file.c_str()); 2016818SLisa.Hsu@amd.com outstream << "## checkpoint generated: " << ctime(&t); 2022SN/A 20310905Sandreas.sandberg@arm.com globals.serializeSection(outstream, "Globals"); 20410905Sandreas.sandberg@arm.com 205395SN/A SimObject::serializeAll(outstream); 206395SN/A} 2072SN/A 2082797Sktlim@umich.eduvoid 20910905Sandreas.sandberg@arm.comSerializable::unserializeGlobals(CheckpointIn &cp) 210395SN/A{ 21110905Sandreas.sandberg@arm.com globals.unserializeSection(cp, "Globals"); 21210905Sandreas.sandberg@arm.com 21311072Sandreas.sandberg@arm.com for (uint32_t i = 0; i < numMainEventQueues; ++i) 21410905Sandreas.sandberg@arm.com mainEventQueue[i]->setCurTick(globals.unserializedCurTick); 21510905Sandreas.sandberg@arm.com} 21610905Sandreas.sandberg@arm.com 21710905Sandreas.sandberg@arm.comSerializable::ScopedCheckpointSection::~ScopedCheckpointSection() 21810905Sandreas.sandberg@arm.com{ 21910905Sandreas.sandberg@arm.com assert(!path.empty()); 22010905Sandreas.sandberg@arm.com DPRINTF(Checkpoint, "Popping: %s\n", path.top()); 22110905Sandreas.sandberg@arm.com path.pop(); 22210905Sandreas.sandberg@arm.com} 22310905Sandreas.sandberg@arm.com 22410905Sandreas.sandberg@arm.comvoid 22510905Sandreas.sandberg@arm.comSerializable::ScopedCheckpointSection::pushName(const char *obj_name) 22610905Sandreas.sandberg@arm.com{ 22710905Sandreas.sandberg@arm.com if (path.empty()) { 22810905Sandreas.sandberg@arm.com path.push(obj_name); 22910905Sandreas.sandberg@arm.com } else { 23010905Sandreas.sandberg@arm.com path.push(csprintf("%s.%s", path.top(), obj_name)); 23110905Sandreas.sandberg@arm.com } 23210905Sandreas.sandberg@arm.com DPRINTF(Checkpoint, "ScopedCheckpointSection::pushName: %s\n", obj_name); 23310905Sandreas.sandberg@arm.com} 23410905Sandreas.sandberg@arm.com 23510905Sandreas.sandberg@arm.comvoid 23610905Sandreas.sandberg@arm.comSerializable::ScopedCheckpointSection::nameOut(CheckpointOut &cp) 23710905Sandreas.sandberg@arm.com{ 23810905Sandreas.sandberg@arm.com DPRINTF(Checkpoint, "ScopedCheckpointSection::nameOut: %s\n", 23910905Sandreas.sandberg@arm.com Serializable::currentSection()); 24010905Sandreas.sandberg@arm.com cp << "\n[" << Serializable::currentSection() << "]\n"; 241395SN/A} 2422SN/A 24310905Sandreas.sandberg@arm.comconst std::string & 24410905Sandreas.sandberg@arm.comSerializable::currentSection() 24510905Sandreas.sandberg@arm.com{ 24610905Sandreas.sandberg@arm.com assert(!path.empty()); 24710905Sandreas.sandberg@arm.com 24810905Sandreas.sandberg@arm.com return path.top(); 24910905Sandreas.sandberg@arm.com} 250237SN/A 25110905Sandreas.sandberg@arm.comconst char *CheckpointIn::baseFilename = "m5.cpt"; 2527491Ssteve.reinhardt@amd.com 25310905Sandreas.sandberg@arm.comstring CheckpointIn::currentDirectory; 2547491Ssteve.reinhardt@amd.com 2557491Ssteve.reinhardt@amd.comstring 25610905Sandreas.sandberg@arm.comCheckpointIn::setDir(const string &name) 2577491Ssteve.reinhardt@amd.com{ 2587823Ssteve.reinhardt@amd.com // use csprintf to insert curTick() into directory name if it 2597491Ssteve.reinhardt@amd.com // appears to have a format placeholder in it. 2607491Ssteve.reinhardt@amd.com currentDirectory = (name.find("%") != string::npos) ? 2617823Ssteve.reinhardt@amd.com csprintf(name, curTick()) : name; 2627491Ssteve.reinhardt@amd.com if (currentDirectory[currentDirectory.size() - 1] != '/') 2637491Ssteve.reinhardt@amd.com currentDirectory += "/"; 2647491Ssteve.reinhardt@amd.com return currentDirectory; 2657491Ssteve.reinhardt@amd.com} 2667491Ssteve.reinhardt@amd.com 2677491Ssteve.reinhardt@amd.comstring 26810905Sandreas.sandberg@arm.comCheckpointIn::dir() 2697491Ssteve.reinhardt@amd.com{ 2707491Ssteve.reinhardt@amd.com return currentDirectory; 2717491Ssteve.reinhardt@amd.com} 2727491Ssteve.reinhardt@amd.com 27310905Sandreas.sandberg@arm.comCheckpointIn::CheckpointIn(const string &cpt_dir, SimObjectResolver &resolver) 27410453SAndrew.Bardsley@arm.com : db(new IniFile), objNameResolver(resolver), cptDir(setDir(cpt_dir)) 275237SN/A{ 27610905Sandreas.sandberg@arm.com string filename = cptDir + "/" + CheckpointIn::baseFilename; 277237SN/A if (!db->load(filename)) { 278237SN/A fatal("Can't load checkpoint file '%s'\n", filename); 279237SN/A } 280237SN/A} 281237SN/A 28210905Sandreas.sandberg@arm.comCheckpointIn::~CheckpointIn() 2839086Sandreas.hansson@arm.com{ 2849086Sandreas.hansson@arm.com delete db; 2859086Sandreas.hansson@arm.com} 286237SN/A 287237SN/Abool 28811655Sandreas.sandberg@arm.comCheckpointIn::entryExists(const string §ion, const string &entry) 28911655Sandreas.sandberg@arm.com{ 29011655Sandreas.sandberg@arm.com return db->entryExists(section, entry); 29111655Sandreas.sandberg@arm.com} 29211655Sandreas.sandberg@arm.com 29311655Sandreas.sandberg@arm.combool 29410905Sandreas.sandberg@arm.comCheckpointIn::find(const string §ion, const string &entry, string &value) 295237SN/A{ 296237SN/A return db->find(section, entry, value); 297237SN/A} 298237SN/A 299237SN/Abool 30010905Sandreas.sandberg@arm.comCheckpointIn::findObj(const string §ion, const string &entry, 3014000Ssaidi@eecs.umich.edu SimObject *&value) 302237SN/A{ 303237SN/A string path; 304237SN/A 305237SN/A if (!db->find(section, entry, path)) 306237SN/A return false; 307237SN/A 30810453SAndrew.Bardsley@arm.com value = objNameResolver.resolveSimObject(path); 3094000Ssaidi@eecs.umich.edu return true; 310237SN/A} 311304SN/A 312304SN/Abool 31310905Sandreas.sandberg@arm.comCheckpointIn::sectionExists(const string §ion) 314304SN/A{ 315304SN/A return db->sectionExists(section); 316304SN/A} 31713414Sgiacomo.travaglini@arm.com 31813414Sgiacomo.travaglini@arm.comvoid 31913414Sgiacomo.travaglini@arm.comobjParamIn(CheckpointIn &cp, const string &name, SimObject * ¶m) 32013414Sgiacomo.travaglini@arm.com{ 32113414Sgiacomo.travaglini@arm.com const string §ion(Serializable::currentSection()); 32213414Sgiacomo.travaglini@arm.com if (!cp.findObj(section, name, param)) { 32313414Sgiacomo.travaglini@arm.com fatal("Can't unserialize '%s:%s'\n", section, name); 32413414Sgiacomo.travaglini@arm.com } 32513414Sgiacomo.travaglini@arm.com} 32613414Sgiacomo.travaglini@arm.com 32713414Sgiacomo.travaglini@arm.comvoid 32813414Sgiacomo.travaglini@arm.comdebug_serialize(const string &cpt_dir) 32913414Sgiacomo.travaglini@arm.com{ 33013414Sgiacomo.travaglini@arm.com Serializable::serializeAll(cpt_dir); 33113414Sgiacomo.travaglini@arm.com} 332