serialize.hh (13567:08896772e474) serialize.hh (13757:79c0e02258d1)
1/*
2 * Copyright (c) 2015, 2018 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 * All rights reserved.
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions are
19 * met: redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer;
21 * redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution;
24 * neither the name of the copyright holders nor the names of its
25 * contributors may be used to endorse or promote products derived from
26 * this software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 *
40 * Authors: Nathan Binkert
41 * Erik Hallnor
42 * Steve Reinhardt
43 * Andreas Sandberg
44 */
45
46/* @file
47 * Serialization Interface Declarations
48 */
49
50#ifndef __SERIALIZE_HH__
51#define __SERIALIZE_HH__
52
53
54#include <algorithm>
55#include <iostream>
56#include <list>
57#include <map>
58#include <stack>
59#include <set>
60#include <vector>
61
62#include "base/bitunion.hh"
63#include "base/logging.hh"
64#include "base/str.hh"
65
66class IniFile;
67class SimObject;
68class SimObjectResolver;
69
70typedef std::ostream CheckpointOut;
71
72class CheckpointIn
73{
74 private:
75
76 IniFile *db;
77
78 SimObjectResolver &objNameResolver;
79
80 public:
81 CheckpointIn(const std::string &cpt_dir, SimObjectResolver &resolver);
82 ~CheckpointIn();
83
84 const std::string cptDir;
85
86 bool find(const std::string &section, const std::string &entry,
87 std::string &value);
88
89 bool findObj(const std::string &section, const std::string &entry,
90 SimObject *&value);
91
92
93 bool entryExists(const std::string &section, const std::string &entry);
94 bool sectionExists(const std::string &section);
95
96 // The following static functions have to do with checkpoint
97 // creation rather than restoration. This class makes a handy
98 // namespace for them though. Currently no Checkpoint object is
99 // created on serialization (only unserialization) so we track the
100 // directory name as a global. It would be nice to change this
101 // someday
102
103 private:
104 // current directory we're serializing into.
105 static std::string currentDirectory;
106
107 public:
108 // Set the current directory. This function takes care of
109 // inserting curTick() if there's a '%d' in the argument, and
110 // appends a '/' if necessary. The final name is returned.
111 static std::string setDir(const std::string &base_name);
112
113 // Export current checkpoint directory name so other objects can
114 // derive filenames from it (e.g., memory). The return value is
115 // guaranteed to end in '/' so filenames can be directly appended.
116 // This function is only valid while a checkpoint is being created.
117 static std::string dir();
118
119 // Filename for base checkpoint file within directory.
120 static const char *baseFilename;
121};
122
123/**
124 * Basic support for object serialization.
125 *
126 * Objects that support serialization should derive from this
127 * class. Such objects can largely be divided into two categories: 1)
128 * True SimObjects (deriving from SimObject), and 2) child objects
129 * (non-SimObjects).
130 *
131 * SimObjects are serialized automatically into their own sections
132 * automatically by the SimObject base class (see
133 * SimObject::serializeAll().
134 *
135 * SimObjects can contain other serializable objects that are not
136 * SimObjects. Much like normal serialized members are not serialized
137 * automatically, these objects will not be serialized automatically
138 * and it is expected that the objects owning such serializable
139 * objects call the required serialization/unserialization methods on
140 * child objects. The preferred method to serialize a child object is
141 * to call serializeSection() on the child, which serializes the
142 * object into a new subsection in the current section. Another option
143 * is to call serialize() directly, which serializes the object into
144 * the current section. The latter is not recommended as it can lead
145 * to naming clashes between objects.
146 *
147 * @note Many objects that support serialization need to be put in a
148 * consistent state when serialization takes place. We refer to the
149 * action of forcing an object into a consistent state as
150 * 'draining'. Objects that need draining inherit from Drainable. See
151 * Drainable for more information.
152 */
153class Serializable
154{
155 protected:
156 /**
157 * Scoped checkpoint section helper class
158 *
159 * This helper class creates a section within a checkpoint without
160 * the need for a separate serializeable object. It is mainly used
161 * within the Serializable class when serializing or unserializing
162 * section (see serializeSection() and unserializeSection()). It
163 * can also be used to maintain backwards compatibility in
164 * existing code that serializes structs that are not inheriting
165 * from Serializable into subsections.
166 *
167 * When the class is instantiated, it appends a name to the active
168 * path in a checkpoint. The old path is later restored when the
169 * instance is destroyed. For example, serializeSection() could be
170 * implemented by instantiating a ScopedCheckpointSection and then
171 * calling serialize() on an object.
172 */
173 class ScopedCheckpointSection {
174 public:
175 template<class CP>
176 ScopedCheckpointSection(CP &cp, const char *name) {
177 pushName(name);
178 nameOut(cp);
179 }
180
181 template<class CP>
182 ScopedCheckpointSection(CP &cp, const std::string &name) {
183 pushName(name.c_str());
184 nameOut(cp);
185 }
186
187 ~ScopedCheckpointSection();
188
189 ScopedCheckpointSection() = delete;
190 ScopedCheckpointSection(const ScopedCheckpointSection &) = delete;
191 ScopedCheckpointSection &operator=(
192 const ScopedCheckpointSection &) = delete;
193 ScopedCheckpointSection &operator=(
194 ScopedCheckpointSection &&) = delete;
195
196 private:
197 void pushName(const char *name);
198 void nameOut(CheckpointOut &cp);
199 void nameOut(CheckpointIn &cp) {};
200 };
201
202 public:
203 Serializable();
204 virtual ~Serializable();
205
206 /**
207 * Serialize an object
208 *
209 * Output an object's state into the current checkpoint section.
210 *
211 * @param cp Checkpoint state
212 */
213 virtual void serialize(CheckpointOut &cp) const = 0;
214
215 /**
216 * Unserialize an object
217 *
218 * Read an object's state from the current checkpoint section.
219 *
220 * @param cp Checkpoint state
221 */
222 virtual void unserialize(CheckpointIn &cp) = 0;
223
224 /**
225 * Serialize an object into a new section
226 *
227 * This method creates a new section in a checkpoint and calls
228 * serialize() to serialize the current object into that
229 * section. The name of the section is appended to the current
230 * checkpoint path.
231 *
232 * @param cp Checkpoint state
233 * @param name Name to append to the active path
234 */
235 void serializeSection(CheckpointOut &cp, const char *name) const;
236
237 void serializeSection(CheckpointOut &cp, const std::string &name) const {
238 serializeSection(cp, name.c_str());
239 }
240
241 /**
242 * Unserialize an a child object
243 *
244 * This method loads a child object from a checkpoint. The object
245 * name is appended to the active path to form a fully qualified
246 * section name and unserialize() is called.
247 *
248 * @param cp Checkpoint state
249 * @param name Name to append to the active path
250 */
251 void unserializeSection(CheckpointIn &cp, const char *name);
252
253 void unserializeSection(CheckpointIn &cp, const std::string &name) {
254 unserializeSection(cp, name.c_str());
255 }
256
257 /** Get the fully-qualified name of the active section */
258 static const std::string &currentSection();
259
260 static int ckptCount;
261 static int ckptMaxCount;
262 static int ckptPrevCount;
263 static void serializeAll(const std::string &cpt_dir);
264 static void unserializeGlobals(CheckpointIn &cp);
265
266 private:
267 static std::stack<std::string> path;
268};
269
270//
271// The base implementations use to_number for parsing and '<<' for
272// displaying, suitable for integer types.
273//
274template <class T>
275bool
276parseParam(const std::string &s, T &value)
277{
278 return to_number(s, value);
279}
280
281template <class T>
282void
283showParam(CheckpointOut &os, const T &value)
284{
285 os << value;
286}
287
288template <class T>
289bool
290parseParam(const std::string &s, BitUnionType<T> &value)
291{
292 // Zero initialize storage to avoid leaking an uninitialized value
293 BitUnionBaseType<T> storage = BitUnionBaseType<T>();
294 auto res = to_number(s, storage);
295 value = storage;
296 return res;
297}
298
299template <class T>
300void
301showParam(CheckpointOut &os, const BitUnionType<T> &value)
302{
303 auto storage = static_cast<BitUnionBaseType<T>>(value);
304
305 // For a BitUnion8, the storage type is an unsigned char.
306 // Since we want to serialize a number we need to cast to
307 // unsigned int
308 os << ((sizeof(storage) == 1) ?
309 static_cast<unsigned int>(storage) : storage);
310}
311
312// Treat 8-bit ints (chars) as ints on output, not as chars
313template <>
314inline void
315showParam(CheckpointOut &os, const char &value)
316{
317 os << (int)value;
318}
319
320template <>
321inline void
322showParam(CheckpointOut &os, const signed char &value)
323{
324 os << (int)value;
325}
326
327template <>
328inline void
329showParam(CheckpointOut &os, const unsigned char &value)
330{
331 os << (unsigned int)value;
332}
333
334template <>
335inline bool
336parseParam(const std::string &s, float &value)
337{
338 return to_number(s, value);
339}
340
341template <>
342inline bool
343parseParam(const std::string &s, double &value)
344{
345 return to_number(s, value);
346}
347
348template <>
349inline bool
350parseParam(const std::string &s, bool &value)
351{
352 return to_bool(s, value);
353}
354
355// Display bools as strings
356template <>
357inline void
358showParam(CheckpointOut &os, const bool &value)
359{
360 os << (value ? "true" : "false");
361}
362
363// String requires no processing to speak of
364template <>
365inline bool
366parseParam(const std::string &s, std::string &value)
367{
368 value = s;
369 return true;
370}
371
372template <class T>
373void
374paramOut(CheckpointOut &os, const std::string &name, const T &param)
375{
376 os << name << "=";
377 showParam(os, param);
378 os << "\n";
379}
380
381template <class T>
382void
383paramIn(CheckpointIn &cp, const std::string &name, T &param)
384{
385 const std::string &section(Serializable::currentSection());
386 std::string str;
387 if (!cp.find(section, name, str) || !parseParam(str, param)) {
388 fatal("Can't unserialize '%s:%s'\n", section, name);
389 }
390}
391
392template <class T>
393bool
394optParamIn(CheckpointIn &cp, const std::string &name,
395 T &param, bool warn = true)
396{
397 const std::string &section(Serializable::currentSection());
398 std::string str;
399 if (!cp.find(section, name, str) || !parseParam(str, param)) {
400 if (warn)
401 warn("optional parameter %s:%s not present\n", section, name);
402 return false;
403 } else {
404 return true;
405 }
406}
407
408template <class T>
409void
410arrayParamOut(CheckpointOut &os, const std::string &name,
411 const std::vector<T> &param)
412{
413 typename std::vector<T>::size_type size = param.size();
414 os << name << "=";
415 if (size > 0)
416 showParam(os, param[0]);
417 for (typename std::vector<T>::size_type i = 1; i < size; ++i) {
418 os << " ";
419 showParam(os, param[i]);
420 }
421 os << "\n";
422}
423
424template <class T>
425void
426arrayParamOut(CheckpointOut &os, const std::string &name,
427 const std::list<T> &param)
428{
429 typename std::list<T>::const_iterator it = param.begin();
430
431 os << name << "=";
432 if (param.size() > 0)
433 showParam(os, *it);
434 it++;
435 while (it != param.end()) {
436 os << " ";
437 showParam(os, *it);
438 it++;
439 }
440 os << "\n";
441}
442
443template <class T>
444void
445arrayParamOut(CheckpointOut &os, const std::string &name,
446 const std::set<T> &param)
447{
448 typename std::set<T>::const_iterator it = param.begin();
449
450 os << name << "=";
451 if (param.size() > 0)
452 showParam(os, *it);
453 it++;
454 while (it != param.end()) {
455 os << " ";
456 showParam(os, *it);
457 it++;
458 }
459 os << "\n";
460}
461
462template <class T>
463void
464arrayParamOut(CheckpointOut &os, const std::string &name,
465 const T *param, unsigned size)
466{
467 os << name << "=";
468 if (size > 0)
469 showParam(os, param[0]);
470 for (unsigned i = 1; i < size; ++i) {
471 os << " ";
472 showParam(os, param[i]);
473 }
474 os << "\n";
475}
476
1/*
2 * Copyright (c) 2015, 2018 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 * All rights reserved.
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions are
19 * met: redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer;
21 * redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution;
24 * neither the name of the copyright holders nor the names of its
25 * contributors may be used to endorse or promote products derived from
26 * this software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 *
40 * Authors: Nathan Binkert
41 * Erik Hallnor
42 * Steve Reinhardt
43 * Andreas Sandberg
44 */
45
46/* @file
47 * Serialization Interface Declarations
48 */
49
50#ifndef __SERIALIZE_HH__
51#define __SERIALIZE_HH__
52
53
54#include <algorithm>
55#include <iostream>
56#include <list>
57#include <map>
58#include <stack>
59#include <set>
60#include <vector>
61
62#include "base/bitunion.hh"
63#include "base/logging.hh"
64#include "base/str.hh"
65
66class IniFile;
67class SimObject;
68class SimObjectResolver;
69
70typedef std::ostream CheckpointOut;
71
72class CheckpointIn
73{
74 private:
75
76 IniFile *db;
77
78 SimObjectResolver &objNameResolver;
79
80 public:
81 CheckpointIn(const std::string &cpt_dir, SimObjectResolver &resolver);
82 ~CheckpointIn();
83
84 const std::string cptDir;
85
86 bool find(const std::string &section, const std::string &entry,
87 std::string &value);
88
89 bool findObj(const std::string &section, const std::string &entry,
90 SimObject *&value);
91
92
93 bool entryExists(const std::string &section, const std::string &entry);
94 bool sectionExists(const std::string &section);
95
96 // The following static functions have to do with checkpoint
97 // creation rather than restoration. This class makes a handy
98 // namespace for them though. Currently no Checkpoint object is
99 // created on serialization (only unserialization) so we track the
100 // directory name as a global. It would be nice to change this
101 // someday
102
103 private:
104 // current directory we're serializing into.
105 static std::string currentDirectory;
106
107 public:
108 // Set the current directory. This function takes care of
109 // inserting curTick() if there's a '%d' in the argument, and
110 // appends a '/' if necessary. The final name is returned.
111 static std::string setDir(const std::string &base_name);
112
113 // Export current checkpoint directory name so other objects can
114 // derive filenames from it (e.g., memory). The return value is
115 // guaranteed to end in '/' so filenames can be directly appended.
116 // This function is only valid while a checkpoint is being created.
117 static std::string dir();
118
119 // Filename for base checkpoint file within directory.
120 static const char *baseFilename;
121};
122
123/**
124 * Basic support for object serialization.
125 *
126 * Objects that support serialization should derive from this
127 * class. Such objects can largely be divided into two categories: 1)
128 * True SimObjects (deriving from SimObject), and 2) child objects
129 * (non-SimObjects).
130 *
131 * SimObjects are serialized automatically into their own sections
132 * automatically by the SimObject base class (see
133 * SimObject::serializeAll().
134 *
135 * SimObjects can contain other serializable objects that are not
136 * SimObjects. Much like normal serialized members are not serialized
137 * automatically, these objects will not be serialized automatically
138 * and it is expected that the objects owning such serializable
139 * objects call the required serialization/unserialization methods on
140 * child objects. The preferred method to serialize a child object is
141 * to call serializeSection() on the child, which serializes the
142 * object into a new subsection in the current section. Another option
143 * is to call serialize() directly, which serializes the object into
144 * the current section. The latter is not recommended as it can lead
145 * to naming clashes between objects.
146 *
147 * @note Many objects that support serialization need to be put in a
148 * consistent state when serialization takes place. We refer to the
149 * action of forcing an object into a consistent state as
150 * 'draining'. Objects that need draining inherit from Drainable. See
151 * Drainable for more information.
152 */
153class Serializable
154{
155 protected:
156 /**
157 * Scoped checkpoint section helper class
158 *
159 * This helper class creates a section within a checkpoint without
160 * the need for a separate serializeable object. It is mainly used
161 * within the Serializable class when serializing or unserializing
162 * section (see serializeSection() and unserializeSection()). It
163 * can also be used to maintain backwards compatibility in
164 * existing code that serializes structs that are not inheriting
165 * from Serializable into subsections.
166 *
167 * When the class is instantiated, it appends a name to the active
168 * path in a checkpoint. The old path is later restored when the
169 * instance is destroyed. For example, serializeSection() could be
170 * implemented by instantiating a ScopedCheckpointSection and then
171 * calling serialize() on an object.
172 */
173 class ScopedCheckpointSection {
174 public:
175 template<class CP>
176 ScopedCheckpointSection(CP &cp, const char *name) {
177 pushName(name);
178 nameOut(cp);
179 }
180
181 template<class CP>
182 ScopedCheckpointSection(CP &cp, const std::string &name) {
183 pushName(name.c_str());
184 nameOut(cp);
185 }
186
187 ~ScopedCheckpointSection();
188
189 ScopedCheckpointSection() = delete;
190 ScopedCheckpointSection(const ScopedCheckpointSection &) = delete;
191 ScopedCheckpointSection &operator=(
192 const ScopedCheckpointSection &) = delete;
193 ScopedCheckpointSection &operator=(
194 ScopedCheckpointSection &&) = delete;
195
196 private:
197 void pushName(const char *name);
198 void nameOut(CheckpointOut &cp);
199 void nameOut(CheckpointIn &cp) {};
200 };
201
202 public:
203 Serializable();
204 virtual ~Serializable();
205
206 /**
207 * Serialize an object
208 *
209 * Output an object's state into the current checkpoint section.
210 *
211 * @param cp Checkpoint state
212 */
213 virtual void serialize(CheckpointOut &cp) const = 0;
214
215 /**
216 * Unserialize an object
217 *
218 * Read an object's state from the current checkpoint section.
219 *
220 * @param cp Checkpoint state
221 */
222 virtual void unserialize(CheckpointIn &cp) = 0;
223
224 /**
225 * Serialize an object into a new section
226 *
227 * This method creates a new section in a checkpoint and calls
228 * serialize() to serialize the current object into that
229 * section. The name of the section is appended to the current
230 * checkpoint path.
231 *
232 * @param cp Checkpoint state
233 * @param name Name to append to the active path
234 */
235 void serializeSection(CheckpointOut &cp, const char *name) const;
236
237 void serializeSection(CheckpointOut &cp, const std::string &name) const {
238 serializeSection(cp, name.c_str());
239 }
240
241 /**
242 * Unserialize an a child object
243 *
244 * This method loads a child object from a checkpoint. The object
245 * name is appended to the active path to form a fully qualified
246 * section name and unserialize() is called.
247 *
248 * @param cp Checkpoint state
249 * @param name Name to append to the active path
250 */
251 void unserializeSection(CheckpointIn &cp, const char *name);
252
253 void unserializeSection(CheckpointIn &cp, const std::string &name) {
254 unserializeSection(cp, name.c_str());
255 }
256
257 /** Get the fully-qualified name of the active section */
258 static const std::string &currentSection();
259
260 static int ckptCount;
261 static int ckptMaxCount;
262 static int ckptPrevCount;
263 static void serializeAll(const std::string &cpt_dir);
264 static void unserializeGlobals(CheckpointIn &cp);
265
266 private:
267 static std::stack<std::string> path;
268};
269
270//
271// The base implementations use to_number for parsing and '<<' for
272// displaying, suitable for integer types.
273//
274template <class T>
275bool
276parseParam(const std::string &s, T &value)
277{
278 return to_number(s, value);
279}
280
281template <class T>
282void
283showParam(CheckpointOut &os, const T &value)
284{
285 os << value;
286}
287
288template <class T>
289bool
290parseParam(const std::string &s, BitUnionType<T> &value)
291{
292 // Zero initialize storage to avoid leaking an uninitialized value
293 BitUnionBaseType<T> storage = BitUnionBaseType<T>();
294 auto res = to_number(s, storage);
295 value = storage;
296 return res;
297}
298
299template <class T>
300void
301showParam(CheckpointOut &os, const BitUnionType<T> &value)
302{
303 auto storage = static_cast<BitUnionBaseType<T>>(value);
304
305 // For a BitUnion8, the storage type is an unsigned char.
306 // Since we want to serialize a number we need to cast to
307 // unsigned int
308 os << ((sizeof(storage) == 1) ?
309 static_cast<unsigned int>(storage) : storage);
310}
311
312// Treat 8-bit ints (chars) as ints on output, not as chars
313template <>
314inline void
315showParam(CheckpointOut &os, const char &value)
316{
317 os << (int)value;
318}
319
320template <>
321inline void
322showParam(CheckpointOut &os, const signed char &value)
323{
324 os << (int)value;
325}
326
327template <>
328inline void
329showParam(CheckpointOut &os, const unsigned char &value)
330{
331 os << (unsigned int)value;
332}
333
334template <>
335inline bool
336parseParam(const std::string &s, float &value)
337{
338 return to_number(s, value);
339}
340
341template <>
342inline bool
343parseParam(const std::string &s, double &value)
344{
345 return to_number(s, value);
346}
347
348template <>
349inline bool
350parseParam(const std::string &s, bool &value)
351{
352 return to_bool(s, value);
353}
354
355// Display bools as strings
356template <>
357inline void
358showParam(CheckpointOut &os, const bool &value)
359{
360 os << (value ? "true" : "false");
361}
362
363// String requires no processing to speak of
364template <>
365inline bool
366parseParam(const std::string &s, std::string &value)
367{
368 value = s;
369 return true;
370}
371
372template <class T>
373void
374paramOut(CheckpointOut &os, const std::string &name, const T &param)
375{
376 os << name << "=";
377 showParam(os, param);
378 os << "\n";
379}
380
381template <class T>
382void
383paramIn(CheckpointIn &cp, const std::string &name, T &param)
384{
385 const std::string &section(Serializable::currentSection());
386 std::string str;
387 if (!cp.find(section, name, str) || !parseParam(str, param)) {
388 fatal("Can't unserialize '%s:%s'\n", section, name);
389 }
390}
391
392template <class T>
393bool
394optParamIn(CheckpointIn &cp, const std::string &name,
395 T &param, bool warn = true)
396{
397 const std::string &section(Serializable::currentSection());
398 std::string str;
399 if (!cp.find(section, name, str) || !parseParam(str, param)) {
400 if (warn)
401 warn("optional parameter %s:%s not present\n", section, name);
402 return false;
403 } else {
404 return true;
405 }
406}
407
408template <class T>
409void
410arrayParamOut(CheckpointOut &os, const std::string &name,
411 const std::vector<T> &param)
412{
413 typename std::vector<T>::size_type size = param.size();
414 os << name << "=";
415 if (size > 0)
416 showParam(os, param[0]);
417 for (typename std::vector<T>::size_type i = 1; i < size; ++i) {
418 os << " ";
419 showParam(os, param[i]);
420 }
421 os << "\n";
422}
423
424template <class T>
425void
426arrayParamOut(CheckpointOut &os, const std::string &name,
427 const std::list<T> &param)
428{
429 typename std::list<T>::const_iterator it = param.begin();
430
431 os << name << "=";
432 if (param.size() > 0)
433 showParam(os, *it);
434 it++;
435 while (it != param.end()) {
436 os << " ";
437 showParam(os, *it);
438 it++;
439 }
440 os << "\n";
441}
442
443template <class T>
444void
445arrayParamOut(CheckpointOut &os, const std::string &name,
446 const std::set<T> &param)
447{
448 typename std::set<T>::const_iterator it = param.begin();
449
450 os << name << "=";
451 if (param.size() > 0)
452 showParam(os, *it);
453 it++;
454 while (it != param.end()) {
455 os << " ";
456 showParam(os, *it);
457 it++;
458 }
459 os << "\n";
460}
461
462template <class T>
463void
464arrayParamOut(CheckpointOut &os, const std::string &name,
465 const T *param, unsigned size)
466{
467 os << name << "=";
468 if (size > 0)
469 showParam(os, param[0]);
470 for (unsigned i = 1; i < size; ++i) {
471 os << " ";
472 showParam(os, param[i]);
473 }
474 os << "\n";
475}
476
477
477/**
478 * Extract values stored in the checkpoint, and assign them to the provided
479 * array container.
480 *
481 * @param cp The checkpoint to be parsed.
482 * @param name Name of the container.
483 * @param param The array container.
484 * @param size The expected number of entries to be extracted.
485 */
478template <class T>
479void
480arrayParamIn(CheckpointIn &cp, const std::string &name,
481 T *param, unsigned size)
482{
483 const std::string &section(Serializable::currentSection());
484 std::string str;
485 if (!cp.find(section, name, str)) {
486 fatal("Can't unserialize '%s:%s'\n", section, name);
487 }
488
489 // code below stolen from VectorParam<T>::parse().
490 // it would be nice to unify these somehow...
491
492 std::vector<std::string> tokens;
493
494 tokenize(tokens, str, ' ');
495
496 // Need this if we were doing a vector
497 // value.resize(tokens.size());
498
486template <class T>
487void
488arrayParamIn(CheckpointIn &cp, const std::string &name,
489 T *param, unsigned size)
490{
491 const std::string &section(Serializable::currentSection());
492 std::string str;
493 if (!cp.find(section, name, str)) {
494 fatal("Can't unserialize '%s:%s'\n", section, name);
495 }
496
497 // code below stolen from VectorParam<T>::parse().
498 // it would be nice to unify these somehow...
499
500 std::vector<std::string> tokens;
501
502 tokenize(tokens, str, ' ');
503
504 // Need this if we were doing a vector
505 // value.resize(tokens.size());
506
499 if (tokens.size() != size) {
500 fatal("Array size mismatch on %s:%s'\n", section, name);
501 }
507 fatal_if(tokens.size() != size,
508 "Array size mismatch on %s:%s (Got %u, expected %u)'\n",
509 section, name, tokens.size(), size);
502
503 for (std::vector<std::string>::size_type i = 0; i < tokens.size(); i++) {
504 // need to parse into local variable to handle vector<bool>,
505 // for which operator[] returns a special reference class
506 // that's not the same as 'bool&', (since it's a packed
507 // vector)
508 T scalar_value;
509 if (!parseParam(tokens[i], scalar_value)) {
510 std::string err("could not parse \"");
511
512 err += str;
513 err += "\"";
514
515 fatal(err);
516 }
517
518 // assign parsed value to vector
519 param[i] = scalar_value;
520 }
521}
522
523template <class T>
524void
525arrayParamIn(CheckpointIn &cp, const std::string &name, std::vector<T> &param)
526{
527 const std::string &section(Serializable::currentSection());
528 std::string str;
529 if (!cp.find(section, name, str)) {
530 fatal("Can't unserialize '%s:%s'\n", section, name);
531 }
532
533 // code below stolen from VectorParam<T>::parse().
534 // it would be nice to unify these somehow...
535
536 std::vector<std::string> tokens;
537
538 tokenize(tokens, str, ' ');
539
540 // Need this if we were doing a vector
541 // value.resize(tokens.size());
542
543 param.resize(tokens.size());
544
545 for (std::vector<std::string>::size_type i = 0; i < tokens.size(); i++) {
546 // need to parse into local variable to handle vector<bool>,
547 // for which operator[] returns a special reference class
548 // that's not the same as 'bool&', (since it's a packed
549 // vector)
550 T scalar_value;
551 if (!parseParam(tokens[i], scalar_value)) {
552 std::string err("could not parse \"");
553
554 err += str;
555 err += "\"";
556
557 fatal(err);
558 }
559
560 // assign parsed value to vector
561 param[i] = scalar_value;
562 }
563}
564
565template <class T>
566void
567arrayParamIn(CheckpointIn &cp, const std::string &name, std::list<T> &param)
568{
569 const std::string &section(Serializable::currentSection());
570 std::string str;
571 if (!cp.find(section, name, str)) {
572 fatal("Can't unserialize '%s:%s'\n", section, name);
573 }
574 param.clear();
575
576 std::vector<std::string> tokens;
577 tokenize(tokens, str, ' ');
578
579 for (std::vector<std::string>::size_type i = 0; i < tokens.size(); i++) {
580 T scalar_value;
581 if (!parseParam(tokens[i], scalar_value)) {
582 std::string err("could not parse \"");
583
584 err += str;
585 err += "\"";
586
587 fatal(err);
588 }
589
590 // assign parsed value to vector
591 param.push_back(scalar_value);
592 }
593}
594
595template <class T>
596void
597arrayParamIn(CheckpointIn &cp, const std::string &name, std::set<T> &param)
598{
599 const std::string &section(Serializable::currentSection());
600 std::string str;
601 if (!cp.find(section, name, str)) {
602 fatal("Can't unserialize '%s:%s'\n", section, name);
603 }
604 param.clear();
605
606 std::vector<std::string> tokens;
607 tokenize(tokens, str, ' ');
608
609 for (std::vector<std::string>::size_type i = 0; i < tokens.size(); i++) {
610 T scalar_value;
611 if (!parseParam(tokens[i], scalar_value)) {
612 std::string err("could not parse \"");
613
614 err += str;
615 err += "\"";
616
617 fatal(err);
618 }
619
620 // assign parsed value to vector
621 param.insert(scalar_value);
622 }
623}
624
625void
626debug_serialize(const std::string &cpt_dir);
627
628void
629objParamIn(CheckpointIn &cp, const std::string &name, SimObject * &param);
630
631//
632// These macros are streamlined to use in serialize/unserialize
633// functions. It's assumed that serialize() has a parameter 'os' for
634// the ostream, and unserialize() has parameters 'cp' and 'section'.
635#define SERIALIZE_SCALAR(scalar) paramOut(cp, #scalar, scalar)
636
637#define UNSERIALIZE_SCALAR(scalar) paramIn(cp, #scalar, scalar)
638#define UNSERIALIZE_OPT_SCALAR(scalar) optParamIn(cp, #scalar, scalar)
639
640// ENUMs are like SCALARs, but we cast them to ints on the way out
641#define SERIALIZE_ENUM(scalar) paramOut(cp, #scalar, (int)scalar)
642
643#define UNSERIALIZE_ENUM(scalar) \
644 do { \
645 int tmp; \
646 paramIn(cp, #scalar, tmp); \
647 scalar = static_cast<decltype(scalar)>(tmp); \
648 } while (0)
649
650#define SERIALIZE_ARRAY(member, size) \
651 arrayParamOut(cp, #member, member, size)
652
653#define UNSERIALIZE_ARRAY(member, size) \
654 arrayParamIn(cp, #member, member, size)
655
656#define SERIALIZE_CONTAINER(member) \
657 arrayParamOut(cp, #member, member)
658
659#define UNSERIALIZE_CONTAINER(member) \
660 arrayParamIn(cp, #member, member)
661
662#define SERIALIZE_EVENT(event) event.serializeSection(cp, #event);
663
664#define UNSERIALIZE_EVENT(event) \
665 do { \
666 event.unserializeSection(cp, #event); \
667 eventQueue()->checkpointReschedule(&event); \
668 } while (0)
669
670#define SERIALIZE_OBJ(obj) obj.serializeSection(cp, #obj)
671#define UNSERIALIZE_OBJ(obj) obj.unserializeSection(cp, #obj)
672
673#define SERIALIZE_OBJPTR(objptr) paramOut(cp, #objptr, (objptr)->name())
674
675#define UNSERIALIZE_OBJPTR(objptr) \
676 do { \
677 SimObject *sptr; \
678 objParamIn(cp, #objptr, sptr); \
679 objptr = dynamic_cast<decltype(objptr)>(sptr); \
680 } while (0)
681
682#endif // __SERIALIZE_HH__
510
511 for (std::vector<std::string>::size_type i = 0; i < tokens.size(); i++) {
512 // need to parse into local variable to handle vector<bool>,
513 // for which operator[] returns a special reference class
514 // that's not the same as 'bool&', (since it's a packed
515 // vector)
516 T scalar_value;
517 if (!parseParam(tokens[i], scalar_value)) {
518 std::string err("could not parse \"");
519
520 err += str;
521 err += "\"";
522
523 fatal(err);
524 }
525
526 // assign parsed value to vector
527 param[i] = scalar_value;
528 }
529}
530
531template <class T>
532void
533arrayParamIn(CheckpointIn &cp, const std::string &name, std::vector<T> &param)
534{
535 const std::string &section(Serializable::currentSection());
536 std::string str;
537 if (!cp.find(section, name, str)) {
538 fatal("Can't unserialize '%s:%s'\n", section, name);
539 }
540
541 // code below stolen from VectorParam<T>::parse().
542 // it would be nice to unify these somehow...
543
544 std::vector<std::string> tokens;
545
546 tokenize(tokens, str, ' ');
547
548 // Need this if we were doing a vector
549 // value.resize(tokens.size());
550
551 param.resize(tokens.size());
552
553 for (std::vector<std::string>::size_type i = 0; i < tokens.size(); i++) {
554 // need to parse into local variable to handle vector<bool>,
555 // for which operator[] returns a special reference class
556 // that's not the same as 'bool&', (since it's a packed
557 // vector)
558 T scalar_value;
559 if (!parseParam(tokens[i], scalar_value)) {
560 std::string err("could not parse \"");
561
562 err += str;
563 err += "\"";
564
565 fatal(err);
566 }
567
568 // assign parsed value to vector
569 param[i] = scalar_value;
570 }
571}
572
573template <class T>
574void
575arrayParamIn(CheckpointIn &cp, const std::string &name, std::list<T> &param)
576{
577 const std::string &section(Serializable::currentSection());
578 std::string str;
579 if (!cp.find(section, name, str)) {
580 fatal("Can't unserialize '%s:%s'\n", section, name);
581 }
582 param.clear();
583
584 std::vector<std::string> tokens;
585 tokenize(tokens, str, ' ');
586
587 for (std::vector<std::string>::size_type i = 0; i < tokens.size(); i++) {
588 T scalar_value;
589 if (!parseParam(tokens[i], scalar_value)) {
590 std::string err("could not parse \"");
591
592 err += str;
593 err += "\"";
594
595 fatal(err);
596 }
597
598 // assign parsed value to vector
599 param.push_back(scalar_value);
600 }
601}
602
603template <class T>
604void
605arrayParamIn(CheckpointIn &cp, const std::string &name, std::set<T> &param)
606{
607 const std::string &section(Serializable::currentSection());
608 std::string str;
609 if (!cp.find(section, name, str)) {
610 fatal("Can't unserialize '%s:%s'\n", section, name);
611 }
612 param.clear();
613
614 std::vector<std::string> tokens;
615 tokenize(tokens, str, ' ');
616
617 for (std::vector<std::string>::size_type i = 0; i < tokens.size(); i++) {
618 T scalar_value;
619 if (!parseParam(tokens[i], scalar_value)) {
620 std::string err("could not parse \"");
621
622 err += str;
623 err += "\"";
624
625 fatal(err);
626 }
627
628 // assign parsed value to vector
629 param.insert(scalar_value);
630 }
631}
632
633void
634debug_serialize(const std::string &cpt_dir);
635
636void
637objParamIn(CheckpointIn &cp, const std::string &name, SimObject * &param);
638
639//
640// These macros are streamlined to use in serialize/unserialize
641// functions. It's assumed that serialize() has a parameter 'os' for
642// the ostream, and unserialize() has parameters 'cp' and 'section'.
643#define SERIALIZE_SCALAR(scalar) paramOut(cp, #scalar, scalar)
644
645#define UNSERIALIZE_SCALAR(scalar) paramIn(cp, #scalar, scalar)
646#define UNSERIALIZE_OPT_SCALAR(scalar) optParamIn(cp, #scalar, scalar)
647
648// ENUMs are like SCALARs, but we cast them to ints on the way out
649#define SERIALIZE_ENUM(scalar) paramOut(cp, #scalar, (int)scalar)
650
651#define UNSERIALIZE_ENUM(scalar) \
652 do { \
653 int tmp; \
654 paramIn(cp, #scalar, tmp); \
655 scalar = static_cast<decltype(scalar)>(tmp); \
656 } while (0)
657
658#define SERIALIZE_ARRAY(member, size) \
659 arrayParamOut(cp, #member, member, size)
660
661#define UNSERIALIZE_ARRAY(member, size) \
662 arrayParamIn(cp, #member, member, size)
663
664#define SERIALIZE_CONTAINER(member) \
665 arrayParamOut(cp, #member, member)
666
667#define UNSERIALIZE_CONTAINER(member) \
668 arrayParamIn(cp, #member, member)
669
670#define SERIALIZE_EVENT(event) event.serializeSection(cp, #event);
671
672#define UNSERIALIZE_EVENT(event) \
673 do { \
674 event.unserializeSection(cp, #event); \
675 eventQueue()->checkpointReschedule(&event); \
676 } while (0)
677
678#define SERIALIZE_OBJ(obj) obj.serializeSection(cp, #obj)
679#define UNSERIALIZE_OBJ(obj) obj.unserializeSection(cp, #obj)
680
681#define SERIALIZE_OBJPTR(objptr) paramOut(cp, #objptr, (objptr)->name())
682
683#define UNSERIALIZE_OBJPTR(objptr) \
684 do { \
685 SimObject *sptr; \
686 objParamIn(cp, #objptr, sptr); \
687 objptr = dynamic_cast<decltype(objptr)>(sptr); \
688 } while (0)
689
690#endif // __SERIALIZE_HH__