From 44643b573310f910e55c7dc8adbb3cf1c550e2c4 Mon Sep 17 00:00:00 2001 From: dsengupta0628 Date: Fri, 10 Apr 2026 15:44:30 +0000 Subject: [PATCH 1/3] fix state table mbff issue and coverity in this file Signed-off-by: dsengupta0628 --- liberty/Liberty.cc | 5 ++- liberty/Liberty.i | 1 + liberty/test/cpp/TestLibertyStaCallbacks.cc | 48 +++++++++++++++++++++ 3 files changed, 52 insertions(+), 2 deletions(-) diff --git a/liberty/Liberty.cc b/liberty/Liberty.cc index 741ce875..c076d64c 100644 --- a/liberty/Liberty.cc +++ b/liberty/Liberty.cc @@ -1489,7 +1489,8 @@ LibertyCell::outputPortSequential(LibertyPort *port) bool LibertyCell::hasSequentials() const { - return !sequentials_.empty(); + return !sequentials_.empty() + || statetable_ != nullptr; } void @@ -2479,7 +2480,7 @@ LibertyPort::less(const LibertyPort *port1, { if (port1 == nullptr && port2 != nullptr) return true; - if (port1 != nullptr && port2 == nullptr) + if (port1 == nullptr || port2 == nullptr) return false; const std::string &name1 = port1->name(); const std::string &name2 = port2->name(); diff --git a/liberty/Liberty.i b/liberty/Liberty.i index f0a9bc09..81704bad 100644 --- a/liberty/Liberty.i +++ b/liberty/Liberty.i @@ -303,6 +303,7 @@ ensure_voltage_waveforms() } LibertyCell *test_cell() { return self->testCell(); } +bool has_sequentials() { return self->hasSequentials(); } } // LibertyCell methods diff --git a/liberty/test/cpp/TestLibertyStaCallbacks.cc b/liberty/test/cpp/TestLibertyStaCallbacks.cc index 70f3502f..e6e67e0c 100644 --- a/liberty/test/cpp/TestLibertyStaCallbacks.cc +++ b/liberty/test/cpp/TestLibertyStaCallbacks.cc @@ -4308,4 +4308,52 @@ library(test_r11_ccs) { }() )); } +// Regression: hasSequentials must return true for cells that define +// sequential behavior via a statetable group (no ff/latch). +// Multi-bit flip-flops (MBFFs) and clock-gated cells commonly use +// statetable instead of ff/latch groups. Without the statetable_ +// check in hasSequentials(), these cells are misclassified as +// combinational — breaking power categorization, resizer guards, +// and dbSta cell-type mapping. +TEST_F(StaLibertyTest, HasSequentialsStatetableMBFF) { + const char *content = R"( +library(test_mbff_statetable) { + delay_model : table_lookup ; + time_unit : "1ns" ; + voltage_unit : "1V" ; + current_unit : "1mA" ; + capacitive_load_unit(1, ff) ; + cell(MBFF2) { + area : 6.0 ; + pin(D0) { direction : input ; capacitance : 0.01 ; } + pin(D1) { direction : input ; capacitance : 0.01 ; } + pin(CLK) { direction : input ; capacitance : 0.01 ; clock : true ; } + pin(Q0) { direction : output ; function : "IQ0" ; } + pin(Q1) { direction : output ; function : "IQ1" ; } + statetable("D0 D1 CLK", "IQ0 IQ1") { + table : "- - ~R : - - : N N ,\ + H - R : - - : H N ,\ + L - R : - - : L N ,\ + - H R : - - : N H ,\ + - L R : - - : N L" ; + } + } +} +)"; + LibertyLibrary *lib = writeAndReadLibReturn(sta_, content); + ASSERT_NE(lib, nullptr); + LibertyCell *mbff = lib->findLibertyCell("MBFF2"); + ASSERT_NE(mbff, nullptr); + + // The cell has no ff/latch group, so sequentials_ is empty. + EXPECT_TRUE(mbff->sequentials().empty()); + // But it has a statetable, so it IS sequential. + EXPECT_NE(mbff->statetable(), nullptr); + // hasSequentials() must return true for statetable-only cells. + EXPECT_TRUE(mbff->hasSequentials()) + << "MBFF2 uses statetable (no ff/latch) but hasSequentials() " + "returned false — statetable cells are misclassified as " + "combinational"; +} + } // namespace sta From 5878d2594d4992ec913bb11eae116fa23014be68 Mon Sep 17 00:00:00 2001 From: dsengupta0628 Date: Fri, 10 Apr 2026 15:53:55 +0000 Subject: [PATCH 2/3] Dont update the swig as we are not adding any TCL regression so not needed Signed-off-by: dsengupta0628 --- liberty/Liberty.i | 1 - 1 file changed, 1 deletion(-) diff --git a/liberty/Liberty.i b/liberty/Liberty.i index 81704bad..f0a9bc09 100644 --- a/liberty/Liberty.i +++ b/liberty/Liberty.i @@ -303,7 +303,6 @@ ensure_voltage_waveforms() } LibertyCell *test_cell() { return self->testCell(); } -bool has_sequentials() { return self->hasSequentials(); } } // LibertyCell methods From 097daeb3c5b8461b15007d3f3610d19f187bab51 Mon Sep 17 00:00:00 2001 From: dsengupta0628 Date: Fri, 10 Apr 2026 18:59:42 +0000 Subject: [PATCH 3/3] address comment related to Coverity to simplify Signed-off-by: dsengupta0628 --- liberty/Liberty.cc | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/liberty/Liberty.cc b/liberty/Liberty.cc index c076d64c..19177c68 100644 --- a/liberty/Liberty.cc +++ b/liberty/Liberty.cc @@ -2478,10 +2478,8 @@ bool LibertyPort::less(const LibertyPort *port1, const LibertyPort *port2) { - if (port1 == nullptr && port2 != nullptr) - return true; if (port1 == nullptr || port2 == nullptr) - return false; + return port1 == nullptr && port2 != nullptr; const std::string &name1 = port1->name(); const std::string &name2 = port2->name(); if (name1 == name2) {