blob: b8b3a528281727f6d48975b9729ca3146e16be72 [file] [log] [blame]
/**
* 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 "mem/cache/tags/dueling.hh"
#include "base/bitfield.hh"
#include "base/logging.hh"
namespace gem5
{
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.");
panic_if(_isSample & id,
"This dueler is already a sample for id %llu", id);
_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)
{
// The first entries of the constituency belong to one team, and the
// last entries to the other
assert(dueler);
if (regionCounter < teamSize) {
dueler->setSample(id, false);
} else if (regionCounter >= constituencySize - teamSize) {
dueler->setSample(id, true);
}
// Check if we changed constituencies
if (++regionCounter >= constituencySize) {
regionCounter = 0;
}
}
} // namespace gem5