serialize.cc revision 56
15450Sgblack@eecs.umich.edu/*
25450Sgblack@eecs.umich.edu * Copyright (c) 2003 The Regents of The University of Michigan
35450Sgblack@eecs.umich.edu * All rights reserved.
47087Snate@binkert.org *
57087Snate@binkert.org * Redistribution and use in source and binary forms, with or without
67087Snate@binkert.org * modification, are permitted provided that the following conditions are
77087Snate@binkert.org * met: redistributions of source code must retain the above copyright
87087Snate@binkert.org * notice, this list of conditions and the following disclaimer;
97087Snate@binkert.org * redistributions in binary form must reproduce the above copyright
107087Snate@binkert.org * notice, this list of conditions and the following disclaimer in the
117087Snate@binkert.org * documentation and/or other materials provided with the distribution;
125450Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its
137087Snate@binkert.org * contributors may be used to endorse or promote products derived from
147087Snate@binkert.org * this software without specific prior written permission.
157087Snate@binkert.org *
167087Snate@binkert.org * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
177087Snate@binkert.org * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
187087Snate@binkert.org * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
197087Snate@binkert.org * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
207087Snate@binkert.org * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
215450Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
227087Snate@binkert.org * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
235450Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
245450Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
255450Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
265450Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
275450Sgblack@eecs.umich.edu */
285450Sgblack@eecs.umich.edu
295450Sgblack@eecs.umich.edu#include <sys/time.h>
305450Sgblack@eecs.umich.edu
315450Sgblack@eecs.umich.edu#include <fstream>
325450Sgblack@eecs.umich.edu#include <list>
335450Sgblack@eecs.umich.edu#include <string>
345450Sgblack@eecs.umich.edu#include <vector>
355450Sgblack@eecs.umich.edu
365450Sgblack@eecs.umich.edu#include "base/misc.hh"
375450Sgblack@eecs.umich.edu
385450Sgblack@eecs.umich.edu#include "sim/eventq.hh"
395450Sgblack@eecs.umich.edu#include "sim/param.hh"
405450Sgblack@eecs.umich.edu#include "sim/serialize.hh"
415450Sgblack@eecs.umich.edu#include "base/inifile.hh"
425450Sgblack@eecs.umich.edu#include "sim/sim_events.hh"
435610Snate@binkert.org#include "sim/sim_object.hh"
449338SAndreas.Sandberg@arm.com#include "base/trace.hh"
455450Sgblack@eecs.umich.edu
465450Sgblack@eecs.umich.eduusing namespace std;
475450Sgblack@eecs.umich.edu
485450Sgblack@eecs.umich.eduSerializer *Serializeable::serializer = NULL;
495450Sgblack@eecs.umich.edu
505450Sgblack@eecs.umich.eduSerializeable::Serializeable(const string &n)
515450Sgblack@eecs.umich.edu    : proxy(this), objName(n), serialized(false)
525610Snate@binkert.org{ }
539338SAndreas.Sandberg@arm.com
545450Sgblack@eecs.umich.eduSerializeable::~Serializeable()
558323Ssteve.reinhardt@amd.com{ }
56
57void
58Serializeable::mark()
59{
60    if (!serialized)
61        serializer->add_object(this);
62
63    serialized = true;
64}
65
66ostream &
67Serializeable::out() const
68{
69    return serializer->out();
70}
71
72void
73Serializeable::nameOut()
74{
75    out() << "\n[" << name() << "]\n";
76}
77
78void
79Serializeable::nameOut(const string &_name)
80{
81    out() << "\n[" << _name << "]\n";
82}
83
84template<> void
85Serializeable::paramOut(const string &name, const uint64_t& param)
86{
87    out() << name << "=0x" << hex << param << dec << "\n";
88}
89
90void
91Serializeable::childOut(const string &name, Serializeable *child)
92{
93    child->mark();
94    if (child->name() == "")
95        panic("child is unnamed");
96
97    out() << name << "=" << child->name() << "\n";
98}
99
100void
101Serializeable::setName(const string &name)
102{
103    if (objName != "")
104        panic("Cannot change object name");
105
106    objName = name;
107}
108
109Serializer::Serializer()
110{ }
111
112Serializer::~Serializer()
113{ }
114
115ostream &
116Serializer::out() const
117{
118    if (!output)
119        panic("must set output before serializing");
120
121    return *output;
122}
123
124void
125Serializer::add_object(Serializeable *obj)
126{
127    objects.push_back(obj);
128}
129
130void
131Serializer::add_objects()
132{
133    mainEventQueue.mark();
134
135    SimObject::SimObjectList::iterator i = SimObject::simObjectList.begin();
136    SimObject::SimObjectList::iterator end = SimObject::simObjectList.end();
137
138    while (i != end) {
139        (*i)->mark();
140        ++i;
141    }
142}
143
144void
145Serializer::serialize(const string &f)
146{
147    if (Serializeable::serializer != NULL)
148        panic("in process of serializing!");
149
150    Serializeable::serializer = this;
151
152    file = f;
153    string cpt_file = file + ".cpt";
154    output = new ofstream(cpt_file.c_str());
155    time_t t = time(NULL);
156    *output << "// checkpoint generated: " << ctime(&t);
157
158    serlist_t list;
159
160    add_objects();
161    while (!objects.empty()) {
162        Serializeable *serial = objects.front();
163        DPRINTF(Serialize, "Name Children of %s\n", serial->name());
164        serial->nameChildren();
165        objects.pop_front();
166        list.push_back(serial);
167    }
168
169    while (!list.empty()) {
170        list.front()->serialized = false;
171        list.pop_front();
172    }
173
174    add_objects();
175    while (!objects.empty()) {
176        Serializeable *serial = objects.front();
177        DPRINTF(Serialize, "Name Children of %s\n", serial->name());
178        serial->serialize();
179        objects.pop_front();
180        list.push_back(serial);
181    }
182
183    while (!list.empty()) {
184        list.front()->serialized = false;
185        list.pop_front();
186    }
187
188    Serializeable::serializer = NULL;
189
190    delete output;
191    output = NULL;
192    file = "";
193}
194
195class SerializeEvent : public Event
196{
197  protected:
198    string file;
199
200  public:
201    SerializeEvent(EventQueue *q, Tick when, const string &file);
202    ~SerializeEvent();
203
204    virtual void process();
205    virtual void serialize();
206};
207
208SerializeEvent::SerializeEvent(EventQueue *q, Tick when, const string &f)
209    : Event(q), file(f)
210{
211    setFlags(AutoDelete);
212    schedule(when);
213}
214
215SerializeEvent::~SerializeEvent()
216{
217}
218
219void
220SerializeEvent::process()
221{
222    Serializer serial;
223    serial.serialize(file);
224    new SimExitEvent("Serialization caused exit");
225}
226
227void
228SerializeEvent::serialize()
229{
230    panic("Cannot serialize the SerializeEvent");
231}
232
233class SerializeParamContext : public ParamContext
234{
235  private:
236    SerializeEvent *event;
237
238  public:
239    SerializeParamContext(const string &section);
240    ~SerializeParamContext();
241    void checkParams();
242};
243
244SerializeParamContext serialParams("serialize");
245
246Param<Counter> serialize_cycle(&serialParams,
247                                "cycle",
248                                "cycle to serialize",
249                                0);
250
251Param<string> serialize_file(&serialParams,
252                             "file",
253                             "file to write to", "");
254
255SerializeParamContext::SerializeParamContext(const string &section)
256    : ParamContext(section), event(NULL)
257{ }
258
259SerializeParamContext::~SerializeParamContext()
260{
261}
262
263void
264SerializeParamContext::checkParams()
265{
266    if (!((string)serialize_file).empty() && serialize_cycle > 0)
267    event = new SerializeEvent(&mainEventQueue, serialize_cycle,
268                               serialize_file);
269}
270
271void
272debug_serialize(const char *file)
273{
274    Serializer serial;
275    serial.serialize(file);
276    new SimExitEvent("Serialization caused exit");
277}
278
279
280
281
282////////////////////////////////////////////////////////////////////////
283//
284// SerializeableClass member definitions
285//
286////////////////////////////////////////////////////////////////////////
287
288// Map of class names to SerializeableBuilder creation functions.
289// Need to make this a pointer so we can force initialization on the
290// first reference; otherwise, some SerializeableClass constructors
291// may be invoked before the classMap constructor.
292map<string,SerializeableClass::CreateFunc> *SerializeableClass::classMap = 0;
293
294// SerializeableClass constructor: add mapping to classMap
295SerializeableClass::SerializeableClass(const string &className,
296                                       CreateFunc createFunc)
297{
298    if (classMap == NULL)
299        classMap = new map<string,SerializeableClass::CreateFunc>();
300
301    if ((*classMap)[className])
302    {
303        cerr << "Error: simulation object class " << className << " redefined"
304             << endl;
305        fatal("");
306    }
307
308    // add className --> createFunc to class map
309    (*classMap)[className] = createFunc;
310}
311
312
313//
314//
315Serializeable *
316SerializeableClass::createObject(IniFile &configDB,
317                                 const string &configClassName)
318{
319    // find simulation object class name from configuration class
320    // (specified by 'type=' parameter)
321    string simObjClassName;
322
323    if (!configDB.findDefault(configClassName, "type", simObjClassName)) {
324        cerr << "Configuration class '" << configClassName << "' not found."
325             << endl;
326        abort();
327    }
328
329    // look up className to get appropriate createFunc
330    if (classMap->find(simObjClassName) == classMap->end()) {
331        cerr << "Simulator object class '" << simObjClassName << "' not found."
332             << endl;
333        abort();
334    }
335
336    CreateFunc createFunc = (*classMap)[simObjClassName];
337
338    // builder instance
339    SerializeableBuilder *objectBuilder = (*createFunc)();
340
341    assert(objectBuilder != NULL);
342
343    // now create the actual simulation object
344    Serializeable *object = objectBuilder->create();
345
346    assert(object != NULL);
347
348    // done with the SerializeableBuilder now
349    delete objectBuilder;
350
351    return object;
352}
353
354