serialize.cc revision 2797
12SN/A/*
21762SN/A * Copyright (c) 2002-2005 The Regents of The University of Michigan
32SN/A * All rights reserved.
42SN/A *
52SN/A * Redistribution and use in source and binary forms, with or without
62SN/A * modification, are permitted provided that the following conditions are
72SN/A * met: redistributions of source code must retain the above copyright
82SN/A * notice, this list of conditions and the following disclaimer;
92SN/A * redistributions in binary form must reproduce the above copyright
102SN/A * notice, this list of conditions and the following disclaimer in the
112SN/A * documentation and/or other materials provided with the distribution;
122SN/A * neither the name of the copyright holders nor the names of its
132SN/A * contributors may be used to endorse or promote products derived from
142SN/A * this software without specific prior written permission.
152SN/A *
162SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
172SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
182SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
192SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
202SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
212SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
222SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
232SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
242SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
252SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
262SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272665Ssaidi@eecs.umich.edu *
282760Sbinkertn@umich.edu * Authors: Nathan Binkert
292760Sbinkertn@umich.edu *          Erik Hallnor
302665Ssaidi@eecs.umich.edu *          Steve Reinhardt
312SN/A */
322SN/A
332SN/A#include <sys/time.h>
34363SN/A#include <sys/types.h>
35363SN/A#include <sys/stat.h>
361354SN/A#include <errno.h>
372SN/A
382SN/A#include <fstream>
392SN/A#include <list>
402SN/A#include <string>
412SN/A#include <vector>
422SN/A
43363SN/A#include "base/inifile.hh"
4456SN/A#include "base/misc.hh"
451388SN/A#include "base/output.hh"
46217SN/A#include "base/str.hh"
47363SN/A#include "base/trace.hh"
4856SN/A#include "sim/eventq.hh"
4956SN/A#include "sim/param.hh"
5056SN/A#include "sim/serialize.hh"
5156SN/A#include "sim/sim_events.hh"
521638SN/A#include "sim/sim_exit.hh"
5356SN/A#include "sim/sim_object.hh"
542SN/A
552SN/Ausing namespace std;
562SN/A
572287SN/Aint Serializable::ckptMaxCount = 0;
582287SN/Aint Serializable::ckptCount = 0;
592287SN/Aint Serializable::ckptPrevCount = -1;
601637SN/A
612SN/Avoid
62395SN/ASerializable::nameOut(ostream &os)
632SN/A{
64217SN/A    os << "\n[" << name() << "]\n";
652SN/A}
662SN/A
672SN/Avoid
68395SN/ASerializable::nameOut(ostream &os, const string &_name)
692SN/A{
70217SN/A    os << "\n[" << _name << "]\n";
712SN/A}
722SN/A
73217SN/Atemplate <class T>
742SN/Avoid
75502SN/AparamOut(ostream &os, const std::string &name, const T &param)
762SN/A{
77217SN/A    os << name << "=";
78217SN/A    showParam(os, param);
79217SN/A    os << "\n";
802SN/A}
812SN/A
82217SN/A
83217SN/Atemplate <class T>
84217SN/Avoid
85237SN/AparamIn(Checkpoint *cp, const std::string &section,
86502SN/A        const std::string &name, T &param)
872SN/A{
88217SN/A    std::string str;
89237SN/A    if (!cp->find(section, name, str) || !parseParam(str, param)) {
90217SN/A        fatal("Can't unserialize '%s:%s'\n", section, name);
91217SN/A    }
922SN/A}
932SN/A
94217SN/A
95217SN/Atemplate <class T>
96217SN/Avoid
97217SN/AarrayParamOut(ostream &os, const std::string &name,
98217SN/A              const T *param, int size)
99217SN/A{
100217SN/A    os << name << "=";
101217SN/A    if (size > 0)
102217SN/A        showParam(os, param[0]);
103217SN/A    for (int i = 1; i < size; ++i) {
104217SN/A        os << " ";
105217SN/A        showParam(os, param[i]);
106217SN/A    }
107217SN/A    os << "\n";
108217SN/A}
109217SN/A
110217SN/A
111217SN/Atemplate <class T>
112217SN/Avoid
113237SN/AarrayParamIn(Checkpoint *cp, const std::string &section,
114217SN/A             const std::string &name, T *param, int size)
115217SN/A{
116217SN/A    std::string str;
117237SN/A    if (!cp->find(section, name, str)) {
118217SN/A        fatal("Can't unserialize '%s:%s'\n", section, name);
119217SN/A    }
120217SN/A
121217SN/A    // code below stolen from VectorParam<T>::parse().
122217SN/A    // it would be nice to unify these somehow...
123217SN/A
124217SN/A    vector<string> tokens;
125217SN/A
126217SN/A    tokenize(tokens, str, ' ');
127217SN/A
128217SN/A    // Need this if we were doing a vector
129217SN/A    // value.resize(tokens.size());
130217SN/A
131217SN/A    if (tokens.size() != size) {
132217SN/A        fatal("Array size mismatch on %s:%s'\n", section, name);
133217SN/A    }
134217SN/A
135217SN/A    for (int i = 0; i < tokens.size(); i++) {
136217SN/A        // need to parse into local variable to handle vector<bool>,
137217SN/A        // for which operator[] returns a special reference class
138217SN/A        // that's not the same as 'bool&', (since it's a packed
139217SN/A        // vector)
140217SN/A        T scalar_value;
141217SN/A        if (!parseParam(tokens[i], scalar_value)) {
142217SN/A            string err("could not parse \"");
143217SN/A
144217SN/A            err += str;
145217SN/A            err += "\"";
146217SN/A
147217SN/A            fatal(err);
148217SN/A        }
149217SN/A
150217SN/A        // assign parsed value to vector
151217SN/A        param[i] = scalar_value;
152217SN/A    }
153217SN/A}
154217SN/A
155217SN/A
156237SN/Avoid
157237SN/AobjParamIn(Checkpoint *cp, const std::string &section,
158395SN/A           const std::string &name, Serializable * &param)
159237SN/A{
160237SN/A    if (!cp->findObj(section, name, param)) {
161237SN/A        fatal("Can't unserialize '%s:%s'\n", section, name);
162237SN/A    }
163237SN/A}
164237SN/A
165237SN/A
166221SN/A#define INSTANTIATE_PARAM_TEMPLATES(type)				\
167221SN/Atemplate void								\
168237SN/AparamOut(ostream &os, const std::string &name, type const &param);	\
169221SN/Atemplate void								\
170237SN/AparamIn(Checkpoint *cp, const std::string &section,			\
171221SN/A        const std::string &name, type & param);				\
172221SN/Atemplate void								\
173221SN/AarrayParamOut(ostream &os, const std::string &name,			\
174237SN/A              type const *param, int size);				\
175221SN/Atemplate void								\
176237SN/AarrayParamIn(Checkpoint *cp, const std::string &section,		\
177217SN/A             const std::string &name, type *param, int size);
178217SN/A
1791642SN/AINSTANTIATE_PARAM_TEMPLATES(signed char)
1801642SN/AINSTANTIATE_PARAM_TEMPLATES(unsigned char)
1811642SN/AINSTANTIATE_PARAM_TEMPLATES(signed short)
1821642SN/AINSTANTIATE_PARAM_TEMPLATES(unsigned short)
1831642SN/AINSTANTIATE_PARAM_TEMPLATES(signed int)
1841642SN/AINSTANTIATE_PARAM_TEMPLATES(unsigned int)
1851642SN/AINSTANTIATE_PARAM_TEMPLATES(signed long)
1861642SN/AINSTANTIATE_PARAM_TEMPLATES(unsigned long)
1871642SN/AINSTANTIATE_PARAM_TEMPLATES(signed long long)
1881642SN/AINSTANTIATE_PARAM_TEMPLATES(unsigned long long)
189219SN/AINSTANTIATE_PARAM_TEMPLATES(bool)
190217SN/AINSTANTIATE_PARAM_TEMPLATES(string)
191217SN/A
192217SN/A
193395SN/A/////////////////////////////
194395SN/A
195395SN/A/// Container for serializing global variables (not associated with
196395SN/A/// any serialized object).
197395SN/Aclass Globals : public Serializable
1982SN/A{
199395SN/A  public:
200512SN/A    const string name() const;
201510SN/A    void serialize(ostream &os);
202395SN/A    void unserialize(Checkpoint *cp);
203395SN/A};
2042SN/A
205395SN/A/// The one and only instance of the Globals class.
206395SN/AGlobals globals;
2072SN/A
208512SN/Aconst string
209395SN/AGlobals::name() const
2102SN/A{
211395SN/A    return "Globals";
2122SN/A}
2132SN/A
2142SN/Avoid
215510SN/AGlobals::serialize(ostream &os)
2162SN/A{
217395SN/A    nameOut(os);
218395SN/A    SERIALIZE_SCALAR(curTick);
219395SN/A
220395SN/A    nameOut(os, "MainEventQueue");
221395SN/A    mainEventQueue.serialize(os);
2222SN/A}
2232SN/A
2242SN/Avoid
225395SN/AGlobals::unserialize(Checkpoint *cp)
2262SN/A{
227395SN/A    const string &section = name();
228395SN/A    UNSERIALIZE_SCALAR(curTick);
2292SN/A
230395SN/A    mainEventQueue.unserialize(cp, "MainEventQueue");
2312SN/A}
2322SN/A
2332SN/Avoid
234395SN/ASerializable::serializeAll()
2352SN/A{
236449SN/A    string dir = Checkpoint::dir();
237363SN/A    if (mkdir(dir.c_str(), 0775) == -1 && errno != EEXIST)
238449SN/A            fatal("couldn't mkdir %s\n", dir);
239363SN/A
240449SN/A    string cpt_file = dir + Checkpoint::baseFilename;
241395SN/A    ofstream outstream(cpt_file.c_str());
2422SN/A    time_t t = time(NULL);
243395SN/A    outstream << "// checkpoint generated: " << ctime(&t);
2442SN/A
245395SN/A    globals.serialize(outstream);
246395SN/A    SimObject::serializeAll(outstream);
247395SN/A}
2482SN/A
2492797Sktlim@umich.eduvoid
2502797Sktlim@umich.eduSerializable::unserializeAll()
2512797Sktlim@umich.edu{
2522797Sktlim@umich.edu    string dir = Checkpoint::dir();
2532797Sktlim@umich.edu    string cpt_file = dir + Checkpoint::baseFilename;
2542797Sktlim@umich.edu    string section = "";
2552797Sktlim@umich.edu
2562797Sktlim@umich.edu    DPRINTFR(Config, "Loading checkpoint dir '%s'\n",
2572797Sktlim@umich.edu             dir);
2582797Sktlim@umich.edu    Checkpoint *cp = new Checkpoint(dir, section);
2592797Sktlim@umich.edu    unserializeGlobals(cp);
2602797Sktlim@umich.edu
2612797Sktlim@umich.edu    SimObject::unserializeAll(cp);
2622797Sktlim@umich.edu}
2632SN/A
264395SN/Avoid
265395SN/ASerializable::unserializeGlobals(Checkpoint *cp)
266395SN/A{
267395SN/A    globals.unserialize(cp);
268395SN/A}
2692SN/A
270449SN/Aconst char *Checkpoint::baseFilename = "m5.cpt";
271449SN/A
272449SN/Astatic string checkpointDirBase;
273294SN/A
2742797Sktlim@umich.eduvoid
2752797Sktlim@umich.edusetCheckpointDir(const std::string &name)
2762797Sktlim@umich.edu{
2772797Sktlim@umich.edu    checkpointDirBase = name;
2782797Sktlim@umich.edu    if (checkpointDirBase[checkpointDirBase.size() - 1] != '/')
2792797Sktlim@umich.edu        checkpointDirBase += "/";
2802797Sktlim@umich.edu}
2812797Sktlim@umich.edu
282294SN/Astring
283449SN/ACheckpoint::dir()
284294SN/A{
285449SN/A    // use csprintf to insert curTick into directory name if it
286449SN/A    // appears to have a format placeholder in it.
287449SN/A    return (checkpointDirBase.find("%") != string::npos) ?
288449SN/A        csprintf(checkpointDirBase, curTick) : checkpointDirBase;
2892SN/A}
2902SN/A
2912SN/Avoid
292294SN/Adebug_serialize()
2932SN/A{
294395SN/A    Serializable::serializeAll();
2952SN/A}
2962SN/A
2972SN/A
2982SN/A////////////////////////////////////////////////////////////////////////
2992SN/A//
300395SN/A// SerializableClass member definitions
3012SN/A//
3022SN/A////////////////////////////////////////////////////////////////////////
3032SN/A
304395SN/A// Map of class names to SerializableBuilder creation functions.
3052SN/A// Need to make this a pointer so we can force initialization on the
306395SN/A// first reference; otherwise, some SerializableClass constructors
3072SN/A// may be invoked before the classMap constructor.
308395SN/Amap<string,SerializableClass::CreateFunc> *SerializableClass::classMap = 0;
3092SN/A
310395SN/A// SerializableClass constructor: add mapping to classMap
311395SN/ASerializableClass::SerializableClass(const string &className,
3122SN/A                                       CreateFunc createFunc)
3132SN/A{
3142SN/A    if (classMap == NULL)
315395SN/A        classMap = new map<string,SerializableClass::CreateFunc>();
3162SN/A
3172SN/A    if ((*classMap)[className])
3182SN/A    {
3192SN/A        cerr << "Error: simulation object class " << className << " redefined"
3202SN/A             << endl;
3212SN/A        fatal("");
3222SN/A    }
3232SN/A
3242SN/A    // add className --> createFunc to class map
3252SN/A    (*classMap)[className] = createFunc;
3262SN/A}
3272SN/A
3282SN/A
3292SN/A//
3302SN/A//
331395SN/ASerializable *
332395SN/ASerializableClass::createObject(Checkpoint *cp,
333237SN/A                                 const std::string &section)
3342SN/A{
335237SN/A    string className;
3362SN/A
337237SN/A    if (!cp->find(section, "type", className)) {
338395SN/A        fatal("Serializable::create: no 'type' entry in section '%s'.\n",
339237SN/A              section);
3402SN/A    }
3412SN/A
342237SN/A    CreateFunc createFunc = (*classMap)[className];
343237SN/A
344237SN/A    if (createFunc == NULL) {
345395SN/A        fatal("Serializable::create: no create function for class '%s'.\n",
346237SN/A              className);
3472SN/A    }
3482SN/A
349395SN/A    Serializable *object = createFunc(cp, section);
3502SN/A
3512SN/A    assert(object != NULL);
3522SN/A
3532SN/A    return object;
3542SN/A}
3552SN/A
356237SN/A
357395SN/ASerializable *
358395SN/ASerializable::create(Checkpoint *cp, const std::string &section)
359237SN/A{
360395SN/A    Serializable *object = SerializableClass::createObject(cp, section);
361237SN/A    object->unserialize(cp, section);
362237SN/A    return object;
363237SN/A}
364237SN/A
365237SN/A
3662738Sstever@eecs.umich.eduCheckpoint::Checkpoint(const std::string &cpt_dir, const std::string &path)
3672738Sstever@eecs.umich.edu    : db(new IniFile), basePath(path), cptDir(cpt_dir)
368237SN/A{
369449SN/A    string filename = cpt_dir + "/" + Checkpoint::baseFilename;
370237SN/A    if (!db->load(filename)) {
371237SN/A        fatal("Can't load checkpoint file '%s'\n", filename);
372237SN/A    }
373237SN/A}
374237SN/A
375237SN/A
376237SN/Abool
377237SN/ACheckpoint::find(const std::string &section, const std::string &entry,
378237SN/A                 std::string &value)
379237SN/A{
380237SN/A    return db->find(section, entry, value);
381237SN/A}
382237SN/A
383237SN/A
384237SN/Abool
385237SN/ACheckpoint::findObj(const std::string &section, const std::string &entry,
386395SN/A                    Serializable *&value)
387237SN/A{
388237SN/A    string path;
389237SN/A
390237SN/A    if (!db->find(section, entry, path))
391237SN/A        return false;
392237SN/A
393237SN/A    if ((value = objMap[path]) != NULL)
394237SN/A        return true;
395237SN/A
396237SN/A    return false;
397237SN/A}
398304SN/A
399304SN/A
400304SN/Abool
401304SN/ACheckpoint::sectionExists(const std::string &section)
402304SN/A{
403304SN/A    return db->sectionExists(section);
404304SN/A}
405