serialize.cc revision 56
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 38#include "sim/eventq.hh" 39#include "sim/param.hh" 40#include "sim/serialize.hh" 41#include "base/inifile.hh" 42#include "sim/sim_events.hh" 43#include "sim/sim_object.hh" 44#include "base/trace.hh" 45 46using namespace std; 47 48Serializer *Serializeable::serializer = NULL; 49 50Serializeable::Serializeable(const string &n) 51 : proxy(this), objName(n), serialized(false) 52{ } 53 54Serializeable::~Serializeable() 55{ } 56 57void 58Serializeable::mark() 59{ 60 if (!serialized) 61 serializer->add_object(this); 62 63 serialized = true; 64} 65 66ostream & 67Serializeable::out() const 68{ 69 return serializer->out(); 70} 71 72void 73Serializeable::nameOut() 74{ 75 out() << "\n[" << name() << "]\n"; 76} 77 78void 79Serializeable::nameOut(const string &_name) 80{ 81 out() << "\n[" << _name << "]\n"; 82} 83 84template<> void 85Serializeable::paramOut(const string &name, const uint64_t& param) 86{ 87 out() << name << "=0x" << hex << param << dec << "\n"; 88} 89 90void 91Serializeable::childOut(const string &name, Serializeable *child) 92{ 93 child->mark(); 94 if (child->name() == "") 95 panic("child is unnamed"); 96 97 out() << name << "=" << child->name() << "\n"; 98} 99 100void 101Serializeable::setName(const string &name) 102{ 103 if (objName != "") 104 panic("Cannot change object name"); 105 106 objName = name; 107} 108 109Serializer::Serializer() 110{ } 111 112Serializer::~Serializer() 113{ } 114 115ostream & 116Serializer::out() const 117{ 118 if (!output) 119 panic("must set output before serializing"); 120 121 return *output; 122} 123 124void 125Serializer::add_object(Serializeable *obj) 126{ 127 objects.push_back(obj); 128} 129 130void 131Serializer::add_objects() 132{ 133 mainEventQueue.mark(); 134 135 SimObject::SimObjectList::iterator i = SimObject::simObjectList.begin(); 136 SimObject::SimObjectList::iterator end = SimObject::simObjectList.end(); 137 138 while (i != end) { 139 (*i)->mark(); 140 ++i; 141 } 142} 143 144void 145Serializer::serialize(const string &f) 146{ 147 if (Serializeable::serializer != NULL) 148 panic("in process of serializing!"); 149 150 Serializeable::serializer = this; 151 152 file = f; 153 string cpt_file = file + ".cpt"; 154 output = new ofstream(cpt_file.c_str()); 155 time_t t = time(NULL); 156 *output << "// checkpoint generated: " << ctime(&t); 157 158 serlist_t list; 159 160 add_objects(); 161 while (!objects.empty()) { 162 Serializeable *serial = objects.front(); 163 DPRINTF(Serialize, "Name Children of %s\n", serial->name()); 164 serial->nameChildren(); 165 objects.pop_front(); 166 list.push_back(serial); 167 } 168 169 while (!list.empty()) { 170 list.front()->serialized = false; 171 list.pop_front(); 172 } 173 174 add_objects(); 175 while (!objects.empty()) { 176 Serializeable *serial = objects.front(); 177 DPRINTF(Serialize, "Name Children of %s\n", serial->name()); 178 serial->serialize(); 179 objects.pop_front(); 180 list.push_back(serial); 181 } 182 183 while (!list.empty()) { 184 list.front()->serialized = false; 185 list.pop_front(); 186 } 187 188 Serializeable::serializer = NULL; 189 190 delete output; 191 output = NULL; 192 file = ""; 193} 194 195class SerializeEvent : public Event 196{ 197 protected: 198 string file; 199 200 public: 201 SerializeEvent(EventQueue *q, Tick when, const string &file); 202 ~SerializeEvent(); 203 204 virtual void process(); 205 virtual void serialize(); 206}; 207 208SerializeEvent::SerializeEvent(EventQueue *q, Tick when, const string &f) 209 : Event(q), file(f) 210{ 211 setFlags(AutoDelete); 212 schedule(when); 213} 214 215SerializeEvent::~SerializeEvent() 216{ 217} 218 219void 220SerializeEvent::process() 221{ 222 Serializer serial; 223 serial.serialize(file); 224 new SimExitEvent("Serialization caused exit"); 225} 226 227void 228SerializeEvent::serialize() 229{ 230 panic("Cannot serialize the SerializeEvent"); 231} 232 233class SerializeParamContext : public ParamContext 234{ 235 private: 236 SerializeEvent *event; 237 238 public: 239 SerializeParamContext(const string §ion); 240 ~SerializeParamContext(); 241 void checkParams(); 242}; 243 244SerializeParamContext serialParams("serialize"); 245 246Param<Counter> serialize_cycle(&serialParams, 247 "cycle", 248 "cycle to serialize", 249 0); 250 251Param<string> serialize_file(&serialParams, 252 "file", 253 "file to write to", ""); 254 255SerializeParamContext::SerializeParamContext(const string §ion) 256 : ParamContext(section), event(NULL) 257{ } 258 259SerializeParamContext::~SerializeParamContext() 260{ 261} 262 263void 264SerializeParamContext::checkParams() 265{ 266 if (!((string)serialize_file).empty() && serialize_cycle > 0) 267 event = new SerializeEvent(&mainEventQueue, serialize_cycle, 268 serialize_file); 269} 270 271void 272debug_serialize(const char *file) 273{ 274 Serializer serial; 275 serial.serialize(file); 276 new SimExitEvent("Serialization caused exit"); 277} 278 279 280 281 282//////////////////////////////////////////////////////////////////////// 283// 284// SerializeableClass member definitions 285// 286//////////////////////////////////////////////////////////////////////// 287 288// Map of class names to SerializeableBuilder creation functions. 289// Need to make this a pointer so we can force initialization on the 290// first reference; otherwise, some SerializeableClass constructors 291// may be invoked before the classMap constructor. 292map<string,SerializeableClass::CreateFunc> *SerializeableClass::classMap = 0; 293 294// SerializeableClass constructor: add mapping to classMap 295SerializeableClass::SerializeableClass(const string &className, 296 CreateFunc createFunc) 297{ 298 if (classMap == NULL) 299 classMap = new map<string,SerializeableClass::CreateFunc>(); 300 301 if ((*classMap)[className]) 302 { 303 cerr << "Error: simulation object class " << className << " redefined" 304 << endl; 305 fatal(""); 306 } 307 308 // add className --> createFunc to class map 309 (*classMap)[className] = createFunc; 310} 311 312 313// 314// 315Serializeable * 316SerializeableClass::createObject(IniFile &configDB, 317 const string &configClassName) 318{ 319 // find simulation object class name from configuration class 320 // (specified by 'type=' parameter) 321 string simObjClassName; 322 323 if (!configDB.findDefault(configClassName, "type", simObjClassName)) { 324 cerr << "Configuration class '" << configClassName << "' not found." 325 << endl; 326 abort(); 327 } 328 329 // look up className to get appropriate createFunc 330 if (classMap->find(simObjClassName) == classMap->end()) { 331 cerr << "Simulator object class '" << simObjClassName << "' not found." 332 << endl; 333 abort(); 334 } 335 336 CreateFunc createFunc = (*classMap)[simObjClassName]; 337 338 // builder instance 339 SerializeableBuilder *objectBuilder = (*createFunc)(); 340 341 assert(objectBuilder != NULL); 342 343 // now create the actual simulation object 344 Serializeable *object = objectBuilder->create(); 345 346 assert(object != NULL); 347 348 // done with the SerializeableBuilder now 349 delete objectBuilder; 350 351 return object; 352} 353 354