mem-ruby: Parameterize xor bits in BlockBloomFilter

Parameterize bitfield ranges in BlockBloomFilter such that the
hash is applied between masked bitfields of an address.

Change-Id: I008bd873458e9815e98530e308491adb65bb34cb
Signed-off-by: Daniel R. Carvalho <odanrc@yahoo.com.br>
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/18870
Tested-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: Nikos Nikoleris <nikos.nikoleris@arm.com>
Maintainer: Nikos Nikoleris <nikos.nikoleris@arm.com>
diff --git a/src/mem/ruby/filters/BlockBloomFilter.cc b/src/mem/ruby/filters/BlockBloomFilter.cc
index 0718c96..f5f7a91 100644
--- a/src/mem/ruby/filters/BlockBloomFilter.cc
+++ b/src/mem/ruby/filters/BlockBloomFilter.cc
@@ -29,11 +29,26 @@
 #include "mem/ruby/filters/BlockBloomFilter.hh"
 
 #include "base/bitfield.hh"
+#include "base/logging.hh"
 #include "params/BlockBloomFilter.hh"
 
 BlockBloomFilter::BlockBloomFilter(const BlockBloomFilterParams* p)
-    : AbstractBloomFilter(p)
+    : AbstractBloomFilter(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() < 2,
+        "There must be at least two masks to XOR");
+
+    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");
+    }
 }
 
 BlockBloomFilter::~BlockBloomFilter()
@@ -61,16 +76,14 @@
 int
 BlockBloomFilter::hash(Addr addr) const
 {
-    // Pull out some bit field ==> B1
-    // Pull out additional bits, not the same as B1 ==> B2
-    //  XOR B1 and B2 to get hash index
-    Addr block_bits = bits(addr, 2 * offsetBits - 1, offsetBits);
-    int offset = 5;
-    Addr other_bits = bits(addr, 2 * offsetBits + offset + sizeBits - 1,
-        2 * offsetBits + offset);
-    int index = block_bits ^ other_bits;
-    assert(index < filter.size());
-    return index;
+    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;
 }
 
 BlockBloomFilter*
diff --git a/src/mem/ruby/filters/BlockBloomFilter.hh b/src/mem/ruby/filters/BlockBloomFilter.hh
index c386624..280793c 100644
--- a/src/mem/ruby/filters/BlockBloomFilter.hh
+++ b/src/mem/ruby/filters/BlockBloomFilter.hh
@@ -29,10 +29,16 @@
 #ifndef __MEM_RUBY_FILTERS_BLOCKBLOOMFILTER_HH__
 #define __MEM_RUBY_FILTERS_BLOCKBLOOMFILTER_HH__
 
+#include <vector>
+
 #include "mem/ruby/filters/AbstractBloomFilter.hh"
 
 struct BlockBloomFilterParams;
 
+/**
+ * Simple deletable (with false negatives) bloom filter that extracts
+ * bitfields of an address to use as indexes of the filter vector.
+ */
 class BlockBloomFilter : public AbstractBloomFilter
 {
   public:
@@ -44,7 +50,19 @@
     int getCount(Addr addr) const override;
 
   private:
+    /**
+     * XOR hash between bitfields of an address, provided by the mask vector.
+     *
+     * @param addr The address to be hashed.
+     * @return The value of the XOR of the masked bitfields of the address.
+     */
     int hash(Addr addr) const;
+
+    /** Position of the LSB of each mask. */
+    std::vector<unsigned> masksLSBs;
+
+    /** Number of bits in each mask. */
+    std::vector<unsigned> masksSizes;
 };
 
 #endif // __MEM_RUBY_FILTERS_BLOCKBLOOMFILTER_HH__
diff --git a/src/mem/ruby/filters/BloomFilters.py b/src/mem/ruby/filters/BloomFilters.py
index 93d4dec..89a4b9b 100644
--- a/src/mem/ruby/filters/BloomFilters.py
+++ b/src/mem/ruby/filters/BloomFilters.py
@@ -48,6 +48,11 @@
     cxx_class = 'BlockBloomFilter'
     cxx_header = "mem/ruby/filters/BlockBloomFilter.hh"
 
+    masks_lsbs = VectorParam.Unsigned([Self.offset_bits,
+        2 * Self.offset_bits], "Position of the LSB of each mask")
+    masks_sizes = VectorParam.Unsigned([Self.offset_bits, Self.offset_bits],
+        "Size, in number of bits, of each mask")
+
 class BulkBloomFilter(AbstractBloomFilter):
     type = 'BulkBloomFilter'
     cxx_class = 'BulkBloomFilter'