serialize.cc revision 4000
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
552356SN/A// For stat reset hack
562356SN/A#include "sim/stat_control.hh"
572356SN/A
582SN/Ausing namespace std;
592SN/A
604000Ssaidi@eecs.umich.eduextern SimObject *resolveSimObject(const string &);
614000Ssaidi@eecs.umich.edu
622287SN/Aint Serializable::ckptMaxCount = 0;
632287SN/Aint Serializable::ckptCount = 0;
642287SN/Aint Serializable::ckptPrevCount = -1;
651637SN/A
662SN/Avoid
67395SN/ASerializable::nameOut(ostream &os)
682SN/A{
69217SN/A    os << "\n[" << name() << "]\n";
702SN/A}
712SN/A
722SN/Avoid
73395SN/ASerializable::nameOut(ostream &os, const string &_name)
742SN/A{
75217SN/A    os << "\n[" << _name << "]\n";
762SN/A}
772SN/A
78217SN/Atemplate <class T>
792SN/Avoid
80502SN/AparamOut(ostream &os, const std::string &name, const T &param)
812SN/A{
82217SN/A    os << name << "=";
83217SN/A    showParam(os, param);
84217SN/A    os << "\n";
852SN/A}
862SN/A
87217SN/A
88217SN/Atemplate <class T>
89217SN/Avoid
90237SN/AparamIn(Checkpoint *cp, const std::string &section,
91502SN/A        const std::string &name, T &param)
922SN/A{
93217SN/A    std::string str;
94237SN/A    if (!cp->find(section, name, str) || !parseParam(str, param)) {
95217SN/A        fatal("Can't unserialize '%s:%s'\n", section, name);
96217SN/A    }
972SN/A}
982SN/A
99217SN/A
100217SN/Atemplate <class T>
101217SN/Avoid
102217SN/AarrayParamOut(ostream &os, const std::string &name,
103217SN/A              const T *param, int size)
104217SN/A{
105217SN/A    os << name << "=";
106217SN/A    if (size > 0)
107217SN/A        showParam(os, param[0]);
108217SN/A    for (int i = 1; i < size; ++i) {
109217SN/A        os << " ";
110217SN/A        showParam(os, param[i]);
111217SN/A    }
112217SN/A    os << "\n";
113217SN/A}
114217SN/A
115217SN/A
116217SN/Atemplate <class T>
117217SN/Avoid
118237SN/AarrayParamIn(Checkpoint *cp, const std::string &section,
119217SN/A             const std::string &name, T *param, int size)
120217SN/A{
121217SN/A    std::string str;
122237SN/A    if (!cp->find(section, name, str)) {
123217SN/A        fatal("Can't unserialize '%s:%s'\n", section, name);
124217SN/A    }
125217SN/A
126217SN/A    // code below stolen from VectorParam<T>::parse().
127217SN/A    // it would be nice to unify these somehow...
128217SN/A
129217SN/A    vector<string> tokens;
130217SN/A
131217SN/A    tokenize(tokens, str, ' ');
132217SN/A
133217SN/A    // Need this if we were doing a vector
134217SN/A    // value.resize(tokens.size());
135217SN/A
136217SN/A    if (tokens.size() != size) {
137217SN/A        fatal("Array size mismatch on %s:%s'\n", section, name);
138217SN/A    }
139217SN/A
140217SN/A    for (int i = 0; i < tokens.size(); i++) {
141217SN/A        // need to parse into local variable to handle vector<bool>,
142217SN/A        // for which operator[] returns a special reference class
143217SN/A        // that's not the same as 'bool&', (since it's a packed
144217SN/A        // vector)
145217SN/A        T scalar_value;
146217SN/A        if (!parseParam(tokens[i], scalar_value)) {
147217SN/A            string err("could not parse \"");
148217SN/A
149217SN/A            err += str;
150217SN/A            err += "\"";
151217SN/A
152217SN/A            fatal(err);
153217SN/A        }
154217SN/A
155217SN/A        // assign parsed value to vector
156217SN/A        param[i] = scalar_value;
157217SN/A    }
158217SN/A}
159217SN/A
160217SN/A
161237SN/Avoid
162237SN/AobjParamIn(Checkpoint *cp, const std::string &section,
1634000Ssaidi@eecs.umich.edu           const std::string &name, SimObject * &param)
164237SN/A{
165237SN/A    if (!cp->findObj(section, name, param)) {
166237SN/A        fatal("Can't unserialize '%s:%s'\n", section, name);
167237SN/A    }
168237SN/A}
169237SN/A
170237SN/A
171221SN/A#define INSTANTIATE_PARAM_TEMPLATES(type)				\
172221SN/Atemplate void								\
173237SN/AparamOut(ostream &os, const std::string &name, type const &param);	\
174221SN/Atemplate void								\
175237SN/AparamIn(Checkpoint *cp, const std::string &section,			\
176221SN/A        const std::string &name, type & param);				\
177221SN/Atemplate void								\
178221SN/AarrayParamOut(ostream &os, const std::string &name,			\
179237SN/A              type const *param, int size);				\
180221SN/Atemplate void								\
181237SN/AarrayParamIn(Checkpoint *cp, const std::string &section,		\
182217SN/A             const std::string &name, type *param, int size);
183217SN/A
1841642SN/AINSTANTIATE_PARAM_TEMPLATES(signed char)
1851642SN/AINSTANTIATE_PARAM_TEMPLATES(unsigned char)
1861642SN/AINSTANTIATE_PARAM_TEMPLATES(signed short)
1871642SN/AINSTANTIATE_PARAM_TEMPLATES(unsigned short)
1881642SN/AINSTANTIATE_PARAM_TEMPLATES(signed int)
1891642SN/AINSTANTIATE_PARAM_TEMPLATES(unsigned int)
1901642SN/AINSTANTIATE_PARAM_TEMPLATES(signed long)
1911642SN/AINSTANTIATE_PARAM_TEMPLATES(unsigned long)
1921642SN/AINSTANTIATE_PARAM_TEMPLATES(signed long long)
1931642SN/AINSTANTIATE_PARAM_TEMPLATES(unsigned long long)
194219SN/AINSTANTIATE_PARAM_TEMPLATES(bool)
195217SN/AINSTANTIATE_PARAM_TEMPLATES(string)
196217SN/A
197217SN/A
198395SN/A/////////////////////////////
199395SN/A
200395SN/A/// Container for serializing global variables (not associated with
201395SN/A/// any serialized object).
202395SN/Aclass Globals : public Serializable
2032SN/A{
204395SN/A  public:
205512SN/A    const string name() const;
206510SN/A    void serialize(ostream &os);
207395SN/A    void unserialize(Checkpoint *cp);
208395SN/A};
2092SN/A
210395SN/A/// The one and only instance of the Globals class.
211395SN/AGlobals globals;
2122SN/A
213512SN/Aconst string
214395SN/AGlobals::name() const
2152SN/A{
216395SN/A    return "Globals";
2172SN/A}
2182SN/A
2192SN/Avoid
220510SN/AGlobals::serialize(ostream &os)
2212SN/A{
222395SN/A    nameOut(os);
223395SN/A    SERIALIZE_SCALAR(curTick);
224395SN/A
225395SN/A    nameOut(os, "MainEventQueue");
226395SN/A    mainEventQueue.serialize(os);
2272SN/A}
2282SN/A
2292SN/Avoid
230395SN/AGlobals::unserialize(Checkpoint *cp)
2312SN/A{
232395SN/A    const string &section = name();
233395SN/A    UNSERIALIZE_SCALAR(curTick);
2342SN/A
235395SN/A    mainEventQueue.unserialize(cp, "MainEventQueue");
2362SN/A}
2372SN/A
2382SN/Avoid
2392868Sktlim@umich.eduSerializable::serializeAll(const std::string &cpt_dir)
2402SN/A{
2412868Sktlim@umich.edu    setCheckpointDir(cpt_dir);
242449SN/A    string dir = Checkpoint::dir();
243363SN/A    if (mkdir(dir.c_str(), 0775) == -1 && errno != EEXIST)
244449SN/A            fatal("couldn't mkdir %s\n", dir);
245363SN/A
246449SN/A    string cpt_file = dir + Checkpoint::baseFilename;
247395SN/A    ofstream outstream(cpt_file.c_str());
2482SN/A    time_t t = time(NULL);
249395SN/A    outstream << "// checkpoint generated: " << ctime(&t);
2502SN/A
251395SN/A    globals.serialize(outstream);
252395SN/A    SimObject::serializeAll(outstream);
253395SN/A}
2542SN/A
2552797Sktlim@umich.eduvoid
2562868Sktlim@umich.eduSerializable::unserializeAll(const std::string &cpt_dir)
2572797Sktlim@umich.edu{
2582868Sktlim@umich.edu    setCheckpointDir(cpt_dir);
2592797Sktlim@umich.edu    string dir = Checkpoint::dir();
2602797Sktlim@umich.edu    string cpt_file = dir + Checkpoint::baseFilename;
2612797Sktlim@umich.edu    string section = "";
2622797Sktlim@umich.edu
2632797Sktlim@umich.edu    DPRINTFR(Config, "Loading checkpoint dir '%s'\n",
2642797Sktlim@umich.edu             dir);
2652797Sktlim@umich.edu    Checkpoint *cp = new Checkpoint(dir, section);
2662797Sktlim@umich.edu    unserializeGlobals(cp);
2672797Sktlim@umich.edu
2682797Sktlim@umich.edu    SimObject::unserializeAll(cp);
2692797Sktlim@umich.edu}
2702SN/A
271395SN/Avoid
272395SN/ASerializable::unserializeGlobals(Checkpoint *cp)
273395SN/A{
274395SN/A    globals.unserialize(cp);
275395SN/A}
2762SN/A
277449SN/Aconst char *Checkpoint::baseFilename = "m5.cpt";
278449SN/A
279449SN/Astatic string checkpointDirBase;
280294SN/A
2812797Sktlim@umich.eduvoid
2822797Sktlim@umich.edusetCheckpointDir(const std::string &name)
2832797Sktlim@umich.edu{
2842797Sktlim@umich.edu    checkpointDirBase = name;
2852797Sktlim@umich.edu    if (checkpointDirBase[checkpointDirBase.size() - 1] != '/')
2862797Sktlim@umich.edu        checkpointDirBase += "/";
2872797Sktlim@umich.edu}
2882797Sktlim@umich.edu
289294SN/Astring
290449SN/ACheckpoint::dir()
291294SN/A{
292449SN/A    // use csprintf to insert curTick into directory name if it
293449SN/A    // appears to have a format placeholder in it.
294449SN/A    return (checkpointDirBase.find("%") != string::npos) ?
295449SN/A        csprintf(checkpointDirBase, curTick) : checkpointDirBase;
2962SN/A}
2972SN/A
2982SN/Avoid
2992868Sktlim@umich.edudebug_serialize(const std::string &cpt_dir)
3002SN/A{
3012868Sktlim@umich.edu    Serializable::serializeAll(cpt_dir);
3022SN/A}
3032SN/A
3042SN/A
3052SN/A////////////////////////////////////////////////////////////////////////
3062SN/A//
307395SN/A// SerializableClass member definitions
3082SN/A//
3092SN/A////////////////////////////////////////////////////////////////////////
3102SN/A
311395SN/A// Map of class names to SerializableBuilder creation functions.
3122SN/A// Need to make this a pointer so we can force initialization on the
313395SN/A// first reference; otherwise, some SerializableClass constructors
3142SN/A// may be invoked before the classMap constructor.
315395SN/Amap<string,SerializableClass::CreateFunc> *SerializableClass::classMap = 0;
3162SN/A
317395SN/A// SerializableClass constructor: add mapping to classMap
318395SN/ASerializableClass::SerializableClass(const string &className,
3192SN/A                                       CreateFunc createFunc)
3202SN/A{
3212SN/A    if (classMap == NULL)
322395SN/A        classMap = new map<string,SerializableClass::CreateFunc>();
3232SN/A
3242SN/A    if ((*classMap)[className])
3252SN/A    {
3262SN/A        cerr << "Error: simulation object class " << className << " redefined"
3272SN/A             << endl;
3282SN/A        fatal("");
3292SN/A    }
3302SN/A
3312SN/A    // add className --> createFunc to class map
3322SN/A    (*classMap)[className] = createFunc;
3332SN/A}
3342SN/A
3352SN/A
3362SN/A//
3372SN/A//
338395SN/ASerializable *
339395SN/ASerializableClass::createObject(Checkpoint *cp,
340237SN/A                                 const std::string &section)
3412SN/A{
342237SN/A    string className;
3432SN/A
344237SN/A    if (!cp->find(section, "type", className)) {
345395SN/A        fatal("Serializable::create: no 'type' entry in section '%s'.\n",
346237SN/A              section);
3472SN/A    }
3482SN/A
349237SN/A    CreateFunc createFunc = (*classMap)[className];
350237SN/A
351237SN/A    if (createFunc == NULL) {
352395SN/A        fatal("Serializable::create: no create function for class '%s'.\n",
353237SN/A              className);
3542SN/A    }
3552SN/A
356395SN/A    Serializable *object = createFunc(cp, section);
3572SN/A
3582SN/A    assert(object != NULL);
3592SN/A
3602SN/A    return object;
3612SN/A}
3622SN/A
363237SN/A
364395SN/ASerializable *
365395SN/ASerializable::create(Checkpoint *cp, const std::string &section)
366237SN/A{
367395SN/A    Serializable *object = SerializableClass::createObject(cp, section);
368237SN/A    object->unserialize(cp, section);
369237SN/A    return object;
370237SN/A}
371237SN/A
372237SN/A
3732738Sstever@eecs.umich.eduCheckpoint::Checkpoint(const std::string &cpt_dir, const std::string &path)
3742738Sstever@eecs.umich.edu    : db(new IniFile), basePath(path), cptDir(cpt_dir)
375237SN/A{
376449SN/A    string filename = cpt_dir + "/" + Checkpoint::baseFilename;
377237SN/A    if (!db->load(filename)) {
378237SN/A        fatal("Can't load checkpoint file '%s'\n", filename);
379237SN/A    }
380237SN/A}
381237SN/A
382237SN/A
383237SN/Abool
384237SN/ACheckpoint::find(const std::string &section, const std::string &entry,
385237SN/A                 std::string &value)
386237SN/A{
387237SN/A    return db->find(section, entry, value);
388237SN/A}
389237SN/A
390237SN/A
391237SN/Abool
392237SN/ACheckpoint::findObj(const std::string &section, const std::string &entry,
3934000Ssaidi@eecs.umich.edu                    SimObject *&value)
394237SN/A{
395237SN/A    string path;
396237SN/A
397237SN/A    if (!db->find(section, entry, path))
398237SN/A        return false;
399237SN/A
4004000Ssaidi@eecs.umich.edu    value = resolveSimObject(path);
4014000Ssaidi@eecs.umich.edu    return true;
402237SN/A}
403304SN/A
404304SN/A
405304SN/Abool
406304SN/ACheckpoint::sectionExists(const std::string &section)
407304SN/A{
408304SN/A    return db->sectionExists(section);
409304SN/A}
4102356SN/A
4112356SN/A/** Hacked stat reset event */
4122356SN/A
4132356SN/Aclass StatresetParamContext : public ParamContext
4142356SN/A{
4152356SN/A  public:
4162356SN/A    StatresetParamContext(const string &section);
4172356SN/A    ~StatresetParamContext();
4182356SN/A    void startup();
4192356SN/A};
4202356SN/A
4212356SN/AStatresetParamContext statParams("statsreset");
4222356SN/A
4232356SN/AParam<Tick> reset_cycle(&statParams, "reset_cycle",
4242356SN/A                        "Cycle to reset stats on", 0);
4252356SN/A
4262356SN/AStatresetParamContext::StatresetParamContext(const string &section)
4272356SN/A    : ParamContext(section)
4282356SN/A{ }
4292356SN/A
4302356SN/AStatresetParamContext::~StatresetParamContext()
4312356SN/A{
4322356SN/A}
4332356SN/A
4342356SN/Avoid
4352356SN/AStatresetParamContext::startup()
4362356SN/A{
4372356SN/A    if (reset_cycle > 0) {
4382356SN/A        Stats::SetupEvent(Stats::Reset, curTick + reset_cycle, 0);
4392356SN/A        cprintf("Stats reset event scheduled for %lli\n",
4402356SN/A                curTick + reset_cycle);
4412356SN/A    }
4422356SN/A}
443