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