cp_annotate.hh revision 6214:1ec0ec8933ae
1298SN/A/*
22188SN/A * Copyright (c) 2006-2009 The Regents of The University of Michigan
3298SN/A * All rights reserved.
4298SN/A *
5298SN/A * Redistribution and use in source and binary forms, with or without
6298SN/A * modification, are permitted provided that the following conditions are
7298SN/A * met: redistributions of source code must retain the above copyright
8298SN/A * notice, this list of conditions and the following disclaimer;
9298SN/A * redistributions in binary form must reproduce the above copyright
10298SN/A * notice, this list of conditions and the following disclaimer in the
11298SN/A * documentation and/or other materials provided with the distribution;
12298SN/A * neither the name of the copyright holders nor the names of its
13298SN/A * contributors may be used to endorse or promote products derived from
14298SN/A * this software without specific prior written permission.
15298SN/A *
16298SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17298SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18298SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19298SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20298SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21298SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22298SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23298SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24298SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25298SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26298SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272665Ssaidi@eecs.umich.edu *
282665Ssaidi@eecs.umich.edu * Authors: Ali Saidi
29298SN/A */
30298SN/A
311642SN/A#ifndef __BASE__CP_ANNOTATE_HH__
32954SN/A#define __BASE__CP_ANNOTATE_HH__
33956SN/A
34956SN/A#include "base/loader/symtab.hh"
354078Sbinkertn@umich.edu#include "config/cp_annotate.hh"
36299SN/A#include "base/types.hh"
37299SN/A#include "sim/serialize.hh"
385529Snate@binkert.org#include "sim/startup.hh"
392170SN/A#include "sim/system.hh"
405882Snate@binkert.org
411717SN/A#include <string>
422680Sktlim@umich.edu#include <list>
432313SN/A#include <vector>
445529Snate@binkert.org#include <map>
453565Sgblack@eecs.umich.edu#include "base/hashmap.hh"
46298SN/A#include "base/trace.hh"
475606Snate@binkert.org#if CP_ANNOTATE
48298SN/A#include "params/CPA.hh"
49695SN/A#endif
50695SN/A
51954SN/Aclass System;
525780Ssteve.reinhardt@amd.comclass ThreadContext;
532080SN/A
545780Ssteve.reinhardt@amd.com
55298SN/A#if !CP_ANNOTATE
56299SN/Aclass CPA
571052SN/A{
58729SN/A  public:
592107SN/A    enum flags {
60298SN/A        FL_NONE     = 0x00,
615504Snate@binkert.org        FL_HW       = 0x01,
625504Snate@binkert.org        FL_BAD      = 0x02,
635780Ssteve.reinhardt@amd.com        FL_QOPP     = 0x04,
645780Ssteve.reinhardt@amd.com        FL_WAIT     = 0x08,
655504Snate@binkert.org        FL_LINK     = 0x10,
665504Snate@binkert.org        FL_RESET    = 0x20
67298SN/A    };
685504Snate@binkert.org
695504Snate@binkert.org    static CPA *cpa()                                        { return NULL; }
705504Snate@binkert.org    static bool available()                                 { return false; }
715504Snate@binkert.org    bool enabled()                                          { return false; }
725504Snate@binkert.org    void swSmBegin(ThreadContext *tc)                             { return; }
735504Snate@binkert.org    void swSmEnd(ThreadContext *tc)                               { return; }
745504Snate@binkert.org    void swExplictBegin(ThreadContext *tc)                        { return; }
755529Snate@binkert.org    void swAutoBegin(ThreadContext *tc, Addr next_pc)             { return; }
765504Snate@binkert.org    void swEnd(ThreadContext *tc)                                 { return; }
775504Snate@binkert.org    void swQ(ThreadContext *tc)                                   { return; }
785504Snate@binkert.org    void swDq(ThreadContext *tc)                                  { return; }
795504Snate@binkert.org    void swPq(ThreadContext *tc)                                  { return; }
805504Snate@binkert.org    void swRq(ThreadContext *tc)                                  { return; }
815504Snate@binkert.org    void swWf(ThreadContext *tc)                                  { return; }
825504Snate@binkert.org    void swWe(ThreadContext *tc)                                  { return; }
835504Snate@binkert.org    void swSq(ThreadContext *tc)                                  { return; }
845504Snate@binkert.org    void swAq(ThreadContext *tc)                                  { return; }
855504Snate@binkert.org    void swLink(ThreadContext *tc)                                { return; }
865504Snate@binkert.org    void swIdentify(ThreadContext *tc)                            { return; }
875504Snate@binkert.org    uint64_t swGetId(ThreadContext *tc)                         { return 0; }
885529Snate@binkert.org    void swSyscallLink(ThreadContext *tc)                         { return; }
895504Snate@binkert.org    void hwBegin(flags f, System *sys, uint64_t frame, std::string sm,
905504Snate@binkert.org                 std::string st)                                  { return; }
915504Snate@binkert.org    void hwQ(flags f, System *sys, uint64_t frame, std::string sm,
925504Snate@binkert.org             std::string q, uint64_t qid, System *q_sys = NULL,
935504Snate@binkert.org             int32_t count = 1)                                   { return; }
945504Snate@binkert.org    void hwDq(flags f, System *sys, uint64_t frame, std::string sm,
955606Snate@binkert.org              std::string q, uint64_t qid, System *q_sys = NULL,
965504Snate@binkert.org              int32_t count = 1)                                  { return; }
975504Snate@binkert.org    void hwPq(flags f, System *sys, uint64_t frame, std::string sm,
985504Snate@binkert.org              std::string q, uint64_t qid, System *q_sys = NULL,
995504Snate@binkert.org              int32_t count = 1)                                  { return; }
1005504Snate@binkert.org    void hwRq(flags f, System *sys, uint64_t frame, std::string sm,
1015504Snate@binkert.org              std::string q, uint64_t qid, System *q_sys = NULL,
1025504Snate@binkert.org              int32_t count = 1)                                  { return; }
1035504Snate@binkert.org    void hwWf(flags f, System *sys, uint64_t frame, std::string sm,
1045504Snate@binkert.org              std::string q, uint64_t qid, System *q_sys = NULL,
1055504Snate@binkert.org              int32_t count = 1)                                  { return; }
1065504Snate@binkert.org    void hwWe(flags f, System *sys, uint64_t frame, std::string sm,
1075504Snate@binkert.org              std::string q, uint64_t qid, System *q_sys = NULL,
1085529Snate@binkert.org              int32_t count = 1)                                  { return; }
1095504Snate@binkert.org};
1105504Snate@binkert.org#else
1115504Snate@binkert.orgclass CPA : SimObject
1125504Snate@binkert.org{
1135504Snate@binkert.org  public:
1145504Snate@binkert.org    typedef CPAParams Params;
1155606Snate@binkert.org
1165504Snate@binkert.org    /** The known operations that are written to the annotation output file. */
1175504Snate@binkert.org    enum ops {
1185504Snate@binkert.org        OP_BEGIN           = 0x01,
1195504Snate@binkert.org        OP_WAIT_EMPTY      = 0x02,
1205504Snate@binkert.org        OP_WAIT_FULL       = 0x03,
1215504Snate@binkert.org        OP_QUEUE           = 0x04,
1225504Snate@binkert.org        OP_DEQUEUE         = 0x05,
1235504Snate@binkert.org        OP_SIZE_QUEUE      = 0x08,
1245504Snate@binkert.org        OP_PEEK            = 0x09,
1255504Snate@binkert.org        OP_LINK            = 0x0A,
1265504Snate@binkert.org        OP_IDENT           = 0x0B,
1275504Snate@binkert.org        OP_RESERVE         = 0x0C
1285504Snate@binkert.org    };
1295504Snate@binkert.org
1305504Snate@binkert.org    /** Flags for the various options.*/
1315780Ssteve.reinhardt@amd.com    enum flags {
1325780Ssteve.reinhardt@amd.com        /* no flags */
1335741Snate@binkert.org        FL_NONE     = 0x00,
1345741Snate@binkert.org        /* operation was done on hardware */
1355741Snate@binkert.org        FL_HW       = 0x01,
1365741Snate@binkert.org        /* operation should cause a warning when encountered */
1375741Snate@binkert.org        FL_BAD      = 0x02,
1385741Snate@binkert.org        /* Queue like a stack, not a queue */
1395504Snate@binkert.org        FL_QOPP     = 0x04,
1405808Snate@binkert.org        /* Mark HW state as waiting for some non-resource constraint
1415808Snate@binkert.org         * (e.g. wait because SM only starts after 10 items are queued) */
1425808Snate@binkert.org        FL_WAIT     = 0x08,
1435808Snate@binkert.org        /* operation is linking to another state machine */
1445808Snate@binkert.org        FL_LINK     = 0x10,
1455808Snate@binkert.org        /* queue should be completely cleared/reset before executing this
1465808Snate@binkert.org         * operation */
1475808Snate@binkert.org        FL_RESET    = 0x20
1485808Snate@binkert.org    };
1495504Snate@binkert.org
1505504Snate@binkert.org
1515504Snate@binkert.org
1525606Snate@binkert.org  protected:
1535606Snate@binkert.org    const Params *
1545504Snate@binkert.org        params() const
1555504Snate@binkert.org        {
1565780Ssteve.reinhardt@amd.com            return dynamic_cast<const Params *>(_params);
1575780Ssteve.reinhardt@amd.com        }
1585504Snate@binkert.org
1595504Snate@binkert.org    /* struct that is written to the annotation output file */
1605504Snate@binkert.org    struct AnnotateData : public RefCounted {
1615504Snate@binkert.org
1625504Snate@binkert.org        Tick time;
1635504Snate@binkert.org        uint32_t data;
164711SN/A        uint32_t orig_data;
165711SN/A        uint16_t sm;
1665504Snate@binkert.org        uint16_t stq;
1675504Snate@binkert.org        uint8_t  op;
168310SN/A        uint8_t  flag;
1695504Snate@binkert.org        uint8_t  cpu;
1705504Snate@binkert.org        bool dump;
1713373Sstever@eecs.umich.edu
1725504Snate@binkert.org        void serialize(std::ostream &os);
1735504Snate@binkert.org        void unserialize(Checkpoint *cp, const std::string &section);
1745504Snate@binkert.org
1755504Snate@binkert.org    };
1765504Snate@binkert.org
1775504Snate@binkert.org    typedef RefCountingPtr<AnnotateData> AnnDataPtr;
1785504Snate@binkert.org
1795504Snate@binkert.org    /* header for the annotation file */
1805504Snate@binkert.org    struct AnnotateHeader {
1815504Snate@binkert.org        uint64_t version;
1825504Snate@binkert.org        uint64_t num_recs;
1835504Snate@binkert.org        uint64_t key_off;
1845504Snate@binkert.org        uint64_t idx_off;
1855504Snate@binkert.org        uint32_t key_len;
1865504Snate@binkert.org        uint32_t idx_len;
1875504Snate@binkert.org    };
1885504Snate@binkert.org
1895504Snate@binkert.org    AnnotateHeader ah;
1905504Snate@binkert.org
1915504Snate@binkert.org    std::vector<uint64_t> annotateIdx;
1925504Snate@binkert.org
1935504Snate@binkert.org    // number of state machines encountered in the simulation
1945504Snate@binkert.org    int numSm;
1955504Snate@binkert.org    // number of states encountered in the simulation
1965504Snate@binkert.org    int numSmt;
1975504Snate@binkert.org    // number of states/queues for a given state machine/system respectively
1985504Snate@binkert.org    std::vector<int> numSt, numQ;
1995504Snate@binkert.org    // number of systems in the simulation
2005504Snate@binkert.org    int numSys;
2015504Snate@binkert.org    // number of queues in the state machine
2025504Snate@binkert.org    int numQs;
2035504Snate@binkert.org    // maximum connection id assigned so far
2045504Snate@binkert.org    uint64_t conId;
2055504Snate@binkert.org
2065504Snate@binkert.org    // Convert state strings into state ids
2075780Ssteve.reinhardt@amd.com    typedef m5::hash_map<std::string, int> SCache;
2085780Ssteve.reinhardt@amd.com    typedef std::vector<SCache> StCache;
2095780Ssteve.reinhardt@amd.com
2105780Ssteve.reinhardt@amd.com    // Convert sm and queue name,id into queue id
2115780Ssteve.reinhardt@amd.com    typedef std::pair<std::string, uint64_t> Id;
2125780Ssteve.reinhardt@amd.com    typedef m5::hash_map<Id, int> IdHCache;
2135780Ssteve.reinhardt@amd.com    typedef std::vector<IdHCache> IdCache;
2145780Ssteve.reinhardt@amd.com
2155780Ssteve.reinhardt@amd.com    // Hold mapping of sm and queues to output python
2165952Ssaidi@eecs.umich.edu    typedef std::vector<std::pair<int, Id> > IdMap;
2175780Ssteve.reinhardt@amd.com
2185780Ssteve.reinhardt@amd.com    // System pointer to name,id
2195780Ssteve.reinhardt@amd.com    typedef std::map<System*, std::pair<std::string, int> > NameCache;
2205780Ssteve.reinhardt@amd.com
2215780Ssteve.reinhardt@amd.com    // array of systems each of which is a stack of running sm
2225780Ssteve.reinhardt@amd.com    typedef std::pair<int, uint64_t> StackId;
2235504Snate@binkert.org    typedef std::map<StackId, std::vector<int> > SmStack;
2245504Snate@binkert.org
2255529Snate@binkert.org    // map of each context and if it's currently in explict state mode
2265504Snate@binkert.org    // states are not automatically updated until it leaves
2275504Snate@binkert.org    typedef std::map<StackId, bool> SwExpl;
2285504Snate@binkert.org
2295504Snate@binkert.org    typedef std::map<int,int> IMap;
2305504Snate@binkert.org    // List of annotate records have not been written/completed yet
2315504Snate@binkert.org    typedef std::list<AnnDataPtr> AnnotateList;
2325504Snate@binkert.org
2335504Snate@binkert.org    // Maintain link state information
2345504Snate@binkert.org    typedef std::map<int, int> LinkMap;
2355504Snate@binkert.org
2365504Snate@binkert.org    // SC Links
2375504Snate@binkert.org    typedef m5::hash_map<Id, AnnDataPtr> ScHCache;
2385529Snate@binkert.org    typedef std::vector<ScHCache> ScCache;
2395504Snate@binkert.org
2405504Snate@binkert.org
2415504Snate@binkert.org    AnnotateList data;
2425504Snate@binkert.org
2435504Snate@binkert.org    // vector indexed by queueid to find current number of elements and bytes
2445504Snate@binkert.org    std::vector<int> qSize;
2455504Snate@binkert.org    std::vector<int32_t> qBytes;
2465504Snate@binkert.org
2475504Snate@binkert.org
2485504Snate@binkert.org    // Turn state machine string into state machine id (small int)
2495504Snate@binkert.org    // Used for outputting key to convert id back into string
2505504Snate@binkert.org    SCache smtCache;
2515529Snate@binkert.org    // Turn state machine id, state name into state id (small int)
2525504Snate@binkert.org    StCache stCache;
2535504Snate@binkert.org    // turn system, queue, and queue identify into qid (small int)
2545504Snate@binkert.org    // turn system, state, and context into state machine id (small int)
2555504Snate@binkert.org    IdCache qCache, smCache;
2565504Snate@binkert.org    //Link state machines accross system calls
2575504Snate@binkert.org    ScCache scLinks;
2585504Snate@binkert.org    // System pointer to name,id
2595504Snate@binkert.org    NameCache nameCache;
2605504Snate@binkert.org    // Stack of state machines currently nested (should unwind correctly)
2615504Snate@binkert.org    SmStack smStack;
2625504Snate@binkert.org    // Map of currently outstanding links
2635504Snate@binkert.org    LinkMap lnMap;
2645529Snate@binkert.org    // If the state machine is currently exculding automatic changes
2655504Snate@binkert.org    SwExpl swExpl;
2665504Snate@binkert.org    // Last state that a given state machine was in
2675504Snate@binkert.org    IMap lastState;
2685504Snate@binkert.org    // Hold mapping of sm and queues to output python
2695504Snate@binkert.org    IdMap smMap, qMap;
2705606Snate@binkert.org    // Items still in queue, used for sanity checking
2715606Snate@binkert.org    std::vector<AnnotateList> qData;
2725504Snate@binkert.org
2735504Snate@binkert.org    void doDq(System *sys, int flags, int cpu, int sm, std::string q, int qi,
2745780Ssteve.reinhardt@amd.com            int count);
2755780Ssteve.reinhardt@amd.com    void doQ(System *sys, int flags, int cpu, int sm, std::string q, int qi,
2765504Snate@binkert.org            int count);
2775504Snate@binkert.org
2785504Snate@binkert.org    void doSwSmEnd(System *sys, int cpuid, std::string sm, uint64_t frame);
2795504Snate@binkert.org
2805504Snate@binkert.org    // Turn a system id, state machine string, state machine id into a small int
2815504Snate@binkert.org    // for annotation output
282310SN/A    int
283299SN/A    getSm(int sysi, std::string si, uint64_t id)
2845504Snate@binkert.org    {
2852188SN/A        int smi;
2865504Snate@binkert.org        Id smid = Id(si, id);
2875504Snate@binkert.org
2885504Snate@binkert.org        smi = smCache[sysi-1][smid];
2892235SN/A        if (smi == 0) {
2905504Snate@binkert.org            smCache[sysi-1][smid] = smi = ++numSm;
2915504Snate@binkert.org            assert(smi < 65535);
2923368Sstever@eecs.umich.edu            smMap.push_back(std::make_pair<int, Id>(sysi, smid));
2935504Snate@binkert.org        }
2945504Snate@binkert.org        return smi;
2955504Snate@binkert.org    }
2965504Snate@binkert.org
2975504Snate@binkert.org    // Turn a state machine string, state string into a small int
2985504Snate@binkert.org    // for annotation output
2993368Sstever@eecs.umich.edu    int
3005504Snate@binkert.org    getSt(std::string sm, std::string s)
3015504Snate@binkert.org    {
3025504Snate@binkert.org        int sti, smi;
3032188SN/A
3042188SN/A        smi = smtCache[sm];
3055504Snate@binkert.org        if (smi == 0)
3065504Snate@binkert.org           smi = smtCache[sm] = ++numSmt;
3075504Snate@binkert.org
3085504Snate@binkert.org        while (stCache.size() < smi) {
3095504Snate@binkert.org            //stCache.resize(sm);
3102188SN/A            stCache.push_back(SCache());
3115780Ssteve.reinhardt@amd.com            numSt.push_back(0);
3125780Ssteve.reinhardt@amd.com        }
3135504Snate@binkert.org        //assert(stCache.size() == sm);
3145504Snate@binkert.org        //assert(numSt.size() == sm);
3155504Snate@binkert.org        sti = stCache[smi-1][s];
3165504Snate@binkert.org        if (sti == 0)
3175504Snate@binkert.org            stCache[smi-1][s] = sti = ++numSt[smi-1];
3182235SN/A        return sti;
3195504Snate@binkert.org    }
3205504Snate@binkert.org
3215504Snate@binkert.org    // Turn state machine pointer into a smal int for annotation output
3225504Snate@binkert.org    int
3235504Snate@binkert.org    getSys(System *s)
3243368Sstever@eecs.umich.edu    {
3255504Snate@binkert.org        NameCache::iterator i = nameCache.find(s);
326        if (i == nameCache.end()) {
327            nameCache[s] = std::make_pair<std::string,int>(s->name(), ++numSys);
328            i = nameCache.find(s);
329            // might need to put smstackid into map here, but perhaps not
330            //smStack.push_back(std::vector<int>());
331            //swExpl.push_back(false);
332            numQ.push_back(0);
333            qCache.push_back(IdHCache());
334            smCache.push_back(IdHCache());
335            scLinks.push_back(ScHCache());
336        }
337        return i->second.second;
338    }
339
340    // Turn queue name, and queue context into small int for
341    // annotation output
342    int
343    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