serialize.cc revision 1354
16313Sgblack@eecs.umich.edu/* 26313Sgblack@eecs.umich.edu * Copyright (c) 2002-2004 The Regents of The University of Michigan 36313Sgblack@eecs.umich.edu * All rights reserved. 46313Sgblack@eecs.umich.edu * 56313Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 66313Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are 76313Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright 86313Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 96313Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 106313Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 116313Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution; 126313Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its 136313Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from 146313Sgblack@eecs.umich.edu * this software without specific prior written permission. 156313Sgblack@eecs.umich.edu * 166313Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 176313Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 186313Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 196313Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 206313Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 216313Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 226313Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 236313Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 246313Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 256313Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 266313Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 276313Sgblack@eecs.umich.edu */ 286313Sgblack@eecs.umich.edu 296313Sgblack@eecs.umich.edu#include <sys/time.h> 306313Sgblack@eecs.umich.edu#include <sys/types.h> 316313Sgblack@eecs.umich.edu#include <sys/stat.h> 326313Sgblack@eecs.umich.edu#include <errno.h> 336313Sgblack@eecs.umich.edu 348229Snate@binkert.org#include <fstream> 358229Snate@binkert.org#include <list> 368229Snate@binkert.org#include <string> 377629Sgblack@eecs.umich.edu#include <vector> 387629Sgblack@eecs.umich.edu 398229Snate@binkert.org#include "base/inifile.hh" 406336Sgblack@eecs.umich.edu#include "base/misc.hh" 416336Sgblack@eecs.umich.edu#include "base/str.hh" 426313Sgblack@eecs.umich.edu#include "base/trace.hh" 436313Sgblack@eecs.umich.edu#include "sim/config_node.hh" 446336Sgblack@eecs.umich.edu#include "sim/eventq.hh" 456313Sgblack@eecs.umich.edu#include "sim/param.hh" 466313Sgblack@eecs.umich.edu#include "sim/serialize.hh" 476313Sgblack@eecs.umich.edu#include "sim/sim_events.hh" 486313Sgblack@eecs.umich.edu#include "sim/sim_object.hh" 496313Sgblack@eecs.umich.edu 506313Sgblack@eecs.umich.eduusing namespace std; 516336Sgblack@eecs.umich.edu 526336Sgblack@eecs.umich.eduvoid 539376Sgblack@eecs.umich.eduSerializable::nameOut(ostream &os) 549376Sgblack@eecs.umich.edu{ 556313Sgblack@eecs.umich.edu os << "\n[" << name() << "]\n"; 566313Sgblack@eecs.umich.edu} 576313Sgblack@eecs.umich.edu 586313Sgblack@eecs.umich.eduvoid 596336Sgblack@eecs.umich.eduSerializable::nameOut(ostream &os, const string &_name) 606336Sgblack@eecs.umich.edu{ 616336Sgblack@eecs.umich.edu os << "\n[" << _name << "]\n"; 626336Sgblack@eecs.umich.edu} 636336Sgblack@eecs.umich.edu 646313Sgblack@eecs.umich.edutemplate <class T> 656313Sgblack@eecs.umich.eduvoid 666313Sgblack@eecs.umich.eduparamOut(ostream &os, const std::string &name, const T ¶m) 676336Sgblack@eecs.umich.edu{ 686336Sgblack@eecs.umich.edu os << name << "="; 696313Sgblack@eecs.umich.edu showParam(os, param); 706359Sgblack@eecs.umich.edu os << "\n"; 716359Sgblack@eecs.umich.edu} 726359Sgblack@eecs.umich.edu 736361Sgblack@eecs.umich.edu 746359Sgblack@eecs.umich.edutemplate <class T> 756359Sgblack@eecs.umich.eduvoid 766359Sgblack@eecs.umich.eduparamIn(Checkpoint *cp, const std::string §ion, 776359Sgblack@eecs.umich.edu const std::string &name, T ¶m) 786359Sgblack@eecs.umich.edu{ 796359Sgblack@eecs.umich.edu std::string str; 806359Sgblack@eecs.umich.edu if (!cp->find(section, name, str) || !parseParam(str, param)) { 816359Sgblack@eecs.umich.edu fatal("Can't unserialize '%s:%s'\n", section, name); 826359Sgblack@eecs.umich.edu } 836359Sgblack@eecs.umich.edu} 846359Sgblack@eecs.umich.edu 856313Sgblack@eecs.umich.edu 866313Sgblack@eecs.umich.edutemplate <class T> 876313Sgblack@eecs.umich.eduvoid 886313Sgblack@eecs.umich.eduarrayParamOut(ostream &os, const std::string &name, 896313Sgblack@eecs.umich.edu const T *param, int size) 906313Sgblack@eecs.umich.edu{ 916313Sgblack@eecs.umich.edu os << name << "="; 926313Sgblack@eecs.umich.edu if (size > 0) 93 showParam(os, param[0]); 94 for (int i = 1; i < size; ++i) { 95 os << " "; 96 showParam(os, param[i]); 97 } 98 os << "\n"; 99} 100 101 102template <class T> 103void 104arrayParamIn(Checkpoint *cp, const std::string §ion, 105 const std::string &name, T *param, int size) 106{ 107 std::string str; 108 if (!cp->find(section, name, str)) { 109 fatal("Can't unserialize '%s:%s'\n", section, name); 110 } 111 112 // code below stolen from VectorParam<T>::parse(). 113 // it would be nice to unify these somehow... 114 115 vector<string> tokens; 116 117 tokenize(tokens, str, ' '); 118 119 // Need this if we were doing a vector 120 // value.resize(tokens.size()); 121 122 if (tokens.size() != size) { 123 fatal("Array size mismatch on %s:%s'\n", section, name); 124 } 125 126 for (int i = 0; i < tokens.size(); i++) { 127 // need to parse into local variable to handle vector<bool>, 128 // for which operator[] returns a special reference class 129 // that's not the same as 'bool&', (since it's a packed 130 // vector) 131 T scalar_value; 132 if (!parseParam(tokens[i], scalar_value)) { 133 string err("could not parse \""); 134 135 err += str; 136 err += "\""; 137 138 fatal(err); 139 } 140 141 // assign parsed value to vector 142 param[i] = scalar_value; 143 } 144} 145 146 147void 148objParamIn(Checkpoint *cp, const std::string §ion, 149 const std::string &name, Serializable * ¶m) 150{ 151 if (!cp->findObj(section, name, param)) { 152 fatal("Can't unserialize '%s:%s'\n", section, name); 153 } 154} 155 156 157#define INSTANTIATE_PARAM_TEMPLATES(type) \ 158template void \ 159paramOut(ostream &os, const std::string &name, type const ¶m); \ 160template void \ 161paramIn(Checkpoint *cp, const std::string §ion, \ 162 const std::string &name, type & param); \ 163template void \ 164arrayParamOut(ostream &os, const std::string &name, \ 165 type const *param, int size); \ 166template void \ 167arrayParamIn(Checkpoint *cp, const std::string §ion, \ 168 const std::string &name, type *param, int size); 169 170 171INSTANTIATE_PARAM_TEMPLATES(int8_t) 172INSTANTIATE_PARAM_TEMPLATES(uint8_t) 173INSTANTIATE_PARAM_TEMPLATES(int16_t) 174INSTANTIATE_PARAM_TEMPLATES(uint16_t) 175INSTANTIATE_PARAM_TEMPLATES(int32_t) 176INSTANTIATE_PARAM_TEMPLATES(uint32_t) 177INSTANTIATE_PARAM_TEMPLATES(int64_t) 178INSTANTIATE_PARAM_TEMPLATES(uint64_t) 179INSTANTIATE_PARAM_TEMPLATES(bool) 180INSTANTIATE_PARAM_TEMPLATES(string) 181 182 183///////////////////////////// 184 185/// Container for serializing global variables (not associated with 186/// any serialized object). 187class Globals : public Serializable 188{ 189 public: 190 const string name() const; 191 void serialize(ostream &os); 192 void unserialize(Checkpoint *cp); 193}; 194 195/// The one and only instance of the Globals class. 196Globals globals; 197 198const string 199Globals::name() const 200{ 201 return "Globals"; 202} 203 204void 205Globals::serialize(ostream &os) 206{ 207 nameOut(os); 208 SERIALIZE_SCALAR(curTick); 209 210 nameOut(os, "MainEventQueue"); 211 mainEventQueue.serialize(os); 212} 213 214void 215Globals::unserialize(Checkpoint *cp) 216{ 217 const string §ion = name(); 218 UNSERIALIZE_SCALAR(curTick); 219 220 mainEventQueue.unserialize(cp, "MainEventQueue"); 221} 222 223void 224Serializable::serializeAll() 225{ 226 string dir = Checkpoint::dir(); 227 if (mkdir(dir.c_str(), 0775) == -1 && errno != EEXIST) 228 fatal("couldn't mkdir %s\n", dir); 229 230 string cpt_file = dir + Checkpoint::baseFilename; 231 ofstream outstream(cpt_file.c_str()); 232 time_t t = time(NULL); 233 outstream << "// checkpoint generated: " << ctime(&t); 234 235 globals.serialize(outstream); 236 SimObject::serializeAll(outstream); 237} 238 239 240void 241Serializable::unserializeGlobals(Checkpoint *cp) 242{ 243 globals.unserialize(cp); 244} 245 246 247class SerializeEvent : public Event 248{ 249 protected: 250 Tick repeat; 251 252 public: 253 SerializeEvent(Tick _when, Tick _repeat); 254 virtual void process(); 255 virtual void serialize(std::ostream &os) 256 { 257 panic("Cannot serialize the SerializeEvent"); 258 } 259 260}; 261 262SerializeEvent::SerializeEvent(Tick _when, Tick _repeat) 263 : Event(&mainEventQueue, Serialize_Pri), repeat(_repeat) 264{ 265 setFlags(AutoDelete); 266 schedule(_when); 267} 268 269void 270SerializeEvent::process() 271{ 272 Serializable::serializeAll(); 273 if (repeat) 274 schedule(curTick + repeat); 275} 276 277const char *Checkpoint::baseFilename = "m5.cpt"; 278 279static string checkpointDirBase; 280 281string 282Checkpoint::dir() 283{ 284 // use csprintf to insert curTick into directory name if it 285 // appears to have a format placeholder in it. 286 return (checkpointDirBase.find("%") != string::npos) ? 287 csprintf(checkpointDirBase, curTick) : checkpointDirBase; 288} 289 290void 291Checkpoint::setup(Tick when, Tick period) 292{ 293 new SerializeEvent(when, period); 294} 295 296class SerializeParamContext : public ParamContext 297{ 298 private: 299 SerializeEvent *event; 300 301 public: 302 SerializeParamContext(const string §ion); 303 ~SerializeParamContext(); 304 void checkParams(); 305}; 306 307SerializeParamContext serialParams("serialize"); 308 309Param<string> serialize_dir(&serialParams, "dir", 310 "dir to stick checkpoint in " 311 "(sprintf format with cycle #)"); 312 313Param<Counter> serialize_cycle(&serialParams, 314 "cycle", 315 "cycle to serialize", 316 0); 317 318Param<Counter> serialize_period(&serialParams, 319 "period", 320 "period to repeat serializations", 321 0); 322 323 324 325SerializeParamContext::SerializeParamContext(const string §ion) 326 : ParamContext(section), event(NULL) 327{ } 328 329SerializeParamContext::~SerializeParamContext() 330{ 331} 332 333void 334SerializeParamContext::checkParams() 335{ 336 if (serialize_dir.isValid()) { 337 checkpointDirBase = serialize_dir; 338 } else { 339 checkpointDirBase = outputDirectory + "cpt.%012d"; 340 } 341 342 // guarantee that directory ends with a '/' 343 if (checkpointDirBase[checkpointDirBase.size() - 1] != '/') 344 checkpointDirBase += "/"; 345 346 if (serialize_cycle > 0) 347 Checkpoint::setup(serialize_cycle, serialize_period); 348} 349 350void 351debug_serialize() 352{ 353 Serializable::serializeAll(); 354} 355 356void 357debug_serialize(Tick when) 358{ 359 new SerializeEvent(when, 0); 360} 361 362//////////////////////////////////////////////////////////////////////// 363// 364// SerializableClass member definitions 365// 366//////////////////////////////////////////////////////////////////////// 367 368// Map of class names to SerializableBuilder creation functions. 369// Need to make this a pointer so we can force initialization on the 370// first reference; otherwise, some SerializableClass constructors 371// may be invoked before the classMap constructor. 372map<string,SerializableClass::CreateFunc> *SerializableClass::classMap = 0; 373 374// SerializableClass constructor: add mapping to classMap 375SerializableClass::SerializableClass(const string &className, 376 CreateFunc createFunc) 377{ 378 if (classMap == NULL) 379 classMap = new map<string,SerializableClass::CreateFunc>(); 380 381 if ((*classMap)[className]) 382 { 383 cerr << "Error: simulation object class " << className << " redefined" 384 << endl; 385 fatal(""); 386 } 387 388 // add className --> createFunc to class map 389 (*classMap)[className] = createFunc; 390} 391 392 393// 394// 395Serializable * 396SerializableClass::createObject(Checkpoint *cp, 397 const std::string §ion) 398{ 399 string className; 400 401 if (!cp->find(section, "type", className)) { 402 fatal("Serializable::create: no 'type' entry in section '%s'.\n", 403 section); 404 } 405 406 CreateFunc createFunc = (*classMap)[className]; 407 408 if (createFunc == NULL) { 409 fatal("Serializable::create: no create function for class '%s'.\n", 410 className); 411 } 412 413 Serializable *object = createFunc(cp, section); 414 415 assert(object != NULL); 416 417 return object; 418} 419 420 421Serializable * 422Serializable::create(Checkpoint *cp, const std::string §ion) 423{ 424 Serializable *object = SerializableClass::createObject(cp, section); 425 object->unserialize(cp, section); 426 return object; 427} 428 429 430Checkpoint::Checkpoint(const std::string &cpt_dir, const std::string &path, 431 const ConfigNode *_configNode) 432 : db(new IniFile), basePath(path), configNode(_configNode), cptDir(cpt_dir) 433{ 434 string filename = cpt_dir + "/" + Checkpoint::baseFilename; 435 if (!db->load(filename)) { 436 fatal("Can't load checkpoint file '%s'\n", filename); 437 } 438} 439 440 441bool 442Checkpoint::find(const std::string §ion, const std::string &entry, 443 std::string &value) 444{ 445 return db->find(section, entry, value); 446} 447 448 449bool 450Checkpoint::findObj(const std::string §ion, const std::string &entry, 451 Serializable *&value) 452{ 453 string path; 454 455 if (!db->find(section, entry, path)) 456 return false; 457 458 if ((value = configNode->resolveSimObject(path)) != NULL) 459 return true; 460 461 if ((value = objMap[path]) != NULL) 462 return true; 463 464 return false; 465} 466 467 468bool 469Checkpoint::sectionExists(const std::string §ion) 470{ 471 return db->sectionExists(section); 472} 473