fix state table mbff issue and coverity in this file
Signed-off-by: dsengupta0628 <dsengupta@precisioninno.com>
This commit is contained in:
parent
defec0bda3
commit
44643b5733
|
|
@ -1489,7 +1489,8 @@ LibertyCell::outputPortSequential(LibertyPort *port)
|
||||||
bool
|
bool
|
||||||
LibertyCell::hasSequentials() const
|
LibertyCell::hasSequentials() const
|
||||||
{
|
{
|
||||||
return !sequentials_.empty();
|
return !sequentials_.empty()
|
||||||
|
|| statetable_ != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -2479,7 +2480,7 @@ LibertyPort::less(const LibertyPort *port1,
|
||||||
{
|
{
|
||||||
if (port1 == nullptr && port2 != nullptr)
|
if (port1 == nullptr && port2 != nullptr)
|
||||||
return true;
|
return true;
|
||||||
if (port1 != nullptr && port2 == nullptr)
|
if (port1 == nullptr || port2 == nullptr)
|
||||||
return false;
|
return false;
|
||||||
const std::string &name1 = port1->name();
|
const std::string &name1 = port1->name();
|
||||||
const std::string &name2 = port2->name();
|
const std::string &name2 = port2->name();
|
||||||
|
|
|
||||||
|
|
@ -303,6 +303,7 @@ ensure_voltage_waveforms()
|
||||||
}
|
}
|
||||||
|
|
||||||
LibertyCell *test_cell() { return self->testCell(); }
|
LibertyCell *test_cell() { return self->testCell(); }
|
||||||
|
bool has_sequentials() { return self->hasSequentials(); }
|
||||||
|
|
||||||
} // LibertyCell methods
|
} // LibertyCell methods
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
} // namespace sta
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue