/*
 * Copyright (c) 2019 Inria
 * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
 * 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
 */

#include "base/filters/block_bloom_filter.hh"

#include "base/bitfield.hh"
#include "base/logging.hh"
#include "params/BloomFilterBlock.hh"

namespace BloomFilter {

Block::Block(const BloomFilterBlockParams* p)
    : Base(p), masksLSBs(p->masks_lsbs),
      masksSizes(p->masks_sizes)
{
    fatal_if(masksLSBs.size() != masksSizes.size(),
        "Masks haven't been properly provided");
    fatal_if(masksLSBs.size() < 1,
        "There must be at least one mask to extract an address bitfield");

    for (int i = 0; i < masksLSBs.size(); i++) {
        fatal_if((masksSizes[i] > sizeBits) || (masksSizes[i] <= 0),
            "The bitfields must be indexable in the filter");
        fatal_if(masksLSBs[i] + masksSizes[i] >
            std::numeric_limits<Addr>::digits,
            "The total size of the bitfields cannot be bigger than the " \
            "number of bits in an address");
    }
}

Block::~Block()
{
}

void
Block::set(Addr addr)
{
    filter[hash(addr)]++;
}

void
Block::unset(Addr addr)
{
    filter[hash(addr)]--;
}

int
Block::getCount(Addr addr) const
{
    return filter[hash(addr)];
}

int
Block::hash(Addr addr) const
{
    Addr hashed_addr = 0;
    for (int i = 0; i < masksLSBs.size(); i++) {
        hashed_addr ^=
            bits(addr, offsetBits + masksLSBs[i] + masksSizes[i] - 1,
            offsetBits + masksLSBs[i]);
    }
    assert(hashed_addr < filter.size());
    return hashed_addr;
}

} // namespace BloomFilter

BloomFilter::Block*
BloomFilterBlockParams::create()
{
    return new BloomFilter::Block(this);
}

