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 "base/cp_annotate.hh"
32
33#include "arch/generic/linux/threadinfo.hh"
34#include "arch/utility.hh"
35#include "base/callback.hh"
36#include "base/loader/object_file.hh"
37#include "base/output.hh"
38#include "base/trace.hh"
39#include "config/the_isa.hh"
40#include "cpu/thread_context.hh"
41#include "debug/Annotate.hh"
42#include "debug/AnnotateVerbose.hh"
43#include "sim/arguments.hh"
44#include "sim/core.hh"
45#include "sim/sim_exit.hh"
46#include "sim/system.hh"
47
48struct CPAIgnoreSymbol
49{
50    const char *symbol;
51    size_t len;
52};
53#define CPA_IGNORE_SYMBOL(sym) { #sym, sizeof(#sym) }
54
55CPAIgnoreSymbol ignoreSymbols[] = {
56    CPA_IGNORE_SYMBOL("m5a_"),
57    CPA_IGNORE_SYMBOL("ret_from_sys_call"),
58    CPA_IGNORE_SYMBOL("ret_from_reschedule"),
59    CPA_IGNORE_SYMBOL("_spin_"),
60    CPA_IGNORE_SYMBOL("local_bh_"),
61    CPA_IGNORE_SYMBOL("restore_all"),
62    CPA_IGNORE_SYMBOL("Call_Pal_"),
63    CPA_IGNORE_SYMBOL("pal_post_interrupt"),
64    CPA_IGNORE_SYMBOL("rti_to_"),
65    CPA_IGNORE_SYMBOL("sys_int_2"),
66    CPA_IGNORE_SYMBOL("sys_interrupt"),
67    CPA_IGNORE_SYMBOL("normal_int"),
68    CPA_IGNORE_SYMBOL("TRAP_INTERRUPT_10_"),
69    CPA_IGNORE_SYMBOL("Trap_Interrupt"),
70    CPA_IGNORE_SYMBOL("do_entInt"),
71    CPA_IGNORE_SYMBOL("__do_softirq"),
72    CPA_IGNORE_SYMBOL("_end"),
73    CPA_IGNORE_SYMBOL("entInt"),
74    CPA_IGNORE_SYMBOL("entSys"),
75    {0,0}
76};
77#undef CPA_IGNORE_SYMBOL
78
79using namespace std;
80using namespace TheISA;
81
82bool CPA::exists;
83CPA *CPA::_cpa;
84
85class AnnotateDumpCallback : public Callback
86{
87
88  private:
89    CPA *cpa;
90  public:
91    virtual void process();
92    AnnotateDumpCallback(CPA *_cpa)
93        : cpa(_cpa)
94    {}
95};
96
97void
98AnnotateDumpCallback::process()
99{
100    cpa->dump(true);
101    cpa->dumpKey();
102}
103
104
105CPA::CPA(Params *p)
106    : SimObject(p), numSm(0), numSmt(0), numSys(0), numQs(0), conId(0)
107{
108    if (exists)
109        fatal("Multiple annotation objects found in system");
110    exists = true;
111
112    _enabled = p->enabled;
113    _cpa = this;
114
115    vector<string>::iterator i;
116    i = p->user_apps.begin();
117
118    while (i != p->user_apps.end()) {
119        ObjectFile *of = createObjectFile(*i);
120        string sf;
121        if (!of)
122            fatal("Couldn't load symbols from file: %s\n", *i);
123        sf = *i;
124        sf.erase(0, sf.rfind('/') + 1);;
125        DPRINTFN("file %s short: %s\n", *i, sf);
126        userApp[sf] = new SymbolTable;
127        bool result1 = of->loadGlobalSymbols(userApp[sf]);
128        bool result2 = of->loadLocalSymbols(userApp[sf]);
129        if (!result1 || !result2)
130            panic("blah");
131        assert(result1 && result2);
132        i++;
133    }
134}
135
136void
137CPA::startup()
138{
139    osbin = simout.create("annotate.bin", true);
140    // MAGIC version number 'M''5''A'N' + version/capabilities
141    ah.version = 0x4D35414E00000101ULL;
142    ah.num_recs = 0;
143    ah.key_off = 0;
144    osbin->write((char*)&ah, sizeof(AnnotateHeader));
145
146    registerExitCallback(new AnnotateDumpCallback(this));
147}
148
149uint64_t
150CPA::getFrame(ThreadContext *tc)
151{
152    // This code is ISA specific and will need to be changed
153    // if the annotation code is used for something other than Alpha
154    return (tc->readMiscRegNoEffect(TheISA::IPR_PALtemp23) &
155            ~ULL(0x3FFF));
156
157}
158
159void
160CPA::swSmBegin(ThreadContext *tc)
161{
162    if (!enabled())
163        return;
164
165    Arguments args(tc);
166    std::string st;
167    Addr junk;
168    char sm[50];
169    if (!TheISA::inUserMode(tc))
170        debugSymbolTable->findNearestSymbol(
171            tc->readIntReg(ReturnAddressReg), st, junk);
172
173    tc->getVirtProxy().readString(sm, args[0], 50);
174    System *sys = tc->getSystemPtr();
175    StringWrap name(sys->name());
176
177    if (!sm[0])
178        warn("Got null SM at tick %d\n", curTick());
179
180    int sysi = getSys(sys);
181    int smi = getSm(sysi, sm, args[1]);
182    DPRINTF(Annotate,  "Starting machine: %s(%d) sysi: %d id: %#x\n", sm,
183            smi, sysi, args[1]);
184    DPRINTF(Annotate, "smMap[%d] = %d, %s, %#x\n", smi,
185            smMap[smi-1].first, smMap[smi-1].second.first,
186            smMap[smi-1].second.second);
187
188    uint64_t frame = getFrame(tc);
189    StackId sid = StackId(sysi, frame);
190
191    // check if we need to link to the previous state machine
192    int flags = args[2];
193    if (flags & FL_LINK) {
194        if (smStack[sid].size()) {
195            int prev_smi = smStack[sid].back();
196            DPRINTF(Annotate, "Linking from %d to state machine %s(%d) [%#x]\n",
197                    prev_smi, sm, smi, args[1]);
198
199            if (lnMap[smi])
200                DPRINTF(Annotate, "LnMap already contains entry for %d of %d\n",
201                        smi, lnMap[smi]);
202            assert(lnMap[smi] == 0);
203            lnMap[smi] =  prev_smi;
204
205            add(OP_LINK, FL_NONE, tc->contextId(), prev_smi, smi);
206        } else {
207            DPRINTF(Annotate, "Not Linking to state machine %s(%d) [%#x]\n",
208                    sm, smi, args[1]);
209        }
210    }
211
212
213    smStack[sid].push_back(smi);
214
215    DPRINTF(Annotate, "Stack Now (%#X):\n", frame);
216    for (int x = smStack[sid].size()-1; x >= 0; x--)
217        DPRINTF(Annotate, "-- %d\n", smStack[sid][x]);
218
219    // reset the sw state exculsion to false
220    if (swExpl[sid])
221        swExpl[sid] = false;
222
223
224    Id id = Id(sm, frame);
225    if (scLinks[sysi-1][id]) {
226        AnnDataPtr an = scLinks[sysi-1][id];
227        scLinks[sysi-1].erase(id);
228        an->stq = smi;
229        an->dump = true;
230        DPRINTF(Annotate,
231                "Found prev unknown linking from %d to state machine %s(%d)\n",
232                an->sm, sm, smi);
233
234        if (lnMap[smi])
235            DPRINTF(Annotate, "LnMap already contains entry for %d of %d\n",
236                    smi, lnMap[smi]);
237        assert(lnMap[smi] == 0);
238        lnMap[smi] =  an->sm;
239    }
240
241    // add a new begin ifwe have that info
242    if (st != "") {
243        DPRINTF(Annotate, "st: %s smi: %d stCache.size %d\n", st,
244                smi, stCache.size());
245        int sti = getSt(sm, st);
246        lastState[smi] = sti;
247        add(OP_BEGIN, FL_NONE, tc->contextId(), smi, sti);
248    }
249}
250
251void
252CPA::swSmEnd(ThreadContext *tc)
253{
254    if (!enabled())
255        return;
256
257    Arguments args(tc);
258    char sm[50];
259    tc->getVirtProxy().readString(sm, args[0], 50);
260    System *sys = tc->getSystemPtr();
261    doSwSmEnd(sys, tc->contextId(), sm, getFrame(tc));
262}
263
264void
265CPA::doSwSmEnd(System *sys, int cpuid, string sm, uint64_t frame)
266{
267    int sysi = getSys(sys);
268    StackId sid = StackId(sysi, frame);
269
270
271    // reset the sw state exculsion to false
272    if (swExpl[sid])
273        swExpl[sid] = false;
274
275
276    int smib = smStack[sid].back();
277    StringWrap name(sys->name());
278    DPRINTF(Annotate, "Ending machine: %s[%d, %#x] (%d?)\n", sm, sysi,
279            frame, smib);
280
281    if (!smStack[sid].size() || smMap[smib-1].second.first != sm) {
282        DPRINTF(Annotate, "State Machine not unwinding correctly. sid: %d, %#x"
283                " top of stack: %s Current Stack:\n",
284                sysi, frame, smMap[smib-1].second.first);
285        for (int x = smStack[sid].size()-1; x >= 0; x--)
286            DPRINTF(Annotate, "-- %d\n", smStack[sid][x]);
287        DPRINTF(Annotate, "Ending machine: %s; end stack: %s\n", sm,
288                smMap[smib-1].second.first);
289
290        warn("State machine stack not unwinding correctly at %d\n", curTick());
291    } else {
292        DPRINTF(Annotate,
293                "State machine ending:%s sysi:%d id:%#x back:%d getSm:%d\n",
294                sm, sysi, smMap[smib-1].second.second, smStack[sid].back(),
295                getSm(sysi, sm, smMap[smib-1].second.second));
296        assert(getSm(sysi, sm, smMap[smib-1].second.second) ==
297                smStack[sid].back());
298
299        int smi = smStack[sid].back();
300        smStack[sid].pop_back();
301
302        if (lnMap[smi]) {
303            DPRINTF(Annotate, "Linking %d back to %d\n", smi, lnMap[smi]);
304            add(OP_LINK, FL_NONE, cpuid, smi, lnMap[smi]);
305            lnMap.erase(smi);
306        }
307
308        if (smStack[sid].size()) {
309            add(OP_BEGIN, FL_NONE, cpuid, smi, lastState[smi]);
310        }
311
312        DPRINTF(Annotate, "Stack Now:\n");
313        for (int x = smStack[sid].size()-1; x >= 0; x--)
314            DPRINTF(Annotate, "-- %d\n", smStack[sid][x]);
315    }
316}
317
318
319void
320CPA::swExplictBegin(ThreadContext *tc)
321{
322    if (!enabled())
323        return;
324
325    Arguments args(tc);
326    char st[50];
327    tc->getVirtProxy().readString(st, args[1], 50);
328
329    StringWrap name(tc->getSystemPtr()->name());
330    DPRINTF(Annotate, "Explict begin of state %s\n", st);
331    uint32_t flags = args[0];
332    if (flags & FL_BAD)
333        warn("BAD state encountered: at cycle %d: %s\n", curTick(), st);
334    swBegin(tc->getSystemPtr(), tc->contextId(), st, getFrame(tc), true, args[0]);
335}
336
337void
338CPA::swAutoBegin(ThreadContext *tc, Addr next_pc)
339{
340    if (!enabled())
341        return;
342
343    string sym;
344    Addr sym_addr = 0;
345
346    if (!TheISA::inUserMode(tc)) {
347        debugSymbolTable->findNearestSymbol(next_pc, sym, sym_addr);
348    } else {
349        Linux::ThreadInfo ti(tc);
350        string app = ti.curTaskName();
351        if (userApp.count(app))
352            userApp[app]->findNearestSymbol(next_pc, sym, sym_addr);
353    }
354
355    if (sym_addr)
356        swBegin(tc->getSystemPtr(), tc->contextId(), sym, getFrame(tc));
357}
358
359void
360CPA::swBegin(System *sys, int cpuid, std::string st, uint64_t frame, bool expl,
361        int flags)
362{
363    int x = 0;
364    int len;
365    while (ignoreSymbols[x].len)
366    {
367        len = ignoreSymbols[x].len;
368        if (!st.compare(0,len, ignoreSymbols[x].symbol, len))
369            return;
370        x++;
371    }
372
373    int sysi = getSys(sys);
374    StackId sid = StackId(sysi, frame);
375    // if expl is true suspend symbol table based states
376    if (!smStack[sid].size())
377        return;
378    if (!expl && swExpl[sid])
379        return;
380    if (expl)
381        swExpl[sid] = true;
382    DPRINTFS(AnnotateVerbose, sys, "SwBegin: %s sysi: %d\n", st, sysi);
383    int smi = smStack[sid].back();
384    int sti = getSt(smMap[smi-1].second.first, st);
385    if (lastState[smi] != sti) {
386        lastState[smi] = sti;
387        add(OP_BEGIN, flags, cpuid, smi, sti);
388    }
389}
390
391void
392CPA::swEnd(ThreadContext *tc)
393{
394    if (!enabled())
395        return;
396
397    std::string st;
398    Addr junk;
399    if (!TheISA::inUserMode(tc))
400        debugSymbolTable->findNearestSymbol(
401            tc->readIntReg(ReturnAddressReg), st, junk);
402    System *sys = tc->getSystemPtr();
403    StringWrap name(sys->name());
404
405    int sysi = getSys(sys);
406    StackId sid = StackId(sysi, getFrame(tc));
407    if (!smStack[sid].size()) {
408        DPRINTF(Annotate, "Explict end of State: %s IGNORED\n",  st);
409        return;
410    }
411    DPRINTF(Annotate, "Explict end of State: %s\n",  st);
412    // return back to symbol table based states
413    swExpl[sid] = false;
414    int smi = smStack[sid].back();
415    if (st != "") {
416        int sti = getSt(smMap[smi-1].second.first, st);
417        lastState[smi] = sti;
418        add(OP_BEGIN, FL_NONE, tc->contextId(), smi, sti);
419    }
420}
421
422void
423CPA::swQ(ThreadContext *tc)
424{
425    if (!enabled())
426        return;
427
428    char q[50];
429    Arguments args(tc);
430    uint64_t id = args[0];
431    tc->getVirtProxy().readString(q, args[1], 50);
432    int32_t count = args[2];
433    System *sys = tc->getSystemPtr();
434
435    int sysi = getSys(sys);
436    StackId sid = StackId(sysi, getFrame(tc));
437    if (!smStack[sid].size())
438        return;
439    int smi = smStack[sid].back();
440    if (swExpl[sid])
441        swExpl[sid] = false;
442    int qi = getQ(sysi, q, id);
443    if (count == 0) {
444        //warn("Tried to queue 0 bytes in %s, ignoring\n", q);
445        return;
446    }
447    DPRINTFS(AnnotateQ, sys,
448            "swQ: %s[%#x] cur size %d %d bytes: %d adding: %d\n",
449            q, id, qSize[qi-1], qData[qi-1].size(), qBytes[qi-1], count);
450    doQ(sys, FL_NONE, tc->contextId(), smi, q, qi, count);
451}
452
453void
454CPA::swDq(ThreadContext *tc)
455{
456    if (!enabled())
457        return;
458
459    char q[50];
460    Arguments args(tc);
461    uint64_t id = args[0];
462    tc->getVirtProxy().readString(q, args[1], 50);
463    int32_t count = args[2];
464    System *sys = tc->getSystemPtr();
465
466    int sysi = getSys(sys);
467    StackId sid = StackId(sysi, getFrame(tc));
468    if (!smStack[sid].size())
469        return;
470    int smi = smStack[sid].back();
471    int qi = getQ(sysi, q, id);
472    if (swExpl[sid])
473        swExpl[sid] = false;
474    DPRINTFS(AnnotateQ, sys,
475            "swDq: %s[%#x] cur size %d %d bytes: %d removing: %d\n",
476            q, id, qSize[qi-1], qData[qi-1].size(), qBytes[qi-1], count);
477    assert(count != 0);
478
479    doDq(sys, FL_NONE, tc->contextId(), smi, q, qi, count);
480}
481
482void
483CPA::swPq(ThreadContext *tc)
484{
485    if (!enabled())
486        return;
487
488    char q[50];
489    Arguments args(tc);
490    uint64_t id = args[0];
491    tc->getVirtProxy().readString(q, args[1], 50);
492    System *sys = tc->getSystemPtr();
493    int32_t count = args[2];
494
495    int sysi = getSys(sys);
496    StackId sid = StackId(sysi, getFrame(tc));
497    if (!smStack[sid].size())
498        return;
499    int smi = smStack[sid].back();
500    int qi = getQ(sysi, q, id);
501    if (swExpl[sid])
502        swExpl[sid] = false;
503    DPRINTFS(AnnotateQ, sys,
504            "swPq: %s [%#x] cur size %d %d bytes: %d peeking: %d\n",
505            q, id, qSize[qi-1], qData[qi-1].size(), qBytes[qi-1], count);
506
507    assert(count != 0);
508    if (qBytes[qi-1] < count) {
509        dump(true);
510        dumpKey();
511        fatal("Queue %s peeking with not enough bytes available in queue!\n", q);
512    }
513
514    add(OP_PEEK, FL_NONE, tc->contextId(), smi, qi, count);
515}
516
517void
518CPA::swRq(ThreadContext *tc)
519{
520    if (!enabled())
521        return;
522
523    char q[50];
524    Arguments args(tc);
525    uint64_t id = args[0];
526    tc->getVirtProxy().readString(q, args[1], 50);
527    System *sys = tc->getSystemPtr();
528    int32_t count = args[2];
529
530    int sysi = getSys(sys);
531    StackId sid = StackId(sysi, getFrame(tc));
532    if (!smStack[sid].size())
533        return;
534    int smi = smStack[sid].back();
535    int qi = getQ(sysi, q, id);
536    if (swExpl[sid])
537        swExpl[sid] = false;
538    DPRINTFS(AnnotateQ, sys,
539            "swRq: %s [%#x] cur size %d %d bytes: %d reserve: %d\n",
540            q, id, qSize[qi-1], qData[qi-1].size(), qBytes[qi-1], count);
541
542    assert(count != 0);
543
544    add(OP_RESERVE, FL_NONE, tc->contextId(), smi, qi, count);
545}
546
547
548void
549CPA::swWf(ThreadContext *tc)
550{
551    if (!enabled())
552        return;
553
554    char q[50];
555    Arguments args(tc);
556    uint64_t id = args[0];
557    tc->getVirtProxy().readString(q, args[1], 50);
558    System *sys = tc->getSystemPtr();
559    int32_t count = args[3];
560
561    int sysi = getSys(sys);
562    StackId sid = StackId(sysi, getFrame(tc));
563    if (!smStack[sid].size())
564        return;
565    int smi = smStack[sid].back();
566    int qi = getQ(sysi, q, id);
567    add(OP_WAIT_FULL, FL_NONE, tc->contextId(), smi, qi, count);
568
569    if (!!args[2]) {
570        char sm[50];
571        tc->getVirtProxy().readString(sm, args[2], 50);
572        doSwSmEnd(tc->getSystemPtr(), tc->contextId(), sm, getFrame(tc));
573    }
574}
575
576void
577CPA::swWe(ThreadContext *tc)
578{
579    if (!enabled())
580        return;
581
582    char q[50];
583    Arguments args(tc);
584    uint64_t id = args[0];
585    tc->getVirtProxy().readString(q, args[1], 50);
586    System *sys = tc->getSystemPtr();
587    int32_t count = args[3];
588
589    int sysi = getSys(sys);
590    StackId sid = StackId(sysi, getFrame(tc));
591    if (!smStack[sid].size())
592        return;
593    int smi = smStack[sid].back();
594    int qi = getQ(sysi, q, id);
595    add(OP_WAIT_EMPTY, FL_NONE, tc->contextId(), smi, qi, count);
596
597    if (!!args[2]) {
598        char sm[50];
599        tc->getVirtProxy().readString(sm, args[2], 50);
600        doSwSmEnd(tc->getSystemPtr(), tc->contextId(), sm, getFrame(tc));
601    }
602}
603
604void
605CPA::swSq(ThreadContext *tc)
606{
607    if (!enabled())
608        return;
609
610    char q[50];
611    Arguments args(tc);
612    uint64_t id = args[0];
613    tc->getVirtProxy().readString(q, args[1], 50);
614    System *sys = tc->getSystemPtr();
615    StringWrap name(sys->name());
616    int32_t size = args[2];
617    int flags = args[3];
618
619    int sysi = getSys(sys);
620    StackId sid = StackId(sysi, getFrame(tc));
621    if (!smStack[sid].size())
622        return;
623    int smi = smStack[sid].back();
624    int qi = getQ(sysi, q, id);
625    DPRINTF(AnnotateQ, "swSq: %s [%#x] cur size: %d bytes: %d, new size: %d\n",
626             q, id, qSize[qi-1], qBytes[qi-1], size);
627
628    if (FL_RESET & flags) {
629        DPRINTF(AnnotateQ, "Resetting Queue %s\n", q);
630        add(OP_SIZE_QUEUE, FL_NONE, tc->contextId(), smi, qi, 0);
631        qData[qi-1].clear();
632        qSize[qi-1] = 0;
633        qBytes[qi-1] = 0;
634    }
635
636    if (qBytes[qi-1] < size)
637        doQ(sys, FL_NONE, tc->contextId(), smi, q, qi, size - qBytes[qi-1]);
638    else if (qBytes[qi-1] > size) {
639        DPRINTF(AnnotateQ, "removing for resize of queue %s\n", q);
640        add(OP_SIZE_QUEUE, FL_NONE, tc->contextId(), smi, qi, size);
641        if (size <= 0) {
642            qData[qi-1].clear();
643            qSize[qi-1] = 0;
644            qBytes[qi-1] = 0;
645            return;
646        }
647        int need = qBytes[qi-1] - size;
648        qBytes[qi-1] = size;
649        while (need > 0) {
650            int32_t tail_bytes = qData[qi-1].back()->data;
651            if (qSize[qi-1] <= 0 || qBytes[qi-1] < 0) {
652                dump(true);
653                dumpKey();
654                fatal("Queue %s had inconsistancy when doing size queue!\n", q);
655            }
656            if (tail_bytes > need) {
657                qData[qi-1].back()->data -= need;
658                need = 0;
659            } else if (tail_bytes == need) {
660                qData[qi-1].pop_back();
661                qSize[qi-1]--;
662                need = 0;
663            } else {
664                qData[qi-1].pop_back();
665                qSize[qi-1]--;
666                need -= tail_bytes;
667            }
668        }
669    }
670}
671
672void
673CPA::swAq(ThreadContext *tc)
674{
675    if (!enabled())
676        return;
677
678    char q[50];
679    Arguments args(tc);
680    uint64_t id = args[0];
681    tc->getVirtProxy().readString(q, args[1], 50);
682    System *sys = tc->getSystemPtr();
683    StringWrap name(sys->name());
684    int32_t size = args[2];
685
686    int sysi = getSys(sys);
687    int qi = getQ(sysi, q, id);
688    if (qBytes[qi-1] != size) {
689        DPRINTF(AnnotateQ, "Queue %s [%#x] has inconsintant size\n", q, id);
690        //dump(true);
691        //dumpKey();
692        std::list<AnnDataPtr>::iterator ai = qData[qi-1].begin();
693        int x = 0;
694        while (ai != qData[qi-1].end()) {
695            DPRINTF(AnnotateQ, "--Element %d size %d\n", x, (*ai)->data);
696            ai++;
697            x++;
698        }
699
700        warn("%d: Queue Assert: SW said there should be %d byte(s) in %s,"
701                "however there are %d byte(s)\n",
702            curTick(), size, q, qBytes[qi-1]);
703        DPRINTF(AnnotateQ, "%d: Queue Assert: SW said there should be %d"
704                " byte(s) in %s, however there are %d byte(s)\n",
705            curTick(), size, q, qBytes[qi-1]);
706    }
707}
708
709void
710CPA::swLink(ThreadContext *tc)
711{
712    if (!enabled())
713        return;
714
715    char lsm[50];
716    Arguments args(tc);
717    tc->getVirtProxy().readString(lsm, args[0], 50);
718    System *sys = tc->getSystemPtr();
719    StringWrap name(sys->name());
720
721    int sysi = getSys(sys);
722    StackId sid = StackId(sysi, getFrame(tc));
723    if (!smStack[sid].size())
724        return;
725    int smi = smStack[sid].back();
726    int lsmi = getSm(sysi, lsm, args[1]);
727
728    DPRINTF(Annotate, "Linking from %d to state machine %s(%d) [%#x]\n",
729            smi, lsm, lsmi, args[1]);
730
731    if (lnMap[lsmi])
732        DPRINTF(Annotate, "LnMap already contains entry for %d of %d\n",
733                lsmi, lnMap[lsmi]);
734    assert(lnMap[lsmi] == 0);
735    lnMap[lsmi] =  smi;
736
737    add(OP_LINK, FL_NONE, tc->contextId(), smi, lsmi);
738
739    if (!!args[2]) {
740        char sm[50];
741        tc->getVirtProxy().readString(sm, args[2], 50);
742        doSwSmEnd(tc->getSystemPtr(), tc->contextId(), sm, getFrame(tc));
743    }
744}
745
746void
747CPA::swIdentify(ThreadContext *tc)
748{
749    if (!enabled())
750        return;
751
752    Arguments args(tc);
753    int sysi = getSys(tc->getSystemPtr());
754    StackId sid = StackId(sysi, getFrame(tc));
755    if (!smStack[sid].size())
756        return;
757    int smi = smStack[sid].back();
758
759    DPRINTFS(Annotate, tc->getSystemPtr(), "swIdentify: id %#X\n", args[0]);
760
761    add(OP_IDENT, FL_NONE, tc->contextId(), smi, 0, args[0]);
762}
763
764uint64_t
765CPA::swGetId(ThreadContext *tc)
766{
767    if (!enabled())
768        return 0;
769
770    uint64_t id = ++conId;
771    int sysi = getSys(tc->getSystemPtr());
772    StackId sid = StackId(sysi, getFrame(tc));
773    if (!smStack[sid].size())
774        panic("swGetId called without a state machine stack!");
775    int smi = smStack[sid].back();
776
777    DPRINTFS(Annotate, tc->getSystemPtr(), "swGetId: id %#X\n", id);
778
779    add(OP_IDENT, FL_NONE, tc->contextId(), smi, 0, id);
780    return id;
781}
782
783
784void
785CPA::swSyscallLink(ThreadContext  *tc)
786{
787    if (!enabled())
788        return;
789
790    char lsm[50];
791    Arguments args(tc);
792    tc->getVirtProxy().readString(lsm, args[0], 50);
793    System *sys = tc->getSystemPtr();
794    StringWrap name(sys->name());
795    int sysi = getSys(sys);
796
797    Id id = Id(lsm, getFrame(tc));
798    StackId sid = StackId(sysi, getFrame(tc));
799
800    if (!smStack[sid].size())
801        return;
802
803    int smi = smStack[sid].back();
804
805    DPRINTF(Annotate, "Linking from %d to state machine %s(UNKNOWN)\n",
806            smi, lsm);
807
808    if (scLinks[sysi-1][id])
809        DPRINTF(Annotate,
810                "scLinks already contains entry for system %d %s[%x] of %d\n",
811                sysi, lsm, getFrame(tc), scLinks[sysi-1][id]);
812    assert(scLinks[sysi-1][id] == 0);
813    scLinks[sysi-1][id] = add(OP_LINK, FL_NONE, tc->contextId(), smi, 0xFFFF);
814    scLinks[sysi-1][id]->dump = false;
815
816    if (!!args[1]) {
817        char sm[50];
818        tc->getVirtProxy().readString(sm, args[1], 50);
819        doSwSmEnd(tc->getSystemPtr(), tc->contextId(), sm, getFrame(tc));
820    }
821}
822
823CPA::AnnDataPtr
824CPA::add(int t, int f, int c, int sm, int stq, int32_t d)
825{
826    AnnDataPtr an = std::make_shared<AnnotateData>();
827    an->time = curTick();
828    an->data = d;
829    an->orig_data = d;
830    an->op = t;
831    an->flag = f;
832    an->sm = sm;
833    an->stq = stq;
834    an->cpu = c;
835    an->dump = true;
836
837    data.push_back(an);
838
839    DPRINTF(AnnotateVerbose, "Annotate: op: %d flags: 0x%x sm: %d state: %d time: %d, data: %d\n",
840            an->op, an->flag, an->sm, an->stq, an->time, an->data);
841
842    // Don't dump Links because we might be setting no-dump on it
843    if (an->op != OP_LINK)
844        dump(false);
845
846    return an;
847}
848
849void
850CPA::dumpKey()
851{
852    std::streampos curpos = osbin->tellp();
853    ah.key_off = curpos;
854
855    // Output the various state machines and their corresponding states
856    *osbin << "# Automatically generated state machine descriptor file" << endl;
857
858    *osbin << "sms = {}" << endl << endl;
859    vector<string> state_machines;
860    state_machines.resize(numSmt+1);
861
862    // State machines, id -> states
863    SCache::iterator i = smtCache.begin();
864    while (i != smtCache.end()) {
865        state_machines[i->second] = i->first;
866        i++;
867    }
868
869    for (int x = 1; x < state_machines.size(); x++) {
870        vector<string> states;
871        states.resize(numSt[x-1]+1);
872        assert(x-1 < stCache.size());
873        SCache::iterator i = stCache[x-1].begin();
874        while (i != stCache[x-1].end()) {
875            states[i->second] = i->first;
876            i++;
877        }
878        *osbin << "sms[\"" << state_machines[x] << "\"] = [\"NULL\"";
879        for (int y = 1; y < states.size(); y++)
880            *osbin << ", \"" << states[y] << "\"";
881        *osbin << "]" << endl;
882    }
883
884    *osbin << endl << endl << endl;
885
886    // state machine number -> system, name, id
887    *osbin << "smNum = [\"NULL\"";
888    for (int x = 0; x < smMap.size(); x++)
889        *osbin << ", (" << smMap[x].first << ", \"" << smMap[x].second.first <<
890            "\", " << smMap[x].second.second << ")";
891    *osbin << "]" << endl;
892
893    *osbin << endl << endl << endl;
894
895    // Output the systems
896    vector<string> systems;
897    systems.resize(numSys+1);
898    NameCache::iterator i2 = nameCache.begin();
899    while (i2 != nameCache.end()) {
900        systems[i2->second.second] = i2->second.first;
901        i2++;
902    }
903
904    *osbin << "sysNum = [\"NULL\"";
905    for (int x = 1; x < systems.size(); x++) {
906        *osbin << ", \"" << systems[x] << "\"";
907    }
908    *osbin << "]" << endl;
909
910    // queue number -> system, qname, qid
911    *osbin << "queues = [\"NULL\"";
912    for (int x = 0; x < qMap.size(); x++)
913        *osbin << ", (" << qMap[x].first << ", \"" << qMap[x].second.first <<
914            "\", " << qMap[x].second.second << ")";
915    *osbin << "]" << endl;
916
917    *osbin << "smComb = [s for s in [(i,r) for i in xrange(1,len(sysNum)) "
918           << "for r in xrange (1,len(smNum))]]" << endl;
919    ah.key_len = osbin->tellp() - curpos;
920
921    // output index
922    curpos = osbin->tellp();
923    ah.idx_off = curpos;
924
925    for (int x = 0; x < annotateIdx.size(); x++)
926        osbin->write((char*)&annotateIdx[x], sizeof(uint64_t));
927    ah.idx_len = osbin->tellp() - curpos;
928
929    osbin->seekp(0);
930    osbin->write((char*)&ah, sizeof(AnnotateHeader));
931    osbin->flush();
932
933}
934
935void
936CPA::dump(bool all)
937{
938
939    list<AnnDataPtr>::iterator i;
940
941    i = data.begin();
942
943    if (i == data.end())
944        return;
945
946    // Dump the data every
947    if (!all && data.size() < 10000)
948        return;
949
950    DPRINTF(Annotate, "Writing %d\n", data.size());
951    while (i != data.end()) {
952        AnnDataPtr an = *i;
953
954        // If we can't dump this record, hold here
955        if (!an->dump && !all)
956            break;
957
958        ah.num_recs++;
959        if (ah.num_recs % 100000 == 0)
960            annotateIdx.push_back(osbin->tellp());
961
962
963        osbin->write((char*)&(an->time), sizeof(an->time));
964        osbin->write((char*)&(an->orig_data), sizeof(an->orig_data));
965        osbin->write((char*)&(an->sm), sizeof(an->sm));
966        osbin->write((char*)&(an->stq), sizeof(an->stq));
967        osbin->write((char*)&(an->op), sizeof(an->op));
968        osbin->write((char*)&(an->flag), sizeof(an->flag));
969        osbin->write((char*)&(an->cpu), sizeof(an->cpu));
970        i++;
971    }
972    if (data.begin() != i)
973        data.erase(data.begin(), i);
974
975    if (all)
976        osbin->flush();
977}
978
979void
980CPA::doQ(System *sys, int flags, int cpuid, int sm,
981              string q, int qi, int count)
982{
983    qSize[qi-1]++;
984    qBytes[qi-1] += count;
985    if (qSize[qi-1] > 2501 || qBytes[qi-1] > 2000000000)
986        warn("Queue %s is %d elements/%d bytes, "
987                "maybe things aren't being removed?\n",
988                q, qSize[qi-1], qBytes[qi-1]);
989    if (flags & FL_QOPP)
990        qData[qi-1].push_front(add(OP_QUEUE, flags, cpuid, sm, qi, count));
991    else
992        qData[qi-1].push_back(add(OP_QUEUE, flags, cpuid, sm, qi, count));
993    DPRINTFS(AnnotateQ, sys, "Queing in queue %s size now %d/%d\n",
994            q, qSize[qi-1], qBytes[qi-1]);
995    assert(qSize[qi-1] >= 0);
996    assert(qBytes[qi-1] >= 0);
997}
998
999
1000void
1001CPA::doDq(System *sys, int flags, int cpuid, int sm,
1002               string q, int qi, int count)
1003{
1004
1005    StringWrap name(sys->name());
1006    if (count == -1) {
1007        add(OP_DEQUEUE, flags, cpuid, sm, qi, count);
1008        qData[qi-1].clear();
1009        qSize[qi-1] = 0;
1010        qBytes[qi-1] = 0;
1011        DPRINTF(AnnotateQ, "Dequeing all data in queue %s size now %d/%d\n",
1012                q, qSize[qi-1], qBytes[qi-1]);
1013        return;
1014    }
1015
1016    assert(count > 0);
1017    if (qSize[qi-1] <= 0 || qBytes[qi-1] <= 0 || !qData[qi-1].size()) {
1018        dump(true);
1019        dumpKey();
1020        fatal("Queue %s dequing with no data available in queue!\n",
1021                q);
1022    }
1023    assert(qSize[qi-1] >= 0);
1024    assert(qBytes[qi-1] >= 0);
1025    assert(qData[qi-1].size());
1026
1027    int32_t need = count;
1028    qBytes[qi-1] -= count;
1029    if (qBytes[qi-1] < 0) {
1030        dump(true);
1031        dumpKey();
1032        fatal("Queue %s dequing with no bytes available in queue!\n",
1033                q);
1034    }
1035
1036    while (need > 0) {
1037        int32_t head_bytes = qData[qi-1].front()->data;
1038        if (qSize[qi-1] <= 0 || qBytes[qi-1] < 0) {
1039            dump(true);
1040            dumpKey();
1041            fatal("Queue %s dequing with nothing in queue!\n",
1042                q);
1043        }
1044
1045        if (head_bytes > need) {
1046            qData[qi-1].front()->data -= need;
1047            need = 0;
1048        } else if (head_bytes == need) {
1049            qData[qi-1].pop_front();
1050            qSize[qi-1]--;
1051            need = 0;
1052        } else {
1053            qData[qi-1].pop_front();
1054            qSize[qi-1]--;
1055            need -= head_bytes;
1056        }
1057    }
1058
1059    add(OP_DEQUEUE, flags, cpuid, sm, qi, count);
1060    DPRINTF(AnnotateQ, "Dequeing in queue %s size now %d/%d\n",
1061            q, qSize[qi-1], qBytes[qi-1]);
1062}
1063
1064
1065
1066void
1067CPA::serialize(CheckpointOut &cp) const
1068{
1069
1070    SERIALIZE_SCALAR(numSm);
1071    SERIALIZE_SCALAR(numSmt);
1072    arrayParamOut(os, "numSt", numSt);
1073    arrayParamOut(os, "numQ", numQ);
1074    SERIALIZE_SCALAR(numSys);
1075    SERIALIZE_SCALAR(numQs);
1076    SERIALIZE_SCALAR(conId);
1077    arrayParamOut(os, "qSize", qSize);
1078    arrayParamOut(os, "qSize", qSize);
1079    arrayParamOut(os, "qBytes", qBytes);
1080
1081    SCache::iterator i;
1082    int x = 0, y = 0;
1083
1084    // smtCache (SCache)
1085    x = 0;
1086    y = 0;
1087    i = smtCache.begin();
1088    while (i != smtCache.end()) {
1089        paramOut(os, csprintf("smtCache%d.str", x), i->first);
1090        paramOut(os, csprintf("smtCache%d.int", x), i->second);
1091        x++; i++;
1092    }
1093
1094    // stCache  (StCache)
1095    for (x = 0; x < stCache.size(); x++) {
1096        i = stCache[x].begin();
1097        y = 0;
1098        while (i != stCache[x].end()) {
1099            paramOut(os, csprintf("stCache%d_%d.str", x, y), i->first);
1100            paramOut(os, csprintf("stCache%d_%d.int", x, y), i->second);
1101            y++; i++;
1102        }
1103    }
1104
1105    // qCache (IdCache)
1106    IdHCache::iterator idi;
1107    for (x = 0; x < qCache.size(); x++) {
1108        idi = qCache[x].begin();
1109        y = 0;
1110        while (idi != qCache[x].end()) {
1111            paramOut(os, csprintf("qCache%d_%d.str", x, y), idi->first.first);
1112            paramOut(os, csprintf("qCache%d_%d.id", x, y), idi->first.second);
1113            paramOut(os, csprintf("qCache%d_%d.int", x, y), idi->second);
1114            y++; idi++;
1115        }
1116    }
1117
1118    // smCache (IdCache)
1119    for (x = 0; x < smCache.size(); x++) {
1120        idi = smCache[x].begin();
1121        y = 0;
1122        paramOut(os, csprintf("smCache%d", x), smCache[x].size());
1123        while (idi != smCache[x].end()) {
1124            paramOut(os, csprintf("smCache%d_%d.str", x, y), idi->first.first);
1125            paramOut(os, csprintf("smCache%d_%d.id", x, y), idi->first.second);
1126            paramOut(os, csprintf("smCache%d_%d.int", x, y), idi->second);
1127            y++; idi++;
1128        }
1129    }
1130
1131    // scLinks (ScCache) -- data not serialize
1132
1133
1134    // namecache (NameCache)
1135    NameCache::iterator ni;
1136
1137    ni = nameCache.begin();
1138    x = 0;
1139    while (ni != nameCache.end()) {
1140        paramOut(os, csprintf("nameCache%d.name", x), ni->first->name());
1141        paramOut(os, csprintf("nameCache%d.str", x), ni->second.first);
1142        paramOut(os, csprintf("nameCache%d.int", x), ni->second.second);
1143        x++; ni++;
1144    }
1145
1146    // smStack (SmStack)
1147    SmStack::iterator si;
1148    si = smStack.begin();
1149    x = 0;
1150    paramOut(os, "smStackIdCount", smStack.size());
1151    while (si != smStack.end()) {
1152        paramOut(os, csprintf("smStackId%d.sys", x), si->first.first);
1153        paramOut(os, csprintf("smStackId%d.frame", x), si->first.second);
1154        paramOut(os, csprintf("smStackId%d.count", x), si->second.size());
1155        for (y = 0; y < si->second.size(); y++)
1156            paramOut(os, csprintf("smStackId%d_%d", x, y), si->second[y]);
1157        x++; si++;
1158    }
1159
1160    // lnMap (LinkMap)
1161    x = 0;
1162    LinkMap::iterator li;
1163    li = lnMap.begin();
1164    paramOut(os, "lnMapSize", lnMap.size());
1165    while (li != lnMap.end()) {
1166        paramOut(os, csprintf("lnMap%d.smi", x), li->first);
1167        paramOut(os, csprintf("lnMap%d.lsmi", x), li->second);
1168        x++; li++;
1169    }
1170
1171    // swExpl (vector)
1172    SwExpl::iterator swexpli;
1173    swexpli = swExpl.begin();
1174    x = 0;
1175    paramOut(os, "swExplCount", swExpl.size());
1176    while (swexpli != swExpl.end()) {
1177        paramOut(os, csprintf("swExpl%d.sys", x), swexpli->first.first);
1178        paramOut(os, csprintf("swExpl%d.frame", x), swexpli->first.second);
1179        paramOut(os, csprintf("swExpl%d.swexpl", x), swexpli->second);
1180        x++; swexpli++;
1181    }
1182
1183    // lastState (IMap)
1184    x = 0;
1185    IMap::iterator ii;
1186    ii = lastState.begin();
1187    paramOut(os, "lastStateSize", lastState.size());
1188    while (ii != lastState.end()) {
1189        paramOut(os, csprintf("lastState%d.smi", x), ii->first);
1190        paramOut(os, csprintf("lastState%d.sti", x), ii->second);
1191        x++; ii++;
1192    }
1193
1194    // smMap (IdMap)
1195    for (x = 0; x < smMap.size(); x++) {
1196        paramOut(os, csprintf("smMap%d.sys", x), smMap[x].first);
1197        paramOut(os, csprintf("smMap%d.smname", x), smMap[x].second.first);
1198        paramOut(os, csprintf("smMap%d.id", x), smMap[x].second.second);
1199    }
1200
1201    // qMap (IdMap)
1202    for (x = 0; x < qMap.size(); x++) {
1203        paramOut(os, csprintf("qMap%d.sys", x), qMap[x].first);
1204        paramOut(os, csprintf("qMap%d.qname", x), qMap[x].second.first);
1205        paramOut(os, csprintf("qMap%d.id", x), qMap[x].second.second);
1206    }
1207
1208    // qData (vector<AnnotateList>)
1209    for (x = 0; x < qData.size(); x++) {
1210        if (!qData[x].size())
1211            continue;
1212        y = 0;
1213        for (auto &ann : qData[x]) {
1214            ann->serializeSection(os, csprintf("Q%d_%d", x, y));
1215            y++;
1216        }
1217    }
1218}
1219
1220void
1221CPA::unserialize(CheckpointIn &cp)
1222{
1223    UNSERIALIZE_SCALAR(numSm);
1224    UNSERIALIZE_SCALAR(numSmt);
1225    UNSERIALIZE_CONTAINER(numSt);
1226    UNSERIALIZE_CONTAINER(numQ);
1227    UNSERIALIZE_SCALAR(numSys);
1228    UNSERIALIZE_SCALAR(numQs);
1229    UNSERIALIZE_SCALAR(conId);
1230    UNSERIALIZE_CONTAINER(qSize);
1231    UNSERIALIZE_CONTAINER(qBytes);
1232
1233
1234    // smtCache (SCache
1235    string str;
1236    int smi;
1237    for (int x = 0;  x < numSmt; x++) {
1238        paramIn(cp, csprintf("smtCache%d.str", x), str);
1239        paramIn(cp, csprintf("smtCache%d.int", x), smi);
1240        smtCache[str] = smi;
1241    }
1242
1243    // stCache  (StCache)
1244    stCache.resize(numSmt);
1245    for (int x = 0;  x < numSmt; x++) {
1246        for (int y = 0; y < numSt[x]; y++) {
1247            paramIn(cp, csprintf("stCache%d_%d.str", x,y), str);
1248            paramIn(cp, csprintf("stCache%d_%d.int", x,y), smi);
1249            stCache[x][str] = smi;
1250        }
1251    }
1252
1253    // qCache (IdCache)
1254    uint64_t id;
1255    qCache.resize(numSys);
1256    for (int x = 0;  x < numSys; x++) {
1257        for (int y = 0; y < numQ[x]; y++) {
1258            paramIn(cp, csprintf("qCache%d_%d.str", x,y), str);
1259            paramIn(cp, csprintf("qCache%d_%d.id", x,y), id);
1260            paramIn(cp, csprintf("qCache%d_%d.int", x,y), smi);
1261            qCache[x][Id(str,id)] = smi;
1262        }
1263    }
1264
1265    // smCache (IdCache)
1266    smCache.resize(numSys);
1267    for (int x = 0;  x < numSys; x++) {
1268        int size;
1269        paramIn(cp, csprintf("smCache%d", x), size);
1270        for (int y = 0; y < size; y++) {
1271            paramIn(cp, csprintf("smCache%d_%d.str", x,y), str);
1272            paramIn(cp, csprintf("smCache%d_%d.id", x,y), id);
1273            paramIn(cp, csprintf("smCache%d_%d.int", x,y), smi);
1274            smCache[x][Id(str,id)] = smi;
1275        }
1276    }
1277
1278    // scLinks (ScCache) -- data not serialized, just creating one per sys
1279    for (int x = 0; x < numSys; x++)
1280        scLinks.push_back(ScHCache());
1281
1282    // nameCache (NameCache)
1283    for (int x = 0; x < numSys; x++) {
1284        System *sys;
1285        SimObject *sptr;
1286        string str;
1287        int sysi;
1288
1289        objParamIn(cp, csprintf("nameCache%d.name", x), sptr);
1290        sys = dynamic_cast<System*>(sptr);
1291
1292        paramIn(cp, csprintf("nameCache%d.str", x), str);
1293        paramIn(cp, csprintf("nameCache%d.int", x), sysi);
1294        nameCache[sys] = std::make_pair(str, sysi);
1295    }
1296
1297    //smStack (SmStack)
1298    int smStack_size;
1299    paramIn(cp, "smStackIdCount", smStack_size);
1300    for (int x = 0; x < smStack_size; x++) {
1301        int sysi;
1302        uint64_t frame;
1303        int count;
1304        paramIn(cp, csprintf("smStackId%d.sys", x), sysi);
1305        paramIn(cp, csprintf("smStackId%d.frame", x), frame);
1306        paramIn(cp, csprintf("smStackId%d.count", x), count);
1307        StackId sid = StackId(sysi, frame);
1308        for (int y = 0; y < count; y++) {
1309            paramIn(cp, csprintf("smStackId%d_%d", x, y), smi);
1310            smStack[sid].push_back(smi);
1311        }
1312    }
1313
1314    // lnMap (LinkMap)
1315    int lsmi;
1316    int lnMap_size;
1317    paramIn(cp, "lnMapSize", lnMap_size);
1318    for (int x = 0;  x < lnMap_size; x++) {
1319        paramIn(cp, csprintf("lnMap%d.smi", x), smi);
1320        paramIn(cp, csprintf("lnMap%d.lsmi", x), lsmi);
1321        lnMap[smi] = lsmi;
1322    }
1323
1324    // swExpl (vector)
1325    int swExpl_size;
1326    paramIn(cp, "swExplCount", swExpl_size);
1327    for (int x = 0; x < swExpl_size; x++) {
1328        int sysi;
1329        uint64_t frame;
1330        bool b;
1331        paramIn(cp, csprintf("swExpl%d.sys", x), sysi);
1332        paramIn(cp, csprintf("swExpl%d.frame", x), frame);
1333        paramIn(cp, csprintf("swExpl%d.swexpl", x), b);
1334        StackId sid = StackId(sysi, frame);
1335        swExpl[sid] = b;
1336    }
1337
1338    // lastState (IMap)
1339    int sti;
1340    int lastState_size;
1341    paramIn(cp, "lastStateSize", lastState_size);
1342    for (int x = 0;  x < lastState_size; x++) {
1343        paramIn(cp, csprintf("lastState%d.smi", x), smi);
1344        paramIn(cp, csprintf("lastState%d.sti", x), sti);
1345        lastState[smi] = sti;
1346    }
1347
1348
1349    //smMap (IdMap)
1350    smMap.resize(numSm);
1351    for (int x = 0; x < smMap.size(); x++) {
1352        paramIn(cp, csprintf("smMap%d.sys", x), smMap[x].first);
1353        paramIn(cp, csprintf("smMap%d.smname", x), smMap[x].second.first);
1354        paramIn(cp, csprintf("smMap%d.id", x), smMap[x].second.second);
1355    }
1356
1357    //qMap (IdMap)
1358    qMap.resize(numQs);
1359    for (int x = 0; x < qMap.size(); x++) {
1360        paramIn(cp, csprintf("qMap%d.sys", x), qMap[x].first);
1361        paramIn(cp, csprintf("qMap%d.qname", x), qMap[x].second.first);
1362        paramIn(cp, csprintf("qMap%d.id", x), qMap[x].second.second);
1363    }
1364
1365
1366    // qData (vector<AnnotateList>)
1367    qData.resize(qSize.size());
1368    for (int x = 0; x < qSize.size(); x++) {
1369        if (!qSize[x])
1370            continue;
1371        for (int y = 0; y < qSize[x]; y++) {
1372            AnnDataPtr a = std::make_shared<AnnotateData>();
1373            a->unserializeSection(cp, csprintf("Q%d_%d", x, y));
1374            data.push_back(a);
1375            qData[x].push_back(a);
1376        }
1377    }
1378}
1379
1380void
1381CPA::AnnotateData::serialize(CheckpointOut &cp) const
1382{
1383    SERIALIZE_SCALAR(time);
1384    SERIALIZE_SCALAR(data);
1385    SERIALIZE_SCALAR(sm);
1386    SERIALIZE_SCALAR(stq);
1387    SERIALIZE_SCALAR(op);
1388    SERIALIZE_SCALAR(flag);
1389    SERIALIZE_SCALAR(cpu);
1390}
1391
1392void
1393CPA::AnnotateData::unserialize(CheckpointIn &cp)
1394{
1395    UNSERIALIZE_SCALAR(time);
1396    UNSERIALIZE_SCALAR(data);
1397    orig_data = data;
1398    UNSERIALIZE_SCALAR(sm);
1399    UNSERIALIZE_SCALAR(stq);
1400    UNSERIALIZE_SCALAR(op);
1401    UNSERIALIZE_SCALAR(flag);
1402    UNSERIALIZE_SCALAR(cpu);
1403    dump = true;
1404}
1405
1406CPA*
1407CPAParams::create()
1408{
1409    return new CPA(this);
1410}
1411
1412