2 * Copyright (c) 2006-2009 The Regents of The University of Michigan
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.
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.
31 #include "arch/utility.hh"
32 #include "arch/alpha/linux/threadinfo.hh"
33 #include "base/cp_annotate.hh"
34 #include "base/callback.hh"
35 #include "base/loader/object_file.hh"
36 #include "base/output.hh"
37 #include "base/trace.hh"
38 #include "cpu/thread_context.hh"
39 #include "sim/arguments.hh"
40 #include "sim/core.hh"
41 #include "sim/sim_exit.hh"
42 #include "sim/system.hh"
44 struct CPAIgnoreSymbol
49 #define CPA_IGNORE_SYMBOL(sym) { #sym, sizeof(#sym) }
51 CPAIgnoreSymbol ignoreSymbols
[] = {
52 CPA_IGNORE_SYMBOL("m5a_"),
53 CPA_IGNORE_SYMBOL("ret_from_sys_call"),
54 CPA_IGNORE_SYMBOL("ret_from_reschedule"),
55 CPA_IGNORE_SYMBOL("_spin_"),
56 CPA_IGNORE_SYMBOL("local_bh_"),
57 CPA_IGNORE_SYMBOL("restore_all"),
58 CPA_IGNORE_SYMBOL("Call_Pal_"),
59 CPA_IGNORE_SYMBOL("pal_post_interrupt"),
60 CPA_IGNORE_SYMBOL("rti_to_"),
61 CPA_IGNORE_SYMBOL("sys_int_2"),
62 CPA_IGNORE_SYMBOL("sys_interrupt"),
63 CPA_IGNORE_SYMBOL("normal_int"),
64 CPA_IGNORE_SYMBOL("TRAP_INTERRUPT_10_"),
65 CPA_IGNORE_SYMBOL("Trap_Interrupt"),
66 CPA_IGNORE_SYMBOL("do_entInt"),
67 CPA_IGNORE_SYMBOL("__do_softirq"),
68 CPA_IGNORE_SYMBOL("_end"),
69 CPA_IGNORE_SYMBOL("entInt"),
70 CPA_IGNORE_SYMBOL("entSys"),
73 #undef CPA_IGNORE_SYMBOL
76 using namespace TheISA
;
81 class AnnotateDumpCallback
: public Callback
87 virtual void process();
88 AnnotateDumpCallback(CPA
*_cpa
)
94 AnnotateDumpCallback::process()
102 : SimObject(p
), numSm(0), numSmt(0), numSys(0), numQs(0), conId(0)
105 fatal("Multiple annotation objects found in system");
108 _enabled
= p
->enabled
;
111 vector
<string
>::iterator i
;
112 i
= p
->user_apps
.begin();
114 while (i
!= p
->user_apps
.end()) {
115 ObjectFile
*of
= createObjectFile(*i
);
118 fatal("Couldn't load symbols from file: %s\n", *i
);
120 sf
.erase(0, sf
.rfind('/') + 1);;
121 DPRINTFN("file %s short: %s\n", *i
, sf
);
122 userApp
[sf
] = new SymbolTable
;
123 bool result1
= of
->loadGlobalSymbols(userApp
[sf
]);
124 bool result2
= of
->loadLocalSymbols(userApp
[sf
]);
125 if (!result1
|| !result2
)
127 assert(result1
&& result2
);
135 osbin
= simout
.create("annotate.bin", true);
136 // MAGIC version number 'M''5''A'N' + version/capabilities
137 ah
.version
= 0x4D35414E00000101ULL
;
140 osbin
->write((char*)&ah
, sizeof(AnnotateHeader
));
142 registerExitCallback(new AnnotateDumpCallback(this));
145 CPA::swSmBegin(ThreadContext
*tc
)
154 if (!TheISA::inUserMode(tc
))
155 debugSymbolTable
->findNearestSymbol(
156 tc
->readIntReg(ReturnAddressReg
), st
, junk
);
158 CopyStringOut(tc
, sm
, args
[0], 50);
159 System
*sys
= tc
->getSystemPtr();
160 StringWrap
name(sys
->name());
163 warn("Got null SM at tick %d\n", curTick
);
165 int sysi
= getSys(sys
);
166 int smi
= getSm(sysi
, sm
, args
[1]);
167 DPRINTF(Annotate
, "Starting machine: %s(%d) sysi: %d id: %#x\n", sm
,
169 DPRINTF(Annotate
, "smMap[%d] = %d, %s, %#x\n", smi
,
170 smMap
[smi
-1].first
, smMap
[smi
-1].second
.first
,
171 smMap
[smi
-1].second
.second
);
173 uint64_t frame
= getFrame(tc
);
174 StackId sid
= StackId(sysi
, frame
);
176 // check if we need to link to the previous state machine
178 if (flags
& FL_LINK
) {
179 if (smStack
[sid
].size()) {
180 int prev_smi
= smStack
[sid
].back();
181 DPRINTF(Annotate
, "Linking from %d to state machine %s(%d) [%#x]\n",
182 prev_smi
, sm
, smi
, args
[1]);
185 DPRINTF(Annotate
, "LnMap already contains entry for %d of %d\n",
187 assert(lnMap
[smi
] == 0);
188 lnMap
[smi
] = prev_smi
;
190 add(OP_LINK
, FL_NONE
, tc
->contextId(), prev_smi
, smi
);
192 DPRINTF(Annotate
, "Not Linking to state machine %s(%d) [%#x]\n",
198 smStack
[sid
].push_back(smi
);
200 DPRINTF(Annotate
, "Stack Now (%#X):\n", frame
);
201 for (int x
= smStack
[sid
].size()-1; x
>= 0; x
--)
202 DPRINTF(Annotate
, "-- %d\n", smStack
[sid
][x
]);
204 // reset the sw state exculsion to false
209 Id id
= Id(sm
, frame
);
210 if (scLinks
[sysi
-1][id
]) {
211 AnnDataPtr an
= scLinks
[sysi
-1][id
];
212 scLinks
[sysi
-1].erase(id
);
216 "Found prev unknown linking from %d to state machine %s(%d)\n",
220 DPRINTF(Annotate
, "LnMap already contains entry for %d of %d\n",
222 assert(lnMap
[smi
] == 0);
226 // add a new begin ifwe have that info
228 DPRINTF(Annotate
, "st: %s smi: %d stCache.size %d\n", st
,
229 smi
, stCache
.size());
230 int sti
= getSt(sm
, st
);
231 lastState
[smi
] = sti
;
232 add(OP_BEGIN
, FL_NONE
, tc
->contextId(), smi
, sti
);
237 CPA::swSmEnd(ThreadContext
*tc
)
244 CopyStringOut(tc
, sm
, args
[0], 50);
245 System
*sys
= tc
->getSystemPtr();
246 doSwSmEnd(sys
, tc
->contextId(), sm
, getFrame(tc
));
250 CPA::doSwSmEnd(System
*sys
, int cpuid
, string sm
, uint64_t frame
)
252 int sysi
= getSys(sys
);
253 StackId sid
= StackId(sysi
, frame
);
256 // reset the sw state exculsion to false
261 int smib
= smStack
[sid
].back();
262 StringWrap
name(sys
->name());
263 DPRINTF(Annotate
, "Ending machine: %s[%d, %#x] (%d?)\n", sm
, sysi
,
266 if (!smStack
[sid
].size() || smMap
[smib
-1].second
.first
!= sm
) {
267 DPRINTF(Annotate
, "State Machine not unwinding correctly. sid: %d, %#x"
268 " top of stack: %s Current Stack:\n",
269 sysi
, frame
, smMap
[smib
-1].second
.first
);
270 for (int x
= smStack
[sid
].size()-1; x
>= 0; x
--)
271 DPRINTF(Annotate
, "-- %d\n", smStack
[sid
][x
]);
272 DPRINTF(Annotate
, "Ending machine: %s; end stack: %s\n", sm
,
273 smMap
[smib
-1].second
.first
);
275 warn("State machine stack not unwinding correctly at %d\n", curTick
);
278 "State machine ending:%s sysi:%d id:%#x back:%d getSm:%d\n",
279 sm
, sysi
, smMap
[smib
-1].second
.second
, smStack
[sid
].back(),
280 getSm(sysi
, sm
, smMap
[smib
-1].second
.second
));
281 assert(getSm(sysi
, sm
, smMap
[smib
-1].second
.second
) ==
282 smStack
[sid
].back());
284 int smi
= smStack
[sid
].back();
285 smStack
[sid
].pop_back();
288 DPRINTF(Annotate
, "Linking %d back to %d\n", smi
, lnMap
[smi
]);
289 add(OP_LINK
, FL_NONE
, cpuid
, smi
, lnMap
[smi
]);
293 if (smStack
[sid
].size()) {
294 add(OP_BEGIN
, FL_NONE
, cpuid
, smi
, lastState
[smi
]);
297 DPRINTF(Annotate
, "Stack Now:\n");
298 for (int x
= smStack
[sid
].size()-1; x
>= 0; x
--)
299 DPRINTF(Annotate
, "-- %d\n", smStack
[sid
][x
]);
305 CPA::swExplictBegin(ThreadContext
*tc
)
312 CopyStringOut(tc
, st
, args
[1], 50);
314 StringWrap
name(tc
->getSystemPtr()->name());
315 DPRINTF(Annotate
, "Explict begin of state %s\n", st
);
316 uint32_t flags
= args
[0];
318 warn("BAD state encountered: at cycle %d: %s\n", curTick
, st
);
319 swBegin(tc
->getSystemPtr(), tc
->contextId(), st
, getFrame(tc
), true, args
[0]);
323 CPA::swAutoBegin(ThreadContext
*tc
, Addr next_pc
)
330 SymbolTable
*symtab
= NULL
;
333 if (!TheISA::inUserMode(tc
)) {
334 debugSymbolTable
->findNearestSymbol(next_pc
, sym
, sym_addr
);
335 symtab
= debugSymbolTable
;
337 Linux::ThreadInfo
ti(tc
);
338 string app
= ti
.curTaskName();
339 if (userApp
.count(app
))
340 userApp
[app
]->findNearestSymbol(next_pc
, sym
, sym_addr
);
344 swBegin(tc
->getSystemPtr(), tc
->contextId(), sym
, getFrame(tc
));
348 CPA::swBegin(System
*sys
, int cpuid
, std::string st
, uint64_t frame
, bool expl
,
353 while (ignoreSymbols
[x
].len
)
355 len
= ignoreSymbols
[x
].len
;
356 if (!st
.compare(0,len
, ignoreSymbols
[x
].symbol
, len
))
361 int sysi
= getSys(sys
);
362 StackId sid
= StackId(sysi
, frame
);
363 // if expl is true suspend symbol table based states
364 if (!smStack
[sid
].size())
366 if (!expl
&& swExpl
[sid
])
370 DPRINTFS(AnnotateVerbose
, sys
, "SwBegin: %s sysi: %d\n", st
, sysi
);
371 int smi
= smStack
[sid
].back();
372 int sti
= getSt(smMap
[smi
-1].second
.first
, st
);
373 if (lastState
[smi
] != sti
) {
374 lastState
[smi
] = sti
;
375 add(OP_BEGIN
, flags
, cpuid
, smi
, sti
);
380 CPA::swEnd(ThreadContext
*tc
)
387 if (!TheISA::inUserMode(tc
))
388 debugSymbolTable
->findNearestSymbol(
389 tc
->readIntReg(ReturnAddressReg
), st
, junk
);
390 System
*sys
= tc
->getSystemPtr();
391 StringWrap
name(sys
->name());
393 int sysi
= getSys(sys
);
394 StackId sid
= StackId(sysi
, getFrame(tc
));
395 if (!smStack
[sid
].size()) {
396 DPRINTF(Annotate
, "Explict end of State: %s IGNORED\n", st
);
399 DPRINTF(Annotate
, "Explict end of State: %s\n", st
);
400 // return back to symbol table based states
402 int smi
= smStack
[sid
].back();
404 int sti
= getSt(smMap
[smi
-1].second
.first
, st
);
405 lastState
[smi
] = sti
;
406 add(OP_BEGIN
, FL_NONE
, tc
->contextId(), smi
, sti
);
411 CPA::swQ(ThreadContext
*tc
)
418 uint64_t id
= args
[0];
419 CopyStringOut(tc
, q
, args
[1], 50);
420 int32_t count
= args
[2];
421 System
*sys
= tc
->getSystemPtr();
423 int sysi
= getSys(sys
);
424 StackId sid
= StackId(sysi
, getFrame(tc
));
425 if (!smStack
[sid
].size())
427 int smi
= smStack
[sid
].back();
430 int qi
= getQ(sysi
, q
, id
);
432 //warn("Tried to queue 0 bytes in %s, ignoring\n", q);
435 DPRINTFS(AnnotateQ
, sys
,
436 "swQ: %s[%#x] cur size %d %d bytes: %d adding: %d\n",
437 q
, id
, qSize
[qi
-1], qData
[qi
-1].size(), qBytes
[qi
-1], count
);
438 doQ(sys
, FL_NONE
, tc
->contextId(), smi
, q
, qi
, count
);
442 CPA::swDq(ThreadContext
*tc
)
449 uint64_t id
= args
[0];
450 CopyStringOut(tc
, q
, args
[1], 50);
451 int32_t count
= args
[2];
452 System
*sys
= tc
->getSystemPtr();
454 int sysi
= getSys(sys
);
455 StackId sid
= StackId(sysi
, getFrame(tc
));
456 if (!smStack
[sid
].size())
458 int smi
= smStack
[sid
].back();
459 int qi
= getQ(sysi
, q
, id
);
462 DPRINTFS(AnnotateQ
, sys
,
463 "swDq: %s[%#x] cur size %d %d bytes: %d removing: %d\n",
464 q
, id
, qSize
[qi
-1], qData
[qi
-1].size(), qBytes
[qi
-1], count
);
467 doDq(sys
, FL_NONE
, tc
->contextId(), smi
, q
, qi
, count
);
471 CPA::swPq(ThreadContext
*tc
)
478 uint64_t id
= args
[0];
479 CopyStringOut(tc
, q
, args
[1], 50);
480 System
*sys
= tc
->getSystemPtr();
481 int32_t count
= args
[2];
483 int sysi
= getSys(sys
);
484 StackId sid
= StackId(sysi
, getFrame(tc
));
485 if (!smStack
[sid
].size())
487 int smi
= smStack
[sid
].back();
488 int qi
= getQ(sysi
, q
, id
);
491 DPRINTFS(AnnotateQ
, sys
,
492 "swPq: %s [%#x] cur size %d %d bytes: %d peeking: %d\n",
493 q
, id
, qSize
[qi
-1], qData
[qi
-1].size(), qBytes
[qi
-1], count
);
496 if (qBytes
[qi
-1] < count
) {
499 fatal("Queue %s peeking with not enough bytes available in queue!\n", q
);
502 add(OP_PEEK
, FL_NONE
, tc
->contextId(), smi
, qi
, count
);
506 CPA::swRq(ThreadContext
*tc
)
513 uint64_t id
= args
[0];
514 CopyStringOut(tc
, q
, args
[1], 50);
515 System
*sys
= tc
->getSystemPtr();
516 int32_t count
= args
[2];
518 int sysi
= getSys(sys
);
519 StackId sid
= StackId(sysi
, getFrame(tc
));
520 if (!smStack
[sid
].size())
522 int smi
= smStack
[sid
].back();
523 int qi
= getQ(sysi
, q
, id
);
526 DPRINTFS(AnnotateQ
, sys
,
527 "swRq: %s [%#x] cur size %d %d bytes: %d reserve: %d\n",
528 q
, id
, qSize
[qi
-1], qData
[qi
-1].size(), qBytes
[qi
-1], count
);
532 add(OP_RESERVE
, FL_NONE
, tc
->contextId(), smi
, qi
, count
);
537 CPA::swWf(ThreadContext
*tc
)
544 uint64_t id
= args
[0];
545 CopyStringOut(tc
, q
, args
[1], 50);
546 System
*sys
= tc
->getSystemPtr();
547 int32_t count
= args
[3];
549 int sysi
= getSys(sys
);
550 StackId sid
= StackId(sysi
, getFrame(tc
));
551 if (!smStack
[sid
].size())
553 int smi
= smStack
[sid
].back();
554 int qi
= getQ(sysi
, q
, id
);
555 add(OP_WAIT_FULL
, FL_NONE
, tc
->contextId(), smi
, qi
, count
);
559 CopyStringOut(tc
, sm
, args
[2], 50);
560 doSwSmEnd(tc
->getSystemPtr(), tc
->contextId(), sm
, getFrame(tc
));
565 CPA::swWe(ThreadContext
*tc
)
572 uint64_t id
= args
[0];
573 CopyStringOut(tc
, q
, args
[1], 50);
574 System
*sys
= tc
->getSystemPtr();
575 int32_t count
= args
[3];
577 int sysi
= getSys(sys
);
578 StackId sid
= StackId(sysi
, getFrame(tc
));
579 if (!smStack
[sid
].size())
581 int smi
= smStack
[sid
].back();
582 int qi
= getQ(sysi
, q
, id
);
583 add(OP_WAIT_EMPTY
, FL_NONE
, tc
->contextId(), smi
, qi
, count
);
587 CopyStringOut(tc
, sm
, args
[2], 50);
588 doSwSmEnd(tc
->getSystemPtr(), tc
->contextId(), sm
, getFrame(tc
));
593 CPA::swSq(ThreadContext
*tc
)
600 uint64_t id
= args
[0];
601 CopyStringOut(tc
, q
, args
[1], 50);
602 System
*sys
= tc
->getSystemPtr();
603 StringWrap
name(sys
->name());
604 int32_t size
= args
[2];
607 int sysi
= getSys(sys
);
608 StackId sid
= StackId(sysi
, getFrame(tc
));
609 if (!smStack
[sid
].size())
611 int smi
= smStack
[sid
].back();
612 int qi
= getQ(sysi
, q
, id
);
613 DPRINTF(AnnotateQ
, "swSq: %s [%#x] cur size: %d bytes: %d, new size: %d\n",
614 q
, id
, qSize
[qi
-1], qBytes
[qi
-1], size
);
616 if (FL_RESET
& flags
) {
617 DPRINTF(AnnotateQ
, "Resetting Queue %s\n", q
);
618 add(OP_SIZE_QUEUE
, FL_NONE
, tc
->contextId(), smi
, qi
, 0);
624 if (qBytes
[qi
-1] < size
)
625 doQ(sys
, FL_NONE
, tc
->contextId(), smi
, q
, qi
, size
- qBytes
[qi
-1]);
626 else if (qBytes
[qi
-1] > size
) {
627 DPRINTF(AnnotateQ
, "removing for resize of queue %s\n", q
);
628 add(OP_SIZE_QUEUE
, FL_NONE
, tc
->contextId(), smi
, qi
, size
);
635 int need
= qBytes
[qi
-1] - size
;
638 int32_t tail_bytes
= qData
[qi
-1].back()->data
;
639 if (qSize
[qi
-1] <= 0 || qBytes
[qi
-1] < 0) {
642 fatal("Queue %s had inconsistancy when doing size queue!\n", q
);
644 if (tail_bytes
> need
) {
645 qData
[qi
-1].back()->data
-= need
;
647 } else if (tail_bytes
== need
) {
648 qData
[qi
-1].pop_back();
652 qData
[qi
-1].pop_back();
661 CPA::swAq(ThreadContext
*tc
)
668 uint64_t id
= args
[0];
669 CopyStringOut(tc
, q
, args
[1], 50);
670 System
*sys
= tc
->getSystemPtr();
671 StringWrap
name(sys
->name());
672 int32_t size
= args
[2];
674 int sysi
= getSys(sys
);
675 int qi
= getQ(sysi
, q
, id
);
676 if (qBytes
[qi
-1] != size
) {
677 DPRINTF(AnnotateQ
, "Queue %s [%#x] has inconsintant size\n", q
, id
);
680 std::list
<AnnDataPtr
>::iterator ai
= qData
[qi
-1].begin();
682 while (ai
!= qData
[qi
-1].end()) {
683 DPRINTF(AnnotateQ
, "--Element %d size %d\n", x
, (*ai
)->data
);
688 warn("%d: Queue Assert: SW said there should be %d byte(s) in %s,"
689 "however there are %d byte(s)\n",
690 curTick
, size
, q
, qBytes
[qi
-1]);
691 DPRINTF(AnnotateQ
, "%d: Queue Assert: SW said there should be %d"
692 " byte(s) in %s, however there are %d byte(s)\n",
693 curTick
, size
, q
, qBytes
[qi
-1]);
698 CPA::swLink(ThreadContext
*tc
)
705 CopyStringOut(tc
, lsm
, args
[0], 50);
706 System
*sys
= tc
->getSystemPtr();
707 StringWrap
name(sys
->name());
709 int sysi
= getSys(sys
);
710 StackId sid
= StackId(sysi
, getFrame(tc
));
711 if (!smStack
[sid
].size())
713 int smi
= smStack
[sid
].back();
714 int lsmi
= getSm(sysi
, lsm
, args
[1]);
716 DPRINTF(Annotate
, "Linking from %d to state machine %s(%d) [%#x]\n",
717 smi
, lsm
, lsmi
, args
[1]);
720 DPRINTF(Annotate
, "LnMap already contains entry for %d of %d\n",
722 assert(lnMap
[lsmi
] == 0);
725 add(OP_LINK
, FL_NONE
, tc
->contextId(), smi
, lsmi
);
729 CopyStringOut(tc
, sm
, args
[2], 50);
730 doSwSmEnd(tc
->getSystemPtr(), tc
->contextId(), sm
, getFrame(tc
));
735 CPA::swIdentify(ThreadContext
*tc
)
741 int sysi
= getSys(tc
->getSystemPtr());
742 StackId sid
= StackId(sysi
, getFrame(tc
));
743 if (!smStack
[sid
].size())
745 int smi
= smStack
[sid
].back();
747 DPRINTFS(Annotate
, tc
->getSystemPtr(), "swIdentify: id %#X\n", args
[0]);
749 add(OP_IDENT
, FL_NONE
, tc
->contextId(), smi
, 0, args
[0]);
753 CPA::swGetId(ThreadContext
*tc
)
758 uint64_t id
= ++conId
;
759 int sysi
= getSys(tc
->getSystemPtr());
760 StackId sid
= StackId(sysi
, getFrame(tc
));
761 if (!smStack
[sid
].size())
762 panic("swGetId called without a state machine stack!");
763 int smi
= smStack
[sid
].back();
765 DPRINTFS(Annotate
, tc
->getSystemPtr(), "swGetId: id %#X\n", id
);
767 add(OP_IDENT
, FL_NONE
, tc
->contextId(), smi
, 0, id
);
773 CPA::swSyscallLink(ThreadContext
*tc
)
780 CopyStringOut(tc
, lsm
, args
[0], 50);
781 System
*sys
= tc
->getSystemPtr();
782 StringWrap
name(sys
->name());
783 int sysi
= getSys(sys
);
785 Id id
= Id(lsm
, getFrame(tc
));
786 StackId sid
= StackId(sysi
, getFrame(tc
));
788 if (!smStack
[sid
].size())
791 int smi
= smStack
[sid
].back();
793 DPRINTF(Annotate
, "Linking from %d to state machine %s(UNKNOWN)\n",
796 if (scLinks
[sysi
-1][id
])
798 "scLinks already contains entry for system %d %s[%x] of %d\n",
799 sysi
, lsm
, getFrame(tc
), scLinks
[sysi
-1][id
]);
800 assert(scLinks
[sysi
-1][id
] == 0);
801 scLinks
[sysi
-1][id
] = add(OP_LINK
, FL_NONE
, tc
->contextId(), smi
, 0xFFFF);
802 scLinks
[sysi
-1][id
]->dump
= false;
806 CopyStringOut(tc
, sm
, args
[1], 50);
807 doSwSmEnd(tc
->getSystemPtr(), tc
->contextId(), sm
, getFrame(tc
));
812 CPA::add(int t
, int f
, int c
, int sm
, int stq
, int32_t d
)
814 AnnDataPtr an
= new AnnotateData
;
827 DPRINTF(AnnotateVerbose
, "Annotate: op: %d flags: 0x%x sm: %d state: %d time: %d, data: %d\n",
828 an
->op
, an
->flag
, an
->sm
, an
->stq
, an
->time
, an
->data
);
830 // Don't dump Links because we might be setting no-dump on it
831 if (an
->op
!= OP_LINK
)
840 std::streampos curpos
= osbin
->tellp();
843 // Output the various state machines and their corresponding states
844 *osbin
<< "# Automatically generated state machine descriptor file" << endl
;
846 *osbin
<< "sms = {}" << endl
<< endl
;
847 vector
<string
> state_machines
;
848 state_machines
.resize(numSmt
+1);
850 // State machines, id -> states
851 SCache::iterator i
= smtCache
.begin();
852 while (i
!= smtCache
.end()) {
853 state_machines
[i
->second
] = i
->first
;
857 for (int x
= 1; x
< state_machines
.size(); x
++) {
858 vector
<string
> states
;
859 states
.resize(numSt
[x
-1]+1);
860 assert(x
-1 < stCache
.size());
861 SCache::iterator i
= stCache
[x
-1].begin();
862 while (i
!= stCache
[x
-1].end()) {
863 states
[i
->second
] = i
->first
;
866 *osbin
<< "sms[\"" << state_machines
[x
] << "\"] = [\"NULL\"";
867 for (int y
= 1; y
< states
.size(); y
++)
868 *osbin
<< ", \"" << states
[y
] << "\"";
869 *osbin
<< "]" << endl
;
872 *osbin
<< endl
<< endl
<< endl
;
874 // state machine number -> system, name, id
875 *osbin
<< "smNum = [\"NULL\"";
876 for (int x
= 0; x
< smMap
.size(); x
++)
877 *osbin
<< ", (" << smMap
[x
].first
<< ", \"" << smMap
[x
].second
.first
<<
878 "\", " << smMap
[x
].second
.second
<< ")";
879 *osbin
<< "]" << endl
;
881 *osbin
<< endl
<< endl
<< endl
;
883 // Output the systems
884 vector
<string
> systems
;
885 systems
.resize(numSys
+1);
886 NameCache::iterator i2
= nameCache
.begin();
887 while (i2
!= nameCache
.end()) {
888 systems
[i2
->second
.second
] = i2
->second
.first
;
892 *osbin
<< "sysNum = [\"NULL\"";
893 for (int x
= 1; x
< systems
.size(); x
++) {
894 *osbin
<< ", \"" << systems
[x
] << "\"";
896 *osbin
<< "]" << endl
;
898 // queue number -> system, qname, qid
899 *osbin
<< "queues = [\"NULL\"";
900 for (int x
= 0; x
< qMap
.size(); x
++)
901 *osbin
<< ", (" << qMap
[x
].first
<< ", \"" << qMap
[x
].second
.first
<<
902 "\", " << qMap
[x
].second
.second
<< ")";
903 *osbin
<< "]" << endl
;
905 *osbin
<< "smComb = [s for s in [(i,r) for i in xrange(1,len(sysNum)) "
906 << "for r in xrange (1,len(smNum))]]" << endl
;
907 ah
.key_len
= osbin
->tellp() - curpos
;
910 curpos
= osbin
->tellp();
913 for (int x
= 0; x
< annotateIdx
.size(); x
++)
914 osbin
->write((char*)&annotateIdx
[x
], sizeof(uint64_t));
915 ah
.idx_len
= osbin
->tellp() - curpos
;
918 osbin
->write((char*)&ah
, sizeof(AnnotateHeader
));
927 list
<AnnDataPtr
>::iterator i
;
934 // Dump the data every
935 if (!all
&& data
.size() < 10000)
938 DPRINTF(Annotate
, "Writing %d\n", data
.size());
939 while (i
!= data
.end()) {
942 // If we can't dump this record, hold here
943 if (!an
->dump
&& !all
)
947 if (ah
.num_recs
% 100000 == 0)
948 annotateIdx
.push_back(osbin
->tellp());
951 osbin
->write((char*)&(an
->time
), sizeof(an
->time
));
952 osbin
->write((char*)&(an
->orig_data
), sizeof(an
->orig_data
));
953 osbin
->write((char*)&(an
->sm
), sizeof(an
->sm
));
954 osbin
->write((char*)&(an
->stq
), sizeof(an
->stq
));
955 osbin
->write((char*)&(an
->op
), sizeof(an
->op
));
956 osbin
->write((char*)&(an
->flag
), sizeof(an
->flag
));
957 osbin
->write((char*)&(an
->cpu
), sizeof(an
->cpu
));
960 if (data
.begin() != i
)
961 data
.erase(data
.begin(), i
);
968 CPA::doQ(System
*sys
, int flags
, int cpuid
, int sm
,
969 string q
, int qi
, int count
)
972 qBytes
[qi
-1] += count
;
973 if (qSize
[qi
-1] > 2501 || qBytes
[qi
-1] > 2000000000)
974 warn("Queue %s is %d elements/%d bytes, "
975 "maybe things aren't being removed?\n",
976 q
, qSize
[qi
-1], qBytes
[qi
-1]);
978 qData
[qi
-1].push_front(add(OP_QUEUE
, flags
, cpuid
, sm
, qi
, count
));
980 qData
[qi
-1].push_back(add(OP_QUEUE
, flags
, cpuid
, sm
, qi
, count
));
981 DPRINTFS(AnnotateQ
, sys
, "Queing in queue %s size now %d/%d\n",
982 q
, qSize
[qi
-1], qBytes
[qi
-1]);
983 assert(qSize
[qi
-1] >= 0);
984 assert(qBytes
[qi
-1] >= 0);
989 CPA::doDq(System
*sys
, int flags
, int cpuid
, int sm
,
990 string q
, int qi
, int count
)
993 StringWrap
name(sys
->name());
995 add(OP_DEQUEUE
, flags
, cpuid
, sm
, qi
, count
);
999 DPRINTF(AnnotateQ
, "Dequeing all data in queue %s size now %d/%d\n",
1000 q
, qSize
[qi
-1], qBytes
[qi
-1]);
1005 if (qSize
[qi
-1] <= 0 || qBytes
[qi
-1] <= 0 || !qData
[qi
-1].size()) {
1008 fatal("Queue %s dequing with no data available in queue!\n",
1011 assert(qSize
[qi
-1] >= 0);
1012 assert(qBytes
[qi
-1] >= 0);
1013 assert(qData
[qi
-1].size());
1015 int32_t need
= count
;
1016 qBytes
[qi
-1] -= count
;
1017 if (qBytes
[qi
-1] < 0) {
1020 fatal("Queue %s dequing with no bytes available in queue!\n",
1025 int32_t head_bytes
= qData
[qi
-1].front()->data
;
1026 if (qSize
[qi
-1] <= 0 || qBytes
[qi
-1] < 0) {
1029 fatal("Queue %s dequing with nothing in queue!\n",
1033 if (head_bytes
> need
) {
1034 qData
[qi
-1].front()->data
-= need
;
1036 } else if (head_bytes
== need
) {
1037 qData
[qi
-1].pop_front();
1041 qData
[qi
-1].pop_front();
1047 add(OP_DEQUEUE
, flags
, cpuid
, sm
, qi
, count
);
1048 DPRINTF(AnnotateQ
, "Dequeing in queue %s size now %d/%d\n",
1049 q
, qSize
[qi
-1], qBytes
[qi
-1]);
1055 CPA::serialize(std::ostream
&os
)
1058 SERIALIZE_SCALAR(numSm
);
1059 SERIALIZE_SCALAR(numSmt
);
1060 arrayParamOut(os
, "numSt", numSt
);
1061 arrayParamOut(os
, "numQ", numQ
);
1062 SERIALIZE_SCALAR(numSys
);
1063 SERIALIZE_SCALAR(numQs
);
1064 SERIALIZE_SCALAR(conId
);
1065 arrayParamOut(os
, "qSize", qSize
);
1066 arrayParamOut(os
, "qSize", qSize
);
1067 arrayParamOut(os
, "qBytes", qBytes
);
1069 std::list
<AnnDataPtr
>::iterator ai
;
1074 // smtCache (SCache)
1077 i
= smtCache
.begin();
1078 while (i
!= smtCache
.end()) {
1079 paramOut(os
, csprintf("smtCache%d.str", x
), i
->first
);
1080 paramOut(os
, csprintf("smtCache%d.int", x
), i
->second
);
1084 // stCache (StCache)
1085 for (x
= 0; x
< stCache
.size(); x
++) {
1086 i
= stCache
[x
].begin();
1088 while (i
!= stCache
[x
].end()) {
1089 paramOut(os
, csprintf("stCache%d_%d.str", x
, y
), i
->first
);
1090 paramOut(os
, csprintf("stCache%d_%d.int", x
, y
), i
->second
);
1096 IdHCache::iterator idi
;
1097 for (x
= 0; x
< qCache
.size(); x
++) {
1098 idi
= qCache
[x
].begin();
1100 while (idi
!= qCache
[x
].end()) {
1101 paramOut(os
, csprintf("qCache%d_%d.str", x
, y
), idi
->first
.first
);
1102 paramOut(os
, csprintf("qCache%d_%d.id", x
, y
), idi
->first
.second
);
1103 paramOut(os
, csprintf("qCache%d_%d.int", x
, y
), idi
->second
);
1108 // smCache (IdCache)
1109 for (x
= 0; x
< smCache
.size(); x
++) {
1110 idi
= smCache
[x
].begin();
1112 paramOut(os
, csprintf("smCache%d", x
), smCache
[x
].size());
1113 while (idi
!= smCache
[x
].end()) {
1114 paramOut(os
, csprintf("smCache%d_%d.str", x
, y
), idi
->first
.first
);
1115 paramOut(os
, csprintf("smCache%d_%d.id", x
, y
), idi
->first
.second
);
1116 paramOut(os
, csprintf("smCache%d_%d.int", x
, y
), idi
->second
);
1121 // scLinks (ScCache) -- data not serialize
1124 // namecache (NameCache)
1125 NameCache::iterator ni
;
1127 ni
= nameCache
.begin();
1129 while (ni
!= nameCache
.end()) {
1130 paramOut(os
, csprintf("nameCache%d.name", x
), ni
->first
->name());
1131 paramOut(os
, csprintf("nameCache%d.str", x
), ni
->second
.first
);
1132 paramOut(os
, csprintf("nameCache%d.int", x
), ni
->second
.second
);
1136 // smStack (SmStack)
1137 SmStack::iterator si
;
1138 si
= smStack
.begin();
1140 paramOut(os
, "smStackIdCount", smStack
.size());
1141 while (si
!= smStack
.end()) {
1142 paramOut(os
, csprintf("smStackId%d.sys", x
), si
->first
.first
);
1143 paramOut(os
, csprintf("smStackId%d.frame", x
), si
->first
.second
);
1144 paramOut(os
, csprintf("smStackId%d.count", x
), si
->second
.size());
1145 for (y
= 0; y
< si
->second
.size(); y
++)
1146 paramOut(os
, csprintf("smStackId%d_%d", x
, y
), si
->second
[y
]);
1152 LinkMap::iterator li
;
1154 paramOut(os
, "lnMapSize", lnMap
.size());
1155 while (li
!= lnMap
.end()) {
1156 paramOut(os
, csprintf("lnMap%d.smi", x
), li
->first
);
1157 paramOut(os
, csprintf("lnMap%d.lsmi", x
), li
->second
);
1162 SwExpl::iterator swexpli
;
1163 swexpli
= swExpl
.begin();
1165 paramOut(os
, "swExplCount", swExpl
.size());
1166 while (swexpli
!= swExpl
.end()) {
1167 paramOut(os
, csprintf("swExpl%d.sys", x
), swexpli
->first
.first
);
1168 paramOut(os
, csprintf("swExpl%d.frame", x
), swexpli
->first
.second
);
1169 paramOut(os
, csprintf("swExpl%d.swexpl", x
), swexpli
->second
);
1176 ii
= lastState
.begin();
1177 paramOut(os
, "lastStateSize", lastState
.size());
1178 while (ii
!= lastState
.end()) {
1179 paramOut(os
, csprintf("lastState%d.smi", x
), ii
->first
);
1180 paramOut(os
, csprintf("lastState%d.sti", x
), ii
->second
);
1185 for (x
= 0; x
< smMap
.size(); x
++) {
1186 paramOut(os
, csprintf("smMap%d.sys", x
), smMap
[x
].first
);
1187 paramOut(os
, csprintf("smMap%d.smname", x
), smMap
[x
].second
.first
);
1188 paramOut(os
, csprintf("smMap%d.id", x
), smMap
[x
].second
.second
);
1192 for (x
= 0; x
< qMap
.size(); x
++) {
1193 paramOut(os
, csprintf("qMap%d.sys", x
), qMap
[x
].first
);
1194 paramOut(os
, csprintf("qMap%d.qname", x
), qMap
[x
].second
.first
);
1195 paramOut(os
, csprintf("qMap%d.id", x
), qMap
[x
].second
.second
);
1198 // qData (vector<AnnotateList>)
1199 for(x
= 0; x
< qData
.size(); x
++) {
1200 if (!qData
[x
].size())
1203 ai
= qData
[x
].begin();
1204 while (ai
!= qData
[x
].end()) {
1205 nameOut(os
, csprintf("%s.Q%d_%d", name(), x
, y
));
1206 (*ai
)->serialize(os
);
1214 CPA::unserialize(Checkpoint
*cp
, const std::string
§ion
)
1216 UNSERIALIZE_SCALAR(numSm
);
1217 UNSERIALIZE_SCALAR(numSmt
);
1218 arrayParamIn(cp
, section
, "numSt", numSt
);
1219 arrayParamIn(cp
, section
, "numQ", numQ
);
1220 UNSERIALIZE_SCALAR(numSys
);
1221 UNSERIALIZE_SCALAR(numQs
);
1222 UNSERIALIZE_SCALAR(conId
);
1223 arrayParamIn(cp
, section
, "qSize", qSize
);
1224 arrayParamIn(cp
, section
, "qBytes", qBytes
);
1230 for (int x
= 0; x
< numSmt
; x
++) {
1231 paramIn(cp
, section
, csprintf("smtCache%d.str", x
), str
);
1232 paramIn(cp
, section
, csprintf("smtCache%d.int", x
), smi
);
1233 smtCache
[str
] = smi
;
1236 // stCache (StCache)
1237 stCache
.resize(numSmt
);
1238 for (int x
= 0; x
< numSmt
; x
++) {
1239 for (int y
= 0; y
< numSt
[x
]; y
++) {
1240 paramIn(cp
, section
, csprintf("stCache%d_%d.str", x
,y
), str
);
1241 paramIn(cp
, section
, csprintf("stCache%d_%d.int", x
,y
), smi
);
1242 stCache
[x
][str
] = smi
;
1248 qCache
.resize(numSys
);
1249 for (int x
= 0; x
< numSys
; x
++) {
1250 for (int y
= 0; y
< numQ
[x
]; y
++) {
1251 paramIn(cp
, section
, csprintf("qCache%d_%d.str", x
,y
), str
);
1252 paramIn(cp
, section
, csprintf("qCache%d_%d.id", x
,y
), id
);
1253 paramIn(cp
, section
, csprintf("qCache%d_%d.int", x
,y
), smi
);
1254 qCache
[x
][Id(str
,id
)] = smi
;
1258 // smCache (IdCache)
1259 smCache
.resize(numSys
);
1260 for (int x
= 0; x
< numSys
; x
++) {
1262 paramIn(cp
, section
, csprintf("smCache%d", x
), size
);
1263 for (int y
= 0; y
< size
; y
++) {
1264 paramIn(cp
, section
, csprintf("smCache%d_%d.str", x
,y
), str
);
1265 paramIn(cp
, section
, csprintf("smCache%d_%d.id", x
,y
), id
);
1266 paramIn(cp
, section
, csprintf("smCache%d_%d.int", x
,y
), smi
);
1267 smCache
[x
][Id(str
,id
)] = smi
;
1271 // scLinks (ScCache) -- data not serialized, just creating one per sys
1272 for (int x
= 0; x
< numSys
; x
++)
1273 scLinks
.push_back(ScHCache());
1275 // nameCache (NameCache)
1276 for (int x
= 0; x
< numSys
; x
++) {
1282 objParamIn(cp
, section
, csprintf("nameCache%d.name", x
), sptr
);
1283 sys
= dynamic_cast<System
*>(sptr
);
1285 paramIn(cp
, section
, csprintf("nameCache%d.str", x
), str
);
1286 paramIn(cp
, section
, csprintf("nameCache%d.int", x
), sysi
);
1287 nameCache
[sys
] = std::make_pair
<std::string
,int>(str
, sysi
);
1292 paramIn(cp
, section
, "smStackIdCount", smStack_size
);
1293 for (int x
= 0; x
< smStack_size
; x
++) {
1297 paramIn(cp
, section
, csprintf("smStackId%d.sys", x
), sysi
);
1298 paramIn(cp
, section
, csprintf("smStackId%d.frame", x
), frame
);
1299 paramIn(cp
, section
, csprintf("smStackId%d.count", x
), count
);
1300 StackId sid
= StackId(sysi
, frame
);
1301 for (int y
= 0; y
< count
; y
++) {
1302 paramIn(cp
, section
, csprintf("smStackId%d_%d", x
, y
), smi
);
1303 smStack
[sid
].push_back(smi
);
1310 paramIn(cp
, section
, "lnMapSize", lnMap_size
);
1311 for (int x
= 0; x
< lnMap_size
; x
++) {
1312 paramIn(cp
, section
, csprintf("lnMap%d.smi", x
), smi
);
1313 paramIn(cp
, section
, csprintf("lnMap%d.lsmi", x
), lsmi
);
1319 paramIn(cp
, section
, "swExplCount", swExpl_size
);
1320 for (int x
= 0; x
< swExpl_size
; x
++) {
1324 paramIn(cp
, section
, csprintf("swExpl%d.sys", x
), sysi
);
1325 paramIn(cp
, section
, csprintf("swExpl%d.frame", x
), frame
);
1326 paramIn(cp
, section
, csprintf("swExpl%d.swexpl", x
), b
);
1327 StackId sid
= StackId(sysi
, frame
);
1334 paramIn(cp
, section
, "lastStateSize", lastState_size
);
1335 for (int x
= 0; x
< lastState_size
; x
++) {
1336 paramIn(cp
, section
, csprintf("lastState%d.smi", x
), smi
);
1337 paramIn(cp
, section
, csprintf("lastState%d.sti", x
), sti
);
1338 lastState
[smi
] = sti
;
1343 smMap
.resize(numSm
);
1344 for (int x
= 0; x
< smMap
.size(); x
++) {
1345 paramIn(cp
, section
, csprintf("smMap%d.sys", x
), smMap
[x
].first
);
1346 paramIn(cp
, section
, csprintf("smMap%d.smname", x
), smMap
[x
].second
.first
);
1347 paramIn(cp
, section
, csprintf("smMap%d.id", x
), smMap
[x
].second
.second
);
1352 for (int x
= 0; x
< qMap
.size(); x
++) {
1353 paramIn(cp
, section
, csprintf("qMap%d.sys", x
), qMap
[x
].first
);
1354 paramIn(cp
, section
, csprintf("qMap%d.qname", x
), qMap
[x
].second
.first
);
1355 paramIn(cp
, section
, csprintf("qMap%d.id", x
), qMap
[x
].second
.second
);
1359 // qData (vector<AnnotateList>)
1360 qData
.resize(qSize
.size());
1361 for (int x
= 0; x
< qSize
.size(); x
++) {
1364 for (int y
= 0; y
< qSize
[x
]; y
++) {
1365 AnnDataPtr a
= new AnnotateData
;
1366 a
->unserialize(cp
, csprintf("%s.Q%d_%d", section
, x
, y
));
1368 qData
[x
].push_back(a
);
1374 CPA::AnnotateData::serialize(std::ostream
&os
)
1376 SERIALIZE_SCALAR(time
);
1377 SERIALIZE_SCALAR(data
);
1378 SERIALIZE_SCALAR(sm
);
1379 SERIALIZE_SCALAR(stq
);
1380 SERIALIZE_SCALAR(op
);
1381 SERIALIZE_SCALAR(flag
);
1382 SERIALIZE_SCALAR(cpu
);
1386 CPA::AnnotateData::unserialize(Checkpoint
*cp
, const std::string
§ion
)
1388 UNSERIALIZE_SCALAR(time
);
1389 UNSERIALIZE_SCALAR(data
);
1391 UNSERIALIZE_SCALAR(sm
);
1392 UNSERIALIZE_SCALAR(stq
);
1393 UNSERIALIZE_SCALAR(op
);
1394 UNSERIALIZE_SCALAR(flag
);
1395 UNSERIALIZE_SCALAR(cpu
);
1402 return new CPA(this);