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.
29 #include "base/cp_annotate.hh"
31 #include "arch/generic/linux/threadinfo.hh"
32 #include "arch/utility.hh"
33 #include "base/callback.hh"
34 #include "base/loader/object_file.hh"
35 #include "base/output.hh"
36 #include "base/trace.hh"
37 #include "config/the_isa.hh"
38 #include "cpu/thread_context.hh"
39 #include "debug/Annotate.hh"
40 #include "debug/AnnotateVerbose.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 auto *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 Loader::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));
147 CPA::getFrame(ThreadContext
*tc
)
149 // This code is ISA specific and will need to be changed
150 // if the annotation code is used for something other than Alpha
151 return (tc
->readMiscRegNoEffect(TheISA::IPR_PALtemp23
) &
157 CPA::swSmBegin(ThreadContext
*tc
, Addr sm_string
, int32_t sm_id
, int32_t flags
)
165 if (!TheISA::inUserMode(tc
))
166 Loader::debugSymbolTable
->findNearestSymbol(
167 tc
->readIntReg(ReturnAddressReg
), st
, junk
);
169 tc
->getVirtProxy().readString(sm
, sm_string
, 50);
170 System
*sys
= tc
->getSystemPtr();
171 StringWrap
name(sys
->name());
174 warn("Got null SM at tick %d\n", curTick());
176 int sysi
= getSys(sys
);
177 int smi
= getSm(sysi
, sm
, sm_id
);
178 DPRINTF(Annotate
, "Starting machine: %s(%d) sysi: %d id: %#x\n", sm
,
180 DPRINTF(Annotate
, "smMap[%d] = %d, %s, %#x\n", smi
,
181 smMap
[smi
-1].first
, smMap
[smi
-1].second
.first
,
182 smMap
[smi
-1].second
.second
);
184 uint64_t frame
= getFrame(tc
);
185 StackId sid
= StackId(sysi
, frame
);
187 // check if we need to link to the previous state machine
188 if (flags
& FL_LINK
) {
189 if (smStack
[sid
].size()) {
190 int prev_smi
= smStack
[sid
].back();
191 DPRINTF(Annotate
, "Linking from %d to state machine %s(%d) [%#x]\n",
192 prev_smi
, sm
, smi
, sm_id
);
195 DPRINTF(Annotate
, "LnMap already contains entry for %d of %d\n",
197 assert(lnMap
[smi
] == 0);
198 lnMap
[smi
] = prev_smi
;
200 add(OP_LINK
, FL_NONE
, tc
->contextId(), prev_smi
, smi
);
202 DPRINTF(Annotate
, "Not Linking to state machine %s(%d) [%#x]\n",
208 smStack
[sid
].push_back(smi
);
210 DPRINTF(Annotate
, "Stack Now (%#X):\n", frame
);
211 for (int x
= smStack
[sid
].size()-1; x
>= 0; x
--)
212 DPRINTF(Annotate
, "-- %d\n", smStack
[sid
][x
]);
214 // reset the sw state exculsion to false
219 Id id
= Id(sm
, frame
);
220 if (scLinks
[sysi
-1][id
]) {
221 AnnDataPtr an
= scLinks
[sysi
-1][id
];
222 scLinks
[sysi
-1].erase(id
);
226 "Found prev unknown linking from %d to state machine %s(%d)\n",
230 DPRINTF(Annotate
, "LnMap already contains entry for %d of %d\n",
232 assert(lnMap
[smi
] == 0);
236 // add a new begin ifwe have that info
238 DPRINTF(Annotate
, "st: %s smi: %d stCache.size %d\n", st
,
239 smi
, stCache
.size());
240 int sti
= getSt(sm
, st
);
241 lastState
[smi
] = sti
;
242 add(OP_BEGIN
, FL_NONE
, tc
->contextId(), smi
, sti
);
247 CPA::swSmEnd(ThreadContext
*tc
, Addr sm_string
)
253 tc
->getVirtProxy().readString(sm
, sm_string
, 50);
254 System
*sys
= tc
->getSystemPtr();
255 doSwSmEnd(sys
, tc
->contextId(), sm
, getFrame(tc
));
259 CPA::doSwSmEnd(System
*sys
, int cpuid
, string sm
, uint64_t frame
)
261 int sysi
= getSys(sys
);
262 StackId sid
= StackId(sysi
, frame
);
265 // reset the sw state exculsion to false
270 int smib
= smStack
[sid
].back();
271 StringWrap
name(sys
->name());
272 DPRINTF(Annotate
, "Ending machine: %s[%d, %#x] (%d?)\n", sm
, sysi
,
275 if (!smStack
[sid
].size() || smMap
[smib
-1].second
.first
!= sm
) {
276 DPRINTF(Annotate
, "State Machine not unwinding correctly. sid: %d, %#x"
277 " top of stack: %s Current Stack:\n",
278 sysi
, frame
, smMap
[smib
-1].second
.first
);
279 for (int x
= smStack
[sid
].size()-1; x
>= 0; x
--)
280 DPRINTF(Annotate
, "-- %d\n", smStack
[sid
][x
]);
281 DPRINTF(Annotate
, "Ending machine: %s; end stack: %s\n", sm
,
282 smMap
[smib
-1].second
.first
);
284 warn("State machine stack not unwinding correctly at %d\n", curTick());
287 "State machine ending:%s sysi:%d id:%#x back:%d getSm:%d\n",
288 sm
, sysi
, smMap
[smib
-1].second
.second
, smStack
[sid
].back(),
289 getSm(sysi
, sm
, smMap
[smib
-1].second
.second
));
290 assert(getSm(sysi
, sm
, smMap
[smib
-1].second
.second
) ==
291 smStack
[sid
].back());
293 int smi
= smStack
[sid
].back();
294 smStack
[sid
].pop_back();
297 DPRINTF(Annotate
, "Linking %d back to %d\n", smi
, lnMap
[smi
]);
298 add(OP_LINK
, FL_NONE
, cpuid
, smi
, lnMap
[smi
]);
302 if (smStack
[sid
].size()) {
303 add(OP_BEGIN
, FL_NONE
, cpuid
, smi
, lastState
[smi
]);
306 DPRINTF(Annotate
, "Stack Now:\n");
307 for (int x
= smStack
[sid
].size()-1; x
>= 0; x
--)
308 DPRINTF(Annotate
, "-- %d\n", smStack
[sid
][x
]);
314 CPA::swExplictBegin(ThreadContext
*tc
, int32_t flags
, Addr st_string
)
320 tc
->getVirtProxy().readString(st
, st_string
, 50);
322 StringWrap
name(tc
->getSystemPtr()->name());
323 DPRINTF(Annotate
, "Explict begin of state %s\n", st
);
325 warn("BAD state encountered: at cycle %d: %s\n", curTick(), st
);
326 swBegin(tc
->getSystemPtr(), tc
->contextId(),
327 st
, getFrame(tc
), true, flags
);
331 CPA::swAutoBegin(ThreadContext
*tc
, Addr next_pc
)
339 if (!TheISA::inUserMode(tc
)) {
340 Loader::debugSymbolTable
->findNearestSymbol(next_pc
, sym
, sym_addr
);
342 Linux::ThreadInfo
ti(tc
);
343 string app
= ti
.curTaskName();
344 if (userApp
.count(app
))
345 userApp
[app
]->findNearestSymbol(next_pc
, sym
, sym_addr
);
349 swBegin(tc
->getSystemPtr(), tc
->contextId(), sym
, getFrame(tc
));
353 CPA::swBegin(System
*sys
, int cpuid
, std::string st
, uint64_t frame
, bool expl
,
358 while (ignoreSymbols
[x
].len
)
360 len
= ignoreSymbols
[x
].len
;
361 if (!st
.compare(0,len
, ignoreSymbols
[x
].symbol
, len
))
366 int sysi
= getSys(sys
);
367 StackId sid
= StackId(sysi
, frame
);
368 // if expl is true suspend symbol table based states
369 if (!smStack
[sid
].size())
371 if (!expl
&& swExpl
[sid
])
375 DPRINTFS(AnnotateVerbose
, sys
, "SwBegin: %s sysi: %d\n", st
, sysi
);
376 int smi
= smStack
[sid
].back();
377 int sti
= getSt(smMap
[smi
-1].second
.first
, st
);
378 if (lastState
[smi
] != sti
) {
379 lastState
[smi
] = sti
;
380 add(OP_BEGIN
, flags
, cpuid
, smi
, sti
);
385 CPA::swEnd(ThreadContext
*tc
)
392 if (!TheISA::inUserMode(tc
))
393 Loader::debugSymbolTable
->findNearestSymbol(
394 tc
->readIntReg(ReturnAddressReg
), st
, junk
);
395 System
*sys
= tc
->getSystemPtr();
396 StringWrap
name(sys
->name());
398 int sysi
= getSys(sys
);
399 StackId sid
= StackId(sysi
, getFrame(tc
));
400 if (!smStack
[sid
].size()) {
401 DPRINTF(Annotate
, "Explict end of State: %s IGNORED\n", st
);
404 DPRINTF(Annotate
, "Explict end of State: %s\n", st
);
405 // return back to symbol table based states
407 int smi
= smStack
[sid
].back();
409 int sti
= getSt(smMap
[smi
-1].second
.first
, st
);
410 lastState
[smi
] = sti
;
411 add(OP_BEGIN
, FL_NONE
, tc
->contextId(), smi
, sti
);
416 CPA::swQ(ThreadContext
*tc
, Addr id
, Addr q_string
, int32_t count
)
422 tc
->getVirtProxy().readString(q
, q_string
, 50);
423 System
*sys
= tc
->getSystemPtr();
425 int sysi
= getSys(sys
);
426 StackId sid
= StackId(sysi
, getFrame(tc
));
427 if (!smStack
[sid
].size())
429 int smi
= smStack
[sid
].back();
432 int qi
= getQ(sysi
, q
, id
);
434 //warn("Tried to queue 0 bytes in %s, ignoring\n", q);
437 DPRINTFS(AnnotateQ
, sys
,
438 "swQ: %s[%#x] cur size %d %d bytes: %d adding: %d\n",
439 q
, id
, qSize
[qi
-1], qData
[qi
-1].size(), qBytes
[qi
-1], count
);
440 doQ(sys
, FL_NONE
, tc
->contextId(), smi
, q
, qi
, count
);
444 CPA::swDq(ThreadContext
*tc
, Addr id
, Addr q_string
, int32_t count
)
450 tc
->getVirtProxy().readString(q
, q_string
, 50);
451 System
*sys
= tc
->getSystemPtr();
453 int sysi
= getSys(sys
);
454 StackId sid
= StackId(sysi
, getFrame(tc
));
455 if (!smStack
[sid
].size())
457 int smi
= smStack
[sid
].back();
458 int qi
= getQ(sysi
, q
, id
);
461 DPRINTFS(AnnotateQ
, sys
,
462 "swDq: %s[%#x] cur size %d %d bytes: %d removing: %d\n",
463 q
, id
, qSize
[qi
-1], qData
[qi
-1].size(), qBytes
[qi
-1], count
);
466 doDq(sys
, FL_NONE
, tc
->contextId(), smi
, q
, qi
, count
);
470 CPA::swPq(ThreadContext
*tc
, Addr id
, Addr q_string
, int32_t count
)
476 tc
->getVirtProxy().readString(q
, q_string
, 50);
477 System
*sys
= tc
->getSystemPtr();
479 int sysi
= getSys(sys
);
480 StackId sid
= StackId(sysi
, getFrame(tc
));
481 if (!smStack
[sid
].size())
483 int smi
= smStack
[sid
].back();
484 int qi
= getQ(sysi
, q
, id
);
487 DPRINTFS(AnnotateQ
, sys
,
488 "swPq: %s [%#x] cur size %d %d bytes: %d peeking: %d\n",
489 q
, id
, qSize
[qi
-1], qData
[qi
-1].size(), qBytes
[qi
-1], count
);
492 if (qBytes
[qi
-1] < count
) {
495 fatal("Queue %s peeking with not enough bytes available in queue!\n", q
);
498 add(OP_PEEK
, FL_NONE
, tc
->contextId(), smi
, qi
, count
);
502 CPA::swRq(ThreadContext
*tc
, Addr id
, Addr q_string
, int32_t count
)
508 tc
->getVirtProxy().readString(q
, q_string
, 50);
509 System
*sys
= tc
->getSystemPtr();
511 int sysi
= getSys(sys
);
512 StackId sid
= StackId(sysi
, getFrame(tc
));
513 if (!smStack
[sid
].size())
515 int smi
= smStack
[sid
].back();
516 int qi
= getQ(sysi
, q
, id
);
519 DPRINTFS(AnnotateQ
, sys
,
520 "swRq: %s [%#x] cur size %d %d bytes: %d reserve: %d\n",
521 q
, id
, qSize
[qi
-1], qData
[qi
-1].size(), qBytes
[qi
-1], count
);
525 add(OP_RESERVE
, FL_NONE
, tc
->contextId(), smi
, qi
, count
);
530 CPA::swWf(ThreadContext
*tc
, Addr id
, Addr q_string
, Addr sm_string
,
537 tc
->getVirtProxy().readString(q
, q_string
, 50);
538 System
*sys
= tc
->getSystemPtr();
540 int sysi
= getSys(sys
);
541 StackId sid
= StackId(sysi
, getFrame(tc
));
542 if (!smStack
[sid
].size())
544 int smi
= smStack
[sid
].back();
545 int qi
= getQ(sysi
, q
, id
);
546 add(OP_WAIT_FULL
, FL_NONE
, tc
->contextId(), smi
, qi
, count
);
550 tc
->getVirtProxy().readString(sm
, sm_string
, 50);
551 doSwSmEnd(tc
->getSystemPtr(), tc
->contextId(), sm
, getFrame(tc
));
556 CPA::swWe(ThreadContext
*tc
, Addr id
, Addr q_string
, Addr sm_string
,
563 tc
->getVirtProxy().readString(q
, q_string
, 50);
564 System
*sys
= tc
->getSystemPtr();
566 int sysi
= getSys(sys
);
567 StackId sid
= StackId(sysi
, getFrame(tc
));
568 if (!smStack
[sid
].size())
570 int smi
= smStack
[sid
].back();
571 int qi
= getQ(sysi
, q
, id
);
572 add(OP_WAIT_EMPTY
, FL_NONE
, tc
->contextId(), smi
, qi
, count
);
576 tc
->getVirtProxy().readString(sm
, sm_string
, 50);
577 doSwSmEnd(tc
->getSystemPtr(), tc
->contextId(), sm
, getFrame(tc
));
582 CPA::swSq(ThreadContext
*tc
, Addr id
, Addr q_string
, int32_t size
,
589 tc
->getVirtProxy().readString(q
, q_string
, 50);
590 System
*sys
= tc
->getSystemPtr();
591 StringWrap
name(sys
->name());
593 int sysi
= getSys(sys
);
594 StackId sid
= StackId(sysi
, getFrame(tc
));
595 if (!smStack
[sid
].size())
597 int smi
= smStack
[sid
].back();
598 int qi
= getQ(sysi
, q
, id
);
599 DPRINTF(AnnotateQ
, "swSq: %s [%#x] cur size: %d bytes: %d, new size: %d\n",
600 q
, id
, qSize
[qi
-1], qBytes
[qi
-1], size
);
602 if (FL_RESET
& flags
) {
603 DPRINTF(AnnotateQ
, "Resetting Queue %s\n", q
);
604 add(OP_SIZE_QUEUE
, FL_NONE
, tc
->contextId(), smi
, qi
, 0);
610 if (qBytes
[qi
-1] < size
)
611 doQ(sys
, FL_NONE
, tc
->contextId(), smi
, q
, qi
, size
- qBytes
[qi
-1]);
612 else if (qBytes
[qi
-1] > size
) {
613 DPRINTF(AnnotateQ
, "removing for resize of queue %s\n", q
);
614 add(OP_SIZE_QUEUE
, FL_NONE
, tc
->contextId(), smi
, qi
, size
);
621 int need
= qBytes
[qi
-1] - size
;
624 int32_t tail_bytes
= qData
[qi
-1].back()->data
;
625 if (qSize
[qi
-1] <= 0 || qBytes
[qi
-1] < 0) {
628 fatal("Queue %s had inconsistancy when doing size queue!\n", q
);
630 if (tail_bytes
> need
) {
631 qData
[qi
-1].back()->data
-= need
;
633 } else if (tail_bytes
== need
) {
634 qData
[qi
-1].pop_back();
638 qData
[qi
-1].pop_back();
647 CPA::swAq(ThreadContext
*tc
, Addr id
, Addr q_string
, int32_t size
)
653 tc
->getVirtProxy().readString(q
, q_string
, 50);
654 System
*sys
= tc
->getSystemPtr();
655 StringWrap
name(sys
->name());
657 int sysi
= getSys(sys
);
658 int qi
= getQ(sysi
, q
, id
);
659 if (qBytes
[qi
-1] != size
) {
660 DPRINTF(AnnotateQ
, "Queue %s [%#x] has inconsintant size\n", q
, id
);
663 std::list
<AnnDataPtr
>::iterator ai
= qData
[qi
-1].begin();
665 while (ai
!= qData
[qi
-1].end()) {
666 DPRINTF(AnnotateQ
, "--Element %d size %d\n", x
, (*ai
)->data
);
671 warn("%d: Queue Assert: SW said there should be %d byte(s) in %s,"
672 "however there are %d byte(s)\n",
673 curTick(), size
, q
, qBytes
[qi
-1]);
674 DPRINTF(AnnotateQ
, "%d: Queue Assert: SW said there should be %d"
675 " byte(s) in %s, however there are %d byte(s)\n",
676 curTick(), size
, q
, qBytes
[qi
-1]);
681 CPA::swLink(ThreadContext
*tc
, Addr lsm_string
, Addr lsm_id
, Addr sm_string
)
687 tc
->getVirtProxy().readString(lsm
, lsm_string
, 50);
688 System
*sys
= tc
->getSystemPtr();
689 StringWrap
name(sys
->name());
691 int sysi
= getSys(sys
);
692 StackId sid
= StackId(sysi
, getFrame(tc
));
693 if (!smStack
[sid
].size())
695 int smi
= smStack
[sid
].back();
696 int lsmi
= getSm(sysi
, lsm
, lsm_id
);
698 DPRINTF(Annotate
, "Linking from %d to state machine %s(%d) [%#x]\n",
699 smi
, lsm
, lsmi
, lsm_id
);
702 DPRINTF(Annotate
, "LnMap already contains entry for %d of %d\n",
704 assert(lnMap
[lsmi
] == 0);
707 add(OP_LINK
, FL_NONE
, tc
->contextId(), smi
, lsmi
);
711 tc
->getVirtProxy().readString(sm
, sm_string
, 50);
712 doSwSmEnd(tc
->getSystemPtr(), tc
->contextId(), sm
, getFrame(tc
));
717 CPA::swIdentify(ThreadContext
*tc
, Addr smi_string
)
722 int sysi
= getSys(tc
->getSystemPtr());
723 StackId sid
= StackId(sysi
, getFrame(tc
));
724 if (!smStack
[sid
].size())
726 int smi
= smStack
[sid
].back();
728 DPRINTFS(Annotate
, tc
->getSystemPtr(), "swIdentify: id %#X\n", smi_string
);
730 add(OP_IDENT
, FL_NONE
, tc
->contextId(), smi
, 0, smi_string
);
734 CPA::swGetId(ThreadContext
*tc
)
739 uint64_t id
= ++conId
;
740 int sysi
= getSys(tc
->getSystemPtr());
741 StackId sid
= StackId(sysi
, getFrame(tc
));
742 if (!smStack
[sid
].size())
743 panic("swGetId called without a state machine stack!");
744 int smi
= smStack
[sid
].back();
746 DPRINTFS(Annotate
, tc
->getSystemPtr(), "swGetId: id %#X\n", id
);
748 add(OP_IDENT
, FL_NONE
, tc
->contextId(), smi
, 0, id
);
754 CPA::swSyscallLink(ThreadContext
*tc
, Addr lsm_string
, Addr sm_string
)
760 tc
->getVirtProxy().readString(lsm
, lsm_string
, 50);
761 System
*sys
= tc
->getSystemPtr();
762 StringWrap
name(sys
->name());
763 int sysi
= getSys(sys
);
765 Id id
= Id(lsm
, getFrame(tc
));
766 StackId sid
= StackId(sysi
, getFrame(tc
));
768 if (!smStack
[sid
].size())
771 int smi
= smStack
[sid
].back();
773 DPRINTF(Annotate
, "Linking from %d to state machine %s(UNKNOWN)\n",
776 if (scLinks
[sysi
-1][id
])
778 "scLinks already contains entry for system %d %s[%x] of %d\n",
779 sysi
, lsm
, getFrame(tc
), scLinks
[sysi
-1][id
]);
780 assert(scLinks
[sysi
-1][id
] == 0);
781 scLinks
[sysi
-1][id
] = add(OP_LINK
, FL_NONE
, tc
->contextId(), smi
, 0xFFFF);
782 scLinks
[sysi
-1][id
]->dump
= false;
786 tc
->getVirtProxy().readString(sm
, sm_string
, 50);
787 doSwSmEnd(tc
->getSystemPtr(), tc
->contextId(), sm
, getFrame(tc
));
792 CPA::add(int t
, int f
, int c
, int sm
, int stq
, int32_t d
)
794 AnnDataPtr an
= std::make_shared
<AnnotateData
>();
795 an
->time
= curTick();
807 DPRINTF(AnnotateVerbose
, "Annotate: op: %d flags: 0x%x sm: %d state: %d time: %d, data: %d\n",
808 an
->op
, an
->flag
, an
->sm
, an
->stq
, an
->time
, an
->data
);
810 // Don't dump Links because we might be setting no-dump on it
811 if (an
->op
!= OP_LINK
)
820 std::streampos curpos
= osbin
->tellp();
823 // Output the various state machines and their corresponding states
824 *osbin
<< "# Automatically generated state machine descriptor file" << endl
;
826 *osbin
<< "sms = {}" << endl
<< endl
;
827 vector
<string
> state_machines
;
828 state_machines
.resize(numSmt
+1);
830 // State machines, id -> states
831 SCache::iterator i
= smtCache
.begin();
832 while (i
!= smtCache
.end()) {
833 state_machines
[i
->second
] = i
->first
;
837 for (int x
= 1; x
< state_machines
.size(); x
++) {
838 vector
<string
> states
;
839 states
.resize(numSt
[x
-1]+1);
840 assert(x
-1 < stCache
.size());
841 SCache::iterator i
= stCache
[x
-1].begin();
842 while (i
!= stCache
[x
-1].end()) {
843 states
[i
->second
] = i
->first
;
846 *osbin
<< "sms[\"" << state_machines
[x
] << "\"] = [\"NULL\"";
847 for (int y
= 1; y
< states
.size(); y
++)
848 *osbin
<< ", \"" << states
[y
] << "\"";
849 *osbin
<< "]" << endl
;
852 *osbin
<< endl
<< endl
<< endl
;
854 // state machine number -> system, name, id
855 *osbin
<< "smNum = [\"NULL\"";
856 for (int x
= 0; x
< smMap
.size(); x
++)
857 *osbin
<< ", (" << smMap
[x
].first
<< ", \"" << smMap
[x
].second
.first
<<
858 "\", " << smMap
[x
].second
.second
<< ")";
859 *osbin
<< "]" << endl
;
861 *osbin
<< endl
<< endl
<< endl
;
863 // Output the systems
864 vector
<string
> systems
;
865 systems
.resize(numSys
+1);
866 NameCache::iterator i2
= nameCache
.begin();
867 while (i2
!= nameCache
.end()) {
868 systems
[i2
->second
.second
] = i2
->second
.first
;
872 *osbin
<< "sysNum = [\"NULL\"";
873 for (int x
= 1; x
< systems
.size(); x
++) {
874 *osbin
<< ", \"" << systems
[x
] << "\"";
876 *osbin
<< "]" << endl
;
878 // queue number -> system, qname, qid
879 *osbin
<< "queues = [\"NULL\"";
880 for (int x
= 0; x
< qMap
.size(); x
++)
881 *osbin
<< ", (" << qMap
[x
].first
<< ", \"" << qMap
[x
].second
.first
<<
882 "\", " << qMap
[x
].second
.second
<< ")";
883 *osbin
<< "]" << endl
;
885 *osbin
<< "smComb = [s for s in [(i,r) for i in xrange(1,len(sysNum)) "
886 << "for r in xrange (1,len(smNum))]]" << endl
;
887 ah
.key_len
= osbin
->tellp() - curpos
;
890 curpos
= osbin
->tellp();
893 for (int x
= 0; x
< annotateIdx
.size(); x
++)
894 osbin
->write((char*)&annotateIdx
[x
], sizeof(uint64_t));
895 ah
.idx_len
= osbin
->tellp() - curpos
;
898 osbin
->write((char*)&ah
, sizeof(AnnotateHeader
));
907 list
<AnnDataPtr
>::iterator i
;
914 // Dump the data every
915 if (!all
&& data
.size() < 10000)
918 DPRINTF(Annotate
, "Writing %d\n", data
.size());
919 while (i
!= data
.end()) {
922 // If we can't dump this record, hold here
923 if (!an
->dump
&& !all
)
927 if (ah
.num_recs
% 100000 == 0)
928 annotateIdx
.push_back(osbin
->tellp());
931 osbin
->write((char*)&(an
->time
), sizeof(an
->time
));
932 osbin
->write((char*)&(an
->orig_data
), sizeof(an
->orig_data
));
933 osbin
->write((char*)&(an
->sm
), sizeof(an
->sm
));
934 osbin
->write((char*)&(an
->stq
), sizeof(an
->stq
));
935 osbin
->write((char*)&(an
->op
), sizeof(an
->op
));
936 osbin
->write((char*)&(an
->flag
), sizeof(an
->flag
));
937 osbin
->write((char*)&(an
->cpu
), sizeof(an
->cpu
));
940 if (data
.begin() != i
)
941 data
.erase(data
.begin(), i
);
948 CPA::doQ(System
*sys
, int flags
, int cpuid
, int sm
,
949 string q
, int qi
, int count
)
952 qBytes
[qi
-1] += count
;
953 if (qSize
[qi
-1] > 2501 || qBytes
[qi
-1] > 2000000000)
954 warn("Queue %s is %d elements/%d bytes, "
955 "maybe things aren't being removed?\n",
956 q
, qSize
[qi
-1], qBytes
[qi
-1]);
958 qData
[qi
-1].push_front(add(OP_QUEUE
, flags
, cpuid
, sm
, qi
, count
));
960 qData
[qi
-1].push_back(add(OP_QUEUE
, flags
, cpuid
, sm
, qi
, count
));
961 DPRINTFS(AnnotateQ
, sys
, "Queing in queue %s size now %d/%d\n",
962 q
, qSize
[qi
-1], qBytes
[qi
-1]);
963 assert(qSize
[qi
-1] >= 0);
964 assert(qBytes
[qi
-1] >= 0);
969 CPA::doDq(System
*sys
, int flags
, int cpuid
, int sm
,
970 string q
, int qi
, int count
)
973 StringWrap
name(sys
->name());
975 add(OP_DEQUEUE
, flags
, cpuid
, sm
, qi
, count
);
979 DPRINTF(AnnotateQ
, "Dequeing all data in queue %s size now %d/%d\n",
980 q
, qSize
[qi
-1], qBytes
[qi
-1]);
985 if (qSize
[qi
-1] <= 0 || qBytes
[qi
-1] <= 0 || !qData
[qi
-1].size()) {
988 fatal("Queue %s dequing with no data available in queue!\n",
991 assert(qSize
[qi
-1] >= 0);
992 assert(qBytes
[qi
-1] >= 0);
993 assert(qData
[qi
-1].size());
995 int32_t need
= count
;
996 qBytes
[qi
-1] -= count
;
997 if (qBytes
[qi
-1] < 0) {
1000 fatal("Queue %s dequing with no bytes available in queue!\n",
1005 int32_t head_bytes
= qData
[qi
-1].front()->data
;
1006 if (qSize
[qi
-1] <= 0 || qBytes
[qi
-1] < 0) {
1009 fatal("Queue %s dequing with nothing in queue!\n",
1013 if (head_bytes
> need
) {
1014 qData
[qi
-1].front()->data
-= need
;
1016 } else if (head_bytes
== need
) {
1017 qData
[qi
-1].pop_front();
1021 qData
[qi
-1].pop_front();
1027 add(OP_DEQUEUE
, flags
, cpuid
, sm
, qi
, count
);
1028 DPRINTF(AnnotateQ
, "Dequeing in queue %s size now %d/%d\n",
1029 q
, qSize
[qi
-1], qBytes
[qi
-1]);
1035 CPA::serialize(CheckpointOut
&cp
) const
1038 SERIALIZE_SCALAR(numSm
);
1039 SERIALIZE_SCALAR(numSmt
);
1040 arrayParamOut(os
, "numSt", numSt
);
1041 arrayParamOut(os
, "numQ", numQ
);
1042 SERIALIZE_SCALAR(numSys
);
1043 SERIALIZE_SCALAR(numQs
);
1044 SERIALIZE_SCALAR(conId
);
1045 arrayParamOut(os
, "qSize", qSize
);
1046 arrayParamOut(os
, "qSize", qSize
);
1047 arrayParamOut(os
, "qBytes", qBytes
);
1052 // smtCache (SCache)
1055 i
= smtCache
.begin();
1056 while (i
!= smtCache
.end()) {
1057 paramOut(os
, csprintf("smtCache%d.str", x
), i
->first
);
1058 paramOut(os
, csprintf("smtCache%d.int", x
), i
->second
);
1062 // stCache (StCache)
1063 for (x
= 0; x
< stCache
.size(); x
++) {
1064 i
= stCache
[x
].begin();
1066 while (i
!= stCache
[x
].end()) {
1067 paramOut(os
, csprintf("stCache%d_%d.str", x
, y
), i
->first
);
1068 paramOut(os
, csprintf("stCache%d_%d.int", x
, y
), i
->second
);
1074 IdHCache::iterator idi
;
1075 for (x
= 0; x
< qCache
.size(); x
++) {
1076 idi
= qCache
[x
].begin();
1078 while (idi
!= qCache
[x
].end()) {
1079 paramOut(os
, csprintf("qCache%d_%d.str", x
, y
), idi
->first
.first
);
1080 paramOut(os
, csprintf("qCache%d_%d.id", x
, y
), idi
->first
.second
);
1081 paramOut(os
, csprintf("qCache%d_%d.int", x
, y
), idi
->second
);
1086 // smCache (IdCache)
1087 for (x
= 0; x
< smCache
.size(); x
++) {
1088 idi
= smCache
[x
].begin();
1090 paramOut(os
, csprintf("smCache%d", x
), smCache
[x
].size());
1091 while (idi
!= smCache
[x
].end()) {
1092 paramOut(os
, csprintf("smCache%d_%d.str", x
, y
), idi
->first
.first
);
1093 paramOut(os
, csprintf("smCache%d_%d.id", x
, y
), idi
->first
.second
);
1094 paramOut(os
, csprintf("smCache%d_%d.int", x
, y
), idi
->second
);
1099 // scLinks (ScCache) -- data not serialize
1102 // namecache (NameCache)
1103 NameCache::iterator ni
;
1105 ni
= nameCache
.begin();
1107 while (ni
!= nameCache
.end()) {
1108 paramOut(os
, csprintf("nameCache%d.name", x
), ni
->first
->name());
1109 paramOut(os
, csprintf("nameCache%d.str", x
), ni
->second
.first
);
1110 paramOut(os
, csprintf("nameCache%d.int", x
), ni
->second
.second
);
1114 // smStack (SmStack)
1115 SmStack::iterator si
;
1116 si
= smStack
.begin();
1118 paramOut(os
, "smStackIdCount", smStack
.size());
1119 while (si
!= smStack
.end()) {
1120 paramOut(os
, csprintf("smStackId%d.sys", x
), si
->first
.first
);
1121 paramOut(os
, csprintf("smStackId%d.frame", x
), si
->first
.second
);
1122 paramOut(os
, csprintf("smStackId%d.count", x
), si
->second
.size());
1123 for (y
= 0; y
< si
->second
.size(); y
++)
1124 paramOut(os
, csprintf("smStackId%d_%d", x
, y
), si
->second
[y
]);
1130 LinkMap::iterator li
;
1132 paramOut(os
, "lnMapSize", lnMap
.size());
1133 while (li
!= lnMap
.end()) {
1134 paramOut(os
, csprintf("lnMap%d.smi", x
), li
->first
);
1135 paramOut(os
, csprintf("lnMap%d.lsmi", x
), li
->second
);
1140 SwExpl::iterator swexpli
;
1141 swexpli
= swExpl
.begin();
1143 paramOut(os
, "swExplCount", swExpl
.size());
1144 while (swexpli
!= swExpl
.end()) {
1145 paramOut(os
, csprintf("swExpl%d.sys", x
), swexpli
->first
.first
);
1146 paramOut(os
, csprintf("swExpl%d.frame", x
), swexpli
->first
.second
);
1147 paramOut(os
, csprintf("swExpl%d.swexpl", x
), swexpli
->second
);
1154 ii
= lastState
.begin();
1155 paramOut(os
, "lastStateSize", lastState
.size());
1156 while (ii
!= lastState
.end()) {
1157 paramOut(os
, csprintf("lastState%d.smi", x
), ii
->first
);
1158 paramOut(os
, csprintf("lastState%d.sti", x
), ii
->second
);
1163 for (x
= 0; x
< smMap
.size(); x
++) {
1164 paramOut(os
, csprintf("smMap%d.sys", x
), smMap
[x
].first
);
1165 paramOut(os
, csprintf("smMap%d.smname", x
), smMap
[x
].second
.first
);
1166 paramOut(os
, csprintf("smMap%d.id", x
), smMap
[x
].second
.second
);
1170 for (x
= 0; x
< qMap
.size(); x
++) {
1171 paramOut(os
, csprintf("qMap%d.sys", x
), qMap
[x
].first
);
1172 paramOut(os
, csprintf("qMap%d.qname", x
), qMap
[x
].second
.first
);
1173 paramOut(os
, csprintf("qMap%d.id", x
), qMap
[x
].second
.second
);
1176 // qData (vector<AnnotateList>)
1177 for (x
= 0; x
< qData
.size(); x
++) {
1178 if (!qData
[x
].size())
1181 for (auto &ann
: qData
[x
]) {
1182 ann
->serializeSection(os
, csprintf("Q%d_%d", x
, y
));
1189 CPA::unserialize(CheckpointIn
&cp
)
1191 UNSERIALIZE_SCALAR(numSm
);
1192 UNSERIALIZE_SCALAR(numSmt
);
1193 UNSERIALIZE_CONTAINER(numSt
);
1194 UNSERIALIZE_CONTAINER(numQ
);
1195 UNSERIALIZE_SCALAR(numSys
);
1196 UNSERIALIZE_SCALAR(numQs
);
1197 UNSERIALIZE_SCALAR(conId
);
1198 UNSERIALIZE_CONTAINER(qSize
);
1199 UNSERIALIZE_CONTAINER(qBytes
);
1205 for (int x
= 0; x
< numSmt
; x
++) {
1206 paramIn(cp
, csprintf("smtCache%d.str", x
), str
);
1207 paramIn(cp
, csprintf("smtCache%d.int", x
), smi
);
1208 smtCache
[str
] = smi
;
1211 // stCache (StCache)
1212 stCache
.resize(numSmt
);
1213 for (int x
= 0; x
< numSmt
; x
++) {
1214 for (int y
= 0; y
< numSt
[x
]; y
++) {
1215 paramIn(cp
, csprintf("stCache%d_%d.str", x
,y
), str
);
1216 paramIn(cp
, csprintf("stCache%d_%d.int", x
,y
), smi
);
1217 stCache
[x
][str
] = smi
;
1223 qCache
.resize(numSys
);
1224 for (int x
= 0; x
< numSys
; x
++) {
1225 for (int y
= 0; y
< numQ
[x
]; y
++) {
1226 paramIn(cp
, csprintf("qCache%d_%d.str", x
,y
), str
);
1227 paramIn(cp
, csprintf("qCache%d_%d.id", x
,y
), id
);
1228 paramIn(cp
, csprintf("qCache%d_%d.int", x
,y
), smi
);
1229 qCache
[x
][Id(str
,id
)] = smi
;
1233 // smCache (IdCache)
1234 smCache
.resize(numSys
);
1235 for (int x
= 0; x
< numSys
; x
++) {
1237 paramIn(cp
, csprintf("smCache%d", x
), size
);
1238 for (int y
= 0; y
< size
; y
++) {
1239 paramIn(cp
, csprintf("smCache%d_%d.str", x
,y
), str
);
1240 paramIn(cp
, csprintf("smCache%d_%d.id", x
,y
), id
);
1241 paramIn(cp
, csprintf("smCache%d_%d.int", x
,y
), smi
);
1242 smCache
[x
][Id(str
,id
)] = smi
;
1246 // scLinks (ScCache) -- data not serialized, just creating one per sys
1247 for (int x
= 0; x
< numSys
; x
++)
1248 scLinks
.push_back(ScHCache());
1250 // nameCache (NameCache)
1251 for (int x
= 0; x
< numSys
; x
++) {
1257 objParamIn(cp
, csprintf("nameCache%d.name", x
), sptr
);
1258 sys
= dynamic_cast<System
*>(sptr
);
1260 paramIn(cp
, csprintf("nameCache%d.str", x
), str
);
1261 paramIn(cp
, csprintf("nameCache%d.int", x
), sysi
);
1262 nameCache
[sys
] = std::make_pair(str
, sysi
);
1267 paramIn(cp
, "smStackIdCount", smStack_size
);
1268 for (int x
= 0; x
< smStack_size
; x
++) {
1272 paramIn(cp
, csprintf("smStackId%d.sys", x
), sysi
);
1273 paramIn(cp
, csprintf("smStackId%d.frame", x
), frame
);
1274 paramIn(cp
, csprintf("smStackId%d.count", x
), count
);
1275 StackId sid
= StackId(sysi
, frame
);
1276 for (int y
= 0; y
< count
; y
++) {
1277 paramIn(cp
, csprintf("smStackId%d_%d", x
, y
), smi
);
1278 smStack
[sid
].push_back(smi
);
1285 paramIn(cp
, "lnMapSize", lnMap_size
);
1286 for (int x
= 0; x
< lnMap_size
; x
++) {
1287 paramIn(cp
, csprintf("lnMap%d.smi", x
), smi
);
1288 paramIn(cp
, csprintf("lnMap%d.lsmi", x
), lsmi
);
1294 paramIn(cp
, "swExplCount", swExpl_size
);
1295 for (int x
= 0; x
< swExpl_size
; x
++) {
1299 paramIn(cp
, csprintf("swExpl%d.sys", x
), sysi
);
1300 paramIn(cp
, csprintf("swExpl%d.frame", x
), frame
);
1301 paramIn(cp
, csprintf("swExpl%d.swexpl", x
), b
);
1302 StackId sid
= StackId(sysi
, frame
);
1309 paramIn(cp
, "lastStateSize", lastState_size
);
1310 for (int x
= 0; x
< lastState_size
; x
++) {
1311 paramIn(cp
, csprintf("lastState%d.smi", x
), smi
);
1312 paramIn(cp
, csprintf("lastState%d.sti", x
), sti
);
1313 lastState
[smi
] = sti
;
1318 smMap
.resize(numSm
);
1319 for (int x
= 0; x
< smMap
.size(); x
++) {
1320 paramIn(cp
, csprintf("smMap%d.sys", x
), smMap
[x
].first
);
1321 paramIn(cp
, csprintf("smMap%d.smname", x
), smMap
[x
].second
.first
);
1322 paramIn(cp
, csprintf("smMap%d.id", x
), smMap
[x
].second
.second
);
1327 for (int x
= 0; x
< qMap
.size(); x
++) {
1328 paramIn(cp
, csprintf("qMap%d.sys", x
), qMap
[x
].first
);
1329 paramIn(cp
, csprintf("qMap%d.qname", x
), qMap
[x
].second
.first
);
1330 paramIn(cp
, csprintf("qMap%d.id", x
), qMap
[x
].second
.second
);
1334 // qData (vector<AnnotateList>)
1335 qData
.resize(qSize
.size());
1336 for (int x
= 0; x
< qSize
.size(); x
++) {
1339 for (int y
= 0; y
< qSize
[x
]; y
++) {
1340 AnnDataPtr a
= std::make_shared
<AnnotateData
>();
1341 a
->unserializeSection(cp
, csprintf("Q%d_%d", x
, y
));
1343 qData
[x
].push_back(a
);
1349 CPA::AnnotateData::serialize(CheckpointOut
&cp
) const
1351 SERIALIZE_SCALAR(time
);
1352 SERIALIZE_SCALAR(data
);
1353 SERIALIZE_SCALAR(sm
);
1354 SERIALIZE_SCALAR(stq
);
1355 SERIALIZE_SCALAR(op
);
1356 SERIALIZE_SCALAR(flag
);
1357 SERIALIZE_SCALAR(cpu
);
1361 CPA::AnnotateData::unserialize(CheckpointIn
&cp
)
1363 UNSERIALIZE_SCALAR(time
);
1364 UNSERIALIZE_SCALAR(data
);
1366 UNSERIALIZE_SCALAR(sm
);
1367 UNSERIALIZE_SCALAR(stq
);
1368 UNSERIALIZE_SCALAR(op
);
1369 UNSERIALIZE_SCALAR(flag
);
1370 UNSERIALIZE_SCALAR(cpu
);
1377 return new CPA(this);