/*
 * Copyright (c) 2012-2013, 2015 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) 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: Ron Dreslinski
 *          Steve Reinhardt
 */

/**
 * @file
 * Stride Prefetcher template instantiations.
 */

#include "mem/cache/prefetch/stride.hh"

#include <cassert>

#include "base/intmath.hh"
#include "base/logging.hh"
#include "base/random.hh"
#include "base/trace.hh"
#include "debug/HWPrefetch.hh"
#include "params/StridePrefetcher.hh"

StridePrefetcher::StridePrefetcher(const StridePrefetcherParams *p)
    : QueuedPrefetcher(p),
      maxConf(p->max_conf),
      threshConf(p->thresh_conf),
      minConf(p->min_conf),
      startConf(p->start_conf),
      pcTableAssoc(p->table_assoc),
      pcTableSets(p->table_sets),
      useMasterId(p->use_master_id),
      degree(p->degree),
      pcTable(pcTableAssoc, pcTableSets, name())
{
    assert(isPowerOf2(pcTableSets));
}

std::vector<std::vector<StridePrefetcher::StrideEntry>>&
StridePrefetcher::PCTable::allocateNewContext(int context)
{
    auto res = entries.insert(std::make_pair(context,
        std::vector<std::vector<StrideEntry>>(pcTableSets)));
    auto it = res.first;
    chatty_assert(res.second, "Allocating an already created context\n");
    assert(it->first == context);

    DPRINTF(HWPrefetch, "Adding context %i with stride entries\n", context);

    std::vector<std::vector<StrideEntry>>& table = it->second;
    for (auto& set : table) {
        set.resize(pcTableAssoc);
    }
    return table;
}

StridePrefetcher::PCTable::~PCTable()
{
}

void
StridePrefetcher::calculatePrefetch(const PacketPtr &pkt,
                                    std::vector<AddrPriority> &addresses)
{
    if (!pkt->req->hasPC()) {
        DPRINTF(HWPrefetch, "Ignoring request with no PC.\n");
        return;
    }

    // Get required packet info
    Addr pkt_addr = pkt->getAddr();
    Addr pc = pkt->req->getPC();
    bool is_secure = pkt->isSecure();
    MasterID master_id = useMasterId ? pkt->req->masterId() : 0;

    // Search for entry in the pc table
    StrideEntry *entry = findEntry(pc, is_secure, master_id);

    if (entry != nullptr) {
        // Hit in table
        int new_stride = pkt_addr - entry->lastAddr;
        bool stride_match = (new_stride == entry->stride);

        // Adjust confidence for stride entry
        if (stride_match && new_stride != 0) {
            if (entry->confidence < maxConf)
                entry->confidence++;
        } else {
            if (entry->confidence > minConf)
                entry->confidence--;
            // If confidence has dropped below the threshold, train new stride
            if (entry->confidence < threshConf)
                entry->stride = new_stride;
        }

        DPRINTF(HWPrefetch, "Hit: PC %x pkt_addr %x (%s) stride %d (%s), "
                "conf %d\n", pc, pkt_addr, is_secure ? "s" : "ns", new_stride,
                stride_match ? "match" : "change",
                entry->confidence);

        entry->lastAddr = pkt_addr;

        // Abort prefetch generation if below confidence threshold
        if (entry->confidence < threshConf)
            return;

        // Generate up to degree prefetches
        for (int d = 1; d <= degree; d++) {
            // Round strides up to atleast 1 cacheline
            int prefetch_stride = new_stride;
            if (abs(new_stride) < blkSize) {
                prefetch_stride = (new_stride < 0) ? -blkSize : blkSize;
            }

            Addr new_addr = pkt_addr + d * prefetch_stride;
            if (samePage(pkt_addr, new_addr)) {
                DPRINTF(HWPrefetch, "Queuing prefetch to %#x.\n", new_addr);
                addresses.push_back(AddrPriority(new_addr, 0));
            } else {
                // Record the number of page crossing prefetches generated
                pfSpanPage += degree - d + 1;
                DPRINTF(HWPrefetch, "Ignoring page crossing prefetch.\n");
                return;
            }
        }
    } else {
        // Miss in table
        DPRINTF(HWPrefetch, "Miss: PC %x pkt_addr %x (%s)\n", pc, pkt_addr,
                is_secure ? "s" : "ns");

        StrideEntry* entry = pcTableVictim(pc, master_id);
        entry->instAddr = pc;
        entry->lastAddr = pkt_addr;
        entry->isSecure= is_secure;
        entry->stride = 0;
        entry->confidence = startConf;
    }
}

inline Addr
StridePrefetcher::pcHash(Addr pc) const
{
    Addr hash1 = pc >> 1;
    Addr hash2 = hash1 >> floorLog2(pcTableSets);
    return (hash1 ^ hash2) & (Addr)(pcTableSets - 1);
}

inline StridePrefetcher::StrideEntry*
StridePrefetcher::pcTableVictim(Addr pc, int master_id)
{
    // Rand replacement for now
    int set = pcHash(pc);
    int way = random_mt.random<int>(0, pcTableAssoc - 1);

    DPRINTF(HWPrefetch, "Victimizing lookup table[%d][%d].\n", set, way);
    return &pcTable[master_id][set][way];
}

inline StridePrefetcher::StrideEntry*
StridePrefetcher::findEntry(Addr pc, bool is_secure, int master_id)
{
    int set = pcHash(pc);
    std::vector<StrideEntry>& set_entries = pcTable[master_id][set];
    for (int way = 0; way < pcTableAssoc; way++) {
        StrideEntry* entry = &set_entries[way];
        // Search ways for match
        if ((entry->instAddr == pc) && (entry->isSecure == is_secure)) {
            DPRINTF(HWPrefetch, "Lookup hit table[%d][%d].\n", set, way);
            return entry;
        }
    }
    return nullptr;
}

StridePrefetcher*
StridePrefetcherParams::create()
{
    return new StridePrefetcher(this);
}
