#include #include #include #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 static void expectCallablePointerUsable(FnPtr fn) { ASSERT_NE(fn, nullptr); EXPECT_TRUE((std::is_pointer_v || std::is_member_function_pointer_v)); EXPECT_TRUE(std::is_copy_constructible_v); EXPECT_TRUE(std::is_copy_assignable_v); 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(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(nullptr), false, false, 0, 0, false, false, sta_->cmdMode()), Exception); } TEST_F(StaInitTest, StaFindFanoutPinsThrows2) { EXPECT_THROW(sta_->findFanoutPins(static_cast(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::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::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::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::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::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::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::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::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::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::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, "", 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(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; (void)hash; }() )); } // === TagLess: constructor === TEST_F(StaInitTest, TagLessCtor) { ASSERT_NO_THROW(( [&](){ TagLess less(sta_); (void)less; }() )); } // === TagIndexLess: existence === TEST_F(StaInitTest, TagIndexLessExists) { ASSERT_NO_THROW(( [&](){ TagIndexLess less; (void)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; (void)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(std::string("hello")); EXPECT_EQ(pv.type(), PropertyValue::Type::string); EXPECT_EQ(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(std::string("test")); PropertyValue pv2(pv1); EXPECT_EQ(pv2.type(), PropertyValue::Type::string); EXPECT_EQ(pv2.stringValue(), "test"); } // === PropertyValue: move constructor === TEST_F(StaInitTest, PropertyValueMoveCtor) { PropertyValue pv1(std::string("test")); PropertyValue pv2(std::move(pv1)); EXPECT_EQ(pv2.type(), PropertyValue::Type::string); EXPECT_EQ(pv2.stringValue(), "test"); } // === PropertyValue: copy assignment === TEST_F(StaInitTest, PropertyValueCopyAssign) { PropertyValue pv1(std::string("test")); PropertyValue pv2; pv2 = pv1; EXPECT_EQ(pv2.type(), PropertyValue::Type::string); EXPECT_EQ(pv2.stringValue(), "test"); } // === PropertyValue: move assignment === TEST_F(StaInitTest, PropertyValueMoveAssign) { PropertyValue pv1(std::string("test")); PropertyValue pv2; pv2 = std::move(pv1); EXPECT_EQ(pv2.type(), PropertyValue::Type::string); EXPECT_EQ(pv2.stringValue(), "test"); } // === PropertyValue: Library constructor === TEST_F(StaInitTest, PropertyValueLibraryCtor) { PropertyValue pv(static_cast(nullptr)); EXPECT_EQ(pv.type(), PropertyValue::Type::library); EXPECT_EQ(pv.library(), nullptr); } // === PropertyValue: Cell constructor === TEST_F(StaInitTest, PropertyValueCellCtor) { PropertyValue pv(static_cast(nullptr)); EXPECT_EQ(pv.type(), PropertyValue::Type::cell); EXPECT_EQ(pv.cell(), nullptr); } // === PropertyValue: Port constructor === TEST_F(StaInitTest, PropertyValuePortCtor) { PropertyValue pv(static_cast(nullptr)); EXPECT_EQ(pv.type(), PropertyValue::Type::port); EXPECT_EQ(pv.port(), nullptr); } // === PropertyValue: LibertyLibrary constructor === TEST_F(StaInitTest, PropertyValueLibertyLibraryCtor) { PropertyValue pv(static_cast(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(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(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(nullptr)); EXPECT_EQ(pv.type(), PropertyValue::Type::instance); EXPECT_EQ(pv.instance(), nullptr); } // === PropertyValue: Pin constructor === TEST_F(StaInitTest, PropertyValuePinCtor) { PropertyValue pv(static_cast(nullptr)); EXPECT_EQ(pv.type(), PropertyValue::Type::pin); EXPECT_EQ(pv.pin(), nullptr); } // === PropertyValue: Net constructor === TEST_F(StaInitTest, PropertyValueNetCtor) { PropertyValue pv(static_cast(nullptr)); EXPECT_EQ(pv.type(), PropertyValue::Type::net); EXPECT_EQ(pv.net(), nullptr); } // === PropertyValue: Clock constructor === TEST_F(StaInitTest, PropertyValueClockCtor) { PropertyValue pv(static_cast(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_FALSE(field->name().empty()); EXPECT_FALSE(field->title().empty()); EXPECT_GT(field->width(), 0); EXPECT_FALSE(field->blank().empty()); } // === 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(PathEnd::Type::unconstrained), 0); EXPECT_EQ(static_cast(PathEnd::Type::check), 1); EXPECT_EQ(static_cast(PathEnd::Type::data_check), 2); EXPECT_EQ(static_cast(PathEnd::Type::latch_check), 3); EXPECT_EQ(static_cast(PathEnd::Type::output_delay), 4); EXPECT_EQ(static_cast(PathEnd::Type::gated_clk), 5); EXPECT_EQ(static_cast(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_EQ(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_EQ(slew->name(), "slew"); } TEST_F(StaInitTest, ReportPathFindFieldFanout) { ReportPath *rpt = sta_->reportPath(); ReportField *fo = rpt->findField("fanout"); EXPECT_NE(fo, nullptr); EXPECT_EQ(fo->name(), "fanout"); } TEST_F(StaInitTest, ReportPathFindFieldCapacitance) { ReportPath *rpt = sta_->reportPath(); ReportField *cap = rpt->findField("capacitance"); EXPECT_NE(cap, nullptr); EXPECT_EQ(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(); (void)src; // 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 std::string &blank = field->blank(); EXPECT_FALSE(blank.empty()); } // === 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(0)); } // === PathGroups: static group names === TEST_F(StaInitTest, PathGroupsAsyncGroupName) { std::string_view name = PathGroups::asyncPathGroupName(); EXPECT_FALSE(name.empty()); } TEST_F(StaInitTest, PathGroupsPathDelayGroupName) { std::string_view name = PathGroups::pathDelayGroupName(); EXPECT_FALSE(name.empty()); } TEST_F(StaInitTest, PathGroupsGatedClkGroupName) { std::string_view name = PathGroups::gatedClkGroupName(); EXPECT_FALSE(name.empty()); } TEST_F(StaInitTest, PathGroupsUnconstrainedGroupName) { std::string_view name = PathGroups::unconstrainedGroupName(); EXPECT_FALSE(name.empty()); } // === PathGroup: static max path count === TEST_F(StaInitTest, PathGroupMaxPathCountMax) { EXPECT_GT(PathGroup::group_path_count_max, static_cast(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(0)); pg->clear(); EXPECT_EQ(pg->pathEnds().size(), static_cast(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(); (void)corners; 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(); (void)rpt; expectStaCoreState(sta_); }() )); } // === ReportPath: reportPathEndFooter === TEST_F(StaInitTest, ReportPathReportPathEndFooter) { ASSERT_NO_THROW(( [&](){ ReportPath *rpt = sta_->reportPath(); (void)rpt; 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) { std::string_view name = PathGroups::asyncPathGroupName(); EXPECT_FALSE(name.empty()); } TEST_F(StaInitTest, PathGroupsPathDelayGroupName2) { std::string_view name = PathGroups::pathDelayGroupName(); EXPECT_FALSE(name.empty()); } TEST_F(StaInitTest, PathGroupsGatedClkGroupName2) { std::string_view name = PathGroups::gatedClkGroupName(); EXPECT_FALSE(name.empty()); } TEST_F(StaInitTest, PathGroupsUnconstrainedGroupName2) { std::string_view name = PathGroups::unconstrainedGroupName(); EXPECT_FALSE(name.empty()); } // 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