/*
 * Copyright (c) 2010-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) 2010,2015 Advanced Micro Devices, Inc.
 * 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: Erik Hallnor
 *          Dave Greene
 *          Nathan Binkert
 *          Steve Reinhardt
 *          Ron Dreslinski
 *          Andreas Sandberg
 *          Nikos Nikoleris
 */

/**
 * @file
 * Cache definitions.
 */

#include "mem/cache/noncoherent_cache.hh"

#include <cassert>

#include "base/logging.hh"
#include "base/trace.hh"
#include "base/types.hh"
#include "debug/Cache.hh"
#include "mem/cache/cache_blk.hh"
#include "mem/cache/mshr.hh"
#include "params/NoncoherentCache.hh"

NoncoherentCache::NoncoherentCache(const NoncoherentCacheParams *p)
    : BaseCache(p, p->system->cacheLineSize())
{
}

void
NoncoherentCache::satisfyRequest(PacketPtr pkt, CacheBlk *blk, bool, bool)
{
    // As this a non-coherent cache located below the point of
    // coherency, we do not expect requests that are typically used to
    // keep caches coherent (e.g., InvalidateReq or UpdateReq).
    assert(pkt->isRead() || pkt->isWrite());
    BaseCache::satisfyRequest(pkt, blk);
}

bool
NoncoherentCache::access(PacketPtr pkt, CacheBlk *&blk, Cycles &lat,
                         PacketList &writebacks)
{
    bool success = BaseCache::access(pkt, blk, lat, writebacks);

    if (pkt->isWriteback() || pkt->cmd == MemCmd::WriteClean) {
        assert(blk && blk->isValid());
        // Writeback and WriteClean can allocate and fill even if the
        // referenced block was not present or it was invalid. If that
        // is the case, make sure that the new block is marked as
        // writable
        blk->status |= BlkWritable;
    }

    return success;
}

void
NoncoherentCache::doWritebacks(PacketList& writebacks, Tick forward_time)
{
    while (!writebacks.empty()) {
        PacketPtr wb_pkt = writebacks.front();
        allocateWriteBuffer(wb_pkt, forward_time);
        writebacks.pop_front();
    }
}

void
NoncoherentCache::doWritebacksAtomic(PacketList& writebacks)
{
    while (!writebacks.empty()) {
        PacketPtr wb_pkt = writebacks.front();
        memSidePort.sendAtomic(wb_pkt);
        writebacks.pop_front();
        delete wb_pkt;
    }
}

void
NoncoherentCache::handleTimingReqMiss(PacketPtr pkt, CacheBlk *blk,
                                      Tick forward_time, Tick request_time)
{
    // miss
    Addr blk_addr = pkt->getBlockAddr(blkSize);
    MSHR *mshr = mshrQueue.findMatch(blk_addr, pkt->isSecure(), false);

    // We can always write to a non coherent cache if the block is
    // present and therefore if we have reached this point then the
    // block should not be in the cache.
    assert(mshr || !blk || !blk->isValid());

    BaseCache::handleTimingReqMiss(pkt, mshr, blk, forward_time, request_time);
}

void
NoncoherentCache::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 non-coherent cache\n");

    BaseCache::recvTimingReq(pkt);
}

PacketPtr
NoncoherentCache::createMissPacket(PacketPtr cpu_pkt, CacheBlk *blk,
                                   bool needs_writable,
                                   bool is_whole_line_write) const
{
    // We also fill for writebacks from the coherent caches above us,
    // and they do not need responses
    assert(cpu_pkt->needsResponse());

    // A miss can happen only due to missing block
    assert(!blk || !blk->isValid());

    PacketPtr pkt = new Packet(cpu_pkt->req, MemCmd::ReadReq, blkSize);

    // the packet should be block aligned
    assert(pkt->getAddr() == pkt->getBlockAddr(blkSize));

    pkt->allocate();
    DPRINTF(Cache, "%s created %s from %s\n", __func__, pkt->print(),
            cpu_pkt->print());
    return pkt;
}


Cycles
NoncoherentCache::handleAtomicReqMiss(PacketPtr pkt, CacheBlk *&blk,
                                      PacketList &writebacks)
{
    PacketPtr bus_pkt = createMissPacket(pkt, blk, true,
                                         pkt->isWholeLineWrite(blkSize));
    DPRINTF(Cache, "Sending an atomic %s\n", bus_pkt->print());

    Cycles latency = ticksToCycles(memSidePort.sendAtomic(bus_pkt));

    assert(bus_pkt->isResponse());
    // At the moment the only supported downstream requests we issue
    // are ReadReq and therefore here we should only see the
    // corresponding responses
    assert(bus_pkt->isRead());
    assert(pkt->cmd != MemCmd::UpgradeResp);
    assert(!bus_pkt->isInvalidate());
    assert(!bus_pkt->hasSharers());

    // We are now dealing with the response handling
    DPRINTF(Cache, "Receive response: %s\n", bus_pkt->print());

    if (!bus_pkt->isError()) {
        // Any reponse that does not have an error should be filling,
        // afterall it is a read response
        DPRINTF(Cache, "Block for addr %#llx being updated in Cache\n",
                bus_pkt->getAddr());
        blk = handleFill(bus_pkt, blk, writebacks, allocOnFill(bus_pkt->cmd));
        assert(blk);
    }
    satisfyRequest(pkt, blk);

    maintainClusivity(true, blk);

    // Use the separate bus_pkt to generate response to pkt and
    // then delete it.
    if (!pkt->isWriteback() && pkt->cmd != MemCmd::WriteClean) {
        assert(pkt->needsResponse());
        pkt->makeAtomicResponse();
        if (bus_pkt->isError()) {
            pkt->copyError(bus_pkt);
        }
    }

    delete bus_pkt;

    return latency;
}

Tick
NoncoherentCache::recvAtomic(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 non-coherent cache\n");

    return BaseCache::recvAtomic(pkt);
}


void
NoncoherentCache::functionalAccess(PacketPtr pkt, bool from_cpu_side)
{
    panic_if(!from_cpu_side, "Non-coherent cache received functional snoop"
             " request\n");

    BaseCache::functionalAccess(pkt, from_cpu_side);
}

void
NoncoherentCache::serviceMSHRTargets(MSHR *mshr, const PacketPtr pkt,
                                     CacheBlk *blk)
{
    MSHR::Target *initial_tgt = mshr->getTarget();
    // First offset for critical word first calculations
    const int initial_offset = initial_tgt->pkt->getOffset(blkSize);

    MSHR::TargetList targets = mshr->extractServiceableTargets(pkt);
    for (auto &target: targets) {
        Packet *tgt_pkt = target.pkt;

        switch (target.source) {
          case MSHR::Target::FromCPU:
            // handle deferred requests comming from a cache or core
            // above

            Tick completion_time;
            // Here we charge on completion_time the delay of the xbar if the
            // packet comes from it, charged on headerDelay.
            completion_time = pkt->headerDelay;

            satisfyRequest(tgt_pkt, blk);

            // How many bytes past the first request is this one
            int transfer_offset;
            transfer_offset = tgt_pkt->getOffset(blkSize) - initial_offset;
            if (transfer_offset < 0) {
                transfer_offset += blkSize;
            }
            // If not critical word (offset) return payloadDelay.
            // responseLatency is the latency of the return path
            // from lower level caches/memory to an upper level cache or
            // the core.
            completion_time += clockEdge(responseLatency) +
                (transfer_offset ? pkt->payloadDelay : 0);

            assert(tgt_pkt->req->masterId() < system->maxMasters());
            missLatency[tgt_pkt->cmdToIndex()][tgt_pkt->req->masterId()] +=
                completion_time - target.recvTime;

            tgt_pkt->makeTimingResponse();
            if (pkt->isError())
                tgt_pkt->copyError(pkt);

            // Reset the bus additional time as it is now accounted for
            tgt_pkt->headerDelay = tgt_pkt->payloadDelay = 0;
            cpuSidePort.schedTimingResp(tgt_pkt, completion_time);
            break;

          case MSHR::Target::FromPrefetcher:
            // handle deferred requests comming from a prefetcher
            // attached to this cache
            assert(tgt_pkt->cmd == MemCmd::HardPFReq);

            if (blk)
                blk->status |= BlkHWPrefetched;

            // We have filled the block and the prefetcher does not
            // require responses.
            delete tgt_pkt;
            break;

          default:
            // we should never see FromSnoop Targets as this is a
            // non-coherent cache
            panic("Illegal target->source enum %d\n", target.source);
        }
    }

    // Reponses are filling and bring in writable blocks, therefore
    // there should be no deferred targets and all the non-deferred
    // targets are now serviced.
    assert(mshr->getNumTargets() == 0);
}

void
NoncoherentCache::recvTimingResp(PacketPtr pkt)
{
    assert(pkt->isResponse());
    // At the moment the only supported downstream requests we issue
    // are ReadReq and therefore here we should only see the
    // corresponding responses
    assert(pkt->isRead());
    assert(pkt->cmd != MemCmd::UpgradeResp);
    assert(!pkt->isInvalidate());
    // This cache is non-coherent and any memories below are
    // non-coherent too (non-coherent caches or the main memory),
    // therefore the fetched block can be marked as writable.
    assert(!pkt->hasSharers());

    BaseCache::recvTimingResp(pkt);
}

PacketPtr
NoncoherentCache::evictBlock(CacheBlk *blk)
{
    // A dirty block is always written back.

    // A clean block can we written back, if we turned on writebacks
    // for clean blocks. This could be useful if there is a cache
    // below and we want to make sure the block is cached but if the
    // memory below is the main memory WritebackCleans are
    // unnecessary.

    // If we clean writebacks are not enabled, we do not take any
    // further action for evictions of clean blocks (i.e., CleanEvicts
    // are unnecessary).
    PacketPtr pkt = (blk->isDirty() || writebackClean) ?
        writebackBlk(blk) : nullptr;

    invalidateBlock(blk);

    return pkt;
}

NoncoherentCache*
NoncoherentCacheParams::create()
{
    assert(tags);
    assert(replacement_policy);

    return new NoncoherentCache(this);
}
