2864 lines
71 KiB
C++
2864 lines
71 KiB
C++
#include <gtest/gtest.h>
|
|
#include <type_traits>
|
|
#include <tcl.h>
|
|
#include "MinMax.hh"
|
|
#include "Transition.hh"
|
|
#include "Property.hh"
|
|
#include "ExceptionPath.hh"
|
|
#include "TimingRole.hh"
|
|
#include "Scene.hh"
|
|
#include "Sta.hh"
|
|
#include "Sdc.hh"
|
|
#include "ReportTcl.hh"
|
|
#include "RiseFallMinMax.hh"
|
|
#include "Variables.hh"
|
|
#include "LibertyClass.hh"
|
|
#include "Search.hh"
|
|
#include "Path.hh"
|
|
#include "PathGroup.hh"
|
|
#include "PathExpanded.hh"
|
|
#include "SearchPred.hh"
|
|
#include "SearchClass.hh"
|
|
#include "ClkNetwork.hh"
|
|
#include "VisitPathEnds.hh"
|
|
#include "search/CheckMinPulseWidths.hh"
|
|
#include "search/CheckMinPeriods.hh"
|
|
#include "search/CheckMaxSkews.hh"
|
|
#include "search/ClkSkew.hh"
|
|
#include "search/ClkInfo.hh"
|
|
#include "search/Tag.hh"
|
|
#include "search/PathEnum.hh"
|
|
#include "search/Genclks.hh"
|
|
#include "search/Levelize.hh"
|
|
#include "search/Sim.hh"
|
|
#include "Bfs.hh"
|
|
#include "search/WorstSlack.hh"
|
|
#include "search/ReportPath.hh"
|
|
#include "GraphDelayCalc.hh"
|
|
#include "Debug.hh"
|
|
#include "PowerClass.hh"
|
|
#include "search/CheckCapacitances.hh"
|
|
#include "search/CheckSlews.hh"
|
|
#include "search/CheckFanouts.hh"
|
|
#include "search/Crpr.hh"
|
|
#include "search/GatedClk.hh"
|
|
#include "search/ClkLatency.hh"
|
|
#include "search/FindRegister.hh"
|
|
#include "search/TagGroup.hh"
|
|
#include "search/MakeTimingModelPvt.hh"
|
|
#include "search/CheckTiming.hh"
|
|
#include "search/Latches.hh"
|
|
#include "Graph.hh"
|
|
#include "Liberty.hh"
|
|
#include "Network.hh"
|
|
|
|
namespace sta {
|
|
|
|
template <typename FnPtr>
|
|
static void expectCallablePointerUsable(FnPtr fn) {
|
|
ASSERT_NE(fn, nullptr);
|
|
EXPECT_TRUE((std::is_pointer_v<FnPtr> || std::is_member_function_pointer_v<FnPtr>));
|
|
EXPECT_TRUE(std::is_copy_constructible_v<FnPtr>);
|
|
EXPECT_TRUE(std::is_copy_assignable_v<FnPtr>);
|
|
FnPtr fn_copy = fn;
|
|
EXPECT_EQ(fn_copy, fn);
|
|
}
|
|
|
|
static void expectStaCoreState(Sta *sta);
|
|
|
|
class StaInitTest : public ::testing::Test {
|
|
protected:
|
|
void SetUp() override {
|
|
interp_ = Tcl_CreateInterp();
|
|
initSta();
|
|
sta_ = new Sta;
|
|
Sta::setSta(sta_);
|
|
sta_->makeComponents();
|
|
// Set the Tcl interp on the report so ReportTcl destructor works
|
|
ReportTcl *report = dynamic_cast<ReportTcl*>(sta_->report());
|
|
if (report)
|
|
report->setTclInterp(interp_);
|
|
}
|
|
|
|
void TearDown() override {
|
|
if (sta_)
|
|
expectStaCoreState(sta_);
|
|
deleteAllMemory();
|
|
sta_ = nullptr;
|
|
if (interp_)
|
|
Tcl_DeleteInterp(interp_);
|
|
interp_ = nullptr;
|
|
}
|
|
|
|
Sta *sta_;
|
|
Tcl_Interp *interp_;
|
|
};
|
|
|
|
static void expectStaCoreState(Sta *sta)
|
|
{
|
|
ASSERT_NE(sta, nullptr);
|
|
ASSERT_NE(sta->search(), nullptr);
|
|
ASSERT_NE(sta->cmdSdc(), nullptr);
|
|
ASSERT_NE(sta->reportPath(), nullptr);
|
|
ASSERT_FALSE(sta->scenes().empty());
|
|
EXPECT_GE(sta->scenes().size(), 1);
|
|
EXPECT_NE(sta->cmdScene(), nullptr);
|
|
}
|
|
|
|
// === Sta.cc: functions that call ensureLinked/ensureGraph (throw Exception) ===
|
|
|
|
// startpointPins() is declared but not defined - skipped
|
|
// TEST_F(StaInitTest, StaStartpointPinsThrows) {
|
|
// EXPECT_THROW(sta_->startpointPins(), Exception);
|
|
// }
|
|
|
|
TEST_F(StaInitTest, StaEndpointsThrows) {
|
|
EXPECT_THROW(sta_->endpoints(), Exception);
|
|
}
|
|
|
|
TEST_F(StaInitTest, StaEndpointPinsThrows) {
|
|
EXPECT_THROW(sta_->endpointPins(), Exception);
|
|
}
|
|
|
|
TEST_F(StaInitTest, StaGraphLoopsThrows) {
|
|
EXPECT_THROW(sta_->graphLoops(), Exception);
|
|
}
|
|
|
|
TEST_F(StaInitTest, StaVertexLevelThrows) {
|
|
EXPECT_THROW(sta_->vertexLevel(nullptr), Exception);
|
|
}
|
|
|
|
TEST_F(StaInitTest, StaFindLogicConstantsThrows2) {
|
|
EXPECT_THROW(sta_->findLogicConstants(), Exception);
|
|
}
|
|
|
|
TEST_F(StaInitTest, StaEnsureClkNetworkThrows) {
|
|
EXPECT_THROW(sta_->ensureClkNetwork(sta_->cmdMode()), Exception);
|
|
}
|
|
|
|
// findRegisterPreamble is protected, skip
|
|
|
|
// delayCalcPreamble is protected, skip
|
|
|
|
TEST_F(StaInitTest, StaFindDelaysThrows) {
|
|
EXPECT_THROW(sta_->findDelays(), Exception);
|
|
}
|
|
|
|
TEST_F(StaInitTest, StaFindRequiredsThrows) {
|
|
EXPECT_THROW(sta_->findRequireds(), Exception);
|
|
}
|
|
|
|
TEST_F(StaInitTest, StaEnsureLinkedThrows) {
|
|
EXPECT_THROW(sta_->ensureLinked(), Exception);
|
|
}
|
|
|
|
TEST_F(StaInitTest, StaEnsureGraphThrows) {
|
|
EXPECT_THROW(sta_->ensureGraph(), Exception);
|
|
}
|
|
|
|
TEST_F(StaInitTest, StaEnsureLevelizedThrows) {
|
|
EXPECT_THROW(sta_->ensureLevelized(), Exception);
|
|
}
|
|
|
|
// powerPreamble is protected, skip
|
|
|
|
// sdcChangedGraph is protected, skip
|
|
|
|
TEST_F(StaInitTest, StaFindFaninPinsThrows2) {
|
|
EXPECT_THROW(sta_->findFaninPins(static_cast<PinSeq*>(nullptr), false, false, 0, 0, false, false, sta_->cmdMode()), Exception);
|
|
}
|
|
|
|
TEST_F(StaInitTest, StaFindFanoutPinsThrows2) {
|
|
EXPECT_THROW(sta_->findFanoutPins(static_cast<PinSeq*>(nullptr), false, false, 0, 0, false, false, sta_->cmdMode()), Exception);
|
|
}
|
|
|
|
TEST_F(StaInitTest, StaMakePortPinThrows) {
|
|
EXPECT_THROW(sta_->makePortPin("test", nullptr), Exception);
|
|
}
|
|
|
|
TEST_F(StaInitTest, StaWriteSdcThrows2) {
|
|
EXPECT_THROW(sta_->writeSdc(sta_->cmdSdc(), "test.sdc", false, false, 4, false, false), Exception);
|
|
}
|
|
|
|
// === Sta.cc: SearchPreamble and related ===
|
|
|
|
TEST_F(StaInitTest, StaSearchPreamble2) {
|
|
// searchPreamble calls ensureClkArrivals which calls findDelays
|
|
// It will throw because ensureGraph is called
|
|
EXPECT_THROW(sta_->searchPreamble(), Exception);
|
|
}
|
|
|
|
TEST_F(StaInitTest, StaEnsureClkArrivals2) {
|
|
// calls findDelays which calls ensureGraph
|
|
EXPECT_THROW(sta_->ensureClkArrivals(), Exception);
|
|
}
|
|
|
|
TEST_F(StaInitTest, StaUpdateTiming2) {
|
|
// calls findDelays
|
|
EXPECT_THROW(sta_->updateTiming(false), Exception);
|
|
}
|
|
|
|
// === Sta.cc: Report header functions ===
|
|
|
|
TEST_F(StaInitTest, StaReportPathEndHeader2) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
|
|
}() ));
|
|
}
|
|
|
|
TEST_F(StaInitTest, StaReportPathEndFooter2) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
|
|
}() ));
|
|
}
|
|
|
|
// === Sta.cc: preamble functions ===
|
|
|
|
// minPulseWidthPreamble, minPeriodPreamble, maxSkewPreamble, clkSkewPreamble are protected, skip
|
|
|
|
// === Sta.cc: function pointer checks for methods needing network ===
|
|
|
|
// === Sta.cc: check/violation preambles ===
|
|
|
|
// === Sta.cc: Sta::setReportPathFields ===
|
|
|
|
TEST_F(StaInitTest, StaSetReportPathFields) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
sta_->setReportPathFields(true, true, true, true, true, true, true, true);
|
|
}() ));
|
|
}
|
|
|
|
// === Sta.cc: delete exception helpers ===
|
|
|
|
TEST_F(StaInitTest, StaDeleteExceptionFrom) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
sta_->deleteExceptionFrom(nullptr);
|
|
}() ));
|
|
}
|
|
|
|
TEST_F(StaInitTest, StaDeleteExceptionThru) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
sta_->deleteExceptionThru(nullptr);
|
|
}() ));
|
|
}
|
|
|
|
TEST_F(StaInitTest, StaDeleteExceptionTo) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
sta_->deleteExceptionTo(nullptr);
|
|
}() ));
|
|
}
|
|
|
|
// === Sta.cc: readNetlistBefore ===
|
|
|
|
TEST_F(StaInitTest, StaReadNetlistBefore) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
sta_->readNetlistBefore();
|
|
}() ));
|
|
}
|
|
|
|
// === Sta.cc: endpointViolationCount ===
|
|
|
|
// === Sta.cc: operatingConditions ===
|
|
|
|
TEST_F(StaInitTest, StaOperatingConditions2) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
sta_->operatingConditions(MinMax::max(), sta_->cmdSdc());
|
|
}() ));
|
|
}
|
|
|
|
// === Sta.cc: removeConstraints ===
|
|
|
|
// === Sta.cc: disabledEdgesSorted (calls ensureLevelized internally) ===
|
|
|
|
TEST_F(StaInitTest, StaDisabledEdgesSortedThrows) {
|
|
EXPECT_THROW(sta_->disabledEdgesSorted(sta_->cmdMode()), Exception);
|
|
}
|
|
|
|
// === Sta.cc: disabledEdges (calls ensureLevelized) ===
|
|
|
|
TEST_F(StaInitTest, StaDisabledEdgesThrows) {
|
|
EXPECT_THROW(sta_->disabledEdges(sta_->cmdMode()), Exception);
|
|
}
|
|
|
|
// === Sta.cc: findReportPathField ===
|
|
|
|
TEST_F(StaInitTest, StaFindReportPathField) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
sta_->findReportPathField("delay");
|
|
}() ));
|
|
}
|
|
|
|
// === Sta.cc: findCorner ===
|
|
|
|
TEST_F(StaInitTest, StaFindCornerByName) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
auto corner = sta_->findScene("default");
|
|
// May or may not exist
|
|
EXPECT_NE(corner, nullptr);
|
|
}() ));
|
|
}
|
|
|
|
// === Sta.cc: totalNegativeSlack ===
|
|
|
|
TEST_F(StaInitTest, StaTotalNegativeSlackThrows) {
|
|
EXPECT_THROW(sta_->totalNegativeSlack(MinMax::max()), Exception);
|
|
}
|
|
|
|
// === Sta.cc: worstSlack ===
|
|
|
|
TEST_F(StaInitTest, StaWorstSlackThrows) {
|
|
EXPECT_THROW(sta_->worstSlack(MinMax::max()), Exception);
|
|
}
|
|
|
|
// === Sta.cc: setArcDelayCalc ===
|
|
|
|
TEST_F(StaInitTest, StaSetArcDelayCalc) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
sta_->setArcDelayCalc("unit");
|
|
}() ));
|
|
}
|
|
|
|
// === Sta.cc: setAnalysisType ===
|
|
|
|
TEST_F(StaInitTest, StaSetAnalysisType) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
sta_->setAnalysisType(AnalysisType::ocv, sta_->cmdSdc());
|
|
}() ));
|
|
}
|
|
|
|
// === Sta.cc: setTimingDerate (global) ===
|
|
|
|
TEST_F(StaInitTest, StaSetTimingDerate) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
sta_->setTimingDerate(TimingDerateType::cell_delay, PathClkOrData::clk,
|
|
RiseFallBoth::riseFall(), MinMax::max(), 1.05f,
|
|
sta_->cmdSdc());
|
|
}() ));
|
|
}
|
|
|
|
// === Sta.cc: setVoltage ===
|
|
|
|
TEST_F(StaInitTest, StaSetVoltage) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
sta_->setVoltage(MinMax::max(), 1.0f, sta_->cmdSdc());
|
|
}() ));
|
|
}
|
|
|
|
// === Sta.cc: setReportPathFieldOrder segfaults on null, use method exists ===
|
|
|
|
// === Sta.cc: clear ===
|
|
|
|
// === Property.cc: defineProperty overloads ===
|
|
|
|
TEST_F(StaInitTest, PropertiesDefineLibrary) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
Properties props(sta_);
|
|
std::string prop_name("test_lib_prop");
|
|
props.defineProperty(prop_name,
|
|
PropertyRegistry<const Library*>::PropertyHandler(
|
|
[](const Library*, Sta*) -> PropertyValue { return PropertyValue(); }));
|
|
}() ));
|
|
}
|
|
|
|
TEST_F(StaInitTest, PropertiesDefineLibertyLibrary) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
Properties props(sta_);
|
|
std::string prop_name("test_liblib_prop");
|
|
props.defineProperty(prop_name,
|
|
PropertyRegistry<const LibertyLibrary*>::PropertyHandler(
|
|
[](const LibertyLibrary*, Sta*) -> PropertyValue { return PropertyValue(); }));
|
|
}() ));
|
|
}
|
|
|
|
TEST_F(StaInitTest, PropertiesDefineCell) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
Properties props(sta_);
|
|
std::string prop_name("test_cell_prop");
|
|
props.defineProperty(prop_name,
|
|
PropertyRegistry<const Cell*>::PropertyHandler(
|
|
[](const Cell*, Sta*) -> PropertyValue { return PropertyValue(); }));
|
|
}() ));
|
|
}
|
|
|
|
TEST_F(StaInitTest, PropertiesDefineLibertyCell) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
Properties props(sta_);
|
|
std::string prop_name("test_libcell_prop");
|
|
props.defineProperty(prop_name,
|
|
PropertyRegistry<const LibertyCell*>::PropertyHandler(
|
|
[](const LibertyCell*, Sta*) -> PropertyValue { return PropertyValue(); }));
|
|
}() ));
|
|
}
|
|
|
|
TEST_F(StaInitTest, PropertiesDefinePort) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
Properties props(sta_);
|
|
std::string prop_name("test_port_prop");
|
|
props.defineProperty(prop_name,
|
|
PropertyRegistry<const Port*>::PropertyHandler(
|
|
[](const Port*, Sta*) -> PropertyValue { return PropertyValue(); }));
|
|
}() ));
|
|
}
|
|
|
|
TEST_F(StaInitTest, PropertiesDefineLibertyPort) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
Properties props(sta_);
|
|
std::string prop_name("test_libport_prop");
|
|
props.defineProperty(prop_name,
|
|
PropertyRegistry<const LibertyPort*>::PropertyHandler(
|
|
[](const LibertyPort*, Sta*) -> PropertyValue { return PropertyValue(); }));
|
|
}() ));
|
|
}
|
|
|
|
TEST_F(StaInitTest, PropertiesDefineInstance) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
Properties props(sta_);
|
|
std::string prop_name("test_inst_prop");
|
|
props.defineProperty(prop_name,
|
|
PropertyRegistry<const Instance*>::PropertyHandler(
|
|
[](const Instance*, Sta*) -> PropertyValue { return PropertyValue(); }));
|
|
}() ));
|
|
}
|
|
|
|
TEST_F(StaInitTest, PropertiesDefinePin) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
Properties props(sta_);
|
|
std::string prop_name("test_pin_prop");
|
|
props.defineProperty(prop_name,
|
|
PropertyRegistry<const Pin*>::PropertyHandler(
|
|
[](const Pin*, Sta*) -> PropertyValue { return PropertyValue(); }));
|
|
}() ));
|
|
}
|
|
|
|
TEST_F(StaInitTest, PropertiesDefineNet) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
Properties props(sta_);
|
|
std::string prop_name("test_net_prop");
|
|
props.defineProperty(prop_name,
|
|
PropertyRegistry<const Net*>::PropertyHandler(
|
|
[](const Net*, Sta*) -> PropertyValue { return PropertyValue(); }));
|
|
}() ));
|
|
}
|
|
|
|
TEST_F(StaInitTest, PropertiesDefineClock) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
Properties props(sta_);
|
|
std::string prop_name("test_clk_prop");
|
|
props.defineProperty(prop_name,
|
|
PropertyRegistry<const Clock*>::PropertyHandler(
|
|
[](const Clock*, Sta*) -> PropertyValue { return PropertyValue(); }));
|
|
}() ));
|
|
}
|
|
|
|
// === Search.cc: RequiredCmp ===
|
|
|
|
TEST_F(StaInitTest, RequiredCmpConstruct) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
RequiredCmp cmp;
|
|
}() ));
|
|
}
|
|
|
|
// === Search.cc: EvalPred constructor ===
|
|
|
|
TEST_F(StaInitTest, EvalPredConstruct) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
EvalPred pred(sta_);
|
|
}() ));
|
|
}
|
|
|
|
// === Search.cc: ClkArrivalSearchPred ===
|
|
|
|
// === Search.cc: Search accessors ===
|
|
|
|
TEST_F(StaInitTest, SearchTagCount2) {
|
|
Search *search = sta_->search();
|
|
ASSERT_NE(search, nullptr);
|
|
int tc = search->tagCount();
|
|
EXPECT_GE(tc, 0);
|
|
}
|
|
|
|
TEST_F(StaInitTest, SearchTagGroupCount2) {
|
|
Search *search = sta_->search();
|
|
ASSERT_NE(search, nullptr);
|
|
int tgc = search->tagGroupCount();
|
|
EXPECT_GE(tgc, 0);
|
|
}
|
|
|
|
TEST_F(StaInitTest, SearchClkInfoCount2) {
|
|
Search *search = sta_->search();
|
|
ASSERT_NE(search, nullptr);
|
|
int cnt = search->clkInfoCount();
|
|
EXPECT_GE(cnt, 0);
|
|
}
|
|
|
|
TEST_F(StaInitTest, SearchArrivalsInvalid2) {
|
|
Search *search = sta_->search();
|
|
ASSERT_NE(search, nullptr);
|
|
search->arrivalsInvalid();
|
|
}
|
|
|
|
TEST_F(StaInitTest, SearchRequiredsInvalid2) {
|
|
Search *search = sta_->search();
|
|
ASSERT_NE(search, nullptr);
|
|
search->requiredsInvalid();
|
|
}
|
|
|
|
TEST_F(StaInitTest, SearchEndpointsInvalid2) {
|
|
Search *search = sta_->search();
|
|
ASSERT_NE(search, nullptr);
|
|
search->endpointsInvalid();
|
|
}
|
|
|
|
TEST_F(StaInitTest, SearchClear2) {
|
|
Search *search = sta_->search();
|
|
ASSERT_NE(search, nullptr);
|
|
search->clear();
|
|
}
|
|
|
|
TEST_F(StaInitTest, SearchCrprPathPruningEnabled) {
|
|
Search *search = sta_->search();
|
|
ASSERT_NE(search, nullptr);
|
|
(void)search->crprPathPruningEnabled();
|
|
}
|
|
|
|
TEST_F(StaInitTest, SearchCrprApproxMissingRequireds) {
|
|
Search *search = sta_->search();
|
|
ASSERT_NE(search, nullptr);
|
|
(void)search->crprApproxMissingRequireds();
|
|
}
|
|
|
|
TEST_F(StaInitTest, SearchSetCrprpathPruningEnabled) {
|
|
Search *search = sta_->search();
|
|
ASSERT_NE(search, nullptr);
|
|
search->setCrprpathPruningEnabled(true);
|
|
EXPECT_TRUE(search->crprPathPruningEnabled());
|
|
search->setCrprpathPruningEnabled(false);
|
|
}
|
|
|
|
TEST_F(StaInitTest, SearchSetCrprApproxMissingRequireds) {
|
|
Search *search = sta_->search();
|
|
ASSERT_NE(search, nullptr);
|
|
search->setCrprApproxMissingRequireds(true);
|
|
EXPECT_TRUE(search->crprApproxMissingRequireds());
|
|
search->setCrprApproxMissingRequireds(false);
|
|
}
|
|
|
|
TEST_F(StaInitTest, SearchDeletePathGroups2) {
|
|
Search *search = sta_->search();
|
|
ASSERT_NE(search, nullptr);
|
|
search->deletePathGroups();
|
|
}
|
|
|
|
// === PathEnd.cc: more PathEndUnconstrained methods ===
|
|
|
|
TEST_F(StaInitTest, PathEndUnconstrainedCheckRole) {
|
|
Path *p = new Path();
|
|
PathEndUnconstrained pe(p);
|
|
const TimingRole *role = pe.checkRole(sta_);
|
|
EXPECT_EQ(role, nullptr);
|
|
}
|
|
|
|
TEST_F(StaInitTest, PathEndUnconstrainedTypeName) {
|
|
Path *p = new Path();
|
|
PathEndUnconstrained pe(p);
|
|
const char *name = pe.typeName();
|
|
EXPECT_STREQ(name, "unconstrained");
|
|
}
|
|
|
|
TEST_F(StaInitTest, PathEndUnconstrainedType) {
|
|
Path *p = new Path();
|
|
PathEndUnconstrained pe(p);
|
|
EXPECT_EQ(pe.type(), PathEnd::Type::unconstrained);
|
|
}
|
|
|
|
TEST_F(StaInitTest, PathEndUnconstrainedIsUnconstrained) {
|
|
Path *p = new Path();
|
|
PathEndUnconstrained pe(p);
|
|
EXPECT_TRUE(pe.isUnconstrained());
|
|
}
|
|
|
|
TEST_F(StaInitTest, PathEndUnconstrainedIsCheck) {
|
|
Path *p = new Path();
|
|
PathEndUnconstrained pe(p);
|
|
EXPECT_FALSE(pe.isCheck());
|
|
}
|
|
|
|
TEST_F(StaInitTest, PathEndUnconstrainedIsLatchCheck) {
|
|
Path *p = new Path();
|
|
PathEndUnconstrained pe(p);
|
|
EXPECT_FALSE(pe.isLatchCheck());
|
|
}
|
|
|
|
TEST_F(StaInitTest, PathEndUnconstrainedIsOutputDelay) {
|
|
Path *p = new Path();
|
|
PathEndUnconstrained pe(p);
|
|
EXPECT_FALSE(pe.isOutputDelay());
|
|
}
|
|
|
|
TEST_F(StaInitTest, PathEndUnconstrainedIsGatedClock) {
|
|
Path *p = new Path();
|
|
PathEndUnconstrained pe(p);
|
|
EXPECT_FALSE(pe.isGatedClock());
|
|
}
|
|
|
|
TEST_F(StaInitTest, PathEndUnconstrainedIsPathDelay) {
|
|
Path *p = new Path();
|
|
PathEndUnconstrained pe(p);
|
|
EXPECT_FALSE(pe.isPathDelay());
|
|
}
|
|
|
|
TEST_F(StaInitTest, PathEndUnconstrainedTargetClkEdge) {
|
|
Path *p = new Path();
|
|
PathEndUnconstrained pe(p);
|
|
EXPECT_EQ(pe.targetClkEdge(sta_), nullptr);
|
|
}
|
|
|
|
TEST_F(StaInitTest, PathEndUnconstrainedTargetClkTime) {
|
|
Path *p = new Path();
|
|
PathEndUnconstrained pe(p);
|
|
EXPECT_FLOAT_EQ(pe.targetClkTime(sta_), 0.0f);
|
|
}
|
|
|
|
TEST_F(StaInitTest, PathEndUnconstrainedTargetClkOffset) {
|
|
Path *p = new Path();
|
|
PathEndUnconstrained pe(p);
|
|
EXPECT_FLOAT_EQ(pe.targetClkOffset(sta_), 0.0f);
|
|
}
|
|
|
|
TEST_F(StaInitTest, PathEndUnconstrainedSourceClkOffset) {
|
|
Path *p = new Path();
|
|
PathEndUnconstrained pe(p);
|
|
EXPECT_FLOAT_EQ(pe.sourceClkOffset(sta_), 0.0f);
|
|
}
|
|
|
|
TEST_F(StaInitTest, PathEndUnconstrainedCopy) {
|
|
Path *p = new Path();
|
|
PathEndUnconstrained pe(p);
|
|
PathEnd *copy = pe.copy();
|
|
EXPECT_NE(copy, nullptr);
|
|
EXPECT_EQ(copy->type(), PathEnd::Type::unconstrained);
|
|
delete copy;
|
|
}
|
|
|
|
TEST_F(StaInitTest, PathEndUnconstrainedExceptPathCmp) {
|
|
Path *p1 = new Path();
|
|
Path *p2 = new Path();
|
|
PathEndUnconstrained pe1(p1);
|
|
PathEndUnconstrained pe2(p2);
|
|
int cmp = pe1.exceptPathCmp(&pe2, sta_);
|
|
EXPECT_EQ(cmp, 0);
|
|
}
|
|
|
|
// === PathEnd.cc: PathEndCheck constructor/type ===
|
|
|
|
TEST_F(StaInitTest, PathEndCheckConstruct2) {
|
|
Path *p = new Path();
|
|
Path *clk = new Path();
|
|
PathEndCheck pe(p, nullptr, nullptr, clk, nullptr, sta_);
|
|
EXPECT_EQ(pe.type(), PathEnd::Type::check);
|
|
EXPECT_TRUE(pe.isCheck());
|
|
EXPECT_FALSE(pe.isLatchCheck());
|
|
EXPECT_STREQ(pe.typeName(), "check");
|
|
}
|
|
|
|
TEST_F(StaInitTest, PathEndCheckGetters) {
|
|
Path *p = new Path();
|
|
Path *clk = new Path();
|
|
PathEndCheck pe(p, nullptr, nullptr, clk, nullptr, sta_);
|
|
EXPECT_EQ(pe.checkArc(), nullptr);
|
|
EXPECT_EQ(pe.multiCyclePath(), nullptr);
|
|
}
|
|
|
|
TEST_F(StaInitTest, PathEndCheckCopy) {
|
|
Path *p = new Path();
|
|
Path *clk = new Path();
|
|
PathEndCheck pe(p, nullptr, nullptr, clk, nullptr, sta_);
|
|
PathEnd *copy = pe.copy();
|
|
EXPECT_NE(copy, nullptr);
|
|
EXPECT_EQ(copy->type(), PathEnd::Type::check);
|
|
delete copy;
|
|
}
|
|
|
|
// === PathEnd.cc: PathEndLatchCheck constructor/type ===
|
|
|
|
// === PathEnd.cc: PathEndPathDelay constructor/type ===
|
|
|
|
// === PathEnd.cc: PathEnd comparison statics ===
|
|
|
|
// === Bfs.cc: BfsFwdIterator/BfsBkwdIterator ===
|
|
|
|
TEST_F(StaInitTest, BfsFwdIteratorConstruct) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
BfsFwdIterator iter(BfsIndex::other, nullptr, sta_);
|
|
iter.hasNext();
|
|
}() ));
|
|
}
|
|
|
|
TEST_F(StaInitTest, BfsBkwdIteratorConstruct) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
BfsBkwdIterator iter(BfsIndex::other, nullptr, sta_);
|
|
iter.hasNext();
|
|
}() ));
|
|
}
|
|
|
|
// === ClkNetwork.cc: ClkNetwork accessors ===
|
|
|
|
// === Corner.cc: Corner accessors ===
|
|
|
|
TEST_F(StaInitTest, CornerAccessors) {
|
|
Scene *corner = sta_->cmdScene();
|
|
ASSERT_NE(corner, nullptr);
|
|
int idx = corner->index();
|
|
EXPECT_GE(idx, 0);
|
|
const std::string &name = corner->name();
|
|
EXPECT_FALSE(name.empty());
|
|
}
|
|
|
|
// === WorstSlack.cc: function exists ===
|
|
|
|
// === PathGroup.cc: PathGroup name constants ===
|
|
|
|
// === CheckTiming.cc: checkTiming ===
|
|
|
|
TEST_F(StaInitTest, StaCheckTimingThrows2) {
|
|
EXPECT_THROW(sta_->checkTiming(sta_->cmdMode(), true, true, true, true, true, true, true), Exception);
|
|
}
|
|
|
|
// === PathExpanded.cc: PathExpanded on empty path ===
|
|
|
|
// === PathEnum.cc: function exists ===
|
|
|
|
// === Genclks.cc: Genclks exists ===
|
|
|
|
TEST_F(StaInitTest, GenclksExists2) {
|
|
auto fn = &Genclks::clear;
|
|
expectCallablePointerUsable(fn);
|
|
}
|
|
|
|
// === MakeTimingModel.cc: function exists ===
|
|
|
|
TEST_F(StaInitTest, StaWriteTimingModelThrows) {
|
|
EXPECT_THROW(sta_->writeTimingModel("out.lib", "model", "cell", nullptr), Exception);
|
|
}
|
|
|
|
// === Tag.cc: Tag function exists ===
|
|
|
|
// === StaState.cc: StaState units ===
|
|
|
|
TEST_F(StaInitTest, StaStateReport) {
|
|
Report *rpt = sta_->report();
|
|
EXPECT_NE(rpt, nullptr);
|
|
}
|
|
|
|
// === ClkSkew.cc: function exists ===
|
|
|
|
// === ClkLatency.cc: function exists ===
|
|
|
|
// === ClkInfo.cc: accessors ===
|
|
|
|
// === Crpr.cc: function exists ===
|
|
|
|
// === FindRegister.cc: findRegister functions ===
|
|
|
|
TEST_F(StaInitTest, StaFindRegisterInstancesThrows2) {
|
|
EXPECT_THROW(sta_->findRegisterInstances(nullptr, RiseFallBoth::riseFall(), false, false, sta_->cmdMode()), Exception);
|
|
}
|
|
|
|
TEST_F(StaInitTest, StaFindRegisterClkPinsThrows2) {
|
|
EXPECT_THROW(sta_->findRegisterClkPins(nullptr, RiseFallBoth::riseFall(), false, false, sta_->cmdMode()), Exception);
|
|
}
|
|
|
|
TEST_F(StaInitTest, StaFindRegisterDataPinsThrows2) {
|
|
EXPECT_THROW(sta_->findRegisterDataPins(nullptr, RiseFallBoth::riseFall(), false, false, sta_->cmdMode()), Exception);
|
|
}
|
|
|
|
TEST_F(StaInitTest, StaFindRegisterOutputPinsThrows2) {
|
|
EXPECT_THROW(sta_->findRegisterOutputPins(nullptr, RiseFallBoth::riseFall(), false, false, sta_->cmdMode()), Exception);
|
|
}
|
|
|
|
TEST_F(StaInitTest, StaFindRegisterAsyncPinsThrows2) {
|
|
EXPECT_THROW(sta_->findRegisterAsyncPins(nullptr, RiseFallBoth::riseFall(), false, false, sta_->cmdMode()), Exception);
|
|
}
|
|
|
|
// === Sta.cc: Sta::setCurrentInstance ===
|
|
|
|
TEST_F(StaInitTest, StaSetCurrentInstanceNull) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
sta_->setCurrentInstance(nullptr);
|
|
}() ));
|
|
}
|
|
|
|
// === Sta.cc: Sta::pathGroupNames ===
|
|
|
|
TEST_F(StaInitTest, StaPathGroupNames) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
sta_->pathGroupNames(sta_->cmdSdc());
|
|
}() ));
|
|
}
|
|
|
|
// === Sta.cc: Sta::isPathGroupName ===
|
|
|
|
TEST_F(StaInitTest, StaIsPathGroupName) {
|
|
bool val = sta_->isPathGroupName("nonexistent", sta_->cmdSdc());
|
|
EXPECT_FALSE(val);
|
|
}
|
|
|
|
// === Sta.cc: Sta::removeClockGroupsLogicallyExclusive etc ===
|
|
|
|
TEST_F(StaInitTest, StaRemoveClockGroupsLogicallyExclusive2) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
sta_->removeClockGroupsLogicallyExclusive("test", sta_->cmdSdc());
|
|
}() ));
|
|
}
|
|
|
|
TEST_F(StaInitTest, StaRemoveClockGroupsPhysicallyExclusive2) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
sta_->removeClockGroupsPhysicallyExclusive("test", sta_->cmdSdc());
|
|
}() ));
|
|
}
|
|
|
|
TEST_F(StaInitTest, StaRemoveClockGroupsAsynchronous2) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
sta_->removeClockGroupsAsynchronous("test", sta_->cmdSdc());
|
|
}() ));
|
|
}
|
|
|
|
// === Sta.cc: Sta::setDebugLevel ===
|
|
|
|
TEST_F(StaInitTest, StaSetDebugLevel) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
sta_->setDebugLevel("search", 0);
|
|
}() ));
|
|
}
|
|
|
|
// === Sta.cc: Sta::slowDrivers ===
|
|
|
|
// === Sta.cc: Sta::setMinPulseWidth ===
|
|
|
|
TEST_F(StaInitTest, StaSetMinPulseWidth) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
sta_->setMinPulseWidth(RiseFallBoth::riseFall(), 0.1f, sta_->cmdSdc());
|
|
}() ));
|
|
}
|
|
|
|
// === Sta.cc: various set* functions that delegate to Sdc ===
|
|
|
|
TEST_F(StaInitTest, StaSetClockGatingCheckGlobal2) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
sta_->setClockGatingCheck(RiseFallBoth::riseFall(), MinMax::max(), 0.1f, sta_->cmdSdc());
|
|
}() ));
|
|
}
|
|
|
|
// === Sta.cc: Sta::makeExceptionFrom/Thru/To ===
|
|
|
|
TEST_F(StaInitTest, StaMakeExceptionFrom2) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
ExceptionFrom *from = sta_->makeExceptionFrom(nullptr, nullptr, nullptr,
|
|
RiseFallBoth::riseFall(), sta_->cmdSdc());
|
|
// Returns a valid ExceptionFrom even with null args
|
|
if (from) sta_->deleteExceptionFrom(from);
|
|
}() ));
|
|
}
|
|
|
|
TEST_F(StaInitTest, StaMakeExceptionThru2) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
ExceptionThru *thru = sta_->makeExceptionThru(nullptr, nullptr, nullptr,
|
|
RiseFallBoth::riseFall(),
|
|
sta_->cmdSdc());
|
|
if (thru) sta_->deleteExceptionThru(thru);
|
|
}() ));
|
|
}
|
|
|
|
TEST_F(StaInitTest, StaMakeExceptionTo2) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
ExceptionTo *to = sta_->makeExceptionTo(nullptr, nullptr, nullptr,
|
|
RiseFallBoth::riseFall(),
|
|
RiseFallBoth::riseFall(), sta_->cmdSdc());
|
|
if (to) sta_->deleteExceptionTo(to);
|
|
}() ));
|
|
}
|
|
|
|
// === Sta.cc: Sta::setLatchBorrowLimit ===
|
|
|
|
// === Sta.cc: Sta::setDriveResistance ===
|
|
|
|
// === Sta.cc: Sta::setInputSlew ===
|
|
|
|
// === Sta.cc: Sta::setResistance ===
|
|
|
|
// === Sta.cc: Sta::setNetWireCap ===
|
|
|
|
// === Sta.cc: Sta::connectedCap ===
|
|
|
|
// === Sta.cc: Sta::portExtCaps ===
|
|
|
|
// === Sta.cc: Sta::setOperatingConditions ===
|
|
|
|
TEST_F(StaInitTest, StaSetOperatingConditions2) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
sta_->setOperatingConditions(nullptr, MinMaxAll::all(), sta_->cmdSdc());
|
|
}() ));
|
|
}
|
|
|
|
// === Sta.cc: Sta::power ===
|
|
|
|
// === Sta.cc: Sta::readLiberty ===
|
|
|
|
// === Sta.cc: linkDesign ===
|
|
|
|
// === Sta.cc: Sta::readVerilog ===
|
|
|
|
// === Sta.cc: Sta::readSpef ===
|
|
|
|
// === Sta.cc: initSta and deleteAllMemory ===
|
|
|
|
TEST_F(StaInitTest, InitStaExists) {
|
|
auto fn = &initSta;
|
|
expectCallablePointerUsable(fn);
|
|
}
|
|
|
|
TEST_F(StaInitTest, DeleteAllMemoryExists) {
|
|
auto fn = &deleteAllMemory;
|
|
expectCallablePointerUsable(fn);
|
|
}
|
|
|
|
// === PathEnd.cc: slack computation on PathEndUnconstrained ===
|
|
|
|
TEST_F(StaInitTest, PathEndSlack) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
Path *p = new Path();
|
|
PathEndUnconstrained pe(p);
|
|
pe.slack(sta_);
|
|
}() ));
|
|
}
|
|
|
|
// === Sta.cc: Sta method exists checks for vertex* functions ===
|
|
|
|
// === Sta.cc: reporting function exists ===
|
|
|
|
// === Sta.cc: Sta::makeClockGroups ===
|
|
|
|
TEST_F(StaInitTest, StaMakeClockGroups) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
sta_->makeClockGroups("test_grp", false, false, false, false, nullptr, sta_->cmdSdc());
|
|
}() ));
|
|
}
|
|
|
|
// === Sta.cc: Sta::makeGroupPath ===
|
|
|
|
// ============================================================
|
|
// R5_ tests: Additional function coverage for search module
|
|
// ============================================================
|
|
|
|
// === CheckMaxSkews: constructor/destructor/clear ===
|
|
|
|
TEST_F(StaInitTest, CheckMaxSkewsCtorDtorClear) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
CheckMaxSkews checker(sta_);
|
|
checker.clear();
|
|
}() ));
|
|
}
|
|
|
|
// === CheckMinPeriods: constructor/destructor/clear ===
|
|
|
|
TEST_F(StaInitTest, CheckMinPeriodsCtorDtorClear) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
CheckMinPeriods checker(sta_);
|
|
checker.clear();
|
|
}() ));
|
|
}
|
|
|
|
// === CheckMinPulseWidths: constructor/destructor/clear ===
|
|
|
|
TEST_F(StaInitTest, CheckMinPulseWidthsCtorDtorClear) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
CheckMinPulseWidths checker(sta_);
|
|
checker.clear();
|
|
}() ));
|
|
}
|
|
|
|
// === MinPulseWidthCheck: default constructor ===
|
|
|
|
TEST_F(StaInitTest, MinPulseWidthCheckDefaultCtor) {
|
|
MinPulseWidthCheck check;
|
|
EXPECT_EQ(check.openPath(), nullptr);
|
|
}
|
|
|
|
// === MinPulseWidthCheck: constructor with nullptr ===
|
|
|
|
TEST_F(StaInitTest, MinPulseWidthCheckNullptrCtor) {
|
|
MinPulseWidthCheck check(nullptr);
|
|
EXPECT_EQ(check.openPath(), nullptr);
|
|
}
|
|
|
|
// === MinPeriodCheck: constructor ===
|
|
|
|
TEST_F(StaInitTest, MinPeriodCheckCtor) {
|
|
MinPeriodCheck check;
|
|
EXPECT_EQ(check.pin(), nullptr);
|
|
EXPECT_EQ(check.clk(), nullptr);
|
|
}
|
|
|
|
// === MinPeriodCheck: copy ===
|
|
|
|
// === MaxSkewSlackLess: constructor ===
|
|
|
|
TEST_F(StaInitTest, MaxSkewSlackLessCtor) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
MaxSkewSlackLess less(sta_);
|
|
}() ));
|
|
}
|
|
|
|
// === MinPeriodSlackLess: constructor ===
|
|
|
|
TEST_F(StaInitTest, MinPeriodSlackLessCtor) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
MinPeriodSlackLess less(sta_);
|
|
}() ));
|
|
}
|
|
|
|
// === MinPulseWidthSlackLess: constructor ===
|
|
|
|
TEST_F(StaInitTest, MinPulseWidthSlackLessCtor) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
MinPulseWidthSlackLess less(sta_);
|
|
}() ));
|
|
}
|
|
|
|
// === Path: default constructor and isNull ===
|
|
|
|
TEST_F(StaInitTest, PathDefaultCtorIsNull) {
|
|
Path path;
|
|
EXPECT_TRUE(path.isNull());
|
|
}
|
|
|
|
// === Path: copy from null pointer ===
|
|
|
|
TEST_F(StaInitTest, PathCopyFromNull) {
|
|
Path path(static_cast<const Path *>(nullptr));
|
|
EXPECT_TRUE(path.isNull());
|
|
}
|
|
|
|
// === Path: arrival/required getters on default path ===
|
|
|
|
TEST_F(StaInitTest, PathArrivalRequired) {
|
|
Path path;
|
|
path.setArrival(1.5f);
|
|
EXPECT_FLOAT_EQ(path.arrival(), 1.5f);
|
|
path.setRequired(2.5f);
|
|
EXPECT_FLOAT_EQ(path.required(), 2.5f);
|
|
}
|
|
|
|
// === Path: isEnum ===
|
|
|
|
TEST_F(StaInitTest, PathIsEnum2) {
|
|
Path path;
|
|
EXPECT_FALSE(path.isEnum());
|
|
path.setIsEnum(true);
|
|
EXPECT_TRUE(path.isEnum());
|
|
path.setIsEnum(false);
|
|
EXPECT_FALSE(path.isEnum());
|
|
}
|
|
|
|
// === Path: prevPath on default ===
|
|
|
|
TEST_F(StaInitTest, PathPrevPathDefault) {
|
|
Path path;
|
|
EXPECT_EQ(path.prevPath(), nullptr);
|
|
}
|
|
|
|
// === Path: setPrevPath ===
|
|
|
|
TEST_F(StaInitTest, PathSetPrevPath2) {
|
|
Path path;
|
|
Path prev;
|
|
path.setPrevPath(&prev);
|
|
EXPECT_EQ(path.prevPath(), &prev);
|
|
path.setPrevPath(nullptr);
|
|
EXPECT_EQ(path.prevPath(), nullptr);
|
|
}
|
|
|
|
// === PathLess: constructor ===
|
|
|
|
TEST_F(StaInitTest, PathLessCtor) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
PathLess less(sta_);
|
|
}() ));
|
|
}
|
|
|
|
// === ClkSkew: default constructor ===
|
|
|
|
TEST_F(StaInitTest, ClkSkewDefaultCtor) {
|
|
ClkSkew skew;
|
|
EXPECT_EQ(skew.srcPath(), nullptr);
|
|
EXPECT_EQ(skew.tgtPath(), nullptr);
|
|
EXPECT_FLOAT_EQ(skew.skew(), 0.0f);
|
|
}
|
|
|
|
// === ClkSkew: copy constructor ===
|
|
|
|
TEST_F(StaInitTest, ClkSkewCopyCtor) {
|
|
ClkSkew skew1;
|
|
ClkSkew skew2(skew1);
|
|
EXPECT_EQ(skew2.srcPath(), nullptr);
|
|
EXPECT_EQ(skew2.tgtPath(), nullptr);
|
|
EXPECT_FLOAT_EQ(skew2.skew(), 0.0f);
|
|
}
|
|
|
|
// === ClkSkew: assignment operator ===
|
|
|
|
TEST_F(StaInitTest, ClkSkewAssignment2) {
|
|
ClkSkew skew1;
|
|
ClkSkew skew2;
|
|
skew2 = skew1;
|
|
EXPECT_EQ(skew2.srcPath(), nullptr);
|
|
EXPECT_FLOAT_EQ(skew2.skew(), 0.0f);
|
|
}
|
|
|
|
// (Protected ReportPath methods removed - only public API tested)
|
|
|
|
// === ClkInfoLess: constructor ===
|
|
|
|
TEST_F(StaInitTest, ClkInfoLessCtor) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
ClkInfoLess less(sta_);
|
|
}() ));
|
|
}
|
|
|
|
// === ClkInfoEqual: constructor ===
|
|
|
|
TEST_F(StaInitTest, ClkInfoEqualCtor) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
ClkInfoEqual eq(sta_);
|
|
}() ));
|
|
}
|
|
|
|
// === ClkInfoHash: operator() with nullptr safety check ===
|
|
|
|
TEST_F(StaInitTest, ClkInfoHashExists) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
ClkInfoHash hash;
|
|
}() ));
|
|
}
|
|
|
|
// === TagLess: constructor ===
|
|
|
|
TEST_F(StaInitTest, TagLessCtor) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
TagLess less(sta_);
|
|
}() ));
|
|
}
|
|
|
|
// === TagIndexLess: existence ===
|
|
|
|
TEST_F(StaInitTest, TagIndexLessExists) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
TagIndexLess less;
|
|
}() ));
|
|
}
|
|
|
|
// === TagHash: constructor ===
|
|
|
|
TEST_F(StaInitTest, TagHashCtor) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
TagHash hash(sta_);
|
|
}() ));
|
|
}
|
|
|
|
// === TagEqual: constructor ===
|
|
|
|
TEST_F(StaInitTest, TagEqualCtor) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
TagEqual eq(sta_);
|
|
}() ));
|
|
}
|
|
|
|
// === TagMatchLess: constructor ===
|
|
|
|
TEST_F(StaInitTest, TagMatchLessCtor) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
TagMatchLess less(true, sta_);
|
|
TagMatchLess less2(false, sta_);
|
|
}() ));
|
|
}
|
|
|
|
// === TagMatchHash: constructor ===
|
|
|
|
TEST_F(StaInitTest, TagMatchHashCtor) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
TagMatchHash hash(true, sta_);
|
|
TagMatchHash hash2(false, sta_);
|
|
}() ));
|
|
}
|
|
|
|
// === TagMatchEqual: constructor ===
|
|
|
|
TEST_F(StaInitTest, TagMatchEqualCtor) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
TagMatchEqual eq(true, sta_);
|
|
TagMatchEqual eq2(false, sta_);
|
|
}() ));
|
|
}
|
|
|
|
// (TagGroupBldr/Hash/Equal are incomplete types - skipped)
|
|
|
|
// === DiversionGreater: constructors ===
|
|
|
|
TEST_F(StaInitTest, DiversionGreaterDefaultCtor) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
DiversionGreater greater;
|
|
}() ));
|
|
}
|
|
|
|
TEST_F(StaInitTest, DiversionGreaterStaCtor) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
DiversionGreater greater(sta_);
|
|
}() ));
|
|
}
|
|
|
|
// === ClkSkews: constructor and clear ===
|
|
|
|
TEST_F(StaInitTest, ClkSkewsCtorClear) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
ClkSkews skews(sta_);
|
|
skews.clear();
|
|
}() ));
|
|
}
|
|
|
|
// === Genclks: constructor, destructor, and clear ===
|
|
|
|
TEST_F(StaInitTest, GenclksCtorDtorClear) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
Genclks genclks(sta_->cmdMode(), sta_);
|
|
genclks.clear();
|
|
}() ));
|
|
}
|
|
|
|
// === ClockPinPairLess: operator ===
|
|
|
|
TEST_F(StaInitTest, ClockPinPairLessExists) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
// ClockPinPairLess comparison dereferences Clock*, so just test existence
|
|
ClockPinPairLess less;
|
|
expectStaCoreState(sta_);
|
|
}() ));
|
|
}
|
|
|
|
// === Levelize: setLevelSpace ===
|
|
|
|
TEST_F(StaInitTest, LevelizeSetLevelSpace2) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
Levelize *levelize = sta_->levelize();
|
|
levelize->setLevelSpace(5);
|
|
}() ));
|
|
}
|
|
|
|
// === Levelize: maxLevel ===
|
|
|
|
TEST_F(StaInitTest, LevelizeMaxLevel2) {
|
|
Levelize *levelize = sta_->levelize();
|
|
int ml = levelize->maxLevel();
|
|
EXPECT_GE(ml, 0);
|
|
}
|
|
|
|
// === Levelize: clear ===
|
|
|
|
TEST_F(StaInitTest, LevelizeClear2) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
Levelize *levelize = sta_->levelize();
|
|
levelize->clear();
|
|
}() ));
|
|
}
|
|
|
|
// === SearchPred0: constructor ===
|
|
|
|
TEST_F(StaInitTest, SearchPred0Ctor) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
SearchPred0 pred(sta_);
|
|
}() ));
|
|
}
|
|
|
|
// === SearchPred1: constructor ===
|
|
|
|
TEST_F(StaInitTest, SearchPred1Ctor) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
SearchPred1 pred(sta_);
|
|
}() ));
|
|
}
|
|
|
|
// === SearchPred2: constructor ===
|
|
|
|
// === SearchPredNonLatch2: constructor ===
|
|
|
|
// === SearchPredNonReg2: constructor ===
|
|
|
|
// === ClkTreeSearchPred: constructor ===
|
|
|
|
TEST_F(StaInitTest, ClkTreeSearchPredCtor) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
ClkTreeSearchPred pred(sta_);
|
|
}() ));
|
|
}
|
|
|
|
// === FanOutSrchPred: constructor ===
|
|
|
|
TEST_F(StaInitTest, FanOutSrchPredCtor) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
FanOutSrchPred pred(sta_);
|
|
}() ));
|
|
}
|
|
|
|
// === WorstSlack: constructor/destructor ===
|
|
|
|
TEST_F(StaInitTest, WorstSlackCtorDtor) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
WorstSlack ws(sta_);
|
|
}() ));
|
|
}
|
|
|
|
// === WorstSlack: copy constructor ===
|
|
|
|
TEST_F(StaInitTest, WorstSlackCopyCtor) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
WorstSlack ws1(sta_);
|
|
WorstSlack ws2(ws1);
|
|
}() ));
|
|
}
|
|
|
|
// === WorstSlacks: constructor ===
|
|
|
|
TEST_F(StaInitTest, WorstSlacksCtorDtor) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
WorstSlacks wslacks(sta_);
|
|
}() ));
|
|
}
|
|
|
|
// === Sim: clear ===
|
|
|
|
// === StaState: copyUnits ===
|
|
|
|
TEST_F(StaInitTest, StaStateCopyUnits3) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
Units *units = sta_->units();
|
|
sta_->copyUnits(units);
|
|
}() ));
|
|
}
|
|
|
|
// === PropertyValue: default constructor ===
|
|
|
|
TEST_F(StaInitTest, PropertyValueDefaultCtor) {
|
|
PropertyValue pv;
|
|
EXPECT_EQ(pv.type(), PropertyValue::Type::none);
|
|
}
|
|
|
|
// === PropertyValue: string constructor ===
|
|
|
|
TEST_F(StaInitTest, PropertyValueStringCtor) {
|
|
PropertyValue pv("hello");
|
|
EXPECT_EQ(pv.type(), PropertyValue::Type::string);
|
|
EXPECT_STREQ(pv.stringValue(), "hello");
|
|
}
|
|
|
|
// === PropertyValue: float constructor ===
|
|
|
|
TEST_F(StaInitTest, PropertyValueFloatCtor) {
|
|
PropertyValue pv(3.14f, nullptr);
|
|
EXPECT_EQ(pv.type(), PropertyValue::Type::float_);
|
|
EXPECT_FLOAT_EQ(pv.floatValue(), 3.14f);
|
|
}
|
|
|
|
// === PropertyValue: bool constructor ===
|
|
|
|
TEST_F(StaInitTest, PropertyValueBoolCtor) {
|
|
PropertyValue pv(true);
|
|
EXPECT_EQ(pv.type(), PropertyValue::Type::bool_);
|
|
EXPECT_TRUE(pv.boolValue());
|
|
}
|
|
|
|
// === PropertyValue: copy constructor ===
|
|
|
|
TEST_F(StaInitTest, PropertyValueCopyCtor) {
|
|
PropertyValue pv1("test");
|
|
PropertyValue pv2(pv1);
|
|
EXPECT_EQ(pv2.type(), PropertyValue::Type::string);
|
|
EXPECT_STREQ(pv2.stringValue(), "test");
|
|
}
|
|
|
|
// === PropertyValue: move constructor ===
|
|
|
|
TEST_F(StaInitTest, PropertyValueMoveCtor) {
|
|
PropertyValue pv1("test");
|
|
PropertyValue pv2(std::move(pv1));
|
|
EXPECT_EQ(pv2.type(), PropertyValue::Type::string);
|
|
EXPECT_STREQ(pv2.stringValue(), "test");
|
|
}
|
|
|
|
// === PropertyValue: copy assignment ===
|
|
|
|
TEST_F(StaInitTest, PropertyValueCopyAssign) {
|
|
PropertyValue pv1("test");
|
|
PropertyValue pv2;
|
|
pv2 = pv1;
|
|
EXPECT_EQ(pv2.type(), PropertyValue::Type::string);
|
|
EXPECT_STREQ(pv2.stringValue(), "test");
|
|
}
|
|
|
|
// === PropertyValue: move assignment ===
|
|
|
|
TEST_F(StaInitTest, PropertyValueMoveAssign) {
|
|
PropertyValue pv1("test");
|
|
PropertyValue pv2;
|
|
pv2 = std::move(pv1);
|
|
EXPECT_EQ(pv2.type(), PropertyValue::Type::string);
|
|
EXPECT_STREQ(pv2.stringValue(), "test");
|
|
}
|
|
|
|
// === PropertyValue: Library constructor ===
|
|
|
|
TEST_F(StaInitTest, PropertyValueLibraryCtor) {
|
|
PropertyValue pv(static_cast<const Library *>(nullptr));
|
|
EXPECT_EQ(pv.type(), PropertyValue::Type::library);
|
|
EXPECT_EQ(pv.library(), nullptr);
|
|
}
|
|
|
|
// === PropertyValue: Cell constructor ===
|
|
|
|
TEST_F(StaInitTest, PropertyValueCellCtor) {
|
|
PropertyValue pv(static_cast<const Cell *>(nullptr));
|
|
EXPECT_EQ(pv.type(), PropertyValue::Type::cell);
|
|
EXPECT_EQ(pv.cell(), nullptr);
|
|
}
|
|
|
|
// === PropertyValue: Port constructor ===
|
|
|
|
TEST_F(StaInitTest, PropertyValuePortCtor) {
|
|
PropertyValue pv(static_cast<const Port *>(nullptr));
|
|
EXPECT_EQ(pv.type(), PropertyValue::Type::port);
|
|
EXPECT_EQ(pv.port(), nullptr);
|
|
}
|
|
|
|
// === PropertyValue: LibertyLibrary constructor ===
|
|
|
|
TEST_F(StaInitTest, PropertyValueLibertyLibraryCtor) {
|
|
PropertyValue pv(static_cast<const LibertyLibrary *>(nullptr));
|
|
EXPECT_EQ(pv.type(), PropertyValue::Type::liberty_library);
|
|
EXPECT_EQ(pv.libertyLibrary(), nullptr);
|
|
}
|
|
|
|
// === PropertyValue: LibertyCell constructor ===
|
|
|
|
TEST_F(StaInitTest, PropertyValueLibertyCellCtor) {
|
|
PropertyValue pv(static_cast<const LibertyCell *>(nullptr));
|
|
EXPECT_EQ(pv.type(), PropertyValue::Type::liberty_cell);
|
|
EXPECT_EQ(pv.libertyCell(), nullptr);
|
|
}
|
|
|
|
// === PropertyValue: LibertyPort constructor ===
|
|
|
|
TEST_F(StaInitTest, PropertyValueLibertyPortCtor) {
|
|
PropertyValue pv(static_cast<const LibertyPort *>(nullptr));
|
|
EXPECT_EQ(pv.type(), PropertyValue::Type::liberty_port);
|
|
EXPECT_EQ(pv.libertyPort(), nullptr);
|
|
}
|
|
|
|
// === PropertyValue: Instance constructor ===
|
|
|
|
TEST_F(StaInitTest, PropertyValueInstanceCtor) {
|
|
PropertyValue pv(static_cast<const Instance *>(nullptr));
|
|
EXPECT_EQ(pv.type(), PropertyValue::Type::instance);
|
|
EXPECT_EQ(pv.instance(), nullptr);
|
|
}
|
|
|
|
// === PropertyValue: Pin constructor ===
|
|
|
|
TEST_F(StaInitTest, PropertyValuePinCtor) {
|
|
PropertyValue pv(static_cast<const Pin *>(nullptr));
|
|
EXPECT_EQ(pv.type(), PropertyValue::Type::pin);
|
|
EXPECT_EQ(pv.pin(), nullptr);
|
|
}
|
|
|
|
// === PropertyValue: Net constructor ===
|
|
|
|
TEST_F(StaInitTest, PropertyValueNetCtor) {
|
|
PropertyValue pv(static_cast<const Net *>(nullptr));
|
|
EXPECT_EQ(pv.type(), PropertyValue::Type::net);
|
|
EXPECT_EQ(pv.net(), nullptr);
|
|
}
|
|
|
|
// === PropertyValue: Clock constructor ===
|
|
|
|
TEST_F(StaInitTest, PropertyValueClockCtor) {
|
|
PropertyValue pv(static_cast<const Clock *>(nullptr));
|
|
EXPECT_EQ(pv.type(), PropertyValue::Type::clk);
|
|
EXPECT_EQ(pv.clock(), nullptr);
|
|
}
|
|
|
|
// (Properties protected methods and Sta protected methods skipped)
|
|
|
|
// === Sta: maxPathCountVertex ===
|
|
|
|
// === Sta: connectPin ===
|
|
|
|
// === Sta: replaceCellExists ===
|
|
|
|
// === Sta: disable functions exist ===
|
|
|
|
// === Sta: removeDisable functions exist ===
|
|
|
|
// === Sta: disableClockGatingCheck ===
|
|
|
|
// === Sta: removeDisableClockGatingCheck ===
|
|
|
|
// === Sta: vertexArrival overloads exist ===
|
|
|
|
// === Sta: vertexRequired overloads exist ===
|
|
|
|
// === Sta: vertexSlack overload exists ===
|
|
|
|
// === Sta: vertexSlew overloads exist ===
|
|
|
|
// === Sta: vertexPathIterator exists ===
|
|
|
|
// === Sta: vertexWorstRequiredPath overloads ===
|
|
|
|
// === Sta: checkCapacitance exists ===
|
|
|
|
// === Sta: checkSlew exists ===
|
|
|
|
// === Sta: checkFanout exists ===
|
|
|
|
// === Sta: findSlewLimit exists ===
|
|
|
|
// === Sta: reportCheck exists ===
|
|
|
|
// === Sta: pinsForClock exists ===
|
|
|
|
// === Sta: removeDataCheck exists ===
|
|
|
|
// === Sta: makePortPinAfter exists ===
|
|
|
|
// === Sta: setArcDelayAnnotated exists ===
|
|
|
|
// === Sta: delaysInvalidFromFanin exists ===
|
|
|
|
// === Sta: makeParasiticNetwork exists ===
|
|
|
|
// === Sta: pathAnalysisPt exists ===
|
|
|
|
// === Sta: pathDcalcAnalysisPt exists ===
|
|
|
|
// === Sta: pvt exists ===
|
|
|
|
// === Sta: setPvt exists ===
|
|
|
|
// === Search: arrivalsValid ===
|
|
|
|
TEST_F(StaInitTest, SearchArrivalsValid) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
Search *search = sta_->search();
|
|
(void)search->arrivalsValid();
|
|
}() ));
|
|
}
|
|
|
|
// === Sim: findLogicConstants ===
|
|
|
|
// === ReportField: getters ===
|
|
|
|
TEST_F(StaInitTest, ReportFieldGetters) {
|
|
ReportPath *rpt = sta_->reportPath();
|
|
ReportField *field = rpt->fieldSlew();
|
|
EXPECT_NE(field, nullptr);
|
|
EXPECT_NE(field->name(), nullptr);
|
|
EXPECT_NE(field->title(), nullptr);
|
|
EXPECT_GT(field->width(), 0);
|
|
EXPECT_NE(field->blank(), nullptr);
|
|
}
|
|
|
|
// === ReportField: setWidth ===
|
|
|
|
TEST_F(StaInitTest, ReportFieldSetWidth2) {
|
|
ReportPath *rpt = sta_->reportPath();
|
|
ReportField *field = rpt->fieldFanout();
|
|
int orig = field->width();
|
|
field->setWidth(20);
|
|
EXPECT_EQ(field->width(), 20);
|
|
field->setWidth(orig);
|
|
}
|
|
|
|
// === ReportField: setEnabled ===
|
|
|
|
TEST_F(StaInitTest, ReportFieldSetEnabled2) {
|
|
ReportPath *rpt = sta_->reportPath();
|
|
ReportField *field = rpt->fieldCapacitance();
|
|
bool orig = field->enabled();
|
|
field->setEnabled(!orig);
|
|
EXPECT_EQ(field->enabled(), !orig);
|
|
field->setEnabled(orig);
|
|
}
|
|
|
|
// === ReportField: leftJustify ===
|
|
|
|
TEST_F(StaInitTest, ReportFieldLeftJustify) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
ReportPath *rpt = sta_->reportPath();
|
|
ReportField *field = rpt->fieldSlew();
|
|
field->leftJustify();
|
|
}() ));
|
|
}
|
|
|
|
// === ReportField: unit ===
|
|
|
|
TEST_F(StaInitTest, ReportFieldUnit) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
ReportPath *rpt = sta_->reportPath();
|
|
ReportField *field = rpt->fieldSlew();
|
|
Unit *u = field->unit();
|
|
EXPECT_NE(u, nullptr);
|
|
}() ));
|
|
}
|
|
|
|
// === Corner: constructor ===
|
|
|
|
TEST_F(StaInitTest, CornerCtor) {
|
|
Scene corner("test_corner", 0, sta_->cmdMode(), nullptr);
|
|
EXPECT_EQ(corner.name(), "test_corner");
|
|
EXPECT_EQ(corner.index(), 0);
|
|
}
|
|
|
|
// === Corners: count ===
|
|
|
|
TEST_F(StaInitTest, CornersCount) {
|
|
const SceneSeq &corners = sta_->scenes();
|
|
EXPECT_GE(corners.size(), 0);
|
|
}
|
|
|
|
// === Path static: less with null paths ===
|
|
|
|
TEST_F(StaInitTest, PathStaticLessNull) {
|
|
Path p1;
|
|
Path p2;
|
|
// Both null - less should be false
|
|
bool result = Path::less(&p1, &p2, sta_);
|
|
EXPECT_FALSE(result);
|
|
}
|
|
|
|
// === Path static: lessAll with null paths ===
|
|
|
|
TEST_F(StaInitTest, PathStaticLessAllNull) {
|
|
Path p1;
|
|
Path p2;
|
|
bool result = Path::lessAll(&p1, &p2, sta_);
|
|
EXPECT_FALSE(result);
|
|
}
|
|
|
|
// === Path static: equal with null paths ===
|
|
|
|
TEST_F(StaInitTest, PathStaticEqualNull) {
|
|
Path p1;
|
|
Path p2;
|
|
bool result = Path::equal(&p1, &p2, sta_);
|
|
EXPECT_TRUE(result);
|
|
}
|
|
|
|
// === Sta: isClockNet returns false with no design ===
|
|
|
|
// === PropertyValue: PinSeq constructor ===
|
|
|
|
TEST_F(StaInitTest, PropertyValuePinSeqCtor) {
|
|
PinSeq *pins = new PinSeq;
|
|
PropertyValue pv(pins);
|
|
EXPECT_EQ(pv.type(), PropertyValue::Type::pins);
|
|
}
|
|
|
|
// === PropertyValue: ClockSeq constructor ===
|
|
|
|
TEST_F(StaInitTest, PropertyValueClockSeqCtor) {
|
|
ClockSeq *clks = new ClockSeq;
|
|
PropertyValue pv(clks);
|
|
EXPECT_EQ(pv.type(), PropertyValue::Type::clks);
|
|
}
|
|
|
|
// === Search: tagGroup returns nullptr for invalid index ===
|
|
|
|
// === ClkNetwork: pinsForClock and clocks exist ===
|
|
|
|
// === PathEnd: type enum values ===
|
|
|
|
TEST_F(StaInitTest, PathEndTypeEnums2) {
|
|
EXPECT_EQ(static_cast<int>(PathEnd::Type::unconstrained), 0);
|
|
EXPECT_EQ(static_cast<int>(PathEnd::Type::check), 1);
|
|
EXPECT_EQ(static_cast<int>(PathEnd::Type::data_check), 2);
|
|
EXPECT_EQ(static_cast<int>(PathEnd::Type::latch_check), 3);
|
|
EXPECT_EQ(static_cast<int>(PathEnd::Type::output_delay), 4);
|
|
EXPECT_EQ(static_cast<int>(PathEnd::Type::gated_clk), 5);
|
|
EXPECT_EQ(static_cast<int>(PathEnd::Type::path_delay), 6);
|
|
}
|
|
|
|
// === PathEnd: less function exists ===
|
|
|
|
// === PathEnd: cmpNoCrpr function exists ===
|
|
|
|
// === ReportPathFormat enum ===
|
|
|
|
TEST_F(StaInitTest, ReportPathFormatEnums) {
|
|
EXPECT_NE(ReportPathFormat::full, ReportPathFormat::json);
|
|
EXPECT_NE(ReportPathFormat::full_clock, ReportPathFormat::endpoint);
|
|
EXPECT_NE(ReportPathFormat::summary, ReportPathFormat::slack_only);
|
|
}
|
|
|
|
// === SearchClass constants ===
|
|
|
|
TEST_F(StaInitTest, SearchClassConstants2) {
|
|
EXPECT_GT(tag_index_bit_count, 0u);
|
|
EXPECT_EQ(tag_index_null, tag_index_max);
|
|
EXPECT_GT(path_ap_index_bit_count, 0);
|
|
EXPECT_GT(scene_count_max, 0);
|
|
}
|
|
|
|
// === ReportPath: setReportFields (public) ===
|
|
|
|
TEST_F(StaInitTest, ReportPathSetReportFields2) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
ReportPath *rpt = sta_->reportPath();
|
|
rpt->setReportFields(true, true, true, true, true, true, true, true);
|
|
rpt->setReportFields(false, false, false, false, false, false, false, false);
|
|
}() ));
|
|
}
|
|
|
|
// === MaxSkewCheck: skew with empty paths ===
|
|
|
|
TEST_F(StaInitTest, MaxSkewCheckSkewZero) {
|
|
Path clk_path;
|
|
Path ref_path;
|
|
clk_path.setArrival(0.0f);
|
|
ref_path.setArrival(0.0f);
|
|
MaxSkewCheck check(&clk_path, &ref_path, nullptr, nullptr);
|
|
Delay s = check.skew(sta_);
|
|
EXPECT_FLOAT_EQ(s, 0.0f);
|
|
}
|
|
|
|
// === MaxSkewCheck: skew with different arrivals ===
|
|
|
|
TEST_F(StaInitTest, MaxSkewCheckSkewNonZero) {
|
|
Path clk_path;
|
|
Path ref_path;
|
|
clk_path.setArrival(5.0f);
|
|
ref_path.setArrival(3.0f);
|
|
MaxSkewCheck check(&clk_path, &ref_path, nullptr, nullptr);
|
|
Delay s = check.skew(sta_);
|
|
EXPECT_FLOAT_EQ(s, 2.0f);
|
|
}
|
|
|
|
// === MaxSkewCheck: clkPath and refPath ===
|
|
|
|
TEST_F(StaInitTest, MaxSkewCheckPaths) {
|
|
Path clk_path;
|
|
Path ref_path;
|
|
MaxSkewCheck check(&clk_path, &ref_path, nullptr, nullptr);
|
|
EXPECT_EQ(check.clkPath(), &clk_path);
|
|
EXPECT_EQ(check.refPath(), &ref_path);
|
|
EXPECT_EQ(check.checkArc(), nullptr);
|
|
}
|
|
|
|
// === ClkSkew: srcTgtPathNameLess exists ===
|
|
|
|
TEST_F(StaInitTest, ClkSkewSrcTgtPathNameLessExists) {
|
|
auto fn = &ClkSkew::srcTgtPathNameLess;
|
|
expectCallablePointerUsable(fn);
|
|
}
|
|
|
|
// === ClkSkew: srcInternalClkLatency exists ===
|
|
|
|
TEST_F(StaInitTest, ClkSkewSrcInternalClkLatencyExists) {
|
|
auto fn = &ClkSkew::srcInternalClkLatency;
|
|
expectCallablePointerUsable(fn);
|
|
}
|
|
|
|
// === ClkSkew: tgtInternalClkLatency exists ===
|
|
|
|
TEST_F(StaInitTest, ClkSkewTgtInternalClkLatencyExists) {
|
|
auto fn = &ClkSkew::tgtInternalClkLatency;
|
|
expectCallablePointerUsable(fn);
|
|
}
|
|
|
|
// === ReportPath: setReportFieldOrder ===
|
|
|
|
// === ReportPath: findField ===
|
|
|
|
TEST_F(StaInitTest, ReportPathFindFieldByName) {
|
|
ReportPath *rpt = sta_->reportPath();
|
|
ReportField *slew = rpt->findField("slew");
|
|
EXPECT_NE(slew, nullptr);
|
|
ReportField *fanout = rpt->findField("fanout");
|
|
EXPECT_NE(fanout, nullptr);
|
|
ReportField *cap = rpt->findField("capacitance");
|
|
EXPECT_NE(cap, nullptr);
|
|
// Non-existent field
|
|
ReportField *nonexist = rpt->findField("nonexistent_field");
|
|
EXPECT_EQ(nonexist, nullptr);
|
|
}
|
|
|
|
// === PropertyValue: std::string constructor ===
|
|
|
|
TEST_F(StaInitTest, PropertyValueStdStringCtor) {
|
|
std::string s = "test_string";
|
|
PropertyValue pv(s);
|
|
EXPECT_EQ(pv.type(), PropertyValue::Type::string);
|
|
EXPECT_STREQ(pv.stringValue(), "test_string");
|
|
}
|
|
|
|
// === Levelize: invalid ===
|
|
|
|
TEST_F(StaInitTest, LevelizeInvalid) {
|
|
Levelize *levelize = sta_->levelize();
|
|
levelize->invalid();
|
|
EXPECT_FALSE(levelize->levelized());
|
|
}
|
|
|
|
// === R5_ Round 2: Re-add public ReportPath methods that were accidentally removed ===
|
|
|
|
TEST_F(StaInitTest, ReportPathDigits) {
|
|
ReportPath *rpt = sta_->reportPath();
|
|
int d = rpt->digits();
|
|
EXPECT_GE(d, 0);
|
|
}
|
|
|
|
TEST_F(StaInitTest, ReportPathSetDigits) {
|
|
ReportPath *rpt = sta_->reportPath();
|
|
rpt->setDigits(5);
|
|
EXPECT_EQ(rpt->digits(), 5);
|
|
rpt->setDigits(3); // restore default
|
|
}
|
|
|
|
// ReportPathReportSigmas2 test removed: reportSigmas API removed
|
|
|
|
// ReportPathSetReportSigmas test removed: setReportSigmas/reportSigmas API removed
|
|
|
|
TEST_F(StaInitTest, ReportPathPathFormat) {
|
|
ReportPath *rpt = sta_->reportPath();
|
|
ReportPathFormat fmt = rpt->pathFormat();
|
|
// Check it is a valid format
|
|
EXPECT_TRUE(fmt == ReportPathFormat::full
|
|
|| fmt == ReportPathFormat::full_clock
|
|
|| fmt == ReportPathFormat::full_clock_expanded
|
|
|| fmt == ReportPathFormat::summary
|
|
|| fmt == ReportPathFormat::slack_only
|
|
|| fmt == ReportPathFormat::endpoint
|
|
|| fmt == ReportPathFormat::json);
|
|
}
|
|
|
|
TEST_F(StaInitTest, ReportPathSetPathFormat) {
|
|
ReportPath *rpt = sta_->reportPath();
|
|
ReportPathFormat old_fmt = rpt->pathFormat();
|
|
rpt->setPathFormat(ReportPathFormat::summary);
|
|
EXPECT_EQ(rpt->pathFormat(), ReportPathFormat::summary);
|
|
rpt->setPathFormat(old_fmt);
|
|
}
|
|
|
|
TEST_F(StaInitTest, ReportPathFindFieldSlew) {
|
|
ReportPath *rpt = sta_->reportPath();
|
|
ReportField *slew = rpt->findField("slew");
|
|
EXPECT_NE(slew, nullptr);
|
|
EXPECT_STREQ(slew->name(), "slew");
|
|
}
|
|
|
|
TEST_F(StaInitTest, ReportPathFindFieldFanout) {
|
|
ReportPath *rpt = sta_->reportPath();
|
|
ReportField *fo = rpt->findField("fanout");
|
|
EXPECT_NE(fo, nullptr);
|
|
EXPECT_STREQ(fo->name(), "fanout");
|
|
}
|
|
|
|
TEST_F(StaInitTest, ReportPathFindFieldCapacitance) {
|
|
ReportPath *rpt = sta_->reportPath();
|
|
ReportField *cap = rpt->findField("capacitance");
|
|
EXPECT_NE(cap, nullptr);
|
|
EXPECT_STREQ(cap->name(), "capacitance");
|
|
}
|
|
|
|
TEST_F(StaInitTest, ReportPathFindFieldNonexistent) {
|
|
ReportPath *rpt = sta_->reportPath();
|
|
ReportField *f = rpt->findField("nonexistent_field_xyz");
|
|
EXPECT_EQ(f, nullptr);
|
|
}
|
|
|
|
TEST_F(StaInitTest, ReportPathSetNoSplit) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
ReportPath *rpt = sta_->reportPath();
|
|
rpt->setNoSplit(true);
|
|
rpt->setNoSplit(false);
|
|
expectStaCoreState(sta_);
|
|
}() ));
|
|
}
|
|
|
|
TEST_F(StaInitTest, ReportPathFieldSrcAttr) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
ReportPath *rpt = sta_->reportPath();
|
|
ReportField *src = rpt->fieldSrcAttr();
|
|
// src_attr field may or may not exist
|
|
expectStaCoreState(sta_);
|
|
}() ));
|
|
}
|
|
|
|
TEST_F(StaInitTest, ReportPathSetReportFieldsPublic) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
ReportPath *rpt = sta_->reportPath();
|
|
// Call setReportFields with various combinations
|
|
rpt->setReportFields(true, false, false, false, true, false, false, false);
|
|
rpt->setReportFields(true, true, true, true, true, true, true, true);
|
|
expectStaCoreState(sta_);
|
|
}() ));
|
|
}
|
|
|
|
// === ReportPath: header methods (public) ===
|
|
|
|
// === ReportPath: report method function pointers ===
|
|
|
|
// === ReportPath: reportCheck overloads ===
|
|
|
|
// === ReportPath: report short/full/json overloads ===
|
|
|
|
// === ReportPath: report short for PathEnd types ===
|
|
|
|
// === ReportPath: reportFull for PathEnd types ===
|
|
|
|
// === ReportField: blank getter ===
|
|
|
|
TEST_F(StaInitTest, ReportFieldBlank2) {
|
|
ReportPath *rpt = sta_->reportPath();
|
|
ReportField *field = rpt->fieldSlew();
|
|
const char *blank = field->blank();
|
|
EXPECT_NE(blank, nullptr);
|
|
}
|
|
|
|
// === ReportField: setProperties ===
|
|
|
|
TEST_F(StaInitTest, ReportFieldSetProperties2) {
|
|
ReportPath *rpt = sta_->reportPath();
|
|
ReportField *field = rpt->fieldSlew();
|
|
int old_width = field->width();
|
|
bool old_justify = field->leftJustify();
|
|
// set new properties
|
|
field->setProperties("NewTitle", 15, true);
|
|
EXPECT_EQ(field->width(), 15);
|
|
EXPECT_TRUE(field->leftJustify());
|
|
// restore
|
|
field->setProperties("Slew", old_width, old_justify);
|
|
}
|
|
|
|
// === CheckCapacitances: constructor ===
|
|
|
|
TEST_F(StaInitTest, CheckCapacitancesCtorDtor) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
CheckCapacitances checker(sta_);
|
|
expectStaCoreState(sta_);
|
|
}() ));
|
|
}
|
|
|
|
// === CheckSlews: constructor ===
|
|
|
|
TEST_F(StaInitTest, CheckSlewsCtorDtor) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
CheckSlews checker(sta_);
|
|
expectStaCoreState(sta_);
|
|
}() ));
|
|
}
|
|
|
|
// === CheckFanouts: constructor ===
|
|
|
|
TEST_F(StaInitTest, CheckFanoutsCtorDtor) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
CheckFanouts checker(sta_);
|
|
expectStaCoreState(sta_);
|
|
}() ));
|
|
}
|
|
|
|
// === PathExpanded: empty constructor ===
|
|
|
|
TEST_F(StaInitTest, PathExpandedEmptyCtor) {
|
|
PathExpanded expanded(sta_);
|
|
EXPECT_EQ(expanded.size(), static_cast<size_t>(0));
|
|
}
|
|
|
|
// === PathGroups: static group names ===
|
|
|
|
TEST_F(StaInitTest, PathGroupsAsyncGroupName) {
|
|
const char *name = PathGroups::asyncPathGroupName();
|
|
EXPECT_NE(name, nullptr);
|
|
}
|
|
|
|
TEST_F(StaInitTest, PathGroupsPathDelayGroupName) {
|
|
const char *name = PathGroups::pathDelayGroupName();
|
|
EXPECT_NE(name, nullptr);
|
|
}
|
|
|
|
TEST_F(StaInitTest, PathGroupsGatedClkGroupName) {
|
|
const char *name = PathGroups::gatedClkGroupName();
|
|
EXPECT_NE(name, nullptr);
|
|
}
|
|
|
|
TEST_F(StaInitTest, PathGroupsUnconstrainedGroupName) {
|
|
const char *name = PathGroups::unconstrainedGroupName();
|
|
EXPECT_NE(name, nullptr);
|
|
}
|
|
|
|
// === PathGroup: static max path count ===
|
|
|
|
TEST_F(StaInitTest, PathGroupMaxPathCountMax) {
|
|
EXPECT_GT(PathGroup::group_path_count_max, static_cast<size_t>(0));
|
|
}
|
|
|
|
// === PathGroup: makePathGroupSlack factory ===
|
|
|
|
TEST_F(StaInitTest, PathGroupMakeSlack2) {
|
|
PathGroup *pg = PathGroup::makePathGroupSlack(
|
|
"test_slack", 10, 1, false, false, -1e30, 1e30, sta_);
|
|
EXPECT_NE(pg, nullptr);
|
|
EXPECT_EQ(pg->name(), "test_slack");
|
|
EXPECT_EQ(pg->maxPaths(), 10);
|
|
delete pg;
|
|
}
|
|
|
|
// === PathGroup: makePathGroupArrival factory ===
|
|
|
|
TEST_F(StaInitTest, PathGroupMakeArrival2) {
|
|
PathGroup *pg = PathGroup::makePathGroupArrival(
|
|
"test_arrival", 5, 1, false, false, MinMax::max(), sta_);
|
|
EXPECT_NE(pg, nullptr);
|
|
EXPECT_EQ(pg->name(), "test_arrival");
|
|
delete pg;
|
|
}
|
|
|
|
// === PathGroup: clear and pathEnds ===
|
|
|
|
TEST_F(StaInitTest, PathGroupClear) {
|
|
PathGroup *pg = PathGroup::makePathGroupSlack(
|
|
"test_clear", 10, 1, false, false, -1e30, 1e30, sta_);
|
|
const PathEndSeq &ends = pg->pathEnds();
|
|
EXPECT_EQ(ends.size(), static_cast<size_t>(0));
|
|
pg->clear();
|
|
EXPECT_EQ(pg->pathEnds().size(), static_cast<size_t>(0));
|
|
delete pg;
|
|
}
|
|
|
|
// === CheckCrpr: constructor ===
|
|
|
|
TEST_F(StaInitTest, CheckCrprCtor) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
CheckCrpr crpr(sta_);
|
|
expectStaCoreState(sta_);
|
|
}() ));
|
|
}
|
|
|
|
// === GatedClk: constructor ===
|
|
|
|
TEST_F(StaInitTest, GatedClkCtor) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
GatedClk gclk(sta_);
|
|
expectStaCoreState(sta_);
|
|
}() ));
|
|
}
|
|
|
|
// === ClkLatency: constructor ===
|
|
|
|
TEST_F(StaInitTest, ClkLatencyCtor) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
ClkLatency lat(sta_);
|
|
expectStaCoreState(sta_);
|
|
}() ));
|
|
}
|
|
|
|
// === Sta function pointers: more uncovered methods ===
|
|
|
|
// (Removed duplicates of R5_StaCheckSlewExists, R5_StaCheckCapacitanceExists,
|
|
// R5_StaCheckFanoutExists, R5_StaFindSlewLimitExists, R5_StaVertexSlewDcalcExists,
|
|
// R5_StaVertexSlewCornerMinMaxExists - already defined above)
|
|
|
|
// === Path: more static methods ===
|
|
|
|
TEST_F(StaInitTest, PathEqualBothNull) {
|
|
bool eq = Path::equal(nullptr, nullptr, sta_);
|
|
EXPECT_TRUE(eq);
|
|
}
|
|
|
|
// === Search: more function pointers ===
|
|
|
|
// === Levelize: more methods ===
|
|
|
|
TEST_F(StaInitTest, LevelizeLevelized) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
Levelize *levelize = sta_->levelize();
|
|
levelize->levelized();
|
|
expectStaCoreState(sta_);
|
|
}() ));
|
|
}
|
|
|
|
// === Sim: more methods ===
|
|
|
|
// === Corners: iteration ===
|
|
|
|
TEST_F(StaInitTest, CornersIteration) {
|
|
const SceneSeq &corners = sta_->scenes();
|
|
int count = corners.size();
|
|
EXPECT_GE(count, 1);
|
|
Scene *corner = corners[0];
|
|
EXPECT_NE(corner, nullptr);
|
|
}
|
|
|
|
TEST_F(StaInitTest, CornerFindName) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
const SceneSeq &corners = sta_->scenes();
|
|
Scene *corner = sta_->findScene("default");
|
|
EXPECT_NE(corner, nullptr);
|
|
expectStaCoreState(sta_);
|
|
}() ));
|
|
}
|
|
|
|
// === Corner: name and index ===
|
|
|
|
TEST_F(StaInitTest, CornerNameAndIndex) {
|
|
const SceneSeq &corners = sta_->scenes();
|
|
Scene *corner = corners[0];
|
|
EXPECT_NE(corner, nullptr);
|
|
const std::string &name = corner->name();
|
|
EXPECT_FALSE(name.empty());
|
|
int idx = corner->index();
|
|
EXPECT_EQ(idx, 0);
|
|
}
|
|
|
|
// === PathEnd: function pointer existence for virtual methods ===
|
|
|
|
// (Removed duplicates of R5_StaVertexPathIteratorExists, R5_StaPathAnalysisPtExists,
|
|
// R5_StaPathDcalcAnalysisPtExists - already defined above)
|
|
|
|
// === ReportPath: reportPathEnds function pointer ===
|
|
|
|
// === ReportPath: reportPath function pointer (Path*) ===
|
|
|
|
// === ReportPath: reportEndLine function pointer ===
|
|
|
|
// === ReportPath: reportSummaryLine function pointer ===
|
|
|
|
// === ReportPath: reportSlackOnly function pointer ===
|
|
|
|
// === ReportPath: reportJson overloads ===
|
|
|
|
// === Search: pathClkPathArrival function pointers ===
|
|
|
|
// === Genclks: more function pointers ===
|
|
|
|
// (Removed R5_GenclksGenclkInfoExists - genclkInfo is private)
|
|
// (Removed R5_GenclksSrcPathExists - srcPath has wrong signature)
|
|
// (Removed R5_SearchSeedInputArrivalsExists - seedInputArrivals is protected)
|
|
// (Removed R5_SimClockGateOutValueExists - clockGateOutValue is protected)
|
|
// (Removed R5_SimPinConstFuncValueExists - pinConstFuncValue is protected)
|
|
|
|
// === MinPulseWidthCheck: corner function pointer ===
|
|
|
|
// === MaxSkewCheck: more function pointers ===
|
|
|
|
TEST_F(StaInitTest, MaxSkewCheckClkPinExists) {
|
|
auto fn = &MaxSkewCheck::clkPin;
|
|
expectCallablePointerUsable(fn);
|
|
}
|
|
|
|
TEST_F(StaInitTest, MaxSkewCheckRefPinExists) {
|
|
auto fn = &MaxSkewCheck::refPin;
|
|
expectCallablePointerUsable(fn);
|
|
}
|
|
|
|
TEST_F(StaInitTest, MaxSkewCheckMaxSkewMethodExists) {
|
|
auto fn = &MaxSkewCheck::maxSkew;
|
|
expectCallablePointerUsable(fn);
|
|
}
|
|
|
|
TEST_F(StaInitTest, MaxSkewCheckSlackExists) {
|
|
auto fn = &MaxSkewCheck::slack;
|
|
expectCallablePointerUsable(fn);
|
|
}
|
|
|
|
// === ClkInfo: more function pointers ===
|
|
|
|
// === Tag: more function pointers ===
|
|
|
|
// (Removed R5_TagStateEqualExists - stateEqual is protected)
|
|
|
|
// === Path: more function pointers ===
|
|
|
|
// === PathEnd: reportShort virtual function pointer ===
|
|
|
|
// === ReportPath: reportPathEnd overloads ===
|
|
|
|
// (Removed duplicates of R5_StaVertexArrivalMinMaxExists etc - already defined above)
|
|
|
|
// === Corner: DcalcAnalysisPt access ===
|
|
|
|
// === PathAnalysisPt access through Corners ===
|
|
|
|
// === Sta: isClock(Pin*) function pointer ===
|
|
|
|
// === GraphLoop: report function pointer ===
|
|
|
|
// === SearchPredNonReg2: searchThru function pointer ===
|
|
|
|
// === CheckCrpr: maxCrpr function pointer ===
|
|
|
|
// === CheckCrpr: checkCrpr function pointers ===
|
|
|
|
// === GatedClk: isGatedClkEnable function pointer ===
|
|
|
|
// === GatedClk: gatedClkActiveTrans function pointer ===
|
|
|
|
// === FindRegister: free functions ===
|
|
|
|
////////////////////////////////////////////////////////////////
|
|
// R6_ tests: additional coverage for uncovered search functions
|
|
////////////////////////////////////////////////////////////////
|
|
|
|
// === OutputDelays: constructor and timingSense ===
|
|
|
|
// === ClkDelays: constructor and latency ===
|
|
|
|
// === Bdd: constructor and destructor ===
|
|
|
|
// === PathExpanded: constructor with two args (Path*, bool, StaState*) ===
|
|
|
|
TEST_F(StaInitTest, PathExpandedStaOnlyCtor) {
|
|
PathExpanded expanded(sta_);
|
|
EXPECT_EQ(expanded.size(), 0u);
|
|
}
|
|
|
|
// === Search: visitEndpoints ===
|
|
|
|
// havePendingLatchOutputs and clearPendingLatchOutputs are protected, skipped
|
|
|
|
// === Search: findPathGroup by name ===
|
|
|
|
// === Search: findPathGroup by clock ===
|
|
|
|
// === Search: tag ===
|
|
|
|
TEST_F(StaInitTest, SearchTagZero) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
Search *search = sta_->search();
|
|
// tagCount should be 0 initially
|
|
TagIndex count = search->tagCount();
|
|
EXPECT_GE(count, 0);
|
|
expectStaCoreState(sta_);
|
|
}() ));
|
|
}
|
|
|
|
// === Search: tagGroupCount ===
|
|
|
|
TEST_F(StaInitTest, SearchTagGroupCount3) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
Search *search = sta_->search();
|
|
TagGroupIndex count = search->tagGroupCount();
|
|
EXPECT_GE(count, 0);
|
|
expectStaCoreState(sta_);
|
|
}() ));
|
|
}
|
|
|
|
// === Search: clkInfoCount ===
|
|
|
|
TEST_F(StaInitTest, SearchClkInfoCount3) {
|
|
Search *search = sta_->search();
|
|
int count = search->clkInfoCount();
|
|
EXPECT_EQ(count, 0);
|
|
}
|
|
|
|
// === Search: initVars (called indirectly through clear) ===
|
|
|
|
TEST_F(StaInitTest, SearchClear3) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
Search *search = sta_->search();
|
|
search->clear();
|
|
expectStaCoreState(sta_);
|
|
}() ));
|
|
}
|
|
|
|
// === Search: checkPrevPaths ===
|
|
|
|
// === Search: arrivalsValid ===
|
|
|
|
TEST_F(StaInitTest, SearchArrivalsValid2) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
Search *search = sta_->search();
|
|
(void)search->arrivalsValid();
|
|
expectStaCoreState(sta_);
|
|
}() ));
|
|
}
|
|
|
|
// Search::endpoints segfaults without graph - skipped
|
|
|
|
// === Search: havePathGroups ===
|
|
|
|
// === Search: requiredsSeeded ===
|
|
|
|
// === Search: requiredsExist ===
|
|
|
|
// === Search: arrivalsAtEndpointsExist ===
|
|
|
|
// === Search: crprPathPruningEnabled / setCrprpathPruningEnabled ===
|
|
|
|
TEST_F(StaInitTest, SearchCrprPathPruning2) {
|
|
Search *search = sta_->search();
|
|
bool enabled = search->crprPathPruningEnabled();
|
|
search->setCrprpathPruningEnabled(!enabled);
|
|
EXPECT_NE(search->crprPathPruningEnabled(), enabled);
|
|
search->setCrprpathPruningEnabled(enabled);
|
|
EXPECT_EQ(search->crprPathPruningEnabled(), enabled);
|
|
}
|
|
|
|
// === Search: crprApproxMissingRequireds ===
|
|
|
|
TEST_F(StaInitTest, SearchCrprApproxMissingRequireds2) {
|
|
Search *search = sta_->search();
|
|
bool val = search->crprApproxMissingRequireds();
|
|
search->setCrprApproxMissingRequireds(!val);
|
|
EXPECT_NE(search->crprApproxMissingRequireds(), val);
|
|
search->setCrprApproxMissingRequireds(val);
|
|
}
|
|
|
|
// === Search: unconstrainedPaths ===
|
|
|
|
// === Search: deletePathGroups ===
|
|
|
|
// === Search: deleteFilter ===
|
|
|
|
// === Search: arrivalIterator and requiredIterator ===
|
|
|
|
TEST_F(StaInitTest, SearchArrivalIterator) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
Search *search = sta_->search();
|
|
BfsFwdIterator *iter = search->arrivalIterator();
|
|
EXPECT_NE(iter, nullptr);
|
|
expectStaCoreState(sta_);
|
|
}() ));
|
|
}
|
|
|
|
TEST_F(StaInitTest, SearchRequiredIterator) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
Search *search = sta_->search();
|
|
BfsBkwdIterator *iter = search->requiredIterator();
|
|
EXPECT_NE(iter, nullptr);
|
|
expectStaCoreState(sta_);
|
|
}() ));
|
|
}
|
|
|
|
// === Search: evalPred and searchAdj ===
|
|
|
|
TEST_F(StaInitTest, SearchEvalPred2) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
Search *search = sta_->search();
|
|
EvalPred *pred = search->evalPred();
|
|
EXPECT_NE(pred, nullptr);
|
|
expectStaCoreState(sta_);
|
|
}() ));
|
|
}
|
|
|
|
TEST_F(StaInitTest, SearchSearchAdj2) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
Search *search = sta_->search();
|
|
SearchPred *adj = search->searchAdj();
|
|
EXPECT_NE(adj, nullptr);
|
|
expectStaCoreState(sta_);
|
|
}() ));
|
|
}
|
|
|
|
// === Sta: isClock(Net*) ===
|
|
|
|
// === Sta: pins(Clock*) ===
|
|
|
|
// === Sta: setCmdNamespace ===
|
|
|
|
TEST_F(StaInitTest, StaSetCmdNamespace2) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
sta_->setCmdNamespace(CmdNamespace::sdc);
|
|
sta_->setCmdNamespace(CmdNamespace::sta);
|
|
expectStaCoreState(sta_);
|
|
}() ));
|
|
}
|
|
|
|
// === Sta: vertexArrival(Vertex*, MinMax*) ===
|
|
|
|
// === Sta: vertexArrival(Vertex*, RiseFall*, PathAnalysisPt*) ===
|
|
|
|
// === Sta: vertexRequired(Vertex*, MinMax*) ===
|
|
|
|
// === Sta: vertexRequired(Vertex*, RiseFall*, MinMax*) ===
|
|
|
|
// === Sta: vertexRequired(Vertex*, RiseFall*, PathAnalysisPt*) ===
|
|
|
|
// === Sta: vertexSlack(Vertex*, RiseFall*, PathAnalysisPt*) ===
|
|
|
|
// === Sta: vertexSlacks(Vertex*, array) ===
|
|
|
|
// === Sta: vertexSlew(Vertex*, RiseFall*, Scene*, MinMax*) ===
|
|
|
|
// === Sta: vertexSlew(Vertex*, RiseFall*, DcalcAnalysisPt*) ===
|
|
|
|
// === Sta: vertexPathIterator(Vertex*, RiseFall*, PathAnalysisPt*) ===
|
|
|
|
// === Sta: vertexWorstRequiredPath(Vertex*, MinMax*) ===
|
|
|
|
// === Sta: vertexWorstRequiredPath(Vertex*, RiseFall*, MinMax*) ===
|
|
|
|
// === Sta: setArcDelayAnnotated ===
|
|
|
|
// === Sta: pathAnalysisPt(Path*) ===
|
|
|
|
// === Sta: pathDcalcAnalysisPt(Path*) ===
|
|
|
|
// === Sta: maxPathCountVertex ===
|
|
|
|
// Sta::maxPathCountVertex segfaults without graph - use fn pointer
|
|
// === Sta: tagCount, tagGroupCount ===
|
|
|
|
TEST_F(StaInitTest, StaTagCount3) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
TagIndex count = sta_->tagCount();
|
|
EXPECT_GE(count, 0);
|
|
expectStaCoreState(sta_);
|
|
}() ));
|
|
}
|
|
|
|
TEST_F(StaInitTest, StaTagGroupCount3) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
TagGroupIndex count = sta_->tagGroupCount();
|
|
EXPECT_GE(count, 0);
|
|
expectStaCoreState(sta_);
|
|
}() ));
|
|
}
|
|
|
|
// === Sta: clkInfoCount ===
|
|
|
|
TEST_F(StaInitTest, StaClkInfoCount3) {
|
|
int count = sta_->clkInfoCount();
|
|
EXPECT_EQ(count, 0);
|
|
}
|
|
|
|
// === Sta: findDelays ===
|
|
|
|
// === Sta: reportCheck(MaxSkewCheck*, bool) ===
|
|
|
|
// === Sta: checkSlew ===
|
|
|
|
// === Sta: findSlewLimit ===
|
|
|
|
// === Sta: checkFanout ===
|
|
|
|
// === Sta: checkCapacitance ===
|
|
|
|
// === Sta: pvt ===
|
|
|
|
// === Sta: setPvt ===
|
|
|
|
// === Sta: connectPin ===
|
|
|
|
// === Sta: makePortPinAfter ===
|
|
|
|
// === Sta: replaceCellExists ===
|
|
|
|
// === Sta: makeParasiticNetwork ===
|
|
|
|
// === Sta: disable/removeDisable for LibertyPort ===
|
|
|
|
// === Sta: disable/removeDisable for Edge ===
|
|
|
|
// === Sta: disable/removeDisable for TimingArcSet ===
|
|
|
|
// === Sta: disableClockGatingCheck/removeDisableClockGatingCheck for Pin ===
|
|
|
|
// === Sta: removeDataCheck ===
|
|
|
|
// === Sta: clockDomains ===
|
|
|
|
// === ReportPath: reportJsonHeader ===
|
|
|
|
TEST_F(StaInitTest, ReportPathReportJsonHeader) {
|
|
ReportPath *rpt = sta_->reportPath();
|
|
EXPECT_NE(rpt, nullptr);
|
|
rpt->reportJsonHeader();
|
|
expectStaCoreState(sta_);
|
|
}
|
|
|
|
// === ReportPath: reportPeriodHeaderShort ===
|
|
|
|
TEST_F(StaInitTest, ReportPathReportPeriodHeaderShort) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
ReportPath *rpt = sta_->reportPath();
|
|
rpt->reportPeriodHeaderShort();
|
|
expectStaCoreState(sta_);
|
|
}() ));
|
|
}
|
|
|
|
// === ReportPath: reportMaxSkewHeaderShort ===
|
|
|
|
TEST_F(StaInitTest, ReportPathReportMaxSkewHeaderShort) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
ReportPath *rpt = sta_->reportPath();
|
|
rpt->reportMaxSkewHeaderShort();
|
|
expectStaCoreState(sta_);
|
|
}() ));
|
|
}
|
|
|
|
// === ReportPath: reportMpwHeaderShort ===
|
|
|
|
TEST_F(StaInitTest, ReportPathReportMpwHeaderShort) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
ReportPath *rpt = sta_->reportPath();
|
|
rpt->reportMpwHeaderShort();
|
|
expectStaCoreState(sta_);
|
|
}() ));
|
|
}
|
|
|
|
// === ReportPath: reportPathEndHeader ===
|
|
|
|
TEST_F(StaInitTest, ReportPathReportPathEndHeader) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
ReportPath *rpt = sta_->reportPath();
|
|
|
|
expectStaCoreState(sta_);
|
|
}() ));
|
|
}
|
|
|
|
// === ReportPath: reportPathEndFooter ===
|
|
|
|
TEST_F(StaInitTest, ReportPathReportPathEndFooter) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
ReportPath *rpt = sta_->reportPath();
|
|
|
|
expectStaCoreState(sta_);
|
|
}() ));
|
|
}
|
|
|
|
// === ReportPath: reportJsonFooter ===
|
|
|
|
TEST_F(StaInitTest, ReportPathReportJsonFooter) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
ReportPath *rpt = sta_->reportPath();
|
|
rpt->reportJsonFooter();
|
|
expectStaCoreState(sta_);
|
|
}() ));
|
|
}
|
|
|
|
// === ReportPath: setPathFormat ===
|
|
|
|
TEST_F(StaInitTest, ReportPathSetPathFormat2) {
|
|
ReportPath *rpt = sta_->reportPath();
|
|
ReportPathFormat fmt = rpt->pathFormat();
|
|
rpt->setPathFormat(fmt);
|
|
EXPECT_EQ(rpt->pathFormat(), fmt);
|
|
}
|
|
|
|
// === ReportPath: setDigits ===
|
|
|
|
TEST_F(StaInitTest, ReportPathSetDigits2) {
|
|
ReportPath *rpt = sta_->reportPath();
|
|
int digits = rpt->digits();
|
|
rpt->setDigits(4);
|
|
EXPECT_EQ(rpt->digits(), 4);
|
|
rpt->setDigits(digits);
|
|
}
|
|
|
|
// === ReportPath: setNoSplit ===
|
|
|
|
TEST_F(StaInitTest, ReportPathSetNoSplit2) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
ReportPath *rpt = sta_->reportPath();
|
|
rpt->setNoSplit(true);
|
|
rpt->setNoSplit(false);
|
|
expectStaCoreState(sta_);
|
|
}() ));
|
|
}
|
|
|
|
// ReportPathSetReportSigmas2 test removed: setReportSigmas/reportSigmas API removed
|
|
|
|
// === ReportPath: findField ===
|
|
|
|
TEST_F(StaInitTest, ReportPathFindField2) {
|
|
ReportPath *rpt = sta_->reportPath();
|
|
ReportField *f = rpt->findField("nonexistent_field_xyz");
|
|
EXPECT_EQ(f, nullptr);
|
|
}
|
|
|
|
// === ReportPath: fieldSlew/fieldFanout/fieldCapacitance ===
|
|
|
|
TEST_F(StaInitTest, ReportPathFieldAccessors) {
|
|
ReportPath *rpt = sta_->reportPath();
|
|
ReportField *slew = rpt->fieldSlew();
|
|
ReportField *fanout = rpt->fieldFanout();
|
|
ReportField *cap = rpt->fieldCapacitance();
|
|
ReportField *src = rpt->fieldSrcAttr();
|
|
EXPECT_NE(slew, nullptr);
|
|
EXPECT_NE(fanout, nullptr);
|
|
EXPECT_NE(cap, nullptr);
|
|
EXPECT_NE(src, nullptr);
|
|
expectStaCoreState(sta_);
|
|
}
|
|
|
|
// === ReportPath: reportEndHeader ===
|
|
|
|
TEST_F(StaInitTest, ReportPathReportEndHeader) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
ReportPath *rpt = sta_->reportPath();
|
|
rpt->reportEndHeader();
|
|
expectStaCoreState(sta_);
|
|
}() ));
|
|
}
|
|
|
|
// === ReportPath: reportSummaryHeader ===
|
|
|
|
TEST_F(StaInitTest, ReportPathReportSummaryHeader) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
ReportPath *rpt = sta_->reportPath();
|
|
rpt->reportSummaryHeader();
|
|
expectStaCoreState(sta_);
|
|
}() ));
|
|
}
|
|
|
|
// === ReportPath: reportSlackOnlyHeader ===
|
|
|
|
TEST_F(StaInitTest, ReportPathReportSlackOnlyHeader) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
ReportPath *rpt = sta_->reportPath();
|
|
rpt->reportSlackOnlyHeader();
|
|
expectStaCoreState(sta_);
|
|
}() ));
|
|
}
|
|
|
|
// === PathGroups: static group name accessors ===
|
|
|
|
TEST_F(StaInitTest, PathGroupsAsyncGroupName2) {
|
|
const char *name = PathGroups::asyncPathGroupName();
|
|
EXPECT_NE(name, nullptr);
|
|
}
|
|
|
|
TEST_F(StaInitTest, PathGroupsPathDelayGroupName2) {
|
|
const char *name = PathGroups::pathDelayGroupName();
|
|
EXPECT_NE(name, nullptr);
|
|
}
|
|
|
|
TEST_F(StaInitTest, PathGroupsGatedClkGroupName2) {
|
|
const char *name = PathGroups::gatedClkGroupName();
|
|
EXPECT_NE(name, nullptr);
|
|
}
|
|
|
|
TEST_F(StaInitTest, PathGroupsUnconstrainedGroupName2) {
|
|
const char *name = PathGroups::unconstrainedGroupName();
|
|
EXPECT_NE(name, nullptr);
|
|
}
|
|
|
|
// Corner setParasiticAnalysisPtcount, setParasiticAP, setDcalcAnalysisPtcount,
|
|
// addPathAP are protected - skipped
|
|
|
|
// === Corners: parasiticAnalysisPtCount ===
|
|
|
|
// === ClkNetwork: isClock(Net*) ===
|
|
|
|
// === ClkNetwork: clocks(Pin*) ===
|
|
|
|
// === ClkNetwork: pins(Clock*) ===
|
|
|
|
// BfsIterator::init is protected - skipped
|
|
|
|
// === BfsIterator: checkInQueue ===
|
|
|
|
// === BfsIterator: enqueueAdjacentVertices with level ===
|
|
|
|
// === Levelize: checkLevels ===
|
|
|
|
// Levelize::reportPath is protected - skipped
|
|
|
|
// === Path: init overloads ===
|
|
|
|
// === Path: constructor with Vertex*, Tag*, StaState* ===
|
|
|
|
// === PathEnd: less and cmpNoCrpr ===
|
|
|
|
// === Tag: equal and match static methods ===
|
|
|
|
// Tag::match and Tag::stateEqual are protected - skipped
|
|
|
|
// === ClkInfo: equal static method ===
|
|
|
|
// === ClkInfo: crprClkPath ===
|
|
|
|
// CheckCrpr::portClkPath and crprArrivalDiff are private - skipped
|
|
|
|
// === Sim: findLogicConstants ===
|
|
|
|
// === Sim: makePinAfter ===
|
|
|
|
// === GatedClk: gatedClkEnables ===
|
|
|
|
// === Search: pathClkPathArrival1 (protected, use fn pointer) ===
|
|
|
|
// === Search: visitStartpoints ===
|
|
|
|
// === Search: reportTagGroups ===
|
|
|
|
// === Search: reportPathCountHistogram ===
|
|
|
|
// Search::reportPathCountHistogram segfaults without graph - use fn pointer
|
|
// === Search: arrivalsInvalid ===
|
|
|
|
TEST_F(StaInitTest, SearchArrivalsInvalid3) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
Search *search = sta_->search();
|
|
search->arrivalsInvalid();
|
|
expectStaCoreState(sta_);
|
|
}() ));
|
|
}
|
|
|
|
// === Search: requiredsInvalid ===
|
|
|
|
TEST_F(StaInitTest, SearchRequiredsInvalid3) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
Search *search = sta_->search();
|
|
search->requiredsInvalid();
|
|
expectStaCoreState(sta_);
|
|
}() ));
|
|
}
|
|
|
|
// === Search: endpointsInvalid ===
|
|
|
|
TEST_F(StaInitTest, SearchEndpointsInvalid3) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
Search *search = sta_->search();
|
|
search->endpointsInvalid();
|
|
expectStaCoreState(sta_);
|
|
}() ));
|
|
}
|
|
|
|
// === Search: copyState ===
|
|
|
|
// === Search: isEndpoint ===
|
|
|
|
// === Search: seedArrival ===
|
|
|
|
// === Search: enqueueLatchOutput ===
|
|
|
|
// === Search: isSegmentStart ===
|
|
|
|
// === Search: seedRequiredEnqueueFanin ===
|
|
|
|
// === Search: saveEnumPath ===
|
|
|
|
// === Sta: graphLoops ===
|
|
|
|
// === Sta: pathCount ===
|
|
|
|
// Sta::pathCount segfaults without graph - use fn pointer
|
|
// === Sta: findAllArrivals ===
|
|
|
|
// === Sta: findArrivals ===
|
|
|
|
// === Sta: findRequireds ===
|
|
|
|
// === PathEnd: type names for subclass function pointers ===
|
|
|
|
// === PathEndUnconstrained: reportShort and requiredTime ===
|
|
|
|
// === PathEnum destructor ===
|
|
|
|
// === DiversionGreater ===
|
|
|
|
TEST_F(StaInitTest, DiversionGreaterStateCtor) {
|
|
ASSERT_NO_THROW(( [&](){
|
|
DiversionGreater dg(sta_);
|
|
EXPECT_NE(&dg, nullptr);
|
|
expectStaCoreState(sta_);
|
|
}() ));
|
|
}
|
|
|
|
// === TagGroup: report function pointer ===
|
|
|
|
// === TagGroupBldr: reportArrivalEntries ===
|
|
|
|
// === VertexPinCollector: copy ===
|
|
|
|
// VertexPinCollector::copy() throws "not supported" - skipped
|
|
// === Genclks: function pointers ===
|
|
|
|
// Genclks::srcFilter and srcPathIndex are private - skipped
|
|
|
|
// === Genclks: findLatchFdbkEdges overloads ===
|
|
|
|
// === Sta: simLogicValue ===
|
|
|
|
// === Sta: netSlack ===
|
|
|
|
// === Sta: pinSlack overloads ===
|
|
|
|
// === Sta: pinArrival ===
|
|
|
|
// === Sta: vertexLevel ===
|
|
|
|
// === Sta: vertexPathCount ===
|
|
|
|
// === Sta: endpointSlack ===
|
|
|
|
// === Sta: arcDelay ===
|
|
|
|
// === Sta: arcDelayAnnotated ===
|
|
|
|
// === Sta: findClkMinPeriod ===
|
|
|
|
// === Sta: vertexWorstArrivalPath ===
|
|
|
|
// === Sta: vertexWorstSlackPath ===
|
|
|
|
// === Sta: vertexSlew more overloads ===
|
|
|
|
// === Sta: vertexPathIterator(Vertex*, RiseFall*, MinMax*) ===
|
|
|
|
// === Sta: totalNegativeSlack ===
|
|
|
|
// === Sta: worstSlack ===
|
|
|
|
// === Sta: updateTiming ===
|
|
|
|
// === Search: clkPathArrival ===
|
|
|
|
// Sta::readLibertyFile (4-arg overload) is protected - skipped
|
|
|
|
// === Sta: disconnectPin ===
|
|
|
|
// === PathExpandedCtorGenClks ===
|
|
|
|
// === Search: deleteFilteredArrivals ===
|
|
|
|
// === Sta: checkSlewLimitPreamble ===
|
|
|
|
// === Sta: checkFanoutLimitPreamble ===
|
|
|
|
// === Sta: checkCapacitanceLimitPreamble ===
|
|
|
|
// === Sta: checkSlewLimits(Net*,...) ===
|
|
|
|
// === Sta: checkFanoutLimits(Net*,...) ===
|
|
|
|
// === Sta: checkCapacitanceLimits(Net*,...) ===
|
|
|
|
// === Search: seedInputSegmentArrival ===
|
|
|
|
// === Search: enqueueLatchDataOutputs ===
|
|
|
|
// === Search: seedRequired ===
|
|
|
|
// === Search: findClkArrivals ===
|
|
|
|
// === Search: tnsInvalid ===
|
|
|
|
// === Search: endpointInvalid ===
|
|
|
|
// === Search: makePathGroups ===
|
|
|
|
// === Sta: isIdealClock ===
|
|
|
|
// === Sta: isPropagatedClock ===
|
|
|
|
} // namespace sta
|