/*
 * Copyright (c) 2006-2009 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Ali Saidi
 */

#ifndef __BASE__CP_ANNOTATE_HH__
#define __BASE__CP_ANNOTATE_HH__

#include <list>
#include <map>
#include <string>
#include <vector>

#include "base/loader/symtab.hh"
#include "base/hashmap.hh"
#include "base/trace.hh"
#include "base/types.hh"
#include "config/cp_annotate.hh"
#include "config/the_isa.hh"
#include "sim/serialize.hh"
#include "sim/system.hh"

#if CP_ANNOTATE
#include "params/CPA.hh"
#endif

class System;
class ThreadContext;


#if !CP_ANNOTATE
class CPA
{
  public:
    enum flags {
        FL_NONE     = 0x00,
        FL_HW       = 0x01,
        FL_BAD      = 0x02,
        FL_QOPP     = 0x04,
        FL_WAIT     = 0x08,
        FL_LINK     = 0x10,
        FL_RESET    = 0x20
    };

    static CPA *cpa()                                        { return NULL; }
    static bool available()                                 { return false; }
    bool enabled()                                          { return false; }
    void swSmBegin(ThreadContext *tc)                             { return; }
    void swSmEnd(ThreadContext *tc)                               { return; }
    void swExplictBegin(ThreadContext *tc)                        { return; }
    void swAutoBegin(ThreadContext *tc, Addr next_pc)             { return; }
    void swEnd(ThreadContext *tc)                                 { return; }
    void swQ(ThreadContext *tc)                                   { return; }
    void swDq(ThreadContext *tc)                                  { return; }
    void swPq(ThreadContext *tc)                                  { return; }
    void swRq(ThreadContext *tc)                                  { return; }
    void swWf(ThreadContext *tc)                                  { return; }
    void swWe(ThreadContext *tc)                                  { return; }
    void swSq(ThreadContext *tc)                                  { return; }
    void swAq(ThreadContext *tc)                                  { return; }
    void swLink(ThreadContext *tc)                                { return; }
    void swIdentify(ThreadContext *tc)                            { return; }
    uint64_t swGetId(ThreadContext *tc)                         { return 0; }
    void swSyscallLink(ThreadContext *tc)                         { return; }
    void hwBegin(flags f, System *sys, uint64_t frame, std::string sm, 
                 std::string st)                                  { return; }
    void hwQ(flags f, System *sys, uint64_t frame, std::string sm, 
             std::string q, uint64_t qid, System *q_sys = NULL, 
             int32_t count = 1)                                   { return; }
    void hwDq(flags f, System *sys, uint64_t frame, std::string sm, 
              std::string q, uint64_t qid, System *q_sys = NULL, 
              int32_t count = 1)                                  { return; }
    void hwPq(flags f, System *sys, uint64_t frame, std::string sm, 
              std::string q, uint64_t qid, System *q_sys = NULL, 
              int32_t count = 1)                                  { return; }
    void hwRq(flags f, System *sys, uint64_t frame, std::string sm, 
              std::string q, uint64_t qid, System *q_sys = NULL, 
              int32_t count = 1)                                  { return; }
    void hwWf(flags f, System *sys, uint64_t frame, std::string sm, 
              std::string q, uint64_t qid, System *q_sys = NULL, 
              int32_t count = 1)                                  { return; }
    void hwWe(flags f, System *sys, uint64_t frame, std::string sm, 
              std::string q, uint64_t qid, System *q_sys = NULL, 
              int32_t count = 1)                                  { return; }
};
#else
class CPA : SimObject
{
  public:
    typedef CPAParams Params;
    
    /** The known operations that are written to the annotation output file. */
    enum ops {
        OP_BEGIN           = 0x01,
        OP_WAIT_EMPTY      = 0x02,
        OP_WAIT_FULL       = 0x03,
        OP_QUEUE           = 0x04,
        OP_DEQUEUE         = 0x05,
        OP_SIZE_QUEUE      = 0x08,
        OP_PEEK            = 0x09,
        OP_LINK            = 0x0A,
        OP_IDENT           = 0x0B,
        OP_RESERVE         = 0x0C
    };

    /** Flags for the various options.*/
    enum flags {
        /* no flags */
        FL_NONE     = 0x00,
        /* operation was done on hardware */
        FL_HW       = 0x01,
        /* operation should cause a warning when encountered */
        FL_BAD      = 0x02,
        /* Queue like a stack, not a queue */
        FL_QOPP     = 0x04,
        /* Mark HW state as waiting for some non-resource constraint
         * (e.g. wait because SM only starts after 10 items are queued) */ 
        FL_WAIT     = 0x08,
        /* operation is linking to another state machine */
        FL_LINK     = 0x10,
        /* queue should be completely cleared/reset before executing this
         * operation */
        FL_RESET    = 0x20
    };



  protected:
    const Params *
        params() const
        {
            return dynamic_cast<const Params *>(_params);
        }

    /* struct that is written to the annotation output file */
    struct AnnotateData : public RefCounted {

        Tick time;
        uint32_t data;
        uint32_t orig_data;
        uint16_t sm;
        uint16_t stq;
        uint8_t  op;
        uint8_t  flag;
        uint8_t  cpu;
        bool dump;

        void serialize(std::ostream &os);
        void unserialize(Checkpoint *cp, const std::string &section);

    };

    typedef RefCountingPtr<AnnotateData> AnnDataPtr;

    /* header for the annotation file */
    struct AnnotateHeader {
        uint64_t version;
        uint64_t num_recs;
        uint64_t key_off;
        uint64_t idx_off;
        uint32_t key_len;
        uint32_t idx_len;
    };

    AnnotateHeader ah;

    std::vector<uint64_t> annotateIdx;

    // number of state machines encountered in the simulation 
    int numSm;
    // number of states encountered in the simulation 
    int numSmt;
    // number of states/queues for a given state machine/system respectively
    std::vector<int> numSt, numQ;
    // number of systems in the simulation
    int numSys;
    // number of queues in the state machine
    int numQs;
    // maximum connection id assigned so far
    uint64_t conId;

    // Convert state strings into state ids
    typedef m5::hash_map<std::string, int> SCache;
    typedef std::vector<SCache> StCache;

    // Convert sm and queue name,id into queue id
    typedef std::pair<std::string, uint64_t> Id;
    typedef m5::hash_map<Id, int> IdHCache;
    typedef std::vector<IdHCache> IdCache;

    // Hold mapping of sm and queues to output python
    typedef std::vector<std::pair<int, Id> > IdMap;

    // System pointer to name,id
    typedef std::map<System*, std::pair<std::string, int> > NameCache;

    // array of systems each of which is a stack of running sm
    typedef std::pair<int, uint64_t> StackId;
    typedef std::map<StackId, std::vector<int> > SmStack;

    // map of each context and if it's currently in explict state mode
    // states are not automatically updated until it leaves
    typedef std::map<StackId, bool> SwExpl;

    typedef std::map<int,int> IMap;
    // List of annotate records have not been written/completed yet
    typedef std::list<AnnDataPtr> AnnotateList;

    // Maintain link state information
    typedef std::map<int, int> LinkMap;

    // SC Links
    typedef m5::hash_map<Id, AnnDataPtr> ScHCache;
    typedef std::vector<ScHCache> ScCache;


    AnnotateList data;

    // vector indexed by queueid to find current number of elements and bytes
    std::vector<int> qSize;
    std::vector<int32_t> qBytes;


    // Turn state machine string into state machine id (small int)
    // Used for outputting key to convert id back into string
    SCache smtCache;
    // Turn state machine id, state name into state id (small int)
    StCache stCache;
    // turn system, queue, and queue identify into qid (small int)
    // turn system, state, and context into state machine id (small int)
    IdCache qCache, smCache;
    //Link state machines accross system calls
    ScCache scLinks;
    // System pointer to name,id
    NameCache nameCache;
    // Stack of state machines currently nested (should unwind correctly)
    SmStack smStack;
    // Map of currently outstanding links 
    LinkMap lnMap;
    // If the state machine is currently exculding automatic changes
    SwExpl swExpl;
    // Last state that a given state machine was in
    IMap lastState;
    // Hold mapping of sm and queues to output python
    IdMap smMap, qMap;
    // Items still in queue, used for sanity checking 
    std::vector<AnnotateList> qData;

    void doDq(System *sys, int flags, int cpu, int sm, std::string q, int qi,
            int count);
    void doQ(System *sys, int flags, int cpu, int sm, std::string q, int qi,
            int count);

    void doSwSmEnd(System *sys, int cpuid, std::string sm, uint64_t frame);

    // Turn a system id, state machine string, state machine id into a small int
    // for annotation output
    int 
    getSm(int sysi, std::string si, uint64_t id)
    {
        int smi;
        Id smid = Id(si, id);

        smi = smCache[sysi-1][smid];
        if (smi == 0) {
            smCache[sysi-1][smid] = smi = ++numSm;
            assert(smi < 65535);
            smMap.push_back(std::make_pair<int, Id>(sysi, smid));
        }
        return smi;
    }

    // Turn a state machine string, state string into a small int
    // for annotation output
    int 
    getSt(std::string sm, std::string s)
    {
        int sti, smi;

        smi = smtCache[sm];
        if (smi == 0)
           smi = smtCache[sm] = ++numSmt;

        while (stCache.size() < smi) {
            //stCache.resize(sm);
            stCache.push_back(SCache());
            numSt.push_back(0);
        }
        //assert(stCache.size() == sm);
        //assert(numSt.size() == sm);
        sti = stCache[smi-1][s];
        if (sti == 0)
            stCache[smi-1][s] = sti = ++numSt[smi-1];
        return sti;
    }

    // Turn state machine pointer into a smal int for annotation output
    int 
    getSys(System *s)
    {
        NameCache::iterator i = nameCache.find(s);
        if (i == nameCache.end()) {
            nameCache[s] = std::make_pair<std::string,int>(s->name(), ++numSys);
            i = nameCache.find(s);
            // might need to put smstackid into map here, but perhaps not
            //smStack.push_back(std::vector<int>());
            //swExpl.push_back(false);
            numQ.push_back(0);
            qCache.push_back(IdHCache());
            smCache.push_back(IdHCache());
            scLinks.push_back(ScHCache());
        }
        return i->second.second;
    }

    // Turn queue name, and queue context into small int for 
    // annotation output
    int 
    getQ(int sys, std::string q, uint64_t id)
    {
        int qi;
        Id qid = Id(q, id);

        qi = qCache[sys-1][qid];
        if (qi == 0) {
            qi = qCache[sys-1][qid] = ++numQs;
            assert(qi < 65535);
            qSize.push_back(0);
            qBytes.push_back(0);
            qData.push_back(AnnotateList());
            numQ[sys-1]++;
            qMap.push_back(std::make_pair<int, Id>(sys, qid));
        }
        return qi;
    }

    void swBegin(System *sys, int cpuid, std::string st, uint64_t frame, 
            bool expl = false, int flags = FL_NONE);

    AnnDataPtr add(int t, int f, int c, int sm, int stq, int32_t data=0);

    std::ostream *osbin;

    bool _enabled;

    /** Only allow one CPA object in a system. It doesn't make sense to have 
     * more that one per simulation because if a part of the system was
     * important it would have annotations and queues, and with more than one
     * object none of the sanity checking for queues will work. */
    static bool exists;
    static CPA *_cpa;


    std::map<std::string, SymbolTable*> userApp;

  public:
    static CPA *cpa() { return _cpa; }
    void swSmBegin(ThreadContext *tc);
    void swSmEnd(ThreadContext *tc);
    void swExplictBegin(ThreadContext *tc);
    void swAutoBegin(ThreadContext *tc, Addr next_pc);
    void swEnd(ThreadContext *tc);
    void swQ(ThreadContext *tc);
    void swDq(ThreadContext *tc);
    void swPq(ThreadContext *tc);
    void swRq(ThreadContext *tc);
    void swWf(ThreadContext *tc);
    void swWe(ThreadContext *tc);
    void swSq(ThreadContext *tc);
    void swAq(ThreadContext *tc);
    void swLink(ThreadContext *tc);
    void swIdentify(ThreadContext *tc);
    uint64_t swGetId(ThreadContext *tc);
    void swSyscallLink(ThreadContext *tc);

    inline void hwBegin(flags f, System *sys, uint64_t frame, std::string sm, 
            std::string st)
    {
        if (!enabled())
            return;

        int sysi = getSys(sys);
        int smi = getSm(sysi, sm, frame);
        add(OP_BEGIN, FL_HW | f, 0, smi, getSt(sm, st));
        if (f & FL_BAD)
            warn("BAD state encountered: at cycle %d: %s\n", curTick(), st);
    }

    inline void hwQ(flags f, System *sys, uint64_t frame, std::string sm, 
            std::string q, uint64_t qid, System *q_sys = NULL, int32_t count = 1)
    {
        if (!enabled())
            return;

        int sysi = getSys(sys);
        int qi = getQ(q_sys ?  getSys(q_sys) : sysi, q, qid);
        DPRINTFS(AnnotateQ, sys, 
                "hwQ: %s[%#x] cur size %d %d bytes: %d adding: %d\n",
                q, qid, qSize[qi-1], qData[qi-1].size(), qBytes[qi-1], count);
        doQ(sys, FL_HW | f, 0, getSm(sysi, sm, frame), q, qi, count);

    }

    inline void hwDq(flags f, System *sys, uint64_t frame, std::string sm, 
            std::string q, uint64_t qid, System *q_sys = NULL, int32_t count = 1)
    {
        if (!enabled())
            return;

        int sysi = getSys(sys);
        int qi = getQ(q_sys ?  getSys(q_sys) : sysi, q, qid);
        DPRINTFS(AnnotateQ, sys, 
                "hwDQ: %s[%#x] cur size %d %d bytes: %d removing: %d\n",
                q, qid, qSize[qi-1], qData[qi-1].size(), qBytes[qi-1], count);
        doDq(sys, FL_HW | f, 0, getSm(sysi,sm, frame), q, qi, count);
    }

    inline void hwPq(flags f, System *sys, uint64_t frame, std::string sm, 
            std::string q, uint64_t qid, System *q_sys = NULL, int32_t count = 1)
    {
        if (!enabled())
            return;

        int sysi = getSys(sys);
        int qi = getQ(q_sys ?  getSys(q_sys) : sysi, q, qid);
        DPRINTFS(AnnotateQ, sys, 
                "hwPQ: %s[%#x] cur size %d %d bytes: %d peeking: %d\n",
                q, qid, qSize[qi-1], qData[qi-1].size(), qBytes[qi-1], count);
        add(OP_PEEK, FL_HW | f, 0, getSm(sysi, sm, frame), qi, count);
    }

    inline void hwRq(flags f, System *sys, uint64_t frame, std::string sm, 
            std::string q, uint64_t qid, System *q_sys = NULL, int32_t count = 1)
    {
        if (!enabled())
            return;

        int sysi = getSys(sys);
        int qi = getQ(q_sys ?  getSys(q_sys) : sysi, q, qid);
        DPRINTFS(AnnotateQ, sys, 
                "hwRQ: %s[%#x] cur size %d %d bytes: %d reserving: %d\n",
                q, qid, qSize[qi-1], qData[qi-1].size(), qBytes[qi-1], count);
        add(OP_RESERVE, FL_HW | f, 0, getSm(sysi, sm, frame), qi, count);
    }

    inline void hwWf(flags f, System *sys, uint64_t frame, std::string sm, 
            std::string q, uint64_t qid, System *q_sys = NULL, int32_t count = 1)
    {
        if (!enabled())
            return;

        int sysi = getSys(sys);
        int qi = getQ(q_sys ?  getSys(q_sys) : sysi, q, qid);
        add(OP_WAIT_FULL, FL_HW | f, 0, getSm(sysi, sm, frame), qi, count);
    }

    inline void hwWe(flags f, System *sys, uint64_t frame, std::string sm, 
            std::string q, uint64_t qid, System *q_sys = NULL, int32_t count = 1) 
    {
        if (!enabled())
            return;

        int sysi = getSys(sys);
        int qi = getQ(q_sys ?  getSys(q_sys) : sysi, q, qid);
        add(OP_WAIT_EMPTY, FL_HW | f, 0, getSm(sysi, sm, frame), qi, count);
    }

  public:
    CPA(Params *p);
    void startup();

    // This code is ISA specific and will need to be changed
    // if the annotation code is used for something other than Alpha
    inline uint64_t getFrame(ThreadContext *tc)
        { return (tc->readMiscRegNoEffect(TheISA::IPR_PALtemp23) & 
                ~ULL(0x3FFF)); }

    static bool available()  { return true; }

    bool 
    enabled() 
    {   
        if (!this)
            return false;
        return _enabled;
    }
        
    void dump(bool all);
    void dumpKey();

    void serialize(std::ostream &os);
    void unserialize(Checkpoint *cp, const std::string &section);

};
#endif // !CP_ANNOTATE

#endif //__BASE__CP_ANNOTATE_HH__

