/*
 * Copyright (c) 2004-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.
 *
 * Authors: Lisa Hsu
 */

/**
 * @file
 * Definitions of split cache tag store.
 */

#include <string>
#include <iostream>
#include <fstream>

#include "base/cprintf.hh"
#include "base/intmath.hh"
#include "base/output.hh"
#include "base/trace.hh"
#include "mem/cache/base.hh"
#include "mem/cache/tags/split.hh"
#include "mem/cache/tags/split_lifo.hh"
#include "mem/cache/tags/split_lru.hh"


using namespace std;
using namespace TheISA;

// create and initialize a partitioned cache structure
Split::Split(int _numSets, int _blkSize, int total_ways, int LRU1_assoc,
             bool _lifo, bool _two_queue, int _hit_latency) :
    numSets(_numSets), blkSize(_blkSize), lifo(_lifo), hitLatency(_hit_latency)
{
    DPRINTF(Split, "new split cache!!\n");

    DPRINTF(Split, "lru has %d numSets, %d blkSize, %d assoc, and %d hit_latency\n",
            numSets, blkSize, LRU1_assoc, hitLatency);

    lru = new SplitLRU(_numSets, _blkSize, LRU1_assoc, _hit_latency, 1);

    if (total_ways - LRU1_assoc == 0) {
        lifo_net = NULL;
        lru_net = NULL;
    } else {
        if (lifo) {
            DPRINTF(Split, "Other partition is a LIFO with size %d in bytes. it gets %d ways\n",
                    (total_ways - LRU1_assoc)*_numSets*_blkSize, (total_ways - LRU1_assoc));
            lifo_net = new SplitLIFO(_blkSize, (total_ways - LRU1_assoc)*_numSets*_blkSize,
                                     (total_ways - LRU1_assoc), _hit_latency, _two_queue, 2);
            lru_net = NULL;
        }
        else {
            DPRINTF(Split, "other LRU gets %d ways\n", total_ways - LRU1_assoc);
            lru_net = new SplitLRU(_numSets, _blkSize, total_ways - LRU1_assoc, _hit_latency, 2);
            lifo_net = NULL;
        }
    }

    blkMask = blkSize - 1;

    if (!isPowerOf2(total_ways))
        warn("total cache ways/columns %d should be power of 2",
             total_ways);

    warmedUp = false;
    /** @todo Make warmup percentage a parameter. */
    warmupBound = numSets * total_ways;

}

Split::~Split()
{
    delete lru;
    if (lifo)
        delete lifo_net;
    else
        delete lru_net;
}

void
Split::regStats(const string &name)
{
    using namespace Stats;

    BaseTags::regStats(name);

    usedEvictDist.init(0,3000,40);
    unusedEvictDist.init(0,3000,40);
    useByCPUCycleDist.init(0,35,1);

    nic_repl
        .name(name + ".nic_repl")
        .desc("number of replacements in the nic partition")
        .precision(0)
        ;

    cpu_repl
        .name(name + ".cpu_repl")
        .desc("number of replacements in the cpu partition")
        .precision(0)
        ;

    lru->regStats(name + ".lru");

    if (lifo && lifo_net) {
        lifo_net->regStats(name + ".lifo_net");
    } else if (lru_net) {
        lru_net->regStats(name + ".lru_net");
    }

    nicUsedWhenEvicted
        .name(name + ".nicUsedWhenEvicted")
        .desc("number of NIC blks that were used before evicted")
        ;

    nicUsedTotLatency
        .name(name + ".nicUsedTotLatency")
        .desc("total cycles before eviction of used NIC blks")
        ;

    nicUsedTotEvicted
        .name(name + ".nicUsedTotEvicted")
        .desc("total number of used NIC blks evicted")
        ;

    nicUsedAvgLatency
        .name(name + ".nicUsedAvgLatency")
        .desc("avg number of cycles a used NIC blk is in cache")
        .precision(0)
        ;
    nicUsedAvgLatency = nicUsedTotLatency / nicUsedTotEvicted;

    usedEvictDist
        .name(name + ".usedEvictDist")
        .desc("distribution of used NIC blk eviction times")
        .flags(pdf | cdf)
        ;

    nicUnusedWhenEvicted
        .name(name + ".nicUnusedWhenEvicted")
        .desc("number of NIC blks that were unused when evicted")
        ;

    nicUnusedTotLatency
        .name(name + ".nicUnusedTotLatency")
        .desc("total cycles before eviction of unused NIC blks")
        ;

    nicUnusedTotEvicted
        .name(name + ".nicUnusedTotEvicted")
        .desc("total number of unused NIC blks evicted")
        ;

    nicUnusedAvgLatency
        .name(name + ".nicUnusedAvgLatency")
        .desc("avg number of cycles an unused NIC blk is in cache")
        .precision(0)
        ;
    nicUnusedAvgLatency = nicUnusedTotLatency / nicUnusedTotEvicted;

    unusedEvictDist
        .name(name + ".unusedEvictDist")
        .desc("distribution of unused NIC blk eviction times")
        .flags(pdf | cdf)
        ;

    nicUseByCPUCycleTotal
        .name(name + ".nicUseByCPUCycleTotal")
        .desc("total latency of NIC blks til usage time")
        ;

    nicBlksUsedByCPU
        .name(name + ".nicBlksUsedByCPU")
        .desc("total number of NIC blks used")
        ;

    nicAvgUsageByCPULatency
        .name(name + ".nicAvgUsageByCPULatency")
        .desc("average number of cycles before a NIC blk that is used gets used")
        .precision(0)
        ;
    nicAvgUsageByCPULatency = nicUseByCPUCycleTotal / nicBlksUsedByCPU;

    useByCPUCycleDist
        .name(name + ".useByCPUCycleDist")
        .desc("the distribution of cycle time in cache before NIC blk is used")
        .flags(pdf | cdf)
        ;

    cpuUsedBlks
        .name(name + ".cpuUsedBlks")
        .desc("number of cpu blks that were used before evicted")
        ;

    cpuUnusedBlks
        .name(name + ".cpuUnusedBlks")
        .desc("number of cpu blks that were unused before evicted")
        ;

    nicAvgLatency
        .name(name + ".nicAvgLatency")
        .desc("avg number of cycles a NIC blk is in cache before evicted")
        .precision(0)
        ;
    nicAvgLatency = (nicUnusedTotLatency + nicUsedTotLatency) /
        (nicUnusedTotEvicted + nicUsedTotEvicted);

    NR_CP_hits
        .name(name + ".NR_CP_hits")
        .desc("NIC requests hitting in CPU Partition")
        ;

    NR_NP_hits
        .name(name + ".NR_NP_hits")
        .desc("NIC requests hitting in NIC Partition")
        ;

    CR_CP_hits
        .name(name + ".CR_CP_hits")
        .desc("CPU requests hitting in CPU partition")
        ;

    CR_NP_hits
        .name(name + ".CR_NP_hits")
        .desc("CPU requests hitting in NIC partition")
        ;

}

// probe cache for presence of given block.
bool
Split::probe(Addr addr) const
{
    bool success = lru->probe(addr);
    if (!success) {
        if (lifo && lifo_net)
            success = lifo_net->probe(addr);
        else if (lru_net)
            success = lru_net->probe(addr);
    }

    return success;
}


SplitBlk*
Split::findBlock(Addr addr, int &lat)
{
    SplitBlk *blk = lru->findBlock(addr, lat);
    if (!blk) {
        if (lifo && lifo_net) {
            blk = lifo_net->findBlock(addr, lat);
        } else if (lru_net) {
            blk = lru_net->findBlock(addr, lat);
        }
    }

    return blk;
}

SplitBlk*
Split::findBlock(Addr addr) const
{
    SplitBlk *blk = lru->findBlock(addr);
    if (!blk) {
        if (lifo && lifo_net) {
            blk = lifo_net->findBlock(addr);
        } else if (lru_net) {
            blk = lru_net->findBlock(addr);
        }
    }

    return blk;
}

SplitBlk*
Split::findReplacement(Addr addr, PacketList &writebacks)
{
    SplitBlk *blk = NULL;

    assert(0);
#if 0
    if (pkt->nic_pkt()) {
        DPRINTF(Split, "finding a replacement for nic_req\n");
        nic_repl++;
        if (lifo && lifo_net)
            blk = lifo_net->findReplacement(addr, writebacks);
        else if (lru_net)
            blk = lru_net->findReplacement(addr, writebacks);
        // in this case, this is an LRU only cache, it's non partitioned
        else
            blk = lru->findReplacement(addr, writebacks);
    } else {
        DPRINTF(Split, "finding replacement for cpu_req\n");
        blk = lru->findReplacement(addr, writebacks);
        cpu_repl++;
    }

    Tick latency = curTick - blk->ts;
    if (blk->isNIC) {
        if (blk->isUsed) {
            nicUsedWhenEvicted++;
            usedEvictDist.sample(latency);
            nicUsedTotLatency += latency;
            nicUsedTotEvicted++;
        } else {
            nicUnusedWhenEvicted++;
            unusedEvictDist.sample(latency);
            nicUnusedTotLatency += latency;
            nicUnusedTotEvicted++;
        }
    } else {
        if (blk->isUsed) {
            cpuUsedBlks++;
        } else {
            cpuUnusedBlks++;
        }
    }

    // blk attributes for the new blk coming IN
    blk->ts = curTick;
    blk->isNIC = (pkt->nic_pkt()) ? true : false;
#endif

    return blk;
}

void
Split::invalidateBlk(Split::BlkType *blk)
{
    if (!blk) {
        fatal("FIXME!\n");
#if 0
        if (lifo && lifo_net)
            blk = lifo_net->findBlock(addr);
        else if (lru_net)
            blk = lru_net->findBlock(addr);
#endif

        if (!blk)
            return;
    }

    blk->status = 0;
    blk->isTouched = false;
    tagsInUse--;
}

void
Split::cleanupRefs()
{
    lru->cleanupRefs();
    if (lifo && lifo_net)
        lifo_net->cleanupRefs();
    else if (lru_net)
        lru_net->cleanupRefs();

    ostream *memPrint = simout.create("memory_footprint.txt");

    // this shouldn't be here but it happens at the end, which is what i want
    memIter end = memHash.end();
    for (memIter iter = memHash.begin(); iter != end; ++iter) {
        ccprintf(*memPrint, "%8x\t%d\n", (*iter).first, (*iter).second);
    }
}

Addr
Split::regenerateBlkAddr(Addr tag, int set) const
{
    if (lifo_net)
        return lifo_net->regenerateBlkAddr(tag, set);
    else
        return lru->regenerateBlkAddr(tag, set);
}

Addr
Split::extractTag(Addr addr) const
{
    // need to fix this if we want to use it... old interface of
    // passing in blk was too weird
    assert(0);
    return 0;
/*
    if (blk->part == 2) {
        if (lifo_net)
            return lifo_net->extractTag(addr);
        else if (lru_net)
            return lru_net->extractTag(addr);
        else
            panic("this shouldn't happen");
    } else
        return lru->extractTag(addr);
*/
}

