cp_annotate.hh revision 5952:c1ee8282291d
111482Sandreas.sandberg@arm.com/*
211482Sandreas.sandberg@arm.com * Copyright (c) 2006-2009 The Regents of The University of Michigan
311482Sandreas.sandberg@arm.com * All rights reserved.
411482Sandreas.sandberg@arm.com *
511482Sandreas.sandberg@arm.com * Redistribution and use in source and binary forms, with or without
611482Sandreas.sandberg@arm.com * modification, are permitted provided that the following conditions are
711482Sandreas.sandberg@arm.com * met: redistributions of source code must retain the above copyright
811482Sandreas.sandberg@arm.com * notice, this list of conditions and the following disclaimer;
911482Sandreas.sandberg@arm.com * redistributions in binary form must reproduce the above copyright
1011482Sandreas.sandberg@arm.com * notice, this list of conditions and the following disclaimer in the
1111482Sandreas.sandberg@arm.com * documentation and/or other materials provided with the distribution;
1211482Sandreas.sandberg@arm.com * neither the name of the copyright holders nor the names of its
1311482Sandreas.sandberg@arm.com * contributors may be used to endorse or promote products derived from
1411482Sandreas.sandberg@arm.com * this software without specific prior written permission.
1511482Sandreas.sandberg@arm.com *
1611482Sandreas.sandberg@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1711482Sandreas.sandberg@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1811482Sandreas.sandberg@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1911482Sandreas.sandberg@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2011482Sandreas.sandberg@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2111482Sandreas.sandberg@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2211482Sandreas.sandberg@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2311482Sandreas.sandberg@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2411482Sandreas.sandberg@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2511482Sandreas.sandberg@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2611482Sandreas.sandberg@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2711482Sandreas.sandberg@arm.com *
2811482Sandreas.sandberg@arm.com * Authors: Ali Saidi
2911482Sandreas.sandberg@arm.com */
3011482Sandreas.sandberg@arm.com
3111482Sandreas.sandberg@arm.com#ifndef __BASE__CP_ANNOTATE_HH__
3211482Sandreas.sandberg@arm.com#define __BASE__CP_ANNOTATE_HH__
3311482Sandreas.sandberg@arm.com
3411482Sandreas.sandberg@arm.com#include "base/loader/symtab.hh"
3511482Sandreas.sandberg@arm.com#include "config/cp_annotate.hh"
3611482Sandreas.sandberg@arm.com#include "sim/host.hh"
3711482Sandreas.sandberg@arm.com#include "sim/serialize.hh"
3811482Sandreas.sandberg@arm.com#include "sim/startup.hh"
3911482Sandreas.sandberg@arm.com#include "sim/system.hh"
4011482Sandreas.sandberg@arm.com
4111482Sandreas.sandberg@arm.com#include <string>
4211482Sandreas.sandberg@arm.com#include <list>
4311482Sandreas.sandberg@arm.com#include <vector>
4411482Sandreas.sandberg@arm.com#include <map>
4511482Sandreas.sandberg@arm.com#include "base/hashmap.hh"
4611482Sandreas.sandberg@arm.com#include "base/trace.hh"
4711482Sandreas.sandberg@arm.com#if CP_ANNOTATE
4811482Sandreas.sandberg@arm.com#include "params/CPA.hh"
4911482Sandreas.sandberg@arm.com#endif
5011482Sandreas.sandberg@arm.com
5111482Sandreas.sandberg@arm.comclass System;
5211482Sandreas.sandberg@arm.comclass ThreadContext;
5311482Sandreas.sandberg@arm.com
5411482Sandreas.sandberg@arm.com
5511482Sandreas.sandberg@arm.com#if !CP_ANNOTATE
5611482Sandreas.sandberg@arm.comclass CPA : SimObject
5711482Sandreas.sandberg@arm.com{
5811482Sandreas.sandberg@arm.com  public:
5911482Sandreas.sandberg@arm.com    enum flags {
6011482Sandreas.sandberg@arm.com        FL_NONE     = 0x00,
6111482Sandreas.sandberg@arm.com        FL_HW       = 0x01,
6211482Sandreas.sandberg@arm.com        FL_BAD      = 0x02,
6311482Sandreas.sandberg@arm.com        FL_QOPP     = 0x04,
6411482Sandreas.sandberg@arm.com        FL_WAIT     = 0x08,
6511482Sandreas.sandberg@arm.com        FL_LINK     = 0x10,
6611482Sandreas.sandberg@arm.com        FL_RESET    = 0x20
6711482Sandreas.sandberg@arm.com    };
6811482Sandreas.sandberg@arm.com
6911482Sandreas.sandberg@arm.com    static CPA *cpa()                                        { return NULL; }
7011482Sandreas.sandberg@arm.com    static bool available()                                 { return false; }
7111482Sandreas.sandberg@arm.com    bool enabled()                                          { return false; }
7211482Sandreas.sandberg@arm.com    void swSmBegin(ThreadContext *tc)                             { return; }
7311482Sandreas.sandberg@arm.com    void swSmEnd(ThreadContext *tc)                               { return; }
7411482Sandreas.sandberg@arm.com    void swExplictBegin(ThreadContext *tc)                        { return; }
7511482Sandreas.sandberg@arm.com    void swAutoBegin(ThreadContext *tc, Addr next_pc)             { return; }
7611482Sandreas.sandberg@arm.com    void swEnd(ThreadContext *tc)                                 { return; }
7711482Sandreas.sandberg@arm.com    void swQ(ThreadContext *tc)                                   { return; }
7811482Sandreas.sandberg@arm.com    void swDq(ThreadContext *tc)                                  { return; }
7911482Sandreas.sandberg@arm.com    void swPq(ThreadContext *tc)                                  { return; }
8011482Sandreas.sandberg@arm.com    void swRq(ThreadContext *tc)                                  { return; }
8111482Sandreas.sandberg@arm.com    void swWf(ThreadContext *tc)                                  { return; }
8211482Sandreas.sandberg@arm.com    void swWe(ThreadContext *tc)                                  { return; }
8311482Sandreas.sandberg@arm.com    void swSq(ThreadContext *tc)                                  { return; }
8411482Sandreas.sandberg@arm.com    void swAq(ThreadContext *tc)                                  { return; }
8511482Sandreas.sandberg@arm.com    void swLink(ThreadContext *tc)                                { return; }
8611482Sandreas.sandberg@arm.com    void swIdentify(ThreadContext *tc)                            { return; }
8711482Sandreas.sandberg@arm.com    uint64_t swGetId(ThreadContext *tc)                         { return 0; }
8811482Sandreas.sandberg@arm.com    void swSyscallLink(ThreadContext *tc)                         { return; }
8911482Sandreas.sandberg@arm.com    void hwBegin(flags f, System *sys, uint64_t frame, std::string sm,
9011482Sandreas.sandberg@arm.com                 std::string st)                                  { return; }
9111482Sandreas.sandberg@arm.com    void hwQ(flags f, System *sys, uint64_t frame, std::string sm,
9211482Sandreas.sandberg@arm.com             std::string q, uint64_t qid, System *q_sys = NULL,
9311482Sandreas.sandberg@arm.com             int32_t count = 1)                                   { return; }
9411482Sandreas.sandberg@arm.com    void hwDq(flags f, System *sys, uint64_t frame, std::string sm,
9511482Sandreas.sandberg@arm.com              std::string q, uint64_t qid, System *q_sys = NULL,
9611482Sandreas.sandberg@arm.com              int32_t count = 1)                                  { return; }
9711482Sandreas.sandberg@arm.com    void hwPq(flags f, System *sys, uint64_t frame, std::string sm,
9811482Sandreas.sandberg@arm.com              std::string q, uint64_t qid, System *q_sys = NULL,
9911482Sandreas.sandberg@arm.com              int32_t count = 1)                                  { return; }
10011482Sandreas.sandberg@arm.com    void hwRq(flags f, System *sys, uint64_t frame, std::string sm,
10111482Sandreas.sandberg@arm.com              std::string q, uint64_t qid, System *q_sys = NULL,
10211482Sandreas.sandberg@arm.com              int32_t count = 1)                                  { return; }
10311482Sandreas.sandberg@arm.com    void hwWf(flags f, System *sys, uint64_t frame, std::string sm,
10411482Sandreas.sandberg@arm.com              std::string q, uint64_t qid, System *q_sys = NULL,
10511482Sandreas.sandberg@arm.com              int32_t count = 1)                                  { return; }
10611482Sandreas.sandberg@arm.com    void hwWe(flags f, System *sys, uint64_t frame, std::string sm,
10711482Sandreas.sandberg@arm.com              std::string q, uint64_t qid, System *q_sys = NULL,
10811482Sandreas.sandberg@arm.com              int32_t count = 1)                                  { return; }
10911482Sandreas.sandberg@arm.com};
11011482Sandreas.sandberg@arm.com#else
11111482Sandreas.sandberg@arm.comclass CPA : SimObject
11211482Sandreas.sandberg@arm.com{
11311482Sandreas.sandberg@arm.com  public:
11411482Sandreas.sandberg@arm.com    typedef CPAParams Params;
11511482Sandreas.sandberg@arm.com
11611482Sandreas.sandberg@arm.com    /** The known operations that are written to the annotation output file. */
11711482Sandreas.sandberg@arm.com    enum ops {
11811482Sandreas.sandberg@arm.com        OP_BEGIN           = 0x01,
11911482Sandreas.sandberg@arm.com        OP_WAIT_EMPTY      = 0x02,
12011482Sandreas.sandberg@arm.com        OP_WAIT_FULL       = 0x03,
12111482Sandreas.sandberg@arm.com        OP_QUEUE           = 0x04,
12211482Sandreas.sandberg@arm.com        OP_DEQUEUE         = 0x05,
12311482Sandreas.sandberg@arm.com        OP_SIZE_QUEUE      = 0x08,
12411482Sandreas.sandberg@arm.com        OP_PEEK            = 0x09,
12511482Sandreas.sandberg@arm.com        OP_LINK            = 0x0A,
12611482Sandreas.sandberg@arm.com        OP_IDENT           = 0x0B,
12711482Sandreas.sandberg@arm.com        OP_RESERVE         = 0x0C
12811482Sandreas.sandberg@arm.com    };
12911482Sandreas.sandberg@arm.com
13011482Sandreas.sandberg@arm.com    /** Flags for the various options.*/
13111482Sandreas.sandberg@arm.com    enum flags {
13211482Sandreas.sandberg@arm.com        /* no flags */
13311482Sandreas.sandberg@arm.com        FL_NONE     = 0x00,
13411482Sandreas.sandberg@arm.com        /* operation was done on hardware */
13511482Sandreas.sandberg@arm.com        FL_HW       = 0x01,
13611482Sandreas.sandberg@arm.com        /* operation should cause a warning when encountered */
13711482Sandreas.sandberg@arm.com        FL_BAD      = 0x02,
13811482Sandreas.sandberg@arm.com        /* Queue like a stack, not a queue */
13911482Sandreas.sandberg@arm.com        FL_QOPP     = 0x04,
14011482Sandreas.sandberg@arm.com        /* Mark HW state as waiting for some non-resource constraint
14111482Sandreas.sandberg@arm.com         * (e.g. wait because SM only starts after 10 items are queued) */
14211482Sandreas.sandberg@arm.com        FL_WAIT     = 0x08,
14311482Sandreas.sandberg@arm.com        /* operation is linking to another state machine */
14411482Sandreas.sandberg@arm.com        FL_LINK     = 0x10,
14511482Sandreas.sandberg@arm.com        /* queue should be completely cleared/reset before executing this
14611482Sandreas.sandberg@arm.com         * operation */
14711482Sandreas.sandberg@arm.com        FL_RESET    = 0x20
14811482Sandreas.sandberg@arm.com    };
14911482Sandreas.sandberg@arm.com
15011482Sandreas.sandberg@arm.com
15111482Sandreas.sandberg@arm.com
15211482Sandreas.sandberg@arm.com  protected:
15311482Sandreas.sandberg@arm.com    const Params *
15411482Sandreas.sandberg@arm.com        params() const
15511482Sandreas.sandberg@arm.com        {
15611482Sandreas.sandberg@arm.com            return dynamic_cast<const Params *>(_params);
15711482Sandreas.sandberg@arm.com        }
15811482Sandreas.sandberg@arm.com
15911482Sandreas.sandberg@arm.com    /* struct that is written to the annotation output file */
16011482Sandreas.sandberg@arm.com    struct AnnotateData : public RefCounted {
16111482Sandreas.sandberg@arm.com
16211482Sandreas.sandberg@arm.com        Tick time;
16311482Sandreas.sandberg@arm.com        uint32_t data;
16411482Sandreas.sandberg@arm.com        uint32_t orig_data;
16511482Sandreas.sandberg@arm.com        uint16_t sm;
16611482Sandreas.sandberg@arm.com        uint16_t stq;
16711482Sandreas.sandberg@arm.com        uint8_t  op;
16811482Sandreas.sandberg@arm.com        uint8_t  flag;
16911482Sandreas.sandberg@arm.com        uint8_t  cpu;
17011482Sandreas.sandberg@arm.com        bool dump;
17111482Sandreas.sandberg@arm.com
17211482Sandreas.sandberg@arm.com        void serialize(std::ostream &os);
17311482Sandreas.sandberg@arm.com        void unserialize(Checkpoint *cp, const std::string &section);
17411482Sandreas.sandberg@arm.com
17511482Sandreas.sandberg@arm.com    };
17611482Sandreas.sandberg@arm.com
17711482Sandreas.sandberg@arm.com    typedef RefCountingPtr<AnnotateData> AnnDataPtr;
17811482Sandreas.sandberg@arm.com
17911482Sandreas.sandberg@arm.com    /* header for the annotation file */
18011482Sandreas.sandberg@arm.com    struct AnnotateHeader {
18111482Sandreas.sandberg@arm.com        uint64_t version;
18211482Sandreas.sandberg@arm.com        uint64_t num_recs;
18311482Sandreas.sandberg@arm.com        uint64_t key_off;
18411482Sandreas.sandberg@arm.com        uint64_t idx_off;
18511482Sandreas.sandberg@arm.com        uint32_t key_len;
18611482Sandreas.sandberg@arm.com        uint32_t idx_len;
18711482Sandreas.sandberg@arm.com    };
18811482Sandreas.sandberg@arm.com
18911482Sandreas.sandberg@arm.com    AnnotateHeader ah;
19011482Sandreas.sandberg@arm.com
19111482Sandreas.sandberg@arm.com    std::vector<uint64_t> annotateIdx;
19211482Sandreas.sandberg@arm.com
19311482Sandreas.sandberg@arm.com    // number of state machines encountered in the simulation
19411482Sandreas.sandberg@arm.com    int numSm;
19511482Sandreas.sandberg@arm.com    // number of states encountered in the simulation
19611482Sandreas.sandberg@arm.com    int numSmt;
19711482Sandreas.sandberg@arm.com    // number of states/queues for a given state machine/system respectively
19811482Sandreas.sandberg@arm.com    std::vector<int> numSt, numQ;
19911482Sandreas.sandberg@arm.com    // number of systems in the simulation
20011482Sandreas.sandberg@arm.com    int numSys;
20111482Sandreas.sandberg@arm.com    // number of queues in the state machine
20211482Sandreas.sandberg@arm.com    int numQs;
20311482Sandreas.sandberg@arm.com    // maximum connection id assigned so far
20411482Sandreas.sandberg@arm.com    uint64_t conId;
20511482Sandreas.sandberg@arm.com
20611482Sandreas.sandberg@arm.com    // Convert state strings into state ids
20711482Sandreas.sandberg@arm.com    typedef m5::hash_map<std::string, int> SCache;
20811482Sandreas.sandberg@arm.com    typedef std::vector<SCache> StCache;
20911482Sandreas.sandberg@arm.com
21011482Sandreas.sandberg@arm.com    // Convert sm and queue name,id into queue id
21111482Sandreas.sandberg@arm.com    typedef std::pair<std::string, uint64_t> Id;
21211482Sandreas.sandberg@arm.com    typedef m5::hash_map<Id, int> IdHCache;
21311482Sandreas.sandberg@arm.com    typedef std::vector<IdHCache> IdCache;
21411482Sandreas.sandberg@arm.com
21511482Sandreas.sandberg@arm.com    // Hold mapping of sm and queues to output python
21611482Sandreas.sandberg@arm.com    typedef std::vector<std::pair<int, Id> > IdMap;
21711482Sandreas.sandberg@arm.com
21811482Sandreas.sandberg@arm.com    // System pointer to name,id
21911482Sandreas.sandberg@arm.com    typedef std::map<System*, std::pair<std::string, int> > NameCache;
22011482Sandreas.sandberg@arm.com
22111482Sandreas.sandberg@arm.com    // array of systems each of which is a stack of running sm
22211482Sandreas.sandberg@arm.com    typedef std::pair<int, uint64_t> StackId;
22311482Sandreas.sandberg@arm.com    typedef std::map<StackId, std::vector<int> > SmStack;
22411482Sandreas.sandberg@arm.com
22511482Sandreas.sandberg@arm.com    // map of each context and if it's currently in explict state mode
22611482Sandreas.sandberg@arm.com    // states are not automatically updated until it leaves
22711482Sandreas.sandberg@arm.com    typedef std::map<StackId, bool> SwExpl;
22811482Sandreas.sandberg@arm.com
22911482Sandreas.sandberg@arm.com    typedef std::map<int,int> IMap;
23011482Sandreas.sandberg@arm.com    // List of annotate records have not been written/completed yet
23111482Sandreas.sandberg@arm.com    typedef std::list<AnnDataPtr> AnnotateList;
23211482Sandreas.sandberg@arm.com
23311482Sandreas.sandberg@arm.com    // Maintain link state information
23411482Sandreas.sandberg@arm.com    typedef std::map<int, int> LinkMap;
23511482Sandreas.sandberg@arm.com
23611482Sandreas.sandberg@arm.com    // SC Links
23711482Sandreas.sandberg@arm.com    typedef m5::hash_map<Id, AnnDataPtr> ScHCache;
23811482Sandreas.sandberg@arm.com    typedef std::vector<ScHCache> ScCache;
23911482Sandreas.sandberg@arm.com
24011482Sandreas.sandberg@arm.com
24111482Sandreas.sandberg@arm.com    AnnotateList data;
24211482Sandreas.sandberg@arm.com
24311482Sandreas.sandberg@arm.com    // vector indexed by queueid to find current number of elements and bytes
24411482Sandreas.sandberg@arm.com    std::vector<int> qSize;
24511482Sandreas.sandberg@arm.com    std::vector<int32_t> qBytes;
24611482Sandreas.sandberg@arm.com
24711482Sandreas.sandberg@arm.com
24811482Sandreas.sandberg@arm.com    // Turn state machine string into state machine id (small int)
24911482Sandreas.sandberg@arm.com    // Used for outputting key to convert id back into string
25011482Sandreas.sandberg@arm.com    SCache smtCache;
25111482Sandreas.sandberg@arm.com    // Turn state machine id, state name into state id (small int)
25211482Sandreas.sandberg@arm.com    StCache stCache;
25311482Sandreas.sandberg@arm.com    // turn system, queue, and queue identify into qid (small int)
25411482Sandreas.sandberg@arm.com    // turn system, state, and context into state machine id (small int)
25511482Sandreas.sandberg@arm.com    IdCache qCache, smCache;
25611482Sandreas.sandberg@arm.com    //Link state machines accross system calls
25711482Sandreas.sandberg@arm.com    ScCache scLinks;
25811482Sandreas.sandberg@arm.com    // System pointer to name,id
25911482Sandreas.sandberg@arm.com    NameCache nameCache;
26011482Sandreas.sandberg@arm.com    // Stack of state machines currently nested (should unwind correctly)
26111482Sandreas.sandberg@arm.com    SmStack smStack;
26211482Sandreas.sandberg@arm.com    // Map of currently outstanding links
26311482Sandreas.sandberg@arm.com    LinkMap lnMap;
26411482Sandreas.sandberg@arm.com    // If the state machine is currently exculding automatic changes
26511482Sandreas.sandberg@arm.com    SwExpl swExpl;
26611482Sandreas.sandberg@arm.com    // Last state that a given state machine was in
26711482Sandreas.sandberg@arm.com    IMap lastState;
26811482Sandreas.sandberg@arm.com    // Hold mapping of sm and queues to output python
26911482Sandreas.sandberg@arm.com    IdMap smMap, qMap;
27011482Sandreas.sandberg@arm.com    // Items still in queue, used for sanity checking
27111482Sandreas.sandberg@arm.com    std::vector<AnnotateList> qData;
27211482Sandreas.sandberg@arm.com
27311482Sandreas.sandberg@arm.com    void doDq(System *sys, int flags, int cpu, int sm, std::string q, int qi,
27411482Sandreas.sandberg@arm.com            int count);
27511482Sandreas.sandberg@arm.com    void doQ(System *sys, int flags, int cpu, int sm, std::string q, int qi,
27611482Sandreas.sandberg@arm.com            int count);
27711482Sandreas.sandberg@arm.com
27811482Sandreas.sandberg@arm.com    void doSwSmEnd(System *sys, int cpuid, std::string sm, uint64_t frame);
27911482Sandreas.sandberg@arm.com
28011482Sandreas.sandberg@arm.com    // Turn a system id, state machine string, state machine id into a small int
28111482Sandreas.sandberg@arm.com    // for annotation output
28211482Sandreas.sandberg@arm.com    int
28311482Sandreas.sandberg@arm.com    getSm(int sysi, std::string si, uint64_t id)
28411482Sandreas.sandberg@arm.com    {
28511482Sandreas.sandberg@arm.com        int smi;
28611482Sandreas.sandberg@arm.com        Id smid = Id(si, id);
28711482Sandreas.sandberg@arm.com
28811482Sandreas.sandberg@arm.com        smi = smCache[sysi-1][smid];
28911482Sandreas.sandberg@arm.com        if (smi == 0) {
29011482Sandreas.sandberg@arm.com            smCache[sysi-1][smid] = smi = ++numSm;
29111482Sandreas.sandberg@arm.com            assert(smi < 65535);
29211482Sandreas.sandberg@arm.com            smMap.push_back(std::make_pair<int, Id>(sysi, smid));
29311482Sandreas.sandberg@arm.com        }
29411482Sandreas.sandberg@arm.com        return smi;
29511482Sandreas.sandberg@arm.com    }
29611482Sandreas.sandberg@arm.com
29711482Sandreas.sandberg@arm.com    // Turn a state machine string, state string into a small int
29811482Sandreas.sandberg@arm.com    // for annotation output
29911482Sandreas.sandberg@arm.com    int
30011482Sandreas.sandberg@arm.com    getSt(std::string sm, std::string s)
30111482Sandreas.sandberg@arm.com    {
30211482Sandreas.sandberg@arm.com        int sti, smi;
30311482Sandreas.sandberg@arm.com
30411482Sandreas.sandberg@arm.com        smi = smtCache[sm];
30511482Sandreas.sandberg@arm.com        if (smi == 0)
30611482Sandreas.sandberg@arm.com           smi = smtCache[sm] = ++numSmt;
30711482Sandreas.sandberg@arm.com
30811482Sandreas.sandberg@arm.com        while (stCache.size() < smi) {
30911482Sandreas.sandberg@arm.com            //stCache.resize(sm);
31011482Sandreas.sandberg@arm.com            stCache.push_back(SCache());
31111482Sandreas.sandberg@arm.com            numSt.push_back(0);
31211482Sandreas.sandberg@arm.com        }
31311482Sandreas.sandberg@arm.com        //assert(stCache.size() == sm);
31411482Sandreas.sandberg@arm.com        //assert(numSt.size() == sm);
31511482Sandreas.sandberg@arm.com        sti = stCache[smi-1][s];
31611482Sandreas.sandberg@arm.com        if (sti == 0)
31711482Sandreas.sandberg@arm.com            stCache[smi-1][s] = sti = ++numSt[smi-1];
31811482Sandreas.sandberg@arm.com        return sti;
31911482Sandreas.sandberg@arm.com    }
32011482Sandreas.sandberg@arm.com
32111482Sandreas.sandberg@arm.com    // Turn state machine pointer into a smal int for annotation output
32211482Sandreas.sandberg@arm.com    int
32311482Sandreas.sandberg@arm.com    getSys(System *s)
32411482Sandreas.sandberg@arm.com    {
32511482Sandreas.sandberg@arm.com        NameCache::iterator i = nameCache.find(s);
32611482Sandreas.sandberg@arm.com        if (i == nameCache.end()) {
32711482Sandreas.sandberg@arm.com            nameCache[s] = std::make_pair<std::string,int>(s->name(), ++numSys);
32811482Sandreas.sandberg@arm.com            i = nameCache.find(s);
32911482Sandreas.sandberg@arm.com            // might need to put smstackid into map here, but perhaps not
33011482Sandreas.sandberg@arm.com            //smStack.push_back(std::vector<int>());
33111482Sandreas.sandberg@arm.com            //swExpl.push_back(false);
33211482Sandreas.sandberg@arm.com            numQ.push_back(0);
33311482Sandreas.sandberg@arm.com            qCache.push_back(IdHCache());
33411482Sandreas.sandberg@arm.com            smCache.push_back(IdHCache());
33511482Sandreas.sandberg@arm.com            scLinks.push_back(ScHCache());
33611482Sandreas.sandberg@arm.com        }
33711482Sandreas.sandberg@arm.com        return i->second.second;
33811482Sandreas.sandberg@arm.com    }
33911482Sandreas.sandberg@arm.com
34011482Sandreas.sandberg@arm.com    // Turn queue name, and queue context into small int for
34111482Sandreas.sandberg@arm.com    // annotation output
34211482Sandreas.sandberg@arm.com    int
34311482Sandreas.sandberg@arm.com    getQ(int sys, std::string q, uint64_t id)
344    {
345        int qi;
346        Id qid = Id(q, id);
347
348        qi = qCache[sys-1][qid];
349        if (qi == 0) {
350            qi = qCache[sys-1][qid] = ++numQs;
351            assert(qi < 65535);
352            qSize.push_back(0);
353            qBytes.push_back(0);
354            qData.push_back(AnnotateList());
355            numQ[sys-1]++;
356            qMap.push_back(std::make_pair<int, Id>(sys, qid));
357        }
358        return qi;
359    }
360
361    void swBegin(System *sys, int cpuid, std::string st, uint64_t frame,
362            bool expl = false, int flags = FL_NONE);
363
364    AnnDataPtr add(int t, int f, int c, int sm, int stq, int32_t data=0);
365
366    std::ostream *osbin;
367
368    bool _enabled;
369
370    /** Only allow one CPA object in a system. It doesn't make sense to have
371     * more that one per simulation because if a part of the system was
372     * important it would have annotations and queues, and with more than one
373     * object none of the sanity checking for queues will work. */
374    static bool exists;
375    static CPA *_cpa;
376
377
378    std::map<std::string, SymbolTable*> userApp;
379
380  public:
381    static CPA *cpa() { return _cpa; }
382    void swSmBegin(ThreadContext *tc);
383    void swSmEnd(ThreadContext *tc);
384    void swExplictBegin(ThreadContext *tc);
385    void swAutoBegin(ThreadContext *tc, Addr next_pc);
386    void swEnd(ThreadContext *tc);
387    void swQ(ThreadContext *tc);
388    void swDq(ThreadContext *tc);
389    void swPq(ThreadContext *tc);
390    void swRq(ThreadContext *tc);
391    void swWf(ThreadContext *tc);
392    void swWe(ThreadContext *tc);
393    void swSq(ThreadContext *tc);
394    void swAq(ThreadContext *tc);
395    void swLink(ThreadContext *tc);
396    void swIdentify(ThreadContext *tc);
397    uint64_t swGetId(ThreadContext *tc);
398    void swSyscallLink(ThreadContext *tc);
399
400    inline void hwBegin(flags f, System *sys, uint64_t frame, std::string sm,
401            std::string st)
402    {
403        if (!enabled())
404            return;
405
406        int sysi = getSys(sys);
407        int smi = getSm(sysi, sm, frame);
408        add(OP_BEGIN, FL_HW | f, 0, smi, getSt(sm, st));
409        if (f & FL_BAD)
410            warn("BAD state encountered: at cycle %d: %s\n", curTick, st);
411    }
412
413    inline void hwQ(flags f, System *sys, uint64_t frame, std::string sm,
414            std::string q, uint64_t qid, System *q_sys = NULL, int32_t count = 1)
415    {
416        if (!enabled())
417            return;
418
419        int sysi = getSys(sys);
420        int qi = getQ(q_sys ?  getSys(q_sys) : sysi, q, qid);
421        DPRINTFS(AnnotateQ, sys,
422                "hwQ: %s[%#x] cur size %d %d bytes: %d adding: %d\n",
423                q, qid, qSize[qi-1], qData[qi-1].size(), qBytes[qi-1], count);
424        doQ(sys, FL_HW | f, 0, getSm(sysi, sm, frame), q, qi, count);
425
426    }
427
428    inline void hwDq(flags f, System *sys, uint64_t frame, std::string sm,
429            std::string q, uint64_t qid, System *q_sys = NULL, int32_t count = 1)
430    {
431        if (!enabled())
432            return;
433
434        int sysi = getSys(sys);
435        int qi = getQ(q_sys ?  getSys(q_sys) : sysi, q, qid);
436        DPRINTFS(AnnotateQ, sys,
437                "hwDQ: %s[%#x] cur size %d %d bytes: %d removing: %d\n",
438                q, qid, qSize[qi-1], qData[qi-1].size(), qBytes[qi-1], count);
439        doDq(sys, FL_HW | f, 0, getSm(sysi,sm, frame), q, qi, count);
440    }
441
442    inline void hwPq(flags f, System *sys, uint64_t frame, std::string sm,
443            std::string q, uint64_t qid, System *q_sys = NULL, int32_t count = 1)
444    {
445        if (!enabled())
446            return;
447
448        int sysi = getSys(sys);
449        int qi = getQ(q_sys ?  getSys(q_sys) : sysi, q, qid);
450        DPRINTFS(AnnotateQ, sys,
451                "hwPQ: %s[%#x] cur size %d %d bytes: %d peeking: %d\n",
452                q, qid, qSize[qi-1], qData[qi-1].size(), qBytes[qi-1], count);
453        add(OP_PEEK, FL_HW | f, 0, getSm(sysi, sm, frame), qi, count);
454    }
455
456    inline void hwRq(flags f, System *sys, uint64_t frame, std::string sm,
457            std::string q, uint64_t qid, System *q_sys = NULL, int32_t count = 1)
458    {
459        if (!enabled())
460            return;
461
462        int sysi = getSys(sys);
463        int qi = getQ(q_sys ?  getSys(q_sys) : sysi, q, qid);
464        DPRINTFS(AnnotateQ, sys,
465                "hwRQ: %s[%#x] cur size %d %d bytes: %d reserving: %d\n",
466                q, qid, qSize[qi-1], qData[qi-1].size(), qBytes[qi-1], count);
467        add(OP_RESERVE, FL_HW | f, 0, getSm(sysi, sm, frame), qi, count);
468    }
469
470    inline void hwWf(flags f, System *sys, uint64_t frame, std::string sm,
471            std::string q, uint64_t qid, System *q_sys = NULL, int32_t count = 1)
472    {
473        if (!enabled())
474            return;
475
476        int sysi = getSys(sys);
477        int qi = getQ(q_sys ?  getSys(q_sys) : sysi, q, qid);
478        add(OP_WAIT_FULL, FL_HW | f, 0, getSm(sysi, sm, frame), qi, count);
479    }
480
481    inline void hwWe(flags f, System *sys, uint64_t frame, std::string sm,
482            std::string q, uint64_t qid, System *q_sys = NULL, int32_t count = 1)
483    {
484        if (!enabled())
485            return;
486
487        int sysi = getSys(sys);
488        int qi = getQ(q_sys ?  getSys(q_sys) : sysi, q, qid);
489        add(OP_WAIT_EMPTY, FL_HW | f, 0, getSm(sysi, sm, frame), qi, count);
490    }
491
492  public:
493    CPA(Params *p);
494    void startup();
495
496    // This code is ISA specific and will need to be changed
497    // if the annotation code is used for something other than Alpha
498    inline uint64_t getFrame(ThreadContext *tc)
499        { return (tc->readMiscRegNoEffect(TheISA::IPR_PALtemp23) &
500                ~ULL(0x3FFF)); }
501
502    static bool available()  { return true; }
503
504    bool
505    enabled()
506    {
507        if (!this)
508            return false;
509        return _enabled;
510    }
511
512    void dump(bool all);
513    void dumpKey();
514
515    void serialize(std::ostream &os);
516    void unserialize(Checkpoint *cp, const std::string &section);
517
518};
519#endif // !CP_ANNOTATE
520
521#endif //__BASE__CP_ANNOTATE_HH__
522
523