diff --git a/kernel/bitpattern.h b/kernel/bitpattern.h index 76c008b89..848a753a5 100644 --- a/kernel/bitpattern.h +++ b/kernel/bitpattern.h @@ -102,15 +102,19 @@ struct BitPatternPool bits_t bits; bits.bitdata = sig.as_const().to_bits(); for (auto &b : bits.bitdata) - if (b > RTLIL::State::S1 && b != RTLIL::State::Sx && b != RTLIL::State::Sz) + if (b > RTLIL::State::S1) b = RTLIL::State::Sa; return bits; } - static bool covers_nothing(const bits_t &bits) + /** + * A literal x/z bit can never match a 2-valued selector, so a pattern containing + * one covers nothing. + */ + static bool covers_nothing(RTLIL::SigSpec sig) { - for (auto &b : bits.bitdata) - if (b == RTLIL::State::Sx || b == RTLIL::State::Sz) + for (auto bit : sig) + if (bit.wire == NULL && (bit.data == RTLIL::State::Sx || bit.data == RTLIL::State::Sz)) return true; return false; } @@ -139,9 +143,9 @@ struct BitPatternPool */ bool has_any(RTLIL::SigSpec sig) { - bits_t bits = sig2bits(sig); - if (covers_nothing(bits)) + if (covers_nothing(sig)) return false; + bits_t bits = sig2bits(sig); for (auto &it : database) if (match(it, bits)) return true; @@ -159,9 +163,9 @@ struct BitPatternPool */ bool has_all(RTLIL::SigSpec sig) { - bits_t bits = sig2bits(sig); - if (covers_nothing(bits)) + if (covers_nothing(sig)) return true; + bits_t bits = sig2bits(sig); for (auto &it : database) if (match(it, bits)) { for (int i = 0; i < width; i++) @@ -182,9 +186,9 @@ struct BitPatternPool bool take(RTLIL::SigSpec sig) { bool status = false; - bits_t bits = sig2bits(sig); - if (covers_nothing(bits)) + if (covers_nothing(sig)) return false; + bits_t bits = sig2bits(sig); for (auto it = database.begin(); it != database.end();) if (match(*it, bits)) { for (int i = 0; i < width; i++) { diff --git a/tests/unit/kernel/bitpatternTest.cc b/tests/unit/kernel/bitpatternTest.cc index 001d47060..a641b85a3 100644 --- a/tests/unit/kernel/bitpatternTest.cc +++ b/tests/unit/kernel/bitpatternTest.cc @@ -11,6 +11,8 @@ TEST(BitpatternTest, has) SigSpec _01a = {RTLIL::S0, RTLIL::S1, RTLIL::Sa}; SigSpec _011 = {RTLIL::S0, RTLIL::S1, RTLIL::S1}; SigSpec _111 = {RTLIL::S1, RTLIL::S1, RTLIL::S1}; + SigSpec _01x = {RTLIL::S0, RTLIL::S1, RTLIL::Sx}; + SigSpec _01z = {RTLIL::S0, RTLIL::S1, RTLIL::Sz}; EXPECT_TRUE(BitPatternPool(_aaa).has_any(_01a)); EXPECT_TRUE(BitPatternPool(_01a).has_any(_01a)); @@ -19,6 +21,10 @@ TEST(BitpatternTest, has) // overlap is symmetric EXPECT_TRUE(BitPatternPool(_01a).has_any(_011)); EXPECT_FALSE(BitPatternPool(_111).has_any(_01a)); + // overlaps nothing + EXPECT_FALSE(BitPatternPool(_011).has_any(_01x)); + EXPECT_FALSE(BitPatternPool(_011).has_any(_01z)); + EXPECT_FALSE(BitPatternPool(_aaa).has_any(_01x)); EXPECT_TRUE(BitPatternPool(_aaa).has_all(_01a)); EXPECT_TRUE(BitPatternPool(_01a).has_all(_01a)); @@ -27,6 +33,10 @@ TEST(BitpatternTest, has) // 01a is not covered by 011 EXPECT_FALSE(BitPatternPool(_011).has_all(_01a)); EXPECT_FALSE(BitPatternPool(_111).has_all(_01a)); + // trivially covered by any pool + EXPECT_TRUE(BitPatternPool(_011).has_all(_01x)); + EXPECT_TRUE(BitPatternPool(_011).has_all(_01z)); + EXPECT_TRUE(BitPatternPool(_111).has_all(_01x)); } YOSYS_NAMESPACE_END diff --git a/tests/verilog/temp/issue4402_syn.v b/tests/verilog/temp/issue4402_syn.v new file mode 100644 index 000000000..b098b8d6f --- /dev/null +++ b/tests/verilog/temp/issue4402_syn.v @@ -0,0 +1,48 @@ +/* Generated by Yosys 0.66+154 (git sha1 23aadd92a-dirty, Release, Clang /nix/store/mw4gasdvwgscgpxpzihjgchfhs3hhqhn-clang-wrapper-21.1.8/bin/clang++ 21.1.8) [git@github.com:YosysHQ/yosys at nella/x-wildcard] */ + +(* top = 1 *) +(* src = "<