1/* 2 * Copyright (c) 2002-2005 The Regents of The University of Michigan 3 * Copyright (c) 2013 Advanced Micro Devices, Inc. 4 * Copyright (c) 2013 Mark D. Hill and David A. Wood 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions are 9 * met: redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer; 11 * redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution; 14 * neither the name of the copyright holders nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 * 30 * Authors: Nathan Binkert 31 * Erik Hallnor 32 * Steve Reinhardt 33 */ 34 35#include <sys/stat.h> 36#include <sys/time.h> 37#include <sys/types.h> 38 39#include <cerrno> 40#include <fstream> 41#include <list> 42#include <string> 43#include <vector> 44 45#include "base/inifile.hh" 46#include "base/misc.hh" 47#include "base/output.hh" 48#include "base/str.hh" 49#include "base/trace.hh" 50#include "sim/eventq.hh" 51#include "sim/serialize.hh" 52#include "sim/sim_events.hh" 53#include "sim/sim_exit.hh" 54#include "sim/sim_object.hh" 55 56// For stat reset hack 57#include "sim/stat_control.hh" 58 59using namespace std; 60 61extern SimObject *resolveSimObject(const string &); 62 63// 64// The base implementations use to_number for parsing and '<<' for 65// displaying, suitable for integer types. 66// 67template <class T> 68bool 69parseParam(const string &s, T &value) 70{ 71 return to_number(s, value); 72} 73 74template <class T> 75void 76showParam(ostream &os, const T &value) 77{ 78 os << value; 79} 80 81// 82// Template specializations: 83// - char (8-bit integer) 84// - floating-point types 85// - bool 86// - string 87// 88 89// Treat 8-bit ints (chars) as ints on output, not as chars 90template <> 91void 92showParam(ostream &os, const char &value) 93{ 94 os << (int)value; 95} 96 97 98template <> 99void 100showParam(ostream &os, const signed char &value) 101{ 102 os << (int)value; 103} 104 105 106template <> 107void 108showParam(ostream &os, const unsigned char &value) 109{ 110 os << (unsigned int)value; 111} 112 113
|
133} 134 135// Display bools as strings 136template <> 137void 138showParam(ostream &os, const bool &value) 139{ 140 os << (value ? "true" : "false"); 141} 142 143 144// String requires no processing to speak of 145template <> 146bool 147parseParam(const string &s, string &value) 148{ 149 value = s; 150 return true; 151} 152 153int Serializable::ckptMaxCount = 0; 154int Serializable::ckptCount = 0; 155int Serializable::ckptPrevCount = -1; 156 157void 158Serializable::nameOut(ostream &os) 159{ 160 os << "\n[" << name() << "]\n"; 161} 162 163void 164Serializable::nameOut(ostream &os, const string &_name) 165{ 166 os << "\n[" << _name << "]\n"; 167} 168 169template <class T> 170void 171paramOut(ostream &os, const string &name, const T ¶m) 172{ 173 os << name << "="; 174 showParam(os, param); 175 os << "\n"; 176} 177 178template <class T> 179void 180arrayParamOut(ostream &os, const string &name, const vector<T> ¶m) 181{ 182 typename vector<T>::size_type size = param.size(); 183 os << name << "="; 184 if (size > 0) 185 showParam(os, param[0]); 186 for (typename vector<T>::size_type i = 1; i < size; ++i) { 187 os << " "; 188 showParam(os, param[i]); 189 } 190 os << "\n"; 191} 192 193template <class T> 194void 195arrayParamOut(ostream &os, const string &name, const list<T> ¶m) 196{ 197 typename list<T>::const_iterator it = param.begin(); 198 199 os << name << "="; 200 if (param.size() > 0) 201 showParam(os, *it); 202 it++; 203 while (it != param.end()) { 204 os << " "; 205 showParam(os, *it); 206 it++; 207 } 208 os << "\n"; 209} 210 211template <class T> 212void 213paramIn(Checkpoint *cp, const string §ion, const string &name, T ¶m) 214{ 215 string str; 216 if (!cp->find(section, name, str) || !parseParam(str, param)) { 217 fatal("Can't unserialize '%s:%s'\n", section, name); 218 } 219} 220 221template <class T> 222bool 223optParamIn(Checkpoint *cp, const string §ion, const string &name, T ¶m) 224{ 225 string str; 226 if (!cp->find(section, name, str) || !parseParam(str, param)) { 227 warn("optional parameter %s:%s not present\n", section, name); 228 return false; 229 } else { 230 return true; 231 } 232} 233 234template <class T> 235void 236arrayParamOut(ostream &os, const string &name, const T *param, unsigned size) 237{ 238 os << name << "="; 239 if (size > 0) 240 showParam(os, param[0]); 241 for (unsigned i = 1; i < size; ++i) { 242 os << " "; 243 showParam(os, param[i]); 244 } 245 os << "\n"; 246} 247 248 249template <class T> 250void 251arrayParamIn(Checkpoint *cp, const string §ion, const string &name, 252 T *param, unsigned size) 253{ 254 string str; 255 if (!cp->find(section, name, str)) { 256 fatal("Can't unserialize '%s:%s'\n", section, name); 257 } 258 259 // code below stolen from VectorParam<T>::parse(). 260 // it would be nice to unify these somehow... 261 262 vector<string> tokens; 263 264 tokenize(tokens, str, ' '); 265 266 // Need this if we were doing a vector 267 // value.resize(tokens.size()); 268 269 if (tokens.size() != size) { 270 fatal("Array size mismatch on %s:%s'\n", section, name); 271 } 272 273 for (vector<string>::size_type i = 0; i < tokens.size(); i++) { 274 // need to parse into local variable to handle vector<bool>, 275 // for which operator[] returns a special reference class 276 // that's not the same as 'bool&', (since it's a packed 277 // vector) 278 T scalar_value = 0; 279 if (!parseParam(tokens[i], scalar_value)) { 280 string err("could not parse \""); 281 282 err += str; 283 err += "\""; 284 285 fatal(err); 286 } 287 288 // assign parsed value to vector 289 param[i] = scalar_value; 290 } 291} 292 293template <class T> 294void 295arrayParamIn(Checkpoint *cp, const string §ion, 296 const string &name, vector<T> ¶m) 297{ 298 string str; 299 if (!cp->find(section, name, str)) { 300 fatal("Can't unserialize '%s:%s'\n", section, name); 301 } 302 303 // code below stolen from VectorParam<T>::parse(). 304 // it would be nice to unify these somehow... 305 306 vector<string> tokens; 307 308 tokenize(tokens, str, ' '); 309 310 // Need this if we were doing a vector 311 // value.resize(tokens.size()); 312 313 param.resize(tokens.size()); 314 315 for (vector<string>::size_type i = 0; i < tokens.size(); i++) { 316 // need to parse into local variable to handle vector<bool>, 317 // for which operator[] returns a special reference class 318 // that's not the same as 'bool&', (since it's a packed 319 // vector) 320 T scalar_value = 0; 321 if (!parseParam(tokens[i], scalar_value)) { 322 string err("could not parse \""); 323 324 err += str; 325 err += "\""; 326 327 fatal(err); 328 } 329 330 // assign parsed value to vector 331 param[i] = scalar_value; 332 } 333} 334 335template <class T> 336void 337arrayParamIn(Checkpoint *cp, const string §ion, 338 const string &name, list<T> ¶m) 339{ 340 string str; 341 if (!cp->find(section, name, str)) { 342 fatal("Can't unserialize '%s:%s'\n", section, name); 343 } 344 param.clear(); 345 346 vector<string> tokens; 347 tokenize(tokens, str, ' '); 348 349 for (vector<string>::size_type i = 0; i < tokens.size(); i++) { 350 T scalar_value = 0; 351 if (!parseParam(tokens[i], scalar_value)) { 352 string err("could not parse \""); 353 354 err += str; 355 err += "\""; 356 357 fatal(err); 358 } 359 360 // assign parsed value to vector 361 param.push_back(scalar_value); 362 } 363} 364 365 366void 367objParamIn(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}
|