serialize.cc revision 2868
12SN/A/* 21762SN/A * Copyright (c) 2002-2005 The Regents of The University of Michigan 32SN/A * All rights reserved. 42SN/A * 52SN/A * Redistribution and use in source and binary forms, with or without 62SN/A * modification, are permitted provided that the following conditions are 72SN/A * met: redistributions of source code must retain the above copyright 82SN/A * notice, this list of conditions and the following disclaimer; 92SN/A * redistributions in binary form must reproduce the above copyright 102SN/A * notice, this list of conditions and the following disclaimer in the 112SN/A * documentation and/or other materials provided with the distribution; 122SN/A * neither the name of the copyright holders nor the names of its 132SN/A * contributors may be used to endorse or promote products derived from 142SN/A * this software without specific prior written permission. 152SN/A * 162SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 172SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 182SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 192SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 202SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 212SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 222SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 262SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272665Ssaidi@eecs.umich.edu * 282760Sbinkertn@umich.edu * Authors: Nathan Binkert 292760Sbinkertn@umich.edu * Erik Hallnor 302665Ssaidi@eecs.umich.edu * Steve Reinhardt 312SN/A */ 322SN/A 332SN/A#include <sys/time.h> 34363SN/A#include <sys/types.h> 35363SN/A#include <sys/stat.h> 361354SN/A#include <errno.h> 372SN/A 382SN/A#include <fstream> 392SN/A#include <list> 402SN/A#include <string> 412SN/A#include <vector> 422SN/A 43363SN/A#include "base/inifile.hh" 4456SN/A#include "base/misc.hh" 451388SN/A#include "base/output.hh" 46217SN/A#include "base/str.hh" 47363SN/A#include "base/trace.hh" 4856SN/A#include "sim/eventq.hh" 4956SN/A#include "sim/param.hh" 5056SN/A#include "sim/serialize.hh" 5156SN/A#include "sim/sim_events.hh" 521638SN/A#include "sim/sim_exit.hh" 5356SN/A#include "sim/sim_object.hh" 542SN/A 552SN/Ausing namespace std; 562SN/A 572287SN/Aint Serializable::ckptMaxCount = 0; 582287SN/Aint Serializable::ckptCount = 0; 592287SN/Aint Serializable::ckptPrevCount = -1; 601637SN/A 612SN/Avoid 62395SN/ASerializable::nameOut(ostream &os) 632SN/A{ 64217SN/A os << "\n[" << name() << "]\n"; 652SN/A} 662SN/A 672SN/Avoid 68395SN/ASerializable::nameOut(ostream &os, const string &_name) 692SN/A{ 70217SN/A os << "\n[" << _name << "]\n"; 712SN/A} 722SN/A 73217SN/Atemplate <class T> 742SN/Avoid 75502SN/AparamOut(ostream &os, const std::string &name, const T ¶m) 762SN/A{ 77217SN/A os << name << "="; 78217SN/A showParam(os, param); 79217SN/A os << "\n"; 802SN/A} 812SN/A 82217SN/A 83217SN/Atemplate <class T> 84217SN/Avoid 85237SN/AparamIn(Checkpoint *cp, const std::string §ion, 86502SN/A const std::string &name, T ¶m) 872SN/A{ 88217SN/A std::string str; 89237SN/A if (!cp->find(section, name, str) || !parseParam(str, param)) { 90217SN/A fatal("Can't unserialize '%s:%s'\n", section, name); 91217SN/A } 922SN/A} 932SN/A 94217SN/A 95217SN/Atemplate <class T> 96217SN/Avoid 97217SN/AarrayParamOut(ostream &os, const std::string &name, 98217SN/A const T *param, int size) 99217SN/A{ 100217SN/A os << name << "="; 101217SN/A if (size > 0) 102217SN/A showParam(os, param[0]); 103217SN/A for (int i = 1; i < size; ++i) { 104217SN/A os << " "; 105217SN/A showParam(os, param[i]); 106217SN/A } 107217SN/A os << "\n"; 108217SN/A} 109217SN/A 110217SN/A 111217SN/Atemplate <class T> 112217SN/Avoid 113237SN/AarrayParamIn(Checkpoint *cp, const std::string §ion, 114217SN/A const std::string &name, T *param, int size) 115217SN/A{ 116217SN/A std::string str; 117237SN/A if (!cp->find(section, name, str)) { 118217SN/A fatal("Can't unserialize '%s:%s'\n", section, name); 119217SN/A } 120217SN/A 121217SN/A // code below stolen from VectorParam<T>::parse(). 122217SN/A // it would be nice to unify these somehow... 123217SN/A 124217SN/A vector<string> tokens; 125217SN/A 126217SN/A tokenize(tokens, str, ' '); 127217SN/A 128217SN/A // Need this if we were doing a vector 129217SN/A // value.resize(tokens.size()); 130217SN/A 131217SN/A if (tokens.size() != size) { 132217SN/A fatal("Array size mismatch on %s:%s'\n", section, name); 133217SN/A } 134217SN/A 135217SN/A for (int i = 0; i < tokens.size(); i++) { 136217SN/A // need to parse into local variable to handle vector<bool>, 137217SN/A // for which operator[] returns a special reference class 138217SN/A // that's not the same as 'bool&', (since it's a packed 139217SN/A // vector) 140217SN/A T scalar_value; 141217SN/A if (!parseParam(tokens[i], scalar_value)) { 142217SN/A string err("could not parse \""); 143217SN/A 144217SN/A err += str; 145217SN/A err += "\""; 146217SN/A 147217SN/A fatal(err); 148217SN/A } 149217SN/A 150217SN/A // assign parsed value to vector 151217SN/A param[i] = scalar_value; 152217SN/A } 153217SN/A} 154217SN/A 155217SN/A 156237SN/Avoid 157237SN/AobjParamIn(Checkpoint *cp, const std::string §ion, 158395SN/A const std::string &name, Serializable * ¶m) 159237SN/A{ 160237SN/A if (!cp->findObj(section, name, param)) { 161237SN/A fatal("Can't unserialize '%s:%s'\n", section, name); 162237SN/A } 163237SN/A} 164237SN/A 165237SN/A 166221SN/A#define INSTANTIATE_PARAM_TEMPLATES(type) \ 167221SN/Atemplate void \ 168237SN/AparamOut(ostream &os, const std::string &name, type const ¶m); \ 169221SN/Atemplate void \ 170237SN/AparamIn(Checkpoint *cp, const std::string §ion, \ 171221SN/A const std::string &name, type & param); \ 172221SN/Atemplate void \ 173221SN/AarrayParamOut(ostream &os, const std::string &name, \ 174237SN/A type const *param, int size); \ 175221SN/Atemplate void \ 176237SN/AarrayParamIn(Checkpoint *cp, const std::string §ion, \ 177217SN/A const std::string &name, type *param, int size); 178217SN/A 1791642SN/AINSTANTIATE_PARAM_TEMPLATES(signed char) 1801642SN/AINSTANTIATE_PARAM_TEMPLATES(unsigned char) 1811642SN/AINSTANTIATE_PARAM_TEMPLATES(signed short) 1821642SN/AINSTANTIATE_PARAM_TEMPLATES(unsigned short) 1831642SN/AINSTANTIATE_PARAM_TEMPLATES(signed int) 1841642SN/AINSTANTIATE_PARAM_TEMPLATES(unsigned int) 1851642SN/AINSTANTIATE_PARAM_TEMPLATES(signed long) 1861642SN/AINSTANTIATE_PARAM_TEMPLATES(unsigned long) 1871642SN/AINSTANTIATE_PARAM_TEMPLATES(signed long long) 1881642SN/AINSTANTIATE_PARAM_TEMPLATES(unsigned long long) 189219SN/AINSTANTIATE_PARAM_TEMPLATES(bool) 190217SN/AINSTANTIATE_PARAM_TEMPLATES(string) 191217SN/A 192217SN/A 193395SN/A///////////////////////////// 194395SN/A 195395SN/A/// Container for serializing global variables (not associated with 196395SN/A/// any serialized object). 197395SN/Aclass Globals : public Serializable 1982SN/A{ 199395SN/A public: 200512SN/A const string name() const; 201510SN/A void serialize(ostream &os); 202395SN/A void unserialize(Checkpoint *cp); 203395SN/A}; 2042SN/A 205395SN/A/// The one and only instance of the Globals class. 206395SN/AGlobals globals; 2072SN/A 208512SN/Aconst string 209395SN/AGlobals::name() const 2102SN/A{ 211395SN/A return "Globals"; 2122SN/A} 2132SN/A 2142SN/Avoid 215510SN/AGlobals::serialize(ostream &os) 2162SN/A{ 217395SN/A nameOut(os); 218395SN/A SERIALIZE_SCALAR(curTick); 219395SN/A 220395SN/A nameOut(os, "MainEventQueue"); 221395SN/A mainEventQueue.serialize(os); 2222SN/A} 2232SN/A 2242SN/Avoid 225395SN/AGlobals::unserialize(Checkpoint *cp) 2262SN/A{ 227395SN/A const string §ion = name(); 228395SN/A UNSERIALIZE_SCALAR(curTick); 2292SN/A 230395SN/A mainEventQueue.unserialize(cp, "MainEventQueue"); 2312SN/A} 2322SN/A 2332SN/Avoid 2342868Sktlim@umich.eduSerializable::serializeAll(const std::string &cpt_dir) 2352SN/A{ 2362868Sktlim@umich.edu setCheckpointDir(cpt_dir); 237449SN/A string dir = Checkpoint::dir(); 238363SN/A if (mkdir(dir.c_str(), 0775) == -1 && errno != EEXIST) 239449SN/A fatal("couldn't mkdir %s\n", dir); 240363SN/A 241449SN/A string cpt_file = dir + Checkpoint::baseFilename; 242395SN/A ofstream outstream(cpt_file.c_str()); 2432SN/A time_t t = time(NULL); 244395SN/A outstream << "// checkpoint generated: " << ctime(&t); 2452SN/A 246395SN/A globals.serialize(outstream); 247395SN/A SimObject::serializeAll(outstream); 248395SN/A} 2492SN/A 2502797Sktlim@umich.eduvoid 2512868Sktlim@umich.eduSerializable::unserializeAll(const std::string &cpt_dir) 2522797Sktlim@umich.edu{ 2532868Sktlim@umich.edu setCheckpointDir(cpt_dir); 2542797Sktlim@umich.edu string dir = Checkpoint::dir(); 2552797Sktlim@umich.edu string cpt_file = dir + Checkpoint::baseFilename; 2562797Sktlim@umich.edu string section = ""; 2572797Sktlim@umich.edu 2582797Sktlim@umich.edu DPRINTFR(Config, "Loading checkpoint dir '%s'\n", 2592797Sktlim@umich.edu dir); 2602797Sktlim@umich.edu Checkpoint *cp = new Checkpoint(dir, section); 2612797Sktlim@umich.edu unserializeGlobals(cp); 2622797Sktlim@umich.edu 2632797Sktlim@umich.edu SimObject::unserializeAll(cp); 2642797Sktlim@umich.edu} 2652SN/A 266395SN/Avoid 267395SN/ASerializable::unserializeGlobals(Checkpoint *cp) 268395SN/A{ 269395SN/A globals.unserialize(cp); 270395SN/A} 2712SN/A 272449SN/Aconst char *Checkpoint::baseFilename = "m5.cpt"; 273449SN/A 274449SN/Astatic string checkpointDirBase; 275294SN/A 2762797Sktlim@umich.eduvoid 2772797Sktlim@umich.edusetCheckpointDir(const std::string &name) 2782797Sktlim@umich.edu{ 2792797Sktlim@umich.edu checkpointDirBase = name; 2802797Sktlim@umich.edu if (checkpointDirBase[checkpointDirBase.size() - 1] != '/') 2812797Sktlim@umich.edu checkpointDirBase += "/"; 2822797Sktlim@umich.edu} 2832797Sktlim@umich.edu 284294SN/Astring 285449SN/ACheckpoint::dir() 286294SN/A{ 287449SN/A // use csprintf to insert curTick into directory name if it 288449SN/A // appears to have a format placeholder in it. 289449SN/A return (checkpointDirBase.find("%") != string::npos) ? 290449SN/A csprintf(checkpointDirBase, curTick) : checkpointDirBase; 2912SN/A} 2922SN/A 2932SN/Avoid 2942868Sktlim@umich.edudebug_serialize(const std::string &cpt_dir) 2952SN/A{ 2962868Sktlim@umich.edu Serializable::serializeAll(cpt_dir); 2972SN/A} 2982SN/A 2992SN/A 3002SN/A//////////////////////////////////////////////////////////////////////// 3012SN/A// 302395SN/A// SerializableClass member definitions 3032SN/A// 3042SN/A//////////////////////////////////////////////////////////////////////// 3052SN/A 306395SN/A// Map of class names to SerializableBuilder creation functions. 3072SN/A// Need to make this a pointer so we can force initialization on the 308395SN/A// first reference; otherwise, some SerializableClass constructors 3092SN/A// may be invoked before the classMap constructor. 310395SN/Amap<string,SerializableClass::CreateFunc> *SerializableClass::classMap = 0; 3112SN/A 312395SN/A// SerializableClass constructor: add mapping to classMap 313395SN/ASerializableClass::SerializableClass(const string &className, 3142SN/A CreateFunc createFunc) 3152SN/A{ 3162SN/A if (classMap == NULL) 317395SN/A classMap = new map<string,SerializableClass::CreateFunc>(); 3182SN/A 3192SN/A if ((*classMap)[className]) 3202SN/A { 3212SN/A cerr << "Error: simulation object class " << className << " redefined" 3222SN/A << endl; 3232SN/A fatal(""); 3242SN/A } 3252SN/A 3262SN/A // add className --> createFunc to class map 3272SN/A (*classMap)[className] = createFunc; 3282SN/A} 3292SN/A 3302SN/A 3312SN/A// 3322SN/A// 333395SN/ASerializable * 334395SN/ASerializableClass::createObject(Checkpoint *cp, 335237SN/A const std::string §ion) 3362SN/A{ 337237SN/A string className; 3382SN/A 339237SN/A if (!cp->find(section, "type", className)) { 340395SN/A fatal("Serializable::create: no 'type' entry in section '%s'.\n", 341237SN/A section); 3422SN/A } 3432SN/A 344237SN/A CreateFunc createFunc = (*classMap)[className]; 345237SN/A 346237SN/A if (createFunc == NULL) { 347395SN/A fatal("Serializable::create: no create function for class '%s'.\n", 348237SN/A className); 3492SN/A } 3502SN/A 351395SN/A Serializable *object = createFunc(cp, section); 3522SN/A 3532SN/A assert(object != NULL); 3542SN/A 3552SN/A return object; 3562SN/A} 3572SN/A 358237SN/A 359395SN/ASerializable * 360395SN/ASerializable::create(Checkpoint *cp, const std::string §ion) 361237SN/A{ 362395SN/A Serializable *object = SerializableClass::createObject(cp, section); 363237SN/A object->unserialize(cp, section); 364237SN/A return object; 365237SN/A} 366237SN/A 367237SN/A 3682738Sstever@eecs.umich.eduCheckpoint::Checkpoint(const std::string &cpt_dir, const std::string &path) 3692738Sstever@eecs.umich.edu : db(new IniFile), basePath(path), cptDir(cpt_dir) 370237SN/A{ 371449SN/A string filename = cpt_dir + "/" + Checkpoint::baseFilename; 372237SN/A if (!db->load(filename)) { 373237SN/A fatal("Can't load checkpoint file '%s'\n", filename); 374237SN/A } 375237SN/A} 376237SN/A 377237SN/A 378237SN/Abool 379237SN/ACheckpoint::find(const std::string §ion, const std::string &entry, 380237SN/A std::string &value) 381237SN/A{ 382237SN/A return db->find(section, entry, value); 383237SN/A} 384237SN/A 385237SN/A 386237SN/Abool 387237SN/ACheckpoint::findObj(const std::string §ion, const std::string &entry, 388395SN/A Serializable *&value) 389237SN/A{ 390237SN/A string path; 391237SN/A 392237SN/A if (!db->find(section, entry, path)) 393237SN/A return false; 394237SN/A 395237SN/A if ((value = objMap[path]) != NULL) 396237SN/A return true; 397237SN/A 398237SN/A return false; 399237SN/A} 400304SN/A 401304SN/A 402304SN/Abool 403304SN/ACheckpoint::sectionExists(const std::string §ion) 404304SN/A{ 405304SN/A return db->sectionExists(section); 406304SN/A} 407