serialize.cc revision 2
1/*
2 * Copyright (c) 2003 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <sys/time.h>
30
31#include <fstream>
32#include <list>
33#include <string>
34#include <vector>
35
36#include "misc.hh"
37
38#include "eventq.hh"
39#include "param.hh"
40#include "serialize.hh"
41#include "inifile.hh"
42#include "sim_events.hh"
43#include "sim_object.hh"
44#include "trace.hh"
45
46using namespace std;
47
48Serializer *Serializeable::serializer = NULL;
49
50Serializeable::Serializeable(const string &n)
51    : proxy(this), objName(n), serialized(false)
52{ }
53
54Serializeable::~Serializeable()
55{ }
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