serialize.cc revision 10386:c81407818741
1848SN/A/* 29956SN/A * Copyright (c) 2002-2005 The Regents of The University of Michigan 39956SN/A * Copyright (c) 2013 Advanced Micro Devices, Inc. 49956SN/A * Copyright (c) 2013 Mark D. Hill and David A. Wood 59956SN/A * All rights reserved. 69956SN/A * 79956SN/A * Redistribution and use in source and binary forms, with or without 89956SN/A * modification, are permitted provided that the following conditions are 99956SN/A * met: redistributions of source code must retain the above copyright 109956SN/A * notice, this list of conditions and the following disclaimer; 119956SN/A * redistributions in binary form must reproduce the above copyright 129956SN/A * notice, this list of conditions and the following disclaimer in the 139956SN/A * documentation and/or other materials provided with the distribution; 141762SN/A * neither the name of the copyright holders nor the names of its 15848SN/A * contributors may be used to endorse or promote products derived from 16848SN/A * this software without specific prior written permission. 17848SN/A * 18848SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19848SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20848SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21848SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22848SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23848SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24848SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25848SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26848SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27848SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28848SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29848SN/A * 30848SN/A * Authors: Nathan Binkert 31848SN/A * Erik Hallnor 32848SN/A * Steve Reinhardt 33848SN/A */ 34848SN/A 35848SN/A#include <sys/stat.h> 36848SN/A#include <sys/time.h> 37848SN/A#include <sys/types.h> 38848SN/A 392665SN/A#include <cerrno> 402665SN/A#include <fstream> 41848SN/A#include <list> 42848SN/A#include <string> 43848SN/A#include <vector> 44848SN/A 45848SN/A#include "base/inifile.hh" 46848SN/A#include "base/misc.hh" 4711264Sandreas.sandberg@arm.com#include "base/output.hh" 4811264Sandreas.sandberg@arm.com#include "base/str.hh" 49848SN/A#include "base/trace.hh" 502275SN/A#include "sim/eventq.hh" 51848SN/A#include "sim/serialize.hh" 5211264Sandreas.sandberg@arm.com#include "sim/sim_events.hh" 5311264Sandreas.sandberg@arm.com#include "sim/sim_exit.hh" 5411264Sandreas.sandberg@arm.com#include "sim/sim_object.hh" 5511264Sandreas.sandberg@arm.com 568229SN/A// For stat reset hack 57849SN/A#include "sim/stat_control.hh" 58848SN/A 593090SN/Ausing namespace std; 603090SN/A 618522SN/Aextern SimObject *resolveSimObject(const string &); 62849SN/A 638522SN/A// 648522SN/A// The base implementations use to_number for parsing and '<<' for 658522SN/A// displaying, suitable for integer types. 66849SN/A// 67849SN/Atemplate <class T> 68849SN/Abool 69849SN/AparseParam(const string &s, T &value) 70849SN/A{ 71849SN/A return to_number(s, value); 72849SN/A} 73849SN/A 74849SN/Atemplate <class T> 75849SN/Avoid 76849SN/AshowParam(ostream &os, const T &value) 77849SN/A{ 78849SN/A os << value; 79849SN/A} 80849SN/A 81849SN/A// 82849SN/A// Template specializations: 83849SN/A// - char (8-bit integer) 84849SN/A// - floating-point types 85849SN/A// - bool 86896SN/A// - string 87849SN/A// 888522SN/A 89849SN/A// Treat 8-bit ints (chars) as ints on output, not as chars 90849SN/Atemplate <> 91849SN/Avoid 92849SN/AshowParam(ostream &os, const char &value) 93849SN/A{ 94849SN/A os << (int)value; 95849SN/A} 96849SN/A 97849SN/A 98849SN/Atemplate <> 99849SN/Avoid 100849SN/AshowParam(ostream &os, const signed char &value) 101849SN/A{ 102849SN/A os << (int)value; 103849SN/A} 104849SN/A 105849SN/A 1061817SN/Atemplate <> 107849SN/Avoid 108849SN/AshowParam(ostream &os, const unsigned char &value) 109849SN/A{ 110849SN/A os << (unsigned int)value; 111849SN/A} 112849SN/A 113849SN/A 114849SN/Atemplate <> 115849SN/Abool 116849SN/AparseParam(const string &s, float &value) 117849SN/A{ 118849SN/A return to_number(s, value); 119893SN/A} 120893SN/A 121864SN/Atemplate <> 122849SN/Abool 123849SN/AparseParam(const string &s, double &value) 124849SN/A{ 125849SN/A return to_number(s, value); 126849SN/A} 1271817SN/A 1281817SN/Atemplate <> 129849SN/Abool 130849SN/AparseParam(const string &s, bool &value) 131849SN/A{ 132849SN/A return to_bool(s, value); 133849SN/A} 134849SN/A 135849SN/A// Display bools as strings 136849SN/Atemplate <> 137893SN/Avoid 138849SN/AshowParam(ostream &os, const bool &value) 139849SN/A{ 140864SN/A os << (value ? "true" : "false"); 141864SN/A} 142864SN/A 143864SN/A 144864SN/A// String requires no processing to speak of 145864SN/Atemplate <> 146864SN/Abool 147864SN/AparseParam(const string &s, string &value) 148864SN/A{ 149864SN/A value = s; 150849SN/A return true; 151849SN/A} 152849SN/A 153849SN/Aint Serializable::ckptMaxCount = 0; 154849SN/Aint Serializable::ckptCount = 0; 155893SN/Aint Serializable::ckptPrevCount = -1; 156849SN/A 157849SN/Avoid 158849SN/ASerializable::nameOut(ostream &os) 159849SN/A{ 160849SN/A os << "\n[" << name() << "]\n"; 161849SN/A} 162849SN/A 163893SN/Avoid 164893SN/ASerializable::nameOut(ostream &os, const string &_name) 165893SN/A{ 166849SN/A os << "\n[" << _name << "]\n"; 167849SN/A} 168849SN/A 169849SN/Atemplate <class T> 170849SN/Avoid 171849SN/AparamOut(ostream &os, const string &name, const T ¶m) 172849SN/A{ 173849SN/A os << name << "="; 174893SN/A showParam(os, param); 175893SN/A os << "\n"; 176893SN/A} 177849SN/A 178849SN/Atemplate <class T> 179849SN/Avoid 180849SN/AarrayParamOut(ostream &os, const string &name, const vector<T> ¶m) 181849SN/A{ 182849SN/A typename vector<T>::size_type size = param.size(); 183849SN/A os << name << "="; 184849SN/A if (size > 0) 185849SN/A showParam(os, param[0]); 186849SN/A for (typename vector<T>::size_type i = 1; i < size; ++i) { 187849SN/A os << " "; 188849SN/A showParam(os, param[i]); 189849SN/A } 190849SN/A os << "\n"; 191849SN/A} 1929956SN/A 1939956SN/Atemplate <class T> 194849SN/Avoid 195849SN/AarrayParamOut(ostream &os, const string &name, const list<T> ¶m) 196849SN/A{ 197849SN/A typename list<T>::const_iterator it = param.begin(); 198849SN/A 199849SN/A os << name << "="; 200849SN/A if (param.size() > 0) 201849SN/A showParam(os, *it); 202848SN/A it++; 203848SN/A while (it != param.end()) { 204848SN/A os << " "; 205849SN/A showParam(os, *it); 206848SN/A it++; 207848SN/A } 208848SN/A os << "\n"; 209848SN/A} 210848SN/A 211848SN/Atemplate <class T> 212848SN/Avoid 213848SN/AparamIn(Checkpoint *cp, const string §ion, const string &name, T ¶m) 214848SN/A{ 215848SN/A string str; 216864SN/A if (!cp->find(section, name, str) || !parseParam(str, param)) { 217848SN/A fatal("Can't unserialize '%s:%s'\n", section, name); 218848SN/A } 219849SN/A} 220849SN/A 2211722SN/Atemplate <class T> 222849SN/Abool 223849SN/AoptParamIn(Checkpoint *cp, const string §ion, const string &name, T ¶m) 224893SN/A{ 225893SN/A string str; 226849SN/A if (!cp->find(section, name, str) || !parseParam(str, param)) { 227849SN/A warn("optional parameter %s:%s not present\n", section, name); 228849SN/A return false; 229849SN/A } else { 230849SN/A return true; 231849SN/A } 232849SN/A} 233849SN/A 234893SN/Atemplate <class T> 235893SN/Avoid 236849SN/AarrayParamOut(ostream &os, const string &name, const T *param, unsigned size) 237849SN/A{ 238849SN/A os << name << "="; 239849SN/A if (size > 0) 240849SN/A showParam(os, param[0]); 241849SN/A for (unsigned i = 1; i < size; ++i) { 242849SN/A os << " "; 243849SN/A showParam(os, param[i]); 244849SN/A } 245849SN/A os << "\n"; 246849SN/A} 247849SN/A 248849SN/A 249849SN/Atemplate <class T> 250849SN/Avoid 251849SN/AarrayParamIn(Checkpoint *cp, const string §ion, const string &name, 2529956SN/A T *param, unsigned size) 2539956SN/A{ 254849SN/A string str; 2555999SN/A if (!cp->find(section, name, str)) { 2565999SN/A fatal("Can't unserialize '%s:%s'\n", section, name); 2575999SN/A } 2585999SN/A 2595999SN/A // code below stolen from VectorParam<T>::parse(). 2605999SN/A // it would be nice to unify these somehow... 2612275SN/A 262848SN/A vector<string> tokens; 2635034SN/A 2645034SN/A tokenize(tokens, str, ' '); 265848SN/A 266848SN/A // Need this if we were doing a vector 267848SN/A // value.resize(tokens.size()); 268848SN/A 269848SN/A if (tokens.size() != size) { 270848SN/A fatal("Array size mismatch on %s:%s'\n", section, name); 271848SN/A } 272893SN/A 273893SN/A for (vector<string>::size_type i = 0; i < tokens.size(); i++) { 274893SN/A // need to parse into local variable to handle vector<bool>, 275893SN/A // for which operator[] returns a special reference class 276893SN/A // that's not the same as 'bool&', (since it's a packed 2772629SN/A // vector) 2782629SN/A T scalar_value = 0; 27911169SN/A if (!parseParam(tokens[i], scalar_value)) { 2802629SN/A string err("could not parse \""); 2812629SN/A 282848SN/A err += str; 283848SN/A err += "\""; 284848SN/A 2852565SN/A fatal(err); 286848SN/A } 287848SN/A 288848SN/A // assign parsed value to vector 289848SN/A param[i] = scalar_value; 290849SN/A } 2915772SN/A} 2925772SN/A 2935772SN/Atemplate <class T> 2945772SN/Avoid 295848SN/AarrayParamIn(Checkpoint *cp, const string §ion, 296849SN/A const string &name, vector<T> ¶m) 297849SN/A{ 298849SN/A string str; 299849SN/A if (!cp->find(section, name, str)) { 300849SN/A fatal("Can't unserialize '%s:%s'\n", section, name); 301849SN/A } 302849SN/A 303849SN/A // code below stolen from VectorParam<T>::parse(). 304849SN/A // it would be nice to unify these somehow... 305849SN/A 306849SN/A vector<string> tokens; 307849SN/A 308849SN/A tokenize(tokens, str, ' '); 30912087Sspwilson2@wisc.edu 310849SN/A // Need this if we were doing a vector 3112565SN/A // value.resize(tokens.size()); 3122565SN/A 313849SN/A param.resize(tokens.size()); 3142565SN/A 31512087Sspwilson2@wisc.edu for (vector<string>::size_type i = 0; i < tokens.size(); i++) { 316849SN/A // need to parse into local variable to handle vector<bool>, 3172565SN/A // for which operator[] returns a special reference class 3182565SN/A // that's not the same as 'bool&', (since it's a packed 319849SN/A // vector) 3202565SN/A T scalar_value = 0; 32112087Sspwilson2@wisc.edu if (!parseParam(tokens[i], scalar_value)) { 322849SN/A string err("could not parse \""); 323849SN/A 32412087Sspwilson2@wisc.edu err += str; 325849SN/A err += "\""; 326849SN/A 32712087Sspwilson2@wisc.edu fatal(err); 328849SN/A } 329849SN/A 33012087Sspwilson2@wisc.edu // assign parsed value to vector 331849SN/A param[i] = scalar_value; 332849SN/A } 333849SN/A} 334849SN/A 335849SN/Atemplate <class T> 336849SN/Avoid 337849SN/AarrayParamIn(Checkpoint *cp, const string §ion, 338849SN/A const string &name, list<T> ¶m) 339849SN/A{ 340893SN/A string str; 341849SN/A if (!cp->find(section, name, str)) { 342929SN/A fatal("Can't unserialize '%s:%s'\n", section, name); 343849SN/A } 344849SN/A param.clear(); 345849SN/A 346849SN/A vector<string> tokens; 347893SN/A tokenize(tokens, str, ' '); 348849SN/A 349893SN/A for (vector<string>::size_type i = 0; i < tokens.size(); i++) { 350893SN/A T scalar_value = 0; 351893SN/A if (!parseParam(tokens[i], scalar_value)) { 352849SN/A string err("could not parse \""); 353849SN/A 354849SN/A err += str; 355849SN/A err += "\""; 356849SN/A 357849SN/A fatal(err); 358849SN/A } 359848SN/A 360864SN/A // assign parsed value to vector 361864SN/A param.push_back(scalar_value); 36211168SN/A } 36311168SN/A} 364848SN/A 365848SN/A 366848SN/Avoid 36711264Sandreas.sandberg@arm.comobjParamIn(Checkpoint *cp, const string §ion, 368 const string &name, SimObject * ¶m) 369{ 370 if (!cp->findObj(section, name, param)) { 371 fatal("Can't unserialize '%s:%s'\n", section, name); 372 } 373} 374 375 376#define INSTANTIATE_PARAM_TEMPLATES(type) \ 377template void \ 378paramOut(ostream &os, const string &name, type const ¶m); \ 379template void \ 380paramIn(Checkpoint *cp, const string §ion, \ 381 const string &name, type & param); \ 382template bool \ 383optParamIn(Checkpoint *cp, const string §ion, \ 384 const string &name, type & param); \ 385template void \ 386arrayParamOut(ostream &os, const string &name, \ 387 type const *param, unsigned size); \ 388template void \ 389arrayParamIn(Checkpoint *cp, const string §ion, \ 390 const string &name, type *param, unsigned size); \ 391template void \ 392arrayParamOut(ostream &os, const string &name, \ 393 const vector<type> ¶m); \ 394template void \ 395arrayParamIn(Checkpoint *cp, const string §ion, \ 396 const string &name, vector<type> ¶m); \ 397template void \ 398arrayParamOut(ostream &os, const string &name, \ 399 const list<type> ¶m); \ 400template void \ 401arrayParamIn(Checkpoint *cp, const string §ion, \ 402 const string &name, list<type> ¶m); 403 404INSTANTIATE_PARAM_TEMPLATES(char) 405INSTANTIATE_PARAM_TEMPLATES(signed char) 406INSTANTIATE_PARAM_TEMPLATES(unsigned char) 407INSTANTIATE_PARAM_TEMPLATES(signed short) 408INSTANTIATE_PARAM_TEMPLATES(unsigned short) 409INSTANTIATE_PARAM_TEMPLATES(signed int) 410INSTANTIATE_PARAM_TEMPLATES(unsigned int) 411INSTANTIATE_PARAM_TEMPLATES(signed long) 412INSTANTIATE_PARAM_TEMPLATES(unsigned long) 413INSTANTIATE_PARAM_TEMPLATES(signed long long) 414INSTANTIATE_PARAM_TEMPLATES(unsigned long long) 415INSTANTIATE_PARAM_TEMPLATES(bool) 416INSTANTIATE_PARAM_TEMPLATES(float) 417INSTANTIATE_PARAM_TEMPLATES(double) 418INSTANTIATE_PARAM_TEMPLATES(string) 419 420 421///////////////////////////// 422 423/// Container for serializing global variables (not associated with 424/// any serialized object). 425class Globals : public Serializable 426{ 427 public: 428 const string name() const; 429 void serialize(ostream &os); 430 void unserialize(Checkpoint *cp, const std::string §ion); 431}; 432 433/// The one and only instance of the Globals class. 434Globals globals; 435 436const string 437Globals::name() const 438{ 439 return "Globals"; 440} 441 442void 443Globals::serialize(ostream &os) 444{ 445 nameOut(os); 446 paramOut(os, "curTick", curTick()); 447 448 paramOut(os, "numMainEventQueues", numMainEventQueues); 449 450 for (uint32_t i = 0; i < numMainEventQueues; ++i) { 451 nameOut(os, "MainEventQueue"); 452 mainEventQueue[i]->serialize(os); 453 } 454} 455 456void 457Globals::unserialize(Checkpoint *cp, const std::string §ion) 458{ 459 Tick tick; 460 paramIn(cp, section, "curTick", tick); 461 paramIn(cp, section, "numMainEventQueues", numMainEventQueues); 462 463 for (uint32_t i = 0; i < numMainEventQueues; ++i) { 464 mainEventQueue[i]->setCurTick(tick); 465 mainEventQueue[i]->unserialize(cp, "MainEventQueue"); 466 } 467} 468 469Serializable::Serializable() 470{ 471} 472 473Serializable::~Serializable() 474{ 475} 476 477void 478Serializable::serialize(ostream &os) 479{ 480} 481 482void 483Serializable::unserialize(Checkpoint *cp, const string §ion) 484{ 485} 486 487void 488Serializable::serializeAll(const string &cpt_dir) 489{ 490 string dir = Checkpoint::setDir(cpt_dir); 491 if (mkdir(dir.c_str(), 0775) == -1 && errno != EEXIST) 492 fatal("couldn't mkdir %s\n", dir); 493 494 string cpt_file = dir + Checkpoint::baseFilename; 495 ofstream outstream(cpt_file.c_str()); 496 time_t t = time(NULL); 497 if (!outstream.is_open()) 498 fatal("Unable to open file %s for writing\n", cpt_file.c_str()); 499 outstream << "## checkpoint generated: " << ctime(&t); 500 501 globals.serialize(outstream); 502 SimObject::serializeAll(outstream); 503} 504 505void 506Serializable::unserializeGlobals(Checkpoint *cp) 507{ 508 globals.unserialize(cp, globals.name()); 509} 510 511void 512debug_serialize(const string &cpt_dir) 513{ 514 Serializable::serializeAll(cpt_dir); 515} 516 517 518//////////////////////////////////////////////////////////////////////// 519// 520// SerializableClass member definitions 521// 522//////////////////////////////////////////////////////////////////////// 523 524// Map of class names to SerializableBuilder creation functions. 525// Need to make this a pointer so we can force initialization on the 526// first reference; otherwise, some SerializableClass constructors 527// may be invoked before the classMap constructor. 528map<string, SerializableClass::CreateFunc> *SerializableClass::classMap = 0; 529 530// SerializableClass constructor: add mapping to classMap 531SerializableClass::SerializableClass(const string &className, 532 CreateFunc createFunc) 533{ 534 if (classMap == NULL) 535 classMap = new map<string, SerializableClass::CreateFunc>(); 536 537 if ((*classMap)[className]) 538 fatal("Error: simulation object class %s redefined\n", className); 539 540 // add className --> createFunc to class map 541 (*classMap)[className] = createFunc; 542} 543 544// 545// 546Serializable * 547SerializableClass::createObject(Checkpoint *cp, const string §ion) 548{ 549 string className; 550 551 if (!cp->find(section, "type", className)) { 552 fatal("Serializable::create: no 'type' entry in section '%s'.\n", 553 section); 554 } 555 556 CreateFunc createFunc = (*classMap)[className]; 557 558 if (createFunc == NULL) { 559 fatal("Serializable::create: no create function for class '%s'.\n", 560 className); 561 } 562 563 Serializable *object = createFunc(cp, section); 564 565 assert(object != NULL); 566 567 return object; 568} 569 570 571Serializable * 572Serializable::create(Checkpoint *cp, const string §ion) 573{ 574 Serializable *object = SerializableClass::createObject(cp, section); 575 object->unserialize(cp, section); 576 return object; 577} 578 579 580const char *Checkpoint::baseFilename = "m5.cpt"; 581 582string Checkpoint::currentDirectory; 583 584string 585Checkpoint::setDir(const string &name) 586{ 587 // use csprintf to insert curTick() into directory name if it 588 // appears to have a format placeholder in it. 589 currentDirectory = (name.find("%") != string::npos) ? 590 csprintf(name, curTick()) : name; 591 if (currentDirectory[currentDirectory.size() - 1] != '/') 592 currentDirectory += "/"; 593 return currentDirectory; 594} 595 596string 597Checkpoint::dir() 598{ 599 return currentDirectory; 600} 601 602 603Checkpoint::Checkpoint(const string &cpt_dir) 604 : db(new IniFile), cptDir(setDir(cpt_dir)) 605{ 606 string filename = cptDir + "/" + Checkpoint::baseFilename; 607 if (!db->load(filename)) { 608 fatal("Can't load checkpoint file '%s'\n", filename); 609 } 610} 611 612Checkpoint::~Checkpoint() 613{ 614 delete db; 615} 616 617bool 618Checkpoint::find(const string §ion, const string &entry, string &value) 619{ 620 return db->find(section, entry, value); 621} 622 623 624bool 625Checkpoint::findObj(const string §ion, const string &entry, 626 SimObject *&value) 627{ 628 string path; 629 630 if (!db->find(section, entry, path)) 631 return false; 632 633 value = resolveSimObject(path); 634 return true; 635} 636 637 638bool 639Checkpoint::sectionExists(const string §ion) 640{ 641 return db->sectionExists(section); 642} 643