The function name `update` is too generic. Given that the expected functionality is to replace the selected flag bits with the bits provided as parameters, rename it as `replace`. Change-Id: Ic7613ae09ecf9b92e31103b4e928192c07e9b640 Signed-off-by: Daniel R. Carvalho <odanrc@yahoo.com.br> Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/38737 Tested-by: kokoro <noreply+kokoro@google.com> Reviewed-by: Jason Lowe-Power <power.jg@gmail.com> Maintainer: Bobby R. Bruce <bbruce@ucdavis.edu>
213 lines
7.0 KiB
C++
213 lines
7.0 KiB
C++
/*
|
|
* Copyright (c) 2020 Daniel R. Carvalho
|
|
* 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 <cstdint>
|
|
#include <limits>
|
|
|
|
#include "base/flags.hh"
|
|
|
|
/** Test default zero-initialized constructor. */
|
|
TEST(FlagsTest, ConstructorZero)
|
|
{
|
|
const Flags<uint32_t> flags;
|
|
ASSERT_EQ(uint32_t(0), uint32_t(flags));
|
|
}
|
|
|
|
/** Test constructor with a single-bit initial value. */
|
|
TEST(FlagsTest, ConstructorSingle)
|
|
{
|
|
const uint32_t value = (1 << 3);
|
|
const Flags<uint32_t> flags(value);
|
|
ASSERT_EQ(value, uint32_t(flags));
|
|
}
|
|
|
|
/** Test constructor with an initial multi-bit value. */
|
|
TEST(FlagsTest, ConstructorMulti)
|
|
{
|
|
const uint32_t value = (1 << 3) | (1 << 5) | (1 << 9);
|
|
const Flags<uint32_t> flags(value);
|
|
ASSERT_EQ(value, uint32_t(flags));
|
|
}
|
|
|
|
/** Test assignment of variable of underlying type. */
|
|
TEST(FlagsTest, TypeAssignment)
|
|
{
|
|
const uint32_t value = (1 << 3) | (1 << 5) | (1 << 9);
|
|
Flags<uint32_t> flags;
|
|
flags = value;
|
|
ASSERT_EQ(value, uint32_t(flags));
|
|
}
|
|
|
|
/**
|
|
* Test assignment of variable of underlying type, overwriting an initial
|
|
* value.
|
|
*/
|
|
TEST(FlagsTest, TypeAssignmentOverwrite)
|
|
{
|
|
const uint32_t init_value = (1 << 5) | (1 << 6) ;
|
|
const uint32_t value = (1 << 3) | (1 << 5) | (1 << 9);
|
|
Flags<uint32_t> flags(init_value);
|
|
flags = value;
|
|
ASSERT_EQ(value, uint32_t(flags));
|
|
}
|
|
|
|
/** Test assignment of other Flags. */
|
|
TEST(FlagsTest, FlagsAssignment)
|
|
{
|
|
const uint32_t value = (1 << 3) | (1 << 5) | (1 << 9);
|
|
Flags<uint32_t> flags_a;
|
|
Flags<uint32_t> flags_b(value);
|
|
flags_a = flags_b;
|
|
ASSERT_EQ(uint32_t(flags_a), uint32_t(flags_b));
|
|
}
|
|
|
|
/** Test assignment of other Flags, overwriting an initial value. */
|
|
TEST(FlagsTest, FlagsAssignmentOverwrite)
|
|
{
|
|
const uint32_t init_value = (1 << 5) | (1 << 6);
|
|
const uint32_t value = (1 << 3) | (1 << 5) | (1 << 9);
|
|
Flags<uint32_t> flags_a(init_value);
|
|
Flags<uint32_t> flags_b(value);
|
|
flags_a = flags_b;
|
|
ASSERT_EQ(uint32_t(flags_a), uint32_t(flags_b));
|
|
}
|
|
|
|
/** Test isSet for multiple bits set. */
|
|
TEST(FlagsTest, IsSetValue)
|
|
{
|
|
const uint32_t value_a = (1 << 3);
|
|
const uint32_t value_b = (1 << 5);
|
|
const Flags<uint32_t> flags(value_a | value_b);
|
|
ASSERT_TRUE(flags.isSet(value_a));
|
|
ASSERT_FALSE(flags.isSet(value_a << 1));
|
|
ASSERT_TRUE(flags.isSet(value_b));
|
|
}
|
|
|
|
/** Test isSet comparing against another flag. */
|
|
TEST(FlagsTest, IsSetType)
|
|
{
|
|
const uint32_t value_a = (1 << 5) | (1 << 6);
|
|
const uint32_t value_b = (1 << 3) | (1 << 5) | (1 << 9);
|
|
const uint32_t value_c = (1 << 4) | (1 << 8);
|
|
const Flags<uint32_t> flags(value_a);
|
|
ASSERT_TRUE(flags.isSet(value_b));
|
|
ASSERT_FALSE(flags.isSet(value_c));
|
|
}
|
|
|
|
/** Test allSet comparing against another flag. */
|
|
TEST(FlagsTest, AllSetMatch)
|
|
{
|
|
const uint32_t value_a = (1 << 5) | (1 << 6);
|
|
const uint32_t value_b = (1 << 3) | (1 << 5) | (1 << 9);
|
|
const Flags<uint32_t> flags(value_a);
|
|
ASSERT_TRUE(flags.allSet(value_a));
|
|
ASSERT_FALSE(flags.allSet(value_b));
|
|
}
|
|
|
|
/** Test noneSet comparing against another flag. */
|
|
TEST(FlagsTest, NoneSetMatch)
|
|
{
|
|
const uint32_t value_a = (1 << 5) | (1 << 6);
|
|
const uint32_t value_b = (1 << 3) | (1 << 6);
|
|
const uint32_t value_c = (1 << 3) | (1 << 4) | (1 << 9);
|
|
const Flags<uint32_t> flags(value_a);
|
|
ASSERT_FALSE(flags.noneSet(value_a));
|
|
ASSERT_FALSE(flags.noneSet(value_b));
|
|
ASSERT_TRUE(flags.noneSet(value_c));
|
|
}
|
|
|
|
/** Test if no bits are set after a full clear. */
|
|
TEST(FlagsTest, Clear)
|
|
{
|
|
const uint32_t value = (1 << 5) | (1 << 6);
|
|
Flags<uint32_t> flags(value);
|
|
flags.clear();
|
|
ASSERT_EQ(0, uint32_t(flags));
|
|
}
|
|
|
|
/** Test clearing specific bits. */
|
|
TEST(FlagsTest, ClearMatch)
|
|
{
|
|
const uint32_t value_a = (1 << 5) | (1 << 6);
|
|
const uint32_t value_b = (1 << 3) | (1 << 5) | (1 << 9);
|
|
Flags<uint32_t> flags(value_a);
|
|
flags.clear(value_b);
|
|
ASSERT_FALSE(flags.isSet(value_a & value_b));
|
|
ASSERT_TRUE(flags.isSet(value_a ^ (value_a & value_b)));
|
|
}
|
|
|
|
/** Test setting with a few overlapping bits. */
|
|
TEST(FlagsTest, SetOverlapping)
|
|
{
|
|
const uint32_t value_a = (1 << 5) | (1 << 6);
|
|
const uint32_t value_b = (1 << 3) | (1 << 5) | (1 << 9);
|
|
Flags<uint32_t> flags(value_a);
|
|
flags.set(value_b);
|
|
ASSERT_EQ(value_a | value_b, uint32_t(flags));
|
|
}
|
|
|
|
/**
|
|
* Test conditional set. If true the selected bits are set; otherwise, they
|
|
* are cleared.
|
|
*/
|
|
TEST(FlagsTest, ConditionalSet)
|
|
{
|
|
const uint32_t value_a = (1 << 5) | (1 << 6);
|
|
const uint32_t value_b = (1 << 3) | (1 << 5) | (1 << 9);
|
|
|
|
Flags<uint32_t> flags_true(value_a);
|
|
flags_true.set(value_b, true);
|
|
ASSERT_EQ(value_a | value_b, uint32_t(flags_true));
|
|
|
|
Flags<uint32_t> flags_false(value_a);
|
|
flags_false.set(value_b, false);
|
|
ASSERT_EQ(value_a & ~value_b, uint32_t(flags_false));
|
|
}
|
|
|
|
/**
|
|
* Test replacing a masked selection of bits. This means that bits of the
|
|
* original value that match the mask will be replaced by the bits of
|
|
* the new value that match the mask.
|
|
*/
|
|
TEST(FlagsTest, ReplaceOverlapping)
|
|
{
|
|
const uint32_t value_a = (1 << 4) | (1 << 5) | (1 << 6);
|
|
const uint32_t value_b = (1 << 3) | (1 << 5) | (1 << 9);
|
|
const uint32_t mask = (1 << 4) | (1 << 5) | (1 << 9) | (1 << 10);
|
|
// (1 << 4) is set in value_a, but is not set in value_b, so it is cleared
|
|
// (1 << 5) is set in both values, so it remains set
|
|
// (1 << 9) is not set in value_a, but it is in value_b, so it is set
|
|
// (1 << 10) is not set in both values, so it remains not set
|
|
const uint32_t result = (1 << 5) | (1 << 6) | (1 << 9);
|
|
Flags<uint32_t> flags(value_a);
|
|
flags.replace(value_b, mask);
|
|
ASSERT_EQ(result, uint32_t(flags));
|
|
}
|