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/generic/linux/threadinfo.hh"
32 #include "arch/utility.hh"
33 #include "base/loader/object_file.hh"
34 #include "base/callback.hh"
35 #include "base/cp_annotate.hh"
36 #include "base/output.hh"
37 #include "base/trace.hh"
38 #include "config/the_isa.hh"
39 #include "cpu/thread_context.hh"
40 #include "debug/Annotate.hh"
41 #include "debug/AnnotateVerbose.hh"
42 #include "sim/arguments.hh"
43 #include "sim/core.hh"
44 #include "sim/sim_exit.hh"
45 #include "sim/system.hh"
47 struct CPAIgnoreSymbol
52 #define CPA_IGNORE_SYMBOL(sym) { #sym, sizeof(#sym) }
54 CPAIgnoreSymbol ignoreSymbols
[] = {
55 CPA_IGNORE_SYMBOL("m5a_"),
56 CPA_IGNORE_SYMBOL("ret_from_sys_call"),
57 CPA_IGNORE_SYMBOL("ret_from_reschedule"),
58 CPA_IGNORE_SYMBOL("_spin_"),
59 CPA_IGNORE_SYMBOL("local_bh_"),
60 CPA_IGNORE_SYMBOL("restore_all"),
61 CPA_IGNORE_SYMBOL("Call_Pal_"),
62 CPA_IGNORE_SYMBOL("pal_post_interrupt"),
63 CPA_IGNORE_SYMBOL("rti_to_"),
64 CPA_IGNORE_SYMBOL("sys_int_2"),
65 CPA_IGNORE_SYMBOL("sys_interrupt"),
66 CPA_IGNORE_SYMBOL("normal_int"),
67 CPA_IGNORE_SYMBOL("TRAP_INTERRUPT_10_"),
68 CPA_IGNORE_SYMBOL("Trap_Interrupt"),
69 CPA_IGNORE_SYMBOL("do_entInt"),
70 CPA_IGNORE_SYMBOL("__do_softirq"),
71 CPA_IGNORE_SYMBOL("_end"),
72 CPA_IGNORE_SYMBOL("entInt"),
73 CPA_IGNORE_SYMBOL("entSys"),
76 #undef CPA_IGNORE_SYMBOL
79 using namespace TheISA
;
84 class AnnotateDumpCallback
: public Callback
90 virtual void process();
91 AnnotateDumpCallback(CPA
*_cpa
)
97 AnnotateDumpCallback::process()
105 : SimObject(p
), numSm(0), numSmt(0), numSys(0), numQs(0), conId(0)
108 fatal("Multiple annotation objects found in system");
111 _enabled
= p
->enabled
;
114 vector
<string
>::iterator i
;
115 i
= p
->user_apps
.begin();
117 while (i
!= p
->user_apps
.end()) {
118 ObjectFile
*of
= createObjectFile(*i
);
121 fatal("Couldn't load symbols from file: %s\n", *i
);
123 sf
.erase(0, sf
.rfind('/') + 1);;
124 DPRINTFN("file %s short: %s\n", *i
, sf
);
125 userApp
[sf
] = new SymbolTable
;
126 bool result1
= of
->loadGlobalSymbols(userApp
[sf
]);
127 bool result2
= of
->loadLocalSymbols(userApp
[sf
]);
128 if (!result1
|| !result2
)
130 assert(result1
&& result2
);
138 osbin
= simout
.create("annotate.bin", true);
139 // MAGIC version number 'M''5''A'N' + version/capabilities
140 ah
.version
= 0x4D35414E00000101ULL
;
143 osbin
->write((char*)&ah
, sizeof(AnnotateHeader
));
145 registerExitCallback(new AnnotateDumpCallback(this));
149 CPA::getFrame(ThreadContext
*tc
)
151 // This code is ISA specific and will need to be changed
152 // if the annotation code is used for something other than Alpha
153 return (tc
->readMiscRegNoEffect(TheISA::IPR_PALtemp23
) &
159 CPA::swSmBegin(ThreadContext
*tc
)
168 if (!TheISA::inUserMode(tc
))
169 debugSymbolTable
->findNearestSymbol(
170 tc
->readIntReg(ReturnAddressReg
), st
, junk
);
172 CopyStringOut(tc
, sm
, args
[0], 50);
173 System
*sys
= tc
->getSystemPtr();
174 StringWrap
name(sys
->name());
177 warn("Got null SM at tick %d\n", curTick());
179 int sysi
= getSys(sys
);
180 int smi
= getSm(sysi
, sm
, args
[1]);
181 DPRINTF(Annotate
, "Starting machine: %s(%d) sysi: %d id: %#x\n", sm
,
183 DPRINTF(Annotate
, "smMap[%d] = %d, %s, %#x\n", smi
,
184 smMap
[smi
-1].first
, smMap
[smi
-1].second
.first
,
185 smMap
[smi
-1].second
.second
);
187 uint64_t frame
= getFrame(tc
);
188 StackId sid
= StackId(sysi
, frame
);
190 // check if we need to link to the previous state machine
192 if (flags
& FL_LINK
) {
193 if (smStack
[sid
].size()) {
194 int prev_smi
= smStack
[sid
].back();
195 DPRINTF(Annotate
, "Linking from %d to state machine %s(%d) [%#x]\n",
196 prev_smi
, sm
, smi
, args
[1]);
199 DPRINTF(Annotate
, "LnMap already contains entry for %d of %d\n",
201 assert(lnMap
[smi
] == 0);
202 lnMap
[smi
] = prev_smi
;
204 add(OP_LINK
, FL_NONE
, tc
->contextId(), prev_smi
, smi
);
206 DPRINTF(Annotate
, "Not Linking to state machine %s(%d) [%#x]\n",
212 smStack
[sid
].push_back(smi
);
214 DPRINTF(Annotate
, "Stack Now (%#X):\n", frame
);
215 for (int x
= smStack
[sid
].size()-1; x
>= 0; x
--)
216 DPRINTF(Annotate
, "-- %d\n", smStack
[sid
][x
]);
218 // reset the sw state exculsion to false
223 Id id
= Id(sm
, frame
);
224 if (scLinks
[sysi
-1][id
]) {
225 AnnDataPtr an
= scLinks
[sysi
-1][id
];
226 scLinks
[sysi
-1].erase(id
);
230 "Found prev unknown linking from %d to state machine %s(%d)\n",
234 DPRINTF(Annotate
, "LnMap already contains entry for %d of %d\n",
236 assert(lnMap
[smi
] == 0);
240 // add a new begin ifwe have that info
242 DPRINTF(Annotate
, "st: %s smi: %d stCache.size %d\n", st
,
243 smi
, stCache
.size());
244 int sti
= getSt(sm
, st
);
245 lastState
[smi
] = sti
;
246 add(OP_BEGIN
, FL_NONE
, tc
->contextId(), smi
, sti
);
251 CPA::swSmEnd(ThreadContext
*tc
)
258 CopyStringOut(tc
, sm
, args
[0], 50);
259 System
*sys
= tc
->getSystemPtr();
260 doSwSmEnd(sys
, tc
->contextId(), sm
, getFrame(tc
));
264 CPA::doSwSmEnd(System
*sys
, int cpuid
, string sm
, uint64_t frame
)
266 int sysi
= getSys(sys
);
267 StackId sid
= StackId(sysi
, frame
);
270 // reset the sw state exculsion to false
275 int smib
= smStack
[sid
].back();
276 StringWrap
name(sys
->name());
277 DPRINTF(Annotate
, "Ending machine: %s[%d, %#x] (%d?)\n", sm
, sysi
,
280 if (!smStack
[sid
].size() || smMap
[smib
-1].second
.first
!= sm
) {
281 DPRINTF(Annotate
, "State Machine not unwinding correctly. sid: %d, %#x"
282 " top of stack: %s Current Stack:\n",
283 sysi
, frame
, smMap
[smib
-1].second
.first
);
284 for (int x
= smStack
[sid
].size()-1; x
>= 0; x
--)
285 DPRINTF(Annotate
, "-- %d\n", smStack
[sid
][x
]);
286 DPRINTF(Annotate
, "Ending machine: %s; end stack: %s\n", sm
,
287 smMap
[smib
-1].second
.first
);
289 warn("State machine stack not unwinding correctly at %d\n", curTick());
292 "State machine ending:%s sysi:%d id:%#x back:%d getSm:%d\n",
293 sm
, sysi
, smMap
[smib
-1].second
.second
, smStack
[sid
].back(),
294 getSm(sysi
, sm
, smMap
[smib
-1].second
.second
));
295 assert(getSm(sysi
, sm
, smMap
[smib
-1].second
.second
) ==
296 smStack
[sid
].back());
298 int smi
= smStack
[sid
].back();
299 smStack
[sid
].pop_back();
302 DPRINTF(Annotate
, "Linking %d back to %d\n", smi
, lnMap
[smi
]);
303 add(OP_LINK
, FL_NONE
, cpuid
, smi
, lnMap
[smi
]);
307 if (smStack
[sid
].size()) {
308 add(OP_BEGIN
, FL_NONE
, cpuid
, smi
, lastState
[smi
]);
311 DPRINTF(Annotate
, "Stack Now:\n");
312 for (int x
= smStack
[sid
].size()-1; x
>= 0; x
--)
313 DPRINTF(Annotate
, "-- %d\n", smStack
[sid
][x
]);
319 CPA::swExplictBegin(ThreadContext
*tc
)
326 CopyStringOut(tc
, st
, args
[1], 50);
328 StringWrap
name(tc
->getSystemPtr()->name());
329 DPRINTF(Annotate
, "Explict begin of state %s\n", st
);
330 uint32_t flags
= args
[0];
332 warn("BAD state encountered: at cycle %d: %s\n", curTick(), st
);
333 swBegin(tc
->getSystemPtr(), tc
->contextId(), st
, getFrame(tc
), true, args
[0]);
337 CPA::swAutoBegin(ThreadContext
*tc
, Addr next_pc
)
345 if (!TheISA::inUserMode(tc
)) {
346 debugSymbolTable
->findNearestSymbol(next_pc
, sym
, sym_addr
);
348 Linux::ThreadInfo
ti(tc
);
349 string app
= ti
.curTaskName();
350 if (userApp
.count(app
))
351 userApp
[app
]->findNearestSymbol(next_pc
, sym
, sym_addr
);
355 swBegin(tc
->getSystemPtr(), tc
->contextId(), sym
, getFrame(tc
));
359 CPA::swBegin(System
*sys
, int cpuid
, std::string st
, uint64_t frame
, bool expl
,
364 while (ignoreSymbols
[x
].len
)
366 len
= ignoreSymbols
[x
].len
;
367 if (!st
.compare(0,len
, ignoreSymbols
[x
].symbol
, len
))
372 int sysi
= getSys(sys
);
373 StackId sid
= StackId(sysi
, frame
);
374 // if expl is true suspend symbol table based states
375 if (!smStack
[sid
].size())
377 if (!expl
&& swExpl
[sid
])
381 DPRINTFS(AnnotateVerbose
, sys
, "SwBegin: %s sysi: %d\n", st
, sysi
);
382 int smi
= smStack
[sid
].back();
383 int sti
= getSt(smMap
[smi
-1].second
.first
, st
);
384 if (lastState
[smi
] != sti
) {
385 lastState
[smi
] = sti
;
386 add(OP_BEGIN
, flags
, cpuid
, smi
, sti
);
391 CPA::swEnd(ThreadContext
*tc
)
398 if (!TheISA::inUserMode(tc
))
399 debugSymbolTable
->findNearestSymbol(
400 tc
->readIntReg(ReturnAddressReg
), st
, junk
);
401 System
*sys
= tc
->getSystemPtr();
402 StringWrap
name(sys
->name());
404 int sysi
= getSys(sys
);
405 StackId sid
= StackId(sysi
, getFrame(tc
));
406 if (!smStack
[sid
].size()) {
407 DPRINTF(Annotate
, "Explict end of State: %s IGNORED\n", st
);
410 DPRINTF(Annotate
, "Explict end of State: %s\n", st
);
411 // return back to symbol table based states
413 int smi
= smStack
[sid
].back();
415 int sti
= getSt(smMap
[smi
-1].second
.first
, st
);
416 lastState
[smi
] = sti
;
417 add(OP_BEGIN
, FL_NONE
, tc
->contextId(), smi
, sti
);
422 CPA::swQ(ThreadContext
*tc
)
429 uint64_t id
= args
[0];
430 CopyStringOut(tc
, q
, args
[1], 50);
431 int32_t count
= args
[2];
432 System
*sys
= tc
->getSystemPtr();
434 int sysi
= getSys(sys
);
435 StackId sid
= StackId(sysi
, getFrame(tc
));
436 if (!smStack
[sid
].size())
438 int smi
= smStack
[sid
].back();
441 int qi
= getQ(sysi
, q
, id
);
443 //warn("Tried to queue 0 bytes in %s, ignoring\n", q);
446 DPRINTFS(AnnotateQ
, sys
,
447 "swQ: %s[%#x] cur size %d %d bytes: %d adding: %d\n",
448 q
, id
, qSize
[qi
-1], qData
[qi
-1].size(), qBytes
[qi
-1], count
);
449 doQ(sys
, FL_NONE
, tc
->contextId(), smi
, q
, qi
, count
);
453 CPA::swDq(ThreadContext
*tc
)
460 uint64_t id
= args
[0];
461 CopyStringOut(tc
, q
, args
[1], 50);
462 int32_t count
= args
[2];
463 System
*sys
= tc
->getSystemPtr();
465 int sysi
= getSys(sys
);
466 StackId sid
= StackId(sysi
, getFrame(tc
));
467 if (!smStack
[sid
].size())
469 int smi
= smStack
[sid
].back();
470 int qi
= getQ(sysi
, q
, id
);
473 DPRINTFS(AnnotateQ
, sys
,
474 "swDq: %s[%#x] cur size %d %d bytes: %d removing: %d\n",
475 q
, id
, qSize
[qi
-1], qData
[qi
-1].size(), qBytes
[qi
-1], count
);
478 doDq(sys
, FL_NONE
, tc
->contextId(), smi
, q
, qi
, count
);
482 CPA::swPq(ThreadContext
*tc
)
489 uint64_t id
= args
[0];
490 CopyStringOut(tc
, q
, args
[1], 50);
491 System
*sys
= tc
->getSystemPtr();
492 int32_t count
= args
[2];
494 int sysi
= getSys(sys
);
495 StackId sid
= StackId(sysi
, getFrame(tc
));
496 if (!smStack
[sid
].size())
498 int smi
= smStack
[sid
].back();
499 int qi
= getQ(sysi
, q
, id
);
502 DPRINTFS(AnnotateQ
, sys
,
503 "swPq: %s [%#x] cur size %d %d bytes: %d peeking: %d\n",
504 q
, id
, qSize
[qi
-1], qData
[qi
-1].size(), qBytes
[qi
-1], count
);
507 if (qBytes
[qi
-1] < count
) {
510 fatal("Queue %s peeking with not enough bytes available in queue!\n", q
);
513 add(OP_PEEK
, FL_NONE
, tc
->contextId(), smi
, qi
, count
);
517 CPA::swRq(ThreadContext
*tc
)
524 uint64_t id
= args
[0];
525 CopyStringOut(tc
, q
, args
[1], 50);
526 System
*sys
= tc
->getSystemPtr();
527 int32_t count
= args
[2];
529 int sysi
= getSys(sys
);
530 StackId sid
= StackId(sysi
, getFrame(tc
));
531 if (!smStack
[sid
].size())
533 int smi
= smStack
[sid
].back();
534 int qi
= getQ(sysi
, q
, id
);
537 DPRINTFS(AnnotateQ
, sys
,
538 "swRq: %s [%#x] cur size %d %d bytes: %d reserve: %d\n",
539 q
, id
, qSize
[qi
-1], qData
[qi
-1].size(), qBytes
[qi
-1], count
);
543 add(OP_RESERVE
, FL_NONE
, tc
->contextId(), smi
, qi
, count
);
548 CPA::swWf(ThreadContext
*tc
)
555 uint64_t id
= args
[0];
556 CopyStringOut(tc
, q
, args
[1], 50);
557 System
*sys
= tc
->getSystemPtr();
558 int32_t count
= args
[3];
560 int sysi
= getSys(sys
);
561 StackId sid
= StackId(sysi
, getFrame(tc
));
562 if (!smStack
[sid
].size())
564 int smi
= smStack
[sid
].back();
565 int qi
= getQ(sysi
, q
, id
);
566 add(OP_WAIT_FULL
, FL_NONE
, tc
->contextId(), smi
, qi
, count
);
570 CopyStringOut(tc
, sm
, args
[2], 50);
571 doSwSmEnd(tc
->getSystemPtr(), tc
->contextId(), sm
, getFrame(tc
));
576 CPA::swWe(ThreadContext
*tc
)
583 uint64_t id
= args
[0];
584 CopyStringOut(tc
, q
, args
[1], 50);
585 System
*sys
= tc
->getSystemPtr();
586 int32_t count
= args
[3];
588 int sysi
= getSys(sys
);
589 StackId sid
= StackId(sysi
, getFrame(tc
));
590 if (!smStack
[sid
].size())
592 int smi
= smStack
[sid
].back();
593 int qi
= getQ(sysi
, q
, id
);
594 add(OP_WAIT_EMPTY
, FL_NONE
, tc
->contextId(), smi
, qi
, count
);
598 CopyStringOut(tc
, sm
, args
[2], 50);
599 doSwSmEnd(tc
->getSystemPtr(), tc
->contextId(), sm
, getFrame(tc
));
604 CPA::swSq(ThreadContext
*tc
)
611 uint64_t id
= args
[0];
612 CopyStringOut(tc
, q
, args
[1], 50);
613 System
*sys
= tc
->getSystemPtr();
614 StringWrap
name(sys
->name());
615 int32_t size
= args
[2];
618 int sysi
= getSys(sys
);
619 StackId sid
= StackId(sysi
, getFrame(tc
));
620 if (!smStack
[sid
].size())
622 int smi
= smStack
[sid
].back();
623 int qi
= getQ(sysi
, q
, id
);
624 DPRINTF(AnnotateQ
, "swSq: %s [%#x] cur size: %d bytes: %d, new size: %d\n",
625 q
, id
, qSize
[qi
-1], qBytes
[qi
-1], size
);
627 if (FL_RESET
& flags
) {
628 DPRINTF(AnnotateQ
, "Resetting Queue %s\n", q
);
629 add(OP_SIZE_QUEUE
, FL_NONE
, tc
->contextId(), smi
, qi
, 0);
635 if (qBytes
[qi
-1] < size
)
636 doQ(sys
, FL_NONE
, tc
->contextId(), smi
, q
, qi
, size
- qBytes
[qi
-1]);
637 else if (qBytes
[qi
-1] > size
) {
638 DPRINTF(AnnotateQ
, "removing for resize of queue %s\n", q
);
639 add(OP_SIZE_QUEUE
, FL_NONE
, tc
->contextId(), smi
, qi
, size
);
646 int need
= qBytes
[qi
-1] - size
;
649 int32_t tail_bytes
= qData
[qi
-1].back()->data
;
650 if (qSize
[qi
-1] <= 0 || qBytes
[qi
-1] < 0) {
653 fatal("Queue %s had inconsistancy when doing size queue!\n", q
);
655 if (tail_bytes
> need
) {
656 qData
[qi
-1].back()->data
-= need
;
658 } else if (tail_bytes
== need
) {
659 qData
[qi
-1].pop_back();
663 qData
[qi
-1].pop_back();
672 CPA::swAq(ThreadContext
*tc
)
679 uint64_t id
= args
[0];
680 CopyStringOut(tc
, q
, args
[1], 50);
681 System
*sys
= tc
->getSystemPtr();
682 StringWrap
name(sys
->name());
683 int32_t size
= args
[2];
685 int sysi
= getSys(sys
);
686 int qi
= getQ(sysi
, q
, id
);
687 if (qBytes
[qi
-1] != size
) {
688 DPRINTF(AnnotateQ
, "Queue %s [%#x] has inconsintant size\n", q
, id
);
691 std::list
<AnnDataPtr
>::iterator ai
= qData
[qi
-1].begin();
693 while (ai
!= qData
[qi
-1].end()) {
694 DPRINTF(AnnotateQ
, "--Element %d size %d\n", x
, (*ai
)->data
);
699 warn("%d: Queue Assert: SW said there should be %d byte(s) in %s,"
700 "however there are %d byte(s)\n",
701 curTick(), size
, q
, qBytes
[qi
-1]);
702 DPRINTF(AnnotateQ
, "%d: Queue Assert: SW said there should be %d"
703 " byte(s) in %s, however there are %d byte(s)\n",
704 curTick(), size
, q
, qBytes
[qi
-1]);
709 CPA::swLink(ThreadContext
*tc
)
716 CopyStringOut(tc
, lsm
, args
[0], 50);
717 System
*sys
= tc
->getSystemPtr();
718 StringWrap
name(sys
->name());
720 int sysi
= getSys(sys
);
721 StackId sid
= StackId(sysi
, getFrame(tc
));
722 if (!smStack
[sid
].size())
724 int smi
= smStack
[sid
].back();
725 int lsmi
= getSm(sysi
, lsm
, args
[1]);
727 DPRINTF(Annotate
, "Linking from %d to state machine %s(%d) [%#x]\n",
728 smi
, lsm
, lsmi
, args
[1]);
731 DPRINTF(Annotate
, "LnMap already contains entry for %d of %d\n",
733 assert(lnMap
[lsmi
] == 0);
736 add(OP_LINK
, FL_NONE
, tc
->contextId(), smi
, lsmi
);
740 CopyStringOut(tc
, sm
, args
[2], 50);
741 doSwSmEnd(tc
->getSystemPtr(), tc
->contextId(), sm
, getFrame(tc
));
746 CPA::swIdentify(ThreadContext
*tc
)
752 int sysi
= getSys(tc
->getSystemPtr());
753 StackId sid
= StackId(sysi
, getFrame(tc
));
754 if (!smStack
[sid
].size())
756 int smi
= smStack
[sid
].back();
758 DPRINTFS(Annotate
, tc
->getSystemPtr(), "swIdentify: id %#X\n", args
[0]);
760 add(OP_IDENT
, FL_NONE
, tc
->contextId(), smi
, 0, args
[0]);
764 CPA::swGetId(ThreadContext
*tc
)
769 uint64_t id
= ++conId
;
770 int sysi
= getSys(tc
->getSystemPtr());
771 StackId sid
= StackId(sysi
, getFrame(tc
));
772 if (!smStack
[sid
].size())
773 panic("swGetId called without a state machine stack!");
774 int smi
= smStack
[sid
].back();
776 DPRINTFS(Annotate
, tc
->getSystemPtr(), "swGetId: id %#X\n", id
);
778 add(OP_IDENT
, FL_NONE
, tc
->contextId(), smi
, 0, id
);
784 CPA::swSyscallLink(ThreadContext
*tc
)
791 CopyStringOut(tc
, lsm
, args
[0], 50);
792 System
*sys
= tc
->getSystemPtr();
793 StringWrap
name(sys
->name());
794 int sysi
= getSys(sys
);
796 Id id
= Id(lsm
, getFrame(tc
));
797 StackId sid
= StackId(sysi
, getFrame(tc
));
799 if (!smStack
[sid
].size())
802 int smi
= smStack
[sid
].back();
804 DPRINTF(Annotate
, "Linking from %d to state machine %s(UNKNOWN)\n",
807 if (scLinks
[sysi
-1][id
])
809 "scLinks already contains entry for system %d %s[%x] of %d\n",
810 sysi
, lsm
, getFrame(tc
), scLinks
[sysi
-1][id
]);
811 assert(scLinks
[sysi
-1][id
] == 0);
812 scLinks
[sysi
-1][id
] = add(OP_LINK
, FL_NONE
, tc
->contextId(), smi
, 0xFFFF);
813 scLinks
[sysi
-1][id
]->dump
= false;
817 CopyStringOut(tc
, sm
, args
[1], 50);
818 doSwSmEnd(tc
->getSystemPtr(), tc
->contextId(), sm
, getFrame(tc
));
823 CPA::add(int t
, int f
, int c
, int sm
, int stq
, int32_t d
)
825 AnnDataPtr an
= std::make_shared
<AnnotateData
>();
826 an
->time
= curTick();
838 DPRINTF(AnnotateVerbose
, "Annotate: op: %d flags: 0x%x sm: %d state: %d time: %d, data: %d\n",
839 an
->op
, an
->flag
, an
->sm
, an
->stq
, an
->time
, an
->data
);
841 // Don't dump Links because we might be setting no-dump on it
842 if (an
->op
!= OP_LINK
)
851 std::streampos curpos
= osbin
->tellp();
854 // Output the various state machines and their corresponding states
855 *osbin
<< "# Automatically generated state machine descriptor file" << endl
;
857 *osbin
<< "sms = {}" << endl
<< endl
;
858 vector
<string
> state_machines
;
859 state_machines
.resize(numSmt
+1);
861 // State machines, id -> states
862 SCache::iterator i
= smtCache
.begin();
863 while (i
!= smtCache
.end()) {
864 state_machines
[i
->second
] = i
->first
;
868 for (int x
= 1; x
< state_machines
.size(); x
++) {
869 vector
<string
> states
;
870 states
.resize(numSt
[x
-1]+1);
871 assert(x
-1 < stCache
.size());
872 SCache::iterator i
= stCache
[x
-1].begin();
873 while (i
!= stCache
[x
-1].end()) {
874 states
[i
->second
] = i
->first
;
877 *osbin
<< "sms[\"" << state_machines
[x
] << "\"] = [\"NULL\"";
878 for (int y
= 1; y
< states
.size(); y
++)
879 *osbin
<< ", \"" << states
[y
] << "\"";
880 *osbin
<< "]" << endl
;
883 *osbin
<< endl
<< endl
<< endl
;
885 // state machine number -> system, name, id
886 *osbin
<< "smNum = [\"NULL\"";
887 for (int x
= 0; x
< smMap
.size(); x
++)
888 *osbin
<< ", (" << smMap
[x
].first
<< ", \"" << smMap
[x
].second
.first
<<
889 "\", " << smMap
[x
].second
.second
<< ")";
890 *osbin
<< "]" << endl
;
892 *osbin
<< endl
<< endl
<< endl
;
894 // Output the systems
895 vector
<string
> systems
;
896 systems
.resize(numSys
+1);
897 NameCache::iterator i2
= nameCache
.begin();
898 while (i2
!= nameCache
.end()) {
899 systems
[i2
->second
.second
] = i2
->second
.first
;
903 *osbin
<< "sysNum = [\"NULL\"";
904 for (int x
= 1; x
< systems
.size(); x
++) {
905 *osbin
<< ", \"" << systems
[x
] << "\"";
907 *osbin
<< "]" << endl
;
909 // queue number -> system, qname, qid
910 *osbin
<< "queues = [\"NULL\"";
911 for (int x
= 0; x
< qMap
.size(); x
++)
912 *osbin
<< ", (" << qMap
[x
].first
<< ", \"" << qMap
[x
].second
.first
<<
913 "\", " << qMap
[x
].second
.second
<< ")";
914 *osbin
<< "]" << endl
;
916 *osbin
<< "smComb = [s for s in [(i,r) for i in xrange(1,len(sysNum)) "
917 << "for r in xrange (1,len(smNum))]]" << endl
;
918 ah
.key_len
= osbin
->tellp() - curpos
;
921 curpos
= osbin
->tellp();
924 for (int x
= 0; x
< annotateIdx
.size(); x
++)
925 osbin
->write((char*)&annotateIdx
[x
], sizeof(uint64_t));
926 ah
.idx_len
= osbin
->tellp() - curpos
;
929 osbin
->write((char*)&ah
, sizeof(AnnotateHeader
));
938 list
<AnnDataPtr
>::iterator i
;
945 // Dump the data every
946 if (!all
&& data
.size() < 10000)
949 DPRINTF(Annotate
, "Writing %d\n", data
.size());
950 while (i
!= data
.end()) {
953 // If we can't dump this record, hold here
954 if (!an
->dump
&& !all
)
958 if (ah
.num_recs
% 100000 == 0)
959 annotateIdx
.push_back(osbin
->tellp());
962 osbin
->write((char*)&(an
->time
), sizeof(an
->time
));
963 osbin
->write((char*)&(an
->orig_data
), sizeof(an
->orig_data
));
964 osbin
->write((char*)&(an
->sm
), sizeof(an
->sm
));
965 osbin
->write((char*)&(an
->stq
), sizeof(an
->stq
));
966 osbin
->write((char*)&(an
->op
), sizeof(an
->op
));
967 osbin
->write((char*)&(an
->flag
), sizeof(an
->flag
));
968 osbin
->write((char*)&(an
->cpu
), sizeof(an
->cpu
));
971 if (data
.begin() != i
)
972 data
.erase(data
.begin(), i
);
979 CPA::doQ(System
*sys
, int flags
, int cpuid
, int sm
,
980 string q
, int qi
, int count
)
983 qBytes
[qi
-1] += count
;
984 if (qSize
[qi
-1] > 2501 || qBytes
[qi
-1] > 2000000000)
985 warn("Queue %s is %d elements/%d bytes, "
986 "maybe things aren't being removed?\n",
987 q
, qSize
[qi
-1], qBytes
[qi
-1]);
989 qData
[qi
-1].push_front(add(OP_QUEUE
, flags
, cpuid
, sm
, qi
, count
));
991 qData
[qi
-1].push_back(add(OP_QUEUE
, flags
, cpuid
, sm
, qi
, count
));
992 DPRINTFS(AnnotateQ
, sys
, "Queing in queue %s size now %d/%d\n",
993 q
, qSize
[qi
-1], qBytes
[qi
-1]);
994 assert(qSize
[qi
-1] >= 0);
995 assert(qBytes
[qi
-1] >= 0);
1000 CPA::doDq(System
*sys
, int flags
, int cpuid
, int sm
,
1001 string q
, int qi
, int count
)
1004 StringWrap
name(sys
->name());
1006 add(OP_DEQUEUE
, flags
, cpuid
, sm
, qi
, count
);
1007 qData
[qi
-1].clear();
1010 DPRINTF(AnnotateQ
, "Dequeing all data in queue %s size now %d/%d\n",
1011 q
, qSize
[qi
-1], qBytes
[qi
-1]);
1016 if (qSize
[qi
-1] <= 0 || qBytes
[qi
-1] <= 0 || !qData
[qi
-1].size()) {
1019 fatal("Queue %s dequing with no data available in queue!\n",
1022 assert(qSize
[qi
-1] >= 0);
1023 assert(qBytes
[qi
-1] >= 0);
1024 assert(qData
[qi
-1].size());
1026 int32_t need
= count
;
1027 qBytes
[qi
-1] -= count
;
1028 if (qBytes
[qi
-1] < 0) {
1031 fatal("Queue %s dequing with no bytes available in queue!\n",
1036 int32_t head_bytes
= qData
[qi
-1].front()->data
;
1037 if (qSize
[qi
-1] <= 0 || qBytes
[qi
-1] < 0) {
1040 fatal("Queue %s dequing with nothing in queue!\n",
1044 if (head_bytes
> need
) {
1045 qData
[qi
-1].front()->data
-= need
;
1047 } else if (head_bytes
== need
) {
1048 qData
[qi
-1].pop_front();
1052 qData
[qi
-1].pop_front();
1058 add(OP_DEQUEUE
, flags
, cpuid
, sm
, qi
, count
);
1059 DPRINTF(AnnotateQ
, "Dequeing in queue %s size now %d/%d\n",
1060 q
, qSize
[qi
-1], qBytes
[qi
-1]);
1066 CPA::serialize(CheckpointOut
&cp
) const
1069 SERIALIZE_SCALAR(numSm
);
1070 SERIALIZE_SCALAR(numSmt
);
1071 arrayParamOut(os
, "numSt", numSt
);
1072 arrayParamOut(os
, "numQ", numQ
);
1073 SERIALIZE_SCALAR(numSys
);
1074 SERIALIZE_SCALAR(numQs
);
1075 SERIALIZE_SCALAR(conId
);
1076 arrayParamOut(os
, "qSize", qSize
);
1077 arrayParamOut(os
, "qSize", qSize
);
1078 arrayParamOut(os
, "qBytes", qBytes
);
1083 // smtCache (SCache)
1086 i
= smtCache
.begin();
1087 while (i
!= smtCache
.end()) {
1088 paramOut(os
, csprintf("smtCache%d.str", x
), i
->first
);
1089 paramOut(os
, csprintf("smtCache%d.int", x
), i
->second
);
1093 // stCache (StCache)
1094 for (x
= 0; x
< stCache
.size(); x
++) {
1095 i
= stCache
[x
].begin();
1097 while (i
!= stCache
[x
].end()) {
1098 paramOut(os
, csprintf("stCache%d_%d.str", x
, y
), i
->first
);
1099 paramOut(os
, csprintf("stCache%d_%d.int", x
, y
), i
->second
);
1105 IdHCache::iterator idi
;
1106 for (x
= 0; x
< qCache
.size(); x
++) {
1107 idi
= qCache
[x
].begin();
1109 while (idi
!= qCache
[x
].end()) {
1110 paramOut(os
, csprintf("qCache%d_%d.str", x
, y
), idi
->first
.first
);
1111 paramOut(os
, csprintf("qCache%d_%d.id", x
, y
), idi
->first
.second
);
1112 paramOut(os
, csprintf("qCache%d_%d.int", x
, y
), idi
->second
);
1117 // smCache (IdCache)
1118 for (x
= 0; x
< smCache
.size(); x
++) {
1119 idi
= smCache
[x
].begin();
1121 paramOut(os
, csprintf("smCache%d", x
), smCache
[x
].size());
1122 while (idi
!= smCache
[x
].end()) {
1123 paramOut(os
, csprintf("smCache%d_%d.str", x
, y
), idi
->first
.first
);
1124 paramOut(os
, csprintf("smCache%d_%d.id", x
, y
), idi
->first
.second
);
1125 paramOut(os
, csprintf("smCache%d_%d.int", x
, y
), idi
->second
);
1130 // scLinks (ScCache) -- data not serialize
1133 // namecache (NameCache)
1134 NameCache::iterator ni
;
1136 ni
= nameCache
.begin();
1138 while (ni
!= nameCache
.end()) {
1139 paramOut(os
, csprintf("nameCache%d.name", x
), ni
->first
->name());
1140 paramOut(os
, csprintf("nameCache%d.str", x
), ni
->second
.first
);
1141 paramOut(os
, csprintf("nameCache%d.int", x
), ni
->second
.second
);
1145 // smStack (SmStack)
1146 SmStack::iterator si
;
1147 si
= smStack
.begin();
1149 paramOut(os
, "smStackIdCount", smStack
.size());
1150 while (si
!= smStack
.end()) {
1151 paramOut(os
, csprintf("smStackId%d.sys", x
), si
->first
.first
);
1152 paramOut(os
, csprintf("smStackId%d.frame", x
), si
->first
.second
);
1153 paramOut(os
, csprintf("smStackId%d.count", x
), si
->second
.size());
1154 for (y
= 0; y
< si
->second
.size(); y
++)
1155 paramOut(os
, csprintf("smStackId%d_%d", x
, y
), si
->second
[y
]);
1161 LinkMap::iterator li
;
1163 paramOut(os
, "lnMapSize", lnMap
.size());
1164 while (li
!= lnMap
.end()) {
1165 paramOut(os
, csprintf("lnMap%d.smi", x
), li
->first
);
1166 paramOut(os
, csprintf("lnMap%d.lsmi", x
), li
->second
);
1171 SwExpl::iterator swexpli
;
1172 swexpli
= swExpl
.begin();
1174 paramOut(os
, "swExplCount", swExpl
.size());
1175 while (swexpli
!= swExpl
.end()) {
1176 paramOut(os
, csprintf("swExpl%d.sys", x
), swexpli
->first
.first
);
1177 paramOut(os
, csprintf("swExpl%d.frame", x
), swexpli
->first
.second
);
1178 paramOut(os
, csprintf("swExpl%d.swexpl", x
), swexpli
->second
);
1185 ii
= lastState
.begin();
1186 paramOut(os
, "lastStateSize", lastState
.size());
1187 while (ii
!= lastState
.end()) {
1188 paramOut(os
, csprintf("lastState%d.smi", x
), ii
->first
);
1189 paramOut(os
, csprintf("lastState%d.sti", x
), ii
->second
);
1194 for (x
= 0; x
< smMap
.size(); x
++) {
1195 paramOut(os
, csprintf("smMap%d.sys", x
), smMap
[x
].first
);
1196 paramOut(os
, csprintf("smMap%d.smname", x
), smMap
[x
].second
.first
);
1197 paramOut(os
, csprintf("smMap%d.id", x
), smMap
[x
].second
.second
);
1201 for (x
= 0; x
< qMap
.size(); x
++) {
1202 paramOut(os
, csprintf("qMap%d.sys", x
), qMap
[x
].first
);
1203 paramOut(os
, csprintf("qMap%d.qname", x
), qMap
[x
].second
.first
);
1204 paramOut(os
, csprintf("qMap%d.id", x
), qMap
[x
].second
.second
);
1207 // qData (vector<AnnotateList>)
1208 for(x
= 0; x
< qData
.size(); x
++) {
1209 if (!qData
[x
].size())
1212 for (auto &ann
: qData
[x
]) {
1213 ann
->serializeSection(os
, csprintf("Q%d_%d", x
, y
));
1220 CPA::unserialize(CheckpointIn
&cp
)
1222 UNSERIALIZE_SCALAR(numSm
);
1223 UNSERIALIZE_SCALAR(numSmt
);
1224 UNSERIALIZE_CONTAINER(numSt
);
1225 UNSERIALIZE_CONTAINER(numQ
);
1226 UNSERIALIZE_SCALAR(numSys
);
1227 UNSERIALIZE_SCALAR(numQs
);
1228 UNSERIALIZE_SCALAR(conId
);
1229 UNSERIALIZE_CONTAINER(qSize
);
1230 UNSERIALIZE_CONTAINER(qBytes
);
1236 for (int x
= 0; x
< numSmt
; x
++) {
1237 paramIn(cp
, csprintf("smtCache%d.str", x
), str
);
1238 paramIn(cp
, csprintf("smtCache%d.int", x
), smi
);
1239 smtCache
[str
] = smi
;
1242 // stCache (StCache)
1243 stCache
.resize(numSmt
);
1244 for (int x
= 0; x
< numSmt
; x
++) {
1245 for (int y
= 0; y
< numSt
[x
]; y
++) {
1246 paramIn(cp
, csprintf("stCache%d_%d.str", x
,y
), str
);
1247 paramIn(cp
, csprintf("stCache%d_%d.int", x
,y
), smi
);
1248 stCache
[x
][str
] = smi
;
1254 qCache
.resize(numSys
);
1255 for (int x
= 0; x
< numSys
; x
++) {
1256 for (int y
= 0; y
< numQ
[x
]; y
++) {
1257 paramIn(cp
, csprintf("qCache%d_%d.str", x
,y
), str
);
1258 paramIn(cp
, csprintf("qCache%d_%d.id", x
,y
), id
);
1259 paramIn(cp
, csprintf("qCache%d_%d.int", x
,y
), smi
);
1260 qCache
[x
][Id(str
,id
)] = smi
;
1264 // smCache (IdCache)
1265 smCache
.resize(numSys
);
1266 for (int x
= 0; x
< numSys
; x
++) {
1268 paramIn(cp
, csprintf("smCache%d", x
), size
);
1269 for (int y
= 0; y
< size
; y
++) {
1270 paramIn(cp
, csprintf("smCache%d_%d.str", x
,y
), str
);
1271 paramIn(cp
, csprintf("smCache%d_%d.id", x
,y
), id
);
1272 paramIn(cp
, csprintf("smCache%d_%d.int", x
,y
), smi
);
1273 smCache
[x
][Id(str
,id
)] = smi
;
1277 // scLinks (ScCache) -- data not serialized, just creating one per sys
1278 for (int x
= 0; x
< numSys
; x
++)
1279 scLinks
.push_back(ScHCache());
1281 // nameCache (NameCache)
1282 for (int x
= 0; x
< numSys
; x
++) {
1288 objParamIn(cp
, csprintf("nameCache%d.name", x
), sptr
);
1289 sys
= dynamic_cast<System
*>(sptr
);
1291 paramIn(cp
, csprintf("nameCache%d.str", x
), str
);
1292 paramIn(cp
, csprintf("nameCache%d.int", x
), sysi
);
1293 nameCache
[sys
] = std::make_pair(str
, sysi
);
1298 paramIn(cp
, "smStackIdCount", smStack_size
);
1299 for (int x
= 0; x
< smStack_size
; x
++) {
1303 paramIn(cp
, csprintf("smStackId%d.sys", x
), sysi
);
1304 paramIn(cp
, csprintf("smStackId%d.frame", x
), frame
);
1305 paramIn(cp
, csprintf("smStackId%d.count", x
), count
);
1306 StackId sid
= StackId(sysi
, frame
);
1307 for (int y
= 0; y
< count
; y
++) {
1308 paramIn(cp
, csprintf("smStackId%d_%d", x
, y
), smi
);
1309 smStack
[sid
].push_back(smi
);
1316 paramIn(cp
, "lnMapSize", lnMap_size
);
1317 for (int x
= 0; x
< lnMap_size
; x
++) {
1318 paramIn(cp
, csprintf("lnMap%d.smi", x
), smi
);
1319 paramIn(cp
, csprintf("lnMap%d.lsmi", x
), lsmi
);
1325 paramIn(cp
, "swExplCount", swExpl_size
);
1326 for (int x
= 0; x
< swExpl_size
; x
++) {
1330 paramIn(cp
, csprintf("swExpl%d.sys", x
), sysi
);
1331 paramIn(cp
, csprintf("swExpl%d.frame", x
), frame
);
1332 paramIn(cp
, csprintf("swExpl%d.swexpl", x
), b
);
1333 StackId sid
= StackId(sysi
, frame
);
1340 paramIn(cp
, "lastStateSize", lastState_size
);
1341 for (int x
= 0; x
< lastState_size
; x
++) {
1342 paramIn(cp
, csprintf("lastState%d.smi", x
), smi
);
1343 paramIn(cp
, csprintf("lastState%d.sti", x
), sti
);
1344 lastState
[smi
] = sti
;
1349 smMap
.resize(numSm
);
1350 for (int x
= 0; x
< smMap
.size(); x
++) {
1351 paramIn(cp
, csprintf("smMap%d.sys", x
), smMap
[x
].first
);
1352 paramIn(cp
, csprintf("smMap%d.smname", x
), smMap
[x
].second
.first
);
1353 paramIn(cp
, csprintf("smMap%d.id", x
), smMap
[x
].second
.second
);
1358 for (int x
= 0; x
< qMap
.size(); x
++) {
1359 paramIn(cp
, csprintf("qMap%d.sys", x
), qMap
[x
].first
);
1360 paramIn(cp
, csprintf("qMap%d.qname", x
), qMap
[x
].second
.first
);
1361 paramIn(cp
, csprintf("qMap%d.id", x
), qMap
[x
].second
.second
);
1365 // qData (vector<AnnotateList>)
1366 qData
.resize(qSize
.size());
1367 for (int x
= 0; x
< qSize
.size(); x
++) {
1370 for (int y
= 0; y
< qSize
[x
]; y
++) {
1371 AnnDataPtr a
= std::make_shared
<AnnotateData
>();
1372 a
->unserializeSection(cp
, csprintf("Q%d_%d", x
, y
));
1374 qData
[x
].push_back(a
);
1380 CPA::AnnotateData::serialize(CheckpointOut
&cp
) const
1382 SERIALIZE_SCALAR(time
);
1383 SERIALIZE_SCALAR(data
);
1384 SERIALIZE_SCALAR(sm
);
1385 SERIALIZE_SCALAR(stq
);
1386 SERIALIZE_SCALAR(op
);
1387 SERIALIZE_SCALAR(flag
);
1388 SERIALIZE_SCALAR(cpu
);
1392 CPA::AnnotateData::unserialize(CheckpointIn
&cp
)
1394 UNSERIALIZE_SCALAR(time
);
1395 UNSERIALIZE_SCALAR(data
);
1397 UNSERIALIZE_SCALAR(sm
);
1398 UNSERIALIZE_SCALAR(stq
);
1399 UNSERIALIZE_SCALAR(op
);
1400 UNSERIALIZE_SCALAR(flag
);
1401 UNSERIALIZE_SCALAR(cpu
);
1408 return new CPA(this);