67#include "sim/sim_events.hh" 68#include "sim/sim_exit.hh" 69#include "sim/sim_object.hh" 70 71// For stat reset hack 72#include "sim/stat_control.hh" 73 74using namespace std; 75 76// 77// The base implementations use to_number for parsing and '<<' for 78// displaying, suitable for integer types. 79// 80template <class T> 81bool 82parseParam(const string &s, T &value) 83{ 84 return to_number(s, value); 85} 86 87template <class T> 88void 89showParam(CheckpointOut &os, const T &value) 90{ 91 os << value; 92} 93 94// 95// Template specializations: 96// - char (8-bit integer) 97// - floating-point types 98// - bool 99// - string 100// 101 102// Treat 8-bit ints (chars) as ints on output, not as chars 103template <> 104void 105showParam(CheckpointOut &os, const char &value) 106{ 107 os << (int)value; 108} 109 110 111template <> 112void 113showParam(CheckpointOut &os, const signed char &value) 114{ 115 os << (int)value; 116} 117 118 119template <> 120void 121showParam(CheckpointOut &os, const unsigned char &value) 122{ 123 os << (unsigned int)value; 124} 125 126 127template <> 128bool 129parseParam(const string &s, float &value) 130{ 131 return to_number(s, value); 132} 133 134template <> 135bool 136parseParam(const string &s, double &value) 137{ 138 return to_number(s, value); 139} 140 141template <> 142bool 143parseParam(const string &s, bool &value) 144{ 145 return to_bool(s, value); 146} 147 148// Display bools as strings 149template <> 150void 151showParam(CheckpointOut &os, const bool &value) 152{ 153 os << (value ? "true" : "false"); 154} 155 156 157// String requires no processing to speak of 158template <> 159bool 160parseParam(const string &s, string &value) 161{ 162 value = s; 163 return true; 164} 165 166int Serializable::ckptMaxCount = 0; 167int Serializable::ckptCount = 0; 168int Serializable::ckptPrevCount = -1; 169std::stack<std::string> Serializable::path; 170 171template <class T> 172void 173paramOut(CheckpointOut &os, const string &name, const T ¶m) 174{ 175 os << name << "="; 176 showParam(os, param); 177 os << "\n"; 178} 179 180template <class T> 181void 182arrayParamOut(CheckpointOut &os, const string &name, const vector<T> ¶m) 183{ 184 typename vector<T>::size_type size = param.size(); 185 os << name << "="; 186 if (size > 0) 187 showParam(os, param[0]); 188 for (typename vector<T>::size_type i = 1; i < size; ++i) { 189 os << " "; 190 showParam(os, param[i]); 191 } 192 os << "\n"; 193} 194 195template <class T> 196void 197arrayParamOut(CheckpointOut &os, const string &name, const list<T> ¶m) 198{ 199 typename list<T>::const_iterator it = param.begin(); 200 201 os << name << "="; 202 if (param.size() > 0) 203 showParam(os, *it); 204 it++; 205 while (it != param.end()) { 206 os << " "; 207 showParam(os, *it); 208 it++; 209 } 210 os << "\n"; 211} 212 213template <class T> 214void 215arrayParamOut(CheckpointOut &os, const string &name, const set<T> ¶m) 216{ 217 typename set<T>::const_iterator it = param.begin(); 218 219 os << name << "="; 220 if (param.size() > 0) 221 showParam(os, *it); 222 it++; 223 while (it != param.end()) { 224 os << " "; 225 showParam(os, *it); 226 it++; 227 } 228 os << "\n"; 229} 230 231template <class T> 232void 233paramIn(CheckpointIn &cp, const string &name, T ¶m) 234{ 235 const string §ion(Serializable::currentSection()); 236 string str; 237 if (!cp.find(section, name, str) || !parseParam(str, param)) { 238 fatal("Can't unserialize '%s:%s'\n", section, name); 239 } 240} 241 242template <class T> 243bool 244optParamIn(CheckpointIn &cp, const string &name, T ¶m, bool warn) 245{ 246 const string §ion(Serializable::currentSection()); 247 string str; 248 if (!cp.find(section, name, str) || !parseParam(str, param)) { 249 if (warn) 250 warn("optional parameter %s:%s not present\n", section, name); 251 return false; 252 } else { 253 return true; 254 } 255} 256 257template <class T> 258void 259arrayParamOut(CheckpointOut &os, const string &name, 260 const T *param, unsigned size) 261{ 262 os << name << "="; 263 if (size > 0) 264 showParam(os, param[0]); 265 for (unsigned i = 1; i < size; ++i) { 266 os << " "; 267 showParam(os, param[i]); 268 } 269 os << "\n"; 270} 271 272 273template <class T> 274void 275arrayParamIn(CheckpointIn &cp, const string &name, T *param, unsigned size) 276{ 277 const string §ion(Serializable::currentSection()); 278 string str; 279 if (!cp.find(section, name, str)) { 280 fatal("Can't unserialize '%s:%s'\n", section, name); 281 } 282 283 // code below stolen from VectorParam<T>::parse(). 284 // it would be nice to unify these somehow... 285 286 vector<string> tokens; 287 288 tokenize(tokens, str, ' '); 289 290 // Need this if we were doing a vector 291 // value.resize(tokens.size()); 292 293 if (tokens.size() != size) { 294 fatal("Array size mismatch on %s:%s'\n", section, name); 295 } 296 297 for (vector<string>::size_type i = 0; i < tokens.size(); i++) { 298 // need to parse into local variable to handle vector<bool>, 299 // for which operator[] returns a special reference class 300 // that's not the same as 'bool&', (since it's a packed 301 // vector) 302 T scalar_value; 303 if (!parseParam(tokens[i], scalar_value)) { 304 string err("could not parse \""); 305 306 err += str; 307 err += "\""; 308 309 fatal(err); 310 } 311 312 // assign parsed value to vector 313 param[i] = scalar_value; 314 } 315} 316 317template <class T> 318void 319arrayParamIn(CheckpointIn &cp, const string &name, vector<T> ¶m) 320{ 321 const string §ion(Serializable::currentSection()); 322 string str; 323 if (!cp.find(section, name, str)) { 324 fatal("Can't unserialize '%s:%s'\n", section, name); 325 } 326 327 // code below stolen from VectorParam<T>::parse(). 328 // it would be nice to unify these somehow... 329 330 vector<string> tokens; 331 332 tokenize(tokens, str, ' '); 333 334 // Need this if we were doing a vector 335 // value.resize(tokens.size()); 336 337 param.resize(tokens.size()); 338 339 for (vector<string>::size_type i = 0; i < tokens.size(); i++) { 340 // need to parse into local variable to handle vector<bool>, 341 // for which operator[] returns a special reference class 342 // that's not the same as 'bool&', (since it's a packed 343 // vector) 344 T scalar_value; 345 if (!parseParam(tokens[i], scalar_value)) { 346 string err("could not parse \""); 347 348 err += str; 349 err += "\""; 350 351 fatal(err); 352 } 353 354 // assign parsed value to vector 355 param[i] = scalar_value; 356 } 357} 358 359template <class T> 360void 361arrayParamIn(CheckpointIn &cp, const string &name, list<T> ¶m) 362{ 363 const string §ion(Serializable::currentSection()); 364 string str; 365 if (!cp.find(section, name, str)) { 366 fatal("Can't unserialize '%s:%s'\n", section, name); 367 } 368 param.clear(); 369 370 vector<string> tokens; 371 tokenize(tokens, str, ' '); 372 373 for (vector<string>::size_type i = 0; i < tokens.size(); i++) { 374 T scalar_value; 375 if (!parseParam(tokens[i], scalar_value)) { 376 string err("could not parse \""); 377 378 err += str; 379 err += "\""; 380 381 fatal(err); 382 } 383 384 // assign parsed value to vector 385 param.push_back(scalar_value); 386 } 387} 388 389template <class T> 390void 391arrayParamIn(CheckpointIn &cp, const string &name, set<T> ¶m) 392{ 393 const string §ion(Serializable::currentSection()); 394 string str; 395 if (!cp.find(section, name, str)) { 396 fatal("Can't unserialize '%s:%s'\n", section, name); 397 } 398 param.clear(); 399 400 vector<string> tokens; 401 tokenize(tokens, str, ' '); 402 403 for (vector<string>::size_type i = 0; i < tokens.size(); i++) { 404 T scalar_value; 405 if (!parseParam(tokens[i], scalar_value)) { 406 string err("could not parse \""); 407 408 err += str; 409 err += "\""; 410 411 fatal(err); 412 } 413 414 // assign parsed value to vector 415 param.insert(scalar_value); 416 } 417} 418 419 420void 421objParamIn(CheckpointIn &cp, const string &name, SimObject * ¶m) 422{ 423 const string §ion(Serializable::currentSection()); 424 if (!cp.findObj(section, name, param)) { 425 fatal("Can't unserialize '%s:%s'\n", section, name); 426 } 427} 428 429 430#define INSTANTIATE_PARAM_TEMPLATES(type) \ 431 template void \ 432 paramOut(CheckpointOut &os, const string &name, type const ¶m); \ 433 template void \ 434 paramIn(CheckpointIn &cp, const string &name, type & param); \ 435 template bool \ 436 optParamIn(CheckpointIn &cp, const string &name, type & param, \ 437 bool warn); \ 438 template void \ 439 arrayParamOut(CheckpointOut &os, const string &name, \ 440 type const *param, unsigned size); \ 441 template void \ 442 arrayParamIn(CheckpointIn &cp, const string &name, \ 443 type *param, unsigned size); \ 444 template void \ 445 arrayParamOut(CheckpointOut &os, const string &name, \ 446 const vector<type> ¶m); \ 447 template void \ 448 arrayParamIn(CheckpointIn &cp, const string &name, \ 449 vector<type> ¶m); \ 450 template void \ 451 arrayParamOut(CheckpointOut &os, const string &name, \ 452 const list<type> ¶m); \ 453 template void \ 454 arrayParamIn(CheckpointIn &cp, const string &name, \ 455 list<type> ¶m); 456 457INSTANTIATE_PARAM_TEMPLATES(char) 458INSTANTIATE_PARAM_TEMPLATES(signed char) 459INSTANTIATE_PARAM_TEMPLATES(unsigned char) 460INSTANTIATE_PARAM_TEMPLATES(signed short) 461INSTANTIATE_PARAM_TEMPLATES(unsigned short) 462INSTANTIATE_PARAM_TEMPLATES(signed int) 463INSTANTIATE_PARAM_TEMPLATES(unsigned int) 464INSTANTIATE_PARAM_TEMPLATES(signed long) 465INSTANTIATE_PARAM_TEMPLATES(unsigned long) 466INSTANTIATE_PARAM_TEMPLATES(signed long long) 467INSTANTIATE_PARAM_TEMPLATES(unsigned long long) 468INSTANTIATE_PARAM_TEMPLATES(bool) 469INSTANTIATE_PARAM_TEMPLATES(float) 470INSTANTIATE_PARAM_TEMPLATES(double) 471INSTANTIATE_PARAM_TEMPLATES(string) 472INSTANTIATE_PARAM_TEMPLATES(Pixel) 473 474// set is only used with strings and furthermore doesn't agree with Pixel 475template void 476arrayParamOut(CheckpointOut &, const string &, const set<string> &); 477template void 478arrayParamIn(CheckpointIn &, const string &, set<string> &); 479 480///////////////////////////// 481 482/// Container for serializing global variables (not associated with 483/// any serialized object). 484class Globals : public Serializable 485{ 486 public: 487 Globals() 488 : unserializedCurTick(0) {} 489 490 void serialize(CheckpointOut &cp) const override; 491 void unserialize(CheckpointIn &cp) override; 492 493 Tick unserializedCurTick; 494}; 495 496/// The one and only instance of the Globals class. 497Globals globals; 498 499/// The version tags for this build of the simulator, to be stored in the 500/// Globals section during serialization and compared upon unserialization. 501extern std::set<std::string> version_tags; 502 503void 504Globals::serialize(CheckpointOut &cp) const 505{ 506 paramOut(cp, "curTick", curTick()); 507 SERIALIZE_CONTAINER(version_tags); 508} 509 510void 511Globals::unserialize(CheckpointIn &cp) 512{ 513 paramIn(cp, "curTick", unserializedCurTick); 514 515 const std::string §ion(Serializable::currentSection()); 516 std::string str; 517 if (!cp.find(section, "version_tags", str)) { 518 warn("**********************************************************\n"); 519 warn("!!!! Checkpoint uses an old versioning scheme. !!!!\n"); 520 warn("Run the checkpoint upgrader (util/cpt_upgrader.py) on your " 521 "checkpoint\n"); 522 warn("**********************************************************\n"); 523 return; 524 } 525 526 std::set<std::string> cpt_tags; 527 arrayParamIn(cp, "version_tags", cpt_tags); // UNSERIALIZE_CONTAINER 528 529 bool err = false; 530 for (const auto& t : version_tags) { 531 if (cpt_tags.find(t) == cpt_tags.end()) { 532 // checkpoint is missing tag that this binary has 533 if (!err) { 534 warn("*****************************************************\n"); 535 warn("!!!! Checkpoint is missing the following version tags:\n"); 536 err = true; 537 } 538 warn(" %s\n", t); 539 } 540 } 541 if (err) { 542 warn("You might experience some issues when restoring and should run " 543 "the checkpoint upgrader (util/cpt_upgrader.py) on your " 544 "checkpoint\n"); 545 warn("**********************************************************\n"); 546 } 547 548 err = false; 549 for (const auto& t : cpt_tags) { 550 if (version_tags.find(t) == version_tags.end()) { 551 // gem5 binary is missing tag that this checkpoint has 552 if (!err) { 553 warn("*****************************************************\n"); 554 warn("!!!! gem5 is missing the following version tags:\n"); 555 err = true; 556 } 557 warn(" %s\n", t); 558 } 559 } 560 if (err) { 561 warn("Running a checkpoint with incompatible version tags is not " 562 "supported. While it might work, you may experience incorrect " 563 "behavior or crashes.\n"); 564 warn("**********************************************************\n"); 565 } 566} 567 568Serializable::Serializable() 569{ 570} 571 572Serializable::~Serializable() 573{ 574} 575 576void 577Serializable::serializeSection(CheckpointOut &cp, const char *name) const 578{ 579 Serializable::ScopedCheckpointSection sec(cp, name); 580 serialize(cp); 581} 582 583void 584Serializable::unserializeSection(CheckpointIn &cp, const char *name) 585{ 586 Serializable::ScopedCheckpointSection sec(cp, name); 587 unserialize(cp); 588} 589 590void 591Serializable::serializeAll(const string &cpt_dir) 592{ 593 string dir = CheckpointIn::setDir(cpt_dir); 594 if (mkdir(dir.c_str(), 0775) == -1 && errno != EEXIST) 595 fatal("couldn't mkdir %s\n", dir); 596 597 string cpt_file = dir + CheckpointIn::baseFilename; 598 ofstream outstream(cpt_file.c_str()); 599 time_t t = time(NULL); 600 if (!outstream.is_open()) 601 fatal("Unable to open file %s for writing\n", cpt_file.c_str()); 602 outstream << "## checkpoint generated: " << ctime(&t); 603 604 globals.serializeSection(outstream, "Globals"); 605 606 SimObject::serializeAll(outstream); 607} 608 609void 610Serializable::unserializeGlobals(CheckpointIn &cp) 611{ 612 globals.unserializeSection(cp, "Globals"); 613 614 for (uint32_t i = 0; i < numMainEventQueues; ++i) 615 mainEventQueue[i]->setCurTick(globals.unserializedCurTick); 616} 617 618Serializable::ScopedCheckpointSection::~ScopedCheckpointSection() 619{ 620 assert(!path.empty()); 621 DPRINTF(Checkpoint, "Popping: %s\n", path.top()); 622 path.pop(); 623} 624 625void 626Serializable::ScopedCheckpointSection::pushName(const char *obj_name) 627{ 628 if (path.empty()) { 629 path.push(obj_name); 630 } else { 631 path.push(csprintf("%s.%s", path.top(), obj_name)); 632 } 633 DPRINTF(Checkpoint, "ScopedCheckpointSection::pushName: %s\n", obj_name); 634} 635 636void 637Serializable::ScopedCheckpointSection::nameOut(CheckpointOut &cp) 638{ 639 DPRINTF(Checkpoint, "ScopedCheckpointSection::nameOut: %s\n", 640 Serializable::currentSection()); 641 cp << "\n[" << Serializable::currentSection() << "]\n"; 642} 643 644void 645debug_serialize(const string &cpt_dir) 646{ 647 Serializable::serializeAll(cpt_dir); 648} 649 650const std::string & 651Serializable::currentSection() 652{ 653 assert(!path.empty()); 654 655 return path.top(); 656} 657 658const char *CheckpointIn::baseFilename = "m5.cpt"; 659 660string CheckpointIn::currentDirectory; 661 662string 663CheckpointIn::setDir(const string &name) 664{ 665 // use csprintf to insert curTick() into directory name if it 666 // appears to have a format placeholder in it. 667 currentDirectory = (name.find("%") != string::npos) ? 668 csprintf(name, curTick()) : name; 669 if (currentDirectory[currentDirectory.size() - 1] != '/') 670 currentDirectory += "/"; 671 return currentDirectory; 672} 673 674string 675CheckpointIn::dir() 676{ 677 return currentDirectory; 678} 679 680 681CheckpointIn::CheckpointIn(const string &cpt_dir, SimObjectResolver &resolver) 682 : db(new IniFile), objNameResolver(resolver), cptDir(setDir(cpt_dir)) 683{ 684 string filename = cptDir + "/" + CheckpointIn::baseFilename; 685 if (!db->load(filename)) { 686 fatal("Can't load checkpoint file '%s'\n", filename); 687 } 688} 689 690CheckpointIn::~CheckpointIn() 691{ 692 delete db; 693} 694 695bool 696CheckpointIn::entryExists(const string §ion, const string &entry) 697{ 698 return db->entryExists(section, entry); 699} 700 701bool 702CheckpointIn::find(const string §ion, const string &entry, string &value) 703{ 704 return db->find(section, entry, value); 705} 706 707 708bool 709CheckpointIn::findObj(const string §ion, const string &entry, 710 SimObject *&value) 711{ 712 string path; 713 714 if (!db->find(section, entry, path)) 715 return false; 716 717 value = objNameResolver.resolveSimObject(path); 718 return true; 719} 720 721 722bool 723CheckpointIn::sectionExists(const string §ion) 724{ 725 return db->sectionExists(section); 726}
| 68#include "sim/sim_events.hh" 69#include "sim/sim_exit.hh" 70#include "sim/sim_object.hh" 71 72// For stat reset hack 73#include "sim/stat_control.hh" 74 75using namespace std; 76 77// 78// The base implementations use to_number for parsing and '<<' for 79// displaying, suitable for integer types. 80// 81template <class T> 82bool 83parseParam(const string &s, T &value) 84{ 85 return to_number(s, value); 86} 87 88template <class T> 89void 90showParam(CheckpointOut &os, const T &value) 91{ 92 os << value; 93} 94 95// 96// Template specializations: 97// - char (8-bit integer) 98// - floating-point types 99// - bool 100// - string 101// 102 103// Treat 8-bit ints (chars) as ints on output, not as chars 104template <> 105void 106showParam(CheckpointOut &os, const char &value) 107{ 108 os << (int)value; 109} 110 111 112template <> 113void 114showParam(CheckpointOut &os, const signed char &value) 115{ 116 os << (int)value; 117} 118 119 120template <> 121void 122showParam(CheckpointOut &os, const unsigned char &value) 123{ 124 os << (unsigned int)value; 125} 126 127 128template <> 129bool 130parseParam(const string &s, float &value) 131{ 132 return to_number(s, value); 133} 134 135template <> 136bool 137parseParam(const string &s, double &value) 138{ 139 return to_number(s, value); 140} 141 142template <> 143bool 144parseParam(const string &s, bool &value) 145{ 146 return to_bool(s, value); 147} 148 149// Display bools as strings 150template <> 151void 152showParam(CheckpointOut &os, const bool &value) 153{ 154 os << (value ? "true" : "false"); 155} 156 157 158// String requires no processing to speak of 159template <> 160bool 161parseParam(const string &s, string &value) 162{ 163 value = s; 164 return true; 165} 166 167int Serializable::ckptMaxCount = 0; 168int Serializable::ckptCount = 0; 169int Serializable::ckptPrevCount = -1; 170std::stack<std::string> Serializable::path; 171 172template <class T> 173void 174paramOut(CheckpointOut &os, const string &name, const T ¶m) 175{ 176 os << name << "="; 177 showParam(os, param); 178 os << "\n"; 179} 180 181template <class T> 182void 183arrayParamOut(CheckpointOut &os, const string &name, const vector<T> ¶m) 184{ 185 typename vector<T>::size_type size = param.size(); 186 os << name << "="; 187 if (size > 0) 188 showParam(os, param[0]); 189 for (typename vector<T>::size_type i = 1; i < size; ++i) { 190 os << " "; 191 showParam(os, param[i]); 192 } 193 os << "\n"; 194} 195 196template <class T> 197void 198arrayParamOut(CheckpointOut &os, const string &name, const list<T> ¶m) 199{ 200 typename list<T>::const_iterator it = param.begin(); 201 202 os << name << "="; 203 if (param.size() > 0) 204 showParam(os, *it); 205 it++; 206 while (it != param.end()) { 207 os << " "; 208 showParam(os, *it); 209 it++; 210 } 211 os << "\n"; 212} 213 214template <class T> 215void 216arrayParamOut(CheckpointOut &os, const string &name, const set<T> ¶m) 217{ 218 typename set<T>::const_iterator it = param.begin(); 219 220 os << name << "="; 221 if (param.size() > 0) 222 showParam(os, *it); 223 it++; 224 while (it != param.end()) { 225 os << " "; 226 showParam(os, *it); 227 it++; 228 } 229 os << "\n"; 230} 231 232template <class T> 233void 234paramIn(CheckpointIn &cp, const string &name, T ¶m) 235{ 236 const string §ion(Serializable::currentSection()); 237 string str; 238 if (!cp.find(section, name, str) || !parseParam(str, param)) { 239 fatal("Can't unserialize '%s:%s'\n", section, name); 240 } 241} 242 243template <class T> 244bool 245optParamIn(CheckpointIn &cp, const string &name, T ¶m, bool warn) 246{ 247 const string §ion(Serializable::currentSection()); 248 string str; 249 if (!cp.find(section, name, str) || !parseParam(str, param)) { 250 if (warn) 251 warn("optional parameter %s:%s not present\n", section, name); 252 return false; 253 } else { 254 return true; 255 } 256} 257 258template <class T> 259void 260arrayParamOut(CheckpointOut &os, const string &name, 261 const T *param, unsigned size) 262{ 263 os << name << "="; 264 if (size > 0) 265 showParam(os, param[0]); 266 for (unsigned i = 1; i < size; ++i) { 267 os << " "; 268 showParam(os, param[i]); 269 } 270 os << "\n"; 271} 272 273 274template <class T> 275void 276arrayParamIn(CheckpointIn &cp, const string &name, T *param, unsigned size) 277{ 278 const string §ion(Serializable::currentSection()); 279 string str; 280 if (!cp.find(section, name, str)) { 281 fatal("Can't unserialize '%s:%s'\n", section, name); 282 } 283 284 // code below stolen from VectorParam<T>::parse(). 285 // it would be nice to unify these somehow... 286 287 vector<string> tokens; 288 289 tokenize(tokens, str, ' '); 290 291 // Need this if we were doing a vector 292 // value.resize(tokens.size()); 293 294 if (tokens.size() != size) { 295 fatal("Array size mismatch on %s:%s'\n", section, name); 296 } 297 298 for (vector<string>::size_type i = 0; i < tokens.size(); i++) { 299 // need to parse into local variable to handle vector<bool>, 300 // for which operator[] returns a special reference class 301 // that's not the same as 'bool&', (since it's a packed 302 // vector) 303 T scalar_value; 304 if (!parseParam(tokens[i], scalar_value)) { 305 string err("could not parse \""); 306 307 err += str; 308 err += "\""; 309 310 fatal(err); 311 } 312 313 // assign parsed value to vector 314 param[i] = scalar_value; 315 } 316} 317 318template <class T> 319void 320arrayParamIn(CheckpointIn &cp, const string &name, vector<T> ¶m) 321{ 322 const string §ion(Serializable::currentSection()); 323 string str; 324 if (!cp.find(section, name, str)) { 325 fatal("Can't unserialize '%s:%s'\n", section, name); 326 } 327 328 // code below stolen from VectorParam<T>::parse(). 329 // it would be nice to unify these somehow... 330 331 vector<string> tokens; 332 333 tokenize(tokens, str, ' '); 334 335 // Need this if we were doing a vector 336 // value.resize(tokens.size()); 337 338 param.resize(tokens.size()); 339 340 for (vector<string>::size_type i = 0; i < tokens.size(); i++) { 341 // need to parse into local variable to handle vector<bool>, 342 // for which operator[] returns a special reference class 343 // that's not the same as 'bool&', (since it's a packed 344 // vector) 345 T scalar_value; 346 if (!parseParam(tokens[i], scalar_value)) { 347 string err("could not parse \""); 348 349 err += str; 350 err += "\""; 351 352 fatal(err); 353 } 354 355 // assign parsed value to vector 356 param[i] = scalar_value; 357 } 358} 359 360template <class T> 361void 362arrayParamIn(CheckpointIn &cp, const string &name, list<T> ¶m) 363{ 364 const string §ion(Serializable::currentSection()); 365 string str; 366 if (!cp.find(section, name, str)) { 367 fatal("Can't unserialize '%s:%s'\n", section, name); 368 } 369 param.clear(); 370 371 vector<string> tokens; 372 tokenize(tokens, str, ' '); 373 374 for (vector<string>::size_type i = 0; i < tokens.size(); i++) { 375 T scalar_value; 376 if (!parseParam(tokens[i], scalar_value)) { 377 string err("could not parse \""); 378 379 err += str; 380 err += "\""; 381 382 fatal(err); 383 } 384 385 // assign parsed value to vector 386 param.push_back(scalar_value); 387 } 388} 389 390template <class T> 391void 392arrayParamIn(CheckpointIn &cp, const string &name, set<T> ¶m) 393{ 394 const string §ion(Serializable::currentSection()); 395 string str; 396 if (!cp.find(section, name, str)) { 397 fatal("Can't unserialize '%s:%s'\n", section, name); 398 } 399 param.clear(); 400 401 vector<string> tokens; 402 tokenize(tokens, str, ' '); 403 404 for (vector<string>::size_type i = 0; i < tokens.size(); i++) { 405 T scalar_value; 406 if (!parseParam(tokens[i], scalar_value)) { 407 string err("could not parse \""); 408 409 err += str; 410 err += "\""; 411 412 fatal(err); 413 } 414 415 // assign parsed value to vector 416 param.insert(scalar_value); 417 } 418} 419 420 421void 422objParamIn(CheckpointIn &cp, const string &name, SimObject * ¶m) 423{ 424 const string §ion(Serializable::currentSection()); 425 if (!cp.findObj(section, name, param)) { 426 fatal("Can't unserialize '%s:%s'\n", section, name); 427 } 428} 429 430 431#define INSTANTIATE_PARAM_TEMPLATES(type) \ 432 template void \ 433 paramOut(CheckpointOut &os, const string &name, type const ¶m); \ 434 template void \ 435 paramIn(CheckpointIn &cp, const string &name, type & param); \ 436 template bool \ 437 optParamIn(CheckpointIn &cp, const string &name, type & param, \ 438 bool warn); \ 439 template void \ 440 arrayParamOut(CheckpointOut &os, const string &name, \ 441 type const *param, unsigned size); \ 442 template void \ 443 arrayParamIn(CheckpointIn &cp, const string &name, \ 444 type *param, unsigned size); \ 445 template void \ 446 arrayParamOut(CheckpointOut &os, const string &name, \ 447 const vector<type> ¶m); \ 448 template void \ 449 arrayParamIn(CheckpointIn &cp, const string &name, \ 450 vector<type> ¶m); \ 451 template void \ 452 arrayParamOut(CheckpointOut &os, const string &name, \ 453 const list<type> ¶m); \ 454 template void \ 455 arrayParamIn(CheckpointIn &cp, const string &name, \ 456 list<type> ¶m); 457 458INSTANTIATE_PARAM_TEMPLATES(char) 459INSTANTIATE_PARAM_TEMPLATES(signed char) 460INSTANTIATE_PARAM_TEMPLATES(unsigned char) 461INSTANTIATE_PARAM_TEMPLATES(signed short) 462INSTANTIATE_PARAM_TEMPLATES(unsigned short) 463INSTANTIATE_PARAM_TEMPLATES(signed int) 464INSTANTIATE_PARAM_TEMPLATES(unsigned int) 465INSTANTIATE_PARAM_TEMPLATES(signed long) 466INSTANTIATE_PARAM_TEMPLATES(unsigned long) 467INSTANTIATE_PARAM_TEMPLATES(signed long long) 468INSTANTIATE_PARAM_TEMPLATES(unsigned long long) 469INSTANTIATE_PARAM_TEMPLATES(bool) 470INSTANTIATE_PARAM_TEMPLATES(float) 471INSTANTIATE_PARAM_TEMPLATES(double) 472INSTANTIATE_PARAM_TEMPLATES(string) 473INSTANTIATE_PARAM_TEMPLATES(Pixel) 474 475// set is only used with strings and furthermore doesn't agree with Pixel 476template void 477arrayParamOut(CheckpointOut &, const string &, const set<string> &); 478template void 479arrayParamIn(CheckpointIn &, const string &, set<string> &); 480 481///////////////////////////// 482 483/// Container for serializing global variables (not associated with 484/// any serialized object). 485class Globals : public Serializable 486{ 487 public: 488 Globals() 489 : unserializedCurTick(0) {} 490 491 void serialize(CheckpointOut &cp) const override; 492 void unserialize(CheckpointIn &cp) override; 493 494 Tick unserializedCurTick; 495}; 496 497/// The one and only instance of the Globals class. 498Globals globals; 499 500/// The version tags for this build of the simulator, to be stored in the 501/// Globals section during serialization and compared upon unserialization. 502extern std::set<std::string> version_tags; 503 504void 505Globals::serialize(CheckpointOut &cp) const 506{ 507 paramOut(cp, "curTick", curTick()); 508 SERIALIZE_CONTAINER(version_tags); 509} 510 511void 512Globals::unserialize(CheckpointIn &cp) 513{ 514 paramIn(cp, "curTick", unserializedCurTick); 515 516 const std::string §ion(Serializable::currentSection()); 517 std::string str; 518 if (!cp.find(section, "version_tags", str)) { 519 warn("**********************************************************\n"); 520 warn("!!!! Checkpoint uses an old versioning scheme. !!!!\n"); 521 warn("Run the checkpoint upgrader (util/cpt_upgrader.py) on your " 522 "checkpoint\n"); 523 warn("**********************************************************\n"); 524 return; 525 } 526 527 std::set<std::string> cpt_tags; 528 arrayParamIn(cp, "version_tags", cpt_tags); // UNSERIALIZE_CONTAINER 529 530 bool err = false; 531 for (const auto& t : version_tags) { 532 if (cpt_tags.find(t) == cpt_tags.end()) { 533 // checkpoint is missing tag that this binary has 534 if (!err) { 535 warn("*****************************************************\n"); 536 warn("!!!! Checkpoint is missing the following version tags:\n"); 537 err = true; 538 } 539 warn(" %s\n", t); 540 } 541 } 542 if (err) { 543 warn("You might experience some issues when restoring and should run " 544 "the checkpoint upgrader (util/cpt_upgrader.py) on your " 545 "checkpoint\n"); 546 warn("**********************************************************\n"); 547 } 548 549 err = false; 550 for (const auto& t : cpt_tags) { 551 if (version_tags.find(t) == version_tags.end()) { 552 // gem5 binary is missing tag that this checkpoint has 553 if (!err) { 554 warn("*****************************************************\n"); 555 warn("!!!! gem5 is missing the following version tags:\n"); 556 err = true; 557 } 558 warn(" %s\n", t); 559 } 560 } 561 if (err) { 562 warn("Running a checkpoint with incompatible version tags is not " 563 "supported. While it might work, you may experience incorrect " 564 "behavior or crashes.\n"); 565 warn("**********************************************************\n"); 566 } 567} 568 569Serializable::Serializable() 570{ 571} 572 573Serializable::~Serializable() 574{ 575} 576 577void 578Serializable::serializeSection(CheckpointOut &cp, const char *name) const 579{ 580 Serializable::ScopedCheckpointSection sec(cp, name); 581 serialize(cp); 582} 583 584void 585Serializable::unserializeSection(CheckpointIn &cp, const char *name) 586{ 587 Serializable::ScopedCheckpointSection sec(cp, name); 588 unserialize(cp); 589} 590 591void 592Serializable::serializeAll(const string &cpt_dir) 593{ 594 string dir = CheckpointIn::setDir(cpt_dir); 595 if (mkdir(dir.c_str(), 0775) == -1 && errno != EEXIST) 596 fatal("couldn't mkdir %s\n", dir); 597 598 string cpt_file = dir + CheckpointIn::baseFilename; 599 ofstream outstream(cpt_file.c_str()); 600 time_t t = time(NULL); 601 if (!outstream.is_open()) 602 fatal("Unable to open file %s for writing\n", cpt_file.c_str()); 603 outstream << "## checkpoint generated: " << ctime(&t); 604 605 globals.serializeSection(outstream, "Globals"); 606 607 SimObject::serializeAll(outstream); 608} 609 610void 611Serializable::unserializeGlobals(CheckpointIn &cp) 612{ 613 globals.unserializeSection(cp, "Globals"); 614 615 for (uint32_t i = 0; i < numMainEventQueues; ++i) 616 mainEventQueue[i]->setCurTick(globals.unserializedCurTick); 617} 618 619Serializable::ScopedCheckpointSection::~ScopedCheckpointSection() 620{ 621 assert(!path.empty()); 622 DPRINTF(Checkpoint, "Popping: %s\n", path.top()); 623 path.pop(); 624} 625 626void 627Serializable::ScopedCheckpointSection::pushName(const char *obj_name) 628{ 629 if (path.empty()) { 630 path.push(obj_name); 631 } else { 632 path.push(csprintf("%s.%s", path.top(), obj_name)); 633 } 634 DPRINTF(Checkpoint, "ScopedCheckpointSection::pushName: %s\n", obj_name); 635} 636 637void 638Serializable::ScopedCheckpointSection::nameOut(CheckpointOut &cp) 639{ 640 DPRINTF(Checkpoint, "ScopedCheckpointSection::nameOut: %s\n", 641 Serializable::currentSection()); 642 cp << "\n[" << Serializable::currentSection() << "]\n"; 643} 644 645void 646debug_serialize(const string &cpt_dir) 647{ 648 Serializable::serializeAll(cpt_dir); 649} 650 651const std::string & 652Serializable::currentSection() 653{ 654 assert(!path.empty()); 655 656 return path.top(); 657} 658 659const char *CheckpointIn::baseFilename = "m5.cpt"; 660 661string CheckpointIn::currentDirectory; 662 663string 664CheckpointIn::setDir(const string &name) 665{ 666 // use csprintf to insert curTick() into directory name if it 667 // appears to have a format placeholder in it. 668 currentDirectory = (name.find("%") != string::npos) ? 669 csprintf(name, curTick()) : name; 670 if (currentDirectory[currentDirectory.size() - 1] != '/') 671 currentDirectory += "/"; 672 return currentDirectory; 673} 674 675string 676CheckpointIn::dir() 677{ 678 return currentDirectory; 679} 680 681 682CheckpointIn::CheckpointIn(const string &cpt_dir, SimObjectResolver &resolver) 683 : db(new IniFile), objNameResolver(resolver), cptDir(setDir(cpt_dir)) 684{ 685 string filename = cptDir + "/" + CheckpointIn::baseFilename; 686 if (!db->load(filename)) { 687 fatal("Can't load checkpoint file '%s'\n", filename); 688 } 689} 690 691CheckpointIn::~CheckpointIn() 692{ 693 delete db; 694} 695 696bool 697CheckpointIn::entryExists(const string §ion, const string &entry) 698{ 699 return db->entryExists(section, entry); 700} 701 702bool 703CheckpointIn::find(const string §ion, const string &entry, string &value) 704{ 705 return db->find(section, entry, value); 706} 707 708 709bool 710CheckpointIn::findObj(const string §ion, const string &entry, 711 SimObject *&value) 712{ 713 string path; 714 715 if (!db->find(section, entry, path)) 716 return false; 717 718 value = objNameResolver.resolveSimObject(path); 719 return true; 720} 721 722 723bool 724CheckpointIn::sectionExists(const string §ion) 725{ 726 return db->sectionExists(section); 727}
|