cp_annotate.cc revision 5952
19480Snilay@cs.wisc.edu/*
210785Sgope@wisc.edu * Copyright (c) 2006-2009 The Regents of The University of Michigan
39480Snilay@cs.wisc.edu * All rights reserved.
49480Snilay@cs.wisc.edu *
59480Snilay@cs.wisc.edu * Redistribution and use in source and binary forms, with or without
69480Snilay@cs.wisc.edu * modification, are permitted provided that the following conditions are
79480Snilay@cs.wisc.edu * met: redistributions of source code must retain the above copyright
89480Snilay@cs.wisc.edu * notice, this list of conditions and the following disclaimer;
99480Snilay@cs.wisc.edu * redistributions in binary form must reproduce the above copyright
109480Snilay@cs.wisc.edu * notice, this list of conditions and the following disclaimer in the
119480Snilay@cs.wisc.edu * documentation and/or other materials provided with the distribution;
129480Snilay@cs.wisc.edu * neither the name of the copyright holders nor the names of its
139480Snilay@cs.wisc.edu * contributors may be used to endorse or promote products derived from
149480Snilay@cs.wisc.edu * this software without specific prior written permission.
159480Snilay@cs.wisc.edu *
169480Snilay@cs.wisc.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
179480Snilay@cs.wisc.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
189480Snilay@cs.wisc.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
199480Snilay@cs.wisc.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
209480Snilay@cs.wisc.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
219480Snilay@cs.wisc.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
229480Snilay@cs.wisc.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
239480Snilay@cs.wisc.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
249480Snilay@cs.wisc.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
259480Snilay@cs.wisc.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
269480Snilay@cs.wisc.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
279480Snilay@cs.wisc.edu *
2810785Sgope@wisc.edu * Authors: Ali Saidi
299480Snilay@cs.wisc.edu */
309480Snilay@cs.wisc.edu
319480Snilay@cs.wisc.edu#include "arch/utility.hh"
3213432Spau.cabre@metempsy.com#include "arch/alpha/linux/threadinfo.hh"
339480Snilay@cs.wisc.edu#include "base/cp_annotate.hh"
3413957Sjairo.balart@metempsy.com#include "base/callback.hh"
3513957Sjairo.balart@metempsy.com#include "base/loader/object_file.hh"
3613957Sjairo.balart@metempsy.com#include "base/output.hh"
3713957Sjairo.balart@metempsy.com#include "base/trace.hh"
3813957Sjairo.balart@metempsy.com#include "cpu/thread_context.hh"
3913957Sjairo.balart@metempsy.com#include "sim/arguments.hh"
4013957Sjairo.balart@metempsy.com#include "sim/core.hh"
4113957Sjairo.balart@metempsy.com#include "sim/sim_exit.hh"
4213957Sjairo.balart@metempsy.com#include "sim/system.hh"
4313957Sjairo.balart@metempsy.com
4413957Sjairo.balart@metempsy.comstruct CPAIgnoreSymbol
4513957Sjairo.balart@metempsy.com{
4613957Sjairo.balart@metempsy.com    const char *symbol;
4713957Sjairo.balart@metempsy.com    size_t len;
4813957Sjairo.balart@metempsy.com};
4913957Sjairo.balart@metempsy.com#define CPA_IGNORE_SYMBOL(sym) { #sym, sizeof(#sym) }
5013957Sjairo.balart@metempsy.com
5113957Sjairo.balart@metempsy.comCPAIgnoreSymbol ignoreSymbols[] = {
5213957Sjairo.balart@metempsy.com    CPA_IGNORE_SYMBOL("m5a_"),
5313957Sjairo.balart@metempsy.com    CPA_IGNORE_SYMBOL("ret_from_sys_call"),
5413957Sjairo.balart@metempsy.com    CPA_IGNORE_SYMBOL("ret_from_reschedule"),
5513957Sjairo.balart@metempsy.com    CPA_IGNORE_SYMBOL("_spin_"),
5613957Sjairo.balart@metempsy.com    CPA_IGNORE_SYMBOL("local_bh_"),
579480Snilay@cs.wisc.edu    CPA_IGNORE_SYMBOL("restore_all"),
589480Snilay@cs.wisc.edu    CPA_IGNORE_SYMBOL("Call_Pal_"),
599480Snilay@cs.wisc.edu    CPA_IGNORE_SYMBOL("pal_post_interrupt"),
609480Snilay@cs.wisc.edu    CPA_IGNORE_SYMBOL("rti_to_"),
6110785Sgope@wisc.edu    CPA_IGNORE_SYMBOL("sys_int_2"),
629480Snilay@cs.wisc.edu    CPA_IGNORE_SYMBOL("sys_interrupt"),
6313432Spau.cabre@metempsy.com    CPA_IGNORE_SYMBOL("normal_int"),
6410785Sgope@wisc.edu    CPA_IGNORE_SYMBOL("TRAP_INTERRUPT_10_"),
6510785Sgope@wisc.edu    CPA_IGNORE_SYMBOL("Trap_Interrupt"),
6610785Sgope@wisc.edu    CPA_IGNORE_SYMBOL("do_entInt"),
6710785Sgope@wisc.edu    CPA_IGNORE_SYMBOL("__do_softirq"),
6810785Sgope@wisc.edu    CPA_IGNORE_SYMBOL("_end"),
6913957Sjairo.balart@metempsy.com    CPA_IGNORE_SYMBOL("entInt"),
7013957Sjairo.balart@metempsy.com    CPA_IGNORE_SYMBOL("entSys"),
7110785Sgope@wisc.edu    {0,0}
7210785Sgope@wisc.edu};
7310785Sgope@wisc.edu#undef CPA_IGNORE_SYMBOL
7410785Sgope@wisc.edu
7510785Sgope@wisc.eduusing namespace std;
7610785Sgope@wisc.eduusing namespace TheISA;
779480Snilay@cs.wisc.edu
789480Snilay@cs.wisc.edubool CPA::exists;
7910785Sgope@wisc.eduCPA *CPA::_cpa;
8010785Sgope@wisc.edu
8110785Sgope@wisc.educlass AnnotateDumpCallback : public Callback
8210785Sgope@wisc.edu{
8310785Sgope@wisc.edu
8410785Sgope@wisc.edu  private:
8510785Sgope@wisc.edu    CPA *cpa;
8610785Sgope@wisc.edu  public:
8710785Sgope@wisc.edu    virtual void process();
8810785Sgope@wisc.edu    AnnotateDumpCallback(CPA *_cpa)
899480Snilay@cs.wisc.edu        : cpa(_cpa)
909480Snilay@cs.wisc.edu    {}
919480Snilay@cs.wisc.edu};
929480Snilay@cs.wisc.edu
939480Snilay@cs.wisc.eduvoid
949480Snilay@cs.wisc.eduAnnotateDumpCallback::process()
9510785Sgope@wisc.edu{
9610785Sgope@wisc.edu    cpa->dump(true);
9710785Sgope@wisc.edu    cpa->dumpKey();
9810785Sgope@wisc.edu}
9910785Sgope@wisc.edu
10010785Sgope@wisc.edu
10110785Sgope@wisc.eduCPA::CPA(Params *p)
10210785Sgope@wisc.edu    : SimObject(p), numSm(0), numSmt(0), numSys(0), numQs(0), conId(0)
10310785Sgope@wisc.edu{
10410785Sgope@wisc.edu    if (exists)
10513626Sjairo.balart@metempsy.com        fatal("Multiple annotation objects found in system");
10613626Sjairo.balart@metempsy.com    exists = true;
10713626Sjairo.balart@metempsy.com
10813626Sjairo.balart@metempsy.com    _enabled = p->enabled;
10913626Sjairo.balart@metempsy.com    _cpa = this;
11013626Sjairo.balart@metempsy.com
11113626Sjairo.balart@metempsy.com    vector<string>::iterator i;
11213626Sjairo.balart@metempsy.com    i = p->user_apps.begin();
11313454Spau.cabre@metempsy.com
11413454Spau.cabre@metempsy.com    while (i != p->user_apps.end()) {
11513494Spau.cabre@metempsy.com        ObjectFile *of = createObjectFile(*i);
11613494Spau.cabre@metempsy.com        string sf;
11713454Spau.cabre@metempsy.com        if (!of)
11813454Spau.cabre@metempsy.com            fatal("Couldn't load symbols from file: %s\n", *i);
11913454Spau.cabre@metempsy.com        sf = *i;
12013454Spau.cabre@metempsy.com        sf.erase(0, sf.rfind('/') + 1);;
12113454Spau.cabre@metempsy.com        DPRINTFN("file %s short: %s\n", *i, sf);
12213454Spau.cabre@metempsy.com        userApp[sf] = new SymbolTable;
12313454Spau.cabre@metempsy.com        bool result1 = of->loadGlobalSymbols(userApp[sf]);
12413454Spau.cabre@metempsy.com        bool result2 = of->loadLocalSymbols(userApp[sf]);
12513454Spau.cabre@metempsy.com        if (!result1 || !result2)
12613454Spau.cabre@metempsy.com            panic("blah");
12713454Spau.cabre@metempsy.com        assert(result1 && result2);
12813454Spau.cabre@metempsy.com        i++;
12913454Spau.cabre@metempsy.com    }
13013454Spau.cabre@metempsy.com}
13113454Spau.cabre@metempsy.com
13213454Spau.cabre@metempsy.comvoid
13313454Spau.cabre@metempsy.comCPA::startup()
13413454Spau.cabre@metempsy.com{
13513626Sjairo.balart@metempsy.com    osbin = simout.create("annotate.bin", true);
13613685Sjavier.bueno@metempsy.com    // MAGIC version number 'M''5''A'N' + version/capabilities
13713454Spau.cabre@metempsy.com    ah.version = 0x4D35414E00000101ULL;
13813626Sjairo.balart@metempsy.com    ah.num_recs = 0;
13913626Sjairo.balart@metempsy.com    ah.key_off = 0;
14013626Sjairo.balart@metempsy.com    osbin->write((char*)&ah, sizeof(AnnotateHeader));
14113626Sjairo.balart@metempsy.com
14213626Sjairo.balart@metempsy.com    registerExitCallback(new AnnotateDumpCallback(this));
14313626Sjairo.balart@metempsy.com}
14413626Sjairo.balart@metempsy.comvoid
14513626Sjairo.balart@metempsy.comCPA::swSmBegin(ThreadContext *tc)
14613626Sjairo.balart@metempsy.com{
14713626Sjairo.balart@metempsy.com    if (!enabled())
14813626Sjairo.balart@metempsy.com        return;
14913626Sjairo.balart@metempsy.com
15013626Sjairo.balart@metempsy.com    Arguments args(tc);
15113626Sjairo.balart@metempsy.com    std::string st;
15213626Sjairo.balart@metempsy.com    Addr junk;
15313626Sjairo.balart@metempsy.com    char sm[50];
15413626Sjairo.balart@metempsy.com    if (!TheISA::inUserMode(tc))
15513626Sjairo.balart@metempsy.com        debugSymbolTable->findNearestSymbol(
15613626Sjairo.balart@metempsy.com            tc->readIntReg(ReturnAddressReg), st, junk);
15713626Sjairo.balart@metempsy.com
15813626Sjairo.balart@metempsy.com    CopyStringOut(tc, sm, args[0], 50);
15913626Sjairo.balart@metempsy.com    System *sys = tc->getSystemPtr();
16013626Sjairo.balart@metempsy.com    StringWrap name(sys->name());
16113626Sjairo.balart@metempsy.com
16213454Spau.cabre@metempsy.com    if (!sm[0])
16313627Sjavier.bueno@metempsy.com        warn("Got null SM at tick %d\n", curTick);
16413627Sjavier.bueno@metempsy.com
16513627Sjavier.bueno@metempsy.com    int sysi = getSys(sys);
16613627Sjavier.bueno@metempsy.com    int smi = getSm(sysi, sm, args[1]);
16713454Spau.cabre@metempsy.com    DPRINTF(Annotate,  "Starting machine: %s(%d) sysi: %d id: %#x\n", sm,
16811784Sarthur.perais@inria.fr            smi, sysi, args[1]);
16913444Spau.cabre@metempsy.com    DPRINTF(Annotate, "smMap[%d] = %d, %s, %#x\n", smi,
17013442Spau.cabre@metempsy.com            smMap[smi-1].first, smMap[smi-1].second.first,
17113442Spau.cabre@metempsy.com            smMap[smi-1].second.second);
17213442Spau.cabre@metempsy.com
17313442Spau.cabre@metempsy.com    uint64_t frame = getFrame(tc);
17413442Spau.cabre@metempsy.com    StackId sid = StackId(sysi, frame);
17513444Spau.cabre@metempsy.com
17613442Spau.cabre@metempsy.com    // check if we need to link to the previous state machine
17713493Spau.cabre@metempsy.com    int flags = args[2];
17813627Sjavier.bueno@metempsy.com    if (flags & FL_LINK) {
17913627Sjavier.bueno@metempsy.com        if (smStack[sid].size()) {
18013493Spau.cabre@metempsy.com            int prev_smi = smStack[sid].back();
18113493Spau.cabre@metempsy.com            DPRINTF(Annotate, "Linking from %d to state machine %s(%d) [%#x]\n",
18213493Spau.cabre@metempsy.com                    prev_smi, sm, smi, args[1]);
18313493Spau.cabre@metempsy.com
18413493Spau.cabre@metempsy.com            if (lnMap[smi])
18513493Spau.cabre@metempsy.com                DPRINTF(Annotate, "LnMap already contains entry for %d of %d\n",
18613493Spau.cabre@metempsy.com                        smi, lnMap[smi]);
18713493Spau.cabre@metempsy.com            assert(lnMap[smi] == 0);
18813493Spau.cabre@metempsy.com            lnMap[smi] =  prev_smi;
18913493Spau.cabre@metempsy.com
19013493Spau.cabre@metempsy.com            add(OP_LINK, FL_NONE, tc->contextId(), prev_smi, smi);
19113493Spau.cabre@metempsy.com        } else {
19213493Spau.cabre@metempsy.com            DPRINTF(Annotate, "Not Linking to state machine %s(%d) [%#x]\n",
19313627Sjavier.bueno@metempsy.com                    sm, smi, args[1]);
19413627Sjavier.bueno@metempsy.com        }
19513627Sjavier.bueno@metempsy.com    }
19613627Sjavier.bueno@metempsy.com
19713627Sjavier.bueno@metempsy.com
19813627Sjavier.bueno@metempsy.com    smStack[sid].push_back(smi);
19913627Sjavier.bueno@metempsy.com
20013627Sjavier.bueno@metempsy.com    DPRINTF(Annotate, "Stack Now (%#X):\n", frame);
20113627Sjavier.bueno@metempsy.com    for (int x = smStack[sid].size()-1; x >= 0; x--)
20213627Sjavier.bueno@metempsy.com        DPRINTF(Annotate, "-- %d\n", smStack[sid][x]);
20313685Sjavier.bueno@metempsy.com
20413685Sjavier.bueno@metempsy.com    // reset the sw state exculsion to false
20513685Sjavier.bueno@metempsy.com    if (swExpl[sid])
20613685Sjavier.bueno@metempsy.com        swExpl[sid] = false;
20713685Sjavier.bueno@metempsy.com
20813685Sjavier.bueno@metempsy.com
20913685Sjavier.bueno@metempsy.com    Id id = Id(sm, frame);
21013685Sjavier.bueno@metempsy.com    if (scLinks[sysi-1][id]) {
21113685Sjavier.bueno@metempsy.com        AnnDataPtr an = scLinks[sysi-1][id];
21213685Sjavier.bueno@metempsy.com        scLinks[sysi-1].erase(id);
21313685Sjavier.bueno@metempsy.com        an->stq = smi;
21413685Sjavier.bueno@metempsy.com        an->dump = true;
21513685Sjavier.bueno@metempsy.com        DPRINTF(Annotate,
21613685Sjavier.bueno@metempsy.com                "Found prev unknown linking from %d to state machine %s(%d)\n",
21713685Sjavier.bueno@metempsy.com                an->sm, sm, smi);
21813685Sjavier.bueno@metempsy.com
21913685Sjavier.bueno@metempsy.com        if (lnMap[smi])
22013685Sjavier.bueno@metempsy.com            DPRINTF(Annotate, "LnMap already contains entry for %d of %d\n",
22113685Sjavier.bueno@metempsy.com                    smi, lnMap[smi]);
22213685Sjavier.bueno@metempsy.com        assert(lnMap[smi] == 0);
22313685Sjavier.bueno@metempsy.com        lnMap[smi] =  an->sm;
22413685Sjavier.bueno@metempsy.com    }
22513685Sjavier.bueno@metempsy.com
22613685Sjavier.bueno@metempsy.com    // add a new begin ifwe have that info
22713685Sjavier.bueno@metempsy.com    if (st != "") {
22813685Sjavier.bueno@metempsy.com        DPRINTF(Annotate, "st: %s smi: %d stCache.size %d\n", st,
22913685Sjavier.bueno@metempsy.com                smi, stCache.size());
23013685Sjavier.bueno@metempsy.com        int sti = getSt(sm, st);
23113685Sjavier.bueno@metempsy.com        lastState[smi] = sti;
23213685Sjavier.bueno@metempsy.com        add(OP_BEGIN, FL_NONE, tc->contextId(), smi, sti);
23313685Sjavier.bueno@metempsy.com    }
23413685Sjavier.bueno@metempsy.com}
23513685Sjavier.bueno@metempsy.com
23613685Sjavier.bueno@metempsy.comvoid
23713685Sjavier.bueno@metempsy.comCPA::swSmEnd(ThreadContext *tc)
23813685Sjavier.bueno@metempsy.com{
23913685Sjavier.bueno@metempsy.com    if (!enabled())
24013685Sjavier.bueno@metempsy.com        return;
24113685Sjavier.bueno@metempsy.com
24213685Sjavier.bueno@metempsy.com    Arguments args(tc);
24313685Sjavier.bueno@metempsy.com    char sm[50];
24413685Sjavier.bueno@metempsy.com    CopyStringOut(tc, sm, args[0], 50);
24513685Sjavier.bueno@metempsy.com    System *sys = tc->getSystemPtr();
24613685Sjavier.bueno@metempsy.com    doSwSmEnd(sys, tc->contextId(), sm, getFrame(tc));
24713685Sjavier.bueno@metempsy.com}
24813685Sjavier.bueno@metempsy.com
24913685Sjavier.bueno@metempsy.comvoid
25013685Sjavier.bueno@metempsy.comCPA::doSwSmEnd(System *sys, int cpuid, string sm, uint64_t frame)
25113685Sjavier.bueno@metempsy.com{
25213685Sjavier.bueno@metempsy.com    int sysi = getSys(sys);
25313685Sjavier.bueno@metempsy.com    StackId sid = StackId(sysi, frame);
25413685Sjavier.bueno@metempsy.com
25513685Sjavier.bueno@metempsy.com
25613685Sjavier.bueno@metempsy.com    // reset the sw state exculsion to false
25713685Sjavier.bueno@metempsy.com    if (swExpl[sid])
25813685Sjavier.bueno@metempsy.com        swExpl[sid] = false;
25913685Sjavier.bueno@metempsy.com
26013685Sjavier.bueno@metempsy.com
26113685Sjavier.bueno@metempsy.com    int smib = smStack[sid].back();
26213685Sjavier.bueno@metempsy.com    StringWrap name(sys->name());
26313685Sjavier.bueno@metempsy.com    DPRINTF(Annotate, "Ending machine: %s[%d, %#x] (%d?)\n", sm, sysi,
26413685Sjavier.bueno@metempsy.com            frame, smib);
26513685Sjavier.bueno@metempsy.com
26613685Sjavier.bueno@metempsy.com    if (!smStack[sid].size() || smMap[smib-1].second.first != sm) {
26713685Sjavier.bueno@metempsy.com        DPRINTF(Annotate, "State Machine not unwinding correctly. sid: %d, %#x"
26813685Sjavier.bueno@metempsy.com                " top of stack: %s Current Stack:\n",
26913685Sjavier.bueno@metempsy.com                sysi, frame, smMap[smib-1].second.first);
27013685Sjavier.bueno@metempsy.com        for (int x = smStack[sid].size()-1; x >= 0; x--)
27113685Sjavier.bueno@metempsy.com            DPRINTF(Annotate, "-- %d\n", smStack[sid][x]);
27213685Sjavier.bueno@metempsy.com        DPRINTF(Annotate, "Ending machine: %s; end stack: %s\n", sm,
27313685Sjavier.bueno@metempsy.com                smMap[smib-1].second.first);
27413685Sjavier.bueno@metempsy.com
27513685Sjavier.bueno@metempsy.com        warn("State machine stack not unwinding correctly at %d\n", curTick);
27613685Sjavier.bueno@metempsy.com    } else {
27713685Sjavier.bueno@metempsy.com        DPRINTF(Annotate,
27813685Sjavier.bueno@metempsy.com                "State machine ending:%s sysi:%d id:%#x back:%d getSm:%d\n",
27913685Sjavier.bueno@metempsy.com                sm, sysi, smMap[smib-1].second.second, smStack[sid].back(),
28013685Sjavier.bueno@metempsy.com                getSm(sysi, sm, smMap[smib-1].second.second));
28113685Sjavier.bueno@metempsy.com        assert(getSm(sysi, sm, smMap[smib-1].second.second) ==
28213685Sjavier.bueno@metempsy.com                smStack[sid].back());
28313685Sjavier.bueno@metempsy.com
28413685Sjavier.bueno@metempsy.com        int smi = smStack[sid].back();
28513685Sjavier.bueno@metempsy.com        smStack[sid].pop_back();
28613685Sjavier.bueno@metempsy.com
28713685Sjavier.bueno@metempsy.com        if (lnMap[smi]) {
28813685Sjavier.bueno@metempsy.com            DPRINTF(Annotate, "Linking %d back to %d\n", smi, lnMap[smi]);
28913685Sjavier.bueno@metempsy.com            add(OP_LINK, FL_NONE, cpuid, smi, lnMap[smi]);
29013685Sjavier.bueno@metempsy.com            lnMap.erase(smi);
29113685Sjavier.bueno@metempsy.com        }
29213685Sjavier.bueno@metempsy.com
29313627Sjavier.bueno@metempsy.com        if (smStack[sid].size()) {
29413627Sjavier.bueno@metempsy.com            add(OP_BEGIN, FL_NONE, cpuid, smi, lastState[smi]);
29513627Sjavier.bueno@metempsy.com        }
29613627Sjavier.bueno@metempsy.com
29713627Sjavier.bueno@metempsy.com        DPRINTF(Annotate, "Stack Now:\n");
29813627Sjavier.bueno@metempsy.com        for (int x = smStack[sid].size()-1; x >= 0; x--)
29913627Sjavier.bueno@metempsy.com            DPRINTF(Annotate, "-- %d\n", smStack[sid][x]);
30013627Sjavier.bueno@metempsy.com    }
30113627Sjavier.bueno@metempsy.com}
30213627Sjavier.bueno@metempsy.com
30313627Sjavier.bueno@metempsy.com
30413685Sjavier.bueno@metempsy.comvoid
30513627Sjavier.bueno@metempsy.comCPA::swExplictBegin(ThreadContext *tc)
30613685Sjavier.bueno@metempsy.com{
30713685Sjavier.bueno@metempsy.com    if (!enabled())
30813685Sjavier.bueno@metempsy.com        return;
30913685Sjavier.bueno@metempsy.com
31013685Sjavier.bueno@metempsy.com    Arguments args(tc);
31113685Sjavier.bueno@metempsy.com    char st[50];
31213685Sjavier.bueno@metempsy.com    CopyStringOut(tc, st, args[1], 50);
31313685Sjavier.bueno@metempsy.com
31413685Sjavier.bueno@metempsy.com    StringWrap name(tc->getSystemPtr()->name());
31513685Sjavier.bueno@metempsy.com    DPRINTF(Annotate, "Explict begin of state %s\n", st);
31613685Sjavier.bueno@metempsy.com    uint32_t flags = args[0];
31713685Sjavier.bueno@metempsy.com    if (flags & FL_BAD)
31813685Sjavier.bueno@metempsy.com        warn("BAD state encountered: at cycle %d: %s\n", curTick, st);
31913685Sjavier.bueno@metempsy.com    swBegin(tc->getSystemPtr(), tc->contextId(), st, getFrame(tc), true, args[0]);
32013685Sjavier.bueno@metempsy.com}
32113685Sjavier.bueno@metempsy.com
32213685Sjavier.bueno@metempsy.comvoid
32313685Sjavier.bueno@metempsy.comCPA::swAutoBegin(ThreadContext *tc, Addr next_pc)
32413685Sjavier.bueno@metempsy.com{
32513685Sjavier.bueno@metempsy.com    if (!enabled())
32613685Sjavier.bueno@metempsy.com        return;
32713685Sjavier.bueno@metempsy.com
32813685Sjavier.bueno@metempsy.com    string sym;
32913685Sjavier.bueno@metempsy.com    Addr sym_addr = 0;
33013685Sjavier.bueno@metempsy.com    SymbolTable *symtab = NULL;
33113685Sjavier.bueno@metempsy.com
33213685Sjavier.bueno@metempsy.com
33313685Sjavier.bueno@metempsy.com    if (!TheISA::inUserMode(tc)) {
33413685Sjavier.bueno@metempsy.com        debugSymbolTable->findNearestSymbol(next_pc, sym, sym_addr);
33513685Sjavier.bueno@metempsy.com        symtab = debugSymbolTable;
33613685Sjavier.bueno@metempsy.com    } else {
33713685Sjavier.bueno@metempsy.com        Linux::ThreadInfo ti(tc);
33813685Sjavier.bueno@metempsy.com        string app = ti.curTaskName();
33913685Sjavier.bueno@metempsy.com        if (userApp.count(app))
34013685Sjavier.bueno@metempsy.com            userApp[app]->findNearestSymbol(next_pc, sym, sym_addr);
34113685Sjavier.bueno@metempsy.com    }
34213685Sjavier.bueno@metempsy.com
34313685Sjavier.bueno@metempsy.com    if (sym_addr)
34413685Sjavier.bueno@metempsy.com        swBegin(tc->getSystemPtr(), tc->contextId(), sym, getFrame(tc));
34513685Sjavier.bueno@metempsy.com}
34613685Sjavier.bueno@metempsy.com
34713685Sjavier.bueno@metempsy.comvoid
34813685Sjavier.bueno@metempsy.comCPA::swBegin(System *sys, int cpuid, std::string st, uint64_t frame, bool expl,
34913685Sjavier.bueno@metempsy.com        int flags)
35013685Sjavier.bueno@metempsy.com{
35113685Sjavier.bueno@metempsy.com    int x = 0;
35213685Sjavier.bueno@metempsy.com    int len;
35313685Sjavier.bueno@metempsy.com    while (ignoreSymbols[x].len)
35413685Sjavier.bueno@metempsy.com    {
35513685Sjavier.bueno@metempsy.com        len = ignoreSymbols[x].len;
35613685Sjavier.bueno@metempsy.com        if (!st.compare(0,len, ignoreSymbols[x].symbol, len))
35713685Sjavier.bueno@metempsy.com            return;
35813685Sjavier.bueno@metempsy.com        x++;
35913685Sjavier.bueno@metempsy.com    }
36013685Sjavier.bueno@metempsy.com
36113685Sjavier.bueno@metempsy.com    int sysi = getSys(sys);
36213685Sjavier.bueno@metempsy.com    StackId sid = StackId(sysi, frame);
36313685Sjavier.bueno@metempsy.com    // if expl is true suspend symbol table based states
36413685Sjavier.bueno@metempsy.com    if (!smStack[sid].size())
36513685Sjavier.bueno@metempsy.com        return;
36613685Sjavier.bueno@metempsy.com    if (!expl && swExpl[sid])
36713685Sjavier.bueno@metempsy.com        return;
36813685Sjavier.bueno@metempsy.com    if (expl)
36913685Sjavier.bueno@metempsy.com        swExpl[sid] = true;
37013685Sjavier.bueno@metempsy.com    DPRINTFS(AnnotateVerbose, sys, "SwBegin: %s sysi: %d\n", st, sysi);
37113685Sjavier.bueno@metempsy.com    int smi = smStack[sid].back();
37213685Sjavier.bueno@metempsy.com    int sti = getSt(smMap[smi-1].second.first, st);
37313685Sjavier.bueno@metempsy.com    if (lastState[smi] != sti) {
37413685Sjavier.bueno@metempsy.com        lastState[smi] = sti;
37513685Sjavier.bueno@metempsy.com        add(OP_BEGIN, flags, cpuid, smi, sti);
37613685Sjavier.bueno@metempsy.com    }
37713685Sjavier.bueno@metempsy.com}
37813685Sjavier.bueno@metempsy.com
37913685Sjavier.bueno@metempsy.comvoid
38013685Sjavier.bueno@metempsy.comCPA::swEnd(ThreadContext *tc)
38113685Sjavier.bueno@metempsy.com{
38213685Sjavier.bueno@metempsy.com    if (!enabled())
38313685Sjavier.bueno@metempsy.com        return;
38413685Sjavier.bueno@metempsy.com
38513685Sjavier.bueno@metempsy.com    std::string st;
38613685Sjavier.bueno@metempsy.com    Addr junk;
38713685Sjavier.bueno@metempsy.com    if (!TheISA::inUserMode(tc))
38813685Sjavier.bueno@metempsy.com        debugSymbolTable->findNearestSymbol(
38913685Sjavier.bueno@metempsy.com            tc->readIntReg(ReturnAddressReg), st, junk);
39013685Sjavier.bueno@metempsy.com    System *sys = tc->getSystemPtr();
39113685Sjavier.bueno@metempsy.com    StringWrap name(sys->name());
39213685Sjavier.bueno@metempsy.com
39313685Sjavier.bueno@metempsy.com    int sysi = getSys(sys);
39413685Sjavier.bueno@metempsy.com    StackId sid = StackId(sysi, getFrame(tc));
39513685Sjavier.bueno@metempsy.com    if (!smStack[sid].size()) {
39613685Sjavier.bueno@metempsy.com        DPRINTF(Annotate, "Explict end of State: %s IGNORED\n",  st);
39713685Sjavier.bueno@metempsy.com        return;
39813685Sjavier.bueno@metempsy.com    }
39913685Sjavier.bueno@metempsy.com    DPRINTF(Annotate, "Explict end of State: %s\n",  st);
40013685Sjavier.bueno@metempsy.com    // return back to symbol table based states
40113685Sjavier.bueno@metempsy.com    swExpl[sid] = false;
40213685Sjavier.bueno@metempsy.com    int smi = smStack[sid].back();
40313685Sjavier.bueno@metempsy.com    if (st != "") {
40413685Sjavier.bueno@metempsy.com        int sti = getSt(smMap[smi-1].second.first, st);
40513685Sjavier.bueno@metempsy.com        lastState[smi] = sti;
40613685Sjavier.bueno@metempsy.com        add(OP_BEGIN, FL_NONE, tc->contextId(), smi, sti);
40713685Sjavier.bueno@metempsy.com    }
40813685Sjavier.bueno@metempsy.com}
40913685Sjavier.bueno@metempsy.com
41013685Sjavier.bueno@metempsy.comvoid
41113685Sjavier.bueno@metempsy.comCPA::swQ(ThreadContext *tc)
41213685Sjavier.bueno@metempsy.com{
41313685Sjavier.bueno@metempsy.com    if (!enabled())
41413685Sjavier.bueno@metempsy.com        return;
41513685Sjavier.bueno@metempsy.com
41613685Sjavier.bueno@metempsy.com    char q[50];
41713685Sjavier.bueno@metempsy.com    Arguments args(tc);
41813685Sjavier.bueno@metempsy.com    uint64_t id = args[0];
41913685Sjavier.bueno@metempsy.com    CopyStringOut(tc, q, args[1], 50);
42013685Sjavier.bueno@metempsy.com    int32_t count = args[2];
42113685Sjavier.bueno@metempsy.com    System *sys = tc->getSystemPtr();
42213685Sjavier.bueno@metempsy.com
42313685Sjavier.bueno@metempsy.com    int sysi = getSys(sys);
42413685Sjavier.bueno@metempsy.com    StackId sid = StackId(sysi, getFrame(tc));
42513685Sjavier.bueno@metempsy.com    if (!smStack[sid].size())
42613685Sjavier.bueno@metempsy.com        return;
42713685Sjavier.bueno@metempsy.com    int smi = smStack[sid].back();
42813685Sjavier.bueno@metempsy.com    if (swExpl[sid])
42913685Sjavier.bueno@metempsy.com        swExpl[sid] = false;
43013685Sjavier.bueno@metempsy.com    int qi = getQ(sysi, q, id);
43113685Sjavier.bueno@metempsy.com    if (count == 0) {
43213685Sjavier.bueno@metempsy.com        //warn("Tried to queue 0 bytes in %s, ignoring\n", q);
43313685Sjavier.bueno@metempsy.com        return;
43413685Sjavier.bueno@metempsy.com    }
43513685Sjavier.bueno@metempsy.com    DPRINTFS(AnnotateQ, sys,
43613685Sjavier.bueno@metempsy.com            "swQ: %s[%#x] cur size %d %d bytes: %d adding: %d\n",
43713685Sjavier.bueno@metempsy.com            q, id, qSize[qi-1], qData[qi-1].size(), qBytes[qi-1], count);
43813685Sjavier.bueno@metempsy.com    doQ(sys, FL_NONE, tc->contextId(), smi, q, qi, count);
43913685Sjavier.bueno@metempsy.com}
44013685Sjavier.bueno@metempsy.com
44113685Sjavier.bueno@metempsy.comvoid
44213685Sjavier.bueno@metempsy.comCPA::swDq(ThreadContext *tc)
44313685Sjavier.bueno@metempsy.com{
44413685Sjavier.bueno@metempsy.com    if (!enabled())
44513685Sjavier.bueno@metempsy.com        return;
44613685Sjavier.bueno@metempsy.com
44713685Sjavier.bueno@metempsy.com    char q[50];
44813685Sjavier.bueno@metempsy.com    Arguments args(tc);
44913685Sjavier.bueno@metempsy.com    uint64_t id = args[0];
45013685Sjavier.bueno@metempsy.com    CopyStringOut(tc, q, args[1], 50);
45113685Sjavier.bueno@metempsy.com    int32_t count = args[2];
45213685Sjavier.bueno@metempsy.com    System *sys = tc->getSystemPtr();
45313685Sjavier.bueno@metempsy.com
45413685Sjavier.bueno@metempsy.com    int sysi = getSys(sys);
45513685Sjavier.bueno@metempsy.com    StackId sid = StackId(sysi, getFrame(tc));
45613685Sjavier.bueno@metempsy.com    if (!smStack[sid].size())
45713685Sjavier.bueno@metempsy.com        return;
45813685Sjavier.bueno@metempsy.com    int smi = smStack[sid].back();
45913685Sjavier.bueno@metempsy.com    int qi = getQ(sysi, q, id);
46013685Sjavier.bueno@metempsy.com    if (swExpl[sid])
46113685Sjavier.bueno@metempsy.com        swExpl[sid] = false;
46213685Sjavier.bueno@metempsy.com    DPRINTFS(AnnotateQ, sys,
46313685Sjavier.bueno@metempsy.com            "swDq: %s[%#x] cur size %d %d bytes: %d removing: %d\n",
46413685Sjavier.bueno@metempsy.com            q, id, qSize[qi-1], qData[qi-1].size(), qBytes[qi-1], count);
46513685Sjavier.bueno@metempsy.com    assert(count != 0);
46613685Sjavier.bueno@metempsy.com
46713685Sjavier.bueno@metempsy.com    doDq(sys, FL_NONE, tc->contextId(), smi, q, qi, count);
46813685Sjavier.bueno@metempsy.com}
46913685Sjavier.bueno@metempsy.com
47013685Sjavier.bueno@metempsy.comvoid
47113685Sjavier.bueno@metempsy.comCPA::swPq(ThreadContext *tc)
47213685Sjavier.bueno@metempsy.com{
47313685Sjavier.bueno@metempsy.com    if (!enabled())
47413685Sjavier.bueno@metempsy.com        return;
47513685Sjavier.bueno@metempsy.com
47613685Sjavier.bueno@metempsy.com    char q[50];
47713685Sjavier.bueno@metempsy.com    Arguments args(tc);
47814034Sjavier.bueno@metempsy.com    uint64_t id = args[0];
47914034Sjavier.bueno@metempsy.com    CopyStringOut(tc, q, args[1], 50);
48014034Sjavier.bueno@metempsy.com    System *sys = tc->getSystemPtr();
48114034Sjavier.bueno@metempsy.com    int32_t count = args[2];
48214034Sjavier.bueno@metempsy.com
48314034Sjavier.bueno@metempsy.com    int sysi = getSys(sys);
48414034Sjavier.bueno@metempsy.com    StackId sid = StackId(sysi, getFrame(tc));
48514034Sjavier.bueno@metempsy.com    if (!smStack[sid].size())
48614034Sjavier.bueno@metempsy.com        return;
48714034Sjavier.bueno@metempsy.com    int smi = smStack[sid].back();
48814034Sjavier.bueno@metempsy.com    int qi = getQ(sysi, q, id);
48914034Sjavier.bueno@metempsy.com    if (swExpl[sid])
49014034Sjavier.bueno@metempsy.com        swExpl[sid] = false;
49114034Sjavier.bueno@metempsy.com    DPRINTFS(AnnotateQ, sys,
49214034Sjavier.bueno@metempsy.com            "swPq: %s [%#x] cur size %d %d bytes: %d peeking: %d\n",
49314034Sjavier.bueno@metempsy.com            q, id, qSize[qi-1], qData[qi-1].size(), qBytes[qi-1], count);
49414034Sjavier.bueno@metempsy.com
49514034Sjavier.bueno@metempsy.com    assert(count != 0);
49614034Sjavier.bueno@metempsy.com    if (qBytes[qi-1] < count) {
49714034Sjavier.bueno@metempsy.com        dump(true);
49814034Sjavier.bueno@metempsy.com        dumpKey();
49914034Sjavier.bueno@metempsy.com        fatal("Queue %s peeking with not enough bytes available in queue!\n", q);
50014034Sjavier.bueno@metempsy.com    }
50114034Sjavier.bueno@metempsy.com
50214034Sjavier.bueno@metempsy.com    add(OP_PEEK, FL_NONE, tc->contextId(), smi, qi, count);
50314034Sjavier.bueno@metempsy.com}
50414034Sjavier.bueno@metempsy.com
50514034Sjavier.bueno@metempsy.comvoid
50614034Sjavier.bueno@metempsy.comCPA::swRq(ThreadContext *tc)
50714034Sjavier.bueno@metempsy.com{
50814034Sjavier.bueno@metempsy.com    if (!enabled())
50914034Sjavier.bueno@metempsy.com        return;
51014034Sjavier.bueno@metempsy.com
51114034Sjavier.bueno@metempsy.com    char q[50];
51214034Sjavier.bueno@metempsy.com    Arguments args(tc);
51314034Sjavier.bueno@metempsy.com    uint64_t id = args[0];
51414034Sjavier.bueno@metempsy.com    CopyStringOut(tc, q, args[1], 50);
51514034Sjavier.bueno@metempsy.com    System *sys = tc->getSystemPtr();
51614034Sjavier.bueno@metempsy.com    int32_t count = args[2];
51714034Sjavier.bueno@metempsy.com
51814034Sjavier.bueno@metempsy.com    int sysi = getSys(sys);
51914034Sjavier.bueno@metempsy.com    StackId sid = StackId(sysi, getFrame(tc));
52014034Sjavier.bueno@metempsy.com    if (!smStack[sid].size())
52114034Sjavier.bueno@metempsy.com        return;
52214034Sjavier.bueno@metempsy.com    int smi = smStack[sid].back();
52314034Sjavier.bueno@metempsy.com    int qi = getQ(sysi, q, id);
52414034Sjavier.bueno@metempsy.com    if (swExpl[sid])
52514034Sjavier.bueno@metempsy.com        swExpl[sid] = false;
52614034Sjavier.bueno@metempsy.com    DPRINTFS(AnnotateQ, sys,
52714034Sjavier.bueno@metempsy.com            "swRq: %s [%#x] cur size %d %d bytes: %d reserve: %d\n",
52814034Sjavier.bueno@metempsy.com            q, id, qSize[qi-1], qData[qi-1].size(), qBytes[qi-1], count);
52914034Sjavier.bueno@metempsy.com
53014034Sjavier.bueno@metempsy.com    assert(count != 0);
53114034Sjavier.bueno@metempsy.com
53214034Sjavier.bueno@metempsy.com    add(OP_RESERVE, FL_NONE, tc->contextId(), smi, qi, count);
53314034Sjavier.bueno@metempsy.com}
53414034Sjavier.bueno@metempsy.com
53514034Sjavier.bueno@metempsy.com
53614034Sjavier.bueno@metempsy.comvoid
53714034Sjavier.bueno@metempsy.comCPA::swWf(ThreadContext *tc)
53814034Sjavier.bueno@metempsy.com{
53914034Sjavier.bueno@metempsy.com    if (!enabled())
54014034Sjavier.bueno@metempsy.com        return;
54114034Sjavier.bueno@metempsy.com
54214034Sjavier.bueno@metempsy.com    char q[50];
54314034Sjavier.bueno@metempsy.com    Arguments args(tc);
54414034Sjavier.bueno@metempsy.com    uint64_t id = args[0];
54514034Sjavier.bueno@metempsy.com    CopyStringOut(tc, q, args[1], 50);
54614034Sjavier.bueno@metempsy.com    System *sys = tc->getSystemPtr();
54714034Sjavier.bueno@metempsy.com    int32_t count = args[3];
54814034Sjavier.bueno@metempsy.com
54914034Sjavier.bueno@metempsy.com    int sysi = getSys(sys);
55014034Sjavier.bueno@metempsy.com    StackId sid = StackId(sysi, getFrame(tc));
55114034Sjavier.bueno@metempsy.com    if (!smStack[sid].size())
55214034Sjavier.bueno@metempsy.com        return;
55314034Sjavier.bueno@metempsy.com    int smi = smStack[sid].back();
55414034Sjavier.bueno@metempsy.com    int qi = getQ(sysi, q, id);
55514034Sjavier.bueno@metempsy.com    add(OP_WAIT_FULL, FL_NONE, tc->contextId(), smi, qi, count);
55614034Sjavier.bueno@metempsy.com
55714034Sjavier.bueno@metempsy.com    if (!!args[2]) {
55814034Sjavier.bueno@metempsy.com        char sm[50];
55914034Sjavier.bueno@metempsy.com        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