From 36e59917a72b5d654b115bf995cbba659b069874 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Thu, 10 Oct 2019 16:02:46 -0700 Subject: [PATCH] tests: Added GTests for base/bitfield.hh In addition to the tests, a more detailed explanation of how "insertBits(..)" functions has been included in its doxygen documentation. The previous explanation was ambigious and led to confusion. Change-Id: I2ae8608733ebaa8f8f726cbb3a2cd8639b69c6b7 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/21700 Tested-by: kokoro Reviewed-by: Gabe Black Reviewed-by: Daniel Carvalho Maintainer: Jason Lowe-Power --- src/base/SConscript | 1 + src/base/bitfield.hh | 9 +- src/base/bitfield.test.cc | 409 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 418 insertions(+), 1 deletion(-) create mode 100644 src/base/bitfield.test.cc diff --git a/src/base/SConscript b/src/base/SConscript index 89a8dceba..ca8182203 100644 --- a/src/base/SConscript +++ b/src/base/SConscript @@ -37,6 +37,7 @@ SimObject('Graphics.py') Source('atomicio.cc') GTest('atomicio.test', 'atomicio.test.cc', 'atomicio.cc') Source('bitfield.cc') +GTest('bitfield.test', 'bitfield.test.cc', 'bitfield.cc') Source('imgwriter.cc') Source('bmpwriter.cc') Source('callback.cc') diff --git a/src/base/bitfield.hh b/src/base/bitfield.hh index f2893962c..08e3d2c94 100644 --- a/src/base/bitfield.hh +++ b/src/base/bitfield.hh @@ -117,7 +117,14 @@ sext(uint64_t val) } /** - * Return val with bits first to last set to bit_val + * Returns val with bits first to last set to the LSBs of bit_val + * + * E.g.: + * first: 7 + * last: 4 + * val: 0xFFFF + * bit_val: 0x0000 + * returned: 0xFF0F */ template inline diff --git a/src/base/bitfield.test.cc b/src/base/bitfield.test.cc new file mode 100644 index 000000000..0ee2a510c --- /dev/null +++ b/src/base/bitfield.test.cc @@ -0,0 +1,409 @@ +/* + * Copyright (c) 2019 The Regents of the University of California + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * 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: Bobby R. Bruce + */ + +#include + +#include "base/bitfield.hh" + +/* + * The following tests the "mask(N)" function. It is assumed that the mask + * returned is a 64 bit value with the N LSBs set to one. + */ +TEST(BitfieldTest, Mask0Bits) +{ + EXPECT_EQ(0x0, mask(0)); +} + +TEST(BitfieldTest, Mask1Bit) +{ + EXPECT_EQ(0x1, mask(1)); +} + +TEST(BitfieldTest, Mask8Bits) +{ + EXPECT_EQ(0xFF, mask(8)); +} + +TEST(BitfieldTest, Mask16Bits) +{ + EXPECT_EQ(0xFFFF, mask(16)); +} + +TEST(BitfieldTest, Mask32Bits) +{ + EXPECT_EQ(0xFFFFFFFF, mask(32)); +} + +TEST(BitfieldTest, MaskAllBits) +{ + EXPECT_EQ(0xFFFFFFFFFFFFFFFF, mask(64)); +} + +TEST(BitfieldTest, MaskAllBitsGreaterThan64) +{ + /* We cannot create a mask greater than 64 bits. It should default to 64 + * bits if this occurs. + */ + EXPECT_EQ(0xFFFFFFFFFFFFFFFF, mask(70)); +} + +/* + * The following tests "mask(X, Y)". mask will create a 64 bit value with bits + * X to Y (inclusive) set to one. + */ +TEST(BitfieldTest, MaskOneBit) +{ + EXPECT_EQ(1, mask(0,0)); +} + +TEST(BitfieldTest, MaskTwoBits) +{ + EXPECT_EQ((1 << 1) + 1, mask(1,0)); +} + +TEST(BitfieldTest, MaskThreeBits) +{ + EXPECT_EQ((1 << 5) + (1 << 4) + (1 << 3), mask(5,3)); +} + +TEST(BitfieldTest, MaskEntireRange) +{ + EXPECT_EQ(0xFFFFFFFFFFFFFFFF, mask(63,0)); +} + +TEST(BitfieldTest, MaskOutsideOfRange) +{ + // Masking >64 bits is not possible. The maximum is a 64 bit mask. + EXPECT_EQ(0xFFFFFFFFFFFFFFFF, mask(100, 0)); +} + +/* + * The following tests "bits". This function extracts bit/bits from the input + * value and return them as the LSBs. The remaining bits are set to zero. + */ +TEST(BitfieldTest, ExtractOneBit) +{ + int32_t x = 1 << 31; + EXPECT_EQ(1, bits(x, 31)); +} + +TEST(BitfieldTest, Extract63rdBit) +{ + int64_t x = 1ULL << 63; + EXPECT_EQ(1, bits(x, 63)); +} + +TEST(BitfieldTest, ExtractFirstBit) +{ + int64_t x = 1; + EXPECT_EQ(1, bits(x, 0)); +} + +TEST(BitfieldTest, ExtractFirstBitFirstBitZero) +{ + int64_t x = 1 << 1; + EXPECT_EQ(0, bits(x, 0)); +} + +TEST(BitfieldTest, ExtractThreeBits) +{ + uint64_t x = 1 << 31; + EXPECT_EQ((1 << 2), bits(x, 31, 29)); +} + + +/* + * The following tests "mbits(X, Y, Z)". mbits returns a value with bits Y to + * Z from X (in position Y to Z). + */ +TEST(BitfieldTest, MbitsStandardCase) +{ + uint64_t x = (1 << 10) + (1 << 1); + EXPECT_EQ((1 << 10), mbits(x, 10, 8)); +} + +TEST(BitfieldTest, MbitsEntireRange) +{ + uint64_t x = (1ULL << 63) + 1; + EXPECT_EQ((1ULL << 63) + 1, mbits(x, 63, 0)); +} + +/* + * The following tests the "sext(X)" function. sext carries out a sign + * extention from N bits to 64 bits on value X. + */ +TEST(BitfieldTest, SignExtendPositiveInput) +{ + int8_t val = 14; + int64_t output = 14; + EXPECT_EQ(output, sext<8>(val)); +} + +TEST(BitfieldTest, SignExtendNegativeInput) +{ + int8_t val = -14; + uint64_t output = -14; + EXPECT_EQ(output, sext<8>(val)); +} + +TEST(BitfieldTest, SignExtendPositiveInputOutsideRange) +{ + EXPECT_EQ((1 << 10), sext<8>(1 << 10)); +} + +TEST(BitfieldTest, SignExtendNegativeInputOutsideRange) +{ + uint64_t val = 0x4800000010000008; + uint64_t output = 0xF800000010000008; + EXPECT_EQ(output, sext<60>(val)); +} + +/* The following tests "insertBits(A, B, C, D)". insertBits returns A + * with bits B to C set to D's (B - C) LSBs. "insertBits(A, B, D)" overrides + * the function to insert only B's LSB to position B. + */ +TEST(BitfieldTest, InsertOneBitTo3) +{ + int64_t val = 0; + int64_t bits = (1 << 3) + (1 << 2) + (1 << 1) + 1; + EXPECT_EQ((1 << 3), insertBits(val, 3, bits)); +} + +TEST(BitfieldTest, InsertOneBitTo18) +{ + int64_t val = 0; + int64_t bits = (1 << 3) + (1 << 2) + (1 << 1) + 1; + EXPECT_EQ((1 << 18), insertBits(val, 18, bits)); +} + +TEST(BitfieldTest, InsertOneBitTo3LsbZero) +{ + int64_t val = 0; + int64_t bits = (1 << 3) + (1 << 2) + (1 << 1); + EXPECT_EQ(0, insertBits(val, 3, bits)); +} + +TEST(BitfieldTest, InsertOneBitTo18LsbZero) +{ + int64_t val = 0; + int64_t bits = (1 << 3) + (1 << 2) + (1 << 1); + EXPECT_EQ(0, insertBits(val, 18, bits)); +} + +TEST(BitfieldTest, InsertOnBitTo8LsbZero) +{ + int64_t val = (1 << 8); + int64_t bits = (1 << 3) + (1 << 2) + (1 << 1); + EXPECT_EQ(0, insertBits(val, 8, bits)); +} + +TEST(BitfieldTest, InsertMultipleBits) +{ + int64_t val = (1ULL << 63); + int64_t bits = (1 << 2) + 1; + EXPECT_EQ(val + (1 << 5) + (1 << 3), insertBits(val, 5, 3, bits)); +} + +TEST(BitfieldTest, InsertMultipleBitsOverwrite) +{ + int64_t val = (1 << 29); + int64_t bits = (1 << 2) + 1; + EXPECT_EQ((1 << 30) + (1 << 28), insertBits(val, 30, 28, bits)); +} + +// The following tests the "reverseBits" function. +TEST(BitfieldTest, ReverseBits8Bit) +{ + uint8_t value = (1 << 7); + EXPECT_EQ(1, reverseBits(value)); +} + +TEST(BitfieldTest, ReverseBits64Bit) +{ + uint64_t value = 0xF0F0F0F0F0F0F0F1; + EXPECT_EQ(0x8F0F0F0F0F0F0F0F, reverseBits(value)); +} + +/* The following tests "findMsb" and "findLsb". These return the most position + * of the MSBs/LSBs of the input value. + */ +TEST(BitfieldTest, FindMsb29) +{ + uint64_t val = (1 << 29) + (1 << 1); + EXPECT_EQ(29, findMsbSet(val)); +} + +TEST(BitfieldTest, FindMsb63) +{ + uint64_t val = (1ULL << 63) + (1ULL << 60) + (1 << 1); + EXPECT_EQ(63, findMsbSet(val)); +} + + +TEST(BitfieldTest, FindMsbZero) +{ + EXPECT_EQ(0, findMsbSet(0)); +} + +TEST(BitfieldTest, FindLsb) +{ + uint64_t val = (1ULL << 63) + (1 << 1); + EXPECT_EQ(1, findLsbSet(val)); +} + +TEST(BitfieldTest, FindLsbZero) +{ + EXPECT_EQ(64, findLsbSet(0)); +} + +/* The following tests a simple function that verifies whether a value is a + * a power of two or not. + */ +TEST(BitfieldTest, IsPow2) +{ + EXPECT_TRUE(isPow2(32)); +} + +TEST(BitfieldTest, IsNotPow2) +{ + EXPECT_FALSE(isPow2(36)); +} + +TEST(BitfieldTest, IsPow2Zero) +{ + EXPECT_TRUE(isPow2(0)); +} + +/* + * The following tests "popCount(X)". popCount counts the number of bits set to + * one. + */ +TEST(BitfieldTest, PopCountNoBits) +{ + EXPECT_EQ(0, popCount(0)); +} + +TEST(BitfieldTest, PopCountOneBit) +{ + int64_t val = (1 << 9); + EXPECT_EQ(1, popCount(val)); +} + +TEST(BitfieldTest, PopCountManyBits) +{ + int64_t val = (1 << 22) + (1 << 21) + (1 << 15) + (1 << 9) + 1; + EXPECT_EQ(5, popCount(val)); +} + +TEST(BitfieldTest, PopCountAllOnes) +{ + int64_t val = 0xFFFFFFFFFFFFFFFF; + EXPECT_EQ(64, popCount(val)); +} + +/* + * The following tests the "alignToPowerOfTwo(x)" function which rounds + * uint64_t x up to the nearest power of two. If x is already a power + * of two, that power is returned. + */ +TEST(BitfieldTest, AlignToPowerOfTwo0) +{ + EXPECT_EQ(0, alignToPowerOfTwo(0)); +} + +TEST(BitfieldTest, AlignToPowerOfTwo3) +{ + EXPECT_EQ(4, alignToPowerOfTwo(3)); +} + +TEST(BitfieldTest, AlignToPowerOfTwo5) +{ + EXPECT_EQ(8, alignToPowerOfTwo(5)); +} + +TEST(BitfieldTest, AlignToPowerOfTwo10) +{ + EXPECT_EQ(16, alignToPowerOfTwo(10)); +} + +TEST(BitfieldTest, AlignToPowerOfTwo16) +{ + EXPECT_EQ(16, alignToPowerOfTwo(16)); +} + +TEST(BitfieldTest, AlignToPowerOfTwo31) +{ + EXPECT_EQ(32, alignToPowerOfTwo(31)); +} + +/* + * The following tests test ctz32/64. The value returned in all cases should + * be equal to the number of trailing zeros (i.e., the number before the first + * bit set to one). + */ + +TEST(BitfieldTest, CountTrailingZeros32BitsNoTrailing) +{ + int32_t value = 1; + EXPECT_EQ(0, ctz32(value)); +} + +TEST(BitfieldTest, CountTrailingZeros32Bits) +{ + uint32_t value = (1 << 30) + (1 << 29); + EXPECT_EQ(29, ctz32(value)); +} + +TEST(BitfieldTest, CountTrailingZeros64BitsNoTrailing) +{ + uint64_t value = (1 << 29) + 1; + EXPECT_EQ(0, ctz64(value)); +} + +TEST(BitfieldTest, CountTrailingZeros64Bits) +{ + uint64_t value = 1ULL << 63; + EXPECT_EQ(63, ctz64(value)); +} + +TEST(BitfieldTest, CountTrailingZero64AllZeros) +{ + uint64_t value = 0; + EXPECT_EQ(64, ctz64(value)); +} \ No newline at end of file -- 2.30.2