serialize.cc revision 4000
112853Sgabeblack@google.com/* 212853Sgabeblack@google.com * Copyright (c) 2002-2005 The Regents of The University of Michigan 312853Sgabeblack@google.com * All rights reserved. 412853Sgabeblack@google.com * 512853Sgabeblack@google.com * Redistribution and use in source and binary forms, with or without 612853Sgabeblack@google.com * modification, are permitted provided that the following conditions are 712853Sgabeblack@google.com * met: redistributions of source code must retain the above copyright 812853Sgabeblack@google.com * notice, this list of conditions and the following disclaimer; 912853Sgabeblack@google.com * redistributions in binary form must reproduce the above copyright 1012853Sgabeblack@google.com * notice, this list of conditions and the following disclaimer in the 1112853Sgabeblack@google.com * documentation and/or other materials provided with the distribution; 1212853Sgabeblack@google.com * neither the name of the copyright holders nor the names of its 1312853Sgabeblack@google.com * contributors may be used to endorse or promote products derived from 1412853Sgabeblack@google.com * this software without specific prior written permission. 1512853Sgabeblack@google.com * 1612853Sgabeblack@google.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1712853Sgabeblack@google.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1812853Sgabeblack@google.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1912853Sgabeblack@google.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2012853Sgabeblack@google.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2112853Sgabeblack@google.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2212853Sgabeblack@google.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2312853Sgabeblack@google.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2412853Sgabeblack@google.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2512853Sgabeblack@google.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2612853Sgabeblack@google.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2712853Sgabeblack@google.com * 2812853Sgabeblack@google.com * Authors: Nathan Binkert 2912853Sgabeblack@google.com * Erik Hallnor 3012853Sgabeblack@google.com * Steve Reinhardt 3112853Sgabeblack@google.com */ 3212853Sgabeblack@google.com 3312853Sgabeblack@google.com#include <sys/time.h> 3412853Sgabeblack@google.com#include <sys/types.h> 3512853Sgabeblack@google.com#include <sys/stat.h> 3612853Sgabeblack@google.com#include <errno.h> 3712853Sgabeblack@google.com 3812853Sgabeblack@google.com#include <fstream> 3912853Sgabeblack@google.com#include <list> 4012853Sgabeblack@google.com#include <string> 4112853Sgabeblack@google.com#include <vector> 4212853Sgabeblack@google.com 4312853Sgabeblack@google.com#include "base/inifile.hh" 4412853Sgabeblack@google.com#include "base/misc.hh" 4512853Sgabeblack@google.com#include "base/output.hh" 4612853Sgabeblack@google.com#include "base/str.hh" 4712853Sgabeblack@google.com#include "base/trace.hh" 4812853Sgabeblack@google.com#include "sim/eventq.hh" 4912853Sgabeblack@google.com#include "sim/param.hh" 5012853Sgabeblack@google.com#include "sim/serialize.hh" 5112853Sgabeblack@google.com#include "sim/sim_events.hh" 5212853Sgabeblack@google.com#include "sim/sim_exit.hh" 5312853Sgabeblack@google.com#include "sim/sim_object.hh" 5412853Sgabeblack@google.com 5512853Sgabeblack@google.com// For stat reset hack 5612853Sgabeblack@google.com#include "sim/stat_control.hh" 5712853Sgabeblack@google.com 5812853Sgabeblack@google.comusing namespace std; 5912853Sgabeblack@google.com 6012853Sgabeblack@google.comextern SimObject *resolveSimObject(const string &); 6112853Sgabeblack@google.com 6212853Sgabeblack@google.comint Serializable::ckptMaxCount = 0; 6312853Sgabeblack@google.comint Serializable::ckptCount = 0; 6412853Sgabeblack@google.comint Serializable::ckptPrevCount = -1; 6512853Sgabeblack@google.com 6612853Sgabeblack@google.comvoid 6712853Sgabeblack@google.comSerializable::nameOut(ostream &os) 6812853Sgabeblack@google.com{ 6912853Sgabeblack@google.com os << "\n[" << name() << "]\n"; 7012853Sgabeblack@google.com} 7112853Sgabeblack@google.com 7212853Sgabeblack@google.comvoid 7312853Sgabeblack@google.comSerializable::nameOut(ostream &os, const string &_name) 7412853Sgabeblack@google.com{ 7512853Sgabeblack@google.com os << "\n[" << _name << "]\n"; 7613325Sgabeblack@google.com} 7713325Sgabeblack@google.com 7813325Sgabeblack@google.comtemplate <class T> 7913325Sgabeblack@google.comvoid 8013325Sgabeblack@google.comparamOut(ostream &os, const std::string &name, const T ¶m) 8113325Sgabeblack@google.com{ 8213325Sgabeblack@google.com os << name << "="; 8313325Sgabeblack@google.com showParam(os, param); 8413325Sgabeblack@google.com os << "\n"; 8513325Sgabeblack@google.com} 8613325Sgabeblack@google.com 8713325Sgabeblack@google.com 8812853Sgabeblack@google.comtemplate <class T> 89void 90paramIn(Checkpoint *cp, const std::string §ion, 91 const std::string &name, T ¶m) 92{ 93 std::string str; 94 if (!cp->find(section, name, str) || !parseParam(str, param)) { 95 fatal("Can't unserialize '%s:%s'\n", section, name); 96 } 97} 98 99 100template <class T> 101void 102arrayParamOut(ostream &os, const std::string &name, 103 const T *param, int size) 104{ 105 os << name << "="; 106 if (size > 0) 107 showParam(os, param[0]); 108 for (int i = 1; i < size; ++i) { 109 os << " "; 110 showParam(os, param[i]); 111 } 112 os << "\n"; 113} 114 115 116template <class T> 117void 118arrayParamIn(Checkpoint *cp, const std::string §ion, 119 const std::string &name, T *param, int size) 120{ 121 std::string str; 122 if (!cp->find(section, name, str)) { 123 fatal("Can't unserialize '%s:%s'\n", section, name); 124 } 125 126 // code below stolen from VectorParam<T>::parse(). 127 // it would be nice to unify these somehow... 128 129 vector<string> tokens; 130 131 tokenize(tokens, str, ' '); 132 133 // Need this if we were doing a vector 134 // value.resize(tokens.size()); 135 136 if (tokens.size() != size) { 137 fatal("Array size mismatch on %s:%s'\n", section, name); 138 } 139 140 for (int i = 0; i < tokens.size(); i++) { 141 // need to parse into local variable to handle vector<bool>, 142 // for which operator[] returns a special reference class 143 // that's not the same as 'bool&', (since it's a packed 144 // vector) 145 T scalar_value; 146 if (!parseParam(tokens[i], scalar_value)) { 147 string err("could not parse \""); 148 149 err += str; 150 err += "\""; 151 152 fatal(err); 153 } 154 155 // assign parsed value to vector 156 param[i] = scalar_value; 157 } 158} 159 160 161void 162objParamIn(Checkpoint *cp, const std::string §ion, 163 const std::string &name, SimObject * ¶m) 164{ 165 if (!cp->findObj(section, name, param)) { 166 fatal("Can't unserialize '%s:%s'\n", section, name); 167 } 168} 169 170 171#define INSTANTIATE_PARAM_TEMPLATES(type) \ 172template void \ 173paramOut(ostream &os, const std::string &name, type const ¶m); \ 174template void \ 175paramIn(Checkpoint *cp, const std::string §ion, \ 176 const std::string &name, type & param); \ 177template void \ 178arrayParamOut(ostream &os, const std::string &name, \ 179 type const *param, int size); \ 180template void \ 181arrayParamIn(Checkpoint *cp, const std::string §ion, \ 182 const std::string &name, type *param, int size); 183 184INSTANTIATE_PARAM_TEMPLATES(signed char) 185INSTANTIATE_PARAM_TEMPLATES(unsigned char) 186INSTANTIATE_PARAM_TEMPLATES(signed short) 187INSTANTIATE_PARAM_TEMPLATES(unsigned short) 188INSTANTIATE_PARAM_TEMPLATES(signed int) 189INSTANTIATE_PARAM_TEMPLATES(unsigned int) 190INSTANTIATE_PARAM_TEMPLATES(signed long) 191INSTANTIATE_PARAM_TEMPLATES(unsigned long) 192INSTANTIATE_PARAM_TEMPLATES(signed long long) 193INSTANTIATE_PARAM_TEMPLATES(unsigned long long) 194INSTANTIATE_PARAM_TEMPLATES(bool) 195INSTANTIATE_PARAM_TEMPLATES(string) 196 197 198///////////////////////////// 199 200/// Container for serializing global variables (not associated with 201/// any serialized object). 202class Globals : public Serializable 203{ 204 public: 205 const string name() const; 206 void serialize(ostream &os); 207 void unserialize(Checkpoint *cp); 208}; 209 210/// The one and only instance of the Globals class. 211Globals globals; 212 213const string 214Globals::name() const 215{ 216 return "Globals"; 217} 218 219void 220Globals::serialize(ostream &os) 221{ 222 nameOut(os); 223 SERIALIZE_SCALAR(curTick); 224 225 nameOut(os, "MainEventQueue"); 226 mainEventQueue.serialize(os); 227} 228 229void 230Globals::unserialize(Checkpoint *cp) 231{ 232 const string §ion = name(); 233 UNSERIALIZE_SCALAR(curTick); 234 235 mainEventQueue.unserialize(cp, "MainEventQueue"); 236} 237 238void 239Serializable::serializeAll(const std::string &cpt_dir) 240{ 241 setCheckpointDir(cpt_dir); 242 string dir = Checkpoint::dir(); 243 if (mkdir(dir.c_str(), 0775) == -1 && errno != EEXIST) 244 fatal("couldn't mkdir %s\n", dir); 245 246 string cpt_file = dir + Checkpoint::baseFilename; 247 ofstream outstream(cpt_file.c_str()); 248 time_t t = time(NULL); 249 outstream << "// checkpoint generated: " << ctime(&t); 250 251 globals.serialize(outstream); 252 SimObject::serializeAll(outstream); 253} 254 255void 256Serializable::unserializeAll(const std::string &cpt_dir) 257{ 258 setCheckpointDir(cpt_dir); 259 string dir = Checkpoint::dir(); 260 string cpt_file = dir + Checkpoint::baseFilename; 261 string section = ""; 262 263 DPRINTFR(Config, "Loading checkpoint dir '%s'\n", 264 dir); 265 Checkpoint *cp = new Checkpoint(dir, section); 266 unserializeGlobals(cp); 267 268 SimObject::unserializeAll(cp); 269} 270 271void 272Serializable::unserializeGlobals(Checkpoint *cp) 273{ 274 globals.unserialize(cp); 275} 276 277const char *Checkpoint::baseFilename = "m5.cpt"; 278 279static string checkpointDirBase; 280 281void 282setCheckpointDir(const std::string &name) 283{ 284 checkpointDirBase = name; 285 if (checkpointDirBase[checkpointDirBase.size() - 1] != '/') 286 checkpointDirBase += "/"; 287} 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 299debug_serialize(const std::string &cpt_dir) 300{ 301 Serializable::serializeAll(cpt_dir); 302} 303 304 305//////////////////////////////////////////////////////////////////////// 306// 307// SerializableClass member definitions 308// 309//////////////////////////////////////////////////////////////////////// 310 311// Map of class names to SerializableBuilder creation functions. 312// Need to make this a pointer so we can force initialization on the 313// first reference; otherwise, some SerializableClass constructors 314// may be invoked before the classMap constructor. 315map<string,SerializableClass::CreateFunc> *SerializableClass::classMap = 0; 316 317// SerializableClass constructor: add mapping to classMap 318SerializableClass::SerializableClass(const string &className, 319 CreateFunc createFunc) 320{ 321 if (classMap == NULL) 322 classMap = new map<string,SerializableClass::CreateFunc>(); 323 324 if ((*classMap)[className]) 325 { 326 cerr << "Error: simulation object class " << className << " redefined" 327 << endl; 328 fatal(""); 329 } 330 331 // add className --> createFunc to class map 332 (*classMap)[className] = createFunc; 333} 334 335 336// 337// 338Serializable * 339SerializableClass::createObject(Checkpoint *cp, 340 const std::string §ion) 341{ 342 string className; 343 344 if (!cp->find(section, "type", className)) { 345 fatal("Serializable::create: no 'type' entry in section '%s'.\n", 346 section); 347 } 348 349 CreateFunc createFunc = (*classMap)[className]; 350 351 if (createFunc == NULL) { 352 fatal("Serializable::create: no create function for class '%s'.\n", 353 className); 354 } 355 356 Serializable *object = createFunc(cp, section); 357 358 assert(object != NULL); 359 360 return object; 361} 362 363 364Serializable * 365Serializable::create(Checkpoint *cp, const std::string §ion) 366{ 367 Serializable *object = SerializableClass::createObject(cp, section); 368 object->unserialize(cp, section); 369 return object; 370} 371 372 373Checkpoint::Checkpoint(const std::string &cpt_dir, const std::string &path) 374 : db(new IniFile), basePath(path), cptDir(cpt_dir) 375{ 376 string filename = cpt_dir + "/" + Checkpoint::baseFilename; 377 if (!db->load(filename)) { 378 fatal("Can't load checkpoint file '%s'\n", filename); 379 } 380} 381 382 383bool 384Checkpoint::find(const std::string §ion, const std::string &entry, 385 std::string &value) 386{ 387 return db->find(section, entry, value); 388} 389 390 391bool 392Checkpoint::findObj(const std::string §ion, const std::string &entry, 393 SimObject *&value) 394{ 395 string path; 396 397 if (!db->find(section, entry, path)) 398 return false; 399 400 value = resolveSimObject(path); 401 return true; 402} 403 404 405bool 406Checkpoint::sectionExists(const std::string §ion) 407{ 408 return db->sectionExists(section); 409} 410 411/** Hacked stat reset event */ 412 413class StatresetParamContext : public ParamContext 414{ 415 public: 416 StatresetParamContext(const string §ion); 417 ~StatresetParamContext(); 418 void startup(); 419}; 420 421StatresetParamContext statParams("statsreset"); 422 423Param<Tick> reset_cycle(&statParams, "reset_cycle", 424 "Cycle to reset stats on", 0); 425 426StatresetParamContext::StatresetParamContext(const string §ion) 427 : ParamContext(section) 428{ } 429 430StatresetParamContext::~StatresetParamContext() 431{ 432} 433 434void 435StatresetParamContext::startup() 436{ 437 if (reset_cycle > 0) { 438 Stats::SetupEvent(Stats::Reset, curTick + reset_cycle, 0); 439 cprintf("Stats reset event scheduled for %lli\n", 440 curTick + reset_cycle); 441 } 442} 443