cp_annotate.cc revision 10905
1/*
2 * Copyright (c) 2006-2009 The Regents of The University of Michigan
3 * All rights reserved.
4 *
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.
15 *
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.
27 *
28 * Authors: Ali Saidi
29 */
30
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"
46
47struct CPAIgnoreSymbol
48{
49    const char *symbol;
50    size_t len;
51};
52#define CPA_IGNORE_SYMBOL(sym) { #sym, sizeof(#sym) }
53
54CPAIgnoreSymbol 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"),
74    {0,0}
75};
76#undef CPA_IGNORE_SYMBOL
77
78using namespace std;
79using namespace TheISA;
80
81bool CPA::exists;
82CPA *CPA::_cpa;
83
84class AnnotateDumpCallback : public Callback
85{
86
87  private:
88    CPA *cpa;
89  public:
90    virtual void process();
91    AnnotateDumpCallback(CPA *_cpa)
92        : cpa(_cpa)
93    {}
94};
95
96void
97AnnotateDumpCallback::process()
98{
99    cpa->dump(true);
100    cpa->dumpKey();
101}
102
103
104CPA::CPA(Params *p)
105    : SimObject(p), numSm(0), numSmt(0), numSys(0), numQs(0), conId(0)
106{
107    if (exists)
108        fatal("Multiple annotation objects found in system");
109    exists = true;
110
111    _enabled = p->enabled;
112    _cpa = this;
113
114    vector<string>::iterator i;
115    i = p->user_apps.begin();
116
117    while (i != p->user_apps.end()) {
118        ObjectFile *of = createObjectFile(*i);
119        string sf;
120        if (!of)
121            fatal("Couldn't load symbols from file: %s\n", *i);
122        sf = *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)
129            panic("blah");
130        assert(result1 && result2);
131        i++;
132    }
133}
134
135void
136CPA::startup()
137{
138    osbin = simout.create("annotate.bin", true);
139    // MAGIC version number 'M''5''A'N' + version/capabilities
140    ah.version = 0x4D35414E00000101ULL;
141    ah.num_recs = 0;
142    ah.key_off = 0;
143    osbin->write((char*)&ah, sizeof(AnnotateHeader));
144
145    registerExitCallback(new AnnotateDumpCallback(this));
146}
147
148uint64_t
149CPA::getFrame(ThreadContext *tc)
150{
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) &
154            ~ULL(0x3FFF));
155
156}
157
158void
159CPA::swSmBegin(ThreadContext *tc)
160{
161    if (!enabled())
162        return;
163
164    Arguments args(tc);
165    std::string st;
166    Addr junk;
167    char sm[50];
168    if (!TheISA::inUserMode(tc))
169        debugSymbolTable->findNearestSymbol(
170            tc->readIntReg(ReturnAddressReg), st, junk);
171
172    CopyStringOut(tc, sm, args[0], 50);
173    System *sys = tc->getSystemPtr();
174    StringWrap name(sys->name());
175
176    if (!sm[0])
177        warn("Got null SM at tick %d\n", curTick());
178
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,
182            smi, sysi, args[1]);
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);
186
187    uint64_t frame = getFrame(tc);
188    StackId sid = StackId(sysi, frame);
189
190    // check if we need to link to the previous state machine
191    int flags = args[2];
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]);
197
198            if (lnMap[smi])
199                DPRINTF(Annotate, "LnMap already contains entry for %d of %d\n",
200                        smi, lnMap[smi]);
201            assert(lnMap[smi] == 0);
202            lnMap[smi] =  prev_smi;
203
204            add(OP_LINK, FL_NONE, tc->contextId(), prev_smi, smi);
205        } else {
206            DPRINTF(Annotate, "Not Linking to state machine %s(%d) [%#x]\n",
207                    sm, smi, args[1]);
208        }
209    }
210
211
212    smStack[sid].push_back(smi);
213
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]);
217
218    // reset the sw state exculsion to false
219    if (swExpl[sid])
220        swExpl[sid] = false;
221
222
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);
227        an->stq = smi;
228        an->dump = true;
229        DPRINTF(Annotate,
230                "Found prev unknown linking from %d to state machine %s(%d)\n",
231                an->sm, sm, smi);
232
233        if (lnMap[smi])
234            DPRINTF(Annotate, "LnMap already contains entry for %d of %d\n",
235                    smi, lnMap[smi]);
236        assert(lnMap[smi] == 0);
237        lnMap[smi] =  an->sm;
238    }
239
240    // add a new begin ifwe have that info
241    if (st != "") {
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);
247    }
248}
249
250void
251CPA::swSmEnd(ThreadContext *tc)
252{
253    if (!enabled())
254        return;
255
256    Arguments args(tc);
257    char sm[50];
258    CopyStringOut(tc, sm, args[0], 50);
259    System *sys = tc->getSystemPtr();
260    doSwSmEnd(sys, tc->contextId(), sm, getFrame(tc));
261}
262
263void
264CPA::doSwSmEnd(System *sys, int cpuid, string sm, uint64_t frame)
265{
266    int sysi = getSys(sys);
267    StackId sid = StackId(sysi, frame);
268
269
270    // reset the sw state exculsion to false
271    if (swExpl[sid])
272        swExpl[sid] = false;
273
274
275    int smib = smStack[sid].back();
276    StringWrap name(sys->name());
277    DPRINTF(Annotate, "Ending machine: %s[%d, %#x] (%d?)\n", sm, sysi,
278            frame, smib);
279
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);
288
289        warn("State machine stack not unwinding correctly at %d\n", curTick());
290    } else {
291        DPRINTF(Annotate,
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());
297
298        int smi = smStack[sid].back();
299        smStack[sid].pop_back();
300
301        if (lnMap[smi]) {
302            DPRINTF(Annotate, "Linking %d back to %d\n", smi, lnMap[smi]);
303            add(OP_LINK, FL_NONE, cpuid, smi, lnMap[smi]);
304            lnMap.erase(smi);
305        }
306
307        if (smStack[sid].size()) {
308            add(OP_BEGIN, FL_NONE, cpuid, smi, lastState[smi]);
309        }
310
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]);
314    }
315}
316
317
318void
319CPA::swExplictBegin(ThreadContext *tc)
320{
321    if (!enabled())
322        return;
323
324    Arguments args(tc);
325    char st[50];
326    CopyStringOut(tc, st, args[1], 50);
327
328    StringWrap name(tc->getSystemPtr()->name());
329    DPRINTF(Annotate, "Explict begin of state %s\n", st);
330    uint32_t flags = args[0];
331    if (flags & FL_BAD)
332        warn("BAD state encountered: at cycle %d: %s\n", curTick(), st);
333    swBegin(tc->getSystemPtr(), tc->contextId(), st, getFrame(tc), true, args[0]);
334}
335
336void
337CPA::swAutoBegin(ThreadContext *tc, Addr next_pc)
338{
339    if (!enabled())
340        return;
341
342    string sym;
343    Addr sym_addr = 0;
344
345    if (!TheISA::inUserMode(tc)) {
346        debugSymbolTable->findNearestSymbol(next_pc, sym, sym_addr);
347    } else {
348        Linux::ThreadInfo ti(tc);
349        string app = ti.curTaskName();
350        if (userApp.count(app))
351            userApp[app]->findNearestSymbol(next_pc, sym, sym_addr);
352    }
353
354    if (sym_addr)
355        swBegin(tc->getSystemPtr(), tc->contextId(), sym, getFrame(tc));
356}
357
358void
359CPA::swBegin(System *sys, int cpuid, std::string st, uint64_t frame, bool expl,
360        int flags)
361{
362    int x = 0;
363    int len;
364    while (ignoreSymbols[x].len)
365    {
366        len = ignoreSymbols[x].len;
367        if (!st.compare(0,len, ignoreSymbols[x].symbol, len))
368            return;
369        x++;
370    }
371
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())
376        return;
377    if (!expl && swExpl[sid])
378        return;
379    if (expl)
380        swExpl[sid] = true;
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);
387    }
388}
389
390void
391CPA::swEnd(ThreadContext *tc)
392{
393    if (!enabled())
394        return;
395
396    std::string st;
397    Addr junk;
398    if (!TheISA::inUserMode(tc))
399        debugSymbolTable->findNearestSymbol(
400            tc->readIntReg(ReturnAddressReg), st, junk);
401    System *sys = tc->getSystemPtr();
402    StringWrap name(sys->name());
403
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);
408        return;
409    }
410    DPRINTF(Annotate, "Explict end of State: %s\n",  st);
411    // return back to symbol table based states
412    swExpl[sid] = false;
413    int smi = smStack[sid].back();
414    if (st != "") {
415        int sti = getSt(smMap[smi-1].second.first, st);
416        lastState[smi] = sti;
417        add(OP_BEGIN, FL_NONE, tc->contextId(), smi, sti);
418    }
419}
420
421void
422CPA::swQ(ThreadContext *tc)
423{
424    if (!enabled())
425        return;
426
427    char q[50];
428    Arguments args(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();
433
434    int sysi = getSys(sys);
435    StackId sid = StackId(sysi, getFrame(tc));
436    if (!smStack[sid].size())
437        return;
438    int smi = smStack[sid].back();
439    if (swExpl[sid])
440        swExpl[sid] = false;
441    int qi = getQ(sysi, q, id);
442    if (count == 0) {
443        //warn("Tried to queue 0 bytes in %s, ignoring\n", q);
444        return;
445    }
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);
450}
451
452void
453CPA::swDq(ThreadContext *tc)
454{
455    if (!enabled())
456        return;
457
458    char q[50];
459    Arguments args(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();
464
465    int sysi = getSys(sys);
466    StackId sid = StackId(sysi, getFrame(tc));
467    if (!smStack[sid].size())
468        return;
469    int smi = smStack[sid].back();
470    int qi = getQ(sysi, q, id);
471    if (swExpl[sid])
472        swExpl[sid] = false;
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);
476    assert(count != 0);
477
478    doDq(sys, FL_NONE, tc->contextId(), smi, q, qi, count);
479}
480
481void
482CPA::swPq(ThreadContext *tc)
483{
484    if (!enabled())
485        return;
486
487    char q[50];
488    Arguments args(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];
493
494    int sysi = getSys(sys);
495    StackId sid = StackId(sysi, getFrame(tc));
496    if (!smStack[sid].size())
497        return;
498    int smi = smStack[sid].back();
499    int qi = getQ(sysi, q, id);
500    if (swExpl[sid])
501        swExpl[sid] = false;
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);
505
506    assert(count != 0);
507    if (qBytes[qi-1] < count) {
508        dump(true);
509        dumpKey();
510        fatal("Queue %s peeking with not enough bytes available in queue!\n", q);
511    }
512
513    add(OP_PEEK, FL_NONE, tc->contextId(), smi, qi, count);
514}
515
516void
517CPA::swRq(ThreadContext *tc)
518{
519    if (!enabled())
520        return;
521
522    char q[50];
523    Arguments args(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];
528
529    int sysi = getSys(sys);
530    StackId sid = StackId(sysi, getFrame(tc));
531    if (!smStack[sid].size())
532        return;
533    int smi = smStack[sid].back();
534    int qi = getQ(sysi, q, id);
535    if (swExpl[sid])
536        swExpl[sid] = false;
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);
540
541    assert(count != 0);
542
543    add(OP_RESERVE, FL_NONE, tc->contextId(), smi, qi, count);
544}
545
546
547void
548CPA::swWf(ThreadContext *tc)
549{
550    if (!enabled())
551        return;
552
553    char q[50];
554    Arguments args(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];
559
560    int sysi = getSys(sys);
561    StackId sid = StackId(sysi, getFrame(tc));
562    if (!smStack[sid].size())
563        return;
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);
567
568    if (!!args[2]) {
569        char sm[50];
570        CopyStringOut(tc, sm, args[2], 50);
571        doSwSmEnd(tc->getSystemPtr(), tc->contextId(), sm, getFrame(tc));
572    }
573}
574
575void
576CPA::swWe(ThreadContext *tc)
577{
578    if (!enabled())
579        return;
580
581    char q[50];
582    Arguments args(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];
587
588    int sysi = getSys(sys);
589    StackId sid = StackId(sysi, getFrame(tc));
590    if (!smStack[sid].size())
591        return;
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);
595
596    if (!!args[2]) {
597        char sm[50];
598        CopyStringOut(tc, sm, args[2], 50);
599        doSwSmEnd(tc->getSystemPtr(), tc->contextId(), sm, getFrame(tc));
600    }
601}
602
603void
604CPA::swSq(ThreadContext *tc)
605{
606    if (!enabled())
607        return;
608
609    char q[50];
610    Arguments args(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];
616    int flags = args[3];
617
618    int sysi = getSys(sys);
619    StackId sid = StackId(sysi, getFrame(tc));
620    if (!smStack[sid].size())
621        return;
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);
626
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);
630        qData[qi-1].clear();
631        qSize[qi-1] = 0;
632        qBytes[qi-1] = 0;
633    }
634
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);
640        if (size <= 0) {
641            qData[qi-1].clear();
642            qSize[qi-1] = 0;
643            qBytes[qi-1] = 0;
644            return;
645        }
646        int need = qBytes[qi-1] - size;
647        qBytes[qi-1] = size;
648        while (need > 0) {
649            int32_t tail_bytes = qData[qi-1].back()->data;
650            if (qSize[qi-1] <= 0 || qBytes[qi-1] < 0) {
651                dump(true);
652                dumpKey();
653                fatal("Queue %s had inconsistancy when doing size queue!\n", q);
654            }
655            if (tail_bytes > need) {
656                qData[qi-1].back()->data -= need;
657                need = 0;
658            } else if (tail_bytes == need) {
659                qData[qi-1].pop_back();
660                qSize[qi-1]--;
661                need = 0;
662            } else {
663                qData[qi-1].pop_back();
664                qSize[qi-1]--;
665                need -= tail_bytes;
666            }
667        }
668    }
669}
670
671void
672CPA::swAq(ThreadContext *tc)
673{
674    if (!enabled())
675        return;
676
677    char q[50];
678    Arguments args(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];
684
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);
689        //dump(true);
690        //dumpKey();
691        std::list<AnnDataPtr>::iterator ai = qData[qi-1].begin();
692        int x = 0;
693        while (ai != qData[qi-1].end()) {
694            DPRINTF(AnnotateQ, "--Element %d size %d\n", x, (*ai)->data);
695            ai++;
696            x++;
697        }
698
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]);
705    }
706}
707
708void
709CPA::swLink(ThreadContext *tc)
710{
711    if (!enabled())
712        return;
713
714    char lsm[50];
715    Arguments args(tc);
716    CopyStringOut(tc, lsm, args[0], 50);
717    System *sys = tc->getSystemPtr();
718    StringWrap name(sys->name());
719
720    int sysi = getSys(sys);
721    StackId sid = StackId(sysi, getFrame(tc));
722    if (!smStack[sid].size())
723        return;
724    int smi = smStack[sid].back();
725    int lsmi = getSm(sysi, lsm, args[1]);
726
727    DPRINTF(Annotate, "Linking from %d to state machine %s(%d) [%#x]\n",
728            smi, lsm, lsmi, args[1]);
729
730    if (lnMap[lsmi])
731        DPRINTF(Annotate, "LnMap already contains entry for %d of %d\n",
732                lsmi, lnMap[lsmi]);
733    assert(lnMap[lsmi] == 0);
734    lnMap[lsmi] =  smi;
735
736    add(OP_LINK, FL_NONE, tc->contextId(), smi, lsmi);
737
738    if (!!args[2]) {
739        char sm[50];
740        CopyStringOut(tc, sm, args[2], 50);
741        doSwSmEnd(tc->getSystemPtr(), tc->contextId(), sm, getFrame(tc));
742    }
743}
744
745void
746CPA::swIdentify(ThreadContext *tc)
747{
748    if (!enabled())
749        return;
750
751    Arguments args(tc);
752    int sysi = getSys(tc->getSystemPtr());
753    StackId sid = StackId(sysi, getFrame(tc));
754    if (!smStack[sid].size())
755        return;
756    int smi = smStack[sid].back();
757
758    DPRINTFS(Annotate, tc->getSystemPtr(), "swIdentify: id %#X\n", args[0]);
759
760    add(OP_IDENT, FL_NONE, tc->contextId(), smi, 0, args[0]);
761}
762
763uint64_t
764CPA::swGetId(ThreadContext *tc)
765{
766    if (!enabled())
767        return 0;
768
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();
775
776    DPRINTFS(Annotate, tc->getSystemPtr(), "swGetId: id %#X\n", id);
777
778    add(OP_IDENT, FL_NONE, tc->contextId(), smi, 0, id);
779    return id;
780}
781
782
783void
784CPA::swSyscallLink(ThreadContext  *tc)
785{
786    if (!enabled())
787        return;
788
789    char lsm[50];
790    Arguments args(tc);
791    CopyStringOut(tc, lsm, args[0], 50);
792    System *sys = tc->getSystemPtr();
793    StringWrap name(sys->name());
794    int sysi = getSys(sys);
795
796    Id id = Id(lsm, getFrame(tc));
797    StackId sid = StackId(sysi, getFrame(tc));
798
799    if (!smStack[sid].size())
800        return;
801
802    int smi = smStack[sid].back();
803
804    DPRINTF(Annotate, "Linking from %d to state machine %s(UNKNOWN)\n",
805            smi, lsm);
806
807    if (scLinks[sysi-1][id])
808        DPRINTF(Annotate,
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;
814
815    if (!!args[1]) {
816        char sm[50];
817        CopyStringOut(tc, sm, args[1], 50);
818        doSwSmEnd(tc->getSystemPtr(), tc->contextId(), sm, getFrame(tc));
819    }
820}
821
822CPA::AnnDataPtr
823CPA::add(int t, int f, int c, int sm, int stq, int32_t d)
824{
825    AnnDataPtr an = std::make_shared<AnnotateData>();
826    an->time = curTick();
827    an->data = d;
828    an->orig_data = d;
829    an->op = t;
830    an->flag = f;
831    an->sm = sm;
832    an->stq = stq;
833    an->cpu = c;
834    an->dump = true;
835
836    data.push_back(an);
837
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);
840
841    // Don't dump Links because we might be setting no-dump on it
842    if (an->op != OP_LINK)
843        dump(false);
844
845    return an;
846}
847
848void
849CPA::dumpKey()
850{
851    std::streampos curpos = osbin->tellp();
852    ah.key_off = curpos;
853
854    // Output the various state machines and their corresponding states
855    *osbin << "# Automatically generated state machine descriptor file" << endl;
856
857    *osbin << "sms = {}" << endl << endl;
858    vector<string> state_machines;
859    state_machines.resize(numSmt+1);
860
861    // State machines, id -> states
862    SCache::iterator i = smtCache.begin();
863    while (i != smtCache.end()) {
864        state_machines[i->second] = i->first;
865        i++;
866    }
867
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;
875            i++;
876        }
877        *osbin << "sms[\"" << state_machines[x] << "\"] = [\"NULL\"";
878        for (int y = 1; y < states.size(); y++)
879            *osbin << ", \"" << states[y] << "\"";
880        *osbin << "]" << endl;
881    }
882
883    *osbin << endl << endl << endl;
884
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;
891
892    *osbin << endl << endl << endl;
893
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;
900        i2++;
901    }
902
903    *osbin << "sysNum = [\"NULL\"";
904    for (int x = 1; x < systems.size(); x++) {
905        *osbin << ", \"" << systems[x] << "\"";
906    }
907    *osbin << "]" << endl;
908
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;
915
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;
919
920    // output index
921    curpos = osbin->tellp();
922    ah.idx_off = curpos;
923
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;
927
928    osbin->seekp(0);
929    osbin->write((char*)&ah, sizeof(AnnotateHeader));
930    osbin->flush();
931
932}
933
934void
935CPA::dump(bool all)
936{
937
938    list<AnnDataPtr>::iterator i;
939
940    i = data.begin();
941
942    if (i == data.end())
943        return;
944
945    // Dump the data every
946    if (!all && data.size() < 10000)
947        return;
948
949    DPRINTF(Annotate, "Writing %d\n", data.size());
950    while (i != data.end()) {
951        AnnDataPtr an = *i;
952
953        // If we can't dump this record, hold here
954        if (!an->dump && !all)
955            break;
956
957        ah.num_recs++;
958        if (ah.num_recs % 100000 == 0)
959            annotateIdx.push_back(osbin->tellp());
960
961
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));
969        i++;
970    }
971    if (data.begin() != i)
972        data.erase(data.begin(), i);
973
974    if (all)
975        osbin->flush();
976}
977
978void
979CPA::doQ(System *sys, int flags, int cpuid, int sm,
980              string q, int qi, int count)
981{
982    qSize[qi-1]++;
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]);
988    if (flags & FL_QOPP)
989        qData[qi-1].push_front(add(OP_QUEUE, flags, cpuid, sm, qi, count));
990    else
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);
996}
997
998
999void
1000CPA::doDq(System *sys, int flags, int cpuid, int sm,
1001               string q, int qi, int count)
1002{
1003
1004    StringWrap name(sys->name());
1005    if (count == -1) {
1006        add(OP_DEQUEUE, flags, cpuid, sm, qi, count);
1007        qData[qi-1].clear();
1008        qSize[qi-1] = 0;
1009        qBytes[qi-1] = 0;
1010        DPRINTF(AnnotateQ, "Dequeing all data in queue %s size now %d/%d\n",
1011                q, qSize[qi-1], qBytes[qi-1]);
1012        return;
1013    }
1014
1015    assert(count > 0);
1016    if (qSize[qi-1] <= 0 || qBytes[qi-1] <= 0 || !qData[qi-1].size()) {
1017        dump(true);
1018        dumpKey();
1019        fatal("Queue %s dequing with no data available in queue!\n",
1020                q);
1021    }
1022    assert(qSize[qi-1] >= 0);
1023    assert(qBytes[qi-1] >= 0);
1024    assert(qData[qi-1].size());
1025
1026    int32_t need = count;
1027    qBytes[qi-1] -= count;
1028    if (qBytes[qi-1] < 0) {
1029        dump(true);
1030        dumpKey();
1031        fatal("Queue %s dequing with no bytes available in queue!\n",
1032                q);
1033    }
1034
1035    while (need > 0) {
1036        int32_t head_bytes = qData[qi-1].front()->data;
1037        if (qSize[qi-1] <= 0 || qBytes[qi-1] < 0) {
1038            dump(true);
1039            dumpKey();
1040            fatal("Queue %s dequing with nothing in queue!\n",
1041                q);
1042        }
1043
1044        if (head_bytes > need) {
1045            qData[qi-1].front()->data -= need;
1046            need = 0;
1047        } else if (head_bytes == need) {
1048            qData[qi-1].pop_front();
1049            qSize[qi-1]--;
1050            need = 0;
1051        } else {
1052            qData[qi-1].pop_front();
1053            qSize[qi-1]--;
1054            need -= head_bytes;
1055        }
1056    }
1057
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]);
1061}
1062
1063
1064
1065void
1066CPA::serialize(CheckpointOut &cp) const
1067{
1068
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);
1079
1080    SCache::iterator i;
1081    int x = 0, y = 0;
1082
1083    // smtCache (SCache)
1084    x = 0;
1085    y = 0;
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);
1090        x++; i++;
1091    }
1092
1093    // stCache  (StCache)
1094    for (x = 0; x < stCache.size(); x++) {
1095        i = stCache[x].begin();
1096        y = 0;
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);
1100            y++; i++;
1101        }
1102    }
1103
1104    // qCache (IdCache)
1105    IdHCache::iterator idi;
1106    for (x = 0; x < qCache.size(); x++) {
1107        idi = qCache[x].begin();
1108        y = 0;
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);
1113            y++; idi++;
1114        }
1115    }
1116
1117    // smCache (IdCache)
1118    for (x = 0; x < smCache.size(); x++) {
1119        idi = smCache[x].begin();
1120        y = 0;
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);
1126            y++; idi++;
1127        }
1128    }
1129
1130    // scLinks (ScCache) -- data not serialize
1131
1132
1133    // namecache (NameCache)
1134    NameCache::iterator ni;
1135
1136    ni = nameCache.begin();
1137    x = 0;
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);
1142        x++; ni++;
1143    }
1144
1145    // smStack (SmStack)
1146    SmStack::iterator si;
1147    si = smStack.begin();
1148    x = 0;
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]);
1156        x++; si++;
1157    }
1158
1159    // lnMap (LinkMap)
1160    x = 0;
1161    LinkMap::iterator li;
1162    li = lnMap.begin();
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);
1167        x++; li++;
1168    }
1169
1170    // swExpl (vector)
1171    SwExpl::iterator swexpli;
1172    swexpli = swExpl.begin();
1173    x = 0;
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);
1179        x++; swexpli++;
1180    }
1181
1182    // lastState (IMap)
1183    x = 0;
1184    IMap::iterator ii;
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);
1190        x++; ii++;
1191    }
1192
1193    // smMap (IdMap)
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);
1198    }
1199
1200    // qMap (IdMap)
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);
1205    }
1206
1207    // qData (vector<AnnotateList>)
1208    for(x = 0; x < qData.size(); x++) {
1209        if (!qData[x].size())
1210            continue;
1211        y = 0;
1212        for (auto &ann : qData[x]) {
1213            ann->serializeSection(os, csprintf("Q%d_%d", x, y));
1214            y++;
1215        }
1216    }
1217}
1218
1219void
1220CPA::unserialize(CheckpointIn &cp)
1221{
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);
1231
1232
1233    // smtCache (SCache
1234    string str;
1235    int smi;
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;
1240    }
1241
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;
1249        }
1250    }
1251
1252    // qCache (IdCache)
1253    uint64_t id;
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;
1261        }
1262    }
1263
1264    // smCache (IdCache)
1265    smCache.resize(numSys);
1266    for (int x = 0;  x < numSys; x++) {
1267        int size;
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;
1274        }
1275    }
1276
1277    // scLinks (ScCache) -- data not serialized, just creating one per sys
1278    for (int x = 0; x < numSys; x++)
1279        scLinks.push_back(ScHCache());
1280
1281    // nameCache (NameCache)
1282    for (int x = 0; x < numSys; x++) {
1283        System *sys;
1284        SimObject *sptr;
1285        string str;
1286        int sysi;
1287
1288        objParamIn(cp, csprintf("nameCache%d.name", x), sptr);
1289        sys = dynamic_cast<System*>(sptr);
1290
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);
1294    }
1295
1296    //smStack (SmStack)
1297    int smStack_size;
1298    paramIn(cp, "smStackIdCount", smStack_size);
1299    for (int x = 0; x < smStack_size; x++) {
1300        int sysi;
1301        uint64_t frame;
1302        int count;
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);
1310        }
1311    }
1312
1313    // lnMap (LinkMap)
1314    int lsmi;
1315    int lnMap_size;
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);
1320        lnMap[smi] = lsmi;
1321    }
1322
1323    // swExpl (vector)
1324    int swExpl_size;
1325    paramIn(cp, "swExplCount", swExpl_size);
1326    for (int x = 0; x < swExpl_size; x++) {
1327        int sysi;
1328        uint64_t frame;
1329        bool b;
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);
1334        swExpl[sid] = b;
1335    }
1336
1337    // lastState (IMap)
1338    int sti;
1339    int lastState_size;
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;
1345    }
1346
1347
1348    //smMap (IdMap)
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);
1354    }
1355
1356    //qMap (IdMap)
1357    qMap.resize(numQs);
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);
1362    }
1363
1364
1365    // qData (vector<AnnotateList>)
1366    qData.resize(qSize.size());
1367    for (int x = 0; x < qSize.size(); x++) {
1368        if (!qSize[x])
1369            continue;
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));
1373            data.push_back(a);
1374            qData[x].push_back(a);
1375        }
1376    }
1377}
1378
1379void
1380CPA::AnnotateData::serialize(CheckpointOut &cp) const
1381{
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);
1389}
1390
1391void
1392CPA::AnnotateData::unserialize(CheckpointIn &cp)
1393{
1394    UNSERIALIZE_SCALAR(time);
1395    UNSERIALIZE_SCALAR(data);
1396    orig_data = data;
1397    UNSERIALIZE_SCALAR(sm);
1398    UNSERIALIZE_SCALAR(stq);
1399    UNSERIALIZE_SCALAR(op);
1400    UNSERIALIZE_SCALAR(flag);
1401    UNSERIALIZE_SCALAR(cpu);
1402    dump = true;
1403}
1404
1405CPA*
1406CPAParams::create()
1407{
1408    return new CPA(this);
1409}
1410
1411