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