serialize.cc revision 13414
1/* 2 * Copyright (c) 2015 ARM Limited 3 * All rights reserved 4 * 5 * The license below extends only to copyright in the software and shall 6 * not be construed as granting a license to any other intellectual 7 * property including but not limited to intellectual property relating 8 * to a hardware implementation of the functionality of the software 9 * licensed hereunder. You may use the software subject to the license 10 * terms below provided that you ensure that this notice is replicated 11 * unmodified and in its entirety in all distributions of the software, 12 * modified or unmodified, in source code or in binary form. 13 * 14 * Copyright (c) 2002-2005 The Regents of The University of Michigan 15 * Copyright (c) 2013 Advanced Micro Devices, Inc. 16 * Copyright (c) 2013 Mark D. Hill and David A. Wood 17 * All rights reserved. 18 * 19 * Redistribution and use in source and binary forms, with or without 20 * modification, are permitted provided that the following conditions are 21 * met: redistributions of source code must retain the above copyright 22 * notice, this list of conditions and the following disclaimer; 23 * redistributions in binary form must reproduce the above copyright 24 * notice, this list of conditions and the following disclaimer in the 25 * documentation and/or other materials provided with the distribution; 26 * neither the name of the copyright holders nor the names of its 27 * contributors may be used to endorse or promote products derived from 28 * this software without specific prior written permission. 29 * 30 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 31 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 32 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 33 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 34 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 35 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 36 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 37 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 38 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 39 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 40 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 41 * 42 * Authors: Nathan Binkert 43 * Erik Hallnor 44 * Steve Reinhardt 45 * Andreas Sandberg 46 */ 47 48#include "sim/serialize.hh" 49 50#include <sys/stat.h> 51#include <sys/time.h> 52#include <sys/types.h> 53 54#include <cerrno> 55#include <fstream> 56#include <list> 57#include <string> 58#include <vector> 59 60#include "base/inifile.hh" 61#include "base/output.hh" 62#include "base/trace.hh" 63#include "debug/Checkpoint.hh" 64#include "sim/eventq.hh" 65#include "sim/sim_events.hh" 66#include "sim/sim_exit.hh" 67#include "sim/sim_object.hh" 68 69// For stat reset hack 70#include "sim/stat_control.hh" 71 72using namespace std; 73 74int Serializable::ckptMaxCount = 0; 75int Serializable::ckptCount = 0; 76int Serializable::ckptPrevCount = -1; 77std::stack<std::string> Serializable::path; 78 79///////////////////////////// 80 81/// Container for serializing global variables (not associated with 82/// any serialized object). 83class Globals : public Serializable 84{ 85 public: 86 Globals() 87 : unserializedCurTick(0) {} 88 89 void serialize(CheckpointOut &cp) const override; 90 void unserialize(CheckpointIn &cp) override; 91 92 Tick unserializedCurTick; 93}; 94 95/// The one and only instance of the Globals class. 96Globals globals; 97 98/// The version tags for this build of the simulator, to be stored in the 99/// Globals section during serialization and compared upon unserialization. 100extern std::set<std::string> version_tags; 101 102void 103Globals::serialize(CheckpointOut &cp) const 104{ 105 paramOut(cp, "curTick", curTick()); 106 SERIALIZE_CONTAINER(version_tags); 107} 108 109void 110Globals::unserialize(CheckpointIn &cp) 111{ 112 paramIn(cp, "curTick", unserializedCurTick); 113 114 const std::string §ion(Serializable::currentSection()); 115 std::string str; 116 if (!cp.find(section, "version_tags", str)) { 117 warn("**********************************************************\n"); 118 warn("!!!! Checkpoint uses an old versioning scheme. !!!!\n"); 119 warn("Run the checkpoint upgrader (util/cpt_upgrader.py) on your " 120 "checkpoint\n"); 121 warn("**********************************************************\n"); 122 return; 123 } 124 125 std::set<std::string> cpt_tags; 126 arrayParamIn(cp, "version_tags", cpt_tags); // UNSERIALIZE_CONTAINER 127 128 bool err = false; 129 for (const auto& t : version_tags) { 130 if (cpt_tags.find(t) == cpt_tags.end()) { 131 // checkpoint is missing tag that this binary has 132 if (!err) { 133 warn("*****************************************************\n"); 134 warn("!!!! Checkpoint is missing the following version tags:\n"); 135 err = true; 136 } 137 warn(" %s\n", t); 138 } 139 } 140 if (err) { 141 warn("You might experience some issues when restoring and should run " 142 "the checkpoint upgrader (util/cpt_upgrader.py) on your " 143 "checkpoint\n"); 144 warn("**********************************************************\n"); 145 } 146 147 err = false; 148 for (const auto& t : cpt_tags) { 149 if (version_tags.find(t) == version_tags.end()) { 150 // gem5 binary is missing tag that this checkpoint has 151 if (!err) { 152 warn("*****************************************************\n"); 153 warn("!!!! gem5 is missing the following version tags:\n"); 154 err = true; 155 } 156 warn(" %s\n", t); 157 } 158 } 159 if (err) { 160 warn("Running a checkpoint with incompatible version tags is not " 161 "supported. While it might work, you may experience incorrect " 162 "behavior or crashes.\n"); 163 warn("**********************************************************\n"); 164 } 165} 166 167Serializable::Serializable() 168{ 169} 170 171Serializable::~Serializable() 172{ 173} 174 175void 176Serializable::serializeSection(CheckpointOut &cp, const char *name) const 177{ 178 Serializable::ScopedCheckpointSection sec(cp, name); 179 serialize(cp); 180} 181 182void 183Serializable::unserializeSection(CheckpointIn &cp, const char *name) 184{ 185 Serializable::ScopedCheckpointSection sec(cp, name); 186 unserialize(cp); 187} 188 189void 190Serializable::serializeAll(const string &cpt_dir) 191{ 192 string dir = CheckpointIn::setDir(cpt_dir); 193 if (mkdir(dir.c_str(), 0775) == -1 && errno != EEXIST) 194 fatal("couldn't mkdir %s\n", dir); 195 196 string cpt_file = dir + CheckpointIn::baseFilename; 197 ofstream outstream(cpt_file.c_str()); 198 time_t t = time(NULL); 199 if (!outstream.is_open()) 200 fatal("Unable to open file %s for writing\n", cpt_file.c_str()); 201 outstream << "## checkpoint generated: " << ctime(&t); 202 203 globals.serializeSection(outstream, "Globals"); 204 205 SimObject::serializeAll(outstream); 206} 207 208void 209Serializable::unserializeGlobals(CheckpointIn &cp) 210{ 211 globals.unserializeSection(cp, "Globals"); 212 213 for (uint32_t i = 0; i < numMainEventQueues; ++i) 214 mainEventQueue[i]->setCurTick(globals.unserializedCurTick); 215} 216 217Serializable::ScopedCheckpointSection::~ScopedCheckpointSection() 218{ 219 assert(!path.empty()); 220 DPRINTF(Checkpoint, "Popping: %s\n", path.top()); 221 path.pop(); 222} 223 224void 225Serializable::ScopedCheckpointSection::pushName(const char *obj_name) 226{ 227 if (path.empty()) { 228 path.push(obj_name); 229 } else { 230 path.push(csprintf("%s.%s", path.top(), obj_name)); 231 } 232 DPRINTF(Checkpoint, "ScopedCheckpointSection::pushName: %s\n", obj_name); 233} 234 235void 236Serializable::ScopedCheckpointSection::nameOut(CheckpointOut &cp) 237{ 238 DPRINTF(Checkpoint, "ScopedCheckpointSection::nameOut: %s\n", 239 Serializable::currentSection()); 240 cp << "\n[" << Serializable::currentSection() << "]\n"; 241} 242 243const std::string & 244Serializable::currentSection() 245{ 246 assert(!path.empty()); 247 248 return path.top(); 249} 250 251const char *CheckpointIn::baseFilename = "m5.cpt"; 252 253string CheckpointIn::currentDirectory; 254 255string 256CheckpointIn::setDir(const string &name) 257{ 258 // use csprintf to insert curTick() into directory name if it 259 // appears to have a format placeholder in it. 260 currentDirectory = (name.find("%") != string::npos) ? 261 csprintf(name, curTick()) : name; 262 if (currentDirectory[currentDirectory.size() - 1] != '/') 263 currentDirectory += "/"; 264 return currentDirectory; 265} 266 267string 268CheckpointIn::dir() 269{ 270 return currentDirectory; 271} 272 273CheckpointIn::CheckpointIn(const string &cpt_dir, SimObjectResolver &resolver) 274 : db(new IniFile), objNameResolver(resolver), cptDir(setDir(cpt_dir)) 275{ 276 string filename = cptDir + "/" + CheckpointIn::baseFilename; 277 if (!db->load(filename)) { 278 fatal("Can't load checkpoint file '%s'\n", filename); 279 } 280} 281 282CheckpointIn::~CheckpointIn() 283{ 284 delete db; 285} 286 287bool 288CheckpointIn::entryExists(const string §ion, const string &entry) 289{ 290 return db->entryExists(section, entry); 291} 292 293bool 294CheckpointIn::find(const string §ion, const string &entry, string &value) 295{ 296 return db->find(section, entry, value); 297} 298 299bool 300CheckpointIn::findObj(const string §ion, const string &entry, 301 SimObject *&value) 302{ 303 string path; 304 305 if (!db->find(section, entry, path)) 306 return false; 307 308 value = objNameResolver.resolveSimObject(path); 309 return true; 310} 311 312bool 313CheckpointIn::sectionExists(const string §ion) 314{ 315 return db->sectionExists(section); 316} 317 318void 319objParamIn(CheckpointIn &cp, const string &name, SimObject * ¶m) 320{ 321 const string §ion(Serializable::currentSection()); 322 if (!cp.findObj(section, name, param)) { 323 fatal("Can't unserialize '%s:%s'\n", section, name); 324 } 325} 326 327void 328debug_serialize(const string &cpt_dir) 329{ 330 Serializable::serializeAll(cpt_dir); 331} 332