serialize.cc revision 4000
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 552356SN/A// For stat reset hack 562356SN/A#include "sim/stat_control.hh" 572356SN/A 582SN/Ausing namespace std; 592SN/A 604000Ssaidi@eecs.umich.eduextern SimObject *resolveSimObject(const string &); 614000Ssaidi@eecs.umich.edu 622287SN/Aint Serializable::ckptMaxCount = 0; 632287SN/Aint Serializable::ckptCount = 0; 642287SN/Aint Serializable::ckptPrevCount = -1; 651637SN/A 662SN/Avoid 67395SN/ASerializable::nameOut(ostream &os) 682SN/A{ 69217SN/A os << "\n[" << name() << "]\n"; 702SN/A} 712SN/A 722SN/Avoid 73395SN/ASerializable::nameOut(ostream &os, const string &_name) 742SN/A{ 75217SN/A os << "\n[" << _name << "]\n"; 762SN/A} 772SN/A 78217SN/Atemplate <class T> 792SN/Avoid 80502SN/AparamOut(ostream &os, const std::string &name, const T ¶m) 812SN/A{ 82217SN/A os << name << "="; 83217SN/A showParam(os, param); 84217SN/A os << "\n"; 852SN/A} 862SN/A 87217SN/A 88217SN/Atemplate <class T> 89217SN/Avoid 90237SN/AparamIn(Checkpoint *cp, const std::string §ion, 91502SN/A const std::string &name, T ¶m) 922SN/A{ 93217SN/A std::string str; 94237SN/A if (!cp->find(section, name, str) || !parseParam(str, param)) { 95217SN/A fatal("Can't unserialize '%s:%s'\n", section, name); 96217SN/A } 972SN/A} 982SN/A 99217SN/A 100217SN/Atemplate <class T> 101217SN/Avoid 102217SN/AarrayParamOut(ostream &os, const std::string &name, 103217SN/A const T *param, int size) 104217SN/A{ 105217SN/A os << name << "="; 106217SN/A if (size > 0) 107217SN/A showParam(os, param[0]); 108217SN/A for (int i = 1; i < size; ++i) { 109217SN/A os << " "; 110217SN/A showParam(os, param[i]); 111217SN/A } 112217SN/A os << "\n"; 113217SN/A} 114217SN/A 115217SN/A 116217SN/Atemplate <class T> 117217SN/Avoid 118237SN/AarrayParamIn(Checkpoint *cp, const std::string §ion, 119217SN/A const std::string &name, T *param, int size) 120217SN/A{ 121217SN/A std::string str; 122237SN/A if (!cp->find(section, name, str)) { 123217SN/A fatal("Can't unserialize '%s:%s'\n", section, name); 124217SN/A } 125217SN/A 126217SN/A // code below stolen from VectorParam<T>::parse(). 127217SN/A // it would be nice to unify these somehow... 128217SN/A 129217SN/A vector<string> tokens; 130217SN/A 131217SN/A tokenize(tokens, str, ' '); 132217SN/A 133217SN/A // Need this if we were doing a vector 134217SN/A // value.resize(tokens.size()); 135217SN/A 136217SN/A if (tokens.size() != size) { 137217SN/A fatal("Array size mismatch on %s:%s'\n", section, name); 138217SN/A } 139217SN/A 140217SN/A for (int i = 0; i < tokens.size(); i++) { 141217SN/A // need to parse into local variable to handle vector<bool>, 142217SN/A // for which operator[] returns a special reference class 143217SN/A // that's not the same as 'bool&', (since it's a packed 144217SN/A // vector) 145217SN/A T scalar_value; 146217SN/A if (!parseParam(tokens[i], scalar_value)) { 147217SN/A string err("could not parse \""); 148217SN/A 149217SN/A err += str; 150217SN/A err += "\""; 151217SN/A 152217SN/A fatal(err); 153217SN/A } 154217SN/A 155217SN/A // assign parsed value to vector 156217SN/A param[i] = scalar_value; 157217SN/A } 158217SN/A} 159217SN/A 160217SN/A 161237SN/Avoid 162237SN/AobjParamIn(Checkpoint *cp, const std::string §ion, 1634000Ssaidi@eecs.umich.edu const std::string &name, SimObject * ¶m) 164237SN/A{ 165237SN/A if (!cp->findObj(section, name, param)) { 166237SN/A fatal("Can't unserialize '%s:%s'\n", section, name); 167237SN/A } 168237SN/A} 169237SN/A 170237SN/A 171221SN/A#define INSTANTIATE_PARAM_TEMPLATES(type) \ 172221SN/Atemplate void \ 173237SN/AparamOut(ostream &os, const std::string &name, type const ¶m); \ 174221SN/Atemplate void \ 175237SN/AparamIn(Checkpoint *cp, const std::string §ion, \ 176221SN/A const std::string &name, type & param); \ 177221SN/Atemplate void \ 178221SN/AarrayParamOut(ostream &os, const std::string &name, \ 179237SN/A type const *param, int size); \ 180221SN/Atemplate void \ 181237SN/AarrayParamIn(Checkpoint *cp, const std::string §ion, \ 182217SN/A const std::string &name, type *param, int size); 183217SN/A 1841642SN/AINSTANTIATE_PARAM_TEMPLATES(signed char) 1851642SN/AINSTANTIATE_PARAM_TEMPLATES(unsigned char) 1861642SN/AINSTANTIATE_PARAM_TEMPLATES(signed short) 1871642SN/AINSTANTIATE_PARAM_TEMPLATES(unsigned short) 1881642SN/AINSTANTIATE_PARAM_TEMPLATES(signed int) 1891642SN/AINSTANTIATE_PARAM_TEMPLATES(unsigned int) 1901642SN/AINSTANTIATE_PARAM_TEMPLATES(signed long) 1911642SN/AINSTANTIATE_PARAM_TEMPLATES(unsigned long) 1921642SN/AINSTANTIATE_PARAM_TEMPLATES(signed long long) 1931642SN/AINSTANTIATE_PARAM_TEMPLATES(unsigned long long) 194219SN/AINSTANTIATE_PARAM_TEMPLATES(bool) 195217SN/AINSTANTIATE_PARAM_TEMPLATES(string) 196217SN/A 197217SN/A 198395SN/A///////////////////////////// 199395SN/A 200395SN/A/// Container for serializing global variables (not associated with 201395SN/A/// any serialized object). 202395SN/Aclass Globals : public Serializable 2032SN/A{ 204395SN/A public: 205512SN/A const string name() const; 206510SN/A void serialize(ostream &os); 207395SN/A void unserialize(Checkpoint *cp); 208395SN/A}; 2092SN/A 210395SN/A/// The one and only instance of the Globals class. 211395SN/AGlobals globals; 2122SN/A 213512SN/Aconst string 214395SN/AGlobals::name() const 2152SN/A{ 216395SN/A return "Globals"; 2172SN/A} 2182SN/A 2192SN/Avoid 220510SN/AGlobals::serialize(ostream &os) 2212SN/A{ 222395SN/A nameOut(os); 223395SN/A SERIALIZE_SCALAR(curTick); 224395SN/A 225395SN/A nameOut(os, "MainEventQueue"); 226395SN/A mainEventQueue.serialize(os); 2272SN/A} 2282SN/A 2292SN/Avoid 230395SN/AGlobals::unserialize(Checkpoint *cp) 2312SN/A{ 232395SN/A const string §ion = name(); 233395SN/A UNSERIALIZE_SCALAR(curTick); 2342SN/A 235395SN/A mainEventQueue.unserialize(cp, "MainEventQueue"); 2362SN/A} 2372SN/A 2382SN/Avoid 2392868Sktlim@umich.eduSerializable::serializeAll(const std::string &cpt_dir) 2402SN/A{ 2412868Sktlim@umich.edu setCheckpointDir(cpt_dir); 242449SN/A string dir = Checkpoint::dir(); 243363SN/A if (mkdir(dir.c_str(), 0775) == -1 && errno != EEXIST) 244449SN/A fatal("couldn't mkdir %s\n", dir); 245363SN/A 246449SN/A string cpt_file = dir + Checkpoint::baseFilename; 247395SN/A ofstream outstream(cpt_file.c_str()); 2482SN/A time_t t = time(NULL); 249395SN/A outstream << "// checkpoint generated: " << ctime(&t); 2502SN/A 251395SN/A globals.serialize(outstream); 252395SN/A SimObject::serializeAll(outstream); 253395SN/A} 2542SN/A 2552797Sktlim@umich.eduvoid 2562868Sktlim@umich.eduSerializable::unserializeAll(const std::string &cpt_dir) 2572797Sktlim@umich.edu{ 2582868Sktlim@umich.edu setCheckpointDir(cpt_dir); 2592797Sktlim@umich.edu string dir = Checkpoint::dir(); 2602797Sktlim@umich.edu string cpt_file = dir + Checkpoint::baseFilename; 2612797Sktlim@umich.edu string section = ""; 2622797Sktlim@umich.edu 2632797Sktlim@umich.edu DPRINTFR(Config, "Loading checkpoint dir '%s'\n", 2642797Sktlim@umich.edu dir); 2652797Sktlim@umich.edu Checkpoint *cp = new Checkpoint(dir, section); 2662797Sktlim@umich.edu unserializeGlobals(cp); 2672797Sktlim@umich.edu 2682797Sktlim@umich.edu SimObject::unserializeAll(cp); 2692797Sktlim@umich.edu} 2702SN/A 271395SN/Avoid 272395SN/ASerializable::unserializeGlobals(Checkpoint *cp) 273395SN/A{ 274395SN/A globals.unserialize(cp); 275395SN/A} 2762SN/A 277449SN/Aconst char *Checkpoint::baseFilename = "m5.cpt"; 278449SN/A 279449SN/Astatic string checkpointDirBase; 280294SN/A 2812797Sktlim@umich.eduvoid 2822797Sktlim@umich.edusetCheckpointDir(const std::string &name) 2832797Sktlim@umich.edu{ 2842797Sktlim@umich.edu checkpointDirBase = name; 2852797Sktlim@umich.edu if (checkpointDirBase[checkpointDirBase.size() - 1] != '/') 2862797Sktlim@umich.edu checkpointDirBase += "/"; 2872797Sktlim@umich.edu} 2882797Sktlim@umich.edu 289294SN/Astring 290449SN/ACheckpoint::dir() 291294SN/A{ 292449SN/A // use csprintf to insert curTick into directory name if it 293449SN/A // appears to have a format placeholder in it. 294449SN/A return (checkpointDirBase.find("%") != string::npos) ? 295449SN/A csprintf(checkpointDirBase, curTick) : checkpointDirBase; 2962SN/A} 2972SN/A 2982SN/Avoid 2992868Sktlim@umich.edudebug_serialize(const std::string &cpt_dir) 3002SN/A{ 3012868Sktlim@umich.edu Serializable::serializeAll(cpt_dir); 3022SN/A} 3032SN/A 3042SN/A 3052SN/A//////////////////////////////////////////////////////////////////////// 3062SN/A// 307395SN/A// SerializableClass member definitions 3082SN/A// 3092SN/A//////////////////////////////////////////////////////////////////////// 3102SN/A 311395SN/A// Map of class names to SerializableBuilder creation functions. 3122SN/A// Need to make this a pointer so we can force initialization on the 313395SN/A// first reference; otherwise, some SerializableClass constructors 3142SN/A// may be invoked before the classMap constructor. 315395SN/Amap<string,SerializableClass::CreateFunc> *SerializableClass::classMap = 0; 3162SN/A 317395SN/A// SerializableClass constructor: add mapping to classMap 318395SN/ASerializableClass::SerializableClass(const string &className, 3192SN/A CreateFunc createFunc) 3202SN/A{ 3212SN/A if (classMap == NULL) 322395SN/A classMap = new map<string,SerializableClass::CreateFunc>(); 3232SN/A 3242SN/A if ((*classMap)[className]) 3252SN/A { 3262SN/A cerr << "Error: simulation object class " << className << " redefined" 3272SN/A << endl; 3282SN/A fatal(""); 3292SN/A } 3302SN/A 3312SN/A // add className --> createFunc to class map 3322SN/A (*classMap)[className] = createFunc; 3332SN/A} 3342SN/A 3352SN/A 3362SN/A// 3372SN/A// 338395SN/ASerializable * 339395SN/ASerializableClass::createObject(Checkpoint *cp, 340237SN/A const std::string §ion) 3412SN/A{ 342237SN/A string className; 3432SN/A 344237SN/A if (!cp->find(section, "type", className)) { 345395SN/A fatal("Serializable::create: no 'type' entry in section '%s'.\n", 346237SN/A section); 3472SN/A } 3482SN/A 349237SN/A CreateFunc createFunc = (*classMap)[className]; 350237SN/A 351237SN/A if (createFunc == NULL) { 352395SN/A fatal("Serializable::create: no create function for class '%s'.\n", 353237SN/A className); 3542SN/A } 3552SN/A 356395SN/A Serializable *object = createFunc(cp, section); 3572SN/A 3582SN/A assert(object != NULL); 3592SN/A 3602SN/A return object; 3612SN/A} 3622SN/A 363237SN/A 364395SN/ASerializable * 365395SN/ASerializable::create(Checkpoint *cp, const std::string §ion) 366237SN/A{ 367395SN/A Serializable *object = SerializableClass::createObject(cp, section); 368237SN/A object->unserialize(cp, section); 369237SN/A return object; 370237SN/A} 371237SN/A 372237SN/A 3732738Sstever@eecs.umich.eduCheckpoint::Checkpoint(const std::string &cpt_dir, const std::string &path) 3742738Sstever@eecs.umich.edu : db(new IniFile), basePath(path), cptDir(cpt_dir) 375237SN/A{ 376449SN/A string filename = cpt_dir + "/" + Checkpoint::baseFilename; 377237SN/A if (!db->load(filename)) { 378237SN/A fatal("Can't load checkpoint file '%s'\n", filename); 379237SN/A } 380237SN/A} 381237SN/A 382237SN/A 383237SN/Abool 384237SN/ACheckpoint::find(const std::string §ion, const std::string &entry, 385237SN/A std::string &value) 386237SN/A{ 387237SN/A return db->find(section, entry, value); 388237SN/A} 389237SN/A 390237SN/A 391237SN/Abool 392237SN/ACheckpoint::findObj(const std::string §ion, const std::string &entry, 3934000Ssaidi@eecs.umich.edu SimObject *&value) 394237SN/A{ 395237SN/A string path; 396237SN/A 397237SN/A if (!db->find(section, entry, path)) 398237SN/A return false; 399237SN/A 4004000Ssaidi@eecs.umich.edu value = resolveSimObject(path); 4014000Ssaidi@eecs.umich.edu return true; 402237SN/A} 403304SN/A 404304SN/A 405304SN/Abool 406304SN/ACheckpoint::sectionExists(const std::string §ion) 407304SN/A{ 408304SN/A return db->sectionExists(section); 409304SN/A} 4102356SN/A 4112356SN/A/** Hacked stat reset event */ 4122356SN/A 4132356SN/Aclass StatresetParamContext : public ParamContext 4142356SN/A{ 4152356SN/A public: 4162356SN/A StatresetParamContext(const string §ion); 4172356SN/A ~StatresetParamContext(); 4182356SN/A void startup(); 4192356SN/A}; 4202356SN/A 4212356SN/AStatresetParamContext statParams("statsreset"); 4222356SN/A 4232356SN/AParam<Tick> reset_cycle(&statParams, "reset_cycle", 4242356SN/A "Cycle to reset stats on", 0); 4252356SN/A 4262356SN/AStatresetParamContext::StatresetParamContext(const string §ion) 4272356SN/A : ParamContext(section) 4282356SN/A{ } 4292356SN/A 4302356SN/AStatresetParamContext::~StatresetParamContext() 4312356SN/A{ 4322356SN/A} 4332356SN/A 4342356SN/Avoid 4352356SN/AStatresetParamContext::startup() 4362356SN/A{ 4372356SN/A if (reset_cycle > 0) { 4382356SN/A Stats::SetupEvent(Stats::Reset, curTick + reset_cycle, 0); 4392356SN/A cprintf("Stats reset event scheduled for %lli\n", 4402356SN/A curTick + reset_cycle); 4412356SN/A } 4422356SN/A} 443