serialize.hh revision 13567
112854Sgabeblack@google.com/*
212854Sgabeblack@google.com * Copyright (c) 2015, 2018 ARM Limited
312854Sgabeblack@google.com * All rights reserved
412854Sgabeblack@google.com *
512854Sgabeblack@google.com * The license below extends only to copyright in the software and shall
612854Sgabeblack@google.com * not be construed as granting a license to any other intellectual
712854Sgabeblack@google.com * property including but not limited to intellectual property relating
812854Sgabeblack@google.com * to a hardware implementation of the functionality of the software
912854Sgabeblack@google.com * licensed hereunder.  You may use the software subject to the license
1012854Sgabeblack@google.com * terms below provided that you ensure that this notice is replicated
1112854Sgabeblack@google.com * unmodified and in its entirety in all distributions of the software,
1212854Sgabeblack@google.com * modified or unmodified, in source code or in binary form.
1312854Sgabeblack@google.com *
1412854Sgabeblack@google.com * Copyright (c) 2002-2005 The Regents of The University of Michigan
1512854Sgabeblack@google.com * All rights reserved.
1612854Sgabeblack@google.com *
1712854Sgabeblack@google.com * Redistribution and use in source and binary forms, with or without
1812854Sgabeblack@google.com * modification, are permitted provided that the following conditions are
1912854Sgabeblack@google.com * met: redistributions of source code must retain the above copyright
2012854Sgabeblack@google.com * notice, this list of conditions and the following disclaimer;
2112854Sgabeblack@google.com * redistributions in binary form must reproduce the above copyright
2212854Sgabeblack@google.com * notice, this list of conditions and the following disclaimer in the
2312854Sgabeblack@google.com * documentation and/or other materials provided with the distribution;
2412854Sgabeblack@google.com * neither the name of the copyright holders nor the names of its
2512854Sgabeblack@google.com * contributors may be used to endorse or promote products derived from
2612854Sgabeblack@google.com * this software without specific prior written permission.
2712854Sgabeblack@google.com *
2812854Sgabeblack@google.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2912854Sgabeblack@google.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3012854Sgabeblack@google.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
3112854Sgabeblack@google.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3212854Sgabeblack@google.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3312854Sgabeblack@google.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3412854Sgabeblack@google.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3512854Sgabeblack@google.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3612854Sgabeblack@google.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3712854Sgabeblack@google.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3812854Sgabeblack@google.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3912854Sgabeblack@google.com *
4012854Sgabeblack@google.com * Authors: Nathan Binkert
4112854Sgabeblack@google.com *          Erik Hallnor
4212854Sgabeblack@google.com *          Steve Reinhardt
4312854Sgabeblack@google.com *          Andreas Sandberg
4412854Sgabeblack@google.com */
4512854Sgabeblack@google.com
4612854Sgabeblack@google.com/* @file
4712854Sgabeblack@google.com * Serialization Interface Declarations
4812854Sgabeblack@google.com */
4912854Sgabeblack@google.com
5012854Sgabeblack@google.com#ifndef __SERIALIZE_HH__
5112854Sgabeblack@google.com#define __SERIALIZE_HH__
5212854Sgabeblack@google.com
5312854Sgabeblack@google.com
5412854Sgabeblack@google.com#include <algorithm>
5512854Sgabeblack@google.com#include <iostream>
5612854Sgabeblack@google.com#include <list>
5712854Sgabeblack@google.com#include <map>
5812854Sgabeblack@google.com#include <stack>
5912854Sgabeblack@google.com#include <set>
6012854Sgabeblack@google.com#include <vector>
6112854Sgabeblack@google.com
6212854Sgabeblack@google.com#include "base/bitunion.hh"
6312854Sgabeblack@google.com#include "base/logging.hh"
6412854Sgabeblack@google.com#include "base/str.hh"
6512854Sgabeblack@google.com
6612854Sgabeblack@google.comclass IniFile;
6712854Sgabeblack@google.comclass SimObject;
6812854Sgabeblack@google.comclass SimObjectResolver;
6912854Sgabeblack@google.com
7012854Sgabeblack@google.comtypedef std::ostream CheckpointOut;
7112854Sgabeblack@google.com
7212854Sgabeblack@google.comclass CheckpointIn
7312854Sgabeblack@google.com{
7412854Sgabeblack@google.com  private:
7512854Sgabeblack@google.com
7612854Sgabeblack@google.com    IniFile *db;
7712854Sgabeblack@google.com
7812854Sgabeblack@google.com    SimObjectResolver &objNameResolver;
7912854Sgabeblack@google.com
8012854Sgabeblack@google.com  public:
8112854Sgabeblack@google.com    CheckpointIn(const std::string &cpt_dir, SimObjectResolver &resolver);
8212854Sgabeblack@google.com    ~CheckpointIn();
8312854Sgabeblack@google.com
8412854Sgabeblack@google.com    const std::string cptDir;
8512854Sgabeblack@google.com
8612854Sgabeblack@google.com    bool find(const std::string &section, const std::string &entry,
8712854Sgabeblack@google.com              std::string &value);
8812854Sgabeblack@google.com
8912854Sgabeblack@google.com    bool findObj(const std::string &section, const std::string &entry,
9012854Sgabeblack@google.com                 SimObject *&value);
9112854Sgabeblack@google.com
9212854Sgabeblack@google.com
9312854Sgabeblack@google.com    bool entryExists(const std::string &section, const std::string &entry);
9412854Sgabeblack@google.com    bool sectionExists(const std::string &section);
9512854Sgabeblack@google.com
9612854Sgabeblack@google.com    // The following static functions have to do with checkpoint
9712854Sgabeblack@google.com    // creation rather than restoration.  This class makes a handy
9812854Sgabeblack@google.com    // namespace for them though.  Currently no Checkpoint object is
9912854Sgabeblack@google.com    // created on serialization (only unserialization) so we track the
10012854Sgabeblack@google.com    // directory name as a global.  It would be nice to change this
10112854Sgabeblack@google.com    // someday
10212854Sgabeblack@google.com
10312854Sgabeblack@google.com  private:
10412854Sgabeblack@google.com    // current directory we're serializing into.
10512854Sgabeblack@google.com    static std::string currentDirectory;
10612854Sgabeblack@google.com
10712854Sgabeblack@google.com  public:
10812854Sgabeblack@google.com    // Set the current directory.  This function takes care of
10912854Sgabeblack@google.com    // inserting curTick() if there's a '%d' in the argument, and
11012854Sgabeblack@google.com    // appends a '/' if necessary.  The final name is returned.
11112854Sgabeblack@google.com    static std::string setDir(const std::string &base_name);
11212854Sgabeblack@google.com
11312854Sgabeblack@google.com    // Export current checkpoint directory name so other objects can
11412854Sgabeblack@google.com    // derive filenames from it (e.g., memory).  The return value is
11512854Sgabeblack@google.com    // guaranteed to end in '/' so filenames can be directly appended.
11612854Sgabeblack@google.com    // This function is only valid while a checkpoint is being created.
11712854Sgabeblack@google.com    static std::string dir();
11812854Sgabeblack@google.com
11912854Sgabeblack@google.com    // Filename for base checkpoint file within directory.
12012854Sgabeblack@google.com    static const char *baseFilename;
12112854Sgabeblack@google.com};
12212854Sgabeblack@google.com
12312854Sgabeblack@google.com/**
12412854Sgabeblack@google.com * Basic support for object serialization.
12512854Sgabeblack@google.com *
12613322Sgabeblack@google.com * Objects that support serialization should derive from this
12712854Sgabeblack@google.com * class. Such objects can largely be divided into two categories: 1)
12812854Sgabeblack@google.com * True SimObjects (deriving from SimObject), and 2) child objects
12912854Sgabeblack@google.com * (non-SimObjects).
13012854Sgabeblack@google.com *
13112854Sgabeblack@google.com * SimObjects are serialized automatically into their own sections
13212854Sgabeblack@google.com * automatically by the SimObject base class (see
13312854Sgabeblack@google.com * SimObject::serializeAll().
13412854Sgabeblack@google.com *
13513160Sgabeblack@google.com * SimObjects can contain other serializable objects that are not
13612854Sgabeblack@google.com * SimObjects. Much like normal serialized members are not serialized
13712854Sgabeblack@google.com * automatically, these objects will not be serialized automatically
13813322Sgabeblack@google.com * and it is expected that the objects owning such serializable
13912854Sgabeblack@google.com * objects call the required serialization/unserialization methods on
14012854Sgabeblack@google.com * child objects. The preferred method to serialize a child object is
14112854Sgabeblack@google.com * to call serializeSection() on the child, which serializes the
14212854Sgabeblack@google.com * object into a new subsection in the current section. Another option
14312854Sgabeblack@google.com * is to call serialize() directly, which serializes the object into
14412854Sgabeblack@google.com * the current section. The latter is not recommended as it can lead
14512854Sgabeblack@google.com * to naming clashes between objects.
14612854Sgabeblack@google.com *
14712854Sgabeblack@google.com * @note Many objects that support serialization need to be put in a
14812854Sgabeblack@google.com * consistent state when serialization takes place. We refer to the
14912854Sgabeblack@google.com * action of forcing an object into a consistent state as
15012854Sgabeblack@google.com * 'draining'. Objects that need draining inherit from Drainable. See
15112854Sgabeblack@google.com * Drainable for more information.
15212854Sgabeblack@google.com */
15312854Sgabeblack@google.comclass Serializable
15412854Sgabeblack@google.com{
15512854Sgabeblack@google.com  protected:
15612854Sgabeblack@google.com    /**
15712854Sgabeblack@google.com     * Scoped checkpoint section helper class
15812854Sgabeblack@google.com     *
15912854Sgabeblack@google.com     * This helper class creates a section within a checkpoint without
16012854Sgabeblack@google.com     * the need for a separate serializeable object. It is mainly used
16112854Sgabeblack@google.com     * within the Serializable class when serializing or unserializing
16212854Sgabeblack@google.com     * section (see serializeSection() and unserializeSection()). It
16312854Sgabeblack@google.com     * can also be used to maintain backwards compatibility in
16412854Sgabeblack@google.com     * existing code that serializes structs that are not inheriting
16512854Sgabeblack@google.com     * from Serializable into subsections.
16612854Sgabeblack@google.com     *
16712854Sgabeblack@google.com     * When the class is instantiated, it appends a name to the active
16812854Sgabeblack@google.com     * path in a checkpoint. The old path is later restored when the
16912854Sgabeblack@google.com     * instance is destroyed. For example, serializeSection() could be
17012854Sgabeblack@google.com     * implemented by instantiating a ScopedCheckpointSection and then
17112854Sgabeblack@google.com     * calling serialize() on an object.
17212854Sgabeblack@google.com     */
17312854Sgabeblack@google.com    class ScopedCheckpointSection {
17412854Sgabeblack@google.com      public:
17512854Sgabeblack@google.com        template<class CP>
17612854Sgabeblack@google.com        ScopedCheckpointSection(CP &cp, const char *name) {
17712854Sgabeblack@google.com            pushName(name);
17812854Sgabeblack@google.com            nameOut(cp);
17912854Sgabeblack@google.com        }
18012854Sgabeblack@google.com
18112854Sgabeblack@google.com        template<class CP>
18212854Sgabeblack@google.com        ScopedCheckpointSection(CP &cp, const std::string &name) {
18312854Sgabeblack@google.com            pushName(name.c_str());
18412854Sgabeblack@google.com            nameOut(cp);
18512854Sgabeblack@google.com        }
18612854Sgabeblack@google.com
18712854Sgabeblack@google.com        ~ScopedCheckpointSection();
18812854Sgabeblack@google.com
18912854Sgabeblack@google.com        ScopedCheckpointSection() = delete;
19012854Sgabeblack@google.com        ScopedCheckpointSection(const ScopedCheckpointSection &) = delete;
19112854Sgabeblack@google.com        ScopedCheckpointSection &operator=(
19212854Sgabeblack@google.com            const ScopedCheckpointSection &) = delete;
19312854Sgabeblack@google.com        ScopedCheckpointSection &operator=(
19412854Sgabeblack@google.com            ScopedCheckpointSection &&) = delete;
19512854Sgabeblack@google.com
19612854Sgabeblack@google.com      private:
19712854Sgabeblack@google.com        void pushName(const char *name);
19812854Sgabeblack@google.com        void nameOut(CheckpointOut &cp);
19912854Sgabeblack@google.com        void nameOut(CheckpointIn &cp) {};
20012854Sgabeblack@google.com    };
20112854Sgabeblack@google.com
20212854Sgabeblack@google.com  public:
20312854Sgabeblack@google.com    Serializable();
20412854Sgabeblack@google.com    virtual ~Serializable();
20512854Sgabeblack@google.com
20612854Sgabeblack@google.com    /**
20712854Sgabeblack@google.com     * Serialize an object
20812854Sgabeblack@google.com     *
20912854Sgabeblack@google.com     * Output an object's state into the current checkpoint section.
21012854Sgabeblack@google.com     *
21112854Sgabeblack@google.com     * @param cp Checkpoint state
21212854Sgabeblack@google.com     */
21312854Sgabeblack@google.com    virtual void serialize(CheckpointOut &cp) const = 0;
21412854Sgabeblack@google.com
21512854Sgabeblack@google.com    /**
21612854Sgabeblack@google.com     * Unserialize an object
21712854Sgabeblack@google.com     *
21812854Sgabeblack@google.com     * Read an object's state from the current checkpoint section.
21912854Sgabeblack@google.com     *
22012854Sgabeblack@google.com     * @param cp Checkpoint state
22112854Sgabeblack@google.com     */
22212854Sgabeblack@google.com    virtual void unserialize(CheckpointIn &cp) = 0;
22312854Sgabeblack@google.com
22412854Sgabeblack@google.com    /**
22512854Sgabeblack@google.com     * Serialize an object into a new section
22612854Sgabeblack@google.com     *
22712854Sgabeblack@google.com     * This method creates a new section in a checkpoint and calls
22812854Sgabeblack@google.com     * serialize() to serialize the current object into that
22912854Sgabeblack@google.com     * section. The name of the section is appended to the current
23012854Sgabeblack@google.com     * checkpoint path.
23112854Sgabeblack@google.com     *
23212854Sgabeblack@google.com     * @param cp Checkpoint state
23312854Sgabeblack@google.com     * @param name Name to append to the active path
23412854Sgabeblack@google.com     */
23512854Sgabeblack@google.com    void serializeSection(CheckpointOut &cp, const char *name) const;
23612854Sgabeblack@google.com
23712854Sgabeblack@google.com    void serializeSection(CheckpointOut &cp, const std::string &name) const {
23812854Sgabeblack@google.com        serializeSection(cp, name.c_str());
23912854Sgabeblack@google.com    }
24012854Sgabeblack@google.com
24112854Sgabeblack@google.com    /**
24212854Sgabeblack@google.com     * Unserialize an a child object
24312854Sgabeblack@google.com     *
24412854Sgabeblack@google.com     * This method loads a child object from a checkpoint. The object
24512854Sgabeblack@google.com     * name is appended to the active path to form a fully qualified
24612854Sgabeblack@google.com     * section name and unserialize() is called.
24712854Sgabeblack@google.com     *
24812854Sgabeblack@google.com     * @param cp Checkpoint state
24912854Sgabeblack@google.com     * @param name Name to append to the active path
25012854Sgabeblack@google.com     */
25112854Sgabeblack@google.com    void unserializeSection(CheckpointIn &cp, const char *name);
25212854Sgabeblack@google.com
25312854Sgabeblack@google.com    void unserializeSection(CheckpointIn &cp, const std::string &name) {
25412854Sgabeblack@google.com        unserializeSection(cp, name.c_str());
25512854Sgabeblack@google.com    }
25612854Sgabeblack@google.com
25712854Sgabeblack@google.com    /** Get the fully-qualified name of the active section */
25812854Sgabeblack@google.com    static const std::string &currentSection();
25912854Sgabeblack@google.com
26012854Sgabeblack@google.com    static int ckptCount;
26112854Sgabeblack@google.com    static int ckptMaxCount;
26212854Sgabeblack@google.com    static int ckptPrevCount;
26312854Sgabeblack@google.com    static void serializeAll(const std::string &cpt_dir);
26412854Sgabeblack@google.com    static void unserializeGlobals(CheckpointIn &cp);
26512854Sgabeblack@google.com
26612854Sgabeblack@google.com  private:
26712854Sgabeblack@google.com    static std::stack<std::string> path;
26812854Sgabeblack@google.com};
26912854Sgabeblack@google.com
27012854Sgabeblack@google.com//
27112854Sgabeblack@google.com// The base implementations use to_number for parsing and '<<' for
27212854Sgabeblack@google.com// displaying, suitable for integer types.
27312854Sgabeblack@google.com//
27412854Sgabeblack@google.comtemplate <class T>
27512854Sgabeblack@google.combool
27612854Sgabeblack@google.comparseParam(const std::string &s, T &value)
27712854Sgabeblack@google.com{
27812854Sgabeblack@google.com    return to_number(s, value);
27912854Sgabeblack@google.com}
28012854Sgabeblack@google.com
28112854Sgabeblack@google.comtemplate <class T>
28212854Sgabeblack@google.comvoid
28312854Sgabeblack@google.comshowParam(CheckpointOut &os, const T &value)
28412854Sgabeblack@google.com{
28512854Sgabeblack@google.com    os << value;
28612854Sgabeblack@google.com}
28712854Sgabeblack@google.com
28812854Sgabeblack@google.comtemplate <class T>
28912854Sgabeblack@google.combool
29012854Sgabeblack@google.comparseParam(const std::string &s, BitUnionType<T> &value)
29112854Sgabeblack@google.com{
29212854Sgabeblack@google.com    // Zero initialize storage to avoid leaking an uninitialized value
29312854Sgabeblack@google.com    BitUnionBaseType<T> storage = BitUnionBaseType<T>();
29412854Sgabeblack@google.com    auto res = to_number(s, storage);
29512854Sgabeblack@google.com    value = storage;
29612854Sgabeblack@google.com    return res;
29712854Sgabeblack@google.com}
29812854Sgabeblack@google.com
29912854Sgabeblack@google.comtemplate <class T>
30012854Sgabeblack@google.comvoid
30112854Sgabeblack@google.comshowParam(CheckpointOut &os, const BitUnionType<T> &value)
30212854Sgabeblack@google.com{
30312854Sgabeblack@google.com    auto storage = static_cast<BitUnionBaseType<T>>(value);
30412854Sgabeblack@google.com
30512854Sgabeblack@google.com    // For a BitUnion8, the storage type is an unsigned char.
30612854Sgabeblack@google.com    // Since we want to serialize a number we need to cast to
30712854Sgabeblack@google.com    // unsigned int
30812854Sgabeblack@google.com    os << ((sizeof(storage) == 1) ?
30912854Sgabeblack@google.com        static_cast<unsigned int>(storage) : storage);
31012854Sgabeblack@google.com}
31112854Sgabeblack@google.com
31212854Sgabeblack@google.com// Treat 8-bit ints (chars) as ints on output, not as chars
31312854Sgabeblack@google.comtemplate <>
31412854Sgabeblack@google.cominline void
31512854Sgabeblack@google.comshowParam(CheckpointOut &os, const char &value)
31612854Sgabeblack@google.com{
31712854Sgabeblack@google.com    os << (int)value;
31812854Sgabeblack@google.com}
31912854Sgabeblack@google.com
32012854Sgabeblack@google.comtemplate <>
32112854Sgabeblack@google.cominline void
32212854Sgabeblack@google.comshowParam(CheckpointOut &os, const signed char &value)
32312854Sgabeblack@google.com{
32412854Sgabeblack@google.com    os << (int)value;
32512854Sgabeblack@google.com}
32612854Sgabeblack@google.com
32712854Sgabeblack@google.comtemplate <>
32812854Sgabeblack@google.cominline void
32912854Sgabeblack@google.comshowParam(CheckpointOut &os, const unsigned char &value)
33012854Sgabeblack@google.com{
33112854Sgabeblack@google.com    os << (unsigned int)value;
33212854Sgabeblack@google.com}
33312854Sgabeblack@google.com
33412854Sgabeblack@google.comtemplate <>
33512854Sgabeblack@google.cominline bool
33612854Sgabeblack@google.comparseParam(const std::string &s, float &value)
33712854Sgabeblack@google.com{
33812854Sgabeblack@google.com    return to_number(s, value);
33912854Sgabeblack@google.com}
34012854Sgabeblack@google.com
34112854Sgabeblack@google.comtemplate <>
34212854Sgabeblack@google.cominline bool
34312854Sgabeblack@google.comparseParam(const std::string &s, double &value)
34412854Sgabeblack@google.com{
34512854Sgabeblack@google.com    return to_number(s, value);
34612854Sgabeblack@google.com}
34712854Sgabeblack@google.com
34812854Sgabeblack@google.comtemplate <>
34912854Sgabeblack@google.cominline bool
35012854Sgabeblack@google.comparseParam(const std::string &s, bool &value)
35112854Sgabeblack@google.com{
35212854Sgabeblack@google.com    return to_bool(s, value);
35312854Sgabeblack@google.com}
35412854Sgabeblack@google.com
35512854Sgabeblack@google.com// Display bools as strings
35612854Sgabeblack@google.comtemplate <>
35712854Sgabeblack@google.cominline void
35812854Sgabeblack@google.comshowParam(CheckpointOut &os, const bool &value)
35912854Sgabeblack@google.com{
36012854Sgabeblack@google.com    os << (value ? "true" : "false");
36112854Sgabeblack@google.com}
36212854Sgabeblack@google.com
36312854Sgabeblack@google.com// String requires no processing to speak of
36412854Sgabeblack@google.comtemplate <>
36512854Sgabeblack@google.cominline bool
36612854Sgabeblack@google.comparseParam(const std::string &s, std::string &value)
36712854Sgabeblack@google.com{
36812854Sgabeblack@google.com    value = s;
36912854Sgabeblack@google.com    return true;
37012854Sgabeblack@google.com}
37112854Sgabeblack@google.com
37212854Sgabeblack@google.comtemplate <class T>
37312854Sgabeblack@google.comvoid
37412854Sgabeblack@google.comparamOut(CheckpointOut &os, const std::string &name, const T &param)
37512854Sgabeblack@google.com{
37612854Sgabeblack@google.com    os << name << "=";
37712854Sgabeblack@google.com    showParam(os, param);
37812854Sgabeblack@google.com    os << "\n";
37912854Sgabeblack@google.com}
38012854Sgabeblack@google.com
38112854Sgabeblack@google.comtemplate <class T>
38212854Sgabeblack@google.comvoid
38312854Sgabeblack@google.comparamIn(CheckpointIn &cp, const std::string &name, T &param)
38412854Sgabeblack@google.com{
38512854Sgabeblack@google.com    const std::string &section(Serializable::currentSection());
38612854Sgabeblack@google.com    std::string str;
38712854Sgabeblack@google.com    if (!cp.find(section, name, str) || !parseParam(str, param)) {
38812854Sgabeblack@google.com        fatal("Can't unserialize '%s:%s'\n", section, name);
38912854Sgabeblack@google.com    }
39012854Sgabeblack@google.com}
39112854Sgabeblack@google.com
39212854Sgabeblack@google.comtemplate <class T>
39312854Sgabeblack@google.combool
39412854Sgabeblack@google.comoptParamIn(CheckpointIn &cp, const std::string &name,
39512854Sgabeblack@google.com           T &param, bool warn = true)
39612854Sgabeblack@google.com{
39712854Sgabeblack@google.com    const std::string &section(Serializable::currentSection());
39812854Sgabeblack@google.com    std::string str;
39912854Sgabeblack@google.com    if (!cp.find(section, name, str) || !parseParam(str, param)) {
40012854Sgabeblack@google.com        if (warn)
40112854Sgabeblack@google.com            warn("optional parameter %s:%s not present\n", section, name);
40212854Sgabeblack@google.com        return false;
40312854Sgabeblack@google.com    } else {
40412854Sgabeblack@google.com        return true;
40512854Sgabeblack@google.com    }
40612854Sgabeblack@google.com}
40712854Sgabeblack@google.com
40812854Sgabeblack@google.comtemplate <class T>
40912854Sgabeblack@google.comvoid
41012854Sgabeblack@google.comarrayParamOut(CheckpointOut &os, const std::string &name,
41112854Sgabeblack@google.com              const std::vector<T> &param)
41212854Sgabeblack@google.com{
41312854Sgabeblack@google.com    typename std::vector<T>::size_type size = param.size();
41412854Sgabeblack@google.com    os << name << "=";
41512854Sgabeblack@google.com    if (size > 0)
41612854Sgabeblack@google.com        showParam(os, param[0]);
41712854Sgabeblack@google.com    for (typename std::vector<T>::size_type i = 1; i < size; ++i) {
41812854Sgabeblack@google.com        os << " ";
41912854Sgabeblack@google.com        showParam(os, param[i]);
42012854Sgabeblack@google.com    }
42112854Sgabeblack@google.com    os << "\n";
42212854Sgabeblack@google.com}
42312854Sgabeblack@google.com
42412854Sgabeblack@google.comtemplate <class T>
42512854Sgabeblack@google.comvoid
42612854Sgabeblack@google.comarrayParamOut(CheckpointOut &os, const std::string &name,
42712854Sgabeblack@google.com              const std::list<T> &param)
42812854Sgabeblack@google.com{
42912854Sgabeblack@google.com    typename std::list<T>::const_iterator it = param.begin();
43012854Sgabeblack@google.com
43112854Sgabeblack@google.com    os << name << "=";
43212854Sgabeblack@google.com    if (param.size() > 0)
43312854Sgabeblack@google.com        showParam(os, *it);
43412854Sgabeblack@google.com    it++;
43512854Sgabeblack@google.com    while (it != param.end()) {
43612854Sgabeblack@google.com        os << " ";
43712854Sgabeblack@google.com        showParam(os, *it);
43812854Sgabeblack@google.com        it++;
43912854Sgabeblack@google.com    }
44012854Sgabeblack@google.com    os << "\n";
44112854Sgabeblack@google.com}
44212854Sgabeblack@google.com
44312854Sgabeblack@google.comtemplate <class T>
44412854Sgabeblack@google.comvoid
44512854Sgabeblack@google.comarrayParamOut(CheckpointOut &os, const std::string &name,
44612854Sgabeblack@google.com              const std::set<T> &param)
44712854Sgabeblack@google.com{
44812854Sgabeblack@google.com    typename std::set<T>::const_iterator it = param.begin();
44912854Sgabeblack@google.com
45012854Sgabeblack@google.com    os << name << "=";
45112854Sgabeblack@google.com    if (param.size() > 0)
45212854Sgabeblack@google.com        showParam(os, *it);
45312854Sgabeblack@google.com    it++;
45412854Sgabeblack@google.com    while (it != param.end()) {
45512854Sgabeblack@google.com        os << " ";
45612854Sgabeblack@google.com        showParam(os, *it);
45712854Sgabeblack@google.com        it++;
45812854Sgabeblack@google.com    }
45912854Sgabeblack@google.com    os << "\n";
46012854Sgabeblack@google.com}
46112854Sgabeblack@google.com
46212854Sgabeblack@google.comtemplate <class T>
46312854Sgabeblack@google.comvoid
46412854Sgabeblack@google.comarrayParamOut(CheckpointOut &os, const std::string &name,
46512854Sgabeblack@google.com              const T *param, unsigned size)
46612854Sgabeblack@google.com{
46712854Sgabeblack@google.com    os << name << "=";
46812854Sgabeblack@google.com    if (size > 0)
46912854Sgabeblack@google.com        showParam(os, param[0]);
47012854Sgabeblack@google.com    for (unsigned i = 1; i < size; ++i) {
47112854Sgabeblack@google.com        os << " ";
47212854Sgabeblack@google.com        showParam(os, param[i]);
47312854Sgabeblack@google.com    }
47412854Sgabeblack@google.com    os << "\n";
47512854Sgabeblack@google.com}
47612854Sgabeblack@google.com
47712854Sgabeblack@google.com
47812854Sgabeblack@google.comtemplate <class T>
47912854Sgabeblack@google.comvoid
48012854Sgabeblack@google.comarrayParamIn(CheckpointIn &cp, const std::string &name,
48112854Sgabeblack@google.com             T *param, unsigned size)
48212854Sgabeblack@google.com{
48312854Sgabeblack@google.com    const std::string &section(Serializable::currentSection());
48412854Sgabeblack@google.com    std::string str;
48512854Sgabeblack@google.com    if (!cp.find(section, name, str)) {
48612854Sgabeblack@google.com        fatal("Can't unserialize '%s:%s'\n", section, name);
48712854Sgabeblack@google.com    }
48812854Sgabeblack@google.com
48912854Sgabeblack@google.com    // code below stolen from VectorParam<T>::parse().
49012854Sgabeblack@google.com    // it would be nice to unify these somehow...
49112854Sgabeblack@google.com
49212854Sgabeblack@google.com    std::vector<std::string> tokens;
49312854Sgabeblack@google.com
49412854Sgabeblack@google.com    tokenize(tokens, str, ' ');
49512854Sgabeblack@google.com
49612854Sgabeblack@google.com    // Need this if we were doing a vector
49712854Sgabeblack@google.com    // value.resize(tokens.size());
49812854Sgabeblack@google.com
49912854Sgabeblack@google.com    if (tokens.size() != size) {
50012854Sgabeblack@google.com        fatal("Array size mismatch on %s:%s'\n", section, name);
50112854Sgabeblack@google.com    }
50212854Sgabeblack@google.com
50312854Sgabeblack@google.com    for (std::vector<std::string>::size_type i = 0; i < tokens.size(); i++) {
50412854Sgabeblack@google.com        // need to parse into local variable to handle vector<bool>,
50512854Sgabeblack@google.com        // for which operator[] returns a special reference class
50612854Sgabeblack@google.com        // that's not the same as 'bool&', (since it's a packed
50712854Sgabeblack@google.com        // vector)
50812854Sgabeblack@google.com        T scalar_value;
50912854Sgabeblack@google.com        if (!parseParam(tokens[i], scalar_value)) {
51012854Sgabeblack@google.com            std::string err("could not parse \"");
51112854Sgabeblack@google.com
51212854Sgabeblack@google.com            err += str;
51312854Sgabeblack@google.com            err += "\"";
51412854Sgabeblack@google.com
51512854Sgabeblack@google.com            fatal(err);
51612854Sgabeblack@google.com        }
51712854Sgabeblack@google.com
51812854Sgabeblack@google.com        // assign parsed value to vector
51912854Sgabeblack@google.com        param[i] = scalar_value;
52012854Sgabeblack@google.com    }
52112854Sgabeblack@google.com}
52212854Sgabeblack@google.com
52312854Sgabeblack@google.comtemplate <class T>
52412854Sgabeblack@google.comvoid
52512854Sgabeblack@google.comarrayParamIn(CheckpointIn &cp, const std::string &name, std::vector<T> &param)
52612854Sgabeblack@google.com{
52712854Sgabeblack@google.com    const std::string &section(Serializable::currentSection());
52812854Sgabeblack@google.com    std::string str;
52912854Sgabeblack@google.com    if (!cp.find(section, name, str)) {
53012854Sgabeblack@google.com        fatal("Can't unserialize '%s:%s'\n", section, name);
53112854Sgabeblack@google.com    }
53212854Sgabeblack@google.com
53312854Sgabeblack@google.com    // code below stolen from VectorParam<T>::parse().
53412854Sgabeblack@google.com    // it would be nice to unify these somehow...
53512854Sgabeblack@google.com
53612854Sgabeblack@google.com    std::vector<std::string> tokens;
53712854Sgabeblack@google.com
53812854Sgabeblack@google.com    tokenize(tokens, str, ' ');
53912854Sgabeblack@google.com
54012854Sgabeblack@google.com    // Need this if we were doing a vector
54112854Sgabeblack@google.com    // value.resize(tokens.size());
54212854Sgabeblack@google.com
54312854Sgabeblack@google.com    param.resize(tokens.size());
54412854Sgabeblack@google.com
54512854Sgabeblack@google.com    for (std::vector<std::string>::size_type i = 0; i < tokens.size(); i++) {
54612854Sgabeblack@google.com        // need to parse into local variable to handle vector<bool>,
54712854Sgabeblack@google.com        // for which operator[] returns a special reference class
54812854Sgabeblack@google.com        // that's not the same as 'bool&', (since it's a packed
54912854Sgabeblack@google.com        // vector)
55012854Sgabeblack@google.com        T scalar_value;
55112854Sgabeblack@google.com        if (!parseParam(tokens[i], scalar_value)) {
55212854Sgabeblack@google.com            std::string err("could not parse \"");
55312854Sgabeblack@google.com
55412854Sgabeblack@google.com            err += str;
55512854Sgabeblack@google.com            err += "\"";
55612854Sgabeblack@google.com
55712854Sgabeblack@google.com            fatal(err);
55812854Sgabeblack@google.com        }
55912854Sgabeblack@google.com
56012854Sgabeblack@google.com        // assign parsed value to vector
56112854Sgabeblack@google.com        param[i] = scalar_value;
56212854Sgabeblack@google.com    }
56312854Sgabeblack@google.com}
56412854Sgabeblack@google.com
56512854Sgabeblack@google.comtemplate <class T>
56612854Sgabeblack@google.comvoid
56712854Sgabeblack@google.comarrayParamIn(CheckpointIn &cp, const std::string &name, std::list<T> &param)
56812854Sgabeblack@google.com{
56912854Sgabeblack@google.com    const std::string &section(Serializable::currentSection());
57012854Sgabeblack@google.com    std::string str;
57112854Sgabeblack@google.com    if (!cp.find(section, name, str)) {
57212854Sgabeblack@google.com        fatal("Can't unserialize '%s:%s'\n", section, name);
57312854Sgabeblack@google.com    }
57412854Sgabeblack@google.com    param.clear();
57512854Sgabeblack@google.com
57612854Sgabeblack@google.com    std::vector<std::string> tokens;
57712854Sgabeblack@google.com    tokenize(tokens, str, ' ');
57812854Sgabeblack@google.com
57912854Sgabeblack@google.com    for (std::vector<std::string>::size_type i = 0; i < tokens.size(); i++) {
58012854Sgabeblack@google.com        T scalar_value;
58112854Sgabeblack@google.com        if (!parseParam(tokens[i], scalar_value)) {
58212854Sgabeblack@google.com            std::string err("could not parse \"");
58312854Sgabeblack@google.com
58412854Sgabeblack@google.com            err += str;
58512854Sgabeblack@google.com            err += "\"";
58612854Sgabeblack@google.com
58712854Sgabeblack@google.com            fatal(err);
58812854Sgabeblack@google.com        }
58912854Sgabeblack@google.com
59012854Sgabeblack@google.com        // assign parsed value to vector
59112854Sgabeblack@google.com        param.push_back(scalar_value);
59212854Sgabeblack@google.com    }
59312854Sgabeblack@google.com}
59412854Sgabeblack@google.com
59512854Sgabeblack@google.comtemplate <class T>
59612854Sgabeblack@google.comvoid
59712854Sgabeblack@google.comarrayParamIn(CheckpointIn &cp, const std::string &name, std::set<T> &param)
59812854Sgabeblack@google.com{
59912854Sgabeblack@google.com    const std::string &section(Serializable::currentSection());
60012854Sgabeblack@google.com    std::string str;
60112854Sgabeblack@google.com    if (!cp.find(section, name, str)) {
60212854Sgabeblack@google.com        fatal("Can't unserialize '%s:%s'\n", section, name);
60312854Sgabeblack@google.com    }
60412854Sgabeblack@google.com    param.clear();
60512854Sgabeblack@google.com
60612854Sgabeblack@google.com    std::vector<std::string> tokens;
60712854Sgabeblack@google.com    tokenize(tokens, str, ' ');
60812854Sgabeblack@google.com
60912854Sgabeblack@google.com    for (std::vector<std::string>::size_type i = 0; i < tokens.size(); i++) {
61012854Sgabeblack@google.com        T scalar_value;
61112854Sgabeblack@google.com        if (!parseParam(tokens[i], scalar_value)) {
61212854Sgabeblack@google.com            std::string err("could not parse \"");
61312854Sgabeblack@google.com
61412854Sgabeblack@google.com            err += str;
61512854Sgabeblack@google.com            err += "\"";
61612854Sgabeblack@google.com
61712854Sgabeblack@google.com            fatal(err);
61812854Sgabeblack@google.com        }
61912854Sgabeblack@google.com
62012854Sgabeblack@google.com        // assign parsed value to vector
62112854Sgabeblack@google.com        param.insert(scalar_value);
62212854Sgabeblack@google.com    }
62312854Sgabeblack@google.com}
62412854Sgabeblack@google.com
62512854Sgabeblack@google.comvoid
62612854Sgabeblack@google.comdebug_serialize(const std::string &cpt_dir);
62712854Sgabeblack@google.com
62812854Sgabeblack@google.comvoid
62912854Sgabeblack@google.comobjParamIn(CheckpointIn &cp, const std::string &name, SimObject * &param);
63012854Sgabeblack@google.com
63112854Sgabeblack@google.com//
63212854Sgabeblack@google.com// These macros are streamlined to use in serialize/unserialize
63312854Sgabeblack@google.com// functions.  It's assumed that serialize() has a parameter 'os' for
63412854Sgabeblack@google.com// the ostream, and unserialize() has parameters 'cp' and 'section'.
63512854Sgabeblack@google.com#define SERIALIZE_SCALAR(scalar)        paramOut(cp, #scalar, scalar)
63612854Sgabeblack@google.com
63712854Sgabeblack@google.com#define UNSERIALIZE_SCALAR(scalar)      paramIn(cp, #scalar, scalar)
63812854Sgabeblack@google.com#define UNSERIALIZE_OPT_SCALAR(scalar)      optParamIn(cp, #scalar, scalar)
63912854Sgabeblack@google.com
64012854Sgabeblack@google.com// ENUMs are like SCALARs, but we cast them to ints on the way out
64112854Sgabeblack@google.com#define SERIALIZE_ENUM(scalar)          paramOut(cp, #scalar, (int)scalar)
64212854Sgabeblack@google.com
64312854Sgabeblack@google.com#define UNSERIALIZE_ENUM(scalar)                        \
64412854Sgabeblack@google.com    do {                                                \
64512854Sgabeblack@google.com        int tmp;                                        \
64612854Sgabeblack@google.com        paramIn(cp, #scalar, tmp);                      \
64712854Sgabeblack@google.com        scalar = static_cast<decltype(scalar)>(tmp);    \
64812854Sgabeblack@google.com    } while (0)
64912854Sgabeblack@google.com
65012854Sgabeblack@google.com#define SERIALIZE_ARRAY(member, size)           \
65112854Sgabeblack@google.com        arrayParamOut(cp, #member, member, size)
65212854Sgabeblack@google.com
65312854Sgabeblack@google.com#define UNSERIALIZE_ARRAY(member, size)         \
65412854Sgabeblack@google.com        arrayParamIn(cp, #member, member, size)
65512854Sgabeblack@google.com
65612854Sgabeblack@google.com#define SERIALIZE_CONTAINER(member)             \
65712854Sgabeblack@google.com        arrayParamOut(cp, #member, member)
65812854Sgabeblack@google.com
65912854Sgabeblack@google.com#define UNSERIALIZE_CONTAINER(member)           \
66012854Sgabeblack@google.com        arrayParamIn(cp, #member, member)
66112854Sgabeblack@google.com
66212854Sgabeblack@google.com#define SERIALIZE_EVENT(event) event.serializeSection(cp, #event);
66312854Sgabeblack@google.com
66412854Sgabeblack@google.com#define UNSERIALIZE_EVENT(event)                        \
66512854Sgabeblack@google.com    do {                                                \
66612854Sgabeblack@google.com        event.unserializeSection(cp, #event);           \
66712854Sgabeblack@google.com        eventQueue()->checkpointReschedule(&event);     \
66812854Sgabeblack@google.com    } while (0)
66912854Sgabeblack@google.com
67012854Sgabeblack@google.com#define SERIALIZE_OBJ(obj) obj.serializeSection(cp, #obj)
67112854Sgabeblack@google.com#define UNSERIALIZE_OBJ(obj) obj.unserializeSection(cp, #obj)
67212854Sgabeblack@google.com
67312854Sgabeblack@google.com#define SERIALIZE_OBJPTR(objptr)        paramOut(cp, #objptr, (objptr)->name())
67412854Sgabeblack@google.com
67512854Sgabeblack@google.com#define UNSERIALIZE_OBJPTR(objptr)                      \
67612854Sgabeblack@google.com    do {                                                \
67712854Sgabeblack@google.com        SimObject *sptr;                                \
67812854Sgabeblack@google.com        objParamIn(cp, #objptr, sptr);                  \
67912854Sgabeblack@google.com        objptr = dynamic_cast<decltype(objptr)>(sptr);  \
68012854Sgabeblack@google.com    } while (0)
68112854Sgabeblack@google.com
68212854Sgabeblack@google.com#endif // __SERIALIZE_HH__
68312854Sgabeblack@google.com