serialize.cc revision 7823
15831Sgblack@eecs.umich.edu/*
25831Sgblack@eecs.umich.edu * Copyright (c) 2002-2005 The Regents of The University of Michigan
35831Sgblack@eecs.umich.edu * All rights reserved.
45831Sgblack@eecs.umich.edu *
55831Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without
65831Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are
75831Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright
85831Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer;
95831Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright
105831Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the
115831Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution;
125831Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its
135831Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from
145831Sgblack@eecs.umich.edu * this software without specific prior written permission.
155831Sgblack@eecs.umich.edu *
165831Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
175831Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
185831Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
195831Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
205831Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
215831Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
225831Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
235831Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
245831Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
255831Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
265831Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
275831Sgblack@eecs.umich.edu *
285831Sgblack@eecs.umich.edu * Authors: Nathan Binkert
295831Sgblack@eecs.umich.edu *          Erik Hallnor
305831Sgblack@eecs.umich.edu *          Steve Reinhardt
315831Sgblack@eecs.umich.edu */
325831Sgblack@eecs.umich.edu
335831Sgblack@eecs.umich.edu#include <sys/time.h>
348229Snate@binkert.org#include <sys/types.h>
358229Snate@binkert.org#include <sys/stat.h>
368229Snate@binkert.org#include <errno.h>
375831Sgblack@eecs.umich.edu
385831Sgblack@eecs.umich.edu#include <fstream>
395831Sgblack@eecs.umich.edu#include <list>
405831Sgblack@eecs.umich.edu#include <string>
415831Sgblack@eecs.umich.edu#include <vector>
425831Sgblack@eecs.umich.edu
435831Sgblack@eecs.umich.edu#include "base/inifile.hh"
445831Sgblack@eecs.umich.edu#include "base/misc.hh"
455832Sgblack@eecs.umich.edu#include "base/output.hh"
465832Sgblack@eecs.umich.edu#include "base/str.hh"
475832Sgblack@eecs.umich.edu#include "base/trace.hh"
485832Sgblack@eecs.umich.edu#include "sim/eventq.hh"
495832Sgblack@eecs.umich.edu#include "sim/serialize.hh"
505832Sgblack@eecs.umich.edu#include "sim/sim_events.hh"
515832Sgblack@eecs.umich.edu#include "sim/sim_exit.hh"
525832Sgblack@eecs.umich.edu#include "sim/sim_object.hh"
535832Sgblack@eecs.umich.edu
545832Sgblack@eecs.umich.edu// For stat reset hack
555832Sgblack@eecs.umich.edu#include "sim/stat_control.hh"
565832Sgblack@eecs.umich.edu
575832Sgblack@eecs.umich.eduusing namespace std;
585832Sgblack@eecs.umich.edu
595832Sgblack@eecs.umich.eduextern SimObject *resolveSimObject(const string &);
605832Sgblack@eecs.umich.edu
615832Sgblack@eecs.umich.edu//
625832Sgblack@eecs.umich.edu// The base implementations use to_number for parsing and '<<' for
635832Sgblack@eecs.umich.edu// displaying, suitable for integer types.
645832Sgblack@eecs.umich.edu//
655832Sgblack@eecs.umich.edutemplate <class T>
665832Sgblack@eecs.umich.edubool
675832Sgblack@eecs.umich.eduparseParam(const string &s, T &value)
685832Sgblack@eecs.umich.edu{
695832Sgblack@eecs.umich.edu    return to_number(s, value);
705832Sgblack@eecs.umich.edu}
715832Sgblack@eecs.umich.edu
725832Sgblack@eecs.umich.edutemplate <class T>
735832Sgblack@eecs.umich.eduvoid
745832Sgblack@eecs.umich.edushowParam(ostream &os, const T &value)
755832Sgblack@eecs.umich.edu{
765832Sgblack@eecs.umich.edu    os << value;
775832Sgblack@eecs.umich.edu}
785832Sgblack@eecs.umich.edu
795832Sgblack@eecs.umich.edu//
805832Sgblack@eecs.umich.edu// Template specializations:
815832Sgblack@eecs.umich.edu// - char (8-bit integer)
825832Sgblack@eecs.umich.edu// - floating-point types
835832Sgblack@eecs.umich.edu// - bool
845832Sgblack@eecs.umich.edu// - string
855832Sgblack@eecs.umich.edu//
865832Sgblack@eecs.umich.edu
875832Sgblack@eecs.umich.edu// Treat 8-bit ints (chars) as ints on output, not as chars
885832Sgblack@eecs.umich.edutemplate <>
895832Sgblack@eecs.umich.eduvoid
905832Sgblack@eecs.umich.edushowParam(ostream &os, const char &value)
915832Sgblack@eecs.umich.edu{
925832Sgblack@eecs.umich.edu    os << (int)value;
935832Sgblack@eecs.umich.edu}
945832Sgblack@eecs.umich.edu
955832Sgblack@eecs.umich.edu
965832Sgblack@eecs.umich.edutemplate <>
975832Sgblack@eecs.umich.eduvoid
985832Sgblack@eecs.umich.edushowParam(ostream &os, const signed char &value)
995832Sgblack@eecs.umich.edu{
1005832Sgblack@eecs.umich.edu    os << (int)value;
1015832Sgblack@eecs.umich.edu}
1025832Sgblack@eecs.umich.edu
1035832Sgblack@eecs.umich.edu
1045832Sgblack@eecs.umich.edutemplate <>
1055832Sgblack@eecs.umich.eduvoid
1065832Sgblack@eecs.umich.edushowParam(ostream &os, const unsigned char &value)
1075832Sgblack@eecs.umich.edu{
1085832Sgblack@eecs.umich.edu    os << (unsigned int)value;
1095832Sgblack@eecs.umich.edu}
1105832Sgblack@eecs.umich.edu
1115832Sgblack@eecs.umich.edu
1125832Sgblack@eecs.umich.edu// Use sscanf() for FP types as to_number() only handles integers
1135832Sgblack@eecs.umich.edutemplate <>
1145832Sgblack@eecs.umich.edubool
1155832Sgblack@eecs.umich.eduparseParam(const string &s, float &value)
1165832Sgblack@eecs.umich.edu{
1175832Sgblack@eecs.umich.edu    return (sscanf(s.c_str(), "%f", &value) == 1);
1185832Sgblack@eecs.umich.edu}
1197903Shestness@cs.utexas.edu
1207903Shestness@cs.utexas.edutemplate <>
1217903Shestness@cs.utexas.edubool
1227903Shestness@cs.utexas.eduparseParam(const string &s, double &value)
1235832Sgblack@eecs.umich.edu{
1245832Sgblack@eecs.umich.edu    return (sscanf(s.c_str(), "%lf", &value) == 1);
1255832Sgblack@eecs.umich.edu}
1265832Sgblack@eecs.umich.edu
1275832Sgblack@eecs.umich.edutemplate <>
1285832Sgblack@eecs.umich.edubool
1295832Sgblack@eecs.umich.eduparseParam(const string &s, bool &value)
1305832Sgblack@eecs.umich.edu{
1315832Sgblack@eecs.umich.edu    const string &ls = to_lower(s);
1325832Sgblack@eecs.umich.edu
1335832Sgblack@eecs.umich.edu    if (ls == "true") {
1345832Sgblack@eecs.umich.edu        value = true;
1355832Sgblack@eecs.umich.edu        return true;
1365832Sgblack@eecs.umich.edu    }
1375832Sgblack@eecs.umich.edu
1385832Sgblack@eecs.umich.edu    if (ls == "false") {
1395832Sgblack@eecs.umich.edu        value = false;
1405832Sgblack@eecs.umich.edu        return true;
1415832Sgblack@eecs.umich.edu    }
1425832Sgblack@eecs.umich.edu
1435832Sgblack@eecs.umich.edu    return false;
1445832Sgblack@eecs.umich.edu}
1455832Sgblack@eecs.umich.edu
1465832Sgblack@eecs.umich.edu// Display bools as strings
1475832Sgblack@eecs.umich.edutemplate <>
1485832Sgblack@eecs.umich.eduvoid
1495832Sgblack@eecs.umich.edushowParam(ostream &os, const bool &value)
1505832Sgblack@eecs.umich.edu{
1515832Sgblack@eecs.umich.edu    os << (value ? "true" : "false");
1525832Sgblack@eecs.umich.edu}
1537903Shestness@cs.utexas.edu
1547903Shestness@cs.utexas.edu
1557903Shestness@cs.utexas.edu// String requires no processing to speak of
1567903Shestness@cs.utexas.edutemplate <>
1575832Sgblack@eecs.umich.edubool
1585832Sgblack@eecs.umich.eduparseParam(const string &s, string &value)
1595831Sgblack@eecs.umich.edu{
1605831Sgblack@eecs.umich.edu    value = s;
1615831Sgblack@eecs.umich.edu    return true;
1625832Sgblack@eecs.umich.edu}
1635832Sgblack@eecs.umich.edu
1645832Sgblack@eecs.umich.eduint Serializable::ckptMaxCount = 0;
1655832Sgblack@eecs.umich.eduint Serializable::ckptCount = 0;
1665832Sgblack@eecs.umich.eduint Serializable::ckptPrevCount = -1;
1675832Sgblack@eecs.umich.edu
1685832Sgblack@eecs.umich.eduvoid
1695832Sgblack@eecs.umich.eduSerializable::nameOut(ostream &os)
1705832Sgblack@eecs.umich.edu{
1715832Sgblack@eecs.umich.edu    os << "\n[" << name() << "]\n";
1725832Sgblack@eecs.umich.edu}
1735832Sgblack@eecs.umich.edu
1745832Sgblack@eecs.umich.eduvoid
1755832Sgblack@eecs.umich.eduSerializable::nameOut(ostream &os, const string &_name)
1765832Sgblack@eecs.umich.edu{
1775832Sgblack@eecs.umich.edu    os << "\n[" << _name << "]\n";
1785832Sgblack@eecs.umich.edu}
1795832Sgblack@eecs.umich.edu
1805832Sgblack@eecs.umich.edutemplate <class T>
1815832Sgblack@eecs.umich.eduvoid
1825832Sgblack@eecs.umich.eduparamOut(ostream &os, const string &name, const T &param)
1835832Sgblack@eecs.umich.edu{
1845832Sgblack@eecs.umich.edu    os << name << "=";
1855832Sgblack@eecs.umich.edu    showParam(os, param);
1865832Sgblack@eecs.umich.edu    os << "\n";
1875832Sgblack@eecs.umich.edu}
1885832Sgblack@eecs.umich.edu
1895832Sgblack@eecs.umich.edutemplate <class T>
1905832Sgblack@eecs.umich.eduvoid
1915832Sgblack@eecs.umich.eduarrayParamOut(ostream &os, const string &name, const vector<T> &param)
1925832Sgblack@eecs.umich.edu{
1935832Sgblack@eecs.umich.edu    typename vector<T>::size_type size = param.size();
1945831Sgblack@eecs.umich.edu    os << name << "=";
1955831Sgblack@eecs.umich.edu    if (size > 0)
1965831Sgblack@eecs.umich.edu        showParam(os, param[0]);
1975831Sgblack@eecs.umich.edu    for (typename vector<T>::size_type i = 1; i < size; ++i) {
1985831Sgblack@eecs.umich.edu        os << " ";
1995831Sgblack@eecs.umich.edu        showParam(os, param[i]);
2005831Sgblack@eecs.umich.edu    }
2015831Sgblack@eecs.umich.edu    os << "\n";
2025831Sgblack@eecs.umich.edu}
2035831Sgblack@eecs.umich.edu
2045831Sgblack@eecs.umich.edu
2055831Sgblack@eecs.umich.edutemplate <class T>
2065831Sgblack@eecs.umich.eduvoid
2075831Sgblack@eecs.umich.eduparamIn(Checkpoint *cp, const string &section, const string &name, T &param)
2085831Sgblack@eecs.umich.edu{
2095831Sgblack@eecs.umich.edu    string str;
2105831Sgblack@eecs.umich.edu    if (!cp->find(section, name, str) || !parseParam(str, param)) {
2115831Sgblack@eecs.umich.edu        fatal("Can't unserialize '%s:%s'\n", section, name);
2125831Sgblack@eecs.umich.edu    }
2135831Sgblack@eecs.umich.edu}
2145831Sgblack@eecs.umich.edu
2155831Sgblack@eecs.umich.edutemplate <class T>
2165831Sgblack@eecs.umich.edubool
2175831Sgblack@eecs.umich.eduoptParamIn(Checkpoint *cp, const string &section, const string &name, T &param)
2185831Sgblack@eecs.umich.edu{
2195831Sgblack@eecs.umich.edu    string str;
2205831Sgblack@eecs.umich.edu    if (!cp->find(section, name, str) || !parseParam(str, param)) {
2215831Sgblack@eecs.umich.edu        warn("optional parameter %s:%s not present\n", section, name);
2225831Sgblack@eecs.umich.edu        return false;
2235831Sgblack@eecs.umich.edu    } else {
2245831Sgblack@eecs.umich.edu        return true;
2255831Sgblack@eecs.umich.edu    }
2265832Sgblack@eecs.umich.edu}
2275832Sgblack@eecs.umich.edu
2285831Sgblack@eecs.umich.edutemplate <class T>
2295832Sgblack@eecs.umich.eduvoid
2305832Sgblack@eecs.umich.eduarrayParamOut(ostream &os, const string &name, const T *param, unsigned size)
2315831Sgblack@eecs.umich.edu{
2325832Sgblack@eecs.umich.edu    os << name << "=";
2335831Sgblack@eecs.umich.edu    if (size > 0)
2345831Sgblack@eecs.umich.edu        showParam(os, param[0]);
2355831Sgblack@eecs.umich.edu    for (unsigned i = 1; i < size; ++i) {
2365831Sgblack@eecs.umich.edu        os << " ";
2375831Sgblack@eecs.umich.edu        showParam(os, param[i]);
2385831Sgblack@eecs.umich.edu    }
2395831Sgblack@eecs.umich.edu    os << "\n";
2405831Sgblack@eecs.umich.edu}
2415831Sgblack@eecs.umich.edu
2425831Sgblack@eecs.umich.edu
2435831Sgblack@eecs.umich.edutemplate <class T>
2445831Sgblack@eecs.umich.eduvoid
2455831Sgblack@eecs.umich.eduarrayParamIn(Checkpoint *cp, const string &section, const string &name,
2465831Sgblack@eecs.umich.edu             T *param, unsigned size)
2475832Sgblack@eecs.umich.edu{
2485831Sgblack@eecs.umich.edu    string str;
2495831Sgblack@eecs.umich.edu    if (!cp->find(section, name, str)) {
2505831Sgblack@eecs.umich.edu        fatal("Can't unserialize '%s:%s'\n", section, name);
2515831Sgblack@eecs.umich.edu    }
2525831Sgblack@eecs.umich.edu
2535831Sgblack@eecs.umich.edu    // code below stolen from VectorParam<T>::parse().
2545831Sgblack@eecs.umich.edu    // it would be nice to unify these somehow...
2555831Sgblack@eecs.umich.edu
2565831Sgblack@eecs.umich.edu    vector<string> tokens;
2575831Sgblack@eecs.umich.edu
2585831Sgblack@eecs.umich.edu    tokenize(tokens, str, ' ');
2595831Sgblack@eecs.umich.edu
2605831Sgblack@eecs.umich.edu    // Need this if we were doing a vector
2615831Sgblack@eecs.umich.edu    // value.resize(tokens.size());
2625831Sgblack@eecs.umich.edu
2637903Shestness@cs.utexas.edu    if (tokens.size() != size) {
2647903Shestness@cs.utexas.edu        fatal("Array size mismatch on %s:%s'\n", section, name);
2657903Shestness@cs.utexas.edu    }
2665831Sgblack@eecs.umich.edu
2675831Sgblack@eecs.umich.edu    for (vector<string>::size_type i = 0; i < tokens.size(); i++) {
2687811Ssteve.reinhardt@amd.com        // need to parse into local variable to handle vector<bool>,
2695831Sgblack@eecs.umich.edu        // for which operator[] returns a special reference class
2705831Sgblack@eecs.umich.edu        // that's not the same as 'bool&', (since it's a packed
271        // vector)
272        T scalar_value = 0;
273        if (!parseParam(tokens[i], scalar_value)) {
274            string err("could not parse \"");
275
276            err += str;
277            err += "\"";
278
279            fatal(err);
280        }
281
282        // assign parsed value to vector
283        param[i] = scalar_value;
284    }
285}
286
287template <class T>
288void
289arrayParamIn(Checkpoint *cp, const string &section,
290             const string &name, vector<T> &param)
291{
292    string str;
293    if (!cp->find(section, name, str)) {
294        fatal("Can't unserialize '%s:%s'\n", section, name);
295    }
296
297    // code below stolen from VectorParam<T>::parse().
298    // it would be nice to unify these somehow...
299
300    vector<string> tokens;
301
302    tokenize(tokens, str, ' ');
303
304    // Need this if we were doing a vector
305    // value.resize(tokens.size());
306
307    param.resize(tokens.size());
308
309    for (vector<string>::size_type i = 0; i < tokens.size(); i++) {
310        // need to parse into local variable to handle vector<bool>,
311        // for which operator[] returns a special reference class
312        // that's not the same as 'bool&', (since it's a packed
313        // vector)
314        T scalar_value = 0;
315        if (!parseParam(tokens[i], scalar_value)) {
316            string err("could not parse \"");
317
318            err += str;
319            err += "\"";
320
321            fatal(err);
322        }
323
324        // assign parsed value to vector
325        param[i] = scalar_value;
326    }
327}
328
329void
330objParamIn(Checkpoint *cp, const string &section,
331           const string &name, SimObject * &param)
332{
333    if (!cp->findObj(section, name, param)) {
334        fatal("Can't unserialize '%s:%s'\n", section, name);
335    }
336}
337
338
339#define INSTANTIATE_PARAM_TEMPLATES(type)                               \
340template void                                                           \
341paramOut(ostream &os, const string &name, type const &param);           \
342template void                                                           \
343paramIn(Checkpoint *cp, const string &section,                          \
344        const string &name, type & param);                              \
345template bool                                                           \
346optParamIn(Checkpoint *cp, const string &section,                       \
347        const string &name, type & param);                              \
348template void                                                           \
349arrayParamOut(ostream &os, const string &name,                          \
350              type const *param, unsigned size);                        \
351template void                                                           \
352arrayParamIn(Checkpoint *cp, const string &section,                     \
353             const string &name, type *param, unsigned size);           \
354template void                                                           \
355arrayParamOut(ostream &os, const string &name,                          \
356              const vector<type> &param);                               \
357template void                                                           \
358arrayParamIn(Checkpoint *cp, const string &section,                     \
359             const string &name, vector<type> &param);
360
361INSTANTIATE_PARAM_TEMPLATES(char)
362INSTANTIATE_PARAM_TEMPLATES(signed char)
363INSTANTIATE_PARAM_TEMPLATES(unsigned char)
364INSTANTIATE_PARAM_TEMPLATES(signed short)
365INSTANTIATE_PARAM_TEMPLATES(unsigned short)
366INSTANTIATE_PARAM_TEMPLATES(signed int)
367INSTANTIATE_PARAM_TEMPLATES(unsigned int)
368INSTANTIATE_PARAM_TEMPLATES(signed long)
369INSTANTIATE_PARAM_TEMPLATES(unsigned long)
370INSTANTIATE_PARAM_TEMPLATES(signed long long)
371INSTANTIATE_PARAM_TEMPLATES(unsigned long long)
372INSTANTIATE_PARAM_TEMPLATES(bool)
373INSTANTIATE_PARAM_TEMPLATES(float)
374INSTANTIATE_PARAM_TEMPLATES(double)
375INSTANTIATE_PARAM_TEMPLATES(string)
376
377
378/////////////////////////////
379
380/// Container for serializing global variables (not associated with
381/// any serialized object).
382class Globals : public Serializable
383{
384  public:
385    const string name() const;
386    void serialize(ostream &os);
387    void unserialize(Checkpoint *cp);
388};
389
390/// The one and only instance of the Globals class.
391Globals globals;
392
393const string
394Globals::name() const
395{
396    return "Globals";
397}
398
399void
400Globals::serialize(ostream &os)
401{
402    nameOut(os);
403    SERIALIZE_SCALAR(curTick());
404
405    nameOut(os, "MainEventQueue");
406    mainEventQueue.serialize(os);
407}
408
409void
410Globals::unserialize(Checkpoint *cp)
411{
412    const string &section = name();
413    Tick tick;
414    paramIn(cp, section, "curTick", tick);
415    curTick(tick);
416
417    mainEventQueue.unserialize(cp, "MainEventQueue");
418}
419
420Serializable::Serializable()
421{
422}
423
424Serializable::~Serializable()
425{
426}
427
428void
429Serializable::serialize(ostream &os)
430{
431}
432
433void
434Serializable::unserialize(Checkpoint *cp, const string &section)
435{
436}
437
438void
439Serializable::serializeAll(const string &cpt_dir)
440{
441    string dir = Checkpoint::setDir(cpt_dir);
442    if (mkdir(dir.c_str(), 0775) == -1 && errno != EEXIST)
443            fatal("couldn't mkdir %s\n", dir);
444
445    string cpt_file = dir + Checkpoint::baseFilename;
446    ofstream outstream(cpt_file.c_str());
447    time_t t = time(NULL);
448    if (!outstream.is_open())
449        fatal("Unable to open file %s for writing\n", cpt_file.c_str());
450    outstream << "## checkpoint generated: " << ctime(&t);
451
452    globals.serialize(outstream);
453    SimObject::serializeAll(outstream);
454}
455
456void
457Serializable::unserializeGlobals(Checkpoint *cp)
458{
459    globals.unserialize(cp);
460}
461
462void
463debug_serialize(const string &cpt_dir)
464{
465    Serializable::serializeAll(cpt_dir);
466}
467
468
469////////////////////////////////////////////////////////////////////////
470//
471// SerializableClass member definitions
472//
473////////////////////////////////////////////////////////////////////////
474
475// Map of class names to SerializableBuilder creation functions.
476// Need to make this a pointer so we can force initialization on the
477// first reference; otherwise, some SerializableClass constructors
478// may be invoked before the classMap constructor.
479map<string, SerializableClass::CreateFunc> *SerializableClass::classMap = 0;
480
481// SerializableClass constructor: add mapping to classMap
482SerializableClass::SerializableClass(const string &className,
483                                     CreateFunc createFunc)
484{
485    if (classMap == NULL)
486        classMap = new map<string, SerializableClass::CreateFunc>();
487
488    if ((*classMap)[className])
489        fatal("Error: simulation object class %s redefined\n", className);
490
491    // add className --> createFunc to class map
492    (*classMap)[className] = createFunc;
493}
494
495//
496//
497Serializable *
498SerializableClass::createObject(Checkpoint *cp, const string &section)
499{
500    string className;
501
502    if (!cp->find(section, "type", className)) {
503        fatal("Serializable::create: no 'type' entry in section '%s'.\n",
504              section);
505    }
506
507    CreateFunc createFunc = (*classMap)[className];
508
509    if (createFunc == NULL) {
510        fatal("Serializable::create: no create function for class '%s'.\n",
511              className);
512    }
513
514    Serializable *object = createFunc(cp, section);
515
516    assert(object != NULL);
517
518    return object;
519}
520
521
522Serializable *
523Serializable::create(Checkpoint *cp, const string &section)
524{
525    Serializable *object = SerializableClass::createObject(cp, section);
526    object->unserialize(cp, section);
527    return object;
528}
529
530
531const char *Checkpoint::baseFilename = "m5.cpt";
532
533string Checkpoint::currentDirectory;
534
535string
536Checkpoint::setDir(const string &name)
537{
538    // use csprintf to insert curTick() into directory name if it
539    // appears to have a format placeholder in it.
540    currentDirectory = (name.find("%") != string::npos) ?
541        csprintf(name, curTick()) : name;
542    if (currentDirectory[currentDirectory.size() - 1] != '/')
543        currentDirectory += "/";
544    return currentDirectory;
545}
546
547string
548Checkpoint::dir()
549{
550    return currentDirectory;
551}
552
553
554Checkpoint::Checkpoint(const string &cpt_dir)
555    : db(new IniFile), cptDir(setDir(cpt_dir))
556{
557    string filename = cptDir + "/" + Checkpoint::baseFilename;
558    if (!db->load(filename)) {
559        fatal("Can't load checkpoint file '%s'\n", filename);
560    }
561}
562
563
564bool
565Checkpoint::find(const string &section, const string &entry, string &value)
566{
567    return db->find(section, entry, value);
568}
569
570
571bool
572Checkpoint::findObj(const string &section, const string &entry,
573                    SimObject *&value)
574{
575    string path;
576
577    if (!db->find(section, entry, path))
578        return false;
579
580    value = resolveSimObject(path);
581    return true;
582}
583
584
585bool
586Checkpoint::sectionExists(const string &section)
587{
588    return db->sectionExists(section);
589}
590