/**
 * 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.
 */

/** @file
 * Implementation of a simple superblock class. Each superblock consists of a
 * number of compressed cache blocks limited by the maximum compression factor
 * that may or may not be present in the cache.
 */

#include "mem/cache/tags/super_blk.hh"

#include <climits>
#include <cmath>

#include "base/bitfield.hh"

namespace gem5
{

CompressionBlk::CompressionBlk()
    : SectorSubBlk(), _size(0), _decompressionLatency(0), _compressed(false)
{
}

CacheBlk&
CompressionBlk::operator=(CacheBlk&& other)
{
    operator=(std::move(static_cast<CompressionBlk&&>(other)));
    return *this;
}

CompressionBlk&
CompressionBlk::operator=(CompressionBlk&& other)
{
    // Copy internal variables; if moving, that means we had an expansion or
    // contraction, and therefore the size is no longer valid, so it is not
    // moved
    setDecompressionLatency(other.getDecompressionLatency());
    if (other.isCompressed()) {
        setCompressed();
    } else {
        setUncompressed();
    }

    CacheBlk::operator=(std::move(other));
    return *this;
}

bool
CompressionBlk::isCompressed() const
{
    return _compressed;
}

void
CompressionBlk::setCompressed()
{
    _compressed = true;
}

void
CompressionBlk::setUncompressed()
{
    _compressed = false;
}

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

void
CompressionBlk::setSizeBits(const std::size_t size)
{
    _size = size;

    SuperBlk* superblock = static_cast<SuperBlk*>(getSectorBlock());
    const uint8_t compression_factor =
        superblock->calculateCompressionFactor(size);
    superblock->setCompressionFactor(compression_factor);

    // Either this function is called after an insertion, or an update.
    // If somebody else is present in the block, keep the superblock's
    // compressibility. Otherwise, check if it can co-allocate
    const uint8_t num_valid = superblock->getNumValid();
    assert(num_valid >= 1);
    if (num_valid == 1) {
        if (compression_factor != 1) {
            setCompressed();
        } else {
            setUncompressed();
        }
    } else {
        if (superblock->isCompressed(this)) {
            setCompressed();
        } else {
            setUncompressed();
        }
    }
}

Cycles
CompressionBlk::getDecompressionLatency() const
{
    return _decompressionLatency;
}

void
CompressionBlk::setDecompressionLatency(const Cycles lat)
{
    _decompressionLatency = lat;
}

void
CompressionBlk::invalidate()
{
    SectorSubBlk::invalidate();
    setUncompressed();
}

CompressionBlk::OverwriteType
CompressionBlk::checkExpansionContraction(const std::size_t size) const
{
    // An expansion happens when a block passes from a compressible state
    // to a less compressible state (e.g., blkSize/4 to (blkSize/2 or blkSize),
    // or blkSize/2 to blkSize). A contraction happens when a block passes
    // from a less compressible state to a more compressible state (i.e., the
    // opposite of expansion)
    const SuperBlk* superblock =
        static_cast<const SuperBlk*>(getSectorBlock());
    const uint8_t prev_cf = superblock->getCompressionFactor();
    const uint8_t new_cf = superblock->calculateCompressionFactor(size);
    return (new_cf < prev_cf) ? DATA_EXPANSION :
        ((new_cf > prev_cf) ? DATA_CONTRACTION : UNCHANGED);
}

std::string
CompressionBlk::print() const
{
    return csprintf("%s compressed: %d size: %llu decompression latency: %d",
                    SectorSubBlk::print(), isCompressed(), getSizeBits(),
                    getDecompressionLatency());
}

SuperBlk::SuperBlk()
    : SectorBlk(), blkSize(0), compressionFactor(1)
{
}

void
SuperBlk::invalidate()
{
    SectorBlk::invalidate();
    compressionFactor = 1;
}

bool
SuperBlk::isCompressed(const CompressionBlk* ignored_blk) const
{
    for (const auto& blk : blks) {
        if (blk->isValid() && (blk != ignored_blk)) {
            return static_cast<CompressionBlk*>(blk)->isCompressed();
        }
    }

    // An invalid block is seen as compressed
    return true;
}

bool
SuperBlk::canCoAllocate(const std::size_t compressed_size) const
{
    // A YACC-like (Sardashti et al., 2016) co-allocation function: at most
    // numBlocksPerSector blocks that compress at least to fit in the space
    // allocated by its compression factor can share a superblock
    return (getNumValid() < getCompressionFactor()) &&
        (compressed_size <= (blkSize * CHAR_BIT) / getCompressionFactor());
}

void
SuperBlk::setBlkSize(const std::size_t blk_size)
{
    assert(blkSize == 0);
    blkSize = blk_size;
}

uint8_t
SuperBlk::calculateCompressionFactor(const std::size_t size) const
{
    // The number of blocks per sector determines the maximum comp factor.
    // If the compressed size is worse than the uncompressed size, we assume
    // the size is the uncompressed size, and thus the compression factor is 1
    const std::size_t blk_size_bits = CHAR_BIT * blkSize;
    const std::size_t compression_factor = (size > blk_size_bits) ? 1 :
        ((size == 0) ? blk_size_bits :
        alignToPowerOfTwo(std::floor(double(blk_size_bits) / size)));
    return std::min(compression_factor, blks.size());
}

uint8_t
SuperBlk::getCompressionFactor() const
{
    return compressionFactor;
}

void
SuperBlk::setCompressionFactor(const uint8_t compression_factor)
{
    // Either the block is alone, in which case the compression factor
    // must be set, or it co-allocates with someone with a worse or
    // equal compression factor, in which case it should not be updated
    if (getNumValid() <= 1) {
        compressionFactor = compression_factor;
    }
}

std::string
SuperBlk::print() const
{
    return csprintf("CF: %d %s", getCompressionFactor(), SectorBlk::print());
}

} // namespace gem5
