Merge ehallnor@zizzer:/bk/m5 into zazzer.eecs.umich.edu:/z/ehallnor/m5
[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 cprintf("Renaming object '%s' to '%s'.\n", objName, name);
105 }
106
107 objName = name;
108 }
109
110 Serializer::Serializer()
111 { }
112
113 Serializer::~Serializer()
114 { }
115
116 ostream &
117 Serializer::out() const
118 {
119 if (!output)
120 panic("must set output before serializing");
121
122 return *output;
123 }
124
125 void
126 Serializer::add_object(Serializeable *obj)
127 {
128 objects.push_back(obj);
129 }
130
131 void
132 Serializer::add_objects()
133 {
134 mainEventQueue.mark();
135
136 SimObject::SimObjectList::iterator i = SimObject::simObjectList.begin();
137 SimObject::SimObjectList::iterator end = SimObject::simObjectList.end();
138
139 while (i != end) {
140 (*i)->mark();
141 ++i;
142 }
143 }
144
145 void
146 Serializer::serialize(const string &f)
147 {
148 if (Serializeable::serializer != NULL)
149 panic("in process of serializing!");
150
151 Serializeable::serializer = this;
152
153 file = f;
154 string cpt_file = file + ".cpt";
155 output = new ofstream(cpt_file.c_str());
156 time_t t = time(NULL);
157 *output << "// checkpoint generated: " << ctime(&t);
158
159 serlist_t list;
160
161 add_objects();
162 while (!objects.empty()) {
163 Serializeable *serial = objects.front();
164 DPRINTF(Serialize, "Naming children of %s\n", serial->name());
165 serial->nameChildren();
166 objects.pop_front();
167 list.push_back(serial);
168 }
169
170 while (!list.empty()) {
171 list.front()->serialized = false;
172 list.pop_front();
173 }
174
175 add_objects();
176 while (!objects.empty()) {
177 Serializeable *serial = objects.front();
178 DPRINTF(Serialize, "Serializing %s\n", serial->name());
179 serial->serialize();
180 objects.pop_front();
181 list.push_back(serial);
182 }
183
184 while (!list.empty()) {
185 list.front()->serialized = false;
186 list.pop_front();
187 }
188
189 Serializeable::serializer = NULL;
190
191 delete output;
192 output = NULL;
193 file = "";
194 }
195
196 class SerializeEvent : public Event
197 {
198 protected:
199 string file;
200
201 public:
202 SerializeEvent(EventQueue *q, Tick when, const string &file);
203 ~SerializeEvent();
204
205 virtual void process();
206 virtual void serialize();
207 };
208
209 SerializeEvent::SerializeEvent(EventQueue *q, Tick when, const string &f)
210 : Event(q), file(f)
211 {
212 setFlags(AutoDelete);
213 schedule(when);
214 }
215
216 SerializeEvent::~SerializeEvent()
217 {
218 }
219
220 void
221 SerializeEvent::process()
222 {
223 Serializer serial;
224 serial.serialize(file);
225 new SimExitEvent("Serialization caused exit");
226 }
227
228 void
229 SerializeEvent::serialize()
230 {
231 panic("Cannot serialize the SerializeEvent");
232 }
233
234 class SerializeParamContext : public ParamContext
235 {
236 private:
237 SerializeEvent *event;
238
239 public:
240 SerializeParamContext(const string &section);
241 ~SerializeParamContext();
242 void checkParams();
243 };
244
245 SerializeParamContext serialParams("serialize");
246
247 Param<Counter> serialize_cycle(&serialParams,
248 "cycle",
249 "cycle to serialize",
250 0);
251
252 Param<string> serialize_file(&serialParams,
253 "file",
254 "file to write to", "");
255
256 SerializeParamContext::SerializeParamContext(const string &section)
257 : ParamContext(section), event(NULL)
258 { }
259
260 SerializeParamContext::~SerializeParamContext()
261 {
262 }
263
264 void
265 SerializeParamContext::checkParams()
266 {
267 if (!((string)serialize_file).empty() && serialize_cycle > 0)
268 event = new SerializeEvent(&mainEventQueue, serialize_cycle,
269 serialize_file);
270 }
271
272 void
273 debug_serialize(const char *file)
274 {
275 Serializer serial;
276 serial.serialize(file);
277 new SimExitEvent("Serialization caused exit");
278 }
279
280
281
282
283 ////////////////////////////////////////////////////////////////////////
284 //
285 // SerializeableClass member definitions
286 //
287 ////////////////////////////////////////////////////////////////////////
288
289 // Map of class names to SerializeableBuilder creation functions.
290 // Need to make this a pointer so we can force initialization on the
291 // first reference; otherwise, some SerializeableClass constructors
292 // may be invoked before the classMap constructor.
293 map<string,SerializeableClass::CreateFunc> *SerializeableClass::classMap = 0;
294
295 // SerializeableClass constructor: add mapping to classMap
296 SerializeableClass::SerializeableClass(const string &className,
297 CreateFunc createFunc)
298 {
299 if (classMap == NULL)
300 classMap = new map<string,SerializeableClass::CreateFunc>();
301
302 if ((*classMap)[className])
303 {
304 cerr << "Error: simulation object class " << className << " redefined"
305 << endl;
306 fatal("");
307 }
308
309 // add className --> createFunc to class map
310 (*classMap)[className] = createFunc;
311 }
312
313
314 //
315 //
316 Serializeable *
317 SerializeableClass::createObject(IniFile &configDB,
318 const string &configClassName)
319 {
320 // find simulation object class name from configuration class
321 // (specified by 'type=' parameter)
322 string simObjClassName;
323
324 if (!configDB.findDefault(configClassName, "type", simObjClassName)) {
325 cerr << "Configuration class '" << configClassName << "' not found."
326 << endl;
327 abort();
328 }
329
330 // look up className to get appropriate createFunc
331 if (classMap->find(simObjClassName) == classMap->end()) {
332 cerr << "Simulator object class '" << simObjClassName << "' not found."
333 << endl;
334 abort();
335 }
336
337 CreateFunc createFunc = (*classMap)[simObjClassName];
338
339 // builder instance
340 SerializeableBuilder *objectBuilder = (*createFunc)();
341
342 assert(objectBuilder != NULL);
343
344 // now create the actual simulation object
345 Serializeable *object = objectBuilder->create();
346
347 assert(object != NULL);
348
349 // done with the SerializeableBuilder now
350 delete objectBuilder;
351
352 return object;
353 }
354