Merge zizzer.eecs.umich.edu:/m5/Bitkeeper/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 #include "base/str.hh"
38
39 #include "sim/eventq.hh"
40 #include "sim/param.hh"
41 #include "sim/serialize.hh"
42 #include "base/inifile.hh"
43 #include "sim/sim_events.hh"
44 #include "sim/sim_object.hh"
45 #include "base/trace.hh"
46 #include "sim/config_node.hh"
47
48 using namespace std;
49
50 Serializer *Serializeable::serializer = NULL;
51
52 Serializeable::Serializeable()
53 : serialized(false)
54 { }
55
56 Serializeable::~Serializeable()
57 { }
58
59 void
60 Serializeable::mark()
61 {
62 if (!serialized)
63 serializer->add_object(this);
64
65 serialized = true;
66 }
67
68 void
69 Serializeable::nameOut(ostream &os)
70 {
71 os << "\n[" << name() << "]\n";
72 }
73
74 void
75 Serializeable::nameOut(ostream &os, const string &_name)
76 {
77 os << "\n[" << _name << "]\n";
78 }
79
80 template <class T>
81 void
82 paramOut(ostream &os, const std::string &name, const T& param)
83 {
84 os << name << "=";
85 showParam(os, param);
86 os << "\n";
87 }
88
89
90 template <class T>
91 void
92 paramIn(Checkpoint *cp, const std::string &section,
93 const std::string &name, T& param)
94 {
95 std::string str;
96 if (!cp->find(section, name, str) || !parseParam(str, param)) {
97 fatal("Can't unserialize '%s:%s'\n", section, name);
98 }
99 }
100
101
102 template <class T>
103 void
104 arrayParamOut(ostream &os, const std::string &name,
105 const T *param, int size)
106 {
107 os << name << "=";
108 if (size > 0)
109 showParam(os, param[0]);
110 for (int i = 1; i < size; ++i) {
111 os << " ";
112 showParam(os, param[i]);
113 }
114 os << "\n";
115 }
116
117
118 template <class T>
119 void
120 arrayParamIn(Checkpoint *cp, const std::string &section,
121 const std::string &name, T *param, int size)
122 {
123 std::string str;
124 if (!cp->find(section, name, str)) {
125 fatal("Can't unserialize '%s:%s'\n", section, name);
126 }
127
128 // code below stolen from VectorParam<T>::parse().
129 // it would be nice to unify these somehow...
130
131 vector<string> tokens;
132
133 tokenize(tokens, str, ' ');
134
135 // Need this if we were doing a vector
136 // value.resize(tokens.size());
137
138 if (tokens.size() != size) {
139 fatal("Array size mismatch on %s:%s'\n", section, name);
140 }
141
142 for (int i = 0; i < tokens.size(); i++) {
143 // need to parse into local variable to handle vector<bool>,
144 // for which operator[] returns a special reference class
145 // that's not the same as 'bool&', (since it's a packed
146 // vector)
147 T scalar_value;
148 if (!parseParam(tokens[i], scalar_value)) {
149 string err("could not parse \"");
150
151 err += str;
152 err += "\"";
153
154 fatal(err);
155 }
156
157 // assign parsed value to vector
158 param[i] = scalar_value;
159 }
160 }
161
162
163 void
164 objParamIn(Checkpoint *cp, const std::string &section,
165 const std::string &name, Serializeable * &param)
166 {
167 if (!cp->findObj(section, name, param)) {
168 fatal("Can't unserialize '%s:%s'\n", section, name);
169 }
170 }
171
172
173 #define INSTANTIATE_PARAM_TEMPLATES(type) \
174 template void \
175 paramOut(ostream &os, const std::string &name, type const &param); \
176 template void \
177 paramIn(Checkpoint *cp, const std::string &section, \
178 const std::string &name, type & param); \
179 template void \
180 arrayParamOut(ostream &os, const std::string &name, \
181 type const *param, int size); \
182 template void \
183 arrayParamIn(Checkpoint *cp, const std::string &section, \
184 const std::string &name, type *param, int size);
185
186
187 INSTANTIATE_PARAM_TEMPLATES(int8_t)
188 INSTANTIATE_PARAM_TEMPLATES(uint8_t)
189 INSTANTIATE_PARAM_TEMPLATES(int16_t)
190 INSTANTIATE_PARAM_TEMPLATES(uint16_t)
191 INSTANTIATE_PARAM_TEMPLATES(int32_t)
192 INSTANTIATE_PARAM_TEMPLATES(uint32_t)
193 INSTANTIATE_PARAM_TEMPLATES(int64_t)
194 INSTANTIATE_PARAM_TEMPLATES(uint64_t)
195 INSTANTIATE_PARAM_TEMPLATES(bool)
196 INSTANTIATE_PARAM_TEMPLATES(string)
197
198
199 #if 0
200 // unneeded?
201 void
202 Serializeable::childOut(const string &name, Serializeable *child)
203 {
204 child->mark();
205 if (child->name() == "")
206 panic("child is unnamed");
207
208 out() << name << "=" << child->name() << "\n";
209 }
210 #endif
211
212 Serializer::Serializer()
213 { }
214
215 Serializer::~Serializer()
216 { }
217
218 ostream &
219 Serializer::out() const
220 {
221 if (!output)
222 panic("must set output before serializing");
223
224 return *output;
225 }
226
227 void
228 Serializer::add_object(Serializeable *obj)
229 {
230 objects.push_back(obj);
231 }
232
233 void
234 Serializer::add_objects()
235 {
236 mainEventQueue.mark();
237
238 SimObject::SimObjectList::iterator i = SimObject::simObjectList.begin();
239 SimObject::SimObjectList::iterator end = SimObject::simObjectList.end();
240
241 while (i != end) {
242 (*i)->mark();
243 ++i;
244 }
245 }
246
247 void
248 Serializer::serialize()
249 {
250 if (Serializeable::serializer != NULL)
251 panic("in process of serializing!");
252
253 Serializeable::serializer = this;
254
255 file = CheckpointFile();
256 string cpt_file = file + ".cpt";
257 output = new ofstream(cpt_file.c_str());
258 time_t t = time(NULL);
259 *output << "// checkpoint generated: " << ctime(&t);
260
261 serlist_t list;
262
263 add_objects();
264 while (!objects.empty()) {
265 Serializeable *obj = objects.front();
266 DPRINTF(Serialize, "Serializing %s\n", obj->name());
267 obj->nameOut(out());
268 obj->serialize(out());
269 objects.pop_front();
270 list.push_back(obj);
271 }
272
273 while (!list.empty()) {
274 list.front()->serialized = false;
275 list.pop_front();
276 }
277
278 Serializeable::serializer = NULL;
279
280 delete output;
281 output = NULL;
282 file = "";
283 }
284
285 class SerializeEvent : public Event
286 {
287 protected:
288 string file;
289 Tick repeat;
290
291 public:
292 SerializeEvent(Tick _when, Tick _repeat);
293 virtual void process();
294 virtual void serialize(std::ostream &os)
295 {
296 panic("Cannot serialize the SerializeEvent");
297 }
298
299 };
300
301 SerializeEvent::SerializeEvent(Tick _when, Tick _repeat)
302 : Event(&mainEventQueue, 990), repeat(_repeat)
303 {
304 setFlags(AutoDelete);
305 schedule(_when);
306 }
307
308 void
309 SerializeEvent::process()
310 {
311 Serializer serial;
312 serial.serialize();
313 if (repeat)
314 schedule(curTick + repeat);
315 }
316
317 string __CheckpointFileBase;
318
319 string
320 CheckpointFile()
321 {
322 if (__CheckpointFileBase.empty())
323 return __CheckpointFileBase;
324
325 return csprintf("%s.%d", __CheckpointFileBase, curTick);
326 }
327
328 void
329 SetupCheckpoint(Tick when, Tick period)
330 {
331 new SerializeEvent(when, period);
332 }
333
334 class SerializeParamContext : public ParamContext
335 {
336 private:
337 SerializeEvent *event;
338
339 public:
340 SerializeParamContext(const string &section);
341 ~SerializeParamContext();
342 void checkParams();
343 };
344
345 SerializeParamContext serialParams("serialize");
346
347 Param<string> serialize_file(&serialParams,
348 "file",
349 "file to write to", "m5");
350
351 Param<Counter> serialize_cycle(&serialParams,
352 "cycle",
353 "cycle to serialize",
354 0);
355
356 Param<Counter> serialize_period(&serialParams,
357 "period",
358 "period to repeat serializations",
359 0);
360
361
362
363 SerializeParamContext::SerializeParamContext(const string &section)
364 : ParamContext(section), event(NULL)
365 { }
366
367 SerializeParamContext::~SerializeParamContext()
368 {
369 }
370
371 void
372 SerializeParamContext::checkParams()
373 {
374 __CheckpointFileBase = serialize_file;
375 if (serialize_cycle > 0)
376 SetupCheckpoint(serialize_cycle, serialize_period);
377 }
378
379 void
380 debug_serialize()
381 {
382 Serializer serial;
383 serial.serialize();
384 }
385
386 void
387 debug_serialize(Tick when)
388 {
389 new SerializeEvent(when, 0);
390 }
391
392 ////////////////////////////////////////////////////////////////////////
393 //
394 // SerializeableClass member definitions
395 //
396 ////////////////////////////////////////////////////////////////////////
397
398 // Map of class names to SerializeableBuilder creation functions.
399 // Need to make this a pointer so we can force initialization on the
400 // first reference; otherwise, some SerializeableClass constructors
401 // may be invoked before the classMap constructor.
402 map<string,SerializeableClass::CreateFunc> *SerializeableClass::classMap = 0;
403
404 // SerializeableClass constructor: add mapping to classMap
405 SerializeableClass::SerializeableClass(const string &className,
406 CreateFunc createFunc)
407 {
408 if (classMap == NULL)
409 classMap = new map<string,SerializeableClass::CreateFunc>();
410
411 if ((*classMap)[className])
412 {
413 cerr << "Error: simulation object class " << className << " redefined"
414 << endl;
415 fatal("");
416 }
417
418 // add className --> createFunc to class map
419 (*classMap)[className] = createFunc;
420 }
421
422
423 //
424 //
425 Serializeable *
426 SerializeableClass::createObject(Checkpoint *cp,
427 const std::string &section)
428 {
429 string className;
430
431 if (!cp->find(section, "type", className)) {
432 fatal("Serializeable::create: no 'type' entry in section '%s'.\n",
433 section);
434 }
435
436 CreateFunc createFunc = (*classMap)[className];
437
438 if (createFunc == NULL) {
439 fatal("Serializeable::create: no create function for class '%s'.\n",
440 className);
441 }
442
443 Serializeable *object = createFunc(cp, section);
444
445 assert(object != NULL);
446
447 return object;
448 }
449
450
451 Serializeable *
452 Serializeable::create(Checkpoint *cp, const std::string &section)
453 {
454 Serializeable *object = SerializeableClass::createObject(cp, section);
455 object->unserialize(cp, section);
456 return object;
457 }
458
459
460 Checkpoint::Checkpoint(const std::string &filename, const std::string &path,
461 const ConfigNode *_configNode)
462 : db(new IniFile), basePath(path), configNode(_configNode)
463 {
464 if (!db->load(filename)) {
465 fatal("Can't load checkpoint file '%s'\n", filename);
466 }
467
468 mainEventQueue.unserialize(this, "MainEventQueue");
469 }
470
471
472 bool
473 Checkpoint::find(const std::string &section, const std::string &entry,
474 std::string &value)
475 {
476 return db->find(section, entry, value);
477 }
478
479
480 bool
481 Checkpoint::findObj(const std::string &section, const std::string &entry,
482 Serializeable *&value)
483 {
484 string path;
485
486 if (!db->find(section, entry, path))
487 return false;
488
489 if ((value = configNode->resolveSimObject(path)) != NULL)
490 return true;
491
492 if ((value = objMap[path]) != NULL)
493 return true;
494
495 return false;
496 }