Daniel Carvalho has uploaded this change for review. ( https://gem5-review.googlesource.com/c/public/gem5/+/37895 )

Change subject: base: Creation of dueling classes
......................................................................

base: Creation of dueling classes

Table policies (i.e., replacement, compression, etc) behave differently
depending on the workload, and it is often desired to be able to
selectively switch between them. In this case the relevant metadata
for all the policies must be added to all of the entries being analyzed.

In order to avoid having to monitor all table entries, a few of these
entries are selected to be sampled and estimate overall behavior.
These sampled entries belong each to a single policy. Then, based on
the predominance of these samples, the winning policy is applied to
the other sets (followers).

As of now, in order to avoid having to iterate over a vector, there is
a limited number of dueling instances, but it may be easily extended,
if needed.

Based on Set Dueling, proposed in "Adaptive Insertion Policies for High
Performance Caching".

Change-Id: I692a3e5e0ad98581d68167ad7e6b45ab2f4c7b10
Signed-off-by: Daniel R. Carvalho <oda...@yahoo.com.br>
---
M src/base/SConscript
A src/base/dueling.cc
A src/base/dueling.hh
A src/base/dueling.test.cc
4 files changed, 598 insertions(+), 0 deletions(-)



diff --git a/src/base/SConscript b/src/base/SConscript
index e04d84a..e0c3f6f 100644
--- a/src/base/SConscript
+++ b/src/base/SConscript
@@ -39,6 +39,7 @@
 Source('cprintf.cc', add_tags='gtest lib')
 GTest('cprintf.test', 'cprintf.test.cc')
 Source('debug.cc')
+Source('dueling.cc')
 if env['USE_FENV']:
     Source('fenv.c')
 if env['USE_PNG']:
@@ -89,6 +90,7 @@
 GTest('channel_addr.test', 'channel_addr.test.cc', 'channel_addr.cc')
 GTest('circlebuf.test', 'circlebuf.test.cc')
 GTest('circular_queue.test', 'circular_queue.test.cc')
+GTest('dueling.test', 'dueling.test.cc', 'dueling.cc')
 GTest('sat_counter.test', 'sat_counter.test.cc')
 GTest('refcnt.test','refcnt.test.cc')
 GTest('condcodes.test', 'condcodes.test.cc')
diff --git a/src/base/dueling.cc b/src/base/dueling.cc
new file mode 100644
index 0000000..19d2a69
--- /dev/null
+++ b/src/base/dueling.cc
@@ -0,0 +1,134 @@
+/**
+ * Copyright (c) 2019, 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.
+ */
+
+#include "base/dueling.hh"
+
+#include "base/bitfield.hh"
+#include "base/logging.hh"
+
+unsigned DuelingMonitor::numInstances = 0;
+
+Dueler::Dueler()
+  : _isSample(false), _team(0)
+{
+}
+
+void
+Dueler::setSample(uint64_t id, bool team)
+{
+    panic_if(popCount(id) != 1, "The id must have a single bit set.");
+    _isSample |= id;
+    if (team) {
+        _team |= id;
+    }
+}
+
+bool
+Dueler::isSample(uint64_t id, bool& team) const
+{
+    team = _team & id;
+    return _isSample & id;
+}
+
+DuelingMonitor::DuelingMonitor(std::size_t constituency_size,
+    std::size_t team_size, unsigned num_bits, double low_threshold,
+    double high_threshold)
+  : id(1 << numInstances), constituencySize(constituency_size),
+    teamSize(team_size), lowThreshold(low_threshold),
+    highThreshold(high_threshold), selector(num_bits), regionCounter(0),
+    winner(true)
+{
+    fatal_if(constituencySize < (NUM_DUELERS * teamSize),
+ "There must be at least team size entries per team in a constituency");
+    fatal_if(numInstances > 63, "Too many Dueling instances");
+    fatal_if((lowThreshold <= 0.0) || (highThreshold >= 1.0),
+        "The low threshold must be within the range ]0.0, 1.0[");
+    fatal_if((highThreshold <= 0.0) || (highThreshold >= 1.0),
+        "The high threshold must be within the range ]0.0, 1.0[");
+    fatal_if(lowThreshold > highThreshold,
+        "The low threshold must be below the high threshold");
+    numInstances++;
+
+    // Start selector around its middle value
+    selector.saturate();
+    selector >>= 1;
+    if (selector.calcSaturation() < lowThreshold) {
+        winner = false;
+    }
+}
+
+void
+DuelingMonitor::sample(const Dueler* dueler)
+{
+    bool team;
+    if (dueler->isSample(id, team)) {
+        if (team) {
+            selector++;
+
+            if (selector.calcSaturation() >= highThreshold) {
+                winner = true;
+            }
+        } else {
+            selector--;
+
+            if (selector.calcSaturation() < lowThreshold) {
+                winner = false;
+            }
+        }
+    }
+}
+
+bool
+DuelingMonitor::isSample(const Dueler* dueler, bool& team) const
+{
+    return dueler->isSample(id, team);
+}
+
+bool
+DuelingMonitor::getWinner() const
+{
+    return winner;
+}
+
+void
+DuelingMonitor::initEntry(Dueler* dueler)
+{
+    // Make the first entries of the constituency sampling entries, one
+    // dueling for each dueler
+    assert(dueler);
+    if (regionCounter < teamSize) {
+        dueler->setSample(id, false);
+    } else if (regionCounter < (NUM_DUELERS * teamSize)) {
+        dueler->setSample(id, true);
+    }
+
+    // Check if we changed constituencies
+    if (++regionCounter >= constituencySize) {
+        regionCounter = 0;
+    }
+}
diff --git a/src/base/dueling.hh b/src/base/dueling.hh
new file mode 100644
index 0000000..a2dd68c
--- /dev/null
+++ b/src/base/dueling.hh
@@ -0,0 +1,204 @@
+/**
+ * Copyright (c) 2019, 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.
+ */
+
+#ifndef __BASE_DUELING_HH__
+#define __BASE_DUELING_HH__
+
+#include <cstddef>
+#include <cstdint>
+
+#include "base/sat_counter.hh"
+
+/**
+ * A dueler is an entry that may or may not be accounted for sampling.
+ * Whenever an action triggers sampling, the dueling monitor will check
+ * if the dueler is a sample so that it can decide whether to perform
+ * the sampling or not.
+ *
+ * Each sampling dueler belongs to a team, "True" or "False", for which
+ * it "duels". For example, if a sample belongs to team "True" and it is
+ * sampled, team "True" will score a point.
+ *
+ * @see DuelingMonitor
+ */
+class Dueler
+{
+  private:
+    /**
+     * Whether this entry is a sample or a follower. Each bit corresponds
+     * to a different ueling monitor instance. If more than 64 instances
+     * are needed this needs to be changed to an array containing the ids
+     * being sampled.
+     */
+    uint64_t _isSample;
+
+    /**
+     * If entry is a sample, it belongs to one of two possible teams. Each
+     * bit corresponds to a different dueling monitor instance.
+     */
+    uint64_t _team;
+
+  public:
+    /** By default initializes entries as followers. */
+    Dueler();
+    virtual ~Dueler() = default;
+
+    /**
+     * Make this entry a sampling entry for a specific Dueling instance.
+     *
+     * @param id The ID of the Dueling instance that called this function.
+ * @param team Team to which this sampling entry belongs (only 2 possible).
+     */
+    void setSample(uint64_t id, bool team);
+
+    /**
+     * Check if entry is a sample for the given instance. If so, provide
+     * back its team.
+     *
+     * @param id The ID of the Dueling instance that called this function.
+ * @param team Team to which this sampling entry belongs (only 2 possible).
+     * @return Whether this is a sampling entry.
+     */
+    bool isSample(uint64_t id, bool& team) const;
+};
+
+/**
+ * Duel between two sampled options to determine which is the winner. The
+ * duel happens when a sample is taken: the saturating counter is increased
+ * if the team is "True", or decreased if the team is "False". Whenever the
+ * counter passes the flipping threshold the winning team changes.
+ *
+ * By default the threshold to change teams is the same on both ways, but
+ * this may introduce unwanted flickering, so the threshold can be split
+ * so that it takes longer to change the winning team again just after
+ * changing it.
+ *
+ * Based on Set Dueling, proposed in "Adaptive Insertion Policies for High
+ * Performance Caching".
+ */
+class DuelingMonitor
+{
+  private:
+    // There are always exactly two duelers. If this is changed the logic
+    // must be revisited
+    const int NUM_DUELERS = 2;
+
+    /**
+     * Unique identifier of this instance. It is a one bit mask used to
+     * identify which Dueler refers to this duel. This is done so that
+     * an entry can be dueled by many different policies simultaneously,
+     * which may even be of different domains (e.g., an entry can duel for
+     * 2 replacement policies, and 2 compression methods at the same time).
+     */
+    const uint64_t id;
+
+    /**
+     * Given a table containing X entries, a constituency is a region of
+     * the table such that it contains X/constituencySize entries. Each
+     * constituency contains one sample of each dueler.
+     */
+    const std::size_t constituencySize;
+
+ /** Number of entries that belong to each team within a constituency. */
+    const std::size_t teamSize;
+
+    /**
+     * If the winning team was "True", and the counter is decreased further
+     * than this threshold, "False" will become the winning team.
+     */
+    const double lowThreshold;
+
+    /**
+ * If the winning team was "False", and the counter is increased further
+     * than this threshold, "True" will become the winning team.
+     */
+    const double highThreshold;
+
+    /**
+     * Counter that determines which dueler is winning.
+     * In the DIP paper they propose using a 10-11 bit saturating counter.
+     */
+    SatCounter32 selector;
+
+    /**
+     * Counts the number of entries have been initialized in the current
+     * constituency.
+     */
+    int regionCounter;
+
+    /** The team that is currently winning. */
+    bool winner;
+
+  public:
+    /**
+ * Number of times this class has been instantiated. It is used to assign
+     * unique ids to each dueling monitor instance.
+     */
+    static unsigned numInstances;
+
+ DuelingMonitor(std::size_t constituency_size, std::size_t team_size = 1,
+        unsigned num_bits = 10, double low_threshold = 0.5,
+        double high_threshold = 0.5);
+    virtual ~DuelingMonitor() = default;
+
+    /**
+     * If given dueler is a sampling entry, sample it and check if the
+     * winning team must be updated.
+     *
+     * @param dueler The selected entry.
+     */
+    void sample(const Dueler* dueler);
+
+    /**
+ * Check if the given dueler is a sample for this instance. If so, get its
+     * team.
+     *
+     * @param dueler The selected entry.
+ * @param team Team to which this sampling entry belongs (only 2 possible).
+     * @return Whether this is a sampling entry.
+     */
+    bool isSample(const Dueler* dueler, bool& team) const;
+
+    /**
+     * Get the team that is currently winning the duel.
+     *
+     * @return Winning team.
+     */
+    bool getWinner() const;
+
+    /**
+     * Initialize a dueler entry, deciding wether it is a sample or not.
+     * We opt for a simple approach that uses the first entries of a
+     * constituency to be the samples.
+     *
+     * @param dueler The entry to be initialized.
+     */
+    void initEntry(Dueler* dueler);
+};
+
+#endif // __BASE_DUELING_HH__
diff --git a/src/base/dueling.test.cc b/src/base/dueling.test.cc
new file mode 100644
index 0000000..8799564
--- /dev/null
+++ b/src/base/dueling.test.cc
@@ -0,0 +1,258 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+#include <gtest/gtest.h>
+
+#include <cstddef>
+#include <memory>
+#include <tuple>
+#include <vector>
+
+#include "base/dueling.hh"
+#include "base/sat_counter.hh"
+
+/**
+ * Test whether dueler provides correct sampling functionality and assigns
+ * teams correctly.
+ */
+TEST(DuelerTest, SetSample)
+{
+    const int num_sampled_ids = 3;
+    bool team;
+    Dueler dueler;
+
+    // Initially nobody is sampled
+    for (int id = 0; id < 64; id++) {
+        ASSERT_FALSE(dueler.isSample(1ULL << id, team));
+    }
+
+ // Mark the first num_sampled_ids as samples and assign alternating teams
+    team = false;
+    for (int id = 0; id < num_sampled_ids; id++) {
+        team = !team;
+        dueler.setSample(1ULL << id, team);
+    }
+
+ // Make sure that only the entries marked as samples previously are samples
+    bool expected_team = false;
+    for (int id = 0; id < 64; id++) {
+        expected_team = !expected_team;
+        const bool is_sample = dueler.isSample(1ULL << id, team);
+        if (id < num_sampled_ids) {
+            ASSERT_TRUE(is_sample);
+            ASSERT_EQ(team, expected_team);
+        } else {
+            ASSERT_FALSE(is_sample);
+        }
+    }
+
+}
+
+// We assume that the monitors are assigned sequential powers of
+// two ids starting from 1
+static int monitor_id = 0;
+
+class DuelingMonitorTest : public testing::TestWithParam<
+ std::tuple<unsigned, std::size_t, std::size_t, unsigned, double, double>>
+{
+  protected:
+    /** A vector simulating a table-like structure. */
+    std::vector<Dueler> entries;
+
+    /** The constituency size, acquired from params. */
+    std::size_t constituencySize;
+
+    /** The size of a team, acquired from params. */
+    std::size_t teamSize;
+
+    /** The number of bits in the selector, acquired from params. */
+    unsigned numBits;
+
+    /** The low threshold to change winner, acquired from params. */
+    double lowThreshold;
+
+    /** The high threshold to change winner, acquired from params. */
+    double highThreshold;
+
+    /** The monitor instance being tested. */
+    std::unique_ptr<DuelingMonitor> monitor;
+
+    void
+    SetUp() override
+    {
+        const unsigned num_entries = std::get<0>(GetParam());
+        constituencySize = std::get<1>(GetParam());
+        teamSize = std::get<2>(GetParam());
+        numBits = std::get<3>(GetParam());
+        lowThreshold = std::get<4>(GetParam());
+        highThreshold = std::get<5>(GetParam());
+
+ monitor.reset(new DuelingMonitor(constituencySize, teamSize, numBits,
+            lowThreshold, highThreshold));
+
+        // Initialize entries
+        entries.resize(num_entries);
+        for (auto& entry : entries) {
+            monitor->initEntry(&entry);
+        }
+    }
+
+    void
+    TearDown() override
+    {
+        // Due to the way the DuelingMonitor works, this id is not testable
+        // anymore, so move to the next
+        monitor_id++;
+    }
+};
+
+/**
+ * Test whether entry initialization creates exactly the amount of samples
+ * requested.
+ */
+TEST_P(DuelingMonitorTest, CountSamples)
+{
+    const int expected_num_samples =
+        (entries.size() / constituencySize) * teamSize;
+
+    // Check whether the number of samples match expectation.
+    // Both teams must also have the same number of samples
+    int count_samples_true = 0;
+    int count_samples_false = 0;
+    bool team;
+    for (auto& entry : entries) {
+        if (entry.isSample(1ULL << monitor_id, team)) {
+            if (team) {
+                count_samples_true++;
+            } else {
+                count_samples_false++;
+            }
+        }
+    }
+    ASSERT_EQ(count_samples_true, count_samples_false);
+    ASSERT_EQ(count_samples_true, expected_num_samples);
+}
+
+/** Test winner selection with multiple different threshold configurations. */
+TEST_P(DuelingMonitorTest, WinnerSelection)
+{
+    SatCounter32 expected_selector(numBits);
+    expected_selector.saturate();
+    expected_selector >>= 1;
+
+    // Initialize entries, and save a pointer to a sample of each
+    // team, and one no sample
+    int team_true_index = -1;
+    int team_false_index = -1;
+    int no_sample_index = -1;
+    for (int index = 0; index < entries.size(); index++) {
+        bool team;
+        if (entries[index].isSample(1ULL << monitor_id, team)) {
+            if (team) {
+                team_true_index = index;
+            } else {
+                team_false_index = index;
+            }
+        } else {
+            no_sample_index = index;
+        }
+    }
+    ASSERT_TRUE(team_true_index >= 0);
+    ASSERT_TRUE(team_false_index >= 0);
+
+    // Duel for team true only. If the monitor starts predicting false
+    // the threshold to use is the higher one. Otherwise, we should
+    // start expecting true to be the winner, and thus we use the
+    // low threshold
+    bool current_winner = monitor->getWinner();
+    double threshold = current_winner ? lowThreshold : highThreshold;
+    for (; expected_selector.calcSaturation() < 1.0;
+        expected_selector++) {
+        ASSERT_EQ(expected_selector.calcSaturation() >= threshold,
+            monitor->getWinner());
+        monitor->sample(&entries[team_true_index]);
+    }
+    current_winner = monitor->getWinner();
+    ASSERT_TRUE(current_winner);
+
+    // Duel for no sample. Should not change winner
+    if (no_sample_index >= 0) {
+        for (int i = 0; i < 200; i++) {
+            monitor->sample(&entries[no_sample_index]);
+        }
+        ASSERT_EQ(current_winner, monitor->getWinner());
+    }
+
+    // Duel for team false only. Now that we know that team true
+    // is winning, the low threshold must be passed in order to
+    // make team false win the duel
+    threshold = lowThreshold;
+    for (; expected_selector.calcSaturation() > 0.0;
+        expected_selector--) {
+        ASSERT_EQ(expected_selector.calcSaturation() >= threshold,
+            monitor->getWinner());
+        monitor->sample(&entries[team_false_index]);
+    }
+    current_winner = monitor->getWinner();
+    ASSERT_FALSE(current_winner);
+
+    // Duel for no sample. Should not change winner
+    if (no_sample_index >= 0) {
+        for (int i = 0; i < 200; i++) {
+            monitor->sample(&entries[no_sample_index]);
+        }
+        ASSERT_EQ(current_winner, monitor->getWinner());
+    }
+}
+
+// Test a few possible parameter combinations. Cannot test more
+// because of the static limit of number of monitors. If a new test
+// is added, make sure to remove an old test
+INSTANTIATE_TEST_CASE_P(DuelingMonitorTests, DuelingMonitorTest,
+    ::testing::Values(
+        // Combinations of constituencies and teams
+        std::make_tuple(32, 2, 1, 1, 0.5, 0.5),
+        std::make_tuple(32, 4, 1, 1, 0.5, 0.5),
+        std::make_tuple(32, 4, 2, 1, 0.5, 0.5),
+        std::make_tuple(32, 8, 1, 1, 0.5, 0.5),
+        std::make_tuple(32, 8, 2, 1, 0.5, 0.5),
+        std::make_tuple(32, 8, 4, 1, 0.5, 0.5),
+        std::make_tuple(32, 16, 1, 1, 0.5, 0.5),
+        std::make_tuple(32, 16, 2, 1, 0.5, 0.5),
+        std::make_tuple(32, 16, 4, 1, 0.5, 0.5),
+        std::make_tuple(32, 16, 8, 1, 0.5, 0.5),
+
+        // Tests for the thresholds
+        std::make_tuple(16, 4, 1, 3, 0.5, 0.5),
+        std::make_tuple(16, 4, 1, 3, 0.1, 0.7),
+        std::make_tuple(16, 4, 1, 3, 0.4, 0.6),
+        std::make_tuple(16, 4, 1, 3, 0.8, 0.9),
+
+        // Test for larger tables
+        std::make_tuple(2048, 32, 4, 4, 0.4, 0.6))
+);

--
To view, visit https://gem5-review.googlesource.com/c/public/gem5/+/37895
To unsubscribe, or for help writing mail filters, visit https://gem5-review.googlesource.com/settings

Gerrit-Project: public/gem5
Gerrit-Branch: develop
Gerrit-Change-Id: I692a3e5e0ad98581d68167ad7e6b45ab2f4c7b10
Gerrit-Change-Number: 37895
Gerrit-PatchSet: 1
Gerrit-Owner: Daniel Carvalho <oda...@yahoo.com.br>
Gerrit-MessageType: newchange
_______________________________________________
gem5-dev mailing list -- gem5-dev@gem5.org
To unsubscribe send an email to gem5-dev-le...@gem5.org
%(web_page_url)slistinfo%(cgiext)s/%(_internal_name)s

Reply via email to