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