From a515055be4a8ff78dd6712334b3f7c452e8bad93 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Fri, 29 Aug 2025 04:50:35 +0000 Subject: [PATCH] Make Const::is_*() functions work on packed bits without decaying to vector --- kernel/rtlil.cc | 44 ++++++++++------ tests/unit/kernel/rtlilTest.cc | 91 ++++++++++++++++++++++++++++++++++ 2 files changed, 120 insertions(+), 15 deletions(-) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 1abb58fc5..4175a008d 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -632,10 +632,17 @@ RTLIL::State RTLIL::Const::const_iterator::operator*() const { bool RTLIL::Const::is_fully_zero() const { - bitvectorize_internal(); - bitvectype& bv = get_bits(); cover("kernel.rtlil.const.is_fully_zero"); + if (auto str = get_if_str()) { + for (char ch : *str) + if (ch != 0) + return false; + return true; + } + + bitvectype& bv = get_bits(); + for (const auto &bit : bv) if (bit != RTLIL::State::S0) return false; @@ -645,10 +652,16 @@ bool RTLIL::Const::is_fully_zero() const bool RTLIL::Const::is_fully_ones() const { - bitvectorize_internal(); - bitvectype& bv = get_bits(); cover("kernel.rtlil.const.is_fully_ones"); + if (auto str = get_if_str()) { + for (char ch : *str) + if (ch != (char)0xff) + return false; + return true; + } + + bitvectype& bv = get_bits(); for (const auto &bit : bv) if (bit != RTLIL::State::S1) return false; @@ -660,9 +673,10 @@ bool RTLIL::Const::is_fully_def() const { cover("kernel.rtlil.const.is_fully_def"); - bitvectorize_internal(); - bitvectype& bv = get_bits(); + if (is_str()) + return true; + bitvectype& bv = get_bits(); for (const auto &bit : bv) if (bit != RTLIL::State::S0 && bit != RTLIL::State::S1) return false; @@ -674,9 +688,10 @@ bool RTLIL::Const::is_fully_undef() const { cover("kernel.rtlil.const.is_fully_undef"); - bitvectorize_internal(); - bitvectype& bv = get_bits(); + if (auto str = get_if_str()) + return str->empty(); + bitvectype& bv = get_bits(); for (const auto &bit : bv) if (bit != RTLIL::State::Sx && bit != RTLIL::State::Sz) return false; @@ -688,9 +703,10 @@ bool RTLIL::Const::is_fully_undef_x_only() const { cover("kernel.rtlil.const.is_fully_undef_x_only"); - bitvectorize_internal(); - bitvectype& bv = get_bits(); + if (auto str = get_if_str()) + return str->empty(); + bitvectype& bv = get_bits(); for (const auto &bit : bv) if (bit != RTLIL::State::Sx) return false; @@ -702,12 +718,10 @@ bool RTLIL::Const::is_onehot(int *pos) const { cover("kernel.rtlil.const.is_onehot"); - bitvectorize_internal(); - bitvectype& bv = get_bits(); - bool found = false; - for (int i = 0; i < GetSize(*this); i++) { - auto &bit = bv[i]; + int size = GetSize(*this); + for (int i = 0; i < size; i++) { + State bit = (*this)[i]; if (bit != RTLIL::State::S0 && bit != RTLIL::State::S1) return false; if (bit == RTLIL::State::S1) { diff --git a/tests/unit/kernel/rtlilTest.cc b/tests/unit/kernel/rtlilTest.cc index 5f8c0dd06..97cc936de 100644 --- a/tests/unit/kernel/rtlilTest.cc +++ b/tests/unit/kernel/rtlilTest.cc @@ -157,6 +157,50 @@ namespace RTLIL { Const c(v); EXPECT_EQ(c.decode_string(), " "); } + + { + Const c(" "); + EXPECT_TRUE(c.is_str()); + EXPECT_FALSE(c.is_fully_zero()); + EXPECT_TRUE(c.is_str()); + } + + { + Const c(" "); + EXPECT_TRUE(c.is_str()); + EXPECT_FALSE(c.is_fully_ones()); + EXPECT_TRUE(c.is_str()); + } + + { + Const c(" "); + EXPECT_TRUE(c.is_str()); + EXPECT_TRUE(c.is_fully_def()); + EXPECT_TRUE(c.is_str()); + } + + { + Const c(" "); + EXPECT_TRUE(c.is_str()); + EXPECT_FALSE(c.is_fully_undef()); + EXPECT_TRUE(c.is_str()); + } + + { + Const c(" "); + EXPECT_TRUE(c.is_str()); + EXPECT_FALSE(c.is_fully_undef_x_only()); + EXPECT_TRUE(c.is_str()); + } + + { + Const c(" "); + EXPECT_TRUE(c.is_str()); + int pos; + EXPECT_TRUE(c.is_onehot(&pos)); + EXPECT_EQ(pos, 5); + EXPECT_TRUE(c.is_str()); + } } TEST_F(KernelRtlilTest, ConstConstIteratorWorks) { @@ -267,6 +311,53 @@ namespace RTLIL { EXPECT_NE(hash(Const(v1)), hash(Const("a"))); } + TEST_F(KernelRtlilTest, ConstIsFullyZero) { + EXPECT_TRUE(Const(0, 8).is_fully_zero()); + EXPECT_FALSE(Const(8, 8).is_fully_zero()); + EXPECT_TRUE(Const().is_fully_zero()); + } + + TEST_F(KernelRtlilTest, ConstIsFullyOnes) { + EXPECT_TRUE(Const(0xf, 4).is_fully_ones()); + EXPECT_FALSE(Const(3, 4).is_fully_ones()); + EXPECT_TRUE(Const().is_fully_ones()); + } + + TEST_F(KernelRtlilTest, ConstIsFullyDef) { + EXPECT_TRUE(Const(0xf, 4).is_fully_def()); + std::vector v1 = {S0, Sx}; + EXPECT_FALSE(Const(v1).is_fully_def()); + EXPECT_TRUE(Const().is_fully_def()); + } + + TEST_F(KernelRtlilTest, ConstIsFullyUndef) { + std::vector v1 = {S0, Sx}; + EXPECT_FALSE(Const(v1).is_fully_undef()); + EXPECT_TRUE(Const(Sz, 2).is_fully_undef()); + EXPECT_TRUE(Const().is_fully_undef()); + } + + TEST_F(KernelRtlilTest, ConstIsFullyUndefXOnly) { + std::vector v1 = {Sx, Sz}; + EXPECT_FALSE(Const(v1).is_fully_undef_x_only()); + EXPECT_TRUE(Const(Sx, 2).is_fully_undef_x_only()); + EXPECT_TRUE(Const().is_fully_undef_x_only()); + } + + TEST_F(KernelRtlilTest, ConstIsOnehot) { + int pos; + EXPECT_TRUE(Const(0x80, 8).is_onehot(&pos)); + EXPECT_EQ(pos, 7); + EXPECT_FALSE(Const(0x82, 8).is_onehot(&pos)); + EXPECT_FALSE(Const(0, 8).is_onehot(&pos)); + EXPECT_TRUE(Const(1, 1).is_onehot(&pos)); + EXPECT_EQ(pos, 0); + EXPECT_FALSE(Const(Sx, 1).is_onehot(&pos)); + std::vector v1 = {Sx, S1}; + EXPECT_FALSE(Const(v1).is_onehot(&pos)); + EXPECT_FALSE(Const().is_onehot(&pos)); + } + class WireRtlVsHdlIndexConversionTest : public KernelRtlilTest, public testing::WithParamInterface>