Don't schedule tickEvent if it's already been scheduled.
[gem5.git] / sim / serialize.cc
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 "base/misc.hh"
37
38 #include "sim/eventq.hh"
39 #include "sim/param.hh"
40 #include "sim/serialize.hh"
41 #include "base/inifile.hh"
42 #include "sim/sim_events.hh"
43 #include "sim/sim_object.hh"
44 #include "base/trace.hh"
45
46 using namespace std;
47
48 Serializer *Serializeable::serializer = NULL;
49
50 Serializeable::Serializeable(const string &n)
51 : proxy(this), objName(n), serialized(false)
52 { }
53
54 Serializeable::~Serializeable()
55 { }
56
57 void
58 Serializeable::mark()
59 {
60 if (!serialized)
61 serializer->add_object(this);
62
63 serialized = true;
64 }
65
66 ostream &
67 Serializeable::out() const
68 {
69 return serializer->out();
70 }
71
72 void
73 Serializeable::nameOut()
74 {
75 out() << "\n[" << name() << "]\n";
76 }
77
78 void
79 Serializeable::nameOut(const string &_name)
80 {
81 out() << "\n[" << _name << "]\n";
82 }
83
84 template<> void
85 Serializeable::paramOut(const string &name, const uint64_t& param)
86 {
87 out() << name << "=0x" << hex << param << dec << "\n";
88 }
89
90 void
91 Serializeable::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
100 void
101 Serializeable::setName(const string &name)
102 {
103 if (objName != "")
104 panic("Cannot change object name");
105
106 objName = name;
107 }
108
109 Serializer::Serializer()
110 { }
111
112 Serializer::~Serializer()
113 { }
114
115 ostream &
116 Serializer::out() const
117 {
118 if (!output)
119 panic("must set output before serializing");
120
121 return *output;
122 }
123
124 void
125 Serializer::add_object(Serializeable *obj)
126 {
127 objects.push_back(obj);
128 }
129
130 void
131 Serializer::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
144 void
145 Serializer::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
195 class 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
208 SerializeEvent::SerializeEvent(EventQueue *q, Tick when, const string &f)
209 : Event(q), file(f)
210 {
211 setFlags(AutoDelete);
212 schedule(when);
213 }
214
215 SerializeEvent::~SerializeEvent()
216 {
217 }
218
219 void
220 SerializeEvent::process()
221 {
222 Serializer serial;
223 serial.serialize(file);
224 new SimExitEvent("Serialization caused exit");
225 }
226
227 void
228 SerializeEvent::serialize()
229 {
230 panic("Cannot serialize the SerializeEvent");
231 }
232
233 class SerializeParamContext : public ParamContext
234 {
235 private:
236 SerializeEvent *event;
237
238 public:
239 SerializeParamContext(const string &section);
240 ~SerializeParamContext();
241 void checkParams();
242 };
243
244 SerializeParamContext serialParams("serialize");
245
246 Param<Counter> serialize_cycle(&serialParams,
247 "cycle",
248 "cycle to serialize",
249 0);
250
251 Param<string> serialize_file(&serialParams,
252 "file",
253 "file to write to", "");
254
255 SerializeParamContext::SerializeParamContext(const string &section)
256 : ParamContext(section), event(NULL)
257 { }
258
259 SerializeParamContext::~SerializeParamContext()
260 {
261 }
262
263 void
264 SerializeParamContext::checkParams()
265 {
266 if (!((string)serialize_file).empty() && serialize_cycle > 0)
267 event = new SerializeEvent(&mainEventQueue, serialize_cycle,
268 serialize_file);
269 }
270
271 void
272 debug_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.
292 map<string,SerializeableClass::CreateFunc> *SerializeableClass::classMap = 0;
293
294 // SerializeableClass constructor: add mapping to classMap
295 SerializeableClass::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 //
315 Serializeable *
316 SerializeableClass::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