/*
 * Copyright (c) 2018-2020 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.
 */

/** @file
 * Definition of a basic cache compressor.
 */

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

#include <algorithm>
#include <climits>
#include <cmath>
#include <cstdint>
#include <string>

#include "base/trace.hh"
#include "debug/CacheComp.hh"
#include "mem/cache/tags/super_blk.hh"
#include "params/BaseCacheCompressor.hh"

namespace Compressor {

// Uncomment this line if debugging compression
//#define DEBUG_COMPRESSION

Base::CompressionData::CompressionData()
    : _size(0)
{
}

Base::CompressionData::~CompressionData()
{
}

void
Base::CompressionData::setSizeBits(std::size_t size)
{
    _size = size;
}

std::size_t
Base::CompressionData::getSizeBits() const
{
    return _size;
}

std::size_t
Base::CompressionData::getSize() const
{
    return std::ceil(_size/8);
}

Base::Base(const Params *p)
  : SimObject(p), blkSize(p->block_size), chunkSizeBits(p->chunk_size_bits),
    sizeThreshold((blkSize * p->size_threshold_percentage) / 100),
    stats(*this)
{
    fatal_if(64 % chunkSizeBits,
        "64 must be a multiple of the chunk granularity.");

    fatal_if(blkSize < sizeThreshold, "Compressed data must fit in a block");
}

std::vector<Base::Chunk>
Base::toChunks(const uint64_t* data) const
{
    // Number of chunks in a 64-bit value
    const unsigned num_chunks_per_64 =
        (sizeof(uint64_t) * CHAR_BIT) / chunkSizeBits;

    // Turn a 64-bit array into a chunkSizeBits-array
    std::vector<Chunk> chunks((blkSize * CHAR_BIT) / chunkSizeBits, 0);
    for (int i = 0; i < chunks.size(); i++) {
        const int index_64 = std::floor(i / (double)num_chunks_per_64);
        const unsigned start = i % num_chunks_per_64;
        chunks[i] = bits(data[index_64],
            (start + 1) * chunkSizeBits - 1, start * chunkSizeBits);
    }

    return chunks;
}

void
Base::fromChunks(const std::vector<Chunk>& chunks, uint64_t* data) const
{
    // Number of chunks in a 64-bit value
    const unsigned num_chunks_per_64 =
        (sizeof(uint64_t) * CHAR_BIT) / chunkSizeBits;

    // Turn a chunkSizeBits-array into a 64-bit array
    std::memset(data, 0, blkSize);
    for (int i = 0; i < chunks.size(); i++) {
        const int index_64 = std::floor(i / (double)num_chunks_per_64);
        const unsigned start = i % num_chunks_per_64;
        replaceBits(data[index_64], (start + 1) * chunkSizeBits - 1,
            start * chunkSizeBits, chunks[i]);
    }
}

std::unique_ptr<Base::CompressionData>
Base::compress(const uint64_t* data, Cycles& comp_lat, Cycles& decomp_lat)
{
    // Apply compression
    std::unique_ptr<CompressionData> comp_data =
        compress(toChunks(data), comp_lat, decomp_lat);

    // If we are in debug mode apply decompression just after the compression.
    // If the results do not match, we've got an error
    #ifdef DEBUG_COMPRESSION
    uint64_t decomp_data[blkSize/8];

    // Apply decompression
    decompress(comp_data.get(), decomp_data);

    // Check if decompressed line matches original cache line
    fatal_if(std::memcmp(data, decomp_data, blkSize),
             "Decompressed line does not match original line.");
    #endif

    // Get compression size. If compressed size is greater than the size
    // threshold, the compression is seen as unsuccessful
    std::size_t comp_size_bits = comp_data->getSizeBits();
    if (comp_size_bits > sizeThreshold * CHAR_BIT) {
        comp_size_bits = blkSize * CHAR_BIT;
        comp_data->setSizeBits(comp_size_bits);
        stats.failedCompressions++;
    }

    // Update stats
    stats.compressions++;
    stats.compressionSizeBits += comp_size_bits;
    if (comp_size_bits != 0) {
        stats.compressionSize[1 + std::ceil(std::log2(comp_size_bits))]++;
    } else {
        stats.compressionSize[0]++;
    }

    // Print debug information
    DPRINTF(CacheComp, "Compressed cache line from %d to %d bits. " \
            "Compression latency: %llu, decompression latency: %llu\n",
            blkSize*8, comp_size_bits, comp_lat, decomp_lat);

    return std::move(comp_data);
}

Cycles
Base::getDecompressionLatency(const CacheBlk* blk)
{
    const CompressionBlk* comp_blk = static_cast<const CompressionBlk*>(blk);

    // If block is compressed, return its decompression latency
    if (comp_blk && comp_blk->isCompressed()){
        const Cycles decomp_lat = comp_blk->getDecompressionLatency();
        DPRINTF(CacheComp, "Decompressing block: %s (%d cycles)\n",
                comp_blk->print(), decomp_lat);
        stats.decompressions += 1;
        return decomp_lat;
    }

    // Block is not compressed, so there is no decompression latency
    return Cycles(0);
}

void
Base::setDecompressionLatency(CacheBlk* blk, const Cycles lat)
{
    // Sanity check
    assert(blk != nullptr);

    // Assign latency
    static_cast<CompressionBlk*>(blk)->setDecompressionLatency(lat);
}

void
Base::setSizeBits(CacheBlk* blk, const std::size_t size_bits)
{
    // Sanity check
    assert(blk != nullptr);

    // Assign size
    static_cast<CompressionBlk*>(blk)->setSizeBits(size_bits);
}

Base::BaseStats::BaseStats(Base& _compressor)
  : Stats::Group(&_compressor), compressor(_compressor),
    compressions(this, "compressions",
        "Total number of compressions"),
    failedCompressions(this, "failed_compressions",
        "Total number of failed compressions"),
    compressionSize(this, "compression_size",
        "Number of blocks that were compressed to this power of two size"),
    compressionSizeBits(this, "compression_size_bits",
        "Total compressed data size, in bits"),
    avgCompressionSizeBits(this, "avg_compression_size_bits",
        "Average compression size, in bits"),
    decompressions(this, "total_decompressions",
        "Total number of decompressions")
{
}

void
Base::BaseStats::regStats()
{
    Stats::Group::regStats();

    // Values comprised are {0, 1, 2, 4, ..., blkSize}
    compressionSize.init(std::log2(compressor.blkSize*8) + 2);
    compressionSize.subname(0, "0");
    compressionSize.subdesc(0,
        "Number of blocks that compressed to fit in 0 bits");
    for (unsigned i = 0; i <= std::log2(compressor.blkSize*8); ++i) {
        std::string str_i = std::to_string(1 << i);
        compressionSize.subname(1+i, str_i);
        compressionSize.subdesc(1+i,
            "Number of blocks that compressed to fit in " + str_i + " bits");
    }

    avgCompressionSizeBits.flags(Stats::total | Stats::nozero | Stats::nonan);
    avgCompressionSizeBits = compressionSizeBits / compressions;
}

} // namespace Compressor
