/*
 * Copyright (c) 2018 Inria
 * 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: Daniel Carvalho
 */

/** @file
 * Implementation of the BDI cache compressor.
 */

#include "mem/cache/compressors/bdi.hh"

#include <algorithm>
#include <climits>
#include <cstring>
#include <type_traits>

#include "debug/CacheComp.hh"
#include "params/BDI.hh"

// Number of bytes in a qword
#define BYTES_PER_QWORD 8

// Declare BDI encoding names
const char* BDI::ENCODING_NAMES[] =
    {"Zero", "Repeated_Values", "Base8_1", "Base8_2", "Base8_4", "Base4_1",
     "Base4_2", "Base2_1", "Uncompressed"};

BDI::BDICompData::BDICompData(const uint8_t encoding)
    : CompressionData(), _encoding(encoding)
{
}

uint8_t
BDI::BDICompData::getEncoding() const
{
    return _encoding;
}

std::string
BDI::BDICompData::getName() const
{
    return ENCODING_NAMES[_encoding];
}

BDI::BDICompDataZeros::BDICompDataZeros()
    : BDICompData(ZERO)
{
    // Calculate compressed size
    calculateCompressedSize();
}

uint64_t
BDI::BDICompDataZeros::access(const int index) const
{
    return 0;
}

void
BDI::BDICompDataZeros::calculateCompressedSize()
{
    // Number of bits used by Encoding
    std::size_t size = encodingBits;

    setSizeBits(size);
}

BDI::BDICompDataRep::BDICompDataRep(const uint64_t rep_value)
    : BDICompData(REP_VALUES)
{
    // Set base value
    base = rep_value;

    // Calculate compressed size
    calculateCompressedSize();
}

uint64_t
BDI::BDICompDataRep::access(const int index) const
{
    return base;
}

void
BDI::BDICompDataRep::calculateCompressedSize()
{
    // Number of bits used by Encoding
    std::size_t size = encodingBits;

    // Number of bits used by Base
    size += sizeof(base)*CHAR_BIT;

    setSizeBits(size);
}

BDI::BDICompDataUncompressed::BDICompDataUncompressed(
    const uint64_t* data, const std::size_t blk_size)
    : BDICompData(UNCOMPRESSED), blkSize(blk_size),
      _data(data, data + blk_size/CHAR_BIT)
{
    // Calculate compressed size
    calculateCompressedSize();
}

uint64_t
BDI::BDICompDataUncompressed::access(const int index) const
{
    return _data[index];
}

void
BDI::BDICompDataUncompressed::calculateCompressedSize()
{
    // Number of bits used by Encoding
    std::size_t size = encodingBits;

    // Number of bits used by uncompressed line
    size += blkSize*CHAR_BIT;

    setSizeBits(size);
}

template <class TB, class TD>
BDI::BDICompDataBaseDelta<TB, TD>::BDICompDataBaseDelta(const uint8_t encoding,
    const std::size_t blk_size, const std::size_t max_num_bases)
    : BDICompData(encoding), maxNumBases(max_num_bases)
{
    // Reserve the maximum possible size for the vectors
    bases.reserve(maxNumBases);
    bitMask.reserve(blk_size/sizeof(TD));
    deltas.reserve(blk_size/sizeof(TD));

    // Push virtual base 0 to bases list
    bases.push_back(0);
}

template <class TB, class TD>
void
BDI::BDICompDataBaseDelta<TB, TD>::calculateCompressedSize()
{
    // Number of bits used by Encoding
    std::size_t size = encodingBits;

    // Number of bits used by BitMask
    size += bitMask.size()*std::ceil(std::log2(maxNumBases));

    // Number of bits used by Bases. bases[0] is implicit in a hardware
    // implementation, therefore its size is 0
    size += (maxNumBases-1)*sizeof(TB)*CHAR_BIT;

    // Number of bits used by Deltas
    size += deltas.size()*sizeof(TD)*CHAR_BIT;

    CompressionData::setSizeBits(size);
}

template <class TB, class TD>
bool
BDI::BDICompDataBaseDelta<TB, TD>::addBase(const TB base)
{
    // Can't add base if reached limit of number of bases
    if (bases.size() >= maxNumBases) {
        return false;
    }

    // Push new base to end of bases list
    bases.push_back(base);

    // New delta is 0, as it is a difference between the new base and itself
    addDelta(bases.size() - 1, 0);

    return true;
}

template <class TB, class TD>
void
BDI::BDICompDataBaseDelta<TB, TD>::addDelta(const std::size_t base_index,
    const TD delta)
{
    // Insert new delta with respect to the given base
    bitMask.push_back(base_index);

    // Insert new delta
    deltas.push_back(delta);
}

template <class TB, class TD> bool
BDI::BDICompDataBaseDelta<TB, TD>::compress(const uint64_t* data,
    const std::size_t blk_size)
{
    // Parse through data in a sizeof(TB) granularity
    for (std::size_t byte_start = 0; byte_start < blk_size;
         byte_start += sizeof(TB))
    {
        // Get current value
        TB curValue;
        std::memcpy(&curValue, ((uint8_t*)data) + byte_start,
                    sizeof(TB));

        // Iterate through all bases to search for a valid delta
        bool foundDelta = false;
        for (int base_index = 0; base_index < bases.size(); base_index++) {
            // Calculate delta relative to currently parsed base
            typename std::make_signed<TB>::type delta = curValue -
                                                        bases[base_index];

            // Check if the delta is within the limits of the delta size. If
            // that is the case, add delta to compressed data and keep parsing
            // the input data
            typename std::make_signed<TB>::type limit =
                ULLONG_MAX>>((BYTES_PER_QWORD-sizeof(TD))*CHAR_BIT+1);
            if ((delta >= -limit) && (delta <= limit)) {
                addDelta(base_index, delta);
                foundDelta = true;
                break;
            }
        }

        // If we cannot find a base that can accommodate this new line's data,
        // add this value as the new base and insert its respective delta of 0.
        // If the new base can't be added, it means that we reached the base
        // limit, so line is uncompressible using the given encoding
        if (!foundDelta && !addBase(curValue)) {
            return false;
        }
    }

    // Calculate compressed size
    calculateCompressedSize();

    return true;
}

template <class TB, class TD>
uint64_t
BDI::BDICompDataBaseDelta<TB, TD>::access(const int index) const
{
    // We decompress all base-delta pairs that form the 64-bit entry
    // corresponding to the given 64-bit-array index
    uint64_t value = 0;

    // Get relationship between the size of an uint64_t base and size of TB
    const std::size_t size_diff = sizeof(uint64_t)/sizeof(TB);

    // Mask for a base entry
    const uint64_t mask = ULLONG_MAX>>((BYTES_PER_QWORD-sizeof(TB))*CHAR_BIT);

    // Size, in bits, of a base entry. Cant be const because compiler will
    // optimize and create a 64 bit instance, which will generate a shift size
    // compilation error
    int base_size_bits = sizeof(TB)*CHAR_BIT;

    // Concatenate all base-delta entries until they form a 64-bit entry
    for (int delta_index = size_diff * (index + 1) - 1;
         delta_index >= (int)(size_diff * index); delta_index--) {
        // Get base and delta entries corresponding to the current delta
        assert(delta_index < deltas.size());
        const TD delta = deltas[delta_index];
        const int base_index = bitMask[delta_index];
        assert(base_index < bases.size());
        const TB base = bases[base_index];

        // Concatenate decompressed value
        value <<= base_size_bits;
        value |= static_cast<uint64_t>((base + delta) & mask);
    }

    return value;
}

BDI::BDI(const Params *p)
    : BaseCacheCompressor(p), useMoreCompressors(p->use_more_compressors),
      qwordsPerCacheLine(blkSize/BYTES_PER_QWORD)
{
    static_assert(sizeof(ENCODING_NAMES)/sizeof(char*) == NUM_ENCODINGS,
                  "Number of encodings doesn't match the number of names");
}

bool
BDI::isZeroPackable(const uint64_t* data) const
{
    return std::all_of(data, data + qwordsPerCacheLine,
                       [](const uint64_t entry){ return entry == 0; });
}

bool
BDI::isSameValuePackable(const uint64_t* data) const
{
    // We don't want to copy the whole array to the lambda expression
    const uint64_t rep_value = data[0];
    return std::all_of(data, data + qwordsPerCacheLine,
                       [rep_value](const uint64_t entry)
                           {return entry == rep_value;});
}

template <class TB, class TD>
std::unique_ptr<BDI::BDICompData>
BDI::tryCompress(const uint64_t* data, const uint8_t encoding) const
{
    // Instantiate compressor
    auto temp_data = std::unique_ptr<BDICompDataBaseDelta<TB, TD>>(
        new BDICompDataBaseDelta<TB, TD>(encoding, blkSize));

    // Try compressing. Return nullptr if compressor can't compress given line
    if (temp_data->compress(data, blkSize)) {
        return std::move(temp_data);
    } else {
        return std::unique_ptr<BDICompData>{};
    }
}

void
BDI::decompress(const BaseCacheCompressor::CompressionData* comp_data,
                uint64_t* data)
{
    // Decompress and go back to host endianness
    for (std::size_t i = 0; i < qwordsPerCacheLine; i++)
        data[i] = static_cast<const BDICompData*>(comp_data)->access(i);
}

std::unique_ptr<BaseCacheCompressor::CompressionData>
BDI::compress(const uint64_t* data, Cycles& comp_lat, Cycles& decomp_lat)
{
    std::unique_ptr<BDICompData> bdi_data;

    // Check if it is a zero line
    if (isZeroPackable(data)) {
        bdi_data = std::unique_ptr<BDICompData>(new BDICompDataZeros());

        // Set compression latency (compare 1 qword per cycle)
        comp_lat = Cycles(qwordsPerCacheLine);
    // Check if all values in the line are the same
    } else if (isSameValuePackable(data)) {
        bdi_data = std::unique_ptr<BDICompData>(new BDICompDataRep(data[0]));

        // Set compression latency (compare 1 qword per cycle)
        comp_lat = Cycles(qwordsPerCacheLine);
    } else {
        // Initialize compressed data as an uncompressed instance
        bdi_data = std::unique_ptr<BDICompData>(
                  new BDICompDataUncompressed(data, blkSize));

        // Base size-delta size ratio. Used to optimize run and try to
        // compress less combinations when their size is worse than the
        // current best. It does not reflect the compression ratio, as
        // it does not take the metadata into account.
        int base_delta_ratio = 2;

        // Check which base-delta size combination is the best. This is
        // optimized by giving priority to trying the compressor that would
        // generate the smallest compression size. This way we waste less
        // simulation time by not doing all possible combinations
        for (int ratio = 8; ratio >= base_delta_ratio; ratio/=2) {
            for (int base_size = 8; base_size >= ratio; base_size/=2) {
                // If using more compressors, parse all delta sizes from 1 to
                // one size smaller than the base size, otherwise just parse
                // highest possible delta. When we only instantiate one delta
                // size per base size, we use less area and energy, at the
                // cost of lower compression efficiency
                const int delta_size = base_size/ratio;
                if (!useMoreCompressors && delta_size != base_size/2) {
                    continue;
                }

                std::unique_ptr<BDICompData> temp_bdi_data;

                // Get the compression result for the current combination
                if ((base_size == 8)&&(delta_size == 4)) {
                    temp_bdi_data = tryCompress<uint64_t, int32_t>(data,
                                                                   BASE8_4);
                } else if ((base_size == 8)&&(delta_size == 2)) {
                    temp_bdi_data = tryCompress<uint64_t, int16_t>(data,
                                                                   BASE8_2);
                } else if ((base_size == 8)&&(delta_size == 1)) {
                    temp_bdi_data = tryCompress<uint64_t, int8_t>(data,
                                                                  BASE8_1);
                } else if ((base_size == 4)&&(delta_size == 2)) {
                    temp_bdi_data = tryCompress<uint32_t, int16_t>(data,
                                                                   BASE4_2);
                } else if ((base_size == 4)&&(delta_size == 1)) {
                    temp_bdi_data = tryCompress<uint32_t, int8_t>(data,
                                                                  BASE4_1);
                } else if ((base_size == 2)&&(delta_size == 1)) {
                    temp_bdi_data = tryCompress<uint16_t, int8_t>(data,
                                                                  BASE2_1);
                } else {
                    fatal("Invalid combination of base and delta sizes.");
                }

                // If compressor was successful, check if new compression
                // improves the compression factor
                if (temp_bdi_data &&
                    (bdi_data->getSizeBits() > temp_bdi_data->getSizeBits()))
                {
                    bdi_data = std::move(temp_bdi_data);
                    base_delta_ratio = ratio;
                }

                // Clear temp pointer
                temp_bdi_data.reset(nullptr);
            }
        }

        // Set compression latency. A successful compressor will stop all
        // other compressors when it knows no other will generate a better
        // compression. However, this requires either hard-coding, or a complex
        // function that can calculate the exact size of every compressor for
        // every cache line size. We decide to take a conservative
        // optimization: assume that all compressors with a given base size
        // delta size ratio (no-metadata ratio) must wait for each other.
        // In the worst case scenario the data is left uncompressed, so
        // it loses the time of the worst base size (2 bytes per cycle)
        comp_lat = Cycles(blkSize/base_delta_ratio);
    }

    // Update stats
    encodingStats[bdi_data->getEncoding()]++;

    // Pack compression results (1 extra cycle)
    comp_lat += Cycles(1);

    // Set decompression latency (latency of an adder)
    decomp_lat = Cycles(1);

    // Print debug information
    DPRINTF(CacheComp, "BDI: Compressed cache line to encoding %s (%d bits)\n",
            bdi_data->getName(), bdi_data->getSizeBits());

    return std::move(bdi_data);
}

void
BDI::regStats()
{
    BaseCacheCompressor::regStats();

    // We store the frequency of each encoding
    encodingStats
        .init(NUM_ENCODINGS)
        .name(name() + ".encoding")
        .desc("Number of data entries that were compressed to this encoding.")
        ;

    for (unsigned i = 0; i < NUM_ENCODINGS; ++i) {
        encodingStats.subname(i, ENCODING_NAMES[i]);
        encodingStats.subdesc(i, "Number of data entries that match " \
                                 "encoding " + std::string(ENCODING_NAMES[i]));
    }
}

BDI*
BDIParams::create()
{
    return new BDI(this);
}

#undef BYTES_PER_QWORD
