serialize.cc (6225:ec76e5c7cdd3) serialize.cc (6227:a17798f2a52c)
1/*
2 * Copyright (c) 2002-2005 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Nathan Binkert
29 * Erik Hallnor
30 * Steve Reinhardt
31 */
32
33#include <sys/time.h>
34#include <sys/types.h>
35#include <sys/stat.h>
36#include <errno.h>
37
38#include <fstream>
39#include <list>
40#include <string>
41#include <vector>
42
43#include "base/inifile.hh"
44#include "base/misc.hh"
45#include "base/output.hh"
46#include "base/str.hh"
47#include "base/trace.hh"
48#include "sim/eventq.hh"
49#include "sim/serialize.hh"
50#include "sim/sim_events.hh"
51#include "sim/sim_exit.hh"
52#include "sim/sim_object.hh"
53
54// For stat reset hack
55#include "sim/stat_control.hh"
56
57using namespace std;
58
59extern SimObject *resolveSimObject(const string &);
60
61//
62// The base implementations use to_number for parsing and '<<' for
63// displaying, suitable for integer types.
64//
65template <class T>
66bool
67parseParam(const string &s, T &value)
68{
69 return to_number(s, value);
70}
71
72template <class T>
73void
74showParam(ostream &os, const T &value)
75{
76 os << value;
77}
78
79//
80// Template specializations:
81// - char (8-bit integer)
82// - floating-point types
83// - bool
84// - string
85//
86
87// Treat 8-bit ints (chars) as ints on output, not as chars
88template <>
89void
90showParam(ostream &os, const char &value)
91{
92 os << (int)value;
93}
94
95
96template <>
97void
98showParam(ostream &os, const unsigned char &value)
99{
100 os << (unsigned int)value;
101}
102
103
104// Use sscanf() for FP types as to_number() only handles integers
105template <>
106bool
107parseParam(const string &s, float &value)
108{
109 return (sscanf(s.c_str(), "%f", &value) == 1);
110}
111
112template <>
113bool
114parseParam(const string &s, double &value)
115{
116 return (sscanf(s.c_str(), "%lf", &value) == 1);
117}
118
119template <>
120bool
121parseParam(const string &s, bool &value)
122{
123 const string &ls = to_lower(s);
124
125 if (ls == "true") {
126 value = true;
127 return true;
128 }
129
130 if (ls == "false") {
131 value = false;
132 return true;
133 }
134
135 return false;
136}
137
138// Display bools as strings
139template <>
140void
141showParam(ostream &os, const bool &value)
142{
143 os << (value ? "true" : "false");
144}
145
146
147// String requires no processing to speak of
148template <>
149bool
150parseParam(const string &s, string &value)
151{
152 value = s;
153 return true;
154}
155
156int Serializable::ckptMaxCount = 0;
157int Serializable::ckptCount = 0;
158int Serializable::ckptPrevCount = -1;
159
160void
161Serializable::nameOut(ostream &os)
162{
163 os << "\n[" << name() << "]\n";
164}
165
166void
167Serializable::nameOut(ostream &os, const string &_name)
168{
169 os << "\n[" << _name << "]\n";
170}
171
172template <class T>
173void
174paramOut(ostream &os, const string &name, const T &param)
175{
176 os << name << "=";
177 showParam(os, param);
178 os << "\n";
179}
180
181template <class T>
182void
183arrayParamOut(ostream &os, const string &name, const vector<T> &param)
184{
1/*
2 * Copyright (c) 2002-2005 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Nathan Binkert
29 * Erik Hallnor
30 * Steve Reinhardt
31 */
32
33#include <sys/time.h>
34#include <sys/types.h>
35#include <sys/stat.h>
36#include <errno.h>
37
38#include <fstream>
39#include <list>
40#include <string>
41#include <vector>
42
43#include "base/inifile.hh"
44#include "base/misc.hh"
45#include "base/output.hh"
46#include "base/str.hh"
47#include "base/trace.hh"
48#include "sim/eventq.hh"
49#include "sim/serialize.hh"
50#include "sim/sim_events.hh"
51#include "sim/sim_exit.hh"
52#include "sim/sim_object.hh"
53
54// For stat reset hack
55#include "sim/stat_control.hh"
56
57using namespace std;
58
59extern SimObject *resolveSimObject(const string &);
60
61//
62// The base implementations use to_number for parsing and '<<' for
63// displaying, suitable for integer types.
64//
65template <class T>
66bool
67parseParam(const string &s, T &value)
68{
69 return to_number(s, value);
70}
71
72template <class T>
73void
74showParam(ostream &os, const T &value)
75{
76 os << value;
77}
78
79//
80// Template specializations:
81// - char (8-bit integer)
82// - floating-point types
83// - bool
84// - string
85//
86
87// Treat 8-bit ints (chars) as ints on output, not as chars
88template <>
89void
90showParam(ostream &os, const char &value)
91{
92 os << (int)value;
93}
94
95
96template <>
97void
98showParam(ostream &os, const unsigned char &value)
99{
100 os << (unsigned int)value;
101}
102
103
104// Use sscanf() for FP types as to_number() only handles integers
105template <>
106bool
107parseParam(const string &s, float &value)
108{
109 return (sscanf(s.c_str(), "%f", &value) == 1);
110}
111
112template <>
113bool
114parseParam(const string &s, double &value)
115{
116 return (sscanf(s.c_str(), "%lf", &value) == 1);
117}
118
119template <>
120bool
121parseParam(const string &s, bool &value)
122{
123 const string &ls = to_lower(s);
124
125 if (ls == "true") {
126 value = true;
127 return true;
128 }
129
130 if (ls == "false") {
131 value = false;
132 return true;
133 }
134
135 return false;
136}
137
138// Display bools as strings
139template <>
140void
141showParam(ostream &os, const bool &value)
142{
143 os << (value ? "true" : "false");
144}
145
146
147// String requires no processing to speak of
148template <>
149bool
150parseParam(const string &s, string &value)
151{
152 value = s;
153 return true;
154}
155
156int Serializable::ckptMaxCount = 0;
157int Serializable::ckptCount = 0;
158int Serializable::ckptPrevCount = -1;
159
160void
161Serializable::nameOut(ostream &os)
162{
163 os << "\n[" << name() << "]\n";
164}
165
166void
167Serializable::nameOut(ostream &os, const string &_name)
168{
169 os << "\n[" << _name << "]\n";
170}
171
172template <class T>
173void
174paramOut(ostream &os, const string &name, const T &param)
175{
176 os << name << "=";
177 showParam(os, param);
178 os << "\n";
179}
180
181template <class T>
182void
183arrayParamOut(ostream &os, const string &name, const vector<T> &param)
184{
185 int size = param.size();
185 typename vector<T>::size_type size = param.size();
186 os << name << "=";
187 if (size > 0)
188 showParam(os, param[0]);
186 os << name << "=";
187 if (size > 0)
188 showParam(os, param[0]);
189 for (int i = 1; i < size; ++i) {
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
196
197template <class T>
198void
199paramIn(Checkpoint *cp, const string &section, const string &name, T &param)
200{
201 string str;
202 if (!cp->find(section, name, str) || !parseParam(str, param)) {
203 fatal("Can't unserialize '%s:%s'\n", section, name);
204 }
205}
206
207
208template <class T>
209void
190 os << " ";
191 showParam(os, param[i]);
192 }
193 os << "\n";
194}
195
196
197template <class T>
198void
199paramIn(Checkpoint *cp, const string &section, const string &name, T &param)
200{
201 string str;
202 if (!cp->find(section, name, str) || !parseParam(str, param)) {
203 fatal("Can't unserialize '%s:%s'\n", section, name);
204 }
205}
206
207
208template <class T>
209void
210arrayParamOut(ostream &os, const string &name, const T *param, int size)
210arrayParamOut(ostream &os, const string &name, const T *param, unsigned size)
211{
212 os << name << "=";
213 if (size > 0)
214 showParam(os, param[0]);
211{
212 os << name << "=";
213 if (size > 0)
214 showParam(os, param[0]);
215 for (int i = 1; i < size; ++i) {
215 for (unsigned i = 1; i < size; ++i) {
216 os << " ";
217 showParam(os, param[i]);
218 }
219 os << "\n";
220}
221
222
223template <class T>
224void
225arrayParamIn(Checkpoint *cp, const string &section, const string &name,
216 os << " ";
217 showParam(os, param[i]);
218 }
219 os << "\n";
220}
221
222
223template <class T>
224void
225arrayParamIn(Checkpoint *cp, const string &section, const string &name,
226 T *param, int size)
226 T *param, unsigned size)
227{
228 string str;
229 if (!cp->find(section, name, str)) {
230 fatal("Can't unserialize '%s:%s'\n", section, name);
231 }
232
233 // code below stolen from VectorParam<T>::parse().
234 // it would be nice to unify these somehow...
235
236 vector<string> tokens;
237
238 tokenize(tokens, str, ' ');
239
240 // Need this if we were doing a vector
241 // value.resize(tokens.size());
242
243 if (tokens.size() != size) {
244 fatal("Array size mismatch on %s:%s'\n", section, name);
245 }
246
227{
228 string str;
229 if (!cp->find(section, name, str)) {
230 fatal("Can't unserialize '%s:%s'\n", section, name);
231 }
232
233 // code below stolen from VectorParam<T>::parse().
234 // it would be nice to unify these somehow...
235
236 vector<string> tokens;
237
238 tokenize(tokens, str, ' ');
239
240 // Need this if we were doing a vector
241 // value.resize(tokens.size());
242
243 if (tokens.size() != size) {
244 fatal("Array size mismatch on %s:%s'\n", section, name);
245 }
246
247 for (int i = 0; i < tokens.size(); i++) {
247 for (vector<string>::size_type i = 0; i < tokens.size(); i++) {
248 // need to parse into local variable to handle vector<bool>,
249 // for which operator[] returns a special reference class
250 // that's not the same as 'bool&', (since it's a packed
251 // vector)
252 T scalar_value;
253 if (!parseParam(tokens[i], scalar_value)) {
254 string err("could not parse \"");
255
256 err += str;
257 err += "\"";
258
259 fatal(err);
260 }
261
262 // assign parsed value to vector
263 param[i] = scalar_value;
264 }
265}
266
267template <class T>
268void
269arrayParamIn(Checkpoint *cp, const string &section,
270 const string &name, vector<T> &param)
271{
272 string str;
273 if (!cp->find(section, name, str)) {
274 fatal("Can't unserialize '%s:%s'\n", section, name);
275 }
276
277 // code below stolen from VectorParam<T>::parse().
278 // it would be nice to unify these somehow...
279
280 vector<string> tokens;
281
282 tokenize(tokens, str, ' ');
283
284 // Need this if we were doing a vector
285 // value.resize(tokens.size());
286
287 param.resize(tokens.size());
288
248 // need to parse into local variable to handle vector<bool>,
249 // for which operator[] returns a special reference class
250 // that's not the same as 'bool&', (since it's a packed
251 // vector)
252 T scalar_value;
253 if (!parseParam(tokens[i], scalar_value)) {
254 string err("could not parse \"");
255
256 err += str;
257 err += "\"";
258
259 fatal(err);
260 }
261
262 // assign parsed value to vector
263 param[i] = scalar_value;
264 }
265}
266
267template <class T>
268void
269arrayParamIn(Checkpoint *cp, const string &section,
270 const string &name, vector<T> &param)
271{
272 string str;
273 if (!cp->find(section, name, str)) {
274 fatal("Can't unserialize '%s:%s'\n", section, name);
275 }
276
277 // code below stolen from VectorParam<T>::parse().
278 // it would be nice to unify these somehow...
279
280 vector<string> tokens;
281
282 tokenize(tokens, str, ' ');
283
284 // Need this if we were doing a vector
285 // value.resize(tokens.size());
286
287 param.resize(tokens.size());
288
289 for (int i = 0; i < tokens.size(); i++) {
289 for (vector<string>::size_type i = 0; i < tokens.size(); i++) {
290 // need to parse into local variable to handle vector<bool>,
291 // for which operator[] returns a special reference class
292 // that's not the same as 'bool&', (since it's a packed
293 // vector)
294 T scalar_value;
295 if (!parseParam(tokens[i], scalar_value)) {
296 string err("could not parse \"");
297
298 err += str;
299 err += "\"";
300
301 fatal(err);
302 }
303
304 // assign parsed value to vector
305 param[i] = scalar_value;
306 }
307}
308
290 // need to parse into local variable to handle vector<bool>,
291 // for which operator[] returns a special reference class
292 // that's not the same as 'bool&', (since it's a packed
293 // vector)
294 T scalar_value;
295 if (!parseParam(tokens[i], scalar_value)) {
296 string err("could not parse \"");
297
298 err += str;
299 err += "\"";
300
301 fatal(err);
302 }
303
304 // assign parsed value to vector
305 param[i] = scalar_value;
306 }
307}
308
309
310
311void
312objParamIn(Checkpoint *cp, const string &section,
313 const string &name, SimObject * &param)
314{
315 if (!cp->findObj(section, name, param)) {
316 fatal("Can't unserialize '%s:%s'\n", section, name);
317 }
318}
319
320
321#define INSTANTIATE_PARAM_TEMPLATES(type) \
322template void \
323paramOut(ostream &os, const string &name, type const &param); \
324template void \
325paramIn(Checkpoint *cp, const string &section, \
326 const string &name, type & param); \
327template void \
328arrayParamOut(ostream &os, const string &name, \
309void
310objParamIn(Checkpoint *cp, const string &section,
311 const string &name, SimObject * &param)
312{
313 if (!cp->findObj(section, name, param)) {
314 fatal("Can't unserialize '%s:%s'\n", section, name);
315 }
316}
317
318
319#define INSTANTIATE_PARAM_TEMPLATES(type) \
320template void \
321paramOut(ostream &os, const string &name, type const &param); \
322template void \
323paramIn(Checkpoint *cp, const string &section, \
324 const string &name, type & param); \
325template void \
326arrayParamOut(ostream &os, const string &name, \
329 type const *param, int size); \
327 type const *param, unsigned size); \
330template void \
331arrayParamIn(Checkpoint *cp, const string &section, \
328template void \
329arrayParamIn(Checkpoint *cp, const string &section, \
332 const string &name, type *param, int size); \
330 const string &name, type *param, unsigned size); \
333template void \
334arrayParamOut(ostream &os, const string &name, \
335 const vector<type> &param); \
336template void \
337arrayParamIn(Checkpoint *cp, const string &section, \
338 const string &name, vector<type> &param);
339
340INSTANTIATE_PARAM_TEMPLATES(signed char)
341INSTANTIATE_PARAM_TEMPLATES(unsigned char)
342INSTANTIATE_PARAM_TEMPLATES(signed short)
343INSTANTIATE_PARAM_TEMPLATES(unsigned short)
344INSTANTIATE_PARAM_TEMPLATES(signed int)
345INSTANTIATE_PARAM_TEMPLATES(unsigned int)
346INSTANTIATE_PARAM_TEMPLATES(signed long)
347INSTANTIATE_PARAM_TEMPLATES(unsigned long)
348INSTANTIATE_PARAM_TEMPLATES(signed long long)
349INSTANTIATE_PARAM_TEMPLATES(unsigned long long)
350INSTANTIATE_PARAM_TEMPLATES(bool)
351INSTANTIATE_PARAM_TEMPLATES(float)
352INSTANTIATE_PARAM_TEMPLATES(double)
353INSTANTIATE_PARAM_TEMPLATES(string)
354
355
356/////////////////////////////
357
358/// Container for serializing global variables (not associated with
359/// any serialized object).
360class Globals : public Serializable
361{
362 public:
363 const string name() const;
364 void serialize(ostream &os);
365 void unserialize(Checkpoint *cp);
366};
367
368/// The one and only instance of the Globals class.
369Globals globals;
370
371const string
372Globals::name() const
373{
374 return "Globals";
375}
376
377void
378Globals::serialize(ostream &os)
379{
380 nameOut(os);
381 SERIALIZE_SCALAR(curTick);
382
383 nameOut(os, "MainEventQueue");
384 mainEventQueue.serialize(os);
385}
386
387void
388Globals::unserialize(Checkpoint *cp)
389{
390 const string &section = name();
391 UNSERIALIZE_SCALAR(curTick);
392
393 mainEventQueue.unserialize(cp, "MainEventQueue");
394}
395
396Serializable::Serializable()
397{
398}
399
400Serializable::~Serializable()
401{
402}
403
404void
405Serializable::serialize(ostream &os)
406{
407}
408
409void
410Serializable::unserialize(Checkpoint *cp, const string &section)
411{
412}
413
414void
415Serializable::serializeAll(const string &cpt_dir)
416{
417 setCheckpointDir(cpt_dir);
418 string dir = Checkpoint::dir();
419 if (mkdir(dir.c_str(), 0775) == -1 && errno != EEXIST)
420 fatal("couldn't mkdir %s\n", dir);
421
422 string cpt_file = dir + Checkpoint::baseFilename;
423 ofstream outstream(cpt_file.c_str());
424 time_t t = time(NULL);
425 if (!outstream.is_open())
426 fatal("Unable to open file %s for writing\n", cpt_file.c_str());
427 outstream << "// checkpoint generated: " << ctime(&t);
428
429 globals.serialize(outstream);
430 SimObject::serializeAll(outstream);
431}
432
433void
434Serializable::unserializeAll(const string &cpt_dir)
435{
436 setCheckpointDir(cpt_dir);
437 string dir = Checkpoint::dir();
438 string cpt_file = dir + Checkpoint::baseFilename;
439 string section = "";
440
441 DPRINTFR(Config, "Loading checkpoint dir '%s'\n",
442 dir);
443 Checkpoint *cp = new Checkpoint(dir, section);
444 unserializeGlobals(cp);
445 SimObject::unserializeAll(cp);
446}
447
448void
449Serializable::unserializeGlobals(Checkpoint *cp)
450{
451 globals.unserialize(cp);
452}
453
454const char *Checkpoint::baseFilename = "m5.cpt";
455
456static string checkpointDirBase;
457
458void
459setCheckpointDir(const string &name)
460{
461 checkpointDirBase = name;
462 if (checkpointDirBase[checkpointDirBase.size() - 1] != '/')
463 checkpointDirBase += "/";
464}
465
466string
467Checkpoint::dir()
468{
469 // use csprintf to insert curTick into directory name if it
470 // appears to have a format placeholder in it.
471 return (checkpointDirBase.find("%") != string::npos) ?
472 csprintf(checkpointDirBase, curTick) : checkpointDirBase;
473}
474
475void
476debug_serialize(const string &cpt_dir)
477{
478 Serializable::serializeAll(cpt_dir);
479}
480
481
482////////////////////////////////////////////////////////////////////////
483//
484// SerializableClass member definitions
485//
486////////////////////////////////////////////////////////////////////////
487
488// Map of class names to SerializableBuilder creation functions.
489// Need to make this a pointer so we can force initialization on the
490// first reference; otherwise, some SerializableClass constructors
491// may be invoked before the classMap constructor.
492map<string, SerializableClass::CreateFunc> *SerializableClass::classMap = 0;
493
494// SerializableClass constructor: add mapping to classMap
495SerializableClass::SerializableClass(const string &className,
496 CreateFunc createFunc)
497{
498 if (classMap == NULL)
499 classMap = new map<string, SerializableClass::CreateFunc>();
500
501 if ((*classMap)[className])
502 fatal("Error: simulation object class %s redefined\n", className);
503
504 // add className --> createFunc to class map
505 (*classMap)[className] = createFunc;
506}
507
508//
509//
510Serializable *
511SerializableClass::createObject(Checkpoint *cp, const string &section)
512{
513 string className;
514
515 if (!cp->find(section, "type", className)) {
516 fatal("Serializable::create: no 'type' entry in section '%s'.\n",
517 section);
518 }
519
520 CreateFunc createFunc = (*classMap)[className];
521
522 if (createFunc == NULL) {
523 fatal("Serializable::create: no create function for class '%s'.\n",
524 className);
525 }
526
527 Serializable *object = createFunc(cp, section);
528
529 assert(object != NULL);
530
531 return object;
532}
533
534
535Serializable *
536Serializable::create(Checkpoint *cp, const string &section)
537{
538 Serializable *object = SerializableClass::createObject(cp, section);
539 object->unserialize(cp, section);
540 return object;
541}
542
543
544Checkpoint::Checkpoint(const string &cpt_dir, const string &path)
545 : db(new IniFile), basePath(path), cptDir(cpt_dir)
546{
547 string filename = cpt_dir + "/" + Checkpoint::baseFilename;
548 if (!db->load(filename)) {
549 fatal("Can't load checkpoint file '%s'\n", filename);
550 }
551}
552
553
554bool
555Checkpoint::find(const string &section, const string &entry, string &value)
556{
557 return db->find(section, entry, value);
558}
559
560
561bool
562Checkpoint::findObj(const string &section, const string &entry,
563 SimObject *&value)
564{
565 string path;
566
567 if (!db->find(section, entry, path))
568 return false;
569
570 value = resolveSimObject(path);
571 return true;
572}
573
574
575bool
576Checkpoint::sectionExists(const string &section)
577{
578 return db->sectionExists(section);
579}
331template void \
332arrayParamOut(ostream &os, const string &name, \
333 const vector<type> &param); \
334template void \
335arrayParamIn(Checkpoint *cp, const string &section, \
336 const string &name, vector<type> &param);
337
338INSTANTIATE_PARAM_TEMPLATES(signed char)
339INSTANTIATE_PARAM_TEMPLATES(unsigned char)
340INSTANTIATE_PARAM_TEMPLATES(signed short)
341INSTANTIATE_PARAM_TEMPLATES(unsigned short)
342INSTANTIATE_PARAM_TEMPLATES(signed int)
343INSTANTIATE_PARAM_TEMPLATES(unsigned int)
344INSTANTIATE_PARAM_TEMPLATES(signed long)
345INSTANTIATE_PARAM_TEMPLATES(unsigned long)
346INSTANTIATE_PARAM_TEMPLATES(signed long long)
347INSTANTIATE_PARAM_TEMPLATES(unsigned long long)
348INSTANTIATE_PARAM_TEMPLATES(bool)
349INSTANTIATE_PARAM_TEMPLATES(float)
350INSTANTIATE_PARAM_TEMPLATES(double)
351INSTANTIATE_PARAM_TEMPLATES(string)
352
353
354/////////////////////////////
355
356/// Container for serializing global variables (not associated with
357/// any serialized object).
358class Globals : public Serializable
359{
360 public:
361 const string name() const;
362 void serialize(ostream &os);
363 void unserialize(Checkpoint *cp);
364};
365
366/// The one and only instance of the Globals class.
367Globals globals;
368
369const string
370Globals::name() const
371{
372 return "Globals";
373}
374
375void
376Globals::serialize(ostream &os)
377{
378 nameOut(os);
379 SERIALIZE_SCALAR(curTick);
380
381 nameOut(os, "MainEventQueue");
382 mainEventQueue.serialize(os);
383}
384
385void
386Globals::unserialize(Checkpoint *cp)
387{
388 const string &section = name();
389 UNSERIALIZE_SCALAR(curTick);
390
391 mainEventQueue.unserialize(cp, "MainEventQueue");
392}
393
394Serializable::Serializable()
395{
396}
397
398Serializable::~Serializable()
399{
400}
401
402void
403Serializable::serialize(ostream &os)
404{
405}
406
407void
408Serializable::unserialize(Checkpoint *cp, const string &section)
409{
410}
411
412void
413Serializable::serializeAll(const string &cpt_dir)
414{
415 setCheckpointDir(cpt_dir);
416 string dir = Checkpoint::dir();
417 if (mkdir(dir.c_str(), 0775) == -1 && errno != EEXIST)
418 fatal("couldn't mkdir %s\n", dir);
419
420 string cpt_file = dir + Checkpoint::baseFilename;
421 ofstream outstream(cpt_file.c_str());
422 time_t t = time(NULL);
423 if (!outstream.is_open())
424 fatal("Unable to open file %s for writing\n", cpt_file.c_str());
425 outstream << "// checkpoint generated: " << ctime(&t);
426
427 globals.serialize(outstream);
428 SimObject::serializeAll(outstream);
429}
430
431void
432Serializable::unserializeAll(const string &cpt_dir)
433{
434 setCheckpointDir(cpt_dir);
435 string dir = Checkpoint::dir();
436 string cpt_file = dir + Checkpoint::baseFilename;
437 string section = "";
438
439 DPRINTFR(Config, "Loading checkpoint dir '%s'\n",
440 dir);
441 Checkpoint *cp = new Checkpoint(dir, section);
442 unserializeGlobals(cp);
443 SimObject::unserializeAll(cp);
444}
445
446void
447Serializable::unserializeGlobals(Checkpoint *cp)
448{
449 globals.unserialize(cp);
450}
451
452const char *Checkpoint::baseFilename = "m5.cpt";
453
454static string checkpointDirBase;
455
456void
457setCheckpointDir(const string &name)
458{
459 checkpointDirBase = name;
460 if (checkpointDirBase[checkpointDirBase.size() - 1] != '/')
461 checkpointDirBase += "/";
462}
463
464string
465Checkpoint::dir()
466{
467 // use csprintf to insert curTick into directory name if it
468 // appears to have a format placeholder in it.
469 return (checkpointDirBase.find("%") != string::npos) ?
470 csprintf(checkpointDirBase, curTick) : checkpointDirBase;
471}
472
473void
474debug_serialize(const string &cpt_dir)
475{
476 Serializable::serializeAll(cpt_dir);
477}
478
479
480////////////////////////////////////////////////////////////////////////
481//
482// SerializableClass member definitions
483//
484////////////////////////////////////////////////////////////////////////
485
486// Map of class names to SerializableBuilder creation functions.
487// Need to make this a pointer so we can force initialization on the
488// first reference; otherwise, some SerializableClass constructors
489// may be invoked before the classMap constructor.
490map<string, SerializableClass::CreateFunc> *SerializableClass::classMap = 0;
491
492// SerializableClass constructor: add mapping to classMap
493SerializableClass::SerializableClass(const string &className,
494 CreateFunc createFunc)
495{
496 if (classMap == NULL)
497 classMap = new map<string, SerializableClass::CreateFunc>();
498
499 if ((*classMap)[className])
500 fatal("Error: simulation object class %s redefined\n", className);
501
502 // add className --> createFunc to class map
503 (*classMap)[className] = createFunc;
504}
505
506//
507//
508Serializable *
509SerializableClass::createObject(Checkpoint *cp, const string &section)
510{
511 string className;
512
513 if (!cp->find(section, "type", className)) {
514 fatal("Serializable::create: no 'type' entry in section '%s'.\n",
515 section);
516 }
517
518 CreateFunc createFunc = (*classMap)[className];
519
520 if (createFunc == NULL) {
521 fatal("Serializable::create: no create function for class '%s'.\n",
522 className);
523 }
524
525 Serializable *object = createFunc(cp, section);
526
527 assert(object != NULL);
528
529 return object;
530}
531
532
533Serializable *
534Serializable::create(Checkpoint *cp, const string &section)
535{
536 Serializable *object = SerializableClass::createObject(cp, section);
537 object->unserialize(cp, section);
538 return object;
539}
540
541
542Checkpoint::Checkpoint(const string &cpt_dir, const string &path)
543 : db(new IniFile), basePath(path), cptDir(cpt_dir)
544{
545 string filename = cpt_dir + "/" + Checkpoint::baseFilename;
546 if (!db->load(filename)) {
547 fatal("Can't load checkpoint file '%s'\n", filename);
548 }
549}
550
551
552bool
553Checkpoint::find(const string &section, const string &entry, string &value)
554{
555 return db->find(section, entry, value);
556}
557
558
559bool
560Checkpoint::findObj(const string &section, const string &entry,
561 SimObject *&value)
562{
563 string path;
564
565 if (!db->find(section, entry, path))
566 return false;
567
568 value = resolveSimObject(path);
569 return true;
570}
571
572
573bool
574Checkpoint::sectionExists(const string &section)
575{
576 return db->sectionExists(section);
577}