base: Add addIntlvBits to AddrRange

This method performs the opposite operation of removeIntlvBits and can
be used to transform a channel-local address to a global PA.

Change-Id: I2fab587d7c094597e52422305775ac7f31efba34
Signed-off-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/21599
Reviewed-by: Nikos Nikoleris <nikos.nikoleris@arm.com>
Reviewed-by: Daniel Carvalho <odanrc@yahoo.com.br>
Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
Andreas Sandberg
2019-10-07 16:11:48 +01:00
parent 2111c99600
commit e04e976e22
2 changed files with 62 additions and 0 deletions

View File

@@ -470,6 +470,44 @@ class AddrRange
return a;
}
/**
* This method adds the interleaving bits removed by
* removeIntlvBits.
*/
inline Addr addIntlvBits(Addr a) const
{
// Get the LSB set from each mask
int masks_lsb[masks.size()];
for (int i = 0; i < masks.size(); i++) {
masks_lsb[i] = ctz64(masks[i]);
}
// Add bits one-by-one from the LSB side.
std::sort(masks_lsb, masks_lsb + masks.size());
for (int i = 0; i < masks.size(); i++) {
const int intlv_bit = masks_lsb[i];
if (intlv_bit > 0) {
// on every iteration we add one bit from the input
// address, and therefore the lowest invtl_bit has
// also shifted to the left by i positions.
a = insertBits(a << 1, intlv_bit + i - 1, 0, a);
} else {
a <<= 1;
}
}
for (int i = 0; i < masks.size(); i++) {
const int lsb = ctz64(masks[i]);
const Addr intlv_bit = bits(intlvMatch, i);
// Calculate the mask ignoring the LSB
const Addr masked = a & masks[i] & ~(1 << lsb);
// Set the LSB of the mask to whatever satisfies the selector bit
a = insertBits(a, lsb, intlv_bit ^ popCount(masked));
}
return a;
}
/**
* Determine the offset of an address within the range.
*

View File

@@ -121,6 +121,16 @@ class AddrRangeBase : public testing::Test {
}
}
void testAddRemoveIntlvBits()
{
for (Addr addr = start; addr <= end; addr++) {
AddrRange &r = range[getIndex(addr)];
Addr ch_addr = r.removeIntlvBits(addr);
Addr pa = r.addIntlvBits(ch_addr);
ASSERT_EQ(addr, pa);
}
}
static const Addr end = 0x1ffff;
static const Addr start = 0x0;
static const int intlvSize = 4;
@@ -162,6 +172,11 @@ TEST_F(AddrRangeCont, AddrRangeGetOffset)
testGetOffset();
}
TEST_F(AddrRangeCont, AddrRangeAddRemoveIntlvBits)
{
testAddRemoveIntlvBits();
}
class AddrRangeContLegacy : public AddrRangeCont {
protected:
@@ -185,6 +200,10 @@ TEST_F(AddrRangeContLegacy, AddrRangeGetOffset)
testGetOffset();
}
TEST_F(AddrRangeContLegacy, AddrRangeAddRemoveIntlvBits)
{
testAddRemoveIntlvBits();
}
class AddrRangeArb : public AddrRangeBase {
protected:
@@ -218,3 +237,8 @@ TEST_F(AddrRangeArb, AddrRangeGetOffset)
{
testGetOffset();
}
TEST_F(AddrRangeArb, AddrRangeAddRemoveIntlvBits)
{
testAddRemoveIntlvBits();
}