serialize.cc revision 304
1/* 2 * Copyright (c) 2003 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 31#include <fstream> 32#include <list> 33#include <string> 34#include <vector> 35 36#include "base/misc.hh" 37#include "base/str.hh" 38 39#include "sim/eventq.hh" 40#include "sim/param.hh" 41#include "sim/serialize.hh" 42#include "base/inifile.hh" 43#include "sim/sim_events.hh" 44#include "sim/sim_object.hh" 45#include "base/trace.hh" 46#include "sim/config_node.hh" 47 48using namespace std; 49 50Serializer *Serializeable::serializer = NULL; 51 52Serializeable::Serializeable() 53 : serialized(false) 54{ } 55 56Serializeable::~Serializeable() 57{ } 58 59void 60Serializeable::mark() 61{ 62 if (!serialized) 63 serializer->add_object(this); 64 65 serialized = true; 66} 67 68void 69Serializeable::nameOut(ostream &os) 70{ 71 os << "\n[" << name() << "]\n"; 72} 73 74void 75Serializeable::nameOut(ostream &os, const string &_name) 76{ 77 os << "\n[" << _name << "]\n"; 78} 79 80template <class T> 81void 82paramOut(ostream &os, const std::string &name, const T& param) 83{ 84 os << name << "="; 85 showParam(os, param); 86 os << "\n"; 87} 88 89 90template <class T> 91void 92paramIn(Checkpoint *cp, const std::string §ion, 93 const std::string &name, T& param) 94{ 95 std::string str; 96 if (!cp->find(section, name, str) || !parseParam(str, param)) { 97 fatal("Can't unserialize '%s:%s'\n", section, name); 98 } 99} 100 101 102template <class T> 103void 104arrayParamOut(ostream &os, const std::string &name, 105 const T *param, int size) 106{ 107 os << name << "="; 108 if (size > 0) 109 showParam(os, param[0]); 110 for (int i = 1; i < size; ++i) { 111 os << " "; 112 showParam(os, param[i]); 113 } 114 os << "\n"; 115} 116 117 118template <class T> 119void 120arrayParamIn(Checkpoint *cp, const std::string §ion, 121 const std::string &name, T *param, int size) 122{ 123 std::string str; 124 if (!cp->find(section, name, str)) { 125 fatal("Can't unserialize '%s:%s'\n", section, name); 126 } 127 128 // code below stolen from VectorParam<T>::parse(). 129 // it would be nice to unify these somehow... 130 131 vector<string> tokens; 132 133 tokenize(tokens, str, ' '); 134 135 // Need this if we were doing a vector 136 // value.resize(tokens.size()); 137 138 if (tokens.size() != size) { 139 fatal("Array size mismatch on %s:%s'\n", section, name); 140 } 141 142 for (int i = 0; i < tokens.size(); i++) { 143 // need to parse into local variable to handle vector<bool>, 144 // for which operator[] returns a special reference class 145 // that's not the same as 'bool&', (since it's a packed 146 // vector) 147 T scalar_value; 148 if (!parseParam(tokens[i], scalar_value)) { 149 string err("could not parse \""); 150 151 err += str; 152 err += "\""; 153 154 fatal(err); 155 } 156 157 // assign parsed value to vector 158 param[i] = scalar_value; 159 } 160} 161 162 163void 164objParamIn(Checkpoint *cp, const std::string §ion, 165 const std::string &name, Serializeable * ¶m) 166{ 167 if (!cp->findObj(section, name, param)) { 168 fatal("Can't unserialize '%s:%s'\n", section, name); 169 } 170} 171 172 173#define INSTANTIATE_PARAM_TEMPLATES(type) \ 174template void \ 175paramOut(ostream &os, const std::string &name, type const ¶m); \ 176template void \ 177paramIn(Checkpoint *cp, const std::string §ion, \ 178 const std::string &name, type & param); \ 179template void \ 180arrayParamOut(ostream &os, const std::string &name, \ 181 type const *param, int size); \ 182template void \ 183arrayParamIn(Checkpoint *cp, const std::string §ion, \ 184 const std::string &name, type *param, int size); 185 186 187INSTANTIATE_PARAM_TEMPLATES(int8_t) 188INSTANTIATE_PARAM_TEMPLATES(uint8_t) 189INSTANTIATE_PARAM_TEMPLATES(int16_t) 190INSTANTIATE_PARAM_TEMPLATES(uint16_t) 191INSTANTIATE_PARAM_TEMPLATES(int32_t) 192INSTANTIATE_PARAM_TEMPLATES(uint32_t) 193INSTANTIATE_PARAM_TEMPLATES(int64_t) 194INSTANTIATE_PARAM_TEMPLATES(uint64_t) 195INSTANTIATE_PARAM_TEMPLATES(bool) 196INSTANTIATE_PARAM_TEMPLATES(string) 197 198 199#if 0 200// unneeded? 201void 202Serializeable::childOut(const string &name, Serializeable *child) 203{ 204 child->mark(); 205 if (child->name() == "") 206 panic("child is unnamed"); 207 208 out() << name << "=" << child->name() << "\n"; 209} 210#endif 211 212Serializer::Serializer() 213{ } 214 215Serializer::~Serializer() 216{ } 217 218ostream & 219Serializer::out() const 220{ 221 if (!output) 222 panic("must set output before serializing"); 223 224 return *output; 225} 226 227void 228Serializer::add_object(Serializeable *obj) 229{ 230 objects.push_back(obj); 231} 232 233void 234Serializer::add_objects() 235{ 236 mainEventQueue.mark(); 237 238 SimObject::SimObjectList::iterator i = SimObject::simObjectList.begin(); 239 SimObject::SimObjectList::iterator end = SimObject::simObjectList.end(); 240 241 while (i != end) { 242 (*i)->mark(); 243 ++i; 244 } 245} 246 247void 248Serializer::serialize() 249{ 250 if (Serializeable::serializer != NULL) 251 panic("in process of serializing!"); 252 253 Serializeable::serializer = this; 254 255 file = CheckpointFile(); 256 string cpt_file = file + ".cpt"; 257 output = new ofstream(cpt_file.c_str()); 258 time_t t = time(NULL); 259 *output << "// checkpoint generated: " << ctime(&t); 260 261 serlist_t list; 262 263 add_objects(); 264 while (!objects.empty()) { 265 Serializeable *obj = objects.front(); 266 DPRINTF(Serialize, "Serializing %s\n", obj->name()); 267 obj->nameOut(out()); 268 obj->serialize(out()); 269 objects.pop_front(); 270 list.push_back(obj); 271 } 272 273 while (!list.empty()) { 274 list.front()->serialized = false; 275 list.pop_front(); 276 } 277 278 Serializeable::serializer = NULL; 279 280 delete output; 281 output = NULL; 282 file = ""; 283} 284 285class SerializeEvent : public Event 286{ 287 protected: 288 string file; 289 Tick repeat; 290 291 public: 292 SerializeEvent(Tick _when, Tick _repeat); 293 virtual void process(); 294 virtual void serialize(std::ostream &os) 295 { 296 panic("Cannot serialize the SerializeEvent"); 297 } 298 299}; 300 301SerializeEvent::SerializeEvent(Tick _when, Tick _repeat) 302 : Event(&mainEventQueue, 990), repeat(_repeat) 303{ 304 setFlags(AutoDelete); 305 schedule(_when); 306} 307 308void 309SerializeEvent::process() 310{ 311 Serializer serial; 312 serial.serialize(); 313 if (repeat) 314 schedule(curTick + repeat); 315} 316 317string __CheckpointFileBase; 318 319string 320CheckpointFile() 321{ 322 if (__CheckpointFileBase.empty()) 323 return __CheckpointFileBase; 324 325 return csprintf("%s.%d", __CheckpointFileBase, curTick); 326} 327 328void 329SetupCheckpoint(Tick when, Tick period) 330{ 331 new SerializeEvent(when, period); 332} 333 334class SerializeParamContext : public ParamContext 335{ 336 private: 337 SerializeEvent *event; 338 339 public: 340 SerializeParamContext(const string §ion); 341 ~SerializeParamContext(); 342 void checkParams(); 343}; 344 345SerializeParamContext serialParams("serialize"); 346 347Param<string> serialize_file(&serialParams, 348 "file", 349 "file to write to", "m5"); 350 351Param<Counter> serialize_cycle(&serialParams, 352 "cycle", 353 "cycle to serialize", 354 0); 355 356Param<Counter> serialize_period(&serialParams, 357 "period", 358 "period to repeat serializations", 359 0); 360 361 362 363SerializeParamContext::SerializeParamContext(const string §ion) 364 : ParamContext(section), event(NULL) 365{ } 366 367SerializeParamContext::~SerializeParamContext() 368{ 369} 370 371void 372SerializeParamContext::checkParams() 373{ 374 __CheckpointFileBase = serialize_file; 375 if (serialize_cycle > 0) 376 SetupCheckpoint(serialize_cycle, serialize_period); 377} 378 379void 380debug_serialize() 381{ 382 Serializer serial; 383 serial.serialize(); 384} 385 386void 387debug_serialize(Tick when) 388{ 389 new SerializeEvent(when, 0); 390} 391 392//////////////////////////////////////////////////////////////////////// 393// 394// SerializeableClass member definitions 395// 396//////////////////////////////////////////////////////////////////////// 397 398// Map of class names to SerializeableBuilder creation functions. 399// Need to make this a pointer so we can force initialization on the 400// first reference; otherwise, some SerializeableClass constructors 401// may be invoked before the classMap constructor. 402map<string,SerializeableClass::CreateFunc> *SerializeableClass::classMap = 0; 403 404// SerializeableClass constructor: add mapping to classMap 405SerializeableClass::SerializeableClass(const string &className, 406 CreateFunc createFunc) 407{ 408 if (classMap == NULL) 409 classMap = new map<string,SerializeableClass::CreateFunc>(); 410 411 if ((*classMap)[className]) 412 { 413 cerr << "Error: simulation object class " << className << " redefined" 414 << endl; 415 fatal(""); 416 } 417 418 // add className --> createFunc to class map 419 (*classMap)[className] = createFunc; 420} 421 422 423// 424// 425Serializeable * 426SerializeableClass::createObject(Checkpoint *cp, 427 const std::string §ion) 428{ 429 string className; 430 431 if (!cp->find(section, "type", className)) { 432 fatal("Serializeable::create: no 'type' entry in section '%s'.\n", 433 section); 434 } 435 436 CreateFunc createFunc = (*classMap)[className]; 437 438 if (createFunc == NULL) { 439 fatal("Serializeable::create: no create function for class '%s'.\n", 440 className); 441 } 442 443 Serializeable *object = createFunc(cp, section); 444 445 assert(object != NULL); 446 447 return object; 448} 449 450 451Serializeable * 452Serializeable::create(Checkpoint *cp, const std::string §ion) 453{ 454 Serializeable *object = SerializeableClass::createObject(cp, section); 455 object->unserialize(cp, section); 456 return object; 457} 458 459 460Checkpoint::Checkpoint(const std::string &filename, const std::string &path, 461 const ConfigNode *_configNode) 462 : db(new IniFile), basePath(path), configNode(_configNode) 463{ 464 if (!db->load(filename)) { 465 fatal("Can't load checkpoint file '%s'\n", filename); 466 } 467 468 mainEventQueue.unserialize(this, "MainEventQueue"); 469} 470 471 472bool 473Checkpoint::find(const std::string §ion, const std::string &entry, 474 std::string &value) 475{ 476 return db->find(section, entry, value); 477} 478 479 480bool 481Checkpoint::findObj(const std::string §ion, const std::string &entry, 482 Serializeable *&value) 483{ 484 string path; 485 486 if (!db->find(section, entry, path)) 487 return false; 488 489 if ((value = configNode->resolveSimObject(path)) != NULL) 490 return true; 491 492 if ((value = objMap[path]) != NULL) 493 return true; 494 495 return false; 496} 497 498 499bool 500Checkpoint::sectionExists(const std::string §ion) 501{ 502 return db->sectionExists(section); 503} 504