serialize.cc revision 2868:6a7e69fa92d3
1/* 2 * Copyright (c) 2002-2005 The Regents of The University of Michigan 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Authors: Nathan Binkert 29 * Erik Hallnor 30 * Steve Reinhardt 31 */ 32 33#include <sys/time.h> 34#include <sys/types.h> 35#include <sys/stat.h> 36#include <errno.h> 37 38#include <fstream> 39#include <list> 40#include <string> 41#include <vector> 42 43#include "base/inifile.hh" 44#include "base/misc.hh" 45#include "base/output.hh" 46#include "base/str.hh" 47#include "base/trace.hh" 48#include "sim/eventq.hh" 49#include "sim/param.hh" 50#include "sim/serialize.hh" 51#include "sim/sim_events.hh" 52#include "sim/sim_exit.hh" 53#include "sim/sim_object.hh" 54 55using namespace std; 56 57int Serializable::ckptMaxCount = 0; 58int Serializable::ckptCount = 0; 59int Serializable::ckptPrevCount = -1; 60 61void 62Serializable::nameOut(ostream &os) 63{ 64 os << "\n[" << name() << "]\n"; 65} 66 67void 68Serializable::nameOut(ostream &os, const string &_name) 69{ 70 os << "\n[" << _name << "]\n"; 71} 72 73template <class T> 74void 75paramOut(ostream &os, const std::string &name, const T ¶m) 76{ 77 os << name << "="; 78 showParam(os, param); 79 os << "\n"; 80} 81 82 83template <class T> 84void 85paramIn(Checkpoint *cp, const std::string §ion, 86 const std::string &name, T ¶m) 87{ 88 std::string str; 89 if (!cp->find(section, name, str) || !parseParam(str, param)) { 90 fatal("Can't unserialize '%s:%s'\n", section, name); 91 } 92} 93 94 95template <class T> 96void 97arrayParamOut(ostream &os, const std::string &name, 98 const T *param, int size) 99{ 100 os << name << "="; 101 if (size > 0) 102 showParam(os, param[0]); 103 for (int i = 1; i < size; ++i) { 104 os << " "; 105 showParam(os, param[i]); 106 } 107 os << "\n"; 108} 109 110 111template <class T> 112void 113arrayParamIn(Checkpoint *cp, const std::string §ion, 114 const std::string &name, T *param, int size) 115{ 116 std::string str; 117 if (!cp->find(section, name, str)) { 118 fatal("Can't unserialize '%s:%s'\n", section, name); 119 } 120 121 // code below stolen from VectorParam<T>::parse(). 122 // it would be nice to unify these somehow... 123 124 vector<string> tokens; 125 126 tokenize(tokens, str, ' '); 127 128 // Need this if we were doing a vector 129 // value.resize(tokens.size()); 130 131 if (tokens.size() != size) { 132 fatal("Array size mismatch on %s:%s'\n", section, name); 133 } 134 135 for (int i = 0; i < tokens.size(); i++) { 136 // need to parse into local variable to handle vector<bool>, 137 // for which operator[] returns a special reference class 138 // that's not the same as 'bool&', (since it's a packed 139 // vector) 140 T scalar_value; 141 if (!parseParam(tokens[i], scalar_value)) { 142 string err("could not parse \""); 143 144 err += str; 145 err += "\""; 146 147 fatal(err); 148 } 149 150 // assign parsed value to vector 151 param[i] = scalar_value; 152 } 153} 154 155 156void 157objParamIn(Checkpoint *cp, const std::string §ion, 158 const std::string &name, Serializable * ¶m) 159{ 160 if (!cp->findObj(section, name, param)) { 161 fatal("Can't unserialize '%s:%s'\n", section, name); 162 } 163} 164 165 166#define INSTANTIATE_PARAM_TEMPLATES(type) \ 167template void \ 168paramOut(ostream &os, const std::string &name, type const ¶m); \ 169template void \ 170paramIn(Checkpoint *cp, const std::string §ion, \ 171 const std::string &name, type & param); \ 172template void \ 173arrayParamOut(ostream &os, const std::string &name, \ 174 type const *param, int size); \ 175template void \ 176arrayParamIn(Checkpoint *cp, const std::string §ion, \ 177 const std::string &name, type *param, int size); 178 179INSTANTIATE_PARAM_TEMPLATES(signed char) 180INSTANTIATE_PARAM_TEMPLATES(unsigned char) 181INSTANTIATE_PARAM_TEMPLATES(signed short) 182INSTANTIATE_PARAM_TEMPLATES(unsigned short) 183INSTANTIATE_PARAM_TEMPLATES(signed int) 184INSTANTIATE_PARAM_TEMPLATES(unsigned int) 185INSTANTIATE_PARAM_TEMPLATES(signed long) 186INSTANTIATE_PARAM_TEMPLATES(unsigned long) 187INSTANTIATE_PARAM_TEMPLATES(signed long long) 188INSTANTIATE_PARAM_TEMPLATES(unsigned long long) 189INSTANTIATE_PARAM_TEMPLATES(bool) 190INSTANTIATE_PARAM_TEMPLATES(string) 191 192 193///////////////////////////// 194 195/// Container for serializing global variables (not associated with 196/// any serialized object). 197class Globals : public Serializable 198{ 199 public: 200 const string name() const; 201 void serialize(ostream &os); 202 void unserialize(Checkpoint *cp); 203}; 204 205/// The one and only instance of the Globals class. 206Globals globals; 207 208const string 209Globals::name() const 210{ 211 return "Globals"; 212} 213 214void 215Globals::serialize(ostream &os) 216{ 217 nameOut(os); 218 SERIALIZE_SCALAR(curTick); 219 220 nameOut(os, "MainEventQueue"); 221 mainEventQueue.serialize(os); 222} 223 224void 225Globals::unserialize(Checkpoint *cp) 226{ 227 const string §ion = name(); 228 UNSERIALIZE_SCALAR(curTick); 229 230 mainEventQueue.unserialize(cp, "MainEventQueue"); 231} 232 233void 234Serializable::serializeAll(const std::string &cpt_dir) 235{ 236 setCheckpointDir(cpt_dir); 237 string dir = Checkpoint::dir(); 238 if (mkdir(dir.c_str(), 0775) == -1 && errno != EEXIST) 239 fatal("couldn't mkdir %s\n", dir); 240 241 string cpt_file = dir + Checkpoint::baseFilename; 242 ofstream outstream(cpt_file.c_str()); 243 time_t t = time(NULL); 244 outstream << "// checkpoint generated: " << ctime(&t); 245 246 globals.serialize(outstream); 247 SimObject::serializeAll(outstream); 248} 249 250void 251Serializable::unserializeAll(const std::string &cpt_dir) 252{ 253 setCheckpointDir(cpt_dir); 254 string dir = Checkpoint::dir(); 255 string cpt_file = dir + Checkpoint::baseFilename; 256 string section = ""; 257 258 DPRINTFR(Config, "Loading checkpoint dir '%s'\n", 259 dir); 260 Checkpoint *cp = new Checkpoint(dir, section); 261 unserializeGlobals(cp); 262 263 SimObject::unserializeAll(cp); 264} 265 266void 267Serializable::unserializeGlobals(Checkpoint *cp) 268{ 269 globals.unserialize(cp); 270} 271 272const char *Checkpoint::baseFilename = "m5.cpt"; 273 274static string checkpointDirBase; 275 276void 277setCheckpointDir(const std::string &name) 278{ 279 checkpointDirBase = name; 280 if (checkpointDirBase[checkpointDirBase.size() - 1] != '/') 281 checkpointDirBase += "/"; 282} 283 284string 285Checkpoint::dir() 286{ 287 // use csprintf to insert curTick into directory name if it 288 // appears to have a format placeholder in it. 289 return (checkpointDirBase.find("%") != string::npos) ? 290 csprintf(checkpointDirBase, curTick) : checkpointDirBase; 291} 292 293void 294debug_serialize(const std::string &cpt_dir) 295{ 296 Serializable::serializeAll(cpt_dir); 297} 298 299 300//////////////////////////////////////////////////////////////////////// 301// 302// SerializableClass member definitions 303// 304//////////////////////////////////////////////////////////////////////// 305 306// Map of class names to SerializableBuilder creation functions. 307// Need to make this a pointer so we can force initialization on the 308// first reference; otherwise, some SerializableClass constructors 309// may be invoked before the classMap constructor. 310map<string,SerializableClass::CreateFunc> *SerializableClass::classMap = 0; 311 312// SerializableClass constructor: add mapping to classMap 313SerializableClass::SerializableClass(const string &className, 314 CreateFunc createFunc) 315{ 316 if (classMap == NULL) 317 classMap = new map<string,SerializableClass::CreateFunc>(); 318 319 if ((*classMap)[className]) 320 { 321 cerr << "Error: simulation object class " << className << " redefined" 322 << endl; 323 fatal(""); 324 } 325 326 // add className --> createFunc to class map 327 (*classMap)[className] = createFunc; 328} 329 330 331// 332// 333Serializable * 334SerializableClass::createObject(Checkpoint *cp, 335 const std::string §ion) 336{ 337 string className; 338 339 if (!cp->find(section, "type", className)) { 340 fatal("Serializable::create: no 'type' entry in section '%s'.\n", 341 section); 342 } 343 344 CreateFunc createFunc = (*classMap)[className]; 345 346 if (createFunc == NULL) { 347 fatal("Serializable::create: no create function for class '%s'.\n", 348 className); 349 } 350 351 Serializable *object = createFunc(cp, section); 352 353 assert(object != NULL); 354 355 return object; 356} 357 358 359Serializable * 360Serializable::create(Checkpoint *cp, const std::string §ion) 361{ 362 Serializable *object = SerializableClass::createObject(cp, section); 363 object->unserialize(cp, section); 364 return object; 365} 366 367 368Checkpoint::Checkpoint(const std::string &cpt_dir, const std::string &path) 369 : db(new IniFile), basePath(path), cptDir(cpt_dir) 370{ 371 string filename = cpt_dir + "/" + Checkpoint::baseFilename; 372 if (!db->load(filename)) { 373 fatal("Can't load checkpoint file '%s'\n", filename); 374 } 375} 376 377 378bool 379Checkpoint::find(const std::string §ion, const std::string &entry, 380 std::string &value) 381{ 382 return db->find(section, entry, value); 383} 384 385 386bool 387Checkpoint::findObj(const std::string §ion, const std::string &entry, 388 Serializable *&value) 389{ 390 string path; 391 392 if (!db->find(section, entry, path)) 393 return false; 394 395 if ((value = objMap[path]) != NULL) 396 return true; 397 398 return false; 399} 400 401 402bool 403Checkpoint::sectionExists(const std::string §ion) 404{ 405 return db->sectionExists(section); 406} 407