/**
 * Copyright (c) 2018 Metempsy Technology Consulting
 * 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/cache/prefetch/access_map_pattern_matching.hh"

#include "debug/HWPrefetch.hh"
#include "mem/cache/prefetch/associative_set_impl.hh"
#include "params/AMPMPrefetcher.hh"
#include "params/AccessMapPatternMatching.hh"

namespace Prefetcher {

AccessMapPatternMatching::AccessMapPatternMatching(
    const AccessMapPatternMatchingParams &p)
    : ClockedObject(p), blkSize(p.block_size), limitStride(p.limit_stride),
      startDegree(p.start_degree), hotZoneSize(p.hot_zone_size),
      highCoverageThreshold(p.high_coverage_threshold),
      lowCoverageThreshold(p.low_coverage_threshold),
      highAccuracyThreshold(p.high_accuracy_threshold),
      lowAccuracyThreshold(p.low_accuracy_threshold),
      highCacheHitThreshold(p.high_cache_hit_threshold),
      lowCacheHitThreshold(p.low_cache_hit_threshold),
      epochCycles(p.epoch_cycles),
      offChipMemoryLatency(p.offchip_memory_latency),
      accessMapTable(p.access_map_table_assoc, p.access_map_table_entries,
                     p.access_map_table_indexing_policy,
                     p.access_map_table_replacement_policy,
                     AccessMapEntry(hotZoneSize / blkSize)),
      numGoodPrefetches(0), numTotalPrefetches(0), numRawCacheMisses(0),
      numRawCacheHits(0), degree(startDegree), usefulDegree(startDegree),
      epochEvent([this]{ processEpochEvent(); }, name())
{
    fatal_if(!isPowerOf2(hotZoneSize),
        "the hot zone size must be a power of 2");
}

void
AccessMapPatternMatching::startup()
{
    schedule(epochEvent, clockEdge(epochCycles));
}

void
AccessMapPatternMatching::processEpochEvent()
{
    schedule(epochEvent, clockEdge(epochCycles));
    double prefetch_accuracy =
        ((double) numGoodPrefetches) / ((double) numTotalPrefetches);
    double prefetch_coverage =
        ((double) numGoodPrefetches) / ((double) numRawCacheMisses);
    double cache_hit_ratio = ((double) numRawCacheHits) /
        ((double) (numRawCacheHits + numRawCacheMisses));
    double num_requests = (double) (numRawCacheMisses - numGoodPrefetches +
        numTotalPrefetches);
    double memory_bandwidth = num_requests * offChipMemoryLatency /
        clockEdge(epochCycles);

    if (prefetch_coverage > highCoverageThreshold &&
        (prefetch_accuracy > highAccuracyThreshold ||
        cache_hit_ratio < lowCacheHitThreshold)) {
        usefulDegree += 1;
    } else if ((prefetch_coverage < lowCoverageThreshold &&
               (prefetch_accuracy < lowAccuracyThreshold ||
                cache_hit_ratio > highCacheHitThreshold)) ||
               (prefetch_accuracy < lowAccuracyThreshold &&
                cache_hit_ratio > highCacheHitThreshold)) {
        usefulDegree -= 1;
    }
    degree = std::min((unsigned) memory_bandwidth, usefulDegree);
    // reset epoch stats
    numGoodPrefetches = 0.0;
    numTotalPrefetches = 0.0;
    numRawCacheMisses = 0.0;
    numRawCacheHits = 0.0;
}

AccessMapPatternMatching::AccessMapEntry *
AccessMapPatternMatching::getAccessMapEntry(Addr am_addr,
                bool is_secure)
{
    AccessMapEntry *am_entry = accessMapTable.findEntry(am_addr, is_secure);
    if (am_entry != nullptr) {
        accessMapTable.accessEntry(am_entry);
    } else {
        am_entry = accessMapTable.findVictim(am_addr);
        assert(am_entry != nullptr);

        accessMapTable.insertEntry(am_addr, is_secure, am_entry);
    }
    return am_entry;
}

void
AccessMapPatternMatching::setEntryState(AccessMapEntry &entry,
    Addr block, enum AccessMapState state)
{
    enum AccessMapState old = entry.states[block];
    entry.states[block] = state;

    //do not update stats when initializing
    if (state == AM_INIT) return;

    switch (old) {
        case AM_INIT:
            if (state == AM_PREFETCH) {
                numTotalPrefetches += 1;
            } else if (state == AM_ACCESS) {
                numRawCacheMisses += 1;
            }
            break;
        case AM_PREFETCH:
            if (state == AM_ACCESS) {
                numGoodPrefetches += 1;
                numRawCacheMisses += 1;
            }
            break;
        case AM_ACCESS:
            if (state == AM_ACCESS) {
                numRawCacheHits += 1;
            }
            break;
        default:
            panic("Impossible path\n");
            break;
    }
}

void
AccessMapPatternMatching::calculatePrefetch(const Base::PrefetchInfo &pfi,
    std::vector<Queued::AddrPriority> &addresses)
{
    assert(addresses.empty());

    bool is_secure = pfi.isSecure();
    Addr am_addr = pfi.getAddr() / hotZoneSize;
    Addr current_block = (pfi.getAddr() % hotZoneSize) / blkSize;
    uint64_t lines_per_zone = hotZoneSize / blkSize;

    // Get the entries of the curent block (am_addr), the previous, and the
    // following ones
    AccessMapEntry *am_entry_curr = getAccessMapEntry(am_addr, is_secure);
    AccessMapEntry *am_entry_prev = (am_addr > 0) ?
        getAccessMapEntry(am_addr-1, is_secure) : nullptr;
    AccessMapEntry *am_entry_next = (am_addr < (MaxAddr/hotZoneSize)) ?
        getAccessMapEntry(am_addr+1, is_secure) : nullptr;
    assert(am_entry_curr != am_entry_prev);
    assert(am_entry_curr != am_entry_next);
    assert(am_entry_prev != am_entry_next);
    assert(am_entry_curr != nullptr);

    //Mark the current access as Accessed
    setEntryState(*am_entry_curr, current_block, AM_ACCESS);

    /**
     * Create a contiguous copy of the 3 entries states.
     * With this, we avoid doing boundaries checking in the loop that looks
     * for prefetch candidates, mark out of range positions with AM_INVALID
     */
    std::vector<AccessMapState> states(3 * lines_per_zone);
    for (unsigned idx = 0; idx < lines_per_zone; idx += 1) {
        states[idx] =
            am_entry_prev != nullptr ? am_entry_prev->states[idx] : AM_INVALID;
        states[idx + lines_per_zone] = am_entry_curr->states[idx];
        states[idx + 2 * lines_per_zone] =
            am_entry_next != nullptr ? am_entry_next->states[idx] : AM_INVALID;
    }

    /**
     * am_entry_prev->states => states[               0 ..   lines_per_zone-1]
     * am_entry_curr->states => states[  lines_per_zone .. 2*lines_per_zone-1]
     * am_entry_next->states => states[2*lines_per_zone .. 3*lines_per_zone-1]
     */

    // index of the current_block in the new vector
    Addr states_current_block = current_block + lines_per_zone;
    // consider strides 1..lines_per_zone/2
    int max_stride = limitStride == 0 ? lines_per_zone / 2 : limitStride + 1;
    for (int stride = 1; stride < max_stride; stride += 1) {
        // Test accessed positive strides
        if (checkCandidate(states, states_current_block, stride)) {
            // candidate found, current_block - stride
            Addr pf_addr;
            if (stride > current_block) {
                // The index (current_block - stride) falls in the range of
                // the previous zone (am_entry_prev), adjust the address
                // accordingly
                Addr blk = states_current_block - stride;
                pf_addr = (am_addr - 1) * hotZoneSize + blk * blkSize;
                setEntryState(*am_entry_prev, blk, AM_PREFETCH);
            } else {
                // The index (current_block - stride) falls within
                // am_entry_curr
                Addr blk = current_block - stride;
                pf_addr = am_addr * hotZoneSize + blk * blkSize;
                setEntryState(*am_entry_curr, blk, AM_PREFETCH);
            }
            addresses.push_back(Queued::AddrPriority(pf_addr, 0));
            if (addresses.size() == degree) {
                break;
            }
        }

        // Test accessed negative strides
        if (checkCandidate(states, states_current_block, -stride)) {
            // candidate found, current_block + stride
            Addr pf_addr;
            if (current_block + stride >= lines_per_zone) {
                // The index (current_block + stride) falls in the range of
                // the next zone (am_entry_next), adjust the address
                // accordingly
                Addr blk = (states_current_block + stride) % lines_per_zone;
                pf_addr = (am_addr + 1) * hotZoneSize + blk * blkSize;
                setEntryState(*am_entry_next, blk, AM_PREFETCH);
            } else {
                // The index (current_block + stride) falls within
                // am_entry_curr
                Addr blk = current_block + stride;
                pf_addr = am_addr * hotZoneSize + blk * blkSize;
                setEntryState(*am_entry_curr, blk, AM_PREFETCH);
            }
            addresses.push_back(Queued::AddrPriority(pf_addr, 0));
            if (addresses.size() == degree) {
                break;
            }
        }
    }
}

AMPM::AMPM(const AMPMPrefetcherParams &p)
  : Queued(p), ampm(*p.ampm)
{
}

void
AMPM::calculatePrefetch(const PrefetchInfo &pfi,
    std::vector<AddrPriority> &addresses)
{
    ampm.calculatePrefetch(pfi, addresses);
}

} // namespace Prefetcher
