15952Ssaidi@eecs.umich.edu/*
210377Sandreas.hansson@arm.com * Copyright (c) 2014 ARM Limited
310377Sandreas.hansson@arm.com * All rights reserved.
410377Sandreas.hansson@arm.com *
510377Sandreas.hansson@arm.com * The license below extends only to copyright in the software and shall
610377Sandreas.hansson@arm.com * not be construed as granting a license to any other intellectual
710377Sandreas.hansson@arm.com * property including but not limited to intellectual property relating
810377Sandreas.hansson@arm.com * to a hardware implementation of the functionality of the software
910377Sandreas.hansson@arm.com * licensed hereunder.  You may use the software subject to the license
1010377Sandreas.hansson@arm.com * terms below provided that you ensure that this notice is replicated
1110377Sandreas.hansson@arm.com * unmodified and in its entirety in all distributions of the software,
1210377Sandreas.hansson@arm.com * modified or unmodified, in source code or in binary form.
1310377Sandreas.hansson@arm.com *
145952Ssaidi@eecs.umich.edu * Copyright (c) 2006-2009 The Regents of The University of Michigan
155952Ssaidi@eecs.umich.edu * All rights reserved.
165952Ssaidi@eecs.umich.edu *
175952Ssaidi@eecs.umich.edu * Redistribution and use in source and binary forms, with or without
185952Ssaidi@eecs.umich.edu * modification, are permitted provided that the following conditions are
195952Ssaidi@eecs.umich.edu * met: redistributions of source code must retain the above copyright
205952Ssaidi@eecs.umich.edu * notice, this list of conditions and the following disclaimer;
215952Ssaidi@eecs.umich.edu * redistributions in binary form must reproduce the above copyright
225952Ssaidi@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the
235952Ssaidi@eecs.umich.edu * documentation and/or other materials provided with the distribution;
245952Ssaidi@eecs.umich.edu * neither the name of the copyright holders nor the names of its
255952Ssaidi@eecs.umich.edu * contributors may be used to endorse or promote products derived from
265952Ssaidi@eecs.umich.edu * this software without specific prior written permission.
275952Ssaidi@eecs.umich.edu *
285952Ssaidi@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
295952Ssaidi@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
305952Ssaidi@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
315952Ssaidi@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
325952Ssaidi@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
335952Ssaidi@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
345952Ssaidi@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
355952Ssaidi@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
365952Ssaidi@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
375952Ssaidi@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
385952Ssaidi@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
395952Ssaidi@eecs.umich.edu *
405952Ssaidi@eecs.umich.edu * Authors: Ali Saidi
415952Ssaidi@eecs.umich.edu */
425952Ssaidi@eecs.umich.edu
435952Ssaidi@eecs.umich.edu#ifndef __BASE__CP_ANNOTATE_HH__
445952Ssaidi@eecs.umich.edu#define __BASE__CP_ANNOTATE_HH__
455952Ssaidi@eecs.umich.edu
468229Snate@binkert.org#include <list>
478229Snate@binkert.org#include <map>
4810470Sandreas.hansson@arm.com#include <memory>
496216Snate@binkert.org#include <string>
5011168Sandreas.hansson@arm.com#include <unordered_map>
516216Snate@binkert.org#include <vector>
526216Snate@binkert.org
538229Snate@binkert.org#include "base/loader/symtab.hh"
546216Snate@binkert.org#include "base/trace.hh"
556216Snate@binkert.org#include "base/types.hh"
5610377Sandreas.hansson@arm.com#include "debug/AnnotateQ.hh"
575952Ssaidi@eecs.umich.edu#include "config/cp_annotate.hh"
586658Snate@binkert.org#include "config/the_isa.hh"
595952Ssaidi@eecs.umich.edu#include "sim/serialize.hh"
605952Ssaidi@eecs.umich.edu#include "sim/system.hh"
615952Ssaidi@eecs.umich.edu
625952Ssaidi@eecs.umich.edu#if CP_ANNOTATE
635952Ssaidi@eecs.umich.edu#include "params/CPA.hh"
645952Ssaidi@eecs.umich.edu#endif
655952Ssaidi@eecs.umich.edu
665952Ssaidi@eecs.umich.educlass System;
675952Ssaidi@eecs.umich.educlass ThreadContext;
685952Ssaidi@eecs.umich.edu
695952Ssaidi@eecs.umich.edu
705952Ssaidi@eecs.umich.edu#if !CP_ANNOTATE
716002Snate@binkert.orgclass CPA
725952Ssaidi@eecs.umich.edu{
735952Ssaidi@eecs.umich.edu  public:
745952Ssaidi@eecs.umich.edu    enum flags {
755952Ssaidi@eecs.umich.edu        FL_NONE     = 0x00,
765952Ssaidi@eecs.umich.edu        FL_HW       = 0x01,
775952Ssaidi@eecs.umich.edu        FL_BAD      = 0x02,
785952Ssaidi@eecs.umich.edu        FL_QOPP     = 0x04,
795952Ssaidi@eecs.umich.edu        FL_WAIT     = 0x08,
805952Ssaidi@eecs.umich.edu        FL_LINK     = 0x10,
815952Ssaidi@eecs.umich.edu        FL_RESET    = 0x20
825952Ssaidi@eecs.umich.edu    };
835952Ssaidi@eecs.umich.edu
845952Ssaidi@eecs.umich.edu    static CPA *cpa()                                        { return NULL; }
855952Ssaidi@eecs.umich.edu    static bool available()                                 { return false; }
865952Ssaidi@eecs.umich.edu    bool enabled()                                          { return false; }
875952Ssaidi@eecs.umich.edu    void swSmBegin(ThreadContext *tc)                             { return; }
885952Ssaidi@eecs.umich.edu    void swSmEnd(ThreadContext *tc)                               { return; }
895952Ssaidi@eecs.umich.edu    void swExplictBegin(ThreadContext *tc)                        { return; }
905952Ssaidi@eecs.umich.edu    void swAutoBegin(ThreadContext *tc, Addr next_pc)             { return; }
915952Ssaidi@eecs.umich.edu    void swEnd(ThreadContext *tc)                                 { return; }
925952Ssaidi@eecs.umich.edu    void swQ(ThreadContext *tc)                                   { return; }
935952Ssaidi@eecs.umich.edu    void swDq(ThreadContext *tc)                                  { return; }
945952Ssaidi@eecs.umich.edu    void swPq(ThreadContext *tc)                                  { return; }
955952Ssaidi@eecs.umich.edu    void swRq(ThreadContext *tc)                                  { return; }
965952Ssaidi@eecs.umich.edu    void swWf(ThreadContext *tc)                                  { return; }
975952Ssaidi@eecs.umich.edu    void swWe(ThreadContext *tc)                                  { return; }
985952Ssaidi@eecs.umich.edu    void swSq(ThreadContext *tc)                                  { return; }
995952Ssaidi@eecs.umich.edu    void swAq(ThreadContext *tc)                                  { return; }
1005952Ssaidi@eecs.umich.edu    void swLink(ThreadContext *tc)                                { return; }
1015952Ssaidi@eecs.umich.edu    void swIdentify(ThreadContext *tc)                            { return; }
1025952Ssaidi@eecs.umich.edu    uint64_t swGetId(ThreadContext *tc)                         { return 0; }
1035952Ssaidi@eecs.umich.edu    void swSyscallLink(ThreadContext *tc)                         { return; }
10411320Ssteve.reinhardt@amd.com    void hwBegin(flags f, System *sys, uint64_t frame, std::string sm,
1055952Ssaidi@eecs.umich.edu                 std::string st)                                  { return; }
10611320Ssteve.reinhardt@amd.com    void hwQ(flags f, System *sys, uint64_t frame, std::string sm,
10711320Ssteve.reinhardt@amd.com             std::string q, uint64_t qid, System *q_sys = NULL,
1085952Ssaidi@eecs.umich.edu             int32_t count = 1)                                   { return; }
10911320Ssteve.reinhardt@amd.com    void hwDq(flags f, System *sys, uint64_t frame, std::string sm,
11011320Ssteve.reinhardt@amd.com              std::string q, uint64_t qid, System *q_sys = NULL,
1115952Ssaidi@eecs.umich.edu              int32_t count = 1)                                  { return; }
11211320Ssteve.reinhardt@amd.com    void hwPq(flags f, System *sys, uint64_t frame, std::string sm,
11311320Ssteve.reinhardt@amd.com              std::string q, uint64_t qid, System *q_sys = NULL,
1145952Ssaidi@eecs.umich.edu              int32_t count = 1)                                  { return; }
11511320Ssteve.reinhardt@amd.com    void hwRq(flags f, System *sys, uint64_t frame, std::string sm,
11611320Ssteve.reinhardt@amd.com              std::string q, uint64_t qid, System *q_sys = NULL,
1175952Ssaidi@eecs.umich.edu              int32_t count = 1)                                  { return; }
11811320Ssteve.reinhardt@amd.com    void hwWf(flags f, System *sys, uint64_t frame, std::string sm,
11911320Ssteve.reinhardt@amd.com              std::string q, uint64_t qid, System *q_sys = NULL,
1205952Ssaidi@eecs.umich.edu              int32_t count = 1)                                  { return; }
12111320Ssteve.reinhardt@amd.com    void hwWe(flags f, System *sys, uint64_t frame, std::string sm,
12211320Ssteve.reinhardt@amd.com              std::string q, uint64_t qid, System *q_sys = NULL,
1235952Ssaidi@eecs.umich.edu              int32_t count = 1)                                  { return; }
1245952Ssaidi@eecs.umich.edu};
1255952Ssaidi@eecs.umich.edu#else
12610377Sandreas.hansson@arm.com
12710377Sandreas.hansson@arm.com/**
12810377Sandreas.hansson@arm.com * Provide a hash function for the CPI Id type
12910377Sandreas.hansson@arm.com */
13011168Sandreas.hansson@arm.comnamespace std {
13110377Sandreas.hansson@arm.comtemplate <>
13210377Sandreas.hansson@arm.comstruct hash<std::pair<std::string, uint64_t> >
13310377Sandreas.hansson@arm.com{
13410377Sandreas.hansson@arm.com
13510377Sandreas.hansson@arm.com    size_t
13610377Sandreas.hansson@arm.com    operator()(const std::pair<std::string, uint64_t>& x) const
13710377Sandreas.hansson@arm.com    {
13810377Sandreas.hansson@arm.com        return hash<std::string>()(x.first);
13910377Sandreas.hansson@arm.com    }
14010377Sandreas.hansson@arm.com
14110377Sandreas.hansson@arm.com};
14211168Sandreas.hansson@arm.com}
14310377Sandreas.hansson@arm.com
1445952Ssaidi@eecs.umich.educlass CPA : SimObject
1455952Ssaidi@eecs.umich.edu{
1465952Ssaidi@eecs.umich.edu  public:
1475952Ssaidi@eecs.umich.edu    typedef CPAParams Params;
14811320Ssteve.reinhardt@amd.com
1495952Ssaidi@eecs.umich.edu    /** The known operations that are written to the annotation output file. */
1505952Ssaidi@eecs.umich.edu    enum ops {
1515952Ssaidi@eecs.umich.edu        OP_BEGIN           = 0x01,
1525952Ssaidi@eecs.umich.edu        OP_WAIT_EMPTY      = 0x02,
1535952Ssaidi@eecs.umich.edu        OP_WAIT_FULL       = 0x03,
1545952Ssaidi@eecs.umich.edu        OP_QUEUE           = 0x04,
1555952Ssaidi@eecs.umich.edu        OP_DEQUEUE         = 0x05,
1565952Ssaidi@eecs.umich.edu        OP_SIZE_QUEUE      = 0x08,
1575952Ssaidi@eecs.umich.edu        OP_PEEK            = 0x09,
1585952Ssaidi@eecs.umich.edu        OP_LINK            = 0x0A,
1595952Ssaidi@eecs.umich.edu        OP_IDENT           = 0x0B,
1605952Ssaidi@eecs.umich.edu        OP_RESERVE         = 0x0C
1615952Ssaidi@eecs.umich.edu    };
1625952Ssaidi@eecs.umich.edu
1635952Ssaidi@eecs.umich.edu    /** Flags for the various options.*/
1645952Ssaidi@eecs.umich.edu    enum flags {
1655952Ssaidi@eecs.umich.edu        /* no flags */
1665952Ssaidi@eecs.umich.edu        FL_NONE     = 0x00,
1675952Ssaidi@eecs.umich.edu        /* operation was done on hardware */
1685952Ssaidi@eecs.umich.edu        FL_HW       = 0x01,
1695952Ssaidi@eecs.umich.edu        /* operation should cause a warning when encountered */
1705952Ssaidi@eecs.umich.edu        FL_BAD      = 0x02,
1715952Ssaidi@eecs.umich.edu        /* Queue like a stack, not a queue */
1725952Ssaidi@eecs.umich.edu        FL_QOPP     = 0x04,
1735952Ssaidi@eecs.umich.edu        /* Mark HW state as waiting for some non-resource constraint
17411320Ssteve.reinhardt@amd.com         * (e.g. wait because SM only starts after 10 items are queued) */
1755952Ssaidi@eecs.umich.edu        FL_WAIT     = 0x08,
1765952Ssaidi@eecs.umich.edu        /* operation is linking to another state machine */
1775952Ssaidi@eecs.umich.edu        FL_LINK     = 0x10,
1785952Ssaidi@eecs.umich.edu        /* queue should be completely cleared/reset before executing this
1795952Ssaidi@eecs.umich.edu         * operation */
1805952Ssaidi@eecs.umich.edu        FL_RESET    = 0x20
1815952Ssaidi@eecs.umich.edu    };
1825952Ssaidi@eecs.umich.edu
1835952Ssaidi@eecs.umich.edu
1845952Ssaidi@eecs.umich.edu
1855952Ssaidi@eecs.umich.edu  protected:
1865952Ssaidi@eecs.umich.edu    const Params *
1875952Ssaidi@eecs.umich.edu        params() const
1885952Ssaidi@eecs.umich.edu        {
1895952Ssaidi@eecs.umich.edu            return dynamic_cast<const Params *>(_params);
1905952Ssaidi@eecs.umich.edu        }
1915952Ssaidi@eecs.umich.edu
1925952Ssaidi@eecs.umich.edu    /* struct that is written to the annotation output file */
19310905Sandreas.sandberg@arm.com    struct AnnotateData : public Serializable {
1945952Ssaidi@eecs.umich.edu
1955952Ssaidi@eecs.umich.edu        Tick time;
1965952Ssaidi@eecs.umich.edu        uint32_t data;
1975952Ssaidi@eecs.umich.edu        uint32_t orig_data;
1985952Ssaidi@eecs.umich.edu        uint16_t sm;
1995952Ssaidi@eecs.umich.edu        uint16_t stq;
2005952Ssaidi@eecs.umich.edu        uint8_t  op;
2015952Ssaidi@eecs.umich.edu        uint8_t  flag;
2025952Ssaidi@eecs.umich.edu        uint8_t  cpu;
2035952Ssaidi@eecs.umich.edu        bool dump;
2045952Ssaidi@eecs.umich.edu
20511168Sandreas.hansson@arm.com        void serialize(CheckpointOut &cp) const override;
20611168Sandreas.hansson@arm.com        void unserialize(CheckpointIn &cp) override;
2075952Ssaidi@eecs.umich.edu    };
2085952Ssaidi@eecs.umich.edu
20910470Sandreas.hansson@arm.com    typedef std::shared_ptr<AnnotateData> AnnDataPtr;
2105952Ssaidi@eecs.umich.edu
2115952Ssaidi@eecs.umich.edu    /* header for the annotation file */
2125952Ssaidi@eecs.umich.edu    struct AnnotateHeader {
2135952Ssaidi@eecs.umich.edu        uint64_t version;
2145952Ssaidi@eecs.umich.edu        uint64_t num_recs;
2155952Ssaidi@eecs.umich.edu        uint64_t key_off;
2165952Ssaidi@eecs.umich.edu        uint64_t idx_off;
2175952Ssaidi@eecs.umich.edu        uint32_t key_len;
2185952Ssaidi@eecs.umich.edu        uint32_t idx_len;
2195952Ssaidi@eecs.umich.edu    };
2205952Ssaidi@eecs.umich.edu
2215952Ssaidi@eecs.umich.edu    AnnotateHeader ah;
2225952Ssaidi@eecs.umich.edu
2235952Ssaidi@eecs.umich.edu    std::vector<uint64_t> annotateIdx;
2245952Ssaidi@eecs.umich.edu
22511320Ssteve.reinhardt@amd.com    // number of state machines encountered in the simulation
2265952Ssaidi@eecs.umich.edu    int numSm;
22711320Ssteve.reinhardt@amd.com    // number of states encountered in the simulation
2285952Ssaidi@eecs.umich.edu    int numSmt;
2295952Ssaidi@eecs.umich.edu    // number of states/queues for a given state machine/system respectively
2305952Ssaidi@eecs.umich.edu    std::vector<int> numSt, numQ;
2315952Ssaidi@eecs.umich.edu    // number of systems in the simulation
2325952Ssaidi@eecs.umich.edu    int numSys;
2335952Ssaidi@eecs.umich.edu    // number of queues in the state machine
2345952Ssaidi@eecs.umich.edu    int numQs;
2355952Ssaidi@eecs.umich.edu    // maximum connection id assigned so far
2365952Ssaidi@eecs.umich.edu    uint64_t conId;
2375952Ssaidi@eecs.umich.edu
2385952Ssaidi@eecs.umich.edu    // Convert state strings into state ids
23911168Sandreas.hansson@arm.com    typedef std::unordered_map<std::string, int> SCache;
2405952Ssaidi@eecs.umich.edu    typedef std::vector<SCache> StCache;
2415952Ssaidi@eecs.umich.edu
2425952Ssaidi@eecs.umich.edu    // Convert sm and queue name,id into queue id
2435952Ssaidi@eecs.umich.edu    typedef std::pair<std::string, uint64_t> Id;
24411168Sandreas.hansson@arm.com    typedef std::unordered_map<Id, int> IdHCache;
2455952Ssaidi@eecs.umich.edu    typedef std::vector<IdHCache> IdCache;
2465952Ssaidi@eecs.umich.edu
2475952Ssaidi@eecs.umich.edu    // Hold mapping of sm and queues to output python
2485952Ssaidi@eecs.umich.edu    typedef std::vector<std::pair<int, Id> > IdMap;
2495952Ssaidi@eecs.umich.edu
2505952Ssaidi@eecs.umich.edu    // System pointer to name,id
2515952Ssaidi@eecs.umich.edu    typedef std::map<System*, std::pair<std::string, int> > NameCache;
2525952Ssaidi@eecs.umich.edu
2535952Ssaidi@eecs.umich.edu    // array of systems each of which is a stack of running sm
2545952Ssaidi@eecs.umich.edu    typedef std::pair<int, uint64_t> StackId;
2555952Ssaidi@eecs.umich.edu    typedef std::map<StackId, std::vector<int> > SmStack;
2565952Ssaidi@eecs.umich.edu
2575952Ssaidi@eecs.umich.edu    // map of each context and if it's currently in explict state mode
2585952Ssaidi@eecs.umich.edu    // states are not automatically updated until it leaves
2595952Ssaidi@eecs.umich.edu    typedef std::map<StackId, bool> SwExpl;
2605952Ssaidi@eecs.umich.edu
2615952Ssaidi@eecs.umich.edu    typedef std::map<int,int> IMap;
2625952Ssaidi@eecs.umich.edu    // List of annotate records have not been written/completed yet
2635952Ssaidi@eecs.umich.edu    typedef std::list<AnnDataPtr> AnnotateList;
2645952Ssaidi@eecs.umich.edu
2655952Ssaidi@eecs.umich.edu    // Maintain link state information
2665952Ssaidi@eecs.umich.edu    typedef std::map<int, int> LinkMap;
2675952Ssaidi@eecs.umich.edu
2685952Ssaidi@eecs.umich.edu    // SC Links
26911168Sandreas.hansson@arm.com    typedef std::unordered_map<Id, AnnDataPtr> ScHCache;
2705952Ssaidi@eecs.umich.edu    typedef std::vector<ScHCache> ScCache;
2715952Ssaidi@eecs.umich.edu
2725952Ssaidi@eecs.umich.edu
2735952Ssaidi@eecs.umich.edu    AnnotateList data;
2745952Ssaidi@eecs.umich.edu
2755952Ssaidi@eecs.umich.edu    // vector indexed by queueid to find current number of elements and bytes
2765952Ssaidi@eecs.umich.edu    std::vector<int> qSize;
2775952Ssaidi@eecs.umich.edu    std::vector<int32_t> qBytes;
2785952Ssaidi@eecs.umich.edu
2795952Ssaidi@eecs.umich.edu
2805952Ssaidi@eecs.umich.edu    // Turn state machine string into state machine id (small int)
2815952Ssaidi@eecs.umich.edu    // Used for outputting key to convert id back into string
2825952Ssaidi@eecs.umich.edu    SCache smtCache;
2835952Ssaidi@eecs.umich.edu    // Turn state machine id, state name into state id (small int)
2845952Ssaidi@eecs.umich.edu    StCache stCache;
2855952Ssaidi@eecs.umich.edu    // turn system, queue, and queue identify into qid (small int)
2865952Ssaidi@eecs.umich.edu    // turn system, state, and context into state machine id (small int)
2875952Ssaidi@eecs.umich.edu    IdCache qCache, smCache;
2885952Ssaidi@eecs.umich.edu    //Link state machines accross system calls
2895952Ssaidi@eecs.umich.edu    ScCache scLinks;
2905952Ssaidi@eecs.umich.edu    // System pointer to name,id
2915952Ssaidi@eecs.umich.edu    NameCache nameCache;
2925952Ssaidi@eecs.umich.edu    // Stack of state machines currently nested (should unwind correctly)
2935952Ssaidi@eecs.umich.edu    SmStack smStack;
29411320Ssteve.reinhardt@amd.com    // Map of currently outstanding links
2955952Ssaidi@eecs.umich.edu    LinkMap lnMap;
2965952Ssaidi@eecs.umich.edu    // If the state machine is currently exculding automatic changes
2975952Ssaidi@eecs.umich.edu    SwExpl swExpl;
2985952Ssaidi@eecs.umich.edu    // Last state that a given state machine was in
2995952Ssaidi@eecs.umich.edu    IMap lastState;
3005952Ssaidi@eecs.umich.edu    // Hold mapping of sm and queues to output python
3015952Ssaidi@eecs.umich.edu    IdMap smMap, qMap;
30211320Ssteve.reinhardt@amd.com    // Items still in queue, used for sanity checking
3035952Ssaidi@eecs.umich.edu    std::vector<AnnotateList> qData;
3045952Ssaidi@eecs.umich.edu
3055952Ssaidi@eecs.umich.edu    void doDq(System *sys, int flags, int cpu, int sm, std::string q, int qi,
3065952Ssaidi@eecs.umich.edu            int count);
3075952Ssaidi@eecs.umich.edu    void doQ(System *sys, int flags, int cpu, int sm, std::string q, int qi,
3085952Ssaidi@eecs.umich.edu            int count);
3095952Ssaidi@eecs.umich.edu
3105952Ssaidi@eecs.umich.edu    void doSwSmEnd(System *sys, int cpuid, std::string sm, uint64_t frame);
3115952Ssaidi@eecs.umich.edu
3125952Ssaidi@eecs.umich.edu    // Turn a system id, state machine string, state machine id into a small int
3135952Ssaidi@eecs.umich.edu    // for annotation output
31411320Ssteve.reinhardt@amd.com    int
3155952Ssaidi@eecs.umich.edu    getSm(int sysi, std::string si, uint64_t id)
3165952Ssaidi@eecs.umich.edu    {
3175952Ssaidi@eecs.umich.edu        int smi;
3185952Ssaidi@eecs.umich.edu        Id smid = Id(si, id);
3195952Ssaidi@eecs.umich.edu
3205952Ssaidi@eecs.umich.edu        smi = smCache[sysi-1][smid];
3215952Ssaidi@eecs.umich.edu        if (smi == 0) {
3225952Ssaidi@eecs.umich.edu            smCache[sysi-1][smid] = smi = ++numSm;
3235952Ssaidi@eecs.umich.edu            assert(smi < 65535);
32410377Sandreas.hansson@arm.com            smMap.push_back(std::make_pair(sysi, smid));
3255952Ssaidi@eecs.umich.edu        }
3265952Ssaidi@eecs.umich.edu        return smi;
3275952Ssaidi@eecs.umich.edu    }
3285952Ssaidi@eecs.umich.edu
3295952Ssaidi@eecs.umich.edu    // Turn a state machine string, state string into a small int
3305952Ssaidi@eecs.umich.edu    // for annotation output
33111320Ssteve.reinhardt@amd.com    int
3325952Ssaidi@eecs.umich.edu    getSt(std::string sm, std::string s)
3335952Ssaidi@eecs.umich.edu    {
3345952Ssaidi@eecs.umich.edu        int sti, smi;
3355952Ssaidi@eecs.umich.edu
3365952Ssaidi@eecs.umich.edu        smi = smtCache[sm];
3375952Ssaidi@eecs.umich.edu        if (smi == 0)
3385952Ssaidi@eecs.umich.edu           smi = smtCache[sm] = ++numSmt;
3395952Ssaidi@eecs.umich.edu
3405952Ssaidi@eecs.umich.edu        while (stCache.size() < smi) {
3415952Ssaidi@eecs.umich.edu            //stCache.resize(sm);
3425952Ssaidi@eecs.umich.edu            stCache.push_back(SCache());
3435952Ssaidi@eecs.umich.edu            numSt.push_back(0);
3445952Ssaidi@eecs.umich.edu        }
3455952Ssaidi@eecs.umich.edu        //assert(stCache.size() == sm);
3465952Ssaidi@eecs.umich.edu        //assert(numSt.size() == sm);
3475952Ssaidi@eecs.umich.edu        sti = stCache[smi-1][s];
3485952Ssaidi@eecs.umich.edu        if (sti == 0)
3495952Ssaidi@eecs.umich.edu            stCache[smi-1][s] = sti = ++numSt[smi-1];
3505952Ssaidi@eecs.umich.edu        return sti;
3515952Ssaidi@eecs.umich.edu    }
3525952Ssaidi@eecs.umich.edu
3535952Ssaidi@eecs.umich.edu    // Turn state machine pointer into a smal int for annotation output
35411320Ssteve.reinhardt@amd.com    int
3555952Ssaidi@eecs.umich.edu    getSys(System *s)
3565952Ssaidi@eecs.umich.edu    {
3575952Ssaidi@eecs.umich.edu        NameCache::iterator i = nameCache.find(s);
3585952Ssaidi@eecs.umich.edu        if (i == nameCache.end()) {
35910377Sandreas.hansson@arm.com            nameCache[s] = std::make_pair(s->name(), ++numSys);
3605952Ssaidi@eecs.umich.edu            i = nameCache.find(s);
3615952Ssaidi@eecs.umich.edu            // might need to put smstackid into map here, but perhaps not
3625952Ssaidi@eecs.umich.edu            //smStack.push_back(std::vector<int>());
3635952Ssaidi@eecs.umich.edu            //swExpl.push_back(false);
3645952Ssaidi@eecs.umich.edu            numQ.push_back(0);
3655952Ssaidi@eecs.umich.edu            qCache.push_back(IdHCache());
3665952Ssaidi@eecs.umich.edu            smCache.push_back(IdHCache());
3675952Ssaidi@eecs.umich.edu            scLinks.push_back(ScHCache());
3685952Ssaidi@eecs.umich.edu        }
3695952Ssaidi@eecs.umich.edu        return i->second.second;
3705952Ssaidi@eecs.umich.edu    }
3715952Ssaidi@eecs.umich.edu
37211320Ssteve.reinhardt@amd.com    // Turn queue name, and queue context into small int for
3735952Ssaidi@eecs.umich.edu    // annotation output
37411320Ssteve.reinhardt@amd.com    int
3755952Ssaidi@eecs.umich.edu    getQ(int sys, std::string q, uint64_t id)
3765952Ssaidi@eecs.umich.edu    {
3775952Ssaidi@eecs.umich.edu        int qi;
3785952Ssaidi@eecs.umich.edu        Id qid = Id(q, id);
3795952Ssaidi@eecs.umich.edu
3805952Ssaidi@eecs.umich.edu        qi = qCache[sys-1][qid];
3815952Ssaidi@eecs.umich.edu        if (qi == 0) {
3825952Ssaidi@eecs.umich.edu            qi = qCache[sys-1][qid] = ++numQs;
3835952Ssaidi@eecs.umich.edu            assert(qi < 65535);
3845952Ssaidi@eecs.umich.edu            qSize.push_back(0);
3855952Ssaidi@eecs.umich.edu            qBytes.push_back(0);
3865952Ssaidi@eecs.umich.edu            qData.push_back(AnnotateList());
3875952Ssaidi@eecs.umich.edu            numQ[sys-1]++;
38810377Sandreas.hansson@arm.com            qMap.push_back(std::make_pair(sys, qid));
3895952Ssaidi@eecs.umich.edu        }
3905952Ssaidi@eecs.umich.edu        return qi;
3915952Ssaidi@eecs.umich.edu    }
3925952Ssaidi@eecs.umich.edu
39311320Ssteve.reinhardt@amd.com    void swBegin(System *sys, int cpuid, std::string st, uint64_t frame,
3945952Ssaidi@eecs.umich.edu            bool expl = false, int flags = FL_NONE);
3955952Ssaidi@eecs.umich.edu
3965952Ssaidi@eecs.umich.edu    AnnDataPtr add(int t, int f, int c, int sm, int stq, int32_t data=0);
3975952Ssaidi@eecs.umich.edu
3985952Ssaidi@eecs.umich.edu    std::ostream *osbin;
3995952Ssaidi@eecs.umich.edu
4005952Ssaidi@eecs.umich.edu    bool _enabled;
4015952Ssaidi@eecs.umich.edu
40211320Ssteve.reinhardt@amd.com    /** Only allow one CPA object in a system. It doesn't make sense to have
4035952Ssaidi@eecs.umich.edu     * more that one per simulation because if a part of the system was
4045952Ssaidi@eecs.umich.edu     * important it would have annotations and queues, and with more than one
4055952Ssaidi@eecs.umich.edu     * object none of the sanity checking for queues will work. */
4065952Ssaidi@eecs.umich.edu    static bool exists;
4075952Ssaidi@eecs.umich.edu    static CPA *_cpa;
4085952Ssaidi@eecs.umich.edu
4095952Ssaidi@eecs.umich.edu
4105952Ssaidi@eecs.umich.edu    std::map<std::string, SymbolTable*> userApp;
4115952Ssaidi@eecs.umich.edu
4125952Ssaidi@eecs.umich.edu  public:
4135952Ssaidi@eecs.umich.edu    static CPA *cpa() { return _cpa; }
4145952Ssaidi@eecs.umich.edu    void swSmBegin(ThreadContext *tc);
4155952Ssaidi@eecs.umich.edu    void swSmEnd(ThreadContext *tc);
4165952Ssaidi@eecs.umich.edu    void swExplictBegin(ThreadContext *tc);
4175952Ssaidi@eecs.umich.edu    void swAutoBegin(ThreadContext *tc, Addr next_pc);
4185952Ssaidi@eecs.umich.edu    void swEnd(ThreadContext *tc);
4195952Ssaidi@eecs.umich.edu    void swQ(ThreadContext *tc);
4205952Ssaidi@eecs.umich.edu    void swDq(ThreadContext *tc);
4215952Ssaidi@eecs.umich.edu    void swPq(ThreadContext *tc);
4225952Ssaidi@eecs.umich.edu    void swRq(ThreadContext *tc);
4235952Ssaidi@eecs.umich.edu    void swWf(ThreadContext *tc);
4245952Ssaidi@eecs.umich.edu    void swWe(ThreadContext *tc);
4255952Ssaidi@eecs.umich.edu    void swSq(ThreadContext *tc);
4265952Ssaidi@eecs.umich.edu    void swAq(ThreadContext *tc);
4275952Ssaidi@eecs.umich.edu    void swLink(ThreadContext *tc);
4285952Ssaidi@eecs.umich.edu    void swIdentify(ThreadContext *tc);
4295952Ssaidi@eecs.umich.edu    uint64_t swGetId(ThreadContext *tc);
4305952Ssaidi@eecs.umich.edu    void swSyscallLink(ThreadContext *tc);
4315952Ssaidi@eecs.umich.edu
43211320Ssteve.reinhardt@amd.com    inline void hwBegin(flags f, System *sys, uint64_t frame, std::string sm,
4335952Ssaidi@eecs.umich.edu            std::string st)
4345952Ssaidi@eecs.umich.edu    {
4355952Ssaidi@eecs.umich.edu        if (!enabled())
4365952Ssaidi@eecs.umich.edu            return;
4375952Ssaidi@eecs.umich.edu
4385952Ssaidi@eecs.umich.edu        int sysi = getSys(sys);
4395952Ssaidi@eecs.umich.edu        int smi = getSm(sysi, sm, frame);
4405952Ssaidi@eecs.umich.edu        add(OP_BEGIN, FL_HW | f, 0, smi, getSt(sm, st));
4415952Ssaidi@eecs.umich.edu        if (f & FL_BAD)
4427823Ssteve.reinhardt@amd.com            warn("BAD state encountered: at cycle %d: %s\n", curTick(), st);
4435952Ssaidi@eecs.umich.edu    }
4445952Ssaidi@eecs.umich.edu
44511320Ssteve.reinhardt@amd.com    inline void hwQ(flags f, System *sys, uint64_t frame, std::string sm,
4465952Ssaidi@eecs.umich.edu            std::string q, uint64_t qid, System *q_sys = NULL, int32_t count = 1)
4475952Ssaidi@eecs.umich.edu    {
4485952Ssaidi@eecs.umich.edu        if (!enabled())
4495952Ssaidi@eecs.umich.edu            return;
4505952Ssaidi@eecs.umich.edu
4515952Ssaidi@eecs.umich.edu        int sysi = getSys(sys);
4525952Ssaidi@eecs.umich.edu        int qi = getQ(q_sys ?  getSys(q_sys) : sysi, q, qid);
45311320Ssteve.reinhardt@amd.com        DPRINTFS(AnnotateQ, sys,
4545952Ssaidi@eecs.umich.edu                "hwQ: %s[%#x] cur size %d %d bytes: %d adding: %d\n",
4555952Ssaidi@eecs.umich.edu                q, qid, qSize[qi-1], qData[qi-1].size(), qBytes[qi-1], count);
4565952Ssaidi@eecs.umich.edu        doQ(sys, FL_HW | f, 0, getSm(sysi, sm, frame), q, qi, count);
4575952Ssaidi@eecs.umich.edu
4585952Ssaidi@eecs.umich.edu    }
4595952Ssaidi@eecs.umich.edu
46011320Ssteve.reinhardt@amd.com    inline void hwDq(flags f, System *sys, uint64_t frame, std::string sm,
4615952Ssaidi@eecs.umich.edu            std::string q, uint64_t qid, System *q_sys = NULL, int32_t count = 1)
4625952Ssaidi@eecs.umich.edu    {
4635952Ssaidi@eecs.umich.edu        if (!enabled())
4645952Ssaidi@eecs.umich.edu            return;
4655952Ssaidi@eecs.umich.edu
4665952Ssaidi@eecs.umich.edu        int sysi = getSys(sys);
4675952Ssaidi@eecs.umich.edu        int qi = getQ(q_sys ?  getSys(q_sys) : sysi, q, qid);
46811320Ssteve.reinhardt@amd.com        DPRINTFS(AnnotateQ, sys,
4695952Ssaidi@eecs.umich.edu                "hwDQ: %s[%#x] cur size %d %d bytes: %d removing: %d\n",
4705952Ssaidi@eecs.umich.edu                q, qid, qSize[qi-1], qData[qi-1].size(), qBytes[qi-1], count);
4715952Ssaidi@eecs.umich.edu        doDq(sys, FL_HW | f, 0, getSm(sysi,sm, frame), q, qi, count);
4725952Ssaidi@eecs.umich.edu    }
4735952Ssaidi@eecs.umich.edu
47411320Ssteve.reinhardt@amd.com    inline void hwPq(flags f, System *sys, uint64_t frame, std::string sm,
4755952Ssaidi@eecs.umich.edu            std::string q, uint64_t qid, System *q_sys = NULL, int32_t count = 1)
4765952Ssaidi@eecs.umich.edu    {
4775952Ssaidi@eecs.umich.edu        if (!enabled())
4785952Ssaidi@eecs.umich.edu            return;
4795952Ssaidi@eecs.umich.edu
4805952Ssaidi@eecs.umich.edu        int sysi = getSys(sys);
4815952Ssaidi@eecs.umich.edu        int qi = getQ(q_sys ?  getSys(q_sys) : sysi, q, qid);
48211320Ssteve.reinhardt@amd.com        DPRINTFS(AnnotateQ, sys,
4835952Ssaidi@eecs.umich.edu                "hwPQ: %s[%#x] cur size %d %d bytes: %d peeking: %d\n",
4845952Ssaidi@eecs.umich.edu                q, qid, qSize[qi-1], qData[qi-1].size(), qBytes[qi-1], count);
4855952Ssaidi@eecs.umich.edu        add(OP_PEEK, FL_HW | f, 0, getSm(sysi, sm, frame), qi, count);
4865952Ssaidi@eecs.umich.edu    }
4875952Ssaidi@eecs.umich.edu
48811320Ssteve.reinhardt@amd.com    inline void hwRq(flags f, System *sys, uint64_t frame, std::string sm,
4895952Ssaidi@eecs.umich.edu            std::string q, uint64_t qid, System *q_sys = NULL, int32_t count = 1)
4905952Ssaidi@eecs.umich.edu    {
4915952Ssaidi@eecs.umich.edu        if (!enabled())
4925952Ssaidi@eecs.umich.edu            return;
4935952Ssaidi@eecs.umich.edu
4945952Ssaidi@eecs.umich.edu        int sysi = getSys(sys);
4955952Ssaidi@eecs.umich.edu        int qi = getQ(q_sys ?  getSys(q_sys) : sysi, q, qid);
49611320Ssteve.reinhardt@amd.com        DPRINTFS(AnnotateQ, sys,
4975952Ssaidi@eecs.umich.edu                "hwRQ: %s[%#x] cur size %d %d bytes: %d reserving: %d\n",
4985952Ssaidi@eecs.umich.edu                q, qid, qSize[qi-1], qData[qi-1].size(), qBytes[qi-1], count);
4995952Ssaidi@eecs.umich.edu        add(OP_RESERVE, FL_HW | f, 0, getSm(sysi, sm, frame), qi, count);
5005952Ssaidi@eecs.umich.edu    }
5015952Ssaidi@eecs.umich.edu
50211320Ssteve.reinhardt@amd.com    inline void hwWf(flags f, System *sys, uint64_t frame, std::string sm,
5035952Ssaidi@eecs.umich.edu            std::string q, uint64_t qid, System *q_sys = NULL, int32_t count = 1)
5045952Ssaidi@eecs.umich.edu    {
5055952Ssaidi@eecs.umich.edu        if (!enabled())
5065952Ssaidi@eecs.umich.edu            return;
5075952Ssaidi@eecs.umich.edu
5085952Ssaidi@eecs.umich.edu        int sysi = getSys(sys);
5095952Ssaidi@eecs.umich.edu        int qi = getQ(q_sys ?  getSys(q_sys) : sysi, q, qid);
5105952Ssaidi@eecs.umich.edu        add(OP_WAIT_FULL, FL_HW | f, 0, getSm(sysi, sm, frame), qi, count);
5115952Ssaidi@eecs.umich.edu    }
5125952Ssaidi@eecs.umich.edu
51311320Ssteve.reinhardt@amd.com    inline void hwWe(flags f, System *sys, uint64_t frame, std::string sm,
51411320Ssteve.reinhardt@amd.com            std::string q, uint64_t qid, System *q_sys = NULL, int32_t count = 1)
5155952Ssaidi@eecs.umich.edu    {
5165952Ssaidi@eecs.umich.edu        if (!enabled())
5175952Ssaidi@eecs.umich.edu            return;
5185952Ssaidi@eecs.umich.edu
5195952Ssaidi@eecs.umich.edu        int sysi = getSys(sys);
5205952Ssaidi@eecs.umich.edu        int qi = getQ(q_sys ?  getSys(q_sys) : sysi, q, qid);
5215952Ssaidi@eecs.umich.edu        add(OP_WAIT_EMPTY, FL_HW | f, 0, getSm(sysi, sm, frame), qi, count);
5225952Ssaidi@eecs.umich.edu    }
5235952Ssaidi@eecs.umich.edu
5245952Ssaidi@eecs.umich.edu  public:
5255952Ssaidi@eecs.umich.edu    CPA(Params *p);
5265952Ssaidi@eecs.umich.edu    void startup();
5275952Ssaidi@eecs.umich.edu
52810377Sandreas.hansson@arm.com    uint64_t getFrame(ThreadContext *tc);
5295952Ssaidi@eecs.umich.edu
5305952Ssaidi@eecs.umich.edu    static bool available()  { return true; }
5315952Ssaidi@eecs.umich.edu
53211320Ssteve.reinhardt@amd.com    bool
53311320Ssteve.reinhardt@amd.com    enabled()
53411320Ssteve.reinhardt@amd.com    {
5355952Ssaidi@eecs.umich.edu        if (!this)
5365952Ssaidi@eecs.umich.edu            return false;
5375952Ssaidi@eecs.umich.edu        return _enabled;
5385952Ssaidi@eecs.umich.edu    }
53911320Ssteve.reinhardt@amd.com
5405952Ssaidi@eecs.umich.edu    void dump(bool all);
5415952Ssaidi@eecs.umich.edu    void dumpKey();
5425952Ssaidi@eecs.umich.edu
54311168Sandreas.hansson@arm.com    void serialize(CheckpointOut &cp) const override;
54411168Sandreas.hansson@arm.com    void unserialize(CheckpointIn &cp) override;
5455952Ssaidi@eecs.umich.edu};
5465952Ssaidi@eecs.umich.edu#endif // !CP_ANNOTATE
5475952Ssaidi@eecs.umich.edu
5485952Ssaidi@eecs.umich.edu#endif //__BASE__CP_ANNOTATE_HH__
5495952Ssaidi@eecs.umich.edu
550