serialize.cc revision 395
16157Snate@binkert.org/* 26157Snate@binkert.org * Copyright (c) 2003 The Regents of The University of Michigan 36157Snate@binkert.org * All rights reserved. 46157Snate@binkert.org * 56157Snate@binkert.org * Redistribution and use in source and binary forms, with or without 66157Snate@binkert.org * modification, are permitted provided that the following conditions are 76157Snate@binkert.org * met: redistributions of source code must retain the above copyright 86157Snate@binkert.org * notice, this list of conditions and the following disclaimer; 96157Snate@binkert.org * redistributions in binary form must reproduce the above copyright 106157Snate@binkert.org * notice, this list of conditions and the following disclaimer in the 116157Snate@binkert.org * documentation and/or other materials provided with the distribution; 126157Snate@binkert.org * neither the name of the copyright holders nor the names of its 136157Snate@binkert.org * contributors may be used to endorse or promote products derived from 146157Snate@binkert.org * this software without specific prior written permission. 156157Snate@binkert.org * 166157Snate@binkert.org * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 176157Snate@binkert.org * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 186157Snate@binkert.org * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 196157Snate@binkert.org * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 206157Snate@binkert.org * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 216157Snate@binkert.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 226157Snate@binkert.org * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 236157Snate@binkert.org * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 246157Snate@binkert.org * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 256157Snate@binkert.org * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 266157Snate@binkert.org * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 276157Snate@binkert.org */ 286157Snate@binkert.org 296157Snate@binkert.org#include <sys/time.h> 306157Snate@binkert.org#include <sys/types.h> 316157Snate@binkert.org#include <sys/stat.h> 326157Snate@binkert.org 336157Snate@binkert.org#include <fstream> 346157Snate@binkert.org#include <list> 356157Snate@binkert.org#include <string> 366157Snate@binkert.org#include <vector> 376157Snate@binkert.org 386157Snate@binkert.org#include "base/inifile.hh" 396157Snate@binkert.org#include "base/misc.hh" 4010133Sandreas.hansson@arm.com#include "base/str.hh" 4110133Sandreas.hansson@arm.com#include "base/trace.hh" 4210133Sandreas.hansson@arm.com#include "sim/config_node.hh" 4310133Sandreas.hansson@arm.com#include "sim/eventq.hh" 4410133Sandreas.hansson@arm.com#include "sim/param.hh" 4510133Sandreas.hansson@arm.com#include "sim/serialize.hh" 4610133Sandreas.hansson@arm.com#include "sim/sim_events.hh" 4710133Sandreas.hansson@arm.com#include "sim/sim_object.hh" 4810133Sandreas.hansson@arm.com 4910133Sandreas.hansson@arm.comusing namespace std; 5010133Sandreas.hansson@arm.com 5110133Sandreas.hansson@arm.comvoid 5210133Sandreas.hansson@arm.comSerializable::nameOut(ostream &os) 5310133Sandreas.hansson@arm.com{ 5410133Sandreas.hansson@arm.com os << "\n[" << name() << "]\n"; 5510133Sandreas.hansson@arm.com} 5610133Sandreas.hansson@arm.com 5710133Sandreas.hansson@arm.comvoid 5810133Sandreas.hansson@arm.comSerializable::nameOut(ostream &os, const string &_name) 5910133Sandreas.hansson@arm.com{ 6010133Sandreas.hansson@arm.com os << "\n[" << _name << "]\n"; 6110133Sandreas.hansson@arm.com} 628492Snilay@cs.wisc.edu 636168Snate@binkert.orgtemplate <class T> 646168Snate@binkert.orgvoid 656157Snate@binkert.orgparamOut(ostream &os, const std::string &name, const T& param) 666157Snate@binkert.org{ 676157Snate@binkert.org os << name << "="; 686157Snate@binkert.org showParam(os, param); 696157Snate@binkert.org os << "\n"; 706157Snate@binkert.org} 716157Snate@binkert.org 726157Snate@binkert.org 736157Snate@binkert.orgtemplate <class T> 746157Snate@binkert.orgvoid 756157Snate@binkert.orgparamIn(Checkpoint *cp, const std::string §ion, 766157Snate@binkert.org const std::string &name, T& param) 776157Snate@binkert.org{ 786157Snate@binkert.org std::string str; 796157Snate@binkert.org if (!cp->find(section, name, str) || !parseParam(str, param)) { 806157Snate@binkert.org fatal("Can't unserialize '%s:%s'\n", section, name); 816157Snate@binkert.org } 826157Snate@binkert.org} 836157Snate@binkert.org 846157Snate@binkert.org 856157Snate@binkert.orgtemplate <class T> 866157Snate@binkert.orgvoid 876157Snate@binkert.orgarrayParamOut(ostream &os, const std::string &name, 886157Snate@binkert.org const T *param, int size) 896157Snate@binkert.org{ 906157Snate@binkert.org os << name << "="; 916157Snate@binkert.org if (size > 0) 926157Snate@binkert.org showParam(os, param[0]); 936157Snate@binkert.org for (int i = 1; i < size; ++i) { 946157Snate@binkert.org os << " "; 956157Snate@binkert.org showParam(os, param[i]); 966157Snate@binkert.org } 976157Snate@binkert.org os << "\n"; 986157Snate@binkert.org} 996157Snate@binkert.org 1006157Snate@binkert.org 1016157Snate@binkert.orgtemplate <class T> 1026157Snate@binkert.orgvoid 1036157Snate@binkert.orgarrayParamIn(Checkpoint *cp, const std::string §ion, 1046157Snate@binkert.org const std::string &name, T *param, int size) 1056157Snate@binkert.org{ 1066157Snate@binkert.org std::string str; 1076157Snate@binkert.org if (!cp->find(section, name, str)) { 1088483Sgblack@eecs.umich.edu fatal("Can't unserialize '%s:%s'\n", section, name); 1098483Sgblack@eecs.umich.edu } 1106157Snate@binkert.org 1116882SBrad.Beckmann@amd.com // code below stolen from VectorParam<T>::parse(). 1126286Snate@binkert.org // it would be nice to unify these somehow... 1136286Snate@binkert.org 1148092Snilay@cs.wisc.edu vector<string> tokens; 1156286Snate@binkert.org 1166286Snate@binkert.org tokenize(tokens, str, ' '); 1176157Snate@binkert.org 11811208Sjoseph.gross@amd.com // Need this if we were doing a vector 1196157Snate@binkert.org // value.resize(tokens.size()); 12011210SBrad.Beckmann@amd.com 12110301Snilay@cs.wisc.edu if (tokens.size() != size) { 1226157Snate@binkert.org fatal("Array size mismatch on %s:%s'\n", section, name); 1236157Snate@binkert.org } 12411307Santhony.gutierrez@amd.com 12511122Snilay@cs.wisc.edu for (int i = 0; i < tokens.size(); i++) { 12610301Snilay@cs.wisc.edu // need to parse into local variable to handle vector<bool>, 1279363Snilay@cs.wisc.edu // for which operator[] returns a special reference class 12810301Snilay@cs.wisc.edu // that's not the same as 'bool&', (since it's a packed 1296286Snate@binkert.org // vector) 13010301Snilay@cs.wisc.edu T scalar_value; 13110301Snilay@cs.wisc.edu if (!parseParam(tokens[i], scalar_value)) { 13210301Snilay@cs.wisc.edu string err("could not parse \""); 13310301Snilay@cs.wisc.edu 1346157Snate@binkert.org err += str; 13510301Snilay@cs.wisc.edu err += "\""; 13610301Snilay@cs.wisc.edu 137 fatal(err); 138 } 139 140 // assign parsed value to vector 141 param[i] = scalar_value; 142 } 143} 144 145 146void 147objParamIn(Checkpoint *cp, const std::string §ion, 148 const std::string &name, Serializable * ¶m) 149{ 150 if (!cp->findObj(section, name, param)) { 151 fatal("Can't unserialize '%s:%s'\n", section, name); 152 } 153} 154 155 156#define INSTANTIATE_PARAM_TEMPLATES(type) \ 157template void \ 158paramOut(ostream &os, const std::string &name, type const ¶m); \ 159template void \ 160paramIn(Checkpoint *cp, const std::string §ion, \ 161 const std::string &name, type & param); \ 162template void \ 163arrayParamOut(ostream &os, const std::string &name, \ 164 type const *param, int size); \ 165template void \ 166arrayParamIn(Checkpoint *cp, const std::string §ion, \ 167 const std::string &name, type *param, int size); 168 169 170INSTANTIATE_PARAM_TEMPLATES(int8_t) 171INSTANTIATE_PARAM_TEMPLATES(uint8_t) 172INSTANTIATE_PARAM_TEMPLATES(int16_t) 173INSTANTIATE_PARAM_TEMPLATES(uint16_t) 174INSTANTIATE_PARAM_TEMPLATES(int32_t) 175INSTANTIATE_PARAM_TEMPLATES(uint32_t) 176INSTANTIATE_PARAM_TEMPLATES(int64_t) 177INSTANTIATE_PARAM_TEMPLATES(uint64_t) 178INSTANTIATE_PARAM_TEMPLATES(bool) 179INSTANTIATE_PARAM_TEMPLATES(string) 180 181 182///////////////////////////// 183 184/// Container for serializing global variables (not associated with 185/// any serialized object). 186class Globals : public Serializable 187{ 188 public: 189 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 197string 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 = CheckpointDir(); 226 if (mkdir(dir.c_str(), 0775) == -1 && errno != EEXIST) 227 warn("could mkdir %s\n", dir); 228 229 string cpt_file = dir + "m5.cpt"; 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, 990), 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 276string __CheckpointDirBase; 277 278string 279CheckpointDir() 280{ 281 if (__CheckpointDirBase.empty()) 282 return __CheckpointDirBase; 283 284 return csprintf("%s/m5.%012d/", __CheckpointDirBase, curTick); 285} 286 287void 288SetupCheckpoint(Tick when, Tick period) 289{ 290 new SerializeEvent(when, period); 291} 292 293class SerializeParamContext : public ParamContext 294{ 295 private: 296 SerializeEvent *event; 297 298 public: 299 SerializeParamContext(const string §ion); 300 ~SerializeParamContext(); 301 void checkParams(); 302}; 303 304SerializeParamContext serialParams("serialize"); 305 306Param<string> serialize_dir(&serialParams, 307 "dir", 308 "dir to stick checkpoint in", "."); 309 310Param<Counter> serialize_cycle(&serialParams, 311 "cycle", 312 "cycle to serialize", 313 0); 314 315Param<Counter> serialize_period(&serialParams, 316 "period", 317 "period to repeat serializations", 318 0); 319 320 321 322SerializeParamContext::SerializeParamContext(const string §ion) 323 : ParamContext(section), event(NULL) 324{ } 325 326SerializeParamContext::~SerializeParamContext() 327{ 328} 329 330void 331SerializeParamContext::checkParams() 332{ 333 __CheckpointDirBase = serialize_dir; 334 if (serialize_cycle > 0) 335 SetupCheckpoint(serialize_cycle, serialize_period); 336} 337 338void 339debug_serialize() 340{ 341 Serializable::serializeAll(); 342} 343 344void 345debug_serialize(Tick when) 346{ 347 new SerializeEvent(when, 0); 348} 349 350//////////////////////////////////////////////////////////////////////// 351// 352// SerializableClass member definitions 353// 354//////////////////////////////////////////////////////////////////////// 355 356// Map of class names to SerializableBuilder creation functions. 357// Need to make this a pointer so we can force initialization on the 358// first reference; otherwise, some SerializableClass constructors 359// may be invoked before the classMap constructor. 360map<string,SerializableClass::CreateFunc> *SerializableClass::classMap = 0; 361 362// SerializableClass constructor: add mapping to classMap 363SerializableClass::SerializableClass(const string &className, 364 CreateFunc createFunc) 365{ 366 if (classMap == NULL) 367 classMap = new map<string,SerializableClass::CreateFunc>(); 368 369 if ((*classMap)[className]) 370 { 371 cerr << "Error: simulation object class " << className << " redefined" 372 << endl; 373 fatal(""); 374 } 375 376 // add className --> createFunc to class map 377 (*classMap)[className] = createFunc; 378} 379 380 381// 382// 383Serializable * 384SerializableClass::createObject(Checkpoint *cp, 385 const std::string §ion) 386{ 387 string className; 388 389 if (!cp->find(section, "type", className)) { 390 fatal("Serializable::create: no 'type' entry in section '%s'.\n", 391 section); 392 } 393 394 CreateFunc createFunc = (*classMap)[className]; 395 396 if (createFunc == NULL) { 397 fatal("Serializable::create: no create function for class '%s'.\n", 398 className); 399 } 400 401 Serializable *object = createFunc(cp, section); 402 403 assert(object != NULL); 404 405 return object; 406} 407 408 409Serializable * 410Serializable::create(Checkpoint *cp, const std::string §ion) 411{ 412 Serializable *object = SerializableClass::createObject(cp, section); 413 object->unserialize(cp, section); 414 return object; 415} 416 417 418Checkpoint::Checkpoint(const std::string &filename, const std::string &path, 419 const ConfigNode *_configNode) 420 : db(new IniFile), basePath(path), configNode(_configNode) 421{ 422 if (!db->load(filename)) { 423 fatal("Can't load checkpoint file '%s'\n", filename); 424 } 425} 426 427 428bool 429Checkpoint::find(const std::string §ion, const std::string &entry, 430 std::string &value) 431{ 432 return db->find(section, entry, value); 433} 434 435 436bool 437Checkpoint::findObj(const std::string §ion, const std::string &entry, 438 Serializable *&value) 439{ 440 string path; 441 442 if (!db->find(section, entry, path)) 443 return false; 444 445 if ((value = configNode->resolveSimObject(path)) != NULL) 446 return true; 447 448 if ((value = objMap[path]) != NULL) 449 return true; 450 451 return false; 452} 453 454 455bool 456Checkpoint::sectionExists(const std::string §ion) 457{ 458 return db->sectionExists(section); 459} 460