serialize.cc revision 1638
15086Sgblack@eecs.umich.edu/* 25086Sgblack@eecs.umich.edu * Copyright (c) 2002-2004 The Regents of The University of Michigan 35086Sgblack@eecs.umich.edu * All rights reserved. 45086Sgblack@eecs.umich.edu * 57087Snate@binkert.org * Redistribution and use in source and binary forms, with or without 67087Snate@binkert.org * modification, are permitted provided that the following conditions are 77087Snate@binkert.org * met: redistributions of source code must retain the above copyright 87087Snate@binkert.org * notice, this list of conditions and the following disclaimer; 97087Snate@binkert.org * redistributions in binary form must reproduce the above copyright 107087Snate@binkert.org * notice, this list of conditions and the following disclaimer in the 117087Snate@binkert.org * documentation and/or other materials provided with the distribution; 127087Snate@binkert.org * neither the name of the copyright holders nor the names of its 135086Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from 147087Snate@binkert.org * this software without specific prior written permission. 157087Snate@binkert.org * 167087Snate@binkert.org * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 177087Snate@binkert.org * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 187087Snate@binkert.org * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 197087Snate@binkert.org * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 207087Snate@binkert.org * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 217087Snate@binkert.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 225086Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 237087Snate@binkert.org * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 245086Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 255086Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 265086Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 275086Sgblack@eecs.umich.edu */ 285086Sgblack@eecs.umich.edu 295086Sgblack@eecs.umich.edu#include <sys/time.h> 305086Sgblack@eecs.umich.edu#include <sys/types.h> 315086Sgblack@eecs.umich.edu#include <sys/stat.h> 325086Sgblack@eecs.umich.edu#include <errno.h> 335086Sgblack@eecs.umich.edu 345086Sgblack@eecs.umich.edu#include <fstream> 355086Sgblack@eecs.umich.edu#include <list> 365086Sgblack@eecs.umich.edu#include <string> 375086Sgblack@eecs.umich.edu#include <vector> 385086Sgblack@eecs.umich.edu 395086Sgblack@eecs.umich.edu#include "base/inifile.hh" 405647Sgblack@eecs.umich.edu#include "base/misc.hh" 415647Sgblack@eecs.umich.edu#include "base/output.hh" 425647Sgblack@eecs.umich.edu#include "base/str.hh" 435647Sgblack@eecs.umich.edu#include "base/trace.hh" 445647Sgblack@eecs.umich.edu#include "sim/config_node.hh" 457629Sgblack@eecs.umich.edu#include "sim/eventq.hh" 467629Sgblack@eecs.umich.edu#include "sim/param.hh" 477629Sgblack@eecs.umich.edu#include "sim/serialize.hh" 485086Sgblack@eecs.umich.edu#include "sim/sim_events.hh" 495135Sgblack@eecs.umich.edu#include "sim/sim_exit.hh" 505647Sgblack@eecs.umich.edu#include "sim/sim_object.hh" 515234Sgblack@eecs.umich.edu 525086Sgblack@eecs.umich.eduusing namespace std; 535086Sgblack@eecs.umich.edu 545086Sgblack@eecs.umich.eduint Serializable::maxCount; 557693SAli.Saidi@ARM.comint Serializable::count; 565086Sgblack@eecs.umich.edu 575086Sgblack@eecs.umich.eduvoid 585086Sgblack@eecs.umich.eduSerializable::nameOut(ostream &os) 595086Sgblack@eecs.umich.edu{ 605086Sgblack@eecs.umich.edu os << "\n[" << name() << "]\n"; 615086Sgblack@eecs.umich.edu} 625086Sgblack@eecs.umich.edu 635135Sgblack@eecs.umich.eduvoid 645135Sgblack@eecs.umich.eduSerializable::nameOut(ostream &os, const string &_name) 655135Sgblack@eecs.umich.edu{ 665135Sgblack@eecs.umich.edu os << "\n[" << _name << "]\n"; 676048Sgblack@eecs.umich.edu} 686048Sgblack@eecs.umich.edu 696048Sgblack@eecs.umich.edutemplate <class T> 706048Sgblack@eecs.umich.eduvoid 716048Sgblack@eecs.umich.eduparamOut(ostream &os, const std::string &name, const T ¶m) 726048Sgblack@eecs.umich.edu{ 736048Sgblack@eecs.umich.edu os << name << "="; 746048Sgblack@eecs.umich.edu showParam(os, param); 755135Sgblack@eecs.umich.edu os << "\n"; 765135Sgblack@eecs.umich.edu} 775135Sgblack@eecs.umich.edu 785135Sgblack@eecs.umich.edu 795135Sgblack@eecs.umich.edutemplate <class T> 805135Sgblack@eecs.umich.eduvoid 815135Sgblack@eecs.umich.eduparamIn(Checkpoint *cp, const std::string §ion, 825135Sgblack@eecs.umich.edu const std::string &name, T ¶m) 835135Sgblack@eecs.umich.edu{ 845135Sgblack@eecs.umich.edu std::string str; 855135Sgblack@eecs.umich.edu if (!cp->find(section, name, str) || !parseParam(str, param)) { 865135Sgblack@eecs.umich.edu fatal("Can't unserialize '%s:%s'\n", section, name); 875135Sgblack@eecs.umich.edu } 885135Sgblack@eecs.umich.edu} 895135Sgblack@eecs.umich.edu 905135Sgblack@eecs.umich.edu 915135Sgblack@eecs.umich.edutemplate <class T> 925264Sgblack@eecs.umich.eduvoid 935135Sgblack@eecs.umich.eduarrayParamOut(ostream &os, const std::string &name, 945135Sgblack@eecs.umich.edu const T *param, int size) 955135Sgblack@eecs.umich.edu{ 965135Sgblack@eecs.umich.edu os << name << "="; 975141Sgblack@eecs.umich.edu if (size > 0) 985141Sgblack@eecs.umich.edu showParam(os, param[0]); 995141Sgblack@eecs.umich.edu for (int i = 1; i < size; ++i) { 1005141Sgblack@eecs.umich.edu os << " "; 1015141Sgblack@eecs.umich.edu showParam(os, param[i]); 1025141Sgblack@eecs.umich.edu } 1035141Sgblack@eecs.umich.edu os << "\n"; 1045141Sgblack@eecs.umich.edu} 1055141Sgblack@eecs.umich.edu 1065182Sgblack@eecs.umich.edu 1075141Sgblack@eecs.umich.edutemplate <class T> 1085141Sgblack@eecs.umich.eduvoid 1095141Sgblack@eecs.umich.eduarrayParamIn(Checkpoint *cp, const std::string §ion, 1105141Sgblack@eecs.umich.edu const std::string &name, T *param, int size) 1115141Sgblack@eecs.umich.edu{ 1125141Sgblack@eecs.umich.edu std::string str; 1135135Sgblack@eecs.umich.edu if (!cp->find(section, name, str)) { 1145141Sgblack@eecs.umich.edu fatal("Can't unserialize '%s:%s'\n", section, name); 1155141Sgblack@eecs.umich.edu } 1165141Sgblack@eecs.umich.edu 1175141Sgblack@eecs.umich.edu // code below stolen from VectorParam<T>::parse(). 1185141Sgblack@eecs.umich.edu // it would be nice to unify these somehow... 1195141Sgblack@eecs.umich.edu 1205141Sgblack@eecs.umich.edu vector<string> tokens; 1215141Sgblack@eecs.umich.edu 1225141Sgblack@eecs.umich.edu tokenize(tokens, str, ' '); 1235141Sgblack@eecs.umich.edu 1245141Sgblack@eecs.umich.edu // Need this if we were doing a vector 1255141Sgblack@eecs.umich.edu // value.resize(tokens.size()); 1265135Sgblack@eecs.umich.edu 1275141Sgblack@eecs.umich.edu if (tokens.size() != size) { 1285141Sgblack@eecs.umich.edu fatal("Array size mismatch on %s:%s'\n", section, name); 1295135Sgblack@eecs.umich.edu } 1305141Sgblack@eecs.umich.edu 1315141Sgblack@eecs.umich.edu for (int i = 0; i < tokens.size(); i++) { 1325141Sgblack@eecs.umich.edu // need to parse into local variable to handle vector<bool>, 1335141Sgblack@eecs.umich.edu // for which operator[] returns a special reference class 1345135Sgblack@eecs.umich.edu // that's not the same as 'bool&', (since it's a packed 1355141Sgblack@eecs.umich.edu // vector) 1365141Sgblack@eecs.umich.edu T scalar_value; 1375141Sgblack@eecs.umich.edu if (!parseParam(tokens[i], scalar_value)) { 1385141Sgblack@eecs.umich.edu string err("could not parse \""); 1395141Sgblack@eecs.umich.edu 1405141Sgblack@eecs.umich.edu err += str; 1415141Sgblack@eecs.umich.edu err += "\""; 1425141Sgblack@eecs.umich.edu 1435141Sgblack@eecs.umich.edu fatal(err); 1445141Sgblack@eecs.umich.edu } 1455141Sgblack@eecs.umich.edu 1465141Sgblack@eecs.umich.edu // assign parsed value to vector 1475264Sgblack@eecs.umich.edu param[i] = scalar_value; 1485141Sgblack@eecs.umich.edu } 1495141Sgblack@eecs.umich.edu} 1505141Sgblack@eecs.umich.edu 1515141Sgblack@eecs.umich.edu 1525141Sgblack@eecs.umich.eduvoid 1535141Sgblack@eecs.umich.eduobjParamIn(Checkpoint *cp, const std::string §ion, 1545141Sgblack@eecs.umich.edu const std::string &name, Serializable * ¶m) 1555141Sgblack@eecs.umich.edu{ 1565141Sgblack@eecs.umich.edu if (!cp->findObj(section, name, param)) { 1575141Sgblack@eecs.umich.edu fatal("Can't unserialize '%s:%s'\n", section, name); 1585141Sgblack@eecs.umich.edu } 1595141Sgblack@eecs.umich.edu} 1605141Sgblack@eecs.umich.edu 1615141Sgblack@eecs.umich.edu 1625141Sgblack@eecs.umich.edu#define INSTANTIATE_PARAM_TEMPLATES(type) \ 1635141Sgblack@eecs.umich.edutemplate void \ 1645141Sgblack@eecs.umich.eduparamOut(ostream &os, const std::string &name, type const ¶m); \ 1655135Sgblack@eecs.umich.edutemplate void \ 1665135Sgblack@eecs.umich.eduparamIn(Checkpoint *cp, const std::string §ion, \ 1675135Sgblack@eecs.umich.edu const std::string &name, type & param); \ 1685360Sgblack@eecs.umich.edutemplate void \ 1695360Sgblack@eecs.umich.eduarrayParamOut(ostream &os, const std::string &name, \ 1705360Sgblack@eecs.umich.edu type const *param, int size); \ 1715360Sgblack@eecs.umich.edutemplate void \ 1725360Sgblack@eecs.umich.eduarrayParamIn(Checkpoint *cp, const std::string §ion, \ 1735360Sgblack@eecs.umich.edu const std::string &name, type *param, int size); 1745647Sgblack@eecs.umich.edu 1755647Sgblack@eecs.umich.edu 1765647Sgblack@eecs.umich.eduINSTANTIATE_PARAM_TEMPLATES(int8_t) 1775360Sgblack@eecs.umich.eduINSTANTIATE_PARAM_TEMPLATES(uint8_t) 1785647Sgblack@eecs.umich.eduINSTANTIATE_PARAM_TEMPLATES(int16_t) 1795647Sgblack@eecs.umich.eduINSTANTIATE_PARAM_TEMPLATES(uint16_t) 1805647Sgblack@eecs.umich.eduINSTANTIATE_PARAM_TEMPLATES(int32_t) 1815648Sgblack@eecs.umich.eduINSTANTIATE_PARAM_TEMPLATES(uint32_t) 1825648Sgblack@eecs.umich.eduINSTANTIATE_PARAM_TEMPLATES(int64_t) 1835360Sgblack@eecs.umich.eduINSTANTIATE_PARAM_TEMPLATES(uint64_t) 1845141Sgblack@eecs.umich.eduINSTANTIATE_PARAM_TEMPLATES(bool) 1855141Sgblack@eecs.umich.eduINSTANTIATE_PARAM_TEMPLATES(string) 1865141Sgblack@eecs.umich.edu 1875141Sgblack@eecs.umich.edu 1885141Sgblack@eecs.umich.edu///////////////////////////// 1895141Sgblack@eecs.umich.edu 1905135Sgblack@eecs.umich.edu/// Container for serializing global variables (not associated with 1915135Sgblack@eecs.umich.edu/// any serialized object). 1925135Sgblack@eecs.umich.educlass Globals : public Serializable 1935135Sgblack@eecs.umich.edu{ 1945135Sgblack@eecs.umich.edu public: 1955135Sgblack@eecs.umich.edu const string name() const; 1966042Sgblack@eecs.umich.edu void serialize(ostream &os); 1975135Sgblack@eecs.umich.edu void unserialize(Checkpoint *cp); 1985135Sgblack@eecs.umich.edu}; 1995135Sgblack@eecs.umich.edu 2005135Sgblack@eecs.umich.edu/// The one and only instance of the Globals class. 2015135Sgblack@eecs.umich.eduGlobals globals; 2025135Sgblack@eecs.umich.edu 2036042Sgblack@eecs.umich.educonst string 2045135Sgblack@eecs.umich.eduGlobals::name() const 2056042Sgblack@eecs.umich.edu{ 2066042Sgblack@eecs.umich.edu return "Globals"; 2076042Sgblack@eecs.umich.edu} 2085135Sgblack@eecs.umich.edu 2095135Sgblack@eecs.umich.eduvoid 2106329Sgblack@eecs.umich.eduGlobals::serialize(ostream &os) 2116329Sgblack@eecs.umich.edu{ 2126329Sgblack@eecs.umich.edu nameOut(os); 2136329Sgblack@eecs.umich.edu SERIALIZE_SCALAR(curTick); 2146329Sgblack@eecs.umich.edu 2156329Sgblack@eecs.umich.edu nameOut(os, "MainEventQueue"); 2166329Sgblack@eecs.umich.edu mainEventQueue.serialize(os); 2176329Sgblack@eecs.umich.edu} 2186329Sgblack@eecs.umich.edu 2196329Sgblack@eecs.umich.eduvoid 2206329Sgblack@eecs.umich.eduGlobals::unserialize(Checkpoint *cp) 2216329Sgblack@eecs.umich.edu{ 2226329Sgblack@eecs.umich.edu const string §ion = name(); 2236329Sgblack@eecs.umich.edu UNSERIALIZE_SCALAR(curTick); 2246329Sgblack@eecs.umich.edu 2256329Sgblack@eecs.umich.edu mainEventQueue.unserialize(cp, "MainEventQueue"); 2266329Sgblack@eecs.umich.edu} 2276329Sgblack@eecs.umich.edu 2286329Sgblack@eecs.umich.eduvoid 2296329Sgblack@eecs.umich.eduSerializable::serializeAll() 2306329Sgblack@eecs.umich.edu{ 2316329Sgblack@eecs.umich.edu if (maxCount && count++ > maxCount) 2326329Sgblack@eecs.umich.edu exitNow("Maximum number of checkpoints dropped", 0); 2336329Sgblack@eecs.umich.edu 2346329Sgblack@eecs.umich.edu string dir = Checkpoint::dir(); 2356329Sgblack@eecs.umich.edu if (mkdir(dir.c_str(), 0775) == -1 && errno != EEXIST) 2367693SAli.Saidi@ARM.com fatal("couldn't mkdir %s\n", dir); 2377693SAli.Saidi@ARM.com 2387693SAli.Saidi@ARM.com string cpt_file = dir + Checkpoint::baseFilename; 2397693SAli.Saidi@ARM.com ofstream outstream(cpt_file.c_str()); 2407693SAli.Saidi@ARM.com time_t t = time(NULL); 2417693SAli.Saidi@ARM.com outstream << "// checkpoint generated: " << ctime(&t); 2427693SAli.Saidi@ARM.com 2435086Sgblack@eecs.umich.edu globals.serialize(outstream); 244 SimObject::serializeAll(outstream); 245} 246 247 248void 249Serializable::unserializeGlobals(Checkpoint *cp) 250{ 251 globals.unserialize(cp); 252} 253 254 255class SerializeEvent : public Event 256{ 257 protected: 258 Tick repeat; 259 260 public: 261 SerializeEvent(Tick _when, Tick _repeat); 262 virtual void process(); 263 virtual void serialize(std::ostream &os) 264 { 265 panic("Cannot serialize the SerializeEvent"); 266 } 267 268}; 269 270SerializeEvent::SerializeEvent(Tick _when, Tick _repeat) 271 : Event(&mainEventQueue, Serialize_Pri), repeat(_repeat) 272{ 273 setFlags(AutoDelete); 274 schedule(_when); 275} 276 277void 278SerializeEvent::process() 279{ 280 Serializable::serializeAll(); 281 if (repeat) 282 schedule(curTick + repeat); 283} 284 285const char *Checkpoint::baseFilename = "m5.cpt"; 286 287static string checkpointDirBase; 288 289string 290Checkpoint::dir() 291{ 292 // use csprintf to insert curTick into directory name if it 293 // appears to have a format placeholder in it. 294 return (checkpointDirBase.find("%") != string::npos) ? 295 csprintf(checkpointDirBase, curTick) : checkpointDirBase; 296} 297 298void 299Checkpoint::setup(Tick when, Tick period) 300{ 301 new SerializeEvent(when, period); 302} 303 304class SerializeParamContext : public ParamContext 305{ 306 private: 307 SerializeEvent *event; 308 309 public: 310 SerializeParamContext(const string §ion); 311 ~SerializeParamContext(); 312 void checkParams(); 313}; 314 315SerializeParamContext serialParams("serialize"); 316 317Param<string> serialize_dir(&serialParams, "dir", 318 "dir to stick checkpoint in " 319 "(sprintf format with cycle #)"); 320 321Param<Counter> serialize_cycle(&serialParams, 322 "cycle", 323 "cycle to serialize", 324 0); 325 326Param<Counter> serialize_period(&serialParams, 327 "period", 328 "period to repeat serializations", 329 0); 330 331Param<int> serialize_count(&serialParams, "count", 332 "maximum number of checkpoints to drop"); 333 334SerializeParamContext::SerializeParamContext(const string §ion) 335 : ParamContext(section), event(NULL) 336{ } 337 338SerializeParamContext::~SerializeParamContext() 339{ 340} 341 342void 343SerializeParamContext::checkParams() 344{ 345 checkpointDirBase = simout.resolve(serialize_dir); 346 347 // guarantee that directory ends with a '/' 348 if (checkpointDirBase[checkpointDirBase.size() - 1] != '/') 349 checkpointDirBase += "/"; 350 351 if (serialize_cycle > 0) 352 Checkpoint::setup(serialize_cycle, serialize_period); 353 354 Serializable::maxCount = serialize_count; 355} 356 357void 358debug_serialize() 359{ 360 Serializable::serializeAll(); 361} 362 363void 364debug_serialize(Tick when) 365{ 366 new SerializeEvent(when, 0); 367} 368 369//////////////////////////////////////////////////////////////////////// 370// 371// SerializableClass member definitions 372// 373//////////////////////////////////////////////////////////////////////// 374 375// Map of class names to SerializableBuilder creation functions. 376// Need to make this a pointer so we can force initialization on the 377// first reference; otherwise, some SerializableClass constructors 378// may be invoked before the classMap constructor. 379map<string,SerializableClass::CreateFunc> *SerializableClass::classMap = 0; 380 381// SerializableClass constructor: add mapping to classMap 382SerializableClass::SerializableClass(const string &className, 383 CreateFunc createFunc) 384{ 385 if (classMap == NULL) 386 classMap = new map<string,SerializableClass::CreateFunc>(); 387 388 if ((*classMap)[className]) 389 { 390 cerr << "Error: simulation object class " << className << " redefined" 391 << endl; 392 fatal(""); 393 } 394 395 // add className --> createFunc to class map 396 (*classMap)[className] = createFunc; 397} 398 399 400// 401// 402Serializable * 403SerializableClass::createObject(Checkpoint *cp, 404 const std::string §ion) 405{ 406 string className; 407 408 if (!cp->find(section, "type", className)) { 409 fatal("Serializable::create: no 'type' entry in section '%s'.\n", 410 section); 411 } 412 413 CreateFunc createFunc = (*classMap)[className]; 414 415 if (createFunc == NULL) { 416 fatal("Serializable::create: no create function for class '%s'.\n", 417 className); 418 } 419 420 Serializable *object = createFunc(cp, section); 421 422 assert(object != NULL); 423 424 return object; 425} 426 427 428Serializable * 429Serializable::create(Checkpoint *cp, const std::string §ion) 430{ 431 Serializable *object = SerializableClass::createObject(cp, section); 432 object->unserialize(cp, section); 433 return object; 434} 435 436 437Checkpoint::Checkpoint(const std::string &cpt_dir, const std::string &path, 438 const ConfigNode *_configNode) 439 : db(new IniFile), basePath(path), configNode(_configNode), cptDir(cpt_dir) 440{ 441 string filename = cpt_dir + "/" + Checkpoint::baseFilename; 442 if (!db->load(filename)) { 443 fatal("Can't load checkpoint file '%s'\n", filename); 444 } 445} 446 447 448bool 449Checkpoint::find(const std::string §ion, const std::string &entry, 450 std::string &value) 451{ 452 return db->find(section, entry, value); 453} 454 455 456bool 457Checkpoint::findObj(const std::string §ion, const std::string &entry, 458 Serializable *&value) 459{ 460 string path; 461 462 if (!db->find(section, entry, path)) 463 return false; 464 465 if ((value = configNode->resolveSimObject(path)) != NULL) 466 return true; 467 468 if ((value = objMap[path]) != NULL) 469 return true; 470 471 return false; 472} 473 474 475bool 476Checkpoint::sectionExists(const std::string §ion) 477{ 478 return db->sectionExists(section); 479} 480