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/alpha/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 "sim/arguments.hh"
41 #include "sim/core.hh"
42 #include "sim/sim_exit.hh"
43 #include "sim/system.hh"
45 struct CPAIgnoreSymbol
50 #define CPA_IGNORE_SYMBOL(sym) { #sym, sizeof(#sym) }
52 CPAIgnoreSymbol ignoreSymbols
[] = {
53 CPA_IGNORE_SYMBOL("m5a_"),
54 CPA_IGNORE_SYMBOL("ret_from_sys_call"),
55 CPA_IGNORE_SYMBOL("ret_from_reschedule"),
56 CPA_IGNORE_SYMBOL("_spin_"),
57 CPA_IGNORE_SYMBOL("local_bh_"),
58 CPA_IGNORE_SYMBOL("restore_all"),
59 CPA_IGNORE_SYMBOL("Call_Pal_"),
60 CPA_IGNORE_SYMBOL("pal_post_interrupt"),
61 CPA_IGNORE_SYMBOL("rti_to_"),
62 CPA_IGNORE_SYMBOL("sys_int_2"),
63 CPA_IGNORE_SYMBOL("sys_interrupt"),
64 CPA_IGNORE_SYMBOL("normal_int"),
65 CPA_IGNORE_SYMBOL("TRAP_INTERRUPT_10_"),
66 CPA_IGNORE_SYMBOL("Trap_Interrupt"),
67 CPA_IGNORE_SYMBOL("do_entInt"),
68 CPA_IGNORE_SYMBOL("__do_softirq"),
69 CPA_IGNORE_SYMBOL("_end"),
70 CPA_IGNORE_SYMBOL("entInt"),
71 CPA_IGNORE_SYMBOL("entSys"),
74 #undef CPA_IGNORE_SYMBOL
77 using namespace TheISA
;
82 class AnnotateDumpCallback
: public Callback
88 virtual void process();
89 AnnotateDumpCallback(CPA
*_cpa
)
95 AnnotateDumpCallback::process()
103 : SimObject(p
), numSm(0), numSmt(0), numSys(0), numQs(0), conId(0)
106 fatal("Multiple annotation objects found in system");
109 _enabled
= p
->enabled
;
112 vector
<string
>::iterator i
;
113 i
= p
->user_apps
.begin();
115 while (i
!= p
->user_apps
.end()) {
116 ObjectFile
*of
= createObjectFile(*i
);
119 fatal("Couldn't load symbols from file: %s\n", *i
);
121 sf
.erase(0, sf
.rfind('/') + 1);;
122 DPRINTFN("file %s short: %s\n", *i
, sf
);
123 userApp
[sf
] = new SymbolTable
;
124 bool result1
= of
->loadGlobalSymbols(userApp
[sf
]);
125 bool result2
= of
->loadLocalSymbols(userApp
[sf
]);
126 if (!result1
|| !result2
)
128 assert(result1
&& result2
);
136 osbin
= simout
.create("annotate.bin", true);
137 // MAGIC version number 'M''5''A'N' + version/capabilities
138 ah
.version
= 0x4D35414E00000101ULL
;
141 osbin
->write((char*)&ah
, sizeof(AnnotateHeader
));
143 registerExitCallback(new AnnotateDumpCallback(this));
146 CPA::swSmBegin(ThreadContext
*tc
)
155 if (!TheISA::inUserMode(tc
))
156 debugSymbolTable
->findNearestSymbol(
157 tc
->readIntReg(ReturnAddressReg
), st
, junk
);
159 CopyStringOut(tc
, sm
, args
[0], 50);
160 System
*sys
= tc
->getSystemPtr();
161 StringWrap
name(sys
->name());
164 warn("Got null SM at tick %d\n", curTick());
166 int sysi
= getSys(sys
);
167 int smi
= getSm(sysi
, sm
, args
[1]);
168 DPRINTF(Annotate
, "Starting machine: %s(%d) sysi: %d id: %#x\n", sm
,
170 DPRINTF(Annotate
, "smMap[%d] = %d, %s, %#x\n", smi
,
171 smMap
[smi
-1].first
, smMap
[smi
-1].second
.first
,
172 smMap
[smi
-1].second
.second
);
174 uint64_t frame
= getFrame(tc
);
175 StackId sid
= StackId(sysi
, frame
);
177 // check if we need to link to the previous state machine
179 if (flags
& FL_LINK
) {
180 if (smStack
[sid
].size()) {
181 int prev_smi
= smStack
[sid
].back();
182 DPRINTF(Annotate
, "Linking from %d to state machine %s(%d) [%#x]\n",
183 prev_smi
, sm
, smi
, args
[1]);
186 DPRINTF(Annotate
, "LnMap already contains entry for %d of %d\n",
188 assert(lnMap
[smi
] == 0);
189 lnMap
[smi
] = prev_smi
;
191 add(OP_LINK
, FL_NONE
, tc
->contextId(), prev_smi
, smi
);
193 DPRINTF(Annotate
, "Not Linking to state machine %s(%d) [%#x]\n",
199 smStack
[sid
].push_back(smi
);
201 DPRINTF(Annotate
, "Stack Now (%#X):\n", frame
);
202 for (int x
= smStack
[sid
].size()-1; x
>= 0; x
--)
203 DPRINTF(Annotate
, "-- %d\n", smStack
[sid
][x
]);
205 // reset the sw state exculsion to false
210 Id id
= Id(sm
, frame
);
211 if (scLinks
[sysi
-1][id
]) {
212 AnnDataPtr an
= scLinks
[sysi
-1][id
];
213 scLinks
[sysi
-1].erase(id
);
217 "Found prev unknown linking from %d to state machine %s(%d)\n",
221 DPRINTF(Annotate
, "LnMap already contains entry for %d of %d\n",
223 assert(lnMap
[smi
] == 0);
227 // add a new begin ifwe have that info
229 DPRINTF(Annotate
, "st: %s smi: %d stCache.size %d\n", st
,
230 smi
, stCache
.size());
231 int sti
= getSt(sm
, st
);
232 lastState
[smi
] = sti
;
233 add(OP_BEGIN
, FL_NONE
, tc
->contextId(), smi
, sti
);
238 CPA::swSmEnd(ThreadContext
*tc
)
245 CopyStringOut(tc
, sm
, args
[0], 50);
246 System
*sys
= tc
->getSystemPtr();
247 doSwSmEnd(sys
, tc
->contextId(), sm
, getFrame(tc
));
251 CPA::doSwSmEnd(System
*sys
, int cpuid
, string sm
, uint64_t frame
)
253 int sysi
= getSys(sys
);
254 StackId sid
= StackId(sysi
, frame
);
257 // reset the sw state exculsion to false
262 int smib
= smStack
[sid
].back();
263 StringWrap
name(sys
->name());
264 DPRINTF(Annotate
, "Ending machine: %s[%d, %#x] (%d?)\n", sm
, sysi
,
267 if (!smStack
[sid
].size() || smMap
[smib
-1].second
.first
!= sm
) {
268 DPRINTF(Annotate
, "State Machine not unwinding correctly. sid: %d, %#x"
269 " top of stack: %s Current Stack:\n",
270 sysi
, frame
, smMap
[smib
-1].second
.first
);
271 for (int x
= smStack
[sid
].size()-1; x
>= 0; x
--)
272 DPRINTF(Annotate
, "-- %d\n", smStack
[sid
][x
]);
273 DPRINTF(Annotate
, "Ending machine: %s; end stack: %s\n", sm
,
274 smMap
[smib
-1].second
.first
);
276 warn("State machine stack not unwinding correctly at %d\n", curTick());
279 "State machine ending:%s sysi:%d id:%#x back:%d getSm:%d\n",
280 sm
, sysi
, smMap
[smib
-1].second
.second
, smStack
[sid
].back(),
281 getSm(sysi
, sm
, smMap
[smib
-1].second
.second
));
282 assert(getSm(sysi
, sm
, smMap
[smib
-1].second
.second
) ==
283 smStack
[sid
].back());
285 int smi
= smStack
[sid
].back();
286 smStack
[sid
].pop_back();
289 DPRINTF(Annotate
, "Linking %d back to %d\n", smi
, lnMap
[smi
]);
290 add(OP_LINK
, FL_NONE
, cpuid
, smi
, lnMap
[smi
]);
294 if (smStack
[sid
].size()) {
295 add(OP_BEGIN
, FL_NONE
, cpuid
, smi
, lastState
[smi
]);
298 DPRINTF(Annotate
, "Stack Now:\n");
299 for (int x
= smStack
[sid
].size()-1; x
>= 0; x
--)
300 DPRINTF(Annotate
, "-- %d\n", smStack
[sid
][x
]);
306 CPA::swExplictBegin(ThreadContext
*tc
)
313 CopyStringOut(tc
, st
, args
[1], 50);
315 StringWrap
name(tc
->getSystemPtr()->name());
316 DPRINTF(Annotate
, "Explict begin of state %s\n", st
);
317 uint32_t flags
= args
[0];
319 warn("BAD state encountered: at cycle %d: %s\n", curTick(), st
);
320 swBegin(tc
->getSystemPtr(), tc
->contextId(), st
, getFrame(tc
), true, args
[0]);
324 CPA::swAutoBegin(ThreadContext
*tc
, Addr next_pc
)
331 SymbolTable
*symtab
= NULL
;
334 if (!TheISA::inUserMode(tc
)) {
335 debugSymbolTable
->findNearestSymbol(next_pc
, sym
, sym_addr
);
336 symtab
= debugSymbolTable
;
338 Linux::ThreadInfo
ti(tc
);
339 string app
= ti
.curTaskName();
340 if (userApp
.count(app
))
341 userApp
[app
]->findNearestSymbol(next_pc
, sym
, sym_addr
);
345 swBegin(tc
->getSystemPtr(), tc
->contextId(), sym
, getFrame(tc
));
349 CPA::swBegin(System
*sys
, int cpuid
, std::string st
, uint64_t frame
, bool expl
,
354 while (ignoreSymbols
[x
].len
)
356 len
= ignoreSymbols
[x
].len
;
357 if (!st
.compare(0,len
, ignoreSymbols
[x
].symbol
, len
))
362 int sysi
= getSys(sys
);
363 StackId sid
= StackId(sysi
, frame
);
364 // if expl is true suspend symbol table based states
365 if (!smStack
[sid
].size())
367 if (!expl
&& swExpl
[sid
])
371 DPRINTFS(AnnotateVerbose
, sys
, "SwBegin: %s sysi: %d\n", st
, sysi
);
372 int smi
= smStack
[sid
].back();
373 int sti
= getSt(smMap
[smi
-1].second
.first
, st
);
374 if (lastState
[smi
] != sti
) {
375 lastState
[smi
] = sti
;
376 add(OP_BEGIN
, flags
, cpuid
, smi
, sti
);
381 CPA::swEnd(ThreadContext
*tc
)
388 if (!TheISA::inUserMode(tc
))
389 debugSymbolTable
->findNearestSymbol(
390 tc
->readIntReg(ReturnAddressReg
), st
, junk
);
391 System
*sys
= tc
->getSystemPtr();
392 StringWrap
name(sys
->name());
394 int sysi
= getSys(sys
);
395 StackId sid
= StackId(sysi
, getFrame(tc
));
396 if (!smStack
[sid
].size()) {
397 DPRINTF(Annotate
, "Explict end of State: %s IGNORED\n", st
);
400 DPRINTF(Annotate
, "Explict end of State: %s\n", st
);
401 // return back to symbol table based states
403 int smi
= smStack
[sid
].back();
405 int sti
= getSt(smMap
[smi
-1].second
.first
, st
);
406 lastState
[smi
] = sti
;
407 add(OP_BEGIN
, FL_NONE
, tc
->contextId(), smi
, sti
);
412 CPA::swQ(ThreadContext
*tc
)
419 uint64_t id
= args
[0];
420 CopyStringOut(tc
, q
, args
[1], 50);
421 int32_t count
= args
[2];
422 System
*sys
= tc
->getSystemPtr();
424 int sysi
= getSys(sys
);
425 StackId sid
= StackId(sysi
, getFrame(tc
));
426 if (!smStack
[sid
].size())
428 int smi
= smStack
[sid
].back();
431 int qi
= getQ(sysi
, q
, id
);
433 //warn("Tried to queue 0 bytes in %s, ignoring\n", q);
436 DPRINTFS(AnnotateQ
, sys
,
437 "swQ: %s[%#x] cur size %d %d bytes: %d adding: %d\n",
438 q
, id
, qSize
[qi
-1], qData
[qi
-1].size(), qBytes
[qi
-1], count
);
439 doQ(sys
, FL_NONE
, tc
->contextId(), smi
, q
, qi
, count
);
443 CPA::swDq(ThreadContext
*tc
)
450 uint64_t id
= args
[0];
451 CopyStringOut(tc
, q
, args
[1], 50);
452 int32_t count
= args
[2];
453 System
*sys
= tc
->getSystemPtr();
455 int sysi
= getSys(sys
);
456 StackId sid
= StackId(sysi
, getFrame(tc
));
457 if (!smStack
[sid
].size())
459 int smi
= smStack
[sid
].back();
460 int qi
= getQ(sysi
, q
, id
);
463 DPRINTFS(AnnotateQ
, sys
,
464 "swDq: %s[%#x] cur size %d %d bytes: %d removing: %d\n",
465 q
, id
, qSize
[qi
-1], qData
[qi
-1].size(), qBytes
[qi
-1], count
);
468 doDq(sys
, FL_NONE
, tc
->contextId(), smi
, q
, qi
, count
);
472 CPA::swPq(ThreadContext
*tc
)
479 uint64_t id
= args
[0];
480 CopyStringOut(tc
, q
, args
[1], 50);
481 System
*sys
= tc
->getSystemPtr();
482 int32_t count
= args
[2];
484 int sysi
= getSys(sys
);
485 StackId sid
= StackId(sysi
, getFrame(tc
));
486 if (!smStack
[sid
].size())
488 int smi
= smStack
[sid
].back();
489 int qi
= getQ(sysi
, q
, id
);
492 DPRINTFS(AnnotateQ
, sys
,
493 "swPq: %s [%#x] cur size %d %d bytes: %d peeking: %d\n",
494 q
, id
, qSize
[qi
-1], qData
[qi
-1].size(), qBytes
[qi
-1], count
);
497 if (qBytes
[qi
-1] < count
) {
500 fatal("Queue %s peeking with not enough bytes available in queue!\n", q
);
503 add(OP_PEEK
, FL_NONE
, tc
->contextId(), smi
, qi
, count
);
507 CPA::swRq(ThreadContext
*tc
)
514 uint64_t id
= args
[0];
515 CopyStringOut(tc
, q
, args
[1], 50);
516 System
*sys
= tc
->getSystemPtr();
517 int32_t count
= args
[2];
519 int sysi
= getSys(sys
);
520 StackId sid
= StackId(sysi
, getFrame(tc
));
521 if (!smStack
[sid
].size())
523 int smi
= smStack
[sid
].back();
524 int qi
= getQ(sysi
, q
, id
);
527 DPRINTFS(AnnotateQ
, sys
,
528 "swRq: %s [%#x] cur size %d %d bytes: %d reserve: %d\n",
529 q
, id
, qSize
[qi
-1], qData
[qi
-1].size(), qBytes
[qi
-1], count
);
533 add(OP_RESERVE
, FL_NONE
, tc
->contextId(), smi
, qi
, count
);
538 CPA::swWf(ThreadContext
*tc
)
545 uint64_t id
= args
[0];
546 CopyStringOut(tc
, q
, args
[1], 50);
547 System
*sys
= tc
->getSystemPtr();
548 int32_t count
= args
[3];
550 int sysi
= getSys(sys
);
551 StackId sid
= StackId(sysi
, getFrame(tc
));
552 if (!smStack
[sid
].size())
554 int smi
= smStack
[sid
].back();
555 int qi
= getQ(sysi
, q
, id
);
556 add(OP_WAIT_FULL
, FL_NONE
, tc
->contextId(), smi
, qi
, count
);
560 CopyStringOut(tc
, sm
, args
[2], 50);
561 doSwSmEnd(tc
->getSystemPtr(), tc
->contextId(), sm
, getFrame(tc
));
566 CPA::swWe(ThreadContext
*tc
)
573 uint64_t id
= args
[0];
574 CopyStringOut(tc
, q
, args
[1], 50);
575 System
*sys
= tc
->getSystemPtr();
576 int32_t count
= args
[3];
578 int sysi
= getSys(sys
);
579 StackId sid
= StackId(sysi
, getFrame(tc
));
580 if (!smStack
[sid
].size())
582 int smi
= smStack
[sid
].back();
583 int qi
= getQ(sysi
, q
, id
);
584 add(OP_WAIT_EMPTY
, FL_NONE
, tc
->contextId(), smi
, qi
, count
);
588 CopyStringOut(tc
, sm
, args
[2], 50);
589 doSwSmEnd(tc
->getSystemPtr(), tc
->contextId(), sm
, getFrame(tc
));
594 CPA::swSq(ThreadContext
*tc
)
601 uint64_t id
= args
[0];
602 CopyStringOut(tc
, q
, args
[1], 50);
603 System
*sys
= tc
->getSystemPtr();
604 StringWrap
name(sys
->name());
605 int32_t size
= args
[2];
608 int sysi
= getSys(sys
);
609 StackId sid
= StackId(sysi
, getFrame(tc
));
610 if (!smStack
[sid
].size())
612 int smi
= smStack
[sid
].back();
613 int qi
= getQ(sysi
, q
, id
);
614 DPRINTF(AnnotateQ
, "swSq: %s [%#x] cur size: %d bytes: %d, new size: %d\n",
615 q
, id
, qSize
[qi
-1], qBytes
[qi
-1], size
);
617 if (FL_RESET
& flags
) {
618 DPRINTF(AnnotateQ
, "Resetting Queue %s\n", q
);
619 add(OP_SIZE_QUEUE
, FL_NONE
, tc
->contextId(), smi
, qi
, 0);
625 if (qBytes
[qi
-1] < size
)
626 doQ(sys
, FL_NONE
, tc
->contextId(), smi
, q
, qi
, size
- qBytes
[qi
-1]);
627 else if (qBytes
[qi
-1] > size
) {
628 DPRINTF(AnnotateQ
, "removing for resize of queue %s\n", q
);
629 add(OP_SIZE_QUEUE
, FL_NONE
, tc
->contextId(), smi
, qi
, size
);
636 int need
= qBytes
[qi
-1] - size
;
639 int32_t tail_bytes
= qData
[qi
-1].back()->data
;
640 if (qSize
[qi
-1] <= 0 || qBytes
[qi
-1] < 0) {
643 fatal("Queue %s had inconsistancy when doing size queue!\n", q
);
645 if (tail_bytes
> need
) {
646 qData
[qi
-1].back()->data
-= need
;
648 } else if (tail_bytes
== need
) {
649 qData
[qi
-1].pop_back();
653 qData
[qi
-1].pop_back();
662 CPA::swAq(ThreadContext
*tc
)
669 uint64_t id
= args
[0];
670 CopyStringOut(tc
, q
, args
[1], 50);
671 System
*sys
= tc
->getSystemPtr();
672 StringWrap
name(sys
->name());
673 int32_t size
= args
[2];
675 int sysi
= getSys(sys
);
676 int qi
= getQ(sysi
, q
, id
);
677 if (qBytes
[qi
-1] != size
) {
678 DPRINTF(AnnotateQ
, "Queue %s [%#x] has inconsintant size\n", q
, id
);
681 std::list
<AnnDataPtr
>::iterator ai
= qData
[qi
-1].begin();
683 while (ai
!= qData
[qi
-1].end()) {
684 DPRINTF(AnnotateQ
, "--Element %d size %d\n", x
, (*ai
)->data
);
689 warn("%d: Queue Assert: SW said there should be %d byte(s) in %s,"
690 "however there are %d byte(s)\n",
691 curTick(), size
, q
, qBytes
[qi
-1]);
692 DPRINTF(AnnotateQ
, "%d: Queue Assert: SW said there should be %d"
693 " byte(s) in %s, however there are %d byte(s)\n",
694 curTick(), size
, q
, qBytes
[qi
-1]);
699 CPA::swLink(ThreadContext
*tc
)
706 CopyStringOut(tc
, lsm
, args
[0], 50);
707 System
*sys
= tc
->getSystemPtr();
708 StringWrap
name(sys
->name());
710 int sysi
= getSys(sys
);
711 StackId sid
= StackId(sysi
, getFrame(tc
));
712 if (!smStack
[sid
].size())
714 int smi
= smStack
[sid
].back();
715 int lsmi
= getSm(sysi
, lsm
, args
[1]);
717 DPRINTF(Annotate
, "Linking from %d to state machine %s(%d) [%#x]\n",
718 smi
, lsm
, lsmi
, args
[1]);
721 DPRINTF(Annotate
, "LnMap already contains entry for %d of %d\n",
723 assert(lnMap
[lsmi
] == 0);
726 add(OP_LINK
, FL_NONE
, tc
->contextId(), smi
, lsmi
);
730 CopyStringOut(tc
, sm
, args
[2], 50);
731 doSwSmEnd(tc
->getSystemPtr(), tc
->contextId(), sm
, getFrame(tc
));
736 CPA::swIdentify(ThreadContext
*tc
)
742 int sysi
= getSys(tc
->getSystemPtr());
743 StackId sid
= StackId(sysi
, getFrame(tc
));
744 if (!smStack
[sid
].size())
746 int smi
= smStack
[sid
].back();
748 DPRINTFS(Annotate
, tc
->getSystemPtr(), "swIdentify: id %#X\n", args
[0]);
750 add(OP_IDENT
, FL_NONE
, tc
->contextId(), smi
, 0, args
[0]);
754 CPA::swGetId(ThreadContext
*tc
)
759 uint64_t id
= ++conId
;
760 int sysi
= getSys(tc
->getSystemPtr());
761 StackId sid
= StackId(sysi
, getFrame(tc
));
762 if (!smStack
[sid
].size())
763 panic("swGetId called without a state machine stack!");
764 int smi
= smStack
[sid
].back();
766 DPRINTFS(Annotate
, tc
->getSystemPtr(), "swGetId: id %#X\n", id
);
768 add(OP_IDENT
, FL_NONE
, tc
->contextId(), smi
, 0, id
);
774 CPA::swSyscallLink(ThreadContext
*tc
)
781 CopyStringOut(tc
, lsm
, args
[0], 50);
782 System
*sys
= tc
->getSystemPtr();
783 StringWrap
name(sys
->name());
784 int sysi
= getSys(sys
);
786 Id id
= Id(lsm
, getFrame(tc
));
787 StackId sid
= StackId(sysi
, getFrame(tc
));
789 if (!smStack
[sid
].size())
792 int smi
= smStack
[sid
].back();
794 DPRINTF(Annotate
, "Linking from %d to state machine %s(UNKNOWN)\n",
797 if (scLinks
[sysi
-1][id
])
799 "scLinks already contains entry for system %d %s[%x] of %d\n",
800 sysi
, lsm
, getFrame(tc
), scLinks
[sysi
-1][id
]);
801 assert(scLinks
[sysi
-1][id
] == 0);
802 scLinks
[sysi
-1][id
] = add(OP_LINK
, FL_NONE
, tc
->contextId(), smi
, 0xFFFF);
803 scLinks
[sysi
-1][id
]->dump
= false;
807 CopyStringOut(tc
, sm
, args
[1], 50);
808 doSwSmEnd(tc
->getSystemPtr(), tc
->contextId(), sm
, getFrame(tc
));
813 CPA::add(int t
, int f
, int c
, int sm
, int stq
, int32_t d
)
815 AnnDataPtr an
= new AnnotateData
;
816 an
->time
= curTick();
828 DPRINTF(AnnotateVerbose
, "Annotate: op: %d flags: 0x%x sm: %d state: %d time: %d, data: %d\n",
829 an
->op
, an
->flag
, an
->sm
, an
->stq
, an
->time
, an
->data
);
831 // Don't dump Links because we might be setting no-dump on it
832 if (an
->op
!= OP_LINK
)
841 std::streampos curpos
= osbin
->tellp();
844 // Output the various state machines and their corresponding states
845 *osbin
<< "# Automatically generated state machine descriptor file" << endl
;
847 *osbin
<< "sms = {}" << endl
<< endl
;
848 vector
<string
> state_machines
;
849 state_machines
.resize(numSmt
+1);
851 // State machines, id -> states
852 SCache::iterator i
= smtCache
.begin();
853 while (i
!= smtCache
.end()) {
854 state_machines
[i
->second
] = i
->first
;
858 for (int x
= 1; x
< state_machines
.size(); x
++) {
859 vector
<string
> states
;
860 states
.resize(numSt
[x
-1]+1);
861 assert(x
-1 < stCache
.size());
862 SCache::iterator i
= stCache
[x
-1].begin();
863 while (i
!= stCache
[x
-1].end()) {
864 states
[i
->second
] = i
->first
;
867 *osbin
<< "sms[\"" << state_machines
[x
] << "\"] = [\"NULL\"";
868 for (int y
= 1; y
< states
.size(); y
++)
869 *osbin
<< ", \"" << states
[y
] << "\"";
870 *osbin
<< "]" << endl
;
873 *osbin
<< endl
<< endl
<< endl
;
875 // state machine number -> system, name, id
876 *osbin
<< "smNum = [\"NULL\"";
877 for (int x
= 0; x
< smMap
.size(); x
++)
878 *osbin
<< ", (" << smMap
[x
].first
<< ", \"" << smMap
[x
].second
.first
<<
879 "\", " << smMap
[x
].second
.second
<< ")";
880 *osbin
<< "]" << endl
;
882 *osbin
<< endl
<< endl
<< endl
;
884 // Output the systems
885 vector
<string
> systems
;
886 systems
.resize(numSys
+1);
887 NameCache::iterator i2
= nameCache
.begin();
888 while (i2
!= nameCache
.end()) {
889 systems
[i2
->second
.second
] = i2
->second
.first
;
893 *osbin
<< "sysNum = [\"NULL\"";
894 for (int x
= 1; x
< systems
.size(); x
++) {
895 *osbin
<< ", \"" << systems
[x
] << "\"";
897 *osbin
<< "]" << endl
;
899 // queue number -> system, qname, qid
900 *osbin
<< "queues = [\"NULL\"";
901 for (int x
= 0; x
< qMap
.size(); x
++)
902 *osbin
<< ", (" << qMap
[x
].first
<< ", \"" << qMap
[x
].second
.first
<<
903 "\", " << qMap
[x
].second
.second
<< ")";
904 *osbin
<< "]" << endl
;
906 *osbin
<< "smComb = [s for s in [(i,r) for i in xrange(1,len(sysNum)) "
907 << "for r in xrange (1,len(smNum))]]" << endl
;
908 ah
.key_len
= osbin
->tellp() - curpos
;
911 curpos
= osbin
->tellp();
914 for (int x
= 0; x
< annotateIdx
.size(); x
++)
915 osbin
->write((char*)&annotateIdx
[x
], sizeof(uint64_t));
916 ah
.idx_len
= osbin
->tellp() - curpos
;
919 osbin
->write((char*)&ah
, sizeof(AnnotateHeader
));
928 list
<AnnDataPtr
>::iterator i
;
935 // Dump the data every
936 if (!all
&& data
.size() < 10000)
939 DPRINTF(Annotate
, "Writing %d\n", data
.size());
940 while (i
!= data
.end()) {
943 // If we can't dump this record, hold here
944 if (!an
->dump
&& !all
)
948 if (ah
.num_recs
% 100000 == 0)
949 annotateIdx
.push_back(osbin
->tellp());
952 osbin
->write((char*)&(an
->time
), sizeof(an
->time
));
953 osbin
->write((char*)&(an
->orig_data
), sizeof(an
->orig_data
));
954 osbin
->write((char*)&(an
->sm
), sizeof(an
->sm
));
955 osbin
->write((char*)&(an
->stq
), sizeof(an
->stq
));
956 osbin
->write((char*)&(an
->op
), sizeof(an
->op
));
957 osbin
->write((char*)&(an
->flag
), sizeof(an
->flag
));
958 osbin
->write((char*)&(an
->cpu
), sizeof(an
->cpu
));
961 if (data
.begin() != i
)
962 data
.erase(data
.begin(), i
);
969 CPA::doQ(System
*sys
, int flags
, int cpuid
, int sm
,
970 string q
, int qi
, int count
)
973 qBytes
[qi
-1] += count
;
974 if (qSize
[qi
-1] > 2501 || qBytes
[qi
-1] > 2000000000)
975 warn("Queue %s is %d elements/%d bytes, "
976 "maybe things aren't being removed?\n",
977 q
, qSize
[qi
-1], qBytes
[qi
-1]);
979 qData
[qi
-1].push_front(add(OP_QUEUE
, flags
, cpuid
, sm
, qi
, count
));
981 qData
[qi
-1].push_back(add(OP_QUEUE
, flags
, cpuid
, sm
, qi
, count
));
982 DPRINTFS(AnnotateQ
, sys
, "Queing in queue %s size now %d/%d\n",
983 q
, qSize
[qi
-1], qBytes
[qi
-1]);
984 assert(qSize
[qi
-1] >= 0);
985 assert(qBytes
[qi
-1] >= 0);
990 CPA::doDq(System
*sys
, int flags
, int cpuid
, int sm
,
991 string q
, int qi
, int count
)
994 StringWrap
name(sys
->name());
996 add(OP_DEQUEUE
, flags
, cpuid
, sm
, qi
, count
);
1000 DPRINTF(AnnotateQ
, "Dequeing all data in queue %s size now %d/%d\n",
1001 q
, qSize
[qi
-1], qBytes
[qi
-1]);
1006 if (qSize
[qi
-1] <= 0 || qBytes
[qi
-1] <= 0 || !qData
[qi
-1].size()) {
1009 fatal("Queue %s dequing with no data available in queue!\n",
1012 assert(qSize
[qi
-1] >= 0);
1013 assert(qBytes
[qi
-1] >= 0);
1014 assert(qData
[qi
-1].size());
1016 int32_t need
= count
;
1017 qBytes
[qi
-1] -= count
;
1018 if (qBytes
[qi
-1] < 0) {
1021 fatal("Queue %s dequing with no bytes available in queue!\n",
1026 int32_t head_bytes
= qData
[qi
-1].front()->data
;
1027 if (qSize
[qi
-1] <= 0 || qBytes
[qi
-1] < 0) {
1030 fatal("Queue %s dequing with nothing in queue!\n",
1034 if (head_bytes
> need
) {
1035 qData
[qi
-1].front()->data
-= need
;
1037 } else if (head_bytes
== need
) {
1038 qData
[qi
-1].pop_front();
1042 qData
[qi
-1].pop_front();
1048 add(OP_DEQUEUE
, flags
, cpuid
, sm
, qi
, count
);
1049 DPRINTF(AnnotateQ
, "Dequeing in queue %s size now %d/%d\n",
1050 q
, qSize
[qi
-1], qBytes
[qi
-1]);
1056 CPA::serialize(std::ostream
&os
)
1059 SERIALIZE_SCALAR(numSm
);
1060 SERIALIZE_SCALAR(numSmt
);
1061 arrayParamOut(os
, "numSt", numSt
);
1062 arrayParamOut(os
, "numQ", numQ
);
1063 SERIALIZE_SCALAR(numSys
);
1064 SERIALIZE_SCALAR(numQs
);
1065 SERIALIZE_SCALAR(conId
);
1066 arrayParamOut(os
, "qSize", qSize
);
1067 arrayParamOut(os
, "qSize", qSize
);
1068 arrayParamOut(os
, "qBytes", qBytes
);
1070 std::list
<AnnDataPtr
>::iterator ai
;
1075 // smtCache (SCache)
1078 i
= smtCache
.begin();
1079 while (i
!= smtCache
.end()) {
1080 paramOut(os
, csprintf("smtCache%d.str", x
), i
->first
);
1081 paramOut(os
, csprintf("smtCache%d.int", x
), i
->second
);
1085 // stCache (StCache)
1086 for (x
= 0; x
< stCache
.size(); x
++) {
1087 i
= stCache
[x
].begin();
1089 while (i
!= stCache
[x
].end()) {
1090 paramOut(os
, csprintf("stCache%d_%d.str", x
, y
), i
->first
);
1091 paramOut(os
, csprintf("stCache%d_%d.int", x
, y
), i
->second
);
1097 IdHCache::iterator idi
;
1098 for (x
= 0; x
< qCache
.size(); x
++) {
1099 idi
= qCache
[x
].begin();
1101 while (idi
!= qCache
[x
].end()) {
1102 paramOut(os
, csprintf("qCache%d_%d.str", x
, y
), idi
->first
.first
);
1103 paramOut(os
, csprintf("qCache%d_%d.id", x
, y
), idi
->first
.second
);
1104 paramOut(os
, csprintf("qCache%d_%d.int", x
, y
), idi
->second
);
1109 // smCache (IdCache)
1110 for (x
= 0; x
< smCache
.size(); x
++) {
1111 idi
= smCache
[x
].begin();
1113 paramOut(os
, csprintf("smCache%d", x
), smCache
[x
].size());
1114 while (idi
!= smCache
[x
].end()) {
1115 paramOut(os
, csprintf("smCache%d_%d.str", x
, y
), idi
->first
.first
);
1116 paramOut(os
, csprintf("smCache%d_%d.id", x
, y
), idi
->first
.second
);
1117 paramOut(os
, csprintf("smCache%d_%d.int", x
, y
), idi
->second
);
1122 // scLinks (ScCache) -- data not serialize
1125 // namecache (NameCache)
1126 NameCache::iterator ni
;
1128 ni
= nameCache
.begin();
1130 while (ni
!= nameCache
.end()) {
1131 paramOut(os
, csprintf("nameCache%d.name", x
), ni
->first
->name());
1132 paramOut(os
, csprintf("nameCache%d.str", x
), ni
->second
.first
);
1133 paramOut(os
, csprintf("nameCache%d.int", x
), ni
->second
.second
);
1137 // smStack (SmStack)
1138 SmStack::iterator si
;
1139 si
= smStack
.begin();
1141 paramOut(os
, "smStackIdCount", smStack
.size());
1142 while (si
!= smStack
.end()) {
1143 paramOut(os
, csprintf("smStackId%d.sys", x
), si
->first
.first
);
1144 paramOut(os
, csprintf("smStackId%d.frame", x
), si
->first
.second
);
1145 paramOut(os
, csprintf("smStackId%d.count", x
), si
->second
.size());
1146 for (y
= 0; y
< si
->second
.size(); y
++)
1147 paramOut(os
, csprintf("smStackId%d_%d", x
, y
), si
->second
[y
]);
1153 LinkMap::iterator li
;
1155 paramOut(os
, "lnMapSize", lnMap
.size());
1156 while (li
!= lnMap
.end()) {
1157 paramOut(os
, csprintf("lnMap%d.smi", x
), li
->first
);
1158 paramOut(os
, csprintf("lnMap%d.lsmi", x
), li
->second
);
1163 SwExpl::iterator swexpli
;
1164 swexpli
= swExpl
.begin();
1166 paramOut(os
, "swExplCount", swExpl
.size());
1167 while (swexpli
!= swExpl
.end()) {
1168 paramOut(os
, csprintf("swExpl%d.sys", x
), swexpli
->first
.first
);
1169 paramOut(os
, csprintf("swExpl%d.frame", x
), swexpli
->first
.second
);
1170 paramOut(os
, csprintf("swExpl%d.swexpl", x
), swexpli
->second
);
1177 ii
= lastState
.begin();
1178 paramOut(os
, "lastStateSize", lastState
.size());
1179 while (ii
!= lastState
.end()) {
1180 paramOut(os
, csprintf("lastState%d.smi", x
), ii
->first
);
1181 paramOut(os
, csprintf("lastState%d.sti", x
), ii
->second
);
1186 for (x
= 0; x
< smMap
.size(); x
++) {
1187 paramOut(os
, csprintf("smMap%d.sys", x
), smMap
[x
].first
);
1188 paramOut(os
, csprintf("smMap%d.smname", x
), smMap
[x
].second
.first
);
1189 paramOut(os
, csprintf("smMap%d.id", x
), smMap
[x
].second
.second
);
1193 for (x
= 0; x
< qMap
.size(); x
++) {
1194 paramOut(os
, csprintf("qMap%d.sys", x
), qMap
[x
].first
);
1195 paramOut(os
, csprintf("qMap%d.qname", x
), qMap
[x
].second
.first
);
1196 paramOut(os
, csprintf("qMap%d.id", x
), qMap
[x
].second
.second
);
1199 // qData (vector<AnnotateList>)
1200 for(x
= 0; x
< qData
.size(); x
++) {
1201 if (!qData
[x
].size())
1204 ai
= qData
[x
].begin();
1205 while (ai
!= qData
[x
].end()) {
1206 nameOut(os
, csprintf("%s.Q%d_%d", name(), x
, y
));
1207 (*ai
)->serialize(os
);
1215 CPA::unserialize(Checkpoint
*cp
, const std::string
§ion
)
1217 UNSERIALIZE_SCALAR(numSm
);
1218 UNSERIALIZE_SCALAR(numSmt
);
1219 arrayParamIn(cp
, section
, "numSt", numSt
);
1220 arrayParamIn(cp
, section
, "numQ", numQ
);
1221 UNSERIALIZE_SCALAR(numSys
);
1222 UNSERIALIZE_SCALAR(numQs
);
1223 UNSERIALIZE_SCALAR(conId
);
1224 arrayParamIn(cp
, section
, "qSize", qSize
);
1225 arrayParamIn(cp
, section
, "qBytes", qBytes
);
1231 for (int x
= 0; x
< numSmt
; x
++) {
1232 paramIn(cp
, section
, csprintf("smtCache%d.str", x
), str
);
1233 paramIn(cp
, section
, csprintf("smtCache%d.int", x
), smi
);
1234 smtCache
[str
] = smi
;
1237 // stCache (StCache)
1238 stCache
.resize(numSmt
);
1239 for (int x
= 0; x
< numSmt
; x
++) {
1240 for (int y
= 0; y
< numSt
[x
]; y
++) {
1241 paramIn(cp
, section
, csprintf("stCache%d_%d.str", x
,y
), str
);
1242 paramIn(cp
, section
, csprintf("stCache%d_%d.int", x
,y
), smi
);
1243 stCache
[x
][str
] = smi
;
1249 qCache
.resize(numSys
);
1250 for (int x
= 0; x
< numSys
; x
++) {
1251 for (int y
= 0; y
< numQ
[x
]; y
++) {
1252 paramIn(cp
, section
, csprintf("qCache%d_%d.str", x
,y
), str
);
1253 paramIn(cp
, section
, csprintf("qCache%d_%d.id", x
,y
), id
);
1254 paramIn(cp
, section
, csprintf("qCache%d_%d.int", x
,y
), smi
);
1255 qCache
[x
][Id(str
,id
)] = smi
;
1259 // smCache (IdCache)
1260 smCache
.resize(numSys
);
1261 for (int x
= 0; x
< numSys
; x
++) {
1263 paramIn(cp
, section
, csprintf("smCache%d", x
), size
);
1264 for (int y
= 0; y
< size
; y
++) {
1265 paramIn(cp
, section
, csprintf("smCache%d_%d.str", x
,y
), str
);
1266 paramIn(cp
, section
, csprintf("smCache%d_%d.id", x
,y
), id
);
1267 paramIn(cp
, section
, csprintf("smCache%d_%d.int", x
,y
), smi
);
1268 smCache
[x
][Id(str
,id
)] = smi
;
1272 // scLinks (ScCache) -- data not serialized, just creating one per sys
1273 for (int x
= 0; x
< numSys
; x
++)
1274 scLinks
.push_back(ScHCache());
1276 // nameCache (NameCache)
1277 for (int x
= 0; x
< numSys
; x
++) {
1283 objParamIn(cp
, section
, csprintf("nameCache%d.name", x
), sptr
);
1284 sys
= dynamic_cast<System
*>(sptr
);
1286 paramIn(cp
, section
, csprintf("nameCache%d.str", x
), str
);
1287 paramIn(cp
, section
, csprintf("nameCache%d.int", x
), sysi
);
1288 nameCache
[sys
] = std::make_pair
<std::string
,int>(str
, sysi
);
1293 paramIn(cp
, section
, "smStackIdCount", smStack_size
);
1294 for (int x
= 0; x
< smStack_size
; x
++) {
1298 paramIn(cp
, section
, csprintf("smStackId%d.sys", x
), sysi
);
1299 paramIn(cp
, section
, csprintf("smStackId%d.frame", x
), frame
);
1300 paramIn(cp
, section
, csprintf("smStackId%d.count", x
), count
);
1301 StackId sid
= StackId(sysi
, frame
);
1302 for (int y
= 0; y
< count
; y
++) {
1303 paramIn(cp
, section
, csprintf("smStackId%d_%d", x
, y
), smi
);
1304 smStack
[sid
].push_back(smi
);
1311 paramIn(cp
, section
, "lnMapSize", lnMap_size
);
1312 for (int x
= 0; x
< lnMap_size
; x
++) {
1313 paramIn(cp
, section
, csprintf("lnMap%d.smi", x
), smi
);
1314 paramIn(cp
, section
, csprintf("lnMap%d.lsmi", x
), lsmi
);
1320 paramIn(cp
, section
, "swExplCount", swExpl_size
);
1321 for (int x
= 0; x
< swExpl_size
; x
++) {
1325 paramIn(cp
, section
, csprintf("swExpl%d.sys", x
), sysi
);
1326 paramIn(cp
, section
, csprintf("swExpl%d.frame", x
), frame
);
1327 paramIn(cp
, section
, csprintf("swExpl%d.swexpl", x
), b
);
1328 StackId sid
= StackId(sysi
, frame
);
1335 paramIn(cp
, section
, "lastStateSize", lastState_size
);
1336 for (int x
= 0; x
< lastState_size
; x
++) {
1337 paramIn(cp
, section
, csprintf("lastState%d.smi", x
), smi
);
1338 paramIn(cp
, section
, csprintf("lastState%d.sti", x
), sti
);
1339 lastState
[smi
] = sti
;
1344 smMap
.resize(numSm
);
1345 for (int x
= 0; x
< smMap
.size(); x
++) {
1346 paramIn(cp
, section
, csprintf("smMap%d.sys", x
), smMap
[x
].first
);
1347 paramIn(cp
, section
, csprintf("smMap%d.smname", x
), smMap
[x
].second
.first
);
1348 paramIn(cp
, section
, csprintf("smMap%d.id", x
), smMap
[x
].second
.second
);
1353 for (int x
= 0; x
< qMap
.size(); x
++) {
1354 paramIn(cp
, section
, csprintf("qMap%d.sys", x
), qMap
[x
].first
);
1355 paramIn(cp
, section
, csprintf("qMap%d.qname", x
), qMap
[x
].second
.first
);
1356 paramIn(cp
, section
, csprintf("qMap%d.id", x
), qMap
[x
].second
.second
);
1360 // qData (vector<AnnotateList>)
1361 qData
.resize(qSize
.size());
1362 for (int x
= 0; x
< qSize
.size(); x
++) {
1365 for (int y
= 0; y
< qSize
[x
]; y
++) {
1366 AnnDataPtr a
= new AnnotateData
;
1367 a
->unserialize(cp
, csprintf("%s.Q%d_%d", section
, x
, y
));
1369 qData
[x
].push_back(a
);
1375 CPA::AnnotateData::serialize(std::ostream
&os
)
1377 SERIALIZE_SCALAR(time
);
1378 SERIALIZE_SCALAR(data
);
1379 SERIALIZE_SCALAR(sm
);
1380 SERIALIZE_SCALAR(stq
);
1381 SERIALIZE_SCALAR(op
);
1382 SERIALIZE_SCALAR(flag
);
1383 SERIALIZE_SCALAR(cpu
);
1387 CPA::AnnotateData::unserialize(Checkpoint
*cp
, const std::string
§ion
)
1389 UNSERIALIZE_SCALAR(time
);
1390 UNSERIALIZE_SCALAR(data
);
1392 UNSERIALIZE_SCALAR(sm
);
1393 UNSERIALIZE_SCALAR(stq
);
1394 UNSERIALIZE_SCALAR(op
);
1395 UNSERIALIZE_SCALAR(flag
);
1396 UNSERIALIZE_SCALAR(cpu
);
1403 return new CPA(this);