serialize.cc revision 512
113465Sgabeblack@google.com/* 213465Sgabeblack@google.com * Copyright (c) 2003 The Regents of The University of Michigan 313465Sgabeblack@google.com * All rights reserved. 413465Sgabeblack@google.com * 513465Sgabeblack@google.com * Redistribution and use in source and binary forms, with or without 613465Sgabeblack@google.com * modification, are permitted provided that the following conditions are 713465Sgabeblack@google.com * met: redistributions of source code must retain the above copyright 813465Sgabeblack@google.com * notice, this list of conditions and the following disclaimer; 913465Sgabeblack@google.com * redistributions in binary form must reproduce the above copyright 1013465Sgabeblack@google.com * notice, this list of conditions and the following disclaimer in the 1113465Sgabeblack@google.com * documentation and/or other materials provided with the distribution; 1213465Sgabeblack@google.com * neither the name of the copyright holders nor the names of its 1313465Sgabeblack@google.com * contributors may be used to endorse or promote products derived from 1413465Sgabeblack@google.com * this software without specific prior written permission. 1513465Sgabeblack@google.com * 1613465Sgabeblack@google.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1713465Sgabeblack@google.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1813465Sgabeblack@google.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1913465Sgabeblack@google.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2013465Sgabeblack@google.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2113465Sgabeblack@google.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2213465Sgabeblack@google.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2313465Sgabeblack@google.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2413465Sgabeblack@google.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2513465Sgabeblack@google.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2613465Sgabeblack@google.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2713465Sgabeblack@google.com */ 2813465Sgabeblack@google.com 2913465Sgabeblack@google.com#include <sys/time.h> 3013465Sgabeblack@google.com#include <sys/types.h> 3113465Sgabeblack@google.com#include <sys/stat.h> 3213465Sgabeblack@google.com 3313465Sgabeblack@google.com#include <fstream> 3413465Sgabeblack@google.com#include <list> 3513465Sgabeblack@google.com#include <string> 3613465Sgabeblack@google.com#include <vector> 3713465Sgabeblack@google.com 3813465Sgabeblack@google.com#include "base/inifile.hh" 3913465Sgabeblack@google.com#include "base/misc.hh" 4013465Sgabeblack@google.com#include "base/str.hh" 4113465Sgabeblack@google.com#include "base/trace.hh" 4213465Sgabeblack@google.com#include "sim/config_node.hh" 4313465Sgabeblack@google.com#include "sim/eventq.hh" 4413465Sgabeblack@google.com#include "sim/param.hh" 4513465Sgabeblack@google.com#include "sim/serialize.hh" 4613465Sgabeblack@google.com#include "sim/sim_events.hh" 4713465Sgabeblack@google.com#include "sim/sim_object.hh" 4813465Sgabeblack@google.com 4913465Sgabeblack@google.comusing namespace std; 5013465Sgabeblack@google.com 5113465Sgabeblack@google.comvoid 5213465Sgabeblack@google.comSerializable::nameOut(ostream &os) 5313465Sgabeblack@google.com{ 5413465Sgabeblack@google.com os << "\n[" << name() << "]\n"; 5513465Sgabeblack@google.com} 5613465Sgabeblack@google.com 5713465Sgabeblack@google.comvoid 5813465Sgabeblack@google.comSerializable::nameOut(ostream &os, const string &_name) 5913465Sgabeblack@google.com{ 6013465Sgabeblack@google.com os << "\n[" << _name << "]\n"; 6113465Sgabeblack@google.com} 6213465Sgabeblack@google.com 6313465Sgabeblack@google.comtemplate <class T> 6413465Sgabeblack@google.comvoid 6513465Sgabeblack@google.comparamOut(ostream &os, const std::string &name, const T ¶m) 6613465Sgabeblack@google.com{ 6713465Sgabeblack@google.com os << name << "="; 6813465Sgabeblack@google.com showParam(os, param); 6913465Sgabeblack@google.com os << "\n"; 7013465Sgabeblack@google.com} 7113465Sgabeblack@google.com 7213465Sgabeblack@google.com 7313465Sgabeblack@google.comtemplate <class T> 7413465Sgabeblack@google.comvoid 7513465Sgabeblack@google.comparamIn(Checkpoint *cp, const std::string §ion, 7613465Sgabeblack@google.com const std::string &name, T ¶m) 7713465Sgabeblack@google.com{ 7813465Sgabeblack@google.com std::string str; 7913465Sgabeblack@google.com if (!cp->find(section, name, str) || !parseParam(str, param)) { 8013465Sgabeblack@google.com fatal("Can't unserialize '%s:%s'\n", section, name); 8113465Sgabeblack@google.com } 8213465Sgabeblack@google.com} 8313465Sgabeblack@google.com 8413465Sgabeblack@google.com 8513465Sgabeblack@google.comtemplate <class T> 8613465Sgabeblack@google.comvoid 8713465Sgabeblack@google.comarrayParamOut(ostream &os, const std::string &name, 8813465Sgabeblack@google.com const T *param, int size) 8913465Sgabeblack@google.com{ 9013465Sgabeblack@google.com os << name << "="; 9113465Sgabeblack@google.com if (size > 0) 9213465Sgabeblack@google.com showParam(os, param[0]); 9313465Sgabeblack@google.com for (int i = 1; i < size; ++i) { 9413465Sgabeblack@google.com os << " "; 9513465Sgabeblack@google.com showParam(os, param[i]); 9613465Sgabeblack@google.com } 9713465Sgabeblack@google.com os << "\n"; 9813465Sgabeblack@google.com} 9913465Sgabeblack@google.com 10013465Sgabeblack@google.com 10113465Sgabeblack@google.comtemplate <class T> 10213465Sgabeblack@google.comvoid 10313465Sgabeblack@google.comarrayParamIn(Checkpoint *cp, const std::string §ion, 10413465Sgabeblack@google.com const std::string &name, T *param, int size) 10513465Sgabeblack@google.com{ 10613465Sgabeblack@google.com std::string str; 10713465Sgabeblack@google.com if (!cp->find(section, name, str)) { 10813465Sgabeblack@google.com fatal("Can't unserialize '%s:%s'\n", section, name); 10913465Sgabeblack@google.com } 11013465Sgabeblack@google.com 11113465Sgabeblack@google.com // code below stolen from VectorParam<T>::parse(). 11213465Sgabeblack@google.com // it would be nice to unify these somehow... 11313465Sgabeblack@google.com 11413465Sgabeblack@google.com vector<string> tokens; 11513465Sgabeblack@google.com 11613465Sgabeblack@google.com tokenize(tokens, str, ' '); 11713465Sgabeblack@google.com 11813465Sgabeblack@google.com // Need this if we were doing a vector 11913465Sgabeblack@google.com // value.resize(tokens.size()); 12013465Sgabeblack@google.com 12113465Sgabeblack@google.com if (tokens.size() != size) { 12213465Sgabeblack@google.com fatal("Array size mismatch on %s:%s'\n", section, name); 12313465Sgabeblack@google.com } 12413465Sgabeblack@google.com 12513465Sgabeblack@google.com for (int i = 0; i < tokens.size(); i++) { 12613465Sgabeblack@google.com // need to parse into local variable to handle vector<bool>, 12713465Sgabeblack@google.com // for which operator[] returns a special reference class 12813465Sgabeblack@google.com // that's not the same as 'bool&', (since it's a packed 12913465Sgabeblack@google.com // vector) 13013465Sgabeblack@google.com T scalar_value; 13113465Sgabeblack@google.com if (!parseParam(tokens[i], scalar_value)) { 13213465Sgabeblack@google.com string err("could not parse \""); 13313465Sgabeblack@google.com 13413465Sgabeblack@google.com err += str; 13513465Sgabeblack@google.com err += "\""; 13613465Sgabeblack@google.com 13713465Sgabeblack@google.com fatal(err); 13813465Sgabeblack@google.com } 13913465Sgabeblack@google.com 14013465Sgabeblack@google.com // assign parsed value to vector 14113465Sgabeblack@google.com param[i] = scalar_value; 14213465Sgabeblack@google.com } 14313465Sgabeblack@google.com} 14413465Sgabeblack@google.com 14513465Sgabeblack@google.com 14613465Sgabeblack@google.comvoid 14713465Sgabeblack@google.comobjParamIn(Checkpoint *cp, const std::string §ion, 14813465Sgabeblack@google.com const std::string &name, Serializable * ¶m) 14913465Sgabeblack@google.com{ 15013465Sgabeblack@google.com if (!cp->findObj(section, name, param)) { 15113465Sgabeblack@google.com fatal("Can't unserialize '%s:%s'\n", section, name); 15213465Sgabeblack@google.com } 15313465Sgabeblack@google.com} 15413465Sgabeblack@google.com 15513465Sgabeblack@google.com 15613465Sgabeblack@google.com#define INSTANTIATE_PARAM_TEMPLATES(type) \ 15713465Sgabeblack@google.comtemplate void \ 15813465Sgabeblack@google.comparamOut(ostream &os, const std::string &name, type const ¶m); \ 15913465Sgabeblack@google.comtemplate void \ 16013465Sgabeblack@google.comparamIn(Checkpoint *cp, const std::string §ion, \ 16113465Sgabeblack@google.com const std::string &name, type & param); \ 16213465Sgabeblack@google.comtemplate void \ 16313465Sgabeblack@google.comarrayParamOut(ostream &os, const std::string &name, \ 16413465Sgabeblack@google.com type const *param, int size); \ 16513465Sgabeblack@google.comtemplate void \ 16613465Sgabeblack@google.comarrayParamIn(Checkpoint *cp, const std::string §ion, \ 16713465Sgabeblack@google.com const std::string &name, type *param, int size); 16813465Sgabeblack@google.com 16913465Sgabeblack@google.com 17013465Sgabeblack@google.comINSTANTIATE_PARAM_TEMPLATES(int8_t) 17113465Sgabeblack@google.comINSTANTIATE_PARAM_TEMPLATES(uint8_t) 17213465Sgabeblack@google.comINSTANTIATE_PARAM_TEMPLATES(int16_t) 17313465Sgabeblack@google.comINSTANTIATE_PARAM_TEMPLATES(uint16_t) 17413465Sgabeblack@google.comINSTANTIATE_PARAM_TEMPLATES(int32_t) 17513465Sgabeblack@google.comINSTANTIATE_PARAM_TEMPLATES(uint32_t) 17613465Sgabeblack@google.comINSTANTIATE_PARAM_TEMPLATES(int64_t) 17713465Sgabeblack@google.comINSTANTIATE_PARAM_TEMPLATES(uint64_t) 17813465Sgabeblack@google.comINSTANTIATE_PARAM_TEMPLATES(bool) 17913465Sgabeblack@google.comINSTANTIATE_PARAM_TEMPLATES(string) 18013465Sgabeblack@google.com 18113465Sgabeblack@google.com 18213465Sgabeblack@google.com///////////////////////////// 183 184/// Container for serializing global variables (not associated with 185/// any serialized object). 186class Globals : public Serializable 187{ 188 public: 189 const string name() const; 190 void serialize(ostream& os); 191 void unserialize(Checkpoint *cp); 192}; 193 194/// The one and only instance of the Globals class. 195Globals globals; 196 197const string 198Globals::name() const 199{ 200 return "Globals"; 201} 202 203void 204Globals::serialize(ostream& os) 205{ 206 nameOut(os); 207 SERIALIZE_SCALAR(curTick); 208 209 nameOut(os, "MainEventQueue"); 210 mainEventQueue.serialize(os); 211} 212 213void 214Globals::unserialize(Checkpoint *cp) 215{ 216 const string §ion = name(); 217 UNSERIALIZE_SCALAR(curTick); 218 219 mainEventQueue.unserialize(cp, "MainEventQueue"); 220} 221 222void 223Serializable::serializeAll() 224{ 225 string dir = Checkpoint::dir(); 226 if (mkdir(dir.c_str(), 0775) == -1 && errno != EEXIST) 227 fatal("couldn't mkdir %s\n", dir); 228 229 string cpt_file = dir + Checkpoint::baseFilename; 230 ofstream outstream(cpt_file.c_str()); 231 time_t t = time(NULL); 232 outstream << "// checkpoint generated: " << ctime(&t); 233 234 globals.serialize(outstream); 235 SimObject::serializeAll(outstream); 236} 237 238 239void 240Serializable::unserializeGlobals(Checkpoint *cp) 241{ 242 globals.unserialize(cp); 243} 244 245 246class SerializeEvent : public Event 247{ 248 protected: 249 Tick repeat; 250 251 public: 252 SerializeEvent(Tick _when, Tick _repeat); 253 virtual void process(); 254 virtual void serialize(std::ostream &os) 255 { 256 panic("Cannot serialize the SerializeEvent"); 257 } 258 259}; 260 261SerializeEvent::SerializeEvent(Tick _when, Tick _repeat) 262 : Event(&mainEventQueue, Serialize_Pri), repeat(_repeat) 263{ 264 setFlags(AutoDelete); 265 schedule(_when); 266} 267 268void 269SerializeEvent::process() 270{ 271 Serializable::serializeAll(); 272 if (repeat) 273 schedule(curTick + repeat); 274} 275 276const char *Checkpoint::baseFilename = "m5.cpt"; 277 278static string checkpointDirBase; 279 280string 281Checkpoint::dir() 282{ 283 // use csprintf to insert curTick into directory name if it 284 // appears to have a format placeholder in it. 285 return (checkpointDirBase.find("%") != string::npos) ? 286 csprintf(checkpointDirBase, curTick) : checkpointDirBase; 287} 288 289void 290Checkpoint::setup(Tick when, Tick period) 291{ 292 new SerializeEvent(when, period); 293} 294 295class SerializeParamContext : public ParamContext 296{ 297 private: 298 SerializeEvent *event; 299 300 public: 301 SerializeParamContext(const string §ion); 302 ~SerializeParamContext(); 303 void checkParams(); 304}; 305 306SerializeParamContext serialParams("serialize"); 307 308Param<string> serialize_dir(&serialParams, "dir", 309 "dir to stick checkpoint in " 310 "(sprintf format with cycle #)"); 311 312Param<Counter> serialize_cycle(&serialParams, 313 "cycle", 314 "cycle to serialize", 315 0); 316 317Param<Counter> serialize_period(&serialParams, 318 "period", 319 "period to repeat serializations", 320 0); 321 322 323 324SerializeParamContext::SerializeParamContext(const string §ion) 325 : ParamContext(section), event(NULL) 326{ } 327 328SerializeParamContext::~SerializeParamContext() 329{ 330} 331 332void 333SerializeParamContext::checkParams() 334{ 335 if (serialize_dir.isValid()) { 336 checkpointDirBase = serialize_dir; 337 } else { 338 if (outputDirectory.empty()) 339 checkpointDirBase = "m5.%012d"; 340 else 341 checkpointDirBase = outputDirectory + "cpt.%012d"; 342 } 343 344 // guarantee that directory ends with a '/' 345 if (checkpointDirBase[checkpointDirBase.size() - 1] != '/') 346 checkpointDirBase += "/"; 347 348 if (serialize_cycle > 0) 349 Checkpoint::setup(serialize_cycle, serialize_period); 350} 351 352void 353debug_serialize() 354{ 355 Serializable::serializeAll(); 356} 357 358void 359debug_serialize(Tick when) 360{ 361 new SerializeEvent(when, 0); 362} 363 364//////////////////////////////////////////////////////////////////////// 365// 366// SerializableClass member definitions 367// 368//////////////////////////////////////////////////////////////////////// 369 370// Map of class names to SerializableBuilder creation functions. 371// Need to make this a pointer so we can force initialization on the 372// first reference; otherwise, some SerializableClass constructors 373// may be invoked before the classMap constructor. 374map<string,SerializableClass::CreateFunc> *SerializableClass::classMap = 0; 375 376// SerializableClass constructor: add mapping to classMap 377SerializableClass::SerializableClass(const string &className, 378 CreateFunc createFunc) 379{ 380 if (classMap == NULL) 381 classMap = new map<string,SerializableClass::CreateFunc>(); 382 383 if ((*classMap)[className]) 384 { 385 cerr << "Error: simulation object class " << className << " redefined" 386 << endl; 387 fatal(""); 388 } 389 390 // add className --> createFunc to class map 391 (*classMap)[className] = createFunc; 392} 393 394 395// 396// 397Serializable * 398SerializableClass::createObject(Checkpoint *cp, 399 const std::string §ion) 400{ 401 string className; 402 403 if (!cp->find(section, "type", className)) { 404 fatal("Serializable::create: no 'type' entry in section '%s'.\n", 405 section); 406 } 407 408 CreateFunc createFunc = (*classMap)[className]; 409 410 if (createFunc == NULL) { 411 fatal("Serializable::create: no create function for class '%s'.\n", 412 className); 413 } 414 415 Serializable *object = createFunc(cp, section); 416 417 assert(object != NULL); 418 419 return object; 420} 421 422 423Serializable * 424Serializable::create(Checkpoint *cp, const std::string §ion) 425{ 426 Serializable *object = SerializableClass::createObject(cp, section); 427 object->unserialize(cp, section); 428 return object; 429} 430 431 432Checkpoint::Checkpoint(const std::string &cpt_dir, const std::string &path, 433 const ConfigNode *_configNode) 434 : db(new IniFile), basePath(path), configNode(_configNode) 435{ 436 string filename = cpt_dir + "/" + Checkpoint::baseFilename; 437 if (!db->load(filename)) { 438 fatal("Can't load checkpoint file '%s'\n", filename); 439 } 440} 441 442 443bool 444Checkpoint::find(const std::string §ion, const std::string &entry, 445 std::string &value) 446{ 447 return db->find(section, entry, value); 448} 449 450 451bool 452Checkpoint::findObj(const std::string §ion, const std::string &entry, 453 Serializable *&value) 454{ 455 string path; 456 457 if (!db->find(section, entry, path)) 458 return false; 459 460 if ((value = configNode->resolveSimObject(path)) != NULL) 461 return true; 462 463 if ((value = objMap[path]) != NULL) 464 return true; 465 466 return false; 467} 468 469 470bool 471Checkpoint::sectionExists(const std::string §ion) 472{ 473 return db->sectionExists(section); 474} 475