serialize.cc revision 1388
1/* 2 * Copyright (c) 2002-2004 The Regents of The University of Michigan 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29#include <sys/time.h> 30#include <sys/types.h> 31#include <sys/stat.h> 32#include <errno.h> 33 34#include <fstream> 35#include <list> 36#include <string> 37#include <vector> 38 39#include "base/inifile.hh" 40#include "base/misc.hh" 41#include "base/output.hh" 42#include "base/str.hh" 43#include "base/trace.hh" 44#include "sim/config_node.hh" 45#include "sim/eventq.hh" 46#include "sim/param.hh" 47#include "sim/serialize.hh" 48#include "sim/sim_events.hh" 49#include "sim/sim_object.hh" 50 51using namespace std; 52 53void 54Serializable::nameOut(ostream &os) 55{ 56 os << "\n[" << name() << "]\n"; 57} 58 59void 60Serializable::nameOut(ostream &os, const string &_name) 61{ 62 os << "\n[" << _name << "]\n"; 63} 64 65template <class T> 66void 67paramOut(ostream &os, const std::string &name, const T ¶m) 68{ 69 os << name << "="; 70 showParam(os, param); 71 os << "\n"; 72} 73 74 75template <class T> 76void 77paramIn(Checkpoint *cp, const std::string §ion, 78 const std::string &name, T ¶m) 79{ 80 std::string str; 81 if (!cp->find(section, name, str) || !parseParam(str, param)) { 82 fatal("Can't unserialize '%s:%s'\n", section, name); 83 } 84} 85 86 87template <class T> 88void 89arrayParamOut(ostream &os, const std::string &name, 90 const T *param, int size) 91{ 92 os << name << "="; 93 if (size > 0) 94 showParam(os, param[0]); 95 for (int i = 1; i < size; ++i) { 96 os << " "; 97 showParam(os, param[i]); 98 } 99 os << "\n"; 100} 101 102 103template <class T> 104void 105arrayParamIn(Checkpoint *cp, const std::string §ion, 106 const std::string &name, T *param, int size) 107{ 108 std::string str; 109 if (!cp->find(section, name, str)) { 110 fatal("Can't unserialize '%s:%s'\n", section, name); 111 } 112 113 // code below stolen from VectorParam<T>::parse(). 114 // it would be nice to unify these somehow... 115 116 vector<string> tokens; 117 118 tokenize(tokens, str, ' '); 119 120 // Need this if we were doing a vector 121 // value.resize(tokens.size()); 122 123 if (tokens.size() != size) { 124 fatal("Array size mismatch on %s:%s'\n", section, name); 125 } 126 127 for (int i = 0; i < tokens.size(); i++) { 128 // need to parse into local variable to handle vector<bool>, 129 // for which operator[] returns a special reference class 130 // that's not the same as 'bool&', (since it's a packed 131 // vector) 132 T scalar_value; 133 if (!parseParam(tokens[i], scalar_value)) { 134 string err("could not parse \""); 135 136 err += str; 137 err += "\""; 138 139 fatal(err); 140 } 141 142 // assign parsed value to vector 143 param[i] = scalar_value; 144 } 145} 146 147 148void 149objParamIn(Checkpoint *cp, const std::string §ion, 150 const std::string &name, Serializable * ¶m) 151{ 152 if (!cp->findObj(section, name, param)) { 153 fatal("Can't unserialize '%s:%s'\n", section, name); 154 } 155} 156 157 158#define INSTANTIATE_PARAM_TEMPLATES(type) \ 159template void \ 160paramOut(ostream &os, const std::string &name, type const ¶m); \ 161template void \ 162paramIn(Checkpoint *cp, const std::string §ion, \ 163 const std::string &name, type & param); \ 164template void \ 165arrayParamOut(ostream &os, const std::string &name, \ 166 type const *param, int size); \ 167template void \ 168arrayParamIn(Checkpoint *cp, const std::string §ion, \ 169 const std::string &name, type *param, int size); 170 171 172INSTANTIATE_PARAM_TEMPLATES(int8_t) 173INSTANTIATE_PARAM_TEMPLATES(uint8_t) 174INSTANTIATE_PARAM_TEMPLATES(int16_t) 175INSTANTIATE_PARAM_TEMPLATES(uint16_t) 176INSTANTIATE_PARAM_TEMPLATES(int32_t) 177INSTANTIATE_PARAM_TEMPLATES(uint32_t) 178INSTANTIATE_PARAM_TEMPLATES(int64_t) 179INSTANTIATE_PARAM_TEMPLATES(uint64_t) 180INSTANTIATE_PARAM_TEMPLATES(bool) 181INSTANTIATE_PARAM_TEMPLATES(string) 182 183 184///////////////////////////// 185 186/// Container for serializing global variables (not associated with 187/// any serialized object). 188class Globals : public Serializable 189{ 190 public: 191 const string name() const; 192 void serialize(ostream &os); 193 void unserialize(Checkpoint *cp); 194}; 195 196/// The one and only instance of the Globals class. 197Globals globals; 198 199const string 200Globals::name() const 201{ 202 return "Globals"; 203} 204 205void 206Globals::serialize(ostream &os) 207{ 208 nameOut(os); 209 SERIALIZE_SCALAR(curTick); 210 211 nameOut(os, "MainEventQueue"); 212 mainEventQueue.serialize(os); 213} 214 215void 216Globals::unserialize(Checkpoint *cp) 217{ 218 const string §ion = name(); 219 UNSERIALIZE_SCALAR(curTick); 220 221 mainEventQueue.unserialize(cp, "MainEventQueue"); 222} 223 224void 225Serializable::serializeAll() 226{ 227 string dir = Checkpoint::dir(); 228 if (mkdir(dir.c_str(), 0775) == -1 && errno != EEXIST) 229 fatal("couldn't mkdir %s\n", dir); 230 231 string cpt_file = dir + Checkpoint::baseFilename; 232 ofstream outstream(cpt_file.c_str()); 233 time_t t = time(NULL); 234 outstream << "// checkpoint generated: " << ctime(&t); 235 236 globals.serialize(outstream); 237 SimObject::serializeAll(outstream); 238} 239 240 241void 242Serializable::unserializeGlobals(Checkpoint *cp) 243{ 244 globals.unserialize(cp); 245} 246 247 248class SerializeEvent : public Event 249{ 250 protected: 251 Tick repeat; 252 253 public: 254 SerializeEvent(Tick _when, Tick _repeat); 255 virtual void process(); 256 virtual void serialize(std::ostream &os) 257 { 258 panic("Cannot serialize the SerializeEvent"); 259 } 260 261}; 262 263SerializeEvent::SerializeEvent(Tick _when, Tick _repeat) 264 : Event(&mainEventQueue, Serialize_Pri), repeat(_repeat) 265{ 266 setFlags(AutoDelete); 267 schedule(_when); 268} 269 270void 271SerializeEvent::process() 272{ 273 Serializable::serializeAll(); 274 if (repeat) 275 schedule(curTick + repeat); 276} 277 278const char *Checkpoint::baseFilename = "m5.cpt"; 279 280static string checkpointDirBase; 281 282string 283Checkpoint::dir() 284{ 285 // use csprintf to insert curTick into directory name if it 286 // appears to have a format placeholder in it. 287 return (checkpointDirBase.find("%") != string::npos) ? 288 csprintf(checkpointDirBase, curTick) : checkpointDirBase; 289} 290 291void 292Checkpoint::setup(Tick when, Tick period) 293{ 294 new SerializeEvent(when, period); 295} 296 297class SerializeParamContext : public ParamContext 298{ 299 private: 300 SerializeEvent *event; 301 302 public: 303 SerializeParamContext(const string §ion); 304 ~SerializeParamContext(); 305 void checkParams(); 306}; 307 308SerializeParamContext serialParams("serialize"); 309 310Param<string> serialize_dir(&serialParams, "dir", 311 "dir to stick checkpoint in " 312 "(sprintf format with cycle #)"); 313 314Param<Counter> serialize_cycle(&serialParams, 315 "cycle", 316 "cycle to serialize", 317 0); 318 319Param<Counter> serialize_period(&serialParams, 320 "period", 321 "period to repeat serializations", 322 0); 323 324 325 326SerializeParamContext::SerializeParamContext(const string §ion) 327 : ParamContext(section), event(NULL) 328{ } 329 330SerializeParamContext::~SerializeParamContext() 331{ 332} 333 334void 335SerializeParamContext::checkParams() 336{ 337 checkpointDirBase = simout.resolve(serialize_dir); 338 339 // guarantee that directory ends with a '/' 340 if (checkpointDirBase[checkpointDirBase.size() - 1] != '/') 341 checkpointDirBase += "/"; 342 343 if (serialize_cycle > 0) 344 Checkpoint::setup(serialize_cycle, serialize_period); 345} 346 347void 348debug_serialize() 349{ 350 Serializable::serializeAll(); 351} 352 353void 354debug_serialize(Tick when) 355{ 356 new SerializeEvent(when, 0); 357} 358 359//////////////////////////////////////////////////////////////////////// 360// 361// SerializableClass member definitions 362// 363//////////////////////////////////////////////////////////////////////// 364 365// Map of class names to SerializableBuilder creation functions. 366// Need to make this a pointer so we can force initialization on the 367// first reference; otherwise, some SerializableClass constructors 368// may be invoked before the classMap constructor. 369map<string,SerializableClass::CreateFunc> *SerializableClass::classMap = 0; 370 371// SerializableClass constructor: add mapping to classMap 372SerializableClass::SerializableClass(const string &className, 373 CreateFunc createFunc) 374{ 375 if (classMap == NULL) 376 classMap = new map<string,SerializableClass::CreateFunc>(); 377 378 if ((*classMap)[className]) 379 { 380 cerr << "Error: simulation object class " << className << " redefined" 381 << endl; 382 fatal(""); 383 } 384 385 // add className --> createFunc to class map 386 (*classMap)[className] = createFunc; 387} 388 389 390// 391// 392Serializable * 393SerializableClass::createObject(Checkpoint *cp, 394 const std::string §ion) 395{ 396 string className; 397 398 if (!cp->find(section, "type", className)) { 399 fatal("Serializable::create: no 'type' entry in section '%s'.\n", 400 section); 401 } 402 403 CreateFunc createFunc = (*classMap)[className]; 404 405 if (createFunc == NULL) { 406 fatal("Serializable::create: no create function for class '%s'.\n", 407 className); 408 } 409 410 Serializable *object = createFunc(cp, section); 411 412 assert(object != NULL); 413 414 return object; 415} 416 417 418Serializable * 419Serializable::create(Checkpoint *cp, const std::string §ion) 420{ 421 Serializable *object = SerializableClass::createObject(cp, section); 422 object->unserialize(cp, section); 423 return object; 424} 425 426 427Checkpoint::Checkpoint(const std::string &cpt_dir, const std::string &path, 428 const ConfigNode *_configNode) 429 : db(new IniFile), basePath(path), configNode(_configNode), cptDir(cpt_dir) 430{ 431 string filename = cpt_dir + "/" + Checkpoint::baseFilename; 432 if (!db->load(filename)) { 433 fatal("Can't load checkpoint file '%s'\n", filename); 434 } 435} 436 437 438bool 439Checkpoint::find(const std::string §ion, const std::string &entry, 440 std::string &value) 441{ 442 return db->find(section, entry, value); 443} 444 445 446bool 447Checkpoint::findObj(const std::string §ion, const std::string &entry, 448 Serializable *&value) 449{ 450 string path; 451 452 if (!db->find(section, entry, path)) 453 return false; 454 455 if ((value = configNode->resolveSimObject(path)) != NULL) 456 return true; 457 458 if ((value = objMap[path]) != NULL) 459 return true; 460 461 return false; 462} 463 464 465bool 466Checkpoint::sectionExists(const std::string §ion) 467{ 468 return db->sectionExists(section); 469} 470