arch, base, sim: Replace Copy(String)?(In|Out) with equivalent code.
[gem5.git] / src / base / cp_annotate.cc
1 /*
2 * Copyright (c) 2006-2009 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 * Authors: Ali Saidi
29 */
30
31 #include "base/cp_annotate.hh"
32
33 #include "arch/generic/linux/threadinfo.hh"
34 #include "arch/utility.hh"
35 #include "base/callback.hh"
36 #include "base/loader/object_file.hh"
37 #include "base/output.hh"
38 #include "base/trace.hh"
39 #include "config/the_isa.hh"
40 #include "cpu/thread_context.hh"
41 #include "debug/Annotate.hh"
42 #include "debug/AnnotateVerbose.hh"
43 #include "sim/arguments.hh"
44 #include "sim/core.hh"
45 #include "sim/sim_exit.hh"
46 #include "sim/system.hh"
47
48 struct CPAIgnoreSymbol
49 {
50 const char *symbol;
51 size_t len;
52 };
53 #define CPA_IGNORE_SYMBOL(sym) { #sym, sizeof(#sym) }
54
55 CPAIgnoreSymbol ignoreSymbols[] = {
56 CPA_IGNORE_SYMBOL("m5a_"),
57 CPA_IGNORE_SYMBOL("ret_from_sys_call"),
58 CPA_IGNORE_SYMBOL("ret_from_reschedule"),
59 CPA_IGNORE_SYMBOL("_spin_"),
60 CPA_IGNORE_SYMBOL("local_bh_"),
61 CPA_IGNORE_SYMBOL("restore_all"),
62 CPA_IGNORE_SYMBOL("Call_Pal_"),
63 CPA_IGNORE_SYMBOL("pal_post_interrupt"),
64 CPA_IGNORE_SYMBOL("rti_to_"),
65 CPA_IGNORE_SYMBOL("sys_int_2"),
66 CPA_IGNORE_SYMBOL("sys_interrupt"),
67 CPA_IGNORE_SYMBOL("normal_int"),
68 CPA_IGNORE_SYMBOL("TRAP_INTERRUPT_10_"),
69 CPA_IGNORE_SYMBOL("Trap_Interrupt"),
70 CPA_IGNORE_SYMBOL("do_entInt"),
71 CPA_IGNORE_SYMBOL("__do_softirq"),
72 CPA_IGNORE_SYMBOL("_end"),
73 CPA_IGNORE_SYMBOL("entInt"),
74 CPA_IGNORE_SYMBOL("entSys"),
75 {0,0}
76 };
77 #undef CPA_IGNORE_SYMBOL
78
79 using namespace std;
80 using namespace TheISA;
81
82 bool CPA::exists;
83 CPA *CPA::_cpa;
84
85 class AnnotateDumpCallback : public Callback
86 {
87
88 private:
89 CPA *cpa;
90 public:
91 virtual void process();
92 AnnotateDumpCallback(CPA *_cpa)
93 : cpa(_cpa)
94 {}
95 };
96
97 void
98 AnnotateDumpCallback::process()
99 {
100 cpa->dump(true);
101 cpa->dumpKey();
102 }
103
104
105 CPA::CPA(Params *p)
106 : SimObject(p), numSm(0), numSmt(0), numSys(0), numQs(0), conId(0)
107 {
108 if (exists)
109 fatal("Multiple annotation objects found in system");
110 exists = true;
111
112 _enabled = p->enabled;
113 _cpa = this;
114
115 vector<string>::iterator i;
116 i = p->user_apps.begin();
117
118 while (i != p->user_apps.end()) {
119 ObjectFile *of = createObjectFile(*i);
120 string sf;
121 if (!of)
122 fatal("Couldn't load symbols from file: %s\n", *i);
123 sf = *i;
124 sf.erase(0, sf.rfind('/') + 1);;
125 DPRINTFN("file %s short: %s\n", *i, sf);
126 userApp[sf] = new SymbolTable;
127 bool result1 = of->loadGlobalSymbols(userApp[sf]);
128 bool result2 = of->loadLocalSymbols(userApp[sf]);
129 if (!result1 || !result2)
130 panic("blah");
131 assert(result1 && result2);
132 i++;
133 }
134 }
135
136 void
137 CPA::startup()
138 {
139 osbin = simout.create("annotate.bin", true);
140 // MAGIC version number 'M''5''A'N' + version/capabilities
141 ah.version = 0x4D35414E00000101ULL;
142 ah.num_recs = 0;
143 ah.key_off = 0;
144 osbin->write((char*)&ah, sizeof(AnnotateHeader));
145
146 registerExitCallback(new AnnotateDumpCallback(this));
147 }
148
149 uint64_t
150 CPA::getFrame(ThreadContext *tc)
151 {
152 // This code is ISA specific and will need to be changed
153 // if the annotation code is used for something other than Alpha
154 return (tc->readMiscRegNoEffect(TheISA::IPR_PALtemp23) &
155 ~ULL(0x3FFF));
156
157 }
158
159 void
160 CPA::swSmBegin(ThreadContext *tc)
161 {
162 if (!enabled())
163 return;
164
165 Arguments args(tc);
166 std::string st;
167 Addr junk;
168 char sm[50];
169 if (!TheISA::inUserMode(tc))
170 debugSymbolTable->findNearestSymbol(
171 tc->readIntReg(ReturnAddressReg), st, junk);
172
173 tc->getVirtProxy().readString(sm, args[0], 50);
174 System *sys = tc->getSystemPtr();
175 StringWrap name(sys->name());
176
177 if (!sm[0])
178 warn("Got null SM at tick %d\n", curTick());
179
180 int sysi = getSys(sys);
181 int smi = getSm(sysi, sm, args[1]);
182 DPRINTF(Annotate, "Starting machine: %s(%d) sysi: %d id: %#x\n", sm,
183 smi, sysi, args[1]);
184 DPRINTF(Annotate, "smMap[%d] = %d, %s, %#x\n", smi,
185 smMap[smi-1].first, smMap[smi-1].second.first,
186 smMap[smi-1].second.second);
187
188 uint64_t frame = getFrame(tc);
189 StackId sid = StackId(sysi, frame);
190
191 // check if we need to link to the previous state machine
192 int flags = args[2];
193 if (flags & FL_LINK) {
194 if (smStack[sid].size()) {
195 int prev_smi = smStack[sid].back();
196 DPRINTF(Annotate, "Linking from %d to state machine %s(%d) [%#x]\n",
197 prev_smi, sm, smi, args[1]);
198
199 if (lnMap[smi])
200 DPRINTF(Annotate, "LnMap already contains entry for %d of %d\n",
201 smi, lnMap[smi]);
202 assert(lnMap[smi] == 0);
203 lnMap[smi] = prev_smi;
204
205 add(OP_LINK, FL_NONE, tc->contextId(), prev_smi, smi);
206 } else {
207 DPRINTF(Annotate, "Not Linking to state machine %s(%d) [%#x]\n",
208 sm, smi, args[1]);
209 }
210 }
211
212
213 smStack[sid].push_back(smi);
214
215 DPRINTF(Annotate, "Stack Now (%#X):\n", frame);
216 for (int x = smStack[sid].size()-1; x >= 0; x--)
217 DPRINTF(Annotate, "-- %d\n", smStack[sid][x]);
218
219 // reset the sw state exculsion to false
220 if (swExpl[sid])
221 swExpl[sid] = false;
222
223
224 Id id = Id(sm, frame);
225 if (scLinks[sysi-1][id]) {
226 AnnDataPtr an = scLinks[sysi-1][id];
227 scLinks[sysi-1].erase(id);
228 an->stq = smi;
229 an->dump = true;
230 DPRINTF(Annotate,
231 "Found prev unknown linking from %d to state machine %s(%d)\n",
232 an->sm, sm, smi);
233
234 if (lnMap[smi])
235 DPRINTF(Annotate, "LnMap already contains entry for %d of %d\n",
236 smi, lnMap[smi]);
237 assert(lnMap[smi] == 0);
238 lnMap[smi] = an->sm;
239 }
240
241 // add a new begin ifwe have that info
242 if (st != "") {
243 DPRINTF(Annotate, "st: %s smi: %d stCache.size %d\n", st,
244 smi, stCache.size());
245 int sti = getSt(sm, st);
246 lastState[smi] = sti;
247 add(OP_BEGIN, FL_NONE, tc->contextId(), smi, sti);
248 }
249 }
250
251 void
252 CPA::swSmEnd(ThreadContext *tc)
253 {
254 if (!enabled())
255 return;
256
257 Arguments args(tc);
258 char sm[50];
259 tc->getVirtProxy().readString(sm, args[0], 50);
260 System *sys = tc->getSystemPtr();
261 doSwSmEnd(sys, tc->contextId(), sm, getFrame(tc));
262 }
263
264 void
265 CPA::doSwSmEnd(System *sys, int cpuid, string sm, uint64_t frame)
266 {
267 int sysi = getSys(sys);
268 StackId sid = StackId(sysi, frame);
269
270
271 // reset the sw state exculsion to false
272 if (swExpl[sid])
273 swExpl[sid] = false;
274
275
276 int smib = smStack[sid].back();
277 StringWrap name(sys->name());
278 DPRINTF(Annotate, "Ending machine: %s[%d, %#x] (%d?)\n", sm, sysi,
279 frame, smib);
280
281 if (!smStack[sid].size() || smMap[smib-1].second.first != sm) {
282 DPRINTF(Annotate, "State Machine not unwinding correctly. sid: %d, %#x"
283 " top of stack: %s Current Stack:\n",
284 sysi, frame, smMap[smib-1].second.first);
285 for (int x = smStack[sid].size()-1; x >= 0; x--)
286 DPRINTF(Annotate, "-- %d\n", smStack[sid][x]);
287 DPRINTF(Annotate, "Ending machine: %s; end stack: %s\n", sm,
288 smMap[smib-1].second.first);
289
290 warn("State machine stack not unwinding correctly at %d\n", curTick());
291 } else {
292 DPRINTF(Annotate,
293 "State machine ending:%s sysi:%d id:%#x back:%d getSm:%d\n",
294 sm, sysi, smMap[smib-1].second.second, smStack[sid].back(),
295 getSm(sysi, sm, smMap[smib-1].second.second));
296 assert(getSm(sysi, sm, smMap[smib-1].second.second) ==
297 smStack[sid].back());
298
299 int smi = smStack[sid].back();
300 smStack[sid].pop_back();
301
302 if (lnMap[smi]) {
303 DPRINTF(Annotate, "Linking %d back to %d\n", smi, lnMap[smi]);
304 add(OP_LINK, FL_NONE, cpuid, smi, lnMap[smi]);
305 lnMap.erase(smi);
306 }
307
308 if (smStack[sid].size()) {
309 add(OP_BEGIN, FL_NONE, cpuid, smi, lastState[smi]);
310 }
311
312 DPRINTF(Annotate, "Stack Now:\n");
313 for (int x = smStack[sid].size()-1; x >= 0; x--)
314 DPRINTF(Annotate, "-- %d\n", smStack[sid][x]);
315 }
316 }
317
318
319 void
320 CPA::swExplictBegin(ThreadContext *tc)
321 {
322 if (!enabled())
323 return;
324
325 Arguments args(tc);
326 char st[50];
327 tc->getVirtProxy().readString(st, args[1], 50);
328
329 StringWrap name(tc->getSystemPtr()->name());
330 DPRINTF(Annotate, "Explict begin of state %s\n", st);
331 uint32_t flags = args[0];
332 if (flags & FL_BAD)
333 warn("BAD state encountered: at cycle %d: %s\n", curTick(), st);
334 swBegin(tc->getSystemPtr(), tc->contextId(), st, getFrame(tc), true, args[0]);
335 }
336
337 void
338 CPA::swAutoBegin(ThreadContext *tc, Addr next_pc)
339 {
340 if (!enabled())
341 return;
342
343 string sym;
344 Addr sym_addr = 0;
345
346 if (!TheISA::inUserMode(tc)) {
347 debugSymbolTable->findNearestSymbol(next_pc, sym, sym_addr);
348 } else {
349 Linux::ThreadInfo ti(tc);
350 string app = ti.curTaskName();
351 if (userApp.count(app))
352 userApp[app]->findNearestSymbol(next_pc, sym, sym_addr);
353 }
354
355 if (sym_addr)
356 swBegin(tc->getSystemPtr(), tc->contextId(), sym, getFrame(tc));
357 }
358
359 void
360 CPA::swBegin(System *sys, int cpuid, std::string st, uint64_t frame, bool expl,
361 int flags)
362 {
363 int x = 0;
364 int len;
365 while (ignoreSymbols[x].len)
366 {
367 len = ignoreSymbols[x].len;
368 if (!st.compare(0,len, ignoreSymbols[x].symbol, len))
369 return;
370 x++;
371 }
372
373 int sysi = getSys(sys);
374 StackId sid = StackId(sysi, frame);
375 // if expl is true suspend symbol table based states
376 if (!smStack[sid].size())
377 return;
378 if (!expl && swExpl[sid])
379 return;
380 if (expl)
381 swExpl[sid] = true;
382 DPRINTFS(AnnotateVerbose, sys, "SwBegin: %s sysi: %d\n", st, sysi);
383 int smi = smStack[sid].back();
384 int sti = getSt(smMap[smi-1].second.first, st);
385 if (lastState[smi] != sti) {
386 lastState[smi] = sti;
387 add(OP_BEGIN, flags, cpuid, smi, sti);
388 }
389 }
390
391 void
392 CPA::swEnd(ThreadContext *tc)
393 {
394 if (!enabled())
395 return;
396
397 std::string st;
398 Addr junk;
399 if (!TheISA::inUserMode(tc))
400 debugSymbolTable->findNearestSymbol(
401 tc->readIntReg(ReturnAddressReg), st, junk);
402 System *sys = tc->getSystemPtr();
403 StringWrap name(sys->name());
404
405 int sysi = getSys(sys);
406 StackId sid = StackId(sysi, getFrame(tc));
407 if (!smStack[sid].size()) {
408 DPRINTF(Annotate, "Explict end of State: %s IGNORED\n", st);
409 return;
410 }
411 DPRINTF(Annotate, "Explict end of State: %s\n", st);
412 // return back to symbol table based states
413 swExpl[sid] = false;
414 int smi = smStack[sid].back();
415 if (st != "") {
416 int sti = getSt(smMap[smi-1].second.first, st);
417 lastState[smi] = sti;
418 add(OP_BEGIN, FL_NONE, tc->contextId(), smi, sti);
419 }
420 }
421
422 void
423 CPA::swQ(ThreadContext *tc)
424 {
425 if (!enabled())
426 return;
427
428 char q[50];
429 Arguments args(tc);
430 uint64_t id = args[0];
431 tc->getVirtProxy().readString(q, args[1], 50);
432 int32_t count = args[2];
433 System *sys = tc->getSystemPtr();
434
435 int sysi = getSys(sys);
436 StackId sid = StackId(sysi, getFrame(tc));
437 if (!smStack[sid].size())
438 return;
439 int smi = smStack[sid].back();
440 if (swExpl[sid])
441 swExpl[sid] = false;
442 int qi = getQ(sysi, q, id);
443 if (count == 0) {
444 //warn("Tried to queue 0 bytes in %s, ignoring\n", q);
445 return;
446 }
447 DPRINTFS(AnnotateQ, sys,
448 "swQ: %s[%#x] cur size %d %d bytes: %d adding: %d\n",
449 q, id, qSize[qi-1], qData[qi-1].size(), qBytes[qi-1], count);
450 doQ(sys, FL_NONE, tc->contextId(), smi, q, qi, count);
451 }
452
453 void
454 CPA::swDq(ThreadContext *tc)
455 {
456 if (!enabled())
457 return;
458
459 char q[50];
460 Arguments args(tc);
461 uint64_t id = args[0];
462 tc->getVirtProxy().readString(q, args[1], 50);
463 int32_t count = args[2];
464 System *sys = tc->getSystemPtr();
465
466 int sysi = getSys(sys);
467 StackId sid = StackId(sysi, getFrame(tc));
468 if (!smStack[sid].size())
469 return;
470 int smi = smStack[sid].back();
471 int qi = getQ(sysi, q, id);
472 if (swExpl[sid])
473 swExpl[sid] = false;
474 DPRINTFS(AnnotateQ, sys,
475 "swDq: %s[%#x] cur size %d %d bytes: %d removing: %d\n",
476 q, id, qSize[qi-1], qData[qi-1].size(), qBytes[qi-1], count);
477 assert(count != 0);
478
479 doDq(sys, FL_NONE, tc->contextId(), smi, q, qi, count);
480 }
481
482 void
483 CPA::swPq(ThreadContext *tc)
484 {
485 if (!enabled())
486 return;
487
488 char q[50];
489 Arguments args(tc);
490 uint64_t id = args[0];
491 tc->getVirtProxy().readString(q, args[1], 50);
492 System *sys = tc->getSystemPtr();
493 int32_t count = args[2];
494
495 int sysi = getSys(sys);
496 StackId sid = StackId(sysi, getFrame(tc));
497 if (!smStack[sid].size())
498 return;
499 int smi = smStack[sid].back();
500 int qi = getQ(sysi, q, id);
501 if (swExpl[sid])
502 swExpl[sid] = false;
503 DPRINTFS(AnnotateQ, sys,
504 "swPq: %s [%#x] cur size %d %d bytes: %d peeking: %d\n",
505 q, id, qSize[qi-1], qData[qi-1].size(), qBytes[qi-1], count);
506
507 assert(count != 0);
508 if (qBytes[qi-1] < count) {
509 dump(true);
510 dumpKey();
511 fatal("Queue %s peeking with not enough bytes available in queue!\n", q);
512 }
513
514 add(OP_PEEK, FL_NONE, tc->contextId(), smi, qi, count);
515 }
516
517 void
518 CPA::swRq(ThreadContext *tc)
519 {
520 if (!enabled())
521 return;
522
523 char q[50];
524 Arguments args(tc);
525 uint64_t id = args[0];
526 tc->getVirtProxy().readString(q, args[1], 50);
527 System *sys = tc->getSystemPtr();
528 int32_t count = args[2];
529
530 int sysi = getSys(sys);
531 StackId sid = StackId(sysi, getFrame(tc));
532 if (!smStack[sid].size())
533 return;
534 int smi = smStack[sid].back();
535 int qi = getQ(sysi, q, id);
536 if (swExpl[sid])
537 swExpl[sid] = false;
538 DPRINTFS(AnnotateQ, sys,
539 "swRq: %s [%#x] cur size %d %d bytes: %d reserve: %d\n",
540 q, id, qSize[qi-1], qData[qi-1].size(), qBytes[qi-1], count);
541
542 assert(count != 0);
543
544 add(OP_RESERVE, FL_NONE, tc->contextId(), smi, qi, count);
545 }
546
547
548 void
549 CPA::swWf(ThreadContext *tc)
550 {
551 if (!enabled())
552 return;
553
554 char q[50];
555 Arguments args(tc);
556 uint64_t id = args[0];
557 tc->getVirtProxy().readString(q, args[1], 50);
558 System *sys = tc->getSystemPtr();
559 int32_t count = args[3];
560
561 int sysi = getSys(sys);
562 StackId sid = StackId(sysi, getFrame(tc));
563 if (!smStack[sid].size())
564 return;
565 int smi = smStack[sid].back();
566 int qi = getQ(sysi, q, id);
567 add(OP_WAIT_FULL, FL_NONE, tc->contextId(), smi, qi, count);
568
569 if (!!args[2]) {
570 char sm[50];
571 tc->getVirtProxy().readString(sm, args[2], 50);
572 doSwSmEnd(tc->getSystemPtr(), tc->contextId(), sm, getFrame(tc));
573 }
574 }
575
576 void
577 CPA::swWe(ThreadContext *tc)
578 {
579 if (!enabled())
580 return;
581
582 char q[50];
583 Arguments args(tc);
584 uint64_t id = args[0];
585 tc->getVirtProxy().readString(q, args[1], 50);
586 System *sys = tc->getSystemPtr();
587 int32_t count = args[3];
588
589 int sysi = getSys(sys);
590 StackId sid = StackId(sysi, getFrame(tc));
591 if (!smStack[sid].size())
592 return;
593 int smi = smStack[sid].back();
594 int qi = getQ(sysi, q, id);
595 add(OP_WAIT_EMPTY, FL_NONE, tc->contextId(), smi, qi, count);
596
597 if (!!args[2]) {
598 char sm[50];
599 tc->getVirtProxy().readString(sm, args[2], 50);
600 doSwSmEnd(tc->getSystemPtr(), tc->contextId(), sm, getFrame(tc));
601 }
602 }
603
604 void
605 CPA::swSq(ThreadContext *tc)
606 {
607 if (!enabled())
608 return;
609
610 char q[50];
611 Arguments args(tc);
612 uint64_t id = args[0];
613 tc->getVirtProxy().readString(q, args[1], 50);
614 System *sys = tc->getSystemPtr();
615 StringWrap name(sys->name());
616 int32_t size = args[2];
617 int flags = args[3];
618
619 int sysi = getSys(sys);
620 StackId sid = StackId(sysi, getFrame(tc));
621 if (!smStack[sid].size())
622 return;
623 int smi = smStack[sid].back();
624 int qi = getQ(sysi, q, id);
625 DPRINTF(AnnotateQ, "swSq: %s [%#x] cur size: %d bytes: %d, new size: %d\n",
626 q, id, qSize[qi-1], qBytes[qi-1], size);
627
628 if (FL_RESET & flags) {
629 DPRINTF(AnnotateQ, "Resetting Queue %s\n", q);
630 add(OP_SIZE_QUEUE, FL_NONE, tc->contextId(), smi, qi, 0);
631 qData[qi-1].clear();
632 qSize[qi-1] = 0;
633 qBytes[qi-1] = 0;
634 }
635
636 if (qBytes[qi-1] < size)
637 doQ(sys, FL_NONE, tc->contextId(), smi, q, qi, size - qBytes[qi-1]);
638 else if (qBytes[qi-1] > size) {
639 DPRINTF(AnnotateQ, "removing for resize of queue %s\n", q);
640 add(OP_SIZE_QUEUE, FL_NONE, tc->contextId(), smi, qi, size);
641 if (size <= 0) {
642 qData[qi-1].clear();
643 qSize[qi-1] = 0;
644 qBytes[qi-1] = 0;
645 return;
646 }
647 int need = qBytes[qi-1] - size;
648 qBytes[qi-1] = size;
649 while (need > 0) {
650 int32_t tail_bytes = qData[qi-1].back()->data;
651 if (qSize[qi-1] <= 0 || qBytes[qi-1] < 0) {
652 dump(true);
653 dumpKey();
654 fatal("Queue %s had inconsistancy when doing size queue!\n", q);
655 }
656 if (tail_bytes > need) {
657 qData[qi-1].back()->data -= need;
658 need = 0;
659 } else if (tail_bytes == need) {
660 qData[qi-1].pop_back();
661 qSize[qi-1]--;
662 need = 0;
663 } else {
664 qData[qi-1].pop_back();
665 qSize[qi-1]--;
666 need -= tail_bytes;
667 }
668 }
669 }
670 }
671
672 void
673 CPA::swAq(ThreadContext *tc)
674 {
675 if (!enabled())
676 return;
677
678 char q[50];
679 Arguments args(tc);
680 uint64_t id = args[0];
681 tc->getVirtProxy().readString(q, args[1], 50);
682 System *sys = tc->getSystemPtr();
683 StringWrap name(sys->name());
684 int32_t size = args[2];
685
686 int sysi = getSys(sys);
687 int qi = getQ(sysi, q, id);
688 if (qBytes[qi-1] != size) {
689 DPRINTF(AnnotateQ, "Queue %s [%#x] has inconsintant size\n", q, id);
690 //dump(true);
691 //dumpKey();
692 std::list<AnnDataPtr>::iterator ai = qData[qi-1].begin();
693 int x = 0;
694 while (ai != qData[qi-1].end()) {
695 DPRINTF(AnnotateQ, "--Element %d size %d\n", x, (*ai)->data);
696 ai++;
697 x++;
698 }
699
700 warn("%d: Queue Assert: SW said there should be %d byte(s) in %s,"
701 "however there are %d byte(s)\n",
702 curTick(), size, q, qBytes[qi-1]);
703 DPRINTF(AnnotateQ, "%d: Queue Assert: SW said there should be %d"
704 " byte(s) in %s, however there are %d byte(s)\n",
705 curTick(), size, q, qBytes[qi-1]);
706 }
707 }
708
709 void
710 CPA::swLink(ThreadContext *tc)
711 {
712 if (!enabled())
713 return;
714
715 char lsm[50];
716 Arguments args(tc);
717 tc->getVirtProxy().readString(lsm, args[0], 50);
718 System *sys = tc->getSystemPtr();
719 StringWrap name(sys->name());
720
721 int sysi = getSys(sys);
722 StackId sid = StackId(sysi, getFrame(tc));
723 if (!smStack[sid].size())
724 return;
725 int smi = smStack[sid].back();
726 int lsmi = getSm(sysi, lsm, args[1]);
727
728 DPRINTF(Annotate, "Linking from %d to state machine %s(%d) [%#x]\n",
729 smi, lsm, lsmi, args[1]);
730
731 if (lnMap[lsmi])
732 DPRINTF(Annotate, "LnMap already contains entry for %d of %d\n",
733 lsmi, lnMap[lsmi]);
734 assert(lnMap[lsmi] == 0);
735 lnMap[lsmi] = smi;
736
737 add(OP_LINK, FL_NONE, tc->contextId(), smi, lsmi);
738
739 if (!!args[2]) {
740 char sm[50];
741 tc->getVirtProxy().readString(sm, args[2], 50);
742 doSwSmEnd(tc->getSystemPtr(), tc->contextId(), sm, getFrame(tc));
743 }
744 }
745
746 void
747 CPA::swIdentify(ThreadContext *tc)
748 {
749 if (!enabled())
750 return;
751
752 Arguments args(tc);
753 int sysi = getSys(tc->getSystemPtr());
754 StackId sid = StackId(sysi, getFrame(tc));
755 if (!smStack[sid].size())
756 return;
757 int smi = smStack[sid].back();
758
759 DPRINTFS(Annotate, tc->getSystemPtr(), "swIdentify: id %#X\n", args[0]);
760
761 add(OP_IDENT, FL_NONE, tc->contextId(), smi, 0, args[0]);
762 }
763
764 uint64_t
765 CPA::swGetId(ThreadContext *tc)
766 {
767 if (!enabled())
768 return 0;
769
770 uint64_t id = ++conId;
771 int sysi = getSys(tc->getSystemPtr());
772 StackId sid = StackId(sysi, getFrame(tc));
773 if (!smStack[sid].size())
774 panic("swGetId called without a state machine stack!");
775 int smi = smStack[sid].back();
776
777 DPRINTFS(Annotate, tc->getSystemPtr(), "swGetId: id %#X\n", id);
778
779 add(OP_IDENT, FL_NONE, tc->contextId(), smi, 0, id);
780 return id;
781 }
782
783
784 void
785 CPA::swSyscallLink(ThreadContext *tc)
786 {
787 if (!enabled())
788 return;
789
790 char lsm[50];
791 Arguments args(tc);
792 tc->getVirtProxy().readString(lsm, args[0], 50);
793 System *sys = tc->getSystemPtr();
794 StringWrap name(sys->name());
795 int sysi = getSys(sys);
796
797 Id id = Id(lsm, getFrame(tc));
798 StackId sid = StackId(sysi, getFrame(tc));
799
800 if (!smStack[sid].size())
801 return;
802
803 int smi = smStack[sid].back();
804
805 DPRINTF(Annotate, "Linking from %d to state machine %s(UNKNOWN)\n",
806 smi, lsm);
807
808 if (scLinks[sysi-1][id])
809 DPRINTF(Annotate,
810 "scLinks already contains entry for system %d %s[%x] of %d\n",
811 sysi, lsm, getFrame(tc), scLinks[sysi-1][id]);
812 assert(scLinks[sysi-1][id] == 0);
813 scLinks[sysi-1][id] = add(OP_LINK, FL_NONE, tc->contextId(), smi, 0xFFFF);
814 scLinks[sysi-1][id]->dump = false;
815
816 if (!!args[1]) {
817 char sm[50];
818 tc->getVirtProxy().readString(sm, args[1], 50);
819 doSwSmEnd(tc->getSystemPtr(), tc->contextId(), sm, getFrame(tc));
820 }
821 }
822
823 CPA::AnnDataPtr
824 CPA::add(int t, int f, int c, int sm, int stq, int32_t d)
825 {
826 AnnDataPtr an = std::make_shared<AnnotateData>();
827 an->time = curTick();
828 an->data = d;
829 an->orig_data = d;
830 an->op = t;
831 an->flag = f;
832 an->sm = sm;
833 an->stq = stq;
834 an->cpu = c;
835 an->dump = true;
836
837 data.push_back(an);
838
839 DPRINTF(AnnotateVerbose, "Annotate: op: %d flags: 0x%x sm: %d state: %d time: %d, data: %d\n",
840 an->op, an->flag, an->sm, an->stq, an->time, an->data);
841
842 // Don't dump Links because we might be setting no-dump on it
843 if (an->op != OP_LINK)
844 dump(false);
845
846 return an;
847 }
848
849 void
850 CPA::dumpKey()
851 {
852 std::streampos curpos = osbin->tellp();
853 ah.key_off = curpos;
854
855 // Output the various state machines and their corresponding states
856 *osbin << "# Automatically generated state machine descriptor file" << endl;
857
858 *osbin << "sms = {}" << endl << endl;
859 vector<string> state_machines;
860 state_machines.resize(numSmt+1);
861
862 // State machines, id -> states
863 SCache::iterator i = smtCache.begin();
864 while (i != smtCache.end()) {
865 state_machines[i->second] = i->first;
866 i++;
867 }
868
869 for (int x = 1; x < state_machines.size(); x++) {
870 vector<string> states;
871 states.resize(numSt[x-1]+1);
872 assert(x-1 < stCache.size());
873 SCache::iterator i = stCache[x-1].begin();
874 while (i != stCache[x-1].end()) {
875 states[i->second] = i->first;
876 i++;
877 }
878 *osbin << "sms[\"" << state_machines[x] << "\"] = [\"NULL\"";
879 for (int y = 1; y < states.size(); y++)
880 *osbin << ", \"" << states[y] << "\"";
881 *osbin << "]" << endl;
882 }
883
884 *osbin << endl << endl << endl;
885
886 // state machine number -> system, name, id
887 *osbin << "smNum = [\"NULL\"";
888 for (int x = 0; x < smMap.size(); x++)
889 *osbin << ", (" << smMap[x].first << ", \"" << smMap[x].second.first <<
890 "\", " << smMap[x].second.second << ")";
891 *osbin << "]" << endl;
892
893 *osbin << endl << endl << endl;
894
895 // Output the systems
896 vector<string> systems;
897 systems.resize(numSys+1);
898 NameCache::iterator i2 = nameCache.begin();
899 while (i2 != nameCache.end()) {
900 systems[i2->second.second] = i2->second.first;
901 i2++;
902 }
903
904 *osbin << "sysNum = [\"NULL\"";
905 for (int x = 1; x < systems.size(); x++) {
906 *osbin << ", \"" << systems[x] << "\"";
907 }
908 *osbin << "]" << endl;
909
910 // queue number -> system, qname, qid
911 *osbin << "queues = [\"NULL\"";
912 for (int x = 0; x < qMap.size(); x++)
913 *osbin << ", (" << qMap[x].first << ", \"" << qMap[x].second.first <<
914 "\", " << qMap[x].second.second << ")";
915 *osbin << "]" << endl;
916
917 *osbin << "smComb = [s for s in [(i,r) for i in xrange(1,len(sysNum)) "
918 << "for r in xrange (1,len(smNum))]]" << endl;
919 ah.key_len = osbin->tellp() - curpos;
920
921 // output index
922 curpos = osbin->tellp();
923 ah.idx_off = curpos;
924
925 for (int x = 0; x < annotateIdx.size(); x++)
926 osbin->write((char*)&annotateIdx[x], sizeof(uint64_t));
927 ah.idx_len = osbin->tellp() - curpos;
928
929 osbin->seekp(0);
930 osbin->write((char*)&ah, sizeof(AnnotateHeader));
931 osbin->flush();
932
933 }
934
935 void
936 CPA::dump(bool all)
937 {
938
939 list<AnnDataPtr>::iterator i;
940
941 i = data.begin();
942
943 if (i == data.end())
944 return;
945
946 // Dump the data every
947 if (!all && data.size() < 10000)
948 return;
949
950 DPRINTF(Annotate, "Writing %d\n", data.size());
951 while (i != data.end()) {
952 AnnDataPtr an = *i;
953
954 // If we can't dump this record, hold here
955 if (!an->dump && !all)
956 break;
957
958 ah.num_recs++;
959 if (ah.num_recs % 100000 == 0)
960 annotateIdx.push_back(osbin->tellp());
961
962
963 osbin->write((char*)&(an->time), sizeof(an->time));
964 osbin->write((char*)&(an->orig_data), sizeof(an->orig_data));
965 osbin->write((char*)&(an->sm), sizeof(an->sm));
966 osbin->write((char*)&(an->stq), sizeof(an->stq));
967 osbin->write((char*)&(an->op), sizeof(an->op));
968 osbin->write((char*)&(an->flag), sizeof(an->flag));
969 osbin->write((char*)&(an->cpu), sizeof(an->cpu));
970 i++;
971 }
972 if (data.begin() != i)
973 data.erase(data.begin(), i);
974
975 if (all)
976 osbin->flush();
977 }
978
979 void
980 CPA::doQ(System *sys, int flags, int cpuid, int sm,
981 string q, int qi, int count)
982 {
983 qSize[qi-1]++;
984 qBytes[qi-1] += count;
985 if (qSize[qi-1] > 2501 || qBytes[qi-1] > 2000000000)
986 warn("Queue %s is %d elements/%d bytes, "
987 "maybe things aren't being removed?\n",
988 q, qSize[qi-1], qBytes[qi-1]);
989 if (flags & FL_QOPP)
990 qData[qi-1].push_front(add(OP_QUEUE, flags, cpuid, sm, qi, count));
991 else
992 qData[qi-1].push_back(add(OP_QUEUE, flags, cpuid, sm, qi, count));
993 DPRINTFS(AnnotateQ, sys, "Queing in queue %s size now %d/%d\n",
994 q, qSize[qi-1], qBytes[qi-1]);
995 assert(qSize[qi-1] >= 0);
996 assert(qBytes[qi-1] >= 0);
997 }
998
999
1000 void
1001 CPA::doDq(System *sys, int flags, int cpuid, int sm,
1002 string q, int qi, int count)
1003 {
1004
1005 StringWrap name(sys->name());
1006 if (count == -1) {
1007 add(OP_DEQUEUE, flags, cpuid, sm, qi, count);
1008 qData[qi-1].clear();
1009 qSize[qi-1] = 0;
1010 qBytes[qi-1] = 0;
1011 DPRINTF(AnnotateQ, "Dequeing all data in queue %s size now %d/%d\n",
1012 q, qSize[qi-1], qBytes[qi-1]);
1013 return;
1014 }
1015
1016 assert(count > 0);
1017 if (qSize[qi-1] <= 0 || qBytes[qi-1] <= 0 || !qData[qi-1].size()) {
1018 dump(true);
1019 dumpKey();
1020 fatal("Queue %s dequing with no data available in queue!\n",
1021 q);
1022 }
1023 assert(qSize[qi-1] >= 0);
1024 assert(qBytes[qi-1] >= 0);
1025 assert(qData[qi-1].size());
1026
1027 int32_t need = count;
1028 qBytes[qi-1] -= count;
1029 if (qBytes[qi-1] < 0) {
1030 dump(true);
1031 dumpKey();
1032 fatal("Queue %s dequing with no bytes available in queue!\n",
1033 q);
1034 }
1035
1036 while (need > 0) {
1037 int32_t head_bytes = qData[qi-1].front()->data;
1038 if (qSize[qi-1] <= 0 || qBytes[qi-1] < 0) {
1039 dump(true);
1040 dumpKey();
1041 fatal("Queue %s dequing with nothing in queue!\n",
1042 q);
1043 }
1044
1045 if (head_bytes > need) {
1046 qData[qi-1].front()->data -= need;
1047 need = 0;
1048 } else if (head_bytes == need) {
1049 qData[qi-1].pop_front();
1050 qSize[qi-1]--;
1051 need = 0;
1052 } else {
1053 qData[qi-1].pop_front();
1054 qSize[qi-1]--;
1055 need -= head_bytes;
1056 }
1057 }
1058
1059 add(OP_DEQUEUE, flags, cpuid, sm, qi, count);
1060 DPRINTF(AnnotateQ, "Dequeing in queue %s size now %d/%d\n",
1061 q, qSize[qi-1], qBytes[qi-1]);
1062 }
1063
1064
1065
1066 void
1067 CPA::serialize(CheckpointOut &cp) const
1068 {
1069
1070 SERIALIZE_SCALAR(numSm);
1071 SERIALIZE_SCALAR(numSmt);
1072 arrayParamOut(os, "numSt", numSt);
1073 arrayParamOut(os, "numQ", numQ);
1074 SERIALIZE_SCALAR(numSys);
1075 SERIALIZE_SCALAR(numQs);
1076 SERIALIZE_SCALAR(conId);
1077 arrayParamOut(os, "qSize", qSize);
1078 arrayParamOut(os, "qSize", qSize);
1079 arrayParamOut(os, "qBytes", qBytes);
1080
1081 SCache::iterator i;
1082 int x = 0, y = 0;
1083
1084 // smtCache (SCache)
1085 x = 0;
1086 y = 0;
1087 i = smtCache.begin();
1088 while (i != smtCache.end()) {
1089 paramOut(os, csprintf("smtCache%d.str", x), i->first);
1090 paramOut(os, csprintf("smtCache%d.int", x), i->second);
1091 x++; i++;
1092 }
1093
1094 // stCache (StCache)
1095 for (x = 0; x < stCache.size(); x++) {
1096 i = stCache[x].begin();
1097 y = 0;
1098 while (i != stCache[x].end()) {
1099 paramOut(os, csprintf("stCache%d_%d.str", x, y), i->first);
1100 paramOut(os, csprintf("stCache%d_%d.int", x, y), i->second);
1101 y++; i++;
1102 }
1103 }
1104
1105 // qCache (IdCache)
1106 IdHCache::iterator idi;
1107 for (x = 0; x < qCache.size(); x++) {
1108 idi = qCache[x].begin();
1109 y = 0;
1110 while (idi != qCache[x].end()) {
1111 paramOut(os, csprintf("qCache%d_%d.str", x, y), idi->first.first);
1112 paramOut(os, csprintf("qCache%d_%d.id", x, y), idi->first.second);
1113 paramOut(os, csprintf("qCache%d_%d.int", x, y), idi->second);
1114 y++; idi++;
1115 }
1116 }
1117
1118 // smCache (IdCache)
1119 for (x = 0; x < smCache.size(); x++) {
1120 idi = smCache[x].begin();
1121 y = 0;
1122 paramOut(os, csprintf("smCache%d", x), smCache[x].size());
1123 while (idi != smCache[x].end()) {
1124 paramOut(os, csprintf("smCache%d_%d.str", x, y), idi->first.first);
1125 paramOut(os, csprintf("smCache%d_%d.id", x, y), idi->first.second);
1126 paramOut(os, csprintf("smCache%d_%d.int", x, y), idi->second);
1127 y++; idi++;
1128 }
1129 }
1130
1131 // scLinks (ScCache) -- data not serialize
1132
1133
1134 // namecache (NameCache)
1135 NameCache::iterator ni;
1136
1137 ni = nameCache.begin();
1138 x = 0;
1139 while (ni != nameCache.end()) {
1140 paramOut(os, csprintf("nameCache%d.name", x), ni->first->name());
1141 paramOut(os, csprintf("nameCache%d.str", x), ni->second.first);
1142 paramOut(os, csprintf("nameCache%d.int", x), ni->second.second);
1143 x++; ni++;
1144 }
1145
1146 // smStack (SmStack)
1147 SmStack::iterator si;
1148 si = smStack.begin();
1149 x = 0;
1150 paramOut(os, "smStackIdCount", smStack.size());
1151 while (si != smStack.end()) {
1152 paramOut(os, csprintf("smStackId%d.sys", x), si->first.first);
1153 paramOut(os, csprintf("smStackId%d.frame", x), si->first.second);
1154 paramOut(os, csprintf("smStackId%d.count", x), si->second.size());
1155 for (y = 0; y < si->second.size(); y++)
1156 paramOut(os, csprintf("smStackId%d_%d", x, y), si->second[y]);
1157 x++; si++;
1158 }
1159
1160 // lnMap (LinkMap)
1161 x = 0;
1162 LinkMap::iterator li;
1163 li = lnMap.begin();
1164 paramOut(os, "lnMapSize", lnMap.size());
1165 while (li != lnMap.end()) {
1166 paramOut(os, csprintf("lnMap%d.smi", x), li->first);
1167 paramOut(os, csprintf("lnMap%d.lsmi", x), li->second);
1168 x++; li++;
1169 }
1170
1171 // swExpl (vector)
1172 SwExpl::iterator swexpli;
1173 swexpli = swExpl.begin();
1174 x = 0;
1175 paramOut(os, "swExplCount", swExpl.size());
1176 while (swexpli != swExpl.end()) {
1177 paramOut(os, csprintf("swExpl%d.sys", x), swexpli->first.first);
1178 paramOut(os, csprintf("swExpl%d.frame", x), swexpli->first.second);
1179 paramOut(os, csprintf("swExpl%d.swexpl", x), swexpli->second);
1180 x++; swexpli++;
1181 }
1182
1183 // lastState (IMap)
1184 x = 0;
1185 IMap::iterator ii;
1186 ii = lastState.begin();
1187 paramOut(os, "lastStateSize", lastState.size());
1188 while (ii != lastState.end()) {
1189 paramOut(os, csprintf("lastState%d.smi", x), ii->first);
1190 paramOut(os, csprintf("lastState%d.sti", x), ii->second);
1191 x++; ii++;
1192 }
1193
1194 // smMap (IdMap)
1195 for (x = 0; x < smMap.size(); x++) {
1196 paramOut(os, csprintf("smMap%d.sys", x), smMap[x].first);
1197 paramOut(os, csprintf("smMap%d.smname", x), smMap[x].second.first);
1198 paramOut(os, csprintf("smMap%d.id", x), smMap[x].second.second);
1199 }
1200
1201 // qMap (IdMap)
1202 for (x = 0; x < qMap.size(); x++) {
1203 paramOut(os, csprintf("qMap%d.sys", x), qMap[x].first);
1204 paramOut(os, csprintf("qMap%d.qname", x), qMap[x].second.first);
1205 paramOut(os, csprintf("qMap%d.id", x), qMap[x].second.second);
1206 }
1207
1208 // qData (vector<AnnotateList>)
1209 for (x = 0; x < qData.size(); x++) {
1210 if (!qData[x].size())
1211 continue;
1212 y = 0;
1213 for (auto &ann : qData[x]) {
1214 ann->serializeSection(os, csprintf("Q%d_%d", x, y));
1215 y++;
1216 }
1217 }
1218 }
1219
1220 void
1221 CPA::unserialize(CheckpointIn &cp)
1222 {
1223 UNSERIALIZE_SCALAR(numSm);
1224 UNSERIALIZE_SCALAR(numSmt);
1225 UNSERIALIZE_CONTAINER(numSt);
1226 UNSERIALIZE_CONTAINER(numQ);
1227 UNSERIALIZE_SCALAR(numSys);
1228 UNSERIALIZE_SCALAR(numQs);
1229 UNSERIALIZE_SCALAR(conId);
1230 UNSERIALIZE_CONTAINER(qSize);
1231 UNSERIALIZE_CONTAINER(qBytes);
1232
1233
1234 // smtCache (SCache
1235 string str;
1236 int smi;
1237 for (int x = 0; x < numSmt; x++) {
1238 paramIn(cp, csprintf("smtCache%d.str", x), str);
1239 paramIn(cp, csprintf("smtCache%d.int", x), smi);
1240 smtCache[str] = smi;
1241 }
1242
1243 // stCache (StCache)
1244 stCache.resize(numSmt);
1245 for (int x = 0; x < numSmt; x++) {
1246 for (int y = 0; y < numSt[x]; y++) {
1247 paramIn(cp, csprintf("stCache%d_%d.str", x,y), str);
1248 paramIn(cp, csprintf("stCache%d_%d.int", x,y), smi);
1249 stCache[x][str] = smi;
1250 }
1251 }
1252
1253 // qCache (IdCache)
1254 uint64_t id;
1255 qCache.resize(numSys);
1256 for (int x = 0; x < numSys; x++) {
1257 for (int y = 0; y < numQ[x]; y++) {
1258 paramIn(cp, csprintf("qCache%d_%d.str", x,y), str);
1259 paramIn(cp, csprintf("qCache%d_%d.id", x,y), id);
1260 paramIn(cp, csprintf("qCache%d_%d.int", x,y), smi);
1261 qCache[x][Id(str,id)] = smi;
1262 }
1263 }
1264
1265 // smCache (IdCache)
1266 smCache.resize(numSys);
1267 for (int x = 0; x < numSys; x++) {
1268 int size;
1269 paramIn(cp, csprintf("smCache%d", x), size);
1270 for (int y = 0; y < size; y++) {
1271 paramIn(cp, csprintf("smCache%d_%d.str", x,y), str);
1272 paramIn(cp, csprintf("smCache%d_%d.id", x,y), id);
1273 paramIn(cp, csprintf("smCache%d_%d.int", x,y), smi);
1274 smCache[x][Id(str,id)] = smi;
1275 }
1276 }
1277
1278 // scLinks (ScCache) -- data not serialized, just creating one per sys
1279 for (int x = 0; x < numSys; x++)
1280 scLinks.push_back(ScHCache());
1281
1282 // nameCache (NameCache)
1283 for (int x = 0; x < numSys; x++) {
1284 System *sys;
1285 SimObject *sptr;
1286 string str;
1287 int sysi;
1288
1289 objParamIn(cp, csprintf("nameCache%d.name", x), sptr);
1290 sys = dynamic_cast<System*>(sptr);
1291
1292 paramIn(cp, csprintf("nameCache%d.str", x), str);
1293 paramIn(cp, csprintf("nameCache%d.int", x), sysi);
1294 nameCache[sys] = std::make_pair(str, sysi);
1295 }
1296
1297 //smStack (SmStack)
1298 int smStack_size;
1299 paramIn(cp, "smStackIdCount", smStack_size);
1300 for (int x = 0; x < smStack_size; x++) {
1301 int sysi;
1302 uint64_t frame;
1303 int count;
1304 paramIn(cp, csprintf("smStackId%d.sys", x), sysi);
1305 paramIn(cp, csprintf("smStackId%d.frame", x), frame);
1306 paramIn(cp, csprintf("smStackId%d.count", x), count);
1307 StackId sid = StackId(sysi, frame);
1308 for (int y = 0; y < count; y++) {
1309 paramIn(cp, csprintf("smStackId%d_%d", x, y), smi);
1310 smStack[sid].push_back(smi);
1311 }
1312 }
1313
1314 // lnMap (LinkMap)
1315 int lsmi;
1316 int lnMap_size;
1317 paramIn(cp, "lnMapSize", lnMap_size);
1318 for (int x = 0; x < lnMap_size; x++) {
1319 paramIn(cp, csprintf("lnMap%d.smi", x), smi);
1320 paramIn(cp, csprintf("lnMap%d.lsmi", x), lsmi);
1321 lnMap[smi] = lsmi;
1322 }
1323
1324 // swExpl (vector)
1325 int swExpl_size;
1326 paramIn(cp, "swExplCount", swExpl_size);
1327 for (int x = 0; x < swExpl_size; x++) {
1328 int sysi;
1329 uint64_t frame;
1330 bool b;
1331 paramIn(cp, csprintf("swExpl%d.sys", x), sysi);
1332 paramIn(cp, csprintf("swExpl%d.frame", x), frame);
1333 paramIn(cp, csprintf("swExpl%d.swexpl", x), b);
1334 StackId sid = StackId(sysi, frame);
1335 swExpl[sid] = b;
1336 }
1337
1338 // lastState (IMap)
1339 int sti;
1340 int lastState_size;
1341 paramIn(cp, "lastStateSize", lastState_size);
1342 for (int x = 0; x < lastState_size; x++) {
1343 paramIn(cp, csprintf("lastState%d.smi", x), smi);
1344 paramIn(cp, csprintf("lastState%d.sti", x), sti);
1345 lastState[smi] = sti;
1346 }
1347
1348
1349 //smMap (IdMap)
1350 smMap.resize(numSm);
1351 for (int x = 0; x < smMap.size(); x++) {
1352 paramIn(cp, csprintf("smMap%d.sys", x), smMap[x].first);
1353 paramIn(cp, csprintf("smMap%d.smname", x), smMap[x].second.first);
1354 paramIn(cp, csprintf("smMap%d.id", x), smMap[x].second.second);
1355 }
1356
1357 //qMap (IdMap)
1358 qMap.resize(numQs);
1359 for (int x = 0; x < qMap.size(); x++) {
1360 paramIn(cp, csprintf("qMap%d.sys", x), qMap[x].first);
1361 paramIn(cp, csprintf("qMap%d.qname", x), qMap[x].second.first);
1362 paramIn(cp, csprintf("qMap%d.id", x), qMap[x].second.second);
1363 }
1364
1365
1366 // qData (vector<AnnotateList>)
1367 qData.resize(qSize.size());
1368 for (int x = 0; x < qSize.size(); x++) {
1369 if (!qSize[x])
1370 continue;
1371 for (int y = 0; y < qSize[x]; y++) {
1372 AnnDataPtr a = std::make_shared<AnnotateData>();
1373 a->unserializeSection(cp, csprintf("Q%d_%d", x, y));
1374 data.push_back(a);
1375 qData[x].push_back(a);
1376 }
1377 }
1378 }
1379
1380 void
1381 CPA::AnnotateData::serialize(CheckpointOut &cp) const
1382 {
1383 SERIALIZE_SCALAR(time);
1384 SERIALIZE_SCALAR(data);
1385 SERIALIZE_SCALAR(sm);
1386 SERIALIZE_SCALAR(stq);
1387 SERIALIZE_SCALAR(op);
1388 SERIALIZE_SCALAR(flag);
1389 SERIALIZE_SCALAR(cpu);
1390 }
1391
1392 void
1393 CPA::AnnotateData::unserialize(CheckpointIn &cp)
1394 {
1395 UNSERIALIZE_SCALAR(time);
1396 UNSERIALIZE_SCALAR(data);
1397 orig_data = data;
1398 UNSERIALIZE_SCALAR(sm);
1399 UNSERIALIZE_SCALAR(stq);
1400 UNSERIALIZE_SCALAR(op);
1401 UNSERIALIZE_SCALAR(flag);
1402 UNSERIALIZE_SCALAR(cpu);
1403 dump = true;
1404 }
1405
1406 CPA*
1407 CPAParams::create()
1408 {
1409 return new CPA(this);
1410 }
1411