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 §ion, const std::string &entry, 8712854Sgabeblack@google.com std::string &value); 8812854Sgabeblack@google.com 8912854Sgabeblack@google.com bool findObj(const std::string §ion, const std::string &entry, 9012854Sgabeblack@google.com SimObject *&value); 9112854Sgabeblack@google.com 9212854Sgabeblack@google.com 9312854Sgabeblack@google.com bool entryExists(const std::string §ion, const std::string &entry); 9412854Sgabeblack@google.com bool sectionExists(const std::string §ion); 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 ¤tSection(); 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 ¶m) 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 ¶m) 38412854Sgabeblack@google.com{ 38512854Sgabeblack@google.com const std::string §ion(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 ¶m, bool warn = true) 39612854Sgabeblack@google.com{ 39712854Sgabeblack@google.com const std::string §ion(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> ¶m) 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> ¶m) 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> ¶m) 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 §ion(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> ¶m) 52612854Sgabeblack@google.com{ 52712854Sgabeblack@google.com const std::string §ion(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> ¶m) 56812854Sgabeblack@google.com{ 56912854Sgabeblack@google.com const std::string §ion(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> ¶m) 59812854Sgabeblack@google.com{ 59912854Sgabeblack@google.com const std::string §ion(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 * ¶m); 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