/*
 * Copyright (c) 2010-2013, 2015, 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.
 */

#include "mem/cfi_mem.hh"

#include <cmath>

#include "base/intmath.hh"
#include "base/random.hh"
#include "base/trace.hh"
#include "debug/CFI.hh"
#include "debug/Drain.hh"

namespace gem5
{

bool
CfiMemory::BlockData::isLocked(Addr block_address) const
{
    return locked[blockIdx(block_address)];
}

void
CfiMemory::BlockData::lock(Addr block_address)
{
    locked[blockIdx(block_address)] = true;
}

void
CfiMemory::BlockData::unlock(Addr block_address)
{
    locked[blockIdx(block_address)] = false;
}

void
CfiMemory::BlockData::serialize(CheckpointOut &cp) const
{
    SERIALIZE_CONTAINER(locked);
}

void
CfiMemory::BlockData::unserialize(CheckpointIn &cp)
{
    UNSERIALIZE_CONTAINER(locked);
}

uint32_t
CfiMemory::BlockData::blockIdx(Addr block_address) const
{
    return block_address / blockSize;
}

void
CfiMemory::ProgramBuffer::setup(ssize_t buffer_size)
{
    /** Clipping the size to its limit */
    if (buffer_size > MAX_BUFFER_SIZE) {
        buffer_size = MAX_BUFFER_SIZE;
    }

    buffer.resize(buffer_size);
    std::fill(buffer.begin(), buffer.end(), 0);
    bytesWritten = 0;
}

bool
CfiMemory::ProgramBuffer::write(Addr flash_address,
    void *data_ptr, ssize_t size)
{
    if (bytesWritten >= buffer.size())
        return true;

    if (bytesWritten == 0) {
        blockPointer = flash_address;
    }

    const Addr offset = flash_address - blockPointer;

    if (flash_address < blockPointer || offset >= MAX_BUFFER_SIZE)
        return true;

    std::memcpy(buffer.data() + offset, data_ptr, size);
    bytesWritten += size;

    return false;
}

bool
CfiMemory::ProgramBuffer::writeback()
{
    if (parent.blocks.isLocked(blockPointer)) {
        return false;
    } else {
        std::memcpy(parent.toHostAddr(parent.start() + blockPointer),
            buffer.data(), bytesWritten);
        return true;
    }
}

void
CfiMemory::ProgramBuffer::serialize(CheckpointOut &cp) const
{
    SERIALIZE_CONTAINER(buffer);
    SERIALIZE_SCALAR(bytesWritten);
    SERIALIZE_SCALAR(blockPointer);
}

void
CfiMemory::ProgramBuffer::unserialize(CheckpointIn &cp)
{
    UNSERIALIZE_CONTAINER(buffer);
    UNSERIALIZE_SCALAR(bytesWritten);
    UNSERIALIZE_SCALAR(blockPointer);
}

CfiMemory::CfiMemory(const CfiMemoryParams &p)
  : AbstractMemory(p),
    port(name() + ".port", *this), latency(p.latency),
    latency_var(p.latency_var), bandwidth(p.bandwidth), isBusy(false),
    retryReq(false), retryResp(false),
    releaseEvent([this]{ release(); }, name()),
    dequeueEvent([this]{ dequeue(); }, name()),
    numberOfChips(2),
    vendorID(p.vendor_id),
    deviceID(p.device_id),
    bankWidth(p.bank_width),
    readState(CfiCommand::READ_ARRAY), writeState(CfiCommand::NO_CMD),
    statusRegister(STATUS_READY),
    blocks(*this, size() / p.blk_size, p.blk_size),
    programBuffer(*this),
    cfiQueryTable{
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        /* Query-unique ASCII string */
        'Q', 'R', 'Y',
        /* Primary Algorithm Command Set and Control = Intel/Sharp */
        0x01, 0x00,
        /* Address for Primary Algorithm extended Query */
        0x31, 0x00,
        /* Alternative Algorithm Command Set and Control Interface */
        0x00, 0x00,
        /* Address for Alternative Algorithm extended Query */
        0x00, 0x00,
        /* Vcc Minimum Program/Erase or Write voltage ([7:4].[3-0]V) */
        0x45,
        /* Vcc Maximum Program/Erase or Write voltage ([7:4].[3-0]V) */
        0x55,
        /* Vpp Minimum Program/Erase voltage (0 = No Vpp pin) */
        0x00,
        /* Vpp Minimum Program/Erase voltage (0 = No Vpp pin) */
        0x00,
        /* Typical timeout per single byte/word/D-word program: (2^N us) */
        0x01,
        /* Typical timeout for maximum-size multi-byte program: (2^N us) */
        0x01,
        /* Typical timeout per individual block erase: (2^N ms) */
        0x01,
        /* Typical timeout for full chip erase: (2^N ms) */
        0x00,
        /* Maximum timeout for byte/word/D-word program (2^N typical) */
        0x00,
        /* Maximum timeout for multi-byte program (2^N typical) */
        0x00,
        /* Maximum timeout per individual block erase (2^N typical) */
        0x00,
        /* Maximum timeout for chip erase (2^N typical) */
        0x00,
        /* Device Size in number of bytes (2^N) */
        static_cast<uint8_t>(log2(size())),
        /* Flash Device Interface Code description */
        0x05, 0x00,
        /* Maximum number of bytes in multi-byte program (2^N) */
        static_cast<uint8_t>(bits(log2i(ProgramBuffer::MAX_BUFFER_SIZE), 7, 0)),
        static_cast<uint8_t>(bits(log2i(ProgramBuffer::MAX_BUFFER_SIZE), 15, 8)),
        /* Number of Erase Block Regions within device */
        0x01,
        /* Erase Block Region Information */
        static_cast<uint8_t>(bits(blocks.number(), 7, 0)),
        static_cast<uint8_t>(bits(blocks.number(), 15, 8)),
        static_cast<uint8_t>(bits(blocks.size(), 7, 0)),
        static_cast<uint8_t>(bits(blocks.size(), 15, 8)),
    }
{}

void
CfiMemory::init()
{
    AbstractMemory::init();

    // allow unconnected memories as this is used in several ruby
    // systems at the moment
    if (port.isConnected()) {
        port.sendRangeChange();
    }
}

Tick
CfiMemory::recvAtomic(PacketPtr pkt)
{
    panic_if(pkt->cacheResponding(), "Should not see packets where cache "
             "is responding");

    cfiAccess(pkt);
    return getLatency();
}

Tick
CfiMemory::recvAtomicBackdoor(PacketPtr pkt, MemBackdoorPtr &_backdoor)
{
    Tick latency = recvAtomic(pkt);

    if (backdoor.ptr())
        _backdoor = &backdoor;
    return latency;
}

void
CfiMemory::recvFunctional(PacketPtr pkt)
{
    pkt->pushLabel(name());

    functionalAccess(pkt);

    bool done = false;
    auto p = packetQueue.begin();
    // potentially update the packets in our packet queue as well
    while (!done && p != packetQueue.end()) {
        done = pkt->trySatisfyFunctional(p->pkt);
        ++p;
    }

    pkt->popLabel();
}

bool
CfiMemory::recvTimingReq(PacketPtr pkt)
{
    panic_if(pkt->cacheResponding(), "Should not see packets where cache "
             "is responding");

    panic_if(!(pkt->isRead() || pkt->isWrite()),
             "Should only see read and writes at memory controller, "
             "saw %s to %#llx\n", pkt->cmdString(), pkt->getAddr());

    // we should not get a new request after committing to retry the
    // current one, but unfortunately the CPU violates this rule, so
    // simply ignore it for now
    if (retryReq)
        return false;

    // if we are busy with a read or write, remember that we have to
    // retry
    if (isBusy) {
        retryReq = true;
        return false;
    }

    // technically the packet only reaches us after the header delay,
    // and since this is a memory controller we also need to
    // deserialise the payload before performing any write operation
    Tick receive_delay = pkt->headerDelay + pkt->payloadDelay;
    pkt->headerDelay = pkt->payloadDelay = 0;

    // update the release time according to the bandwidth limit, and
    // do so with respect to the time it takes to finish this request
    // rather than long term as it is the short term data rate that is
    // limited for any real memory

    // calculate an appropriate tick to release to not exceed
    // the bandwidth limit
    Tick duration = pkt->getSize() * bandwidth;

    // only consider ourselves busy if there is any need to wait
    // to avoid extra events being scheduled for (infinitely) fast
    // memories
    if (duration != 0) {
        schedule(releaseEvent, curTick() + duration);
        isBusy = true;
    }

    // go ahead and deal with the packet and put the response in the
    // queue if there is one
    bool needs_response = pkt->needsResponse();
    recvAtomic(pkt);
    // turn packet around to go back to requester if response expected
    if (needs_response) {
        // recvAtomic() should already have turned packet into
        // atomic response
        assert(pkt->isResponse());

        Tick when_to_send = curTick() + receive_delay + getLatency();

        // typically this should be added at the end, so start the
        // insertion sort with the last element, also make sure not to
        // re-order in front of some existing packet with the same
        // address, the latter is important as this memory effectively
        // hands out exclusive copies (shared is not asserted)
        auto i = packetQueue.end();
        --i;
        while (i != packetQueue.begin() && when_to_send < i->tick &&
               !i->pkt->matchAddr(pkt)) {
            --i;
        }

        // emplace inserts the element before the position pointed to by
        // the iterator, so advance it one step
        packetQueue.emplace(++i, pkt, when_to_send);

        if (!retryResp && !dequeueEvent.scheduled())
            schedule(dequeueEvent, packetQueue.back().tick);
    } else {
        pendingDelete.reset(pkt);
    }

    return true;
}

void
CfiMemory::release()
{
    assert(isBusy);
    isBusy = false;
    if (retryReq) {
        retryReq = false;
        port.sendRetryReq();
    }
}

void
CfiMemory::dequeue()
{
    assert(!packetQueue.empty());
    DeferredPacket deferred_pkt = packetQueue.front();

    retryResp = !port.sendTimingResp(deferred_pkt.pkt);

    if (!retryResp) {
        packetQueue.pop_front();

        // if the queue is not empty, schedule the next dequeue event,
        // otherwise signal that we are drained if we were asked to do so
        if (!packetQueue.empty()) {
            // if there were packets that got in-between then we
            // already have an event scheduled, so use re-schedule
            reschedule(dequeueEvent,
                       std::max(packetQueue.front().tick, curTick()), true);
        } else if (drainState() == DrainState::Draining) {
            DPRINTF(Drain, "Draining of CfiMemory complete\n");
            signalDrainDone();
        }
    }
}

Tick
CfiMemory::getLatency() const
{
    return latency +
        (latency_var ? random_mt.random<Tick>(0, latency_var) : 0);
}

void
CfiMemory::recvRespRetry()
{
    assert(retryResp);

    dequeue();
}

Port &
CfiMemory::getPort(const std::string &if_name, PortID idx)
{
    if (if_name != "port") {
        return AbstractMemory::getPort(if_name, idx);
    } else {
        return port;
    }
}

DrainState
CfiMemory::drain()
{
    if (!packetQueue.empty()) {
        DPRINTF(Drain, "CfiMemory Queue has requests, waiting to drain\n");
        return DrainState::Draining;
    } else {
        return DrainState::Drained;
    }
}

void
CfiMemory::serialize(CheckpointOut &cp) const
{
    SERIALIZE_ENUM(readState);
    SERIALIZE_ENUM(writeState);

    SERIALIZE_SCALAR(statusRegister);

    SERIALIZE_OBJ(blocks);
    SERIALIZE_OBJ(programBuffer);
}

void
CfiMemory::unserialize(CheckpointIn &cp)
{
    UNSERIALIZE_ENUM(readState);
    UNSERIALIZE_ENUM(writeState);

    UNSERIALIZE_SCALAR(statusRegister);

    UNSERIALIZE_OBJ(blocks);
    UNSERIALIZE_OBJ(programBuffer);
}

CfiMemory::MemoryPort::MemoryPort(const std::string& _name,
                                     CfiMemory& _memory)
    : ResponsePort(_name, &_memory), mem(_memory)
{ }

AddrRangeList
CfiMemory::MemoryPort::getAddrRanges() const
{
    AddrRangeList ranges;
    ranges.push_back(mem.getAddrRange());
    return ranges;
}

Tick
CfiMemory::MemoryPort::recvAtomic(PacketPtr pkt)
{
    return mem.recvAtomic(pkt);
}

Tick
CfiMemory::MemoryPort::recvAtomicBackdoor(
        PacketPtr pkt, MemBackdoorPtr &_backdoor)
{
    return mem.recvAtomicBackdoor(pkt, _backdoor);
}

void
CfiMemory::MemoryPort::recvFunctional(PacketPtr pkt)
{
    mem.recvFunctional(pkt);
}

bool
CfiMemory::MemoryPort::recvTimingReq(PacketPtr pkt)
{
    return mem.recvTimingReq(pkt);
}

void
CfiMemory::MemoryPort::recvRespRetry()
{
    mem.recvRespRetry();
}

void
CfiMemory::cfiAccess(PacketPtr pkt)
{
    if (pkt->isWrite()) {
        write(pkt);
    } else {
        read(pkt);
    }
}

void
CfiMemory::write(PacketPtr pkt)
{
    DPRINTF(CFI, "write, address: %#x, val: %#x\n", pkt->getAddr(),
        pkt->getUintX(ByteOrder::little));

    const Addr flash_address = pkt->getAddr() - start();

    const uint16_t value = pkt->getUintX(ByteOrder::little) & 0xffff;
    const auto new_cmd = static_cast<CfiCommand>(value & 0xff);

    switch (writeState) {
        case CfiCommand::NO_CMD:
          handleCommand(new_cmd);
          break;

        case CfiCommand::ERASE_BLOCK_SETUP:
          if (new_cmd == CfiCommand::BLOCK_ERASE_CONFIRM) {
              // Erasing the block
              // Check if block is locked
              if (blocks.isLocked(flash_address)) {
                  statusRegister |= STATUS_LOCK_ERROR;
              } else {
                  blocks.erase(pkt);
              }
          } else {
              statusRegister |= STATUS_ERASE_ERROR;
          }
          writeState = CfiCommand::NO_CMD;
          readState = CfiCommand::READ_STATUS_REG;
          break;

        case CfiCommand::LOCK_BLOCK_SETUP:
          if (new_cmd == CfiCommand::LOCK_BLOCK) {

              // Lock the addressed block
              blocks.lock(flash_address);
              readState = CfiCommand::READ_STATUS_REG;

          } else if (new_cmd == CfiCommand::UNLOCK_BLOCK) {

              // Unlock the addressed block
              blocks.unlock(flash_address);
              readState = CfiCommand::READ_STATUS_REG;

          } else {
              statusRegister |= STATUS_ERASE_ERROR;
          }

          writeState = CfiCommand::NO_CMD;
          break;

        case CfiCommand::WORD_PROGRAM:
          readState = CfiCommand::READ_STATUS_REG;
          writeState = CfiCommand::NO_CMD;

          if (blocks.isLocked(flash_address)) {
              statusRegister |= STATUS_LOCK_ERROR;
          } else {
              AbstractMemory::access(pkt);
              return;
          }
          break;

        case CfiCommand::BUFFERED_PROGRAM_SETUP: {
          // Buffer size in bytes
          auto buffer_size = (value + 1) * sizeof(uint32_t);

          // Clearing the program buffer
          programBuffer.setup(buffer_size);

          readState = CfiCommand::READ_STATUS_REG;
          writeState = CfiCommand::BUFFER_SIZE_READ;
          break;
        }

        case CfiCommand::BUFFER_SIZE_READ: {
          // Write to the buffer and check if a writeback is needed
          // (if the buffer is full)
          auto writeback = programBuffer.write(
              flash_address, pkt->getPtr<void>(), pkt->getSize());

          if (writeback) {
              if (new_cmd == CfiCommand::BUFFERED_PROGRAM_CONFIRM) {
                  auto success = programBuffer.writeback();
                  if (!success)
                      statusRegister |= STATUS_LOCK_ERROR;

                  readState = CfiCommand::READ_STATUS_REG;
              } else {
                  statusRegister |= STATUS_PROGRAM_LOCK_BIT;
              }
              writeState = CfiCommand::NO_CMD;
          }
          break;
        }

        default:
          panic("Invalid Write State\n");
          return;
    }

    pkt->makeResponse();
}

void
CfiMemory::read(PacketPtr pkt)
{
    const Addr flash_address = pkt->getAddr() - start();
    uint64_t value = 0;

    switch (readState) {
      case CfiCommand::READ_STATUS_REG:
        value = statusRegister;
        break;
      case CfiCommand::READ_DEVICE_ID:
        value = readDeviceID(flash_address);
        break;
      case CfiCommand::READ_CFI_QUERY:
        value = cfiQuery(flash_address);
        break;
      case CfiCommand::READ_ARRAY:
        AbstractMemory::access(pkt);
        return;
      default:
        panic("Invalid Read State\n");
        return;
    }

    if (numberOfChips == 2) {
        value |= (value << 16);
    }

    pkt->setUintX(value, ByteOrder::little);
    pkt->makeResponse();

    DPRINTF(CFI, "read, address: %#x, val: %#x\n", pkt->getAddr(),
        pkt->getUintX(ByteOrder::little));

}

uint64_t
CfiMemory::readDeviceID(Addr flash_address) const
{
    switch ((flash_address & 0xff) / bankWidth) {
      case 0x00: // vendor ID
        return vendorID;
      case 0x01: // device ID
        return deviceID;
      case 0x02: // lock bit
        return blocks.isLocked(flash_address);
      default:
        // Unsupported entries
        warn("Invalid Device Identifier code: %d\n", flash_address & 0xff);
        return 0;
    }
}

void
CfiMemory::handleCommand(CfiCommand new_cmd)
{
    switch (new_cmd) {
      case CfiCommand::READ_ARRAY:
        DPRINTF(CFI, "CFI Command: Read Array\n");
        readState = CfiCommand::READ_ARRAY;
        break;
      case CfiCommand::READ_DEVICE_ID:
        DPRINTF(CFI, "CFI Command: Read Device Identifier\n");
        readState = CfiCommand::READ_DEVICE_ID;
        break;
     case CfiCommand::READ_CFI_QUERY:
        DPRINTF(CFI, "CFI Command: CFI Query\n");
        readState = CfiCommand::READ_CFI_QUERY;
        break;
      case CfiCommand::READ_STATUS_REG:
        DPRINTF(CFI, "CFI Command: Read Status Register\n");
        readState = CfiCommand::READ_STATUS_REG;
        break;
      case CfiCommand::CLEAR_STATUS_REG:
        DPRINTF(CFI, "CFI Command: Clear Status Register\n");
        statusRegister = STATUS_READY;
        break;
      case CfiCommand::BUFFERED_PROGRAM_CONFIRM:
        DPRINTF(CFI, "CFI Command: Buffered Program Confirm\n");
        break;
      case CfiCommand::ERASE_BLOCK_SETUP:
        DPRINTF(CFI, "CFI Command: Erase Block Setup\n");
        writeState = CfiCommand::ERASE_BLOCK_SETUP;
        readState = CfiCommand::READ_STATUS_REG;
        break;
      case CfiCommand::LOCK_BLOCK_SETUP:
        DPRINTF(CFI, "CFI Command: Lock Block Setup\n");
        writeState = CfiCommand::LOCK_BLOCK_SETUP;
        break;
      case CfiCommand::WORD_PROGRAM:
        DPRINTF(CFI, "CFI Command: Word Program\n");
        writeState = CfiCommand::WORD_PROGRAM;
        readState = CfiCommand::READ_STATUS_REG;
        break;
      case CfiCommand::BUFFERED_PROGRAM_SETUP:
        DPRINTF(CFI, "CFI Command: Buffered Program Setup\n");
        writeState = CfiCommand::BUFFERED_PROGRAM_SETUP;
        readState = CfiCommand::READ_STATUS_REG;
        break;
      default:
        panic("Don't know what to do with %#x\n",
            static_cast<uint16_t>(new_cmd));
    }

}

uint64_t
CfiMemory::cfiQuery(Addr flash_address)
{
    flash_address /= bankWidth;

    panic_if(flash_address >= sizeof(cfiQueryTable),
        "Acessing invalid entry in CFI query table (addr=%#x)",
        flash_address);

    return cfiQueryTable[flash_address];
}

void
CfiMemory::BlockData::erase(PacketPtr pkt)
{
    auto host_address = parent.toHostAddr(pkt->getAddr());
    std::memset(host_address, 0xff, blockSize);
}

} // namespace gem5
