/*
 * Copyright (c) 2012, 2014, 2018 ARM Limited
 * All rights reserved
 *
 * The license below extends only to copyright in the software and shall
 * not be construed as granting a license to any other intellectual
 * property including but not limited to intellectual property relating
 * to a hardware implementation of the functionality of the software
 * licensed hereunder.  You may use the software subject to the license
 * terms below provided that you ensure that this notice is replicated
 * unmodified and in its entirety in all distributions of the software,
 * modified or unmodified, in source code or in binary form.
 *
 * Copyright (c) 2002-2005 The Regents of The University of Michigan
 * Copyright (c) 2011 Regents of the University of California
 * 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.
 */

#ifndef __SYSTEM_HH__
#define __SYSTEM_HH__

#include <set>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>

#include "arch/page_size.hh"
#include "base/loader/memory_image.hh"
#include "base/loader/symtab.hh"
#include "base/statistics.hh"
#include "config/the_isa.hh"
#include "cpu/pc_event.hh"
#include "enums/MemoryMode.hh"
#include "mem/mem_requestor.hh"
#include "mem/physical.hh"
#include "mem/port.hh"
#include "mem/port_proxy.hh"
#include "params/System.hh"
#include "sim/futex_map.hh"
#include "sim/mem_pool.hh"
#include "sim/redirect_path.hh"
#include "sim/se_signal.hh"
#include "sim/sim_object.hh"
#include "sim/workload.hh"

namespace gem5
{

class BaseRemoteGDB;
class KvmVM;
class ThreadContext;

class System : public SimObject, public PCEventScope
{
  private:

    /**
     * Private class for the system port which is only used as a
     * requestor for debug access and for non-structural entities that do
     * not have a port of their own.
     */
    class SystemPort : public RequestPort
    {
      public:

        /**
         * Create a system port with a name and an owner.
         */
        SystemPort(const std::string &_name, SimObject *_owner)
            : RequestPort(_name, _owner)
        { }

        bool
        recvTimingResp(PacketPtr pkt) override
        {
            panic("SystemPort does not receive timing!");
        }

        void
        recvReqRetry() override
        {
            panic("SystemPort does not expect retry!");
        }
    };

    std::list<PCEvent *> liveEvents;
    SystemPort _systemPort;

    // Map of memory address ranges for devices with their own backing stores
    std::unordered_map<RequestorID, std::vector<AbstractMemory *>>
        deviceMemMap;

  public:

    class Threads
    {
      private:
        struct Thread
        {
            ThreadContext *context = nullptr;
            bool active = false;
            Event *resumeEvent = nullptr;

            void resume();
            std::string name() const;
            void quiesce() const;
        };

        std::vector<Thread> threads;

        Thread &
        thread(ContextID id)
        {
            assert(id < size());
            return threads[id];
        }

        const Thread &
        thread(ContextID id) const
        {
            assert(id < size());
            return threads[id];
        }

        void insert(ThreadContext *tc, ContextID id=InvalidContextID);
        void replace(ThreadContext *tc, ContextID id);

        friend class System;

      public:
        class const_iterator
        {
          private:
            const Threads &threads;
            int pos;

            friend class Threads;

            const_iterator(const Threads &_threads, int _pos) :
                threads(_threads), pos(_pos)
            {}

          public:
            const_iterator(const const_iterator &) = default;
            const_iterator &operator = (const const_iterator &) = default;

            using iterator_category = std::forward_iterator_tag;
            using value_type = ThreadContext *;
            using difference_type = int;
            using pointer = const value_type *;
            using reference = const value_type &;

            const_iterator &
            operator ++ ()
            {
                pos++;
                return *this;
            }

            const_iterator
            operator ++ (int)
            {
                return const_iterator(threads, pos++);
            }

            reference operator * () { return threads.thread(pos).context; }
            pointer operator -> () { return &threads.thread(pos).context; }

            bool
            operator == (const const_iterator &other) const
            {
                return &threads == &other.threads && pos == other.pos;
            }

            bool
            operator != (const const_iterator &other) const
            {
                return !(*this == other);
            }
        };

        ThreadContext *findFree();

        ThreadContext *
        operator [](ContextID id) const
        {
            return thread(id).context;
        }

        void markActive(ContextID id) { thread(id).active = true; }

        int size() const { return threads.size(); }
        bool empty() const { return threads.empty(); }
        int numRunning() const;
        int
        numActive() const
        {
            int count = 0;
            for (auto &thread: threads) {
                if (thread.active)
                    count++;
            }
            return count;
        }

        void quiesce(ContextID id);
        void quiesceTick(ContextID id, Tick when);

        const_iterator begin() const { return const_iterator(*this, 0); }
        const_iterator end() const { return const_iterator(*this, size()); }
    };

    /**
     * Get a reference to the system port that can be used by
     * non-structural simulation objects like processes or threads, or
     * external entities like loaders and debuggers, etc, to access
     * the memory system.
     *
     * @return a reference to the system port we own
     */
    RequestPort& getSystemPort() { return _systemPort; }

    /**
     * Additional function to return the Port of a memory object.
     */
    Port &getPort(const std::string &if_name,
                  PortID idx=InvalidPortID) override;

    /** @{ */
    /**
     * Is the system in atomic mode?
     *
     * There are currently two different atomic memory modes:
     * 'atomic', which supports caches; and 'atomic_noncaching', which
     * bypasses caches. The latter is used by hardware virtualized
     * CPUs. SimObjects are expected to use Port::sendAtomic() and
     * Port::recvAtomic() when accessing memory in this mode.
     */
    bool
    isAtomicMode() const
    {
        return memoryMode == enums::atomic ||
            memoryMode == enums::atomic_noncaching;
    }

    /**
     * Is the system in timing mode?
     *
     * SimObjects are expected to use Port::sendTiming() and
     * Port::recvTiming() when accessing memory in this mode.
     */
    bool isTimingMode() const { return memoryMode == enums::timing; }

    /**
     * Should caches be bypassed?
     *
     * Some CPUs need to bypass caches to allow direct memory
     * accesses, which is required for hardware virtualization.
     */
    bool
    bypassCaches() const
    {
        return memoryMode == enums::atomic_noncaching;
    }
    /** @} */

    /** @{ */
    /**
     * Get the memory mode of the system.
     *
     * \warn This should only be used by the Python world. The C++
     * world should use one of the query functions above
     * (isAtomicMode(), isTimingMode(), bypassCaches()).
     */
    enums::MemoryMode getMemoryMode() const { return memoryMode; }

    /**
     * Change the memory mode of the system.
     *
     * \warn This should only be called by the Python!
     *
     * @param mode Mode to change to (atomic/timing/...)
     */
    void setMemoryMode(enums::MemoryMode mode);
    /** @} */

    /**
     * Get the cache line size of the system.
     */
    unsigned int cacheLineSize() const { return _cacheLineSize; }

    Threads threads;

    const bool multiThread;

    using SimObject::schedule;

    bool schedule(PCEvent *event) override;
    bool remove(PCEvent *event) override;

    /** Memory allocation objects for all physical memories in the system. */
    std::vector<MemPool> memPools;

    uint64_t init_param;

    /** Port to physical memory used for writing object files into ram at
     * boot.*/
    PortProxy physProxy;

    /** OS kernel */
    Workload *workload = nullptr;

  public:
    /**
     * Get a pointer to the Kernel Virtual Machine (KVM) SimObject,
     * if present.
     */
    KvmVM *getKvmVM() { return kvmVM; }

    /** Verify gem5 configuration will support KVM emulation */
    bool validKvmEnvironment() const;

    /** Get a pointer to access the physical memory of the system */
    PhysicalMemory& getPhysMem() { return physmem; }

    /** Amount of physical memory that is still free */
    Addr freeMemSize(int poolID = 0) const;

    /** Amount of physical memory that exists */
    Addr memSize(int poolID = 0) const;

    /**
     * Check if a physical address is within a range of a memory that
     * is part of the global address map.
     *
     * @param addr A physical address
     * @return Whether the address corresponds to a memory
     */
    bool isMemAddr(Addr addr) const;

    /**
     * Add a physical memory range for a device. The ranges added here will
     * be considered a non-PIO memory address if the requestorId of the packet
     * and range match something in the device memory map.
     */
    void addDeviceMemory(RequestorID requestorId,
                      AbstractMemory *deviceMemory);

    /**
     * Similar to isMemAddr but for devices. Checks if a physical address
     * of the packet match an address range of a device corresponding to the
     * RequestorId of the request.
     */
    bool isDeviceMemAddr(const PacketPtr& pkt) const;

    /**
     * Return a pointer to the device memory.
     */
    AbstractMemory *getDeviceMemory(const PacketPtr& pkt) const;

    /*
     * Return the list of address ranges backed by a shadowed ROM.
     *
     * @return List of address ranges backed by a shadowed ROM
     */
    AddrRangeList getShadowRomRanges() const { return ShadowRomRanges; }

    /**
     * Get the architecture.
     */
    Arch getArch() const { return Arch::TheISA; }

    /**
     * Get the guest byte order.
     */
    ByteOrder
    getGuestByteOrder() const
    {
        return params().byte_order;
    }

     /**
     * Get the page bytes for the ISA.
     */
    Addr getPageBytes() const { return TheISA::PageBytes; }

    /**
     * Get the number of bits worth of in-page address for the ISA.
     */
    Addr getPageShift() const { return TheISA::PageShift; }

    /**
     * The thermal model used for this system (if any).
     */
    ThermalModel * getThermalModel() const { return thermalModel; }

  protected:

    KvmVM *const kvmVM = nullptr;

    PhysicalMemory physmem;

    AddrRangeList ShadowRomRanges;

    enums::MemoryMode memoryMode;

    const unsigned int _cacheLineSize;

    uint64_t workItemsBegin = 0;
    uint64_t workItemsEnd = 0;
    uint32_t numWorkIds;

    /** This array is a per-system list of all devices capable of issuing a
     * memory system request and an associated string for each requestor id.
     * It's used to uniquely id any requestor in the system by name for things
     * like cache statistics.
     */
    std::vector<RequestorInfo> requestors;

    ThermalModel * thermalModel;

  protected:
    /**
     * Strips off the system name from a requestor name
     */
    std::string stripSystemName(const std::string& requestor_name) const;

  public:

    /**
     * Request an id used to create a request object in the system. All objects
     * that intend to issues requests into the memory system must request an id
     * in the init() phase of startup. All requestor ids must be fixed by the
     * regStats() phase that immediately precedes it. This allows objects in
     * the memory system to understand how many requestors may exist and
     * appropriately name the bins of their per-requestor stats before the
     * stats are finalized.
     *
     * Registers a RequestorID:
     * This method takes two parameters, one of which is optional.
     * The first one is the requestor object, and it is compulsory; in case
     * a object has multiple (sub)requestors, a second parameter must be
     * provided and it contains the name of the subrequestor. The method will
     * create a requestor's name by concatenating the SimObject name with the
     * eventual subrequestor string, separated by a dot.
     *
     * As an example:
     * For a cpu having two requestors: a data requestor and an
     * instruction requestor,
     * the method must be called twice:
     *
     * instRequestorId = getRequestorId(cpu, "inst");
     * dataRequestorId = getRequestorId(cpu, "data");
     *
     * and the requestors' names will be:
     * - "cpu.inst"
     * - "cpu.data"
     *
     * @param requestor SimObject related to the requestor
     * @param subrequestor String containing the subrequestor's name
     * @return the requestor's ID.
     */
    RequestorID getRequestorId(const SimObject* requestor,
                         std::string subrequestor={});

    /**
     * Registers a GLOBAL RequestorID, which is a RequestorID not related
     * to any particular SimObject; since no SimObject is passed,
     * the requestor gets registered by providing the full requestor name.
     *
     * @param requestorName full name of the requestor
     * @return the requestor's ID.
     */
    RequestorID getGlobalRequestorId(const std::string& requestor_name);

    /**
     * Get the name of an object for a given request id.
     */
    std::string getRequestorName(RequestorID requestor_id);

    /**
     * Looks up the RequestorID for a given SimObject
     * returns an invalid RequestorID (invldRequestorId) if not found.
     */
    RequestorID lookupRequestorId(const SimObject* obj) const;

    /**
     * Looks up the RequestorID for a given object name string
     * returns an invalid RequestorID (invldRequestorId) if not found.
     */
    RequestorID lookupRequestorId(const std::string& name) const;

    /** Get the number of requestors registered in the system */
    RequestorID maxRequestors() { return requestors.size(); }

  protected:
    /** helper function for getRequestorId */
    RequestorID _getRequestorId(const SimObject* requestor,
                          const std::string& requestor_name);

    /**
     * Helper function for constructing the full (sub)requestor name
     * by providing the root requestor and the relative subrequestor name.
     */
    std::string leafRequestorName(const SimObject* requestor,
                               const std::string& subrequestor);

  public:

    void regStats() override;
    /**
     * Called by pseudo_inst to track the number of work items started by this
     * system.
     */
    uint64_t
    incWorkItemsBegin()
    {
        return ++workItemsBegin;
    }

    /**
     * Called by pseudo_inst to track the number of work items completed by
     * this system.
     */
    uint64_t
    incWorkItemsEnd()
    {
        return ++workItemsEnd;
    }

    /**
     * Called by pseudo_inst to mark the cpus actively executing work items.
     * Returns the total number of cpus that have executed work item begin or
     * ends.
     */
    int
    markWorkItem(int index)
    {
        threads.markActive(index);
        return threads.numActive();
    }

    void
    workItemBegin(uint32_t tid, uint32_t workid)
    {
        std::pair<uint32_t, uint32_t> p(tid, workid);
        lastWorkItemStarted[p] = curTick();
    }

    void workItemEnd(uint32_t tid, uint32_t workid);

    /* Returns whether we successfully trapped into GDB. */
    bool trapToGdb(int signal, ContextID ctx_id) const;

  protected:
    /**
     * Range for memory-mapped m5 pseudo ops. The range will be
     * invalid/empty if disabled.
     */
    const AddrRange _m5opRange;

  public:
    PARAMS(System);

    System(const Params &p);
    ~System();

    /**
     * Range used by memory-mapped m5 pseudo-ops if enabled. Returns
     * an invalid/empty range if disabled.
     */
    const AddrRange &m5opRange() const { return _m5opRange; }

  public:

    /// Allocate npages contiguous unused physical pages
    /// @return Starting address of first page
    Addr allocPhysPages(int npages, int poolID = 0);

    void registerThreadContext(
            ThreadContext *tc, ContextID assigned=InvalidContextID);
    void replaceThreadContext(ThreadContext *tc, ContextID context_id);

    void serialize(CheckpointOut &cp) const override;
    void unserialize(CheckpointIn &cp) override;

  public:
    std::map<std::pair<uint32_t, uint32_t>, Tick>  lastWorkItemStarted;
    std::map<uint32_t, statistics::Histogram*> workItemStats;

    ////////////////////////////////////////////
    //
    // STATIC GLOBAL SYSTEM LIST
    //
    ////////////////////////////////////////////

    static std::vector<System *> systemList;
    static int numSystemsRunning;

    static void printSystems();

    FutexMap futexMap;

    static const int maxPID = 32768;

    /** Process set to track which PIDs have already been allocated */
    std::set<int> PIDs;

    // By convention, all signals are owned by the receiving process. The
    // receiver will delete the signal upon reception.
    std::list<BasicSignal> signalList;

    // Used by syscall-emulation mode. This member contains paths which need
    // to be redirected to the faux-filesystem (a duplicate filesystem
    // intended to replace certain files on the host filesystem).
    std::vector<RedirectPath*> redirectPaths;
};

void printSystems();

} // namespace gem5

#endif // __SYSTEM_HH__
