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 "base/cp_annotate.hh"
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"
48 struct CPAIgnoreSymbol
53 #define CPA_IGNORE_SYMBOL(sym) { #sym, sizeof(#sym) }
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"),
77 #undef CPA_IGNORE_SYMBOL
80 using namespace TheISA
;
85 class AnnotateDumpCallback
: public Callback
91 virtual void process();
92 AnnotateDumpCallback(CPA
*_cpa
)
98 AnnotateDumpCallback::process()
106 : SimObject(p
), numSm(0), numSmt(0), numSys(0), numQs(0), conId(0)
109 fatal("Multiple annotation objects found in system");
112 _enabled
= p
->enabled
;
115 vector
<string
>::iterator i
;
116 i
= p
->user_apps
.begin();
118 while (i
!= p
->user_apps
.end()) {
119 ObjectFile
*of
= createObjectFile(*i
);
122 fatal("Couldn't load symbols from file: %s\n", *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
)
131 assert(result1
&& result2
);
139 osbin
= simout
.create("annotate.bin", true);
140 // MAGIC version number 'M''5''A'N' + version/capabilities
141 ah
.version
= 0x4D35414E00000101ULL
;
144 osbin
->write((char*)&ah
, sizeof(AnnotateHeader
));
146 registerExitCallback(new AnnotateDumpCallback(this));
150 CPA::getFrame(ThreadContext
*tc
)
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
) &
160 CPA::swSmBegin(ThreadContext
*tc
)
169 if (!TheISA::inUserMode(tc
))
170 debugSymbolTable
->findNearestSymbol(
171 tc
->readIntReg(ReturnAddressReg
), st
, junk
);
173 tc
->getVirtProxy().readString(sm
, args
[0], 50);
174 System
*sys
= tc
->getSystemPtr();
175 StringWrap
name(sys
->name());
178 warn("Got null SM at tick %d\n", curTick());
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
,
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
);
188 uint64_t frame
= getFrame(tc
);
189 StackId sid
= StackId(sysi
, frame
);
191 // check if we need to link to the previous state machine
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]);
200 DPRINTF(Annotate
, "LnMap already contains entry for %d of %d\n",
202 assert(lnMap
[smi
] == 0);
203 lnMap
[smi
] = prev_smi
;
205 add(OP_LINK
, FL_NONE
, tc
->contextId(), prev_smi
, smi
);
207 DPRINTF(Annotate
, "Not Linking to state machine %s(%d) [%#x]\n",
213 smStack
[sid
].push_back(smi
);
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
]);
219 // reset the sw state exculsion to false
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
);
231 "Found prev unknown linking from %d to state machine %s(%d)\n",
235 DPRINTF(Annotate
, "LnMap already contains entry for %d of %d\n",
237 assert(lnMap
[smi
] == 0);
241 // add a new begin ifwe have that info
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
);
252 CPA::swSmEnd(ThreadContext
*tc
)
259 tc
->getVirtProxy().readString(sm
, args
[0], 50);
260 System
*sys
= tc
->getSystemPtr();
261 doSwSmEnd(sys
, tc
->contextId(), sm
, getFrame(tc
));
265 CPA::doSwSmEnd(System
*sys
, int cpuid
, string sm
, uint64_t frame
)
267 int sysi
= getSys(sys
);
268 StackId sid
= StackId(sysi
, frame
);
271 // reset the sw state exculsion to false
276 int smib
= smStack
[sid
].back();
277 StringWrap
name(sys
->name());
278 DPRINTF(Annotate
, "Ending machine: %s[%d, %#x] (%d?)\n", sm
, sysi
,
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
);
290 warn("State machine stack not unwinding correctly at %d\n", curTick());
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());
299 int smi
= smStack
[sid
].back();
300 smStack
[sid
].pop_back();
303 DPRINTF(Annotate
, "Linking %d back to %d\n", smi
, lnMap
[smi
]);
304 add(OP_LINK
, FL_NONE
, cpuid
, smi
, lnMap
[smi
]);
308 if (smStack
[sid
].size()) {
309 add(OP_BEGIN
, FL_NONE
, cpuid
, smi
, lastState
[smi
]);
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
]);
320 CPA::swExplictBegin(ThreadContext
*tc
)
327 tc
->getVirtProxy().readString(st
, args
[1], 50);
329 StringWrap
name(tc
->getSystemPtr()->name());
330 DPRINTF(Annotate
, "Explict begin of state %s\n", st
);
331 uint32_t flags
= args
[0];
333 warn("BAD state encountered: at cycle %d: %s\n", curTick(), st
);
334 swBegin(tc
->getSystemPtr(), tc
->contextId(), st
, getFrame(tc
), true, args
[0]);
338 CPA::swAutoBegin(ThreadContext
*tc
, Addr next_pc
)
346 if (!TheISA::inUserMode(tc
)) {
347 debugSymbolTable
->findNearestSymbol(next_pc
, sym
, sym_addr
);
349 Linux::ThreadInfo
ti(tc
);
350 string app
= ti
.curTaskName();
351 if (userApp
.count(app
))
352 userApp
[app
]->findNearestSymbol(next_pc
, sym
, sym_addr
);
356 swBegin(tc
->getSystemPtr(), tc
->contextId(), sym
, getFrame(tc
));
360 CPA::swBegin(System
*sys
, int cpuid
, std::string st
, uint64_t frame
, bool expl
,
365 while (ignoreSymbols
[x
].len
)
367 len
= ignoreSymbols
[x
].len
;
368 if (!st
.compare(0,len
, ignoreSymbols
[x
].symbol
, len
))
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())
378 if (!expl
&& swExpl
[sid
])
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
);
392 CPA::swEnd(ThreadContext
*tc
)
399 if (!TheISA::inUserMode(tc
))
400 debugSymbolTable
->findNearestSymbol(
401 tc
->readIntReg(ReturnAddressReg
), st
, junk
);
402 System
*sys
= tc
->getSystemPtr();
403 StringWrap
name(sys
->name());
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
);
411 DPRINTF(Annotate
, "Explict end of State: %s\n", st
);
412 // return back to symbol table based states
414 int smi
= smStack
[sid
].back();
416 int sti
= getSt(smMap
[smi
-1].second
.first
, st
);
417 lastState
[smi
] = sti
;
418 add(OP_BEGIN
, FL_NONE
, tc
->contextId(), smi
, sti
);
423 CPA::swQ(ThreadContext
*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();
435 int sysi
= getSys(sys
);
436 StackId sid
= StackId(sysi
, getFrame(tc
));
437 if (!smStack
[sid
].size())
439 int smi
= smStack
[sid
].back();
442 int qi
= getQ(sysi
, q
, id
);
444 //warn("Tried to queue 0 bytes in %s, ignoring\n", q);
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
);
454 CPA::swDq(ThreadContext
*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();
466 int sysi
= getSys(sys
);
467 StackId sid
= StackId(sysi
, getFrame(tc
));
468 if (!smStack
[sid
].size())
470 int smi
= smStack
[sid
].back();
471 int qi
= getQ(sysi
, q
, id
);
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
);
479 doDq(sys
, FL_NONE
, tc
->contextId(), smi
, q
, qi
, count
);
483 CPA::swPq(ThreadContext
*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];
495 int sysi
= getSys(sys
);
496 StackId sid
= StackId(sysi
, getFrame(tc
));
497 if (!smStack
[sid
].size())
499 int smi
= smStack
[sid
].back();
500 int qi
= getQ(sysi
, q
, id
);
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
);
508 if (qBytes
[qi
-1] < count
) {
511 fatal("Queue %s peeking with not enough bytes available in queue!\n", q
);
514 add(OP_PEEK
, FL_NONE
, tc
->contextId(), smi
, qi
, count
);
518 CPA::swRq(ThreadContext
*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];
530 int sysi
= getSys(sys
);
531 StackId sid
= StackId(sysi
, getFrame(tc
));
532 if (!smStack
[sid
].size())
534 int smi
= smStack
[sid
].back();
535 int qi
= getQ(sysi
, q
, id
);
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
);
544 add(OP_RESERVE
, FL_NONE
, tc
->contextId(), smi
, qi
, count
);
549 CPA::swWf(ThreadContext
*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];
561 int sysi
= getSys(sys
);
562 StackId sid
= StackId(sysi
, getFrame(tc
));
563 if (!smStack
[sid
].size())
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
);
571 tc
->getVirtProxy().readString(sm
, args
[2], 50);
572 doSwSmEnd(tc
->getSystemPtr(), tc
->contextId(), sm
, getFrame(tc
));
577 CPA::swWe(ThreadContext
*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];
589 int sysi
= getSys(sys
);
590 StackId sid
= StackId(sysi
, getFrame(tc
));
591 if (!smStack
[sid
].size())
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
);
599 tc
->getVirtProxy().readString(sm
, args
[2], 50);
600 doSwSmEnd(tc
->getSystemPtr(), tc
->contextId(), sm
, getFrame(tc
));
605 CPA::swSq(ThreadContext
*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];
619 int sysi
= getSys(sys
);
620 StackId sid
= StackId(sysi
, getFrame(tc
));
621 if (!smStack
[sid
].size())
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
);
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);
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
);
647 int need
= qBytes
[qi
-1] - size
;
650 int32_t tail_bytes
= qData
[qi
-1].back()->data
;
651 if (qSize
[qi
-1] <= 0 || qBytes
[qi
-1] < 0) {
654 fatal("Queue %s had inconsistancy when doing size queue!\n", q
);
656 if (tail_bytes
> need
) {
657 qData
[qi
-1].back()->data
-= need
;
659 } else if (tail_bytes
== need
) {
660 qData
[qi
-1].pop_back();
664 qData
[qi
-1].pop_back();
673 CPA::swAq(ThreadContext
*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];
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
);
692 std::list
<AnnDataPtr
>::iterator ai
= qData
[qi
-1].begin();
694 while (ai
!= qData
[qi
-1].end()) {
695 DPRINTF(AnnotateQ
, "--Element %d size %d\n", x
, (*ai
)->data
);
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]);
710 CPA::swLink(ThreadContext
*tc
)
717 tc
->getVirtProxy().readString(lsm
, args
[0], 50);
718 System
*sys
= tc
->getSystemPtr();
719 StringWrap
name(sys
->name());
721 int sysi
= getSys(sys
);
722 StackId sid
= StackId(sysi
, getFrame(tc
));
723 if (!smStack
[sid
].size())
725 int smi
= smStack
[sid
].back();
726 int lsmi
= getSm(sysi
, lsm
, args
[1]);
728 DPRINTF(Annotate
, "Linking from %d to state machine %s(%d) [%#x]\n",
729 smi
, lsm
, lsmi
, args
[1]);
732 DPRINTF(Annotate
, "LnMap already contains entry for %d of %d\n",
734 assert(lnMap
[lsmi
] == 0);
737 add(OP_LINK
, FL_NONE
, tc
->contextId(), smi
, lsmi
);
741 tc
->getVirtProxy().readString(sm
, args
[2], 50);
742 doSwSmEnd(tc
->getSystemPtr(), tc
->contextId(), sm
, getFrame(tc
));
747 CPA::swIdentify(ThreadContext
*tc
)
753 int sysi
= getSys(tc
->getSystemPtr());
754 StackId sid
= StackId(sysi
, getFrame(tc
));
755 if (!smStack
[sid
].size())
757 int smi
= smStack
[sid
].back();
759 DPRINTFS(Annotate
, tc
->getSystemPtr(), "swIdentify: id %#X\n", args
[0]);
761 add(OP_IDENT
, FL_NONE
, tc
->contextId(), smi
, 0, args
[0]);
765 CPA::swGetId(ThreadContext
*tc
)
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();
777 DPRINTFS(Annotate
, tc
->getSystemPtr(), "swGetId: id %#X\n", id
);
779 add(OP_IDENT
, FL_NONE
, tc
->contextId(), smi
, 0, id
);
785 CPA::swSyscallLink(ThreadContext
*tc
)
792 tc
->getVirtProxy().readString(lsm
, args
[0], 50);
793 System
*sys
= tc
->getSystemPtr();
794 StringWrap
name(sys
->name());
795 int sysi
= getSys(sys
);
797 Id id
= Id(lsm
, getFrame(tc
));
798 StackId sid
= StackId(sysi
, getFrame(tc
));
800 if (!smStack
[sid
].size())
803 int smi
= smStack
[sid
].back();
805 DPRINTF(Annotate
, "Linking from %d to state machine %s(UNKNOWN)\n",
808 if (scLinks
[sysi
-1][id
])
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;
818 tc
->getVirtProxy().readString(sm
, args
[1], 50);
819 doSwSmEnd(tc
->getSystemPtr(), tc
->contextId(), sm
, getFrame(tc
));
824 CPA::add(int t
, int f
, int c
, int sm
, int stq
, int32_t d
)
826 AnnDataPtr an
= std::make_shared
<AnnotateData
>();
827 an
->time
= curTick();
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
);
842 // Don't dump Links because we might be setting no-dump on it
843 if (an
->op
!= OP_LINK
)
852 std::streampos curpos
= osbin
->tellp();
855 // Output the various state machines and their corresponding states
856 *osbin
<< "# Automatically generated state machine descriptor file" << endl
;
858 *osbin
<< "sms = {}" << endl
<< endl
;
859 vector
<string
> state_machines
;
860 state_machines
.resize(numSmt
+1);
862 // State machines, id -> states
863 SCache::iterator i
= smtCache
.begin();
864 while (i
!= smtCache
.end()) {
865 state_machines
[i
->second
] = i
->first
;
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
;
878 *osbin
<< "sms[\"" << state_machines
[x
] << "\"] = [\"NULL\"";
879 for (int y
= 1; y
< states
.size(); y
++)
880 *osbin
<< ", \"" << states
[y
] << "\"";
881 *osbin
<< "]" << endl
;
884 *osbin
<< endl
<< endl
<< endl
;
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
;
893 *osbin
<< endl
<< endl
<< endl
;
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
;
904 *osbin
<< "sysNum = [\"NULL\"";
905 for (int x
= 1; x
< systems
.size(); x
++) {
906 *osbin
<< ", \"" << systems
[x
] << "\"";
908 *osbin
<< "]" << endl
;
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
;
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
;
922 curpos
= osbin
->tellp();
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
;
930 osbin
->write((char*)&ah
, sizeof(AnnotateHeader
));
939 list
<AnnDataPtr
>::iterator i
;
946 // Dump the data every
947 if (!all
&& data
.size() < 10000)
950 DPRINTF(Annotate
, "Writing %d\n", data
.size());
951 while (i
!= data
.end()) {
954 // If we can't dump this record, hold here
955 if (!an
->dump
&& !all
)
959 if (ah
.num_recs
% 100000 == 0)
960 annotateIdx
.push_back(osbin
->tellp());
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
));
972 if (data
.begin() != i
)
973 data
.erase(data
.begin(), i
);
980 CPA::doQ(System
*sys
, int flags
, int cpuid
, int sm
,
981 string q
, int qi
, int count
)
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]);
990 qData
[qi
-1].push_front(add(OP_QUEUE
, flags
, cpuid
, sm
, qi
, count
));
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);
1001 CPA::doDq(System
*sys
, int flags
, int cpuid
, int sm
,
1002 string q
, int qi
, int count
)
1005 StringWrap
name(sys
->name());
1007 add(OP_DEQUEUE
, flags
, cpuid
, sm
, qi
, count
);
1008 qData
[qi
-1].clear();
1011 DPRINTF(AnnotateQ
, "Dequeing all data in queue %s size now %d/%d\n",
1012 q
, qSize
[qi
-1], qBytes
[qi
-1]);
1017 if (qSize
[qi
-1] <= 0 || qBytes
[qi
-1] <= 0 || !qData
[qi
-1].size()) {
1020 fatal("Queue %s dequing with no data available in queue!\n",
1023 assert(qSize
[qi
-1] >= 0);
1024 assert(qBytes
[qi
-1] >= 0);
1025 assert(qData
[qi
-1].size());
1027 int32_t need
= count
;
1028 qBytes
[qi
-1] -= count
;
1029 if (qBytes
[qi
-1] < 0) {
1032 fatal("Queue %s dequing with no bytes available in queue!\n",
1037 int32_t head_bytes
= qData
[qi
-1].front()->data
;
1038 if (qSize
[qi
-1] <= 0 || qBytes
[qi
-1] < 0) {
1041 fatal("Queue %s dequing with nothing in queue!\n",
1045 if (head_bytes
> need
) {
1046 qData
[qi
-1].front()->data
-= need
;
1048 } else if (head_bytes
== need
) {
1049 qData
[qi
-1].pop_front();
1053 qData
[qi
-1].pop_front();
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]);
1067 CPA::serialize(CheckpointOut
&cp
) const
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
);
1084 // smtCache (SCache)
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
);
1094 // stCache (StCache)
1095 for (x
= 0; x
< stCache
.size(); x
++) {
1096 i
= stCache
[x
].begin();
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
);
1106 IdHCache::iterator idi
;
1107 for (x
= 0; x
< qCache
.size(); x
++) {
1108 idi
= qCache
[x
].begin();
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
);
1118 // smCache (IdCache)
1119 for (x
= 0; x
< smCache
.size(); x
++) {
1120 idi
= smCache
[x
].begin();
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
);
1131 // scLinks (ScCache) -- data not serialize
1134 // namecache (NameCache)
1135 NameCache::iterator ni
;
1137 ni
= nameCache
.begin();
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
);
1146 // smStack (SmStack)
1147 SmStack::iterator si
;
1148 si
= smStack
.begin();
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
]);
1162 LinkMap::iterator li
;
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
);
1172 SwExpl::iterator swexpli
;
1173 swexpli
= swExpl
.begin();
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
);
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
);
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
);
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
);
1208 // qData (vector<AnnotateList>)
1209 for (x
= 0; x
< qData
.size(); x
++) {
1210 if (!qData
[x
].size())
1213 for (auto &ann
: qData
[x
]) {
1214 ann
->serializeSection(os
, csprintf("Q%d_%d", x
, y
));
1221 CPA::unserialize(CheckpointIn
&cp
)
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
);
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
;
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
;
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
;
1265 // smCache (IdCache)
1266 smCache
.resize(numSys
);
1267 for (int x
= 0; x
< numSys
; x
++) {
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
;
1278 // scLinks (ScCache) -- data not serialized, just creating one per sys
1279 for (int x
= 0; x
< numSys
; x
++)
1280 scLinks
.push_back(ScHCache());
1282 // nameCache (NameCache)
1283 for (int x
= 0; x
< numSys
; x
++) {
1289 objParamIn(cp
, csprintf("nameCache%d.name", x
), sptr
);
1290 sys
= dynamic_cast<System
*>(sptr
);
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
);
1299 paramIn(cp
, "smStackIdCount", smStack_size
);
1300 for (int x
= 0; x
< smStack_size
; x
++) {
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
);
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
);
1326 paramIn(cp
, "swExplCount", swExpl_size
);
1327 for (int x
= 0; x
< swExpl_size
; x
++) {
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
);
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
;
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
);
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
);
1366 // qData (vector<AnnotateList>)
1367 qData
.resize(qSize
.size());
1368 for (int x
= 0; x
< qSize
.size(); x
++) {
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
));
1375 qData
[x
].push_back(a
);
1381 CPA::AnnotateData::serialize(CheckpointOut
&cp
) const
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
);
1393 CPA::AnnotateData::unserialize(CheckpointIn
&cp
)
1395 UNSERIALIZE_SCALAR(time
);
1396 UNSERIALIZE_SCALAR(data
);
1398 UNSERIALIZE_SCALAR(sm
);
1399 UNSERIALIZE_SCALAR(stq
);
1400 UNSERIALIZE_SCALAR(op
);
1401 UNSERIALIZE_SCALAR(flag
);
1402 UNSERIALIZE_SCALAR(cpu
);
1409 return new CPA(this);