/*
 * Copyright (c) 2019 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.
 *
 * 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: Giacomo Travaglini
 */

#ifndef __DEV_ARM_GICV3_ITS_H__
#define __DEV_ARM_GICV3_ITS_H__

#include <queue>

#include "base/coroutine.hh"
#include "dev/dma_device.hh"
#include "params/Gicv3Its.hh"

class Gicv3;
class Gicv3Redistributor;
class ItsProcess;
class ItsTranslation;
class ItsCommand;

enum class ItsActionType
{
    INITIAL_NOP,
    SEND_REQ,
    TERMINATE,
};

struct ItsAction
{
    ItsActionType type;
    PacketPtr pkt;
    Tick delay;
};

/**
 * GICv3 ITS module. This class is just modelling a pio device with its
 * memory mapped registers. Most of the ITS functionalities are
 * implemented as processes (ItsProcess) objects, like ItsTranslation or
 * ItsCommand.
 * Main job of Gicv3Its is to spawn those processes upon receival of packets.
 */
class Gicv3Its : public BasicPioDevice
{
    friend class ::ItsProcess;
    friend class ::ItsTranslation;
    friend class ::ItsCommand;
  public:
    class DataPort : public MasterPort
    {
      protected:
        Gicv3Its &its;

      public:
        DataPort(const std::string &_name, Gicv3Its &_its) :
            MasterPort(_name, &_its),
            its(_its)
        {}

        virtual ~DataPort() {}

        bool recvTimingResp(PacketPtr pkt) { return its.recvTimingResp(pkt); }
        void recvReqRetry() { return its.recvReqRetry(); }
    };

    DataPort dmaPort;

    Port & getPort(const std::string &if_name, PortID idx) override;
    bool recvTimingResp(PacketPtr pkt);
    void recvReqRetry();

    Gicv3Its(const Gicv3ItsParams *params);

    void setGIC(Gicv3 *_gic);

    static const uint32_t itsControl = 0x0;
    static const uint32_t itsTranslate = 0x10000;

    // Address range part of Control frame
    static const AddrRange GITS_BASER;

    static const uint32_t NUM_BASER_REGS = 8;

    enum : Addr
    {
        // Control frame
        GITS_CTLR    = itsControl + 0x0000,
        GITS_IIDR    = itsControl + 0x0004,
        GITS_TYPER   = itsControl + 0x0008,
        GITS_CBASER  = itsControl + 0x0080,
        GITS_CWRITER = itsControl + 0x0088,
        GITS_CREADR  = itsControl + 0x0090,

        // Translation frame
        GITS_TRANSLATER = itsTranslate + 0x0040
    };

    AddrRangeList getAddrRanges() const override;

    Tick read(PacketPtr pkt) override;
    Tick write(PacketPtr pkt) override;

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

    void translate(PacketPtr pkt);

    BitUnion32(CTLR)
        Bitfield<31> quiescent;
        Bitfield<7, 4> itsNumber;
        Bitfield<1> imDe;
        Bitfield<0> enabled;
    EndBitUnion(CTLR)

    // Command read/write, (CREADR, CWRITER)
    BitUnion64(CRDWR)
        Bitfield<19, 5> offset;
        Bitfield<0> retry;
        Bitfield<0> stalled;
    EndBitUnion(CRDWR)

    BitUnion64(CBASER)
        Bitfield<63> valid;
        Bitfield<61, 59> innerCache;
        Bitfield<55, 53> outerCache;
        Bitfield<51, 12> physAddr;
        Bitfield<11, 10> shareability;
        Bitfield<7, 0> size;
    EndBitUnion(CBASER)

    BitUnion64(BASER)
        Bitfield<63> valid;
        Bitfield<62> indirect;
        Bitfield<61, 59> innerCache;
        Bitfield<58, 56> type;
        Bitfield<55, 53> outerCache;
        Bitfield<52, 48> entrySize;
        Bitfield<47, 12> physAddr;
        Bitfield<11, 10> shareability;
        Bitfield<9, 8> pageSize;
        Bitfield<7, 0> size;
    EndBitUnion(BASER)

    BitUnion64(TYPER)
        Bitfield<37> vmovp;
        Bitfield<36> cil;
        Bitfield<35, 32> cidBits;
        Bitfield<31, 24> hcc;
        Bitfield<19> pta;
        Bitfield<18> seis;
        Bitfield<17, 13> devBits;
        Bitfield<12, 8> idBits;
        Bitfield<7, 4> ittEntrySize;
        Bitfield<2> cct;
        Bitfield<1> _virtual;
        Bitfield<0> physical;
    EndBitUnion(TYPER)

    CTLR     gitsControl;
    TYPER    gitsTyper;
    CBASER   gitsCbaser;
    CRDWR    gitsCreadr;
    CRDWR    gitsCwriter;
    uint32_t gitsIidr;
    uint32_t gitsTranslater;

    std::vector<BASER> tableBases;

    /**
     * Returns TRUE if the eventID supplied has bits above the implemented
     * size or above the itt_range
     */
    bool idOutOfRange(uint32_t event_id, uint8_t itt_range) const;

    /**
     * Returns TRUE if the value supplied has bits above the implemented range
     * or if the value supplied exceeds the maximum configured size in the
     * appropriate GITS_BASER<n>
     */
    bool deviceOutOfRange(uint32_t device_id) const;

    /**
     * Returns TRUE if the value (size) supplied exceeds the maximum
     * allowed by GITS_TYPER.ID_bits. Size is the parameter which is
     * passed to the ITS via the MAPD command and is stored in the
     * DTE.ittRange field.
     */
    bool sizeOutOfRange(uint32_t size) const;

    /**
     * Returns TRUE if the value supplied has bits above the implemented range
     * or if the value exceeds the total number of collections supported in
     * hardware and external memory
     */
    bool collectionOutOfRange(uint32_t collection_id) const;

    /**
     * Returns TRUE if the value supplied is larger than that permitted by
     * GICD_TYPER.IDbits or not in the LPI range and is not 1023
     */
    bool lpiOutOfRange(uint32_t intid) const;

  private: // Command
    void checkCommandQueue();
    void incrementReadPointer();

  public: // TableWalk
    BitUnion64(DTE)
        Bitfield<57, 53> ittRange;
        Bitfield<52, 1> ittAddress;
        Bitfield<0> valid;
    EndBitUnion(DTE)

    BitUnion64(ITTE)
        Bitfield<59, 46> vpeid;
        Bitfield<45, 30> icid;
        Bitfield<29, 16> intNumHyp;
        Bitfield<15, 2> intNum;
        Bitfield<1> intType;
        Bitfield<0> valid;
    EndBitUnion(ITTE)

    BitUnion64(CTE)
        Bitfield<40, 1> rdBase;
        Bitfield<0> valid;
    EndBitUnion(CTE)

    enum InterruptType
    {
        VIRTUAL_INTERRUPT = 0,
        PHYSICAL_INTERRUPT = 1
    };

  private:
    Gicv3Redistributor* getRedistributor(uint64_t rd_base);
    Gicv3Redistributor* getRedistributor(CTE cte)
    {
        return getRedistributor(cte.rdBase);
    }

    ItsAction runProcess(ItsProcess *proc, PacketPtr pkt);
    ItsAction runProcessTiming(ItsProcess *proc, PacketPtr pkt);
    ItsAction runProcessAtomic(ItsProcess *proc, PacketPtr pkt);

    enum ItsTables
    {
        DEVICE_TABLE = 1,
        VPE_TABLE = 2,
        TRANSLATION_TABLE = 3,
        COLLECTION_TABLE = 4
    };

    enum PageSize
    {
        SIZE_4K,
        SIZE_16K,
        SIZE_64K
    };

    Addr pageAddress(enum ItsTables table);

    void moveAllPendingState(
        Gicv3Redistributor *rd1, Gicv3Redistributor *rd2);

  private:
    std::queue<ItsAction> packetsToRetry;
    uint32_t masterId;
    Gicv3 *gic;
    EventFunctionWrapper commandEvent;

    bool pendingCommands;
    uint32_t pendingTranslations;
};

/**
 * ItsProcess is a base coroutine wrapper which is spawned by
 * the Gicv3Its module when the latter needs to perform different
 * actions, like translating a peripheral's MSI into an LPI
 * (See derived ItsTranslation) or processing a Command from the
 * ITS queue (ItsCommand).
 * The action to take is implemented by the method:
 *
 * virtual void main(Yield &yield) = 0;
 * It's inheriting from Packet::SenderState since the generic process
 * will be stopped (we are using coroutines) and sent with the packet
 * to memory when doing table walks.
 * When Gicv3Its receives a response, it will resume the coroutine from
 * the point it stopped when yielding.
 */
class ItsProcess : public Packet::SenderState
{
  public:
    using DTE = Gicv3Its::DTE;
    using ITTE = Gicv3Its::ITTE;
    using CTE = Gicv3Its::CTE;
    using Coroutine = m5::Coroutine<PacketPtr, ItsAction>;
    using Yield = Coroutine::CallerType;

    ItsProcess(Gicv3Its &_its);
    virtual ~ItsProcess();

    /** Returns the Gicv3Its name. Mainly used for DPRINTS */
    const std::string name() const;

    ItsAction run(PacketPtr pkt);

  protected:
    void reinit();
    virtual void main(Yield &yield) = 0;

    void writeDeviceTable(Yield &yield, uint32_t device_id, DTE dte);

    void writeIrqTranslationTable(
        Yield &yield, const Addr itt_base, uint32_t event_id, ITTE itte);

    void writeIrqCollectionTable(
        Yield &yield, uint32_t collection_id, CTE cte);

    uint64_t readDeviceTable(
        Yield &yield, uint32_t device_id);

    uint64_t readIrqTranslationTable(
        Yield &yield, const Addr itt_base, uint32_t event_id);

    uint64_t readIrqCollectionTable(Yield &yield, uint32_t collection_id);

    void doRead(Yield &yield, Addr addr, void *ptr, size_t size);
    void doWrite(Yield &yield, Addr addr, void *ptr, size_t size);
    void terminate(Yield &yield);

  protected:
    Gicv3Its &its;

  private:
    std::unique_ptr<Coroutine> coroutine;
};

/**
 * An ItsTranslation is created whenever a peripheral writes a message in
 * GITS_TRANSLATER (MSI). In this case main will simply do the table walks
 * until it gets a redistributor and an INTID. It will then raise the
 * LPI interrupt to the target redistributor.
 */
class ItsTranslation : public ItsProcess
{
  public:
    ItsTranslation(Gicv3Its &_its);
    ~ItsTranslation();

  protected:
    void main(Yield &yield) override;

    std::pair<uint32_t, Gicv3Redistributor *>
    translateLPI(Yield &yield, uint32_t device_id, uint32_t event_id);
};

/**
 * An ItsCommand is created whenever there is a new command in the command
 * queue. Only one command can be executed per time.
 * main will firstly read the command from memory and then it will process
 * it.
 */
class ItsCommand : public ItsProcess
{
  public:
    union CommandEntry
    {
        struct
        {
            uint32_t type;
            uint32_t deviceId;
            uint32_t eventId;
            uint32_t pintId;

            uint32_t data[4];
        };
        uint64_t raw[4];
    };

    enum CommandType : uint32_t
    {
        CLEAR = 0x04,
        DISCARD = 0x0F,
        INT = 0x03,
        INV = 0x0C,
        INVALL = 0x0D,
        MAPC = 0x09,
        MAPD = 0x08,
        MAPI = 0x0B,
        MAPTI = 0x0A,
        MOVALL = 0x0E,
        MOVI = 0x01,
        SYNC = 0x05,
        VINVALL = 0x2D,
        VMAPI = 0x2B,
        VMAPP = 0x29,
        VMAPTI = 0x2A,
        VMOVI = 0x21,
        VMOVP = 0x22,
        VSYNC = 0x25
    };

    ItsCommand(Gicv3Its &_its);
    ~ItsCommand();

  protected:
    /**
     * Dispatch entry is a metadata struct which contains information about
     * the command (like the name) and the function object implementing
     * the command.
     */
    struct DispatchEntry
    {
        using ExecFn = std::function<void(ItsCommand*, Yield&, CommandEntry&)>;

        DispatchEntry(std::string _name, ExecFn _exec)
          : name(_name), exec(_exec)
        {}

        std::string name;
        ExecFn exec;
    };

    using DispatchTable = std::unordered_map<
        std::underlying_type<enum CommandType>::type, DispatchEntry>;

    static DispatchTable cmdDispatcher;

    static std::string commandName(uint32_t cmd);

    void main(Yield &yield) override;

    void readCommand(Yield &yield, CommandEntry &command);
    void processCommand(Yield &yield, CommandEntry &command);

    // Commands
    void clear(Yield &yield, CommandEntry &command);
    void discard(Yield &yield, CommandEntry &command);
    void mapc(Yield &yield, CommandEntry &command);
    void mapd(Yield &yield, CommandEntry &command);
    void mapi(Yield &yield, CommandEntry &command);
    void mapti(Yield &yield, CommandEntry &command);
    void movall(Yield &yield, CommandEntry &command);
    void movi(Yield &yield, CommandEntry &command);
    void sync(Yield &yield, CommandEntry &command);
    void doInt(Yield &yield, CommandEntry &command);
    void inv(Yield &yield, CommandEntry &command);
    void invall(Yield &yield, CommandEntry &command);
    void vinvall(Yield &yield, CommandEntry &command);
    void vmapi(Yield &yield, CommandEntry &command);
    void vmapp(Yield &yield, CommandEntry &command);
    void vmapti(Yield &yield, CommandEntry &command);
    void vmovi(Yield &yield, CommandEntry &command);
    void vmovp(Yield &yield, CommandEntry &command);
    void vsync(Yield &yield, CommandEntry &command);

  protected: // Helpers
    bool idOutOfRange(CommandEntry &command, DTE dte) const
    {
        return its.idOutOfRange(command.eventId, dte.ittRange);
    }

    bool deviceOutOfRange(CommandEntry &command) const
    {
        return its.deviceOutOfRange(command.deviceId);
    }

    bool sizeOutOfRange(CommandEntry &command) const
    {
        const auto size = bits(command.raw[1], 4, 0);
        const auto valid = bits(command.raw[2], 63);
        if (valid)
            return its.sizeOutOfRange(size);
        else
            return false;
    }

    bool collectionOutOfRange(CommandEntry &command) const
    {
        return its.collectionOutOfRange(bits(command.raw[2], 15, 0));
    }
};

#endif
