/*
 * Copyright (c) 2012-2013, 2021 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) 2001-2005 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.
 */

#ifndef __MEM_FLASH_MEM_HH__
#define __MEM_FLASH_MEM_HH__

#include "mem/abstract_mem.hh"
#include "params/CfiMemory.hh"

namespace gem5
{

namespace memory
{

/**
 * CfiMemory: This is modelling a flash memory adhering to the
 * Common Flash Interface (CFI):
 *
 * JEDEC JESD68.01
 * JEDEC JEP137B
 * Intel Application Note 646
 *
 * This is as of now a pure functional model of a flash controller:
 * no timing/power information has been encoded in it and it is therefore
 * not representive of a real device. Some voltage/timing values have
 * nevertheless been encoded in the CFI table.
 * This is just a requirement from the CFI specification: guest software
 * might query those entries, but they are not reflected in gem5 statistics.
 *
 * The model is meant to be used to allow execution of flash drivers
 * (e.g. UEFI firmware storing EFI variables in non volatile memory)
 */
class CfiMemory : public AbstractMemory
{
  private:
    enum class CfiCommand
    {
        NO_CMD = 0,
        LOCK_BLOCK = 0x1,
        ERASE_BLOCK_SETUP = 0x20,
        WORD_PROGRAM = 0x40,
        CLEAR_STATUS_REG = 0x50,
        LOCK_BLOCK_SETUP = 0x60,
        READ_STATUS_REG = 0x70,
        READ_DEVICE_ID = 0x90,
        READ_CFI_QUERY = 0x98,
        BUFFERED_PROGRAM_SETUP = 0xE8,
        BUFFERED_PROGRAM_CONFIRM = 0xD0,
        BLOCK_ERASE_CONFIRM = 0xD0,
        UNLOCK_BLOCK = 0xD0,
        READ_ARRAY = 0xFF,

        /** This is not a real command, but it is used by the internal
         * model only to represent the 2nd write cycle state for a buffered
         * program (when the buffer size is supplied) */
        BUFFER_SIZE_READ,
    };

    /** Possible in the status register */
    static const uint8_t STATUS_ERASE_ERROR = 0x30;
    static const uint8_t STATUS_LOCK_ERROR = 0x12;
    static const uint8_t STATUS_READY = 0x80;
    static const uint8_t STATUS_PROGRAM_LOCK_BIT = 0x10;

    /** Metadata about the erase blocks in flash */
    struct BlockData : public Serializable
    {
        BlockData(const CfiMemory &_parent, ssize_t number, ssize_t size)
          : Serializable(), locked(number, false), blockSize(size),
            parent(_parent)
        {}

        /**
         * Return true if the block pointed by the block_address
         * parameter is locked
         *
         * @params block_address address of the erase block in flash
         *         memory: first block starts ad address 0x0
         * @return true if block is locked
         */
        bool isLocked(Addr block_address) const;

        /**
         * Lock the block pointed by the block_address
         * parameter
         *
         * @params block_address address of the erase block in flash
         *         memory: first block starts ad address 0x0
         */
        void lock(Addr block_address);

        /**
         * Unlock the block pointed by the block_address
         * parameter
         *
         * @params block_address address of the erase block in flash
         *         memory: first block starts ad address 0x0
         */
        void unlock(Addr block_address);

        /** Erase a single block. The address of the block
         * is supplied by the packet address.
         *
         * @params pkt memory packet targeting the erase block
         */
        void erase(PacketPtr pkt);

        /** Number of erase blocks in flash memory */
        ssize_t number() const { return locked.size(); }

        /** Size in bytes of a single erase block */
        ssize_t size() const { return blockSize; }

      private: // Serializable
        void serialize(CheckpointOut &cp) const override;

        void unserialize(CheckpointIn &cp) override;

      private:
        uint32_t blockIdx(Addr block_address) const;

        // Per block flag. True if the block is locked
        std::vector<bool> locked;

        // Size of the block in bytes
        const ssize_t blockSize;

        const CfiMemory &parent;
    };

    /**
     * Word Buffer used by the BUFFERED PROGRAM command
     * to write (program) chunks of words to flash
     */
    struct ProgramBuffer : public Serializable
    {
      public:
        // program buffer max size = 32 words
        static const ssize_t MAX_BUFFER_SIZE = 32 * 4;

        ProgramBuffer(const CfiMemory &_parent)
          : Serializable(), parent(_parent)
        {}

        /**
         * Start buffering
         * @param buffer_size new size (in bytes) of the program buffer
         */
        void setup(ssize_t buffer_size);

        /**
         * Write data into the buffer. If the buffer is full, the
         * method will return true, meaning it's time to write
         * back the buffer into memory
         *
         * @params flash_address address in flash (relative to the start)
         * @params data_ptr pointer to the data
         * @params size number of bytes to be written to the buffer
         *
         * @return true if buffer needs to be written back to flash
         */
        bool write(Addr flash_address, void *data_ptr, ssize_t size);

        bool writeback();

      private:
        void serialize(CheckpointOut &cp) const override;

        void unserialize(CheckpointIn &cp) override;

      private:
        // program buffer
        std::vector<uint8_t> buffer;

        // Number of bytes written in the buffer
        ssize_t bytesWritten = 0;

        // Pointing to the latest written word in the buffer
        Addr blockPointer = 0;

        const CfiMemory &parent;
    };

    /**
     * A deferred packet stores a packet along with its scheduled
     * transmission time
     */
    class DeferredPacket
    {

      public:

        const Tick tick;
        const PacketPtr pkt;

        DeferredPacket(PacketPtr _pkt, Tick _tick) : tick(_tick), pkt(_pkt)
        { }
    };

    class MemoryPort : public ResponsePort
    {
      private:
        CfiMemory& mem;

      public:
        MemoryPort(const std::string& _name, CfiMemory& _memory);

      protected:
        Tick recvAtomic(PacketPtr pkt) override;
        Tick recvAtomicBackdoor(
                PacketPtr pkt, MemBackdoorPtr &_backdoor) override;
        void recvFunctional(PacketPtr pkt) override;
        bool recvTimingReq(PacketPtr pkt) override;
        void recvRespRetry() override;
        AddrRangeList getAddrRanges() const override;
    };

    MemoryPort port;

    /**
     * Latency from that a request is accepted until the response is
     * ready to be sent.
     */
    const Tick latency;

    /**
     * Fudge factor added to the latency.
     */
    const Tick latency_var;

    /**
     * Internal (unbounded) storage to mimic the delay caused by the
     * actual memory access. Note that this is where the packet spends
     * the memory latency.
     */
    std::list<DeferredPacket> packetQueue;

    /**
     * Bandwidth in ticks per byte. The regulation affects the
     * acceptance rate of requests and the queueing takes place after
     * the regulation.
     */
    const double bandwidth;

    /**
     * Track the state of the memory as either idle or busy, no need
     * for an enum with only two states.
     */
    bool isBusy;

    /**
     * Remember if we have to retry an outstanding request that
     * arrived while we were busy.
     */
    bool retryReq;

    /**
     * Remember if we failed to send a response and are awaiting a
     * retry. This is only used as a check.
     */
    bool retryResp;

    /**
     * Release the memory after being busy and send a retry if a
     * request was rejected in the meanwhile.
     */
    void release();

    EventFunctionWrapper releaseEvent;

    /**
     * Dequeue a packet from our internal packet queue and move it to
     * the port where it will be sent as soon as possible.
     */
    void dequeue();

    EventFunctionWrapper dequeueEvent;

    /**
     * Detemine the latency.
     *
     * @return the latency seen by the current packet
     */
    Tick getLatency() const;

    /**
     * Upstream caches need this packet until true is returned, so
     * hold it for deletion until a subsequent call
     */
    std::unique_ptr<Packet> pendingDelete;

    const uint8_t numberOfChips;

    const uint16_t vendorID;
    const uint16_t deviceID;
    const uint16_t bankWidth;

    /** Previous command (issued in the previous write cycle) */
    CfiCommand readState;
    CfiCommand writeState;

    uint8_t statusRegister;

    BlockData blocks;

    ProgramBuffer programBuffer;

    uint8_t cfiQueryTable[49];

  public:
    CfiMemory(const CfiMemoryParams &p);

    DrainState drain() override;

    Port &getPort(const std::string &if_name,
                  PortID idx=InvalidPortID) override;
    void init() override;

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

  protected:
    Tick recvAtomic(PacketPtr pkt);
    Tick recvAtomicBackdoor(PacketPtr pkt, MemBackdoorPtr &_backdoor);
    void recvFunctional(PacketPtr pkt);
    bool recvTimingReq(PacketPtr pkt);
    void recvRespRetry();

    /** Make a read/write access to the CFI Memory */
    void cfiAccess(PacketPtr pkt);

    /** Write request to the CFI Memory */
    void write(PacketPtr pkt);

    /** Read request to the CFI Memory */
    void read(PacketPtr pkt);

    /**
     * Helper function to read the device identifier after the
     * read state machine is put in the CfiCommand::READ_DEVICE_ID
     * mode.
     *
     * @param flash_address: The flash address LSBits encode the
     *                       the information the software is trying
     *                       to read
     */
    uint64_t readDeviceID(Addr flash_address) const;

    /**
     * Service a new command issued to the flash device
     *
     * @param command: new command issued to the flash device
     */
    void handleCommand(CfiCommand command);

    /** Return the selected entry in the CFI table
     *
     * @param addr: offset in the CFI table
     */
    uint64_t cfiQuery(Addr addr);
};

} // namespace memory
} // namespace gem5

#endif
