mem: Explicitly check MSHR snoops for cases not dealt with
[gem5.git] / src / sim / serialize.cc
1 /*
2 * Copyright (c) 2015 ARM Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Copyright (c) 2002-2005 The Regents of The University of Michigan
15 * Copyright (c) 2013 Advanced Micro Devices, Inc.
16 * Copyright (c) 2013 Mark D. Hill and David A. Wood
17 * All rights reserved.
18 *
19 * Redistribution and use in source and binary forms, with or without
20 * modification, are permitted provided that the following conditions are
21 * met: redistributions of source code must retain the above copyright
22 * notice, this list of conditions and the following disclaimer;
23 * redistributions in binary form must reproduce the above copyright
24 * notice, this list of conditions and the following disclaimer in the
25 * documentation and/or other materials provided with the distribution;
26 * neither the name of the copyright holders nor the names of its
27 * contributors may be used to endorse or promote products derived from
28 * this software without specific prior written permission.
29 *
30 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
31 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
32 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
33 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
34 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
35 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
36 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
37 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
38 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
39 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
40 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41 *
42 * Authors: Nathan Binkert
43 * Erik Hallnor
44 * Steve Reinhardt
45 * Andreas Sandberg
46 */
47
48 #include <sys/stat.h>
49 #include <sys/time.h>
50 #include <sys/types.h>
51
52 #include <cerrno>
53 #include <fstream>
54 #include <list>
55 #include <string>
56 #include <vector>
57
58 #include "base/framebuffer.hh"
59 #include "base/inifile.hh"
60 #include "base/misc.hh"
61 #include "base/output.hh"
62 #include "base/str.hh"
63 #include "base/trace.hh"
64 #include "debug/Checkpoint.hh"
65 #include "sim/eventq.hh"
66 #include "sim/serialize.hh"
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
74 using namespace std;
75
76 //
77 // The base implementations use to_number for parsing and '<<' for
78 // displaying, suitable for integer types.
79 //
80 template <class T>
81 bool
82 parseParam(const string &s, T &value)
83 {
84 return to_number(s, value);
85 }
86
87 template <class T>
88 void
89 showParam(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
103 template <>
104 void
105 showParam(CheckpointOut &os, const char &value)
106 {
107 os << (int)value;
108 }
109
110
111 template <>
112 void
113 showParam(CheckpointOut &os, const signed char &value)
114 {
115 os << (int)value;
116 }
117
118
119 template <>
120 void
121 showParam(CheckpointOut &os, const unsigned char &value)
122 {
123 os << (unsigned int)value;
124 }
125
126
127 template <>
128 bool
129 parseParam(const string &s, float &value)
130 {
131 return to_number(s, value);
132 }
133
134 template <>
135 bool
136 parseParam(const string &s, double &value)
137 {
138 return to_number(s, value);
139 }
140
141 template <>
142 bool
143 parseParam(const string &s, bool &value)
144 {
145 return to_bool(s, value);
146 }
147
148 // Display bools as strings
149 template <>
150 void
151 showParam(CheckpointOut &os, const bool &value)
152 {
153 os << (value ? "true" : "false");
154 }
155
156
157 // String requires no processing to speak of
158 template <>
159 bool
160 parseParam(const string &s, string &value)
161 {
162 value = s;
163 return true;
164 }
165
166 int Serializable::ckptMaxCount = 0;
167 int Serializable::ckptCount = 0;
168 int Serializable::ckptPrevCount = -1;
169 std::stack<std::string> Serializable::path;
170
171 template <class T>
172 void
173 paramOut(CheckpointOut &os, const string &name, const T &param)
174 {
175 os << name << "=";
176 showParam(os, param);
177 os << "\n";
178 }
179
180 template <class T>
181 void
182 arrayParamOut(CheckpointOut &os, const string &name, const vector<T> &param)
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
195 template <class T>
196 void
197 arrayParamOut(CheckpointOut &os, const string &name, const list<T> &param)
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
213 template <class T>
214 void
215 arrayParamOut(CheckpointOut &os, const string &name, const set<T> &param)
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
231 template <class T>
232 void
233 paramIn(CheckpointIn &cp, const string &name, T &param)
234 {
235 const string &section(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
242 template <class T>
243 bool
244 optParamIn(CheckpointIn &cp, const string &name, T &param, bool warn)
245 {
246 const string &section(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
257 template <class T>
258 void
259 arrayParamOut(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
273 template <class T>
274 void
275 arrayParamIn(CheckpointIn &cp, const string &name, T *param, unsigned size)
276 {
277 const string &section(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
317 template <class T>
318 void
319 arrayParamIn(CheckpointIn &cp, const string &name, vector<T> &param)
320 {
321 const string &section(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
359 template <class T>
360 void
361 arrayParamIn(CheckpointIn &cp, const string &name, list<T> &param)
362 {
363 const string &section(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
389 template <class T>
390 void
391 arrayParamIn(CheckpointIn &cp, const string &name, set<T> &param)
392 {
393 const string &section(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
420 void
421 objParamIn(CheckpointIn &cp, const string &name, SimObject * &param)
422 {
423 const string &section(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 &param); \
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> &param); \
447 template void \
448 arrayParamIn(CheckpointIn &cp, const string &name, \
449 vector<type> &param); \
450 template void \
451 arrayParamOut(CheckpointOut &os, const string &name, \
452 const list<type> &param); \
453 template void \
454 arrayParamIn(CheckpointIn &cp, const string &name, \
455 list<type> &param);
456
457 INSTANTIATE_PARAM_TEMPLATES(char)
458 INSTANTIATE_PARAM_TEMPLATES(signed char)
459 INSTANTIATE_PARAM_TEMPLATES(unsigned char)
460 INSTANTIATE_PARAM_TEMPLATES(signed short)
461 INSTANTIATE_PARAM_TEMPLATES(unsigned short)
462 INSTANTIATE_PARAM_TEMPLATES(signed int)
463 INSTANTIATE_PARAM_TEMPLATES(unsigned int)
464 INSTANTIATE_PARAM_TEMPLATES(signed long)
465 INSTANTIATE_PARAM_TEMPLATES(unsigned long)
466 INSTANTIATE_PARAM_TEMPLATES(signed long long)
467 INSTANTIATE_PARAM_TEMPLATES(unsigned long long)
468 INSTANTIATE_PARAM_TEMPLATES(bool)
469 INSTANTIATE_PARAM_TEMPLATES(float)
470 INSTANTIATE_PARAM_TEMPLATES(double)
471 INSTANTIATE_PARAM_TEMPLATES(string)
472 INSTANTIATE_PARAM_TEMPLATES(Pixel)
473
474 // set is only used with strings and furthermore doesn't agree with Pixel
475 template void
476 arrayParamOut(CheckpointOut &, const string &, const set<string> &);
477 template void
478 arrayParamIn(CheckpointIn &, const string &, set<string> &);
479
480 /////////////////////////////
481
482 /// Container for serializing global variables (not associated with
483 /// any serialized object).
484 class 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.
497 Globals 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.
501 extern std::set<std::string> version_tags;
502
503 void
504 Globals::serialize(CheckpointOut &cp) const
505 {
506 paramOut(cp, "curTick", curTick());
507 SERIALIZE_CONTAINER(version_tags);
508 }
509
510 void
511 Globals::unserialize(CheckpointIn &cp)
512 {
513 paramIn(cp, "curTick", unserializedCurTick);
514
515 const std::string &section(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
568 Serializable::Serializable()
569 {
570 }
571
572 Serializable::~Serializable()
573 {
574 }
575
576 void
577 Serializable::serializeSection(CheckpointOut &cp, const char *name) const
578 {
579 Serializable::ScopedCheckpointSection sec(cp, name);
580 serialize(cp);
581 }
582
583 void
584 Serializable::unserializeSection(CheckpointIn &cp, const char *name)
585 {
586 Serializable::ScopedCheckpointSection sec(cp, name);
587 unserialize(cp);
588 }
589
590 void
591 Serializable::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
609 void
610 Serializable::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
618 Serializable::ScopedCheckpointSection::~ScopedCheckpointSection()
619 {
620 assert(!path.empty());
621 DPRINTF(Checkpoint, "Popping: %s\n", path.top());
622 path.pop();
623 }
624
625 void
626 Serializable::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
636 void
637 Serializable::ScopedCheckpointSection::nameOut(CheckpointOut &cp)
638 {
639 DPRINTF(Checkpoint, "ScopedCheckpointSection::nameOut: %s\n",
640 Serializable::currentSection());
641 cp << "\n[" << Serializable::currentSection() << "]\n";
642 }
643
644 void
645 debug_serialize(const string &cpt_dir)
646 {
647 Serializable::serializeAll(cpt_dir);
648 }
649
650 const std::string &
651 Serializable::currentSection()
652 {
653 assert(!path.empty());
654
655 return path.top();
656 }
657
658 const char *CheckpointIn::baseFilename = "m5.cpt";
659
660 string CheckpointIn::currentDirectory;
661
662 string
663 CheckpointIn::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
674 string
675 CheckpointIn::dir()
676 {
677 return currentDirectory;
678 }
679
680
681 CheckpointIn::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
690 CheckpointIn::~CheckpointIn()
691 {
692 delete db;
693 }
694
695 bool
696 CheckpointIn::find(const string &section, const string &entry, string &value)
697 {
698 return db->find(section, entry, value);
699 }
700
701
702 bool
703 CheckpointIn::findObj(const string &section, const string &entry,
704 SimObject *&value)
705 {
706 string path;
707
708 if (!db->find(section, entry, path))
709 return false;
710
711 value = objNameResolver.resolveSimObject(path);
712 return true;
713 }
714
715
716 bool
717 CheckpointIn::sectionExists(const string &section)
718 {
719 return db->sectionExists(section);
720 }