Files
OpenSTA/search/test/cpp/TestSearchStaInit.cc
T
Minju Kim 509913b139 search/test: adapt PathEnd gtests to set_path_margin API
Upstream e9c075ab (BIGFEATURE: Add `set_path_margin` command, parallaxsw#469)
added a `PathMargin *path_margin` parameter to the PathEndCheck,
PathEndOutputDelay and PathEndGatedClock constructors, between `mcp` and the
argument that followed it.

Our per-module gtests are not in the upstream tree, so the upstream change did
not touch them and the merge left them calling the old arity. Pass nullptr for
the new parameter; these cases only exercise type()/typeName()/copy(), so no
margin is needed.

No behavioral change - test-only API adaptation.

Signed-off-by: Minju Kim <[email protected]>
2026-08-14 19:47:46 +09:00

4329 lines
121 KiB
C++

#include <gtest/gtest.h>
#include <type_traits>
#include <tcl.h>
#include "MinMax.hh"
#include "TestReportFields.hh"
#include "Transition.hh"
#include "Property.hh"
#include "ExceptionPath.hh"
#include "TimingRole.hh"
#include "Scene.hh"
#include "Mode.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)
{
ASSERT_NE(sta, nullptr);
EXPECT_EQ(Sta::sta(), sta);
EXPECT_NE(sta->network(), nullptr);
EXPECT_NE(sta->search(), nullptr);
EXPECT_NE(sta->cmdSdc(), nullptr);
EXPECT_NE(sta->report(), nullptr);
EXPECT_FALSE(sta->scenes().empty());
if (!sta->scenes().empty()) {
EXPECT_GE(sta->scenes().size(), 1);
}
EXPECT_NE(sta->cmdScene(), nullptr);
}
////////////////////////////////////////////////////////////////
// Sta initialization tests - exercises Sta.cc and StaState.cc
////////////////////////////////////////////////////////////////
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_;
};
TEST_F(StaInitTest, StaNotNull) {
EXPECT_NE(sta_, nullptr);
EXPECT_EQ(Sta::sta(), sta_);
}
TEST_F(StaInitTest, NetworkExists) {
EXPECT_NE(sta_->network(), nullptr);
}
TEST_F(StaInitTest, SdcExists) {
EXPECT_NE(sta_->cmdSdc(), nullptr);
}
TEST_F(StaInitTest, UnitsExists) {
EXPECT_NE(sta_->units(), nullptr);
}
TEST_F(StaInitTest, ReportExists) {
EXPECT_NE(sta_->report(), nullptr);
}
TEST_F(StaInitTest, DebugExists) {
EXPECT_NE(sta_->debug(), nullptr);
}
TEST_F(StaInitTest, CornersExists) {
EXPECT_FALSE(sta_->scenes().empty());
}
TEST_F(StaInitTest, VariablesExists) {
EXPECT_NE(sta_->variables(), nullptr);
}
TEST_F(StaInitTest, DefaultAnalysisType) {
sta_->setAnalysisType(AnalysisType::single, sta_->cmdSdc());
EXPECT_EQ(sta_->cmdSdc()->analysisType(), AnalysisType::single);
}
TEST_F(StaInitTest, SetAnalysisTypeBcWc) {
sta_->setAnalysisType(AnalysisType::bc_wc, sta_->cmdSdc());
EXPECT_EQ(sta_->cmdSdc()->analysisType(), AnalysisType::bc_wc);
}
TEST_F(StaInitTest, SetAnalysisTypeOcv) {
sta_->setAnalysisType(AnalysisType::ocv, sta_->cmdSdc());
EXPECT_EQ(sta_->cmdSdc()->analysisType(), AnalysisType::ocv);
}
TEST_F(StaInitTest, CmdNamespace) {
sta_->setCmdNamespace(CmdNamespace::sdc);
EXPECT_EQ(sta_->cmdNamespace(), CmdNamespace::sdc);
sta_->setCmdNamespace(CmdNamespace::sta);
EXPECT_EQ(sta_->cmdNamespace(), CmdNamespace::sta);
}
TEST_F(StaInitTest, DefaultThreadCount) {
int tc = sta_->threadCount();
EXPECT_GE(tc, 1);
}
TEST_F(StaInitTest, SetThreadCount) {
sta_->setThreadCount(2);
EXPECT_EQ(sta_->threadCount(), 2);
sta_->setThreadCount(1);
EXPECT_EQ(sta_->threadCount(), 1);
}
TEST_F(StaInitTest, GraphNotCreated) {
// Graph should be null before any design is read
EXPECT_EQ(sta_->graph(), nullptr);
}
TEST_F(StaInitTest, CurrentInstanceNull) {
EXPECT_EQ(sta_->currentInstance(), nullptr);
}
TEST_F(StaInitTest, CmdCorner) {
Scene *corner = sta_->cmdScene();
EXPECT_NE(corner, nullptr);
}
TEST_F(StaInitTest, FindCorner) {
// Default corner name
Scene *corner = sta_->findScene("default");
EXPECT_NE(corner, nullptr);
}
TEST_F(StaInitTest, CornerCount) {
EXPECT_GE(sta_->scenes().size(), 1);
}
TEST_F(StaInitTest, Variables) {
Variables *vars = sta_->variables();
EXPECT_TRUE(vars->crprEnabled());
vars->setCrprEnabled(false);
EXPECT_FALSE(vars->crprEnabled());
vars->setCrprEnabled(true);
}
TEST_F(StaInitTest, EquivCellsNull) {
EXPECT_EQ(sta_->equivCells(nullptr), nullptr);
}
TEST_F(StaInitTest, PropagateAllClocks) {
sta_->setPropagateAllClocks(true);
EXPECT_TRUE(sta_->variables()->propagateAllClocks());
sta_->setPropagateAllClocks(false);
EXPECT_FALSE(sta_->variables()->propagateAllClocks());
}
TEST_F(StaInitTest, WorstSlackNoDesign) {
// Without a design loaded, worst slack should throw
Slack worst;
Vertex *worst_vertex;
EXPECT_THROW(sta_->worstSlack(MinMax::max(), worst, worst_vertex),
std::exception);
}
TEST_F(StaInitTest, ClearNoDesign) {
ASSERT_NE(sta_->network(), nullptr);
ASSERT_NE(sta_->cmdSdc(), nullptr);
sta_->clear();
EXPECT_NE(sta_->network(), nullptr);
EXPECT_NE(sta_->cmdSdc(), nullptr);
EXPECT_NE(sta_->search(), nullptr);
EXPECT_EQ(sta_->graph(), nullptr);
EXPECT_NE(sta_->cmdSdc()->defaultArrivalClock(), nullptr);
}
TEST_F(StaInitTest, SdcAnalysisType) {
Sdc *sdc = sta_->cmdSdc();
sdc->setAnalysisType(AnalysisType::ocv);
EXPECT_EQ(sdc->analysisType(), AnalysisType::ocv);
sdc->setAnalysisType(AnalysisType::single);
EXPECT_EQ(sdc->analysisType(), AnalysisType::single);
}
TEST_F(StaInitTest, StaStateDefaultConstruct) {
StaState state;
EXPECT_EQ(state.report(), nullptr);
EXPECT_EQ(state.debug(), nullptr);
EXPECT_EQ(state.units(), nullptr);
EXPECT_EQ(state.network(), nullptr);
// sdc() not directly on StaState
EXPECT_EQ(state.graph(), nullptr);
// corners() not directly on StaState
EXPECT_EQ(state.variables(), nullptr);
}
TEST_F(StaInitTest, StaStateCopyConstruct) {
StaState state(sta_);
EXPECT_EQ(state.network(), sta_->network());
// sdc() not directly on StaState
EXPECT_EQ(state.report(), sta_->report());
EXPECT_EQ(state.units(), sta_->units());
EXPECT_EQ(state.variables(), sta_->variables());
}
TEST_F(StaInitTest, StaStateCopyState) {
StaState state;
state.copyState(sta_);
EXPECT_EQ(state.network(), sta_->network());
// sdc() not directly on StaState
}
TEST_F(StaInitTest, NetworkEdit) {
// networkEdit should return the same Network as a NetworkEdit*
NetworkEdit *ne = sta_->networkEdit();
EXPECT_NE(ne, nullptr);
}
TEST_F(StaInitTest, NetworkReader) {
NetworkReader *nr = sta_->networkReader();
EXPECT_NE(nr, nullptr);
}
// TCL Variable wrapper tests - exercise Sta.cc variable accessors
TEST_F(StaInitTest, CrprEnabled) {
EXPECT_TRUE(sta_->crprEnabled());
sta_->setCrprEnabled(false);
EXPECT_FALSE(sta_->crprEnabled());
sta_->setCrprEnabled(true);
EXPECT_TRUE(sta_->crprEnabled());
}
TEST_F(StaInitTest, CrprMode) {
sta_->setCrprMode(CrprMode::same_pin);
EXPECT_EQ(sta_->crprMode(), CrprMode::same_pin);
sta_->setCrprMode(CrprMode::same_transition);
EXPECT_EQ(sta_->crprMode(), CrprMode::same_transition);
}
TEST_F(StaInitTest, PocvMode) {
sta_->setPocvMode(PocvMode::normal);
EXPECT_EQ(sta_->pocvMode(), PocvMode::normal);
sta_->setPocvMode(PocvMode::scalar);
EXPECT_EQ(sta_->pocvMode(), PocvMode::scalar);
}
TEST_F(StaInitTest, PropagateGatedClockEnable) {
sta_->setPropagateGatedClockEnable(true);
EXPECT_TRUE(sta_->propagateGatedClockEnable());
sta_->setPropagateGatedClockEnable(false);
EXPECT_FALSE(sta_->propagateGatedClockEnable());
}
TEST_F(StaInitTest, PresetClrArcsEnabled) {
sta_->setPresetClrArcsEnabled(true);
EXPECT_TRUE(sta_->presetClrArcsEnabled());
sta_->setPresetClrArcsEnabled(false);
EXPECT_FALSE(sta_->presetClrArcsEnabled());
}
TEST_F(StaInitTest, CondDefaultArcsEnabled) {
sta_->setCondDefaultArcsEnabled(true);
EXPECT_TRUE(sta_->condDefaultArcsEnabled());
sta_->setCondDefaultArcsEnabled(false);
EXPECT_FALSE(sta_->condDefaultArcsEnabled());
}
TEST_F(StaInitTest, BidirectInstPathsEnabled) {
sta_->setBidirectInstPathsEnabled(true);
EXPECT_TRUE(sta_->bidirectInstPathsEnabled());
sta_->setBidirectInstPathsEnabled(false);
EXPECT_FALSE(sta_->bidirectInstPathsEnabled());
}
TEST_F(StaInitTest, BidirectNetPathsEnabled) {
// bidirectInstPathsEnabled has been removed
sta_->setBidirectInstPathsEnabled(true);
EXPECT_TRUE(sta_->bidirectInstPathsEnabled());
sta_->setBidirectInstPathsEnabled(false);
EXPECT_FALSE(sta_->bidirectInstPathsEnabled());
}
TEST_F(StaInitTest, RecoveryRemovalChecksEnabled) {
sta_->setRecoveryRemovalChecksEnabled(true);
EXPECT_TRUE(sta_->recoveryRemovalChecksEnabled());
sta_->setRecoveryRemovalChecksEnabled(false);
EXPECT_FALSE(sta_->recoveryRemovalChecksEnabled());
}
TEST_F(StaInitTest, GatedClkChecksEnabled) {
sta_->setGatedClkChecksEnabled(true);
EXPECT_TRUE(sta_->gatedClkChecksEnabled());
sta_->setGatedClkChecksEnabled(false);
EXPECT_FALSE(sta_->gatedClkChecksEnabled());
}
TEST_F(StaInitTest, DynamicLoopBreaking) {
sta_->setDynamicLoopBreaking(true);
EXPECT_TRUE(sta_->dynamicLoopBreaking());
sta_->setDynamicLoopBreaking(false);
EXPECT_FALSE(sta_->dynamicLoopBreaking());
}
TEST_F(StaInitTest, ClkThruTristateEnabled) {
sta_->setClkThruTristateEnabled(true);
EXPECT_TRUE(sta_->clkThruTristateEnabled());
sta_->setClkThruTristateEnabled(false);
EXPECT_FALSE(sta_->clkThruTristateEnabled());
}
TEST_F(StaInitTest, UseDefaultArrivalClock) {
sta_->setUseDefaultArrivalClock(true);
EXPECT_TRUE(sta_->useDefaultArrivalClock());
sta_->setUseDefaultArrivalClock(false);
EXPECT_FALSE(sta_->useDefaultArrivalClock());
}
// Report path format settings - exercise ReportPath.cc
TEST_F(StaInitTest, SetReportPathFormat) {
ReportPath *rpt = sta_->reportPath();
ASSERT_NE(rpt, nullptr);
sta_->setReportPathFormat(ReportPathFormat::full);
EXPECT_EQ(rpt->pathFormat(), ReportPathFormat::full);
sta_->setReportPathFormat(ReportPathFormat::full_clock);
EXPECT_EQ(rpt->pathFormat(), ReportPathFormat::full_clock);
sta_->setReportPathFormat(ReportPathFormat::full_clock_expanded);
EXPECT_EQ(rpt->pathFormat(), ReportPathFormat::full_clock_expanded);
sta_->setReportPathFormat(ReportPathFormat::endpoint);
EXPECT_EQ(rpt->pathFormat(), ReportPathFormat::endpoint);
sta_->setReportPathFormat(ReportPathFormat::summary);
EXPECT_EQ(rpt->pathFormat(), ReportPathFormat::summary);
sta_->setReportPathFormat(ReportPathFormat::slack_only);
EXPECT_EQ(rpt->pathFormat(), ReportPathFormat::slack_only);
sta_->setReportPathFormat(ReportPathFormat::json);
EXPECT_EQ(rpt->pathFormat(), ReportPathFormat::json);
}
TEST_F(StaInitTest, SetReportPathDigits) {
ReportPath *rpt = sta_->reportPath();
ASSERT_NE(rpt, nullptr);
sta_->setReportPathDigits(4);
EXPECT_EQ(rpt->digits(), 4);
sta_->setReportPathDigits(2);
EXPECT_EQ(rpt->digits(), 2);
}
TEST_F(StaInitTest, SetReportPathNoSplit) {
ASSERT_NE(sta_->reportPath(), nullptr);
ASSERT_NO_THROW(sta_->setReportPathNoSplit(true));
ASSERT_NO_THROW(sta_->setReportPathNoSplit(false));
}
// SetReportPathSigmas test removed: setReportPathSigmas/reportSigmas API removed
TEST_F(StaInitTest, SetReportPathFields) {
ReportPath *rpt = sta_->reportPath();
ASSERT_NE(rpt, nullptr);
ReportField *cap_field = rpt->findField("capacitance");
ReportField *slew_field = rpt->findField("slew");
ReportField *fanout_field = rpt->findField("fanout");
ReportField *src_attr_field = rpt->findField("src_attr");
ASSERT_NE(cap_field, nullptr);
ASSERT_NE(slew_field, nullptr);
ASSERT_NE(fanout_field, nullptr);
ASSERT_NE(src_attr_field, nullptr);
sta_->setReportPathFields(kAllReportFields);
EXPECT_TRUE(cap_field->enabled());
EXPECT_TRUE(slew_field->enabled());
EXPECT_TRUE(fanout_field->enabled());
EXPECT_TRUE(src_attr_field->enabled());
sta_->setReportPathFields(StringSeq{});
EXPECT_FALSE(cap_field->enabled());
EXPECT_FALSE(slew_field->enabled());
EXPECT_FALSE(fanout_field->enabled());
EXPECT_FALSE(src_attr_field->enabled());
}
// Corner operations
TEST_F(StaInitTest, MultiCorner) {
// Default single corner
EXPECT_FALSE(sta_->multiScene());
}
TEST_F(StaInitTest, SetCmdCorner) {
Scene *corner = sta_->cmdScene();
sta_->setCmdScene(corner);
EXPECT_EQ(sta_->cmdScene(), corner);
}
TEST_F(StaInitTest, CornerName) {
Scene *corner = sta_->cmdScene();
EXPECT_EQ(corner->name(), "default");
}
TEST_F(StaInitTest, CornerIndex) {
Scene *corner = sta_->cmdScene();
EXPECT_EQ(corner->index(), 0);
}
TEST_F(StaInitTest, FindNonexistentCorner) {
Scene *corner = sta_->findScene("nonexistent");
EXPECT_EQ(corner, nullptr);
}
TEST_F(StaInitTest, MakeCorners) {
StringSeq names;
names.push_back("fast");
names.push_back("slow");
sta_->makeScenes(names);
EXPECT_NE(sta_->findScene("fast"), nullptr);
EXPECT_NE(sta_->findScene("slow"), nullptr);
EXPECT_GT(sta_->scenes().size(), 1u);
}
// SDC operations via Sta
TEST_F(StaInitTest, SdcRemoveConstraints) {
Sdc *sdc = sta_->cmdSdc();
ASSERT_NE(sdc, nullptr);
sdc->setAnalysisType(AnalysisType::bc_wc);
// removeConstraints() was removed from Sta API
sdc->clear();
EXPECT_NE(sdc->defaultArrivalClock(), nullptr);
EXPECT_NE(sdc->defaultArrivalClockEdge(), nullptr);
EXPECT_TRUE(sdc->clocks().empty());
}
TEST_F(StaInitTest, SdcConstraintsChanged) {
Sdc *sdc = sta_->cmdSdc();
ASSERT_NE(sdc, nullptr);
ASSERT_NO_THROW(sta_->delaysInvalid());
EXPECT_NE(sta_->search(), nullptr);
}
TEST_F(StaInitTest, UnsetTimingDerate) {
ASSERT_NO_THROW(sta_->unsetTimingDerate(sta_->cmdSdc()));
EXPECT_NE(sta_->cmdSdc(), nullptr);
}
TEST_F(StaInitTest, SetMaxArea) {
Sdc *sdc = sta_->cmdSdc();
ASSERT_NE(sdc, nullptr);
sta_->setMaxArea(100.0, sta_->cmdSdc());
EXPECT_FLOAT_EQ(sdc->maxArea(), 100.0f);
}
// Test Sdc clock operations directly
TEST_F(StaInitTest, SdcClocks) {
Sdc *sdc = sta_->cmdSdc();
// Initially no clocks
ClockSeq clks = sdc->clocks();
EXPECT_TRUE(clks.empty());
}
TEST_F(StaInitTest, SdcFindClock) {
Sdc *sdc = sta_->cmdSdc();
Clock *clk = sdc->findClock("nonexistent");
EXPECT_EQ(clk, nullptr);
}
// Ensure exceptions are thrown when no design is loaded
TEST_F(StaInitTest, EnsureLinkedThrows) {
EXPECT_THROW(sta_->ensureLinked(), std::exception);
}
TEST_F(StaInitTest, EnsureGraphThrows) {
EXPECT_THROW(sta_->ensureGraph(), std::exception);
}
// Clock groups via Sdc
TEST_F(StaInitTest, MakeClockGroups) {
ClockGroups *groups = sta_->makeClockGroups("test_group",
true, // logically_exclusive
false, // physically_exclusive
false, // asynchronous
false, // allow_paths
"test comment", sta_->cmdSdc());
EXPECT_NE(groups, nullptr);
}
// Exception path construction - nullptr pins/clks/insts returns nullptr
TEST_F(StaInitTest, MakeExceptionFromNull) {
ExceptionFrom *from = sta_->makeExceptionFrom(nullptr, nullptr, nullptr,
RiseFallBoth::riseFall(),
sta_->cmdSdc());
// All null inputs returns nullptr
EXPECT_EQ(from, nullptr);
}
TEST_F(StaInitTest, MakeExceptionFromAllNull) {
// All null inputs returns nullptr - exercises the check logic
ExceptionFrom *from = sta_->makeExceptionFrom(nullptr, nullptr, nullptr,
RiseFallBoth::riseFall(),
sta_->cmdSdc());
EXPECT_EQ(from, nullptr);
}
TEST_F(StaInitTest, MakeExceptionFromEmpty) {
// Empty sets also return nullptr
PinSet *pins = new PinSet;
ExceptionFrom *from = sta_->makeExceptionFrom(pins, nullptr, nullptr,
RiseFallBoth::riseFall(),
sta_->cmdSdc());
EXPECT_EQ(from, nullptr);
}
TEST_F(StaInitTest, MakeExceptionThruNull) {
ExceptionThru *thru = sta_->makeExceptionThru(nullptr, nullptr, nullptr,
RiseFallBoth::riseFall(),
sta_->cmdSdc());
EXPECT_EQ(thru, nullptr);
}
TEST_F(StaInitTest, MakeExceptionToNull) {
ExceptionTo *to = sta_->makeExceptionTo(nullptr, nullptr, nullptr,
RiseFallBoth::riseFall(),
RiseFallBoth::riseFall(),
sta_->cmdSdc());
EXPECT_EQ(to, nullptr);
}
// Path group names
TEST_F(StaInitTest, PathGroupNames) {
StringSeq names = sta_->pathGroupNames(sta_->cmdSdc());
EXPECT_FALSE(names.empty());
}
TEST_F(StaInitTest, IsPathGroupName) {
EXPECT_FALSE(sta_->isPathGroupName("nonexistent", sta_->cmdSdc()));
}
// Debug level
TEST_F(StaInitTest, SetDebugLevel) {
sta_->setDebugLevel("search", 0);
EXPECT_EQ(sta_->debug()->level("search"), 0);
sta_->setDebugLevel("search", 1);
EXPECT_EQ(sta_->debug()->level("search"), 1);
sta_->setDebugLevel("search", 0);
EXPECT_EQ(sta_->debug()->level("search"), 0);
}
// Incremental delay tolerance
TEST_F(StaInitTest, IncrementalDelayTolerance) {
GraphDelayCalc *gdc = sta_->graphDelayCalc();
ASSERT_NE(gdc, nullptr);
sta_->setIncrementalDelayTolerance(0.0);
EXPECT_FLOAT_EQ(gdc->incrementalDelayTolerance(), 0.0f);
sta_->setIncrementalDelayTolerance(0.01);
EXPECT_FLOAT_EQ(gdc->incrementalDelayTolerance(), 0.01f);
}
// SigmaFactor test removed: setSigmaFactor API removed
// Properties
TEST_F(StaInitTest, PropertiesAccess) {
Properties &props = sta_->properties();
Properties &props2 = sta_->properties();
EXPECT_EQ(&props, &props2);
}
// TclInterp
TEST_F(StaInitTest, TclInterpAccess) {
sta_->setTclInterp(interp_);
EXPECT_EQ(sta_->tclInterp(), interp_);
}
// SceneSeq analysis points
TEST_F(StaInitTest, CornersDcalcApCount) {
const SceneSeq &corners = sta_->scenes();
// SceneSeq is now std::vector<Scene*>; no dcalcAnalysisPtCount
EXPECT_GE(corners.size(), 1u);
}
TEST_F(StaInitTest, CornersPathApCount) {
const SceneSeq &corners = sta_->scenes();
// SceneSeq is now std::vector<Scene*>; no pathAnalysisPtCount
EXPECT_GE(corners.size(), 1u);
}
TEST_F(StaInitTest, CornersParasiticApCount) {
const SceneSeq &corners = sta_->scenes();
// parasiticAnalysisPtCount removed from API
EXPECT_GE(corners.size(), 1u);
}
TEST_F(StaInitTest, CornerIterator) {
const SceneSeq &corners = sta_->scenes();
int count = 0;
for (Scene *corner : corners) {
EXPECT_NE(corner, nullptr);
count++;
}
EXPECT_GE(count, 1);
}
TEST_F(StaInitTest, CornerFindDcalcAp) {
Scene *corner = sta_->cmdScene();
DcalcAPIndex idx_min = corner->dcalcAnalysisPtIndex(MinMax::min());
DcalcAPIndex idx_max = corner->dcalcAnalysisPtIndex(MinMax::max());
EXPECT_GE(idx_min, 0);
EXPECT_GE(idx_max, 0);
}
TEST_F(StaInitTest, CornerFindPathAp) {
Scene *corner = sta_->cmdScene();
size_t idx_min = corner->pathIndex(MinMax::min());
size_t idx_max = corner->pathIndex(MinMax::max());
EXPECT_GE(idx_min, 0u);
EXPECT_GE(idx_max, 0u);
}
// Tag and path count operations
TEST_F(StaInitTest, TagCount) {
TagIndex count = sta_->tagCount();
EXPECT_EQ(count, 0);
}
TEST_F(StaInitTest, TagGroupCount) {
TagGroupIndex count = sta_->tagGroupCount();
EXPECT_EQ(count, 0);
}
TEST_F(StaInitTest, ClkInfoCount) {
int count = sta_->clkInfoCount();
EXPECT_EQ(count, 0);
}
// pathCount() requires search to be initialized with a design
// so skip this test without design
// Units access
TEST_F(StaInitTest, UnitsAccess) {
Units *units = sta_->units();
EXPECT_NE(units, nullptr);
}
// Report access
TEST_F(StaInitTest, ReportAccess) {
Report *report = sta_->report();
EXPECT_NE(report, nullptr);
}
// Debug access
TEST_F(StaInitTest, DebugAccess) {
Debug *debug = sta_->debug();
EXPECT_NE(debug, nullptr);
}
// Sdc operations
TEST_F(StaInitTest, SdcSetWireloadMode) {
Sdc *sdc = sta_->cmdSdc();
ASSERT_NE(sdc, nullptr);
sta_->setWireloadMode(WireloadMode::top, sta_->cmdSdc());
EXPECT_EQ(sdc->wireloadMode(), WireloadMode::top);
sta_->setWireloadMode(WireloadMode::enclosed, sta_->cmdSdc());
EXPECT_EQ(sdc->wireloadMode(), WireloadMode::enclosed);
sta_->setWireloadMode(WireloadMode::segmented, sta_->cmdSdc());
EXPECT_EQ(sdc->wireloadMode(), WireloadMode::segmented);
}
TEST_F(StaInitTest, SdcClockGatingCheck) {
Sdc *sdc = sta_->cmdSdc();
ASSERT_NE(sdc, nullptr);
sta_->setClockGatingCheck(RiseFallBoth::riseFall(),
SetupHold::max(),
1.0,
sta_->cmdSdc());
bool exists = false;
float margin = 0.0f;
sdc->clockGatingMargin(RiseFall::rise(), SetupHold::max(), exists, margin);
EXPECT_TRUE(exists);
EXPECT_FLOAT_EQ(margin, 1.0f);
}
// Delay calculator name
TEST_F(StaInitTest, SetArcDelayCalc) {
ASSERT_NO_THROW(sta_->setArcDelayCalc("unit"));
ASSERT_NO_THROW(sta_->setArcDelayCalc("lumped_cap"));
}
// RemoveClockGroupsNull removed — nullptr now throws std::logic_error
// FindReportPathField
TEST_F(StaInitTest, FindReportPathField) {
ReportField *field = sta_->findReportPathField("fanout");
EXPECT_NE(field, nullptr);
field = sta_->findReportPathField("capacitance");
EXPECT_NE(field, nullptr);
field = sta_->findReportPathField("slew");
EXPECT_NE(field, nullptr);
field = sta_->findReportPathField("nonexistent");
EXPECT_EQ(field, nullptr);
}
// ReportPath object exists
TEST_F(StaInitTest, ReportPathExists) {
EXPECT_NE(sta_->reportPath(), nullptr);
}
// Power object exists
TEST_F(StaInitTest, PowerExists) {
EXPECT_NE(sta_->power(), nullptr);
}
// OperatingConditions
TEST_F(StaInitTest, OperatingConditionsNull) {
// Without liberty, operating conditions should be null
const OperatingConditions *op_min = sta_->operatingConditions(MinMax::min(), sta_->cmdSdc());
const OperatingConditions *op_max = sta_->operatingConditions(MinMax::max(), sta_->cmdSdc());
EXPECT_EQ(op_min, nullptr);
EXPECT_EQ(op_max, nullptr);
}
// Delete parasitics on empty design
TEST_F(StaInitTest, DeleteParasiticsEmpty) {
ASSERT_NO_THROW(sta_->deleteParasitics());
EXPECT_NE(sta_->network(), nullptr);
}
// Remove net load caps on empty design
TEST_F(StaInitTest, RemoveNetLoadCapsEmpty) {
ASSERT_NO_THROW(sta_->removeNetLoadCaps(sta_->cmdSdc()));
EXPECT_NE(sta_->network(), nullptr);
}
// Remove delay/slew annotations on empty design
TEST_F(StaInitTest, RemoveDelaySlewAnnotationsEmpty) {
ASSERT_NO_THROW(sta_->removeDelaySlewAnnotations());
EXPECT_NE(sta_->network(), nullptr);
}
// Delays invalid (should not crash on empty design)
TEST_F(StaInitTest, DelaysInvalidEmpty) {
ASSERT_NO_THROW(sta_->delaysInvalid());
EXPECT_NE(sta_->search(), nullptr);
}
// Arrivals invalid (should not crash on empty design)
TEST_F(StaInitTest, ArrivalsInvalidEmpty) {
ASSERT_NO_THROW(sta_->arrivalsInvalid());
EXPECT_NE(sta_->search(), nullptr);
}
// Network changed (should not crash on empty design)
TEST_F(StaInitTest, NetworkChangedEmpty) {
ASSERT_NO_THROW(sta_->networkChanged());
EXPECT_NE(sta_->network(), nullptr);
}
// Clk pins invalid (should not crash on empty design)
TEST_F(StaInitTest, ClkPinsInvalidEmpty) {
// clkPinsInvalid requires a linked network; expect throw without one
ASSERT_ANY_THROW(sta_->clkPinsInvalid(sta_->cmdMode()));
EXPECT_NE(sta_->search(), nullptr);
}
// UpdateComponentsState
TEST_F(StaInitTest, UpdateComponentsState) {
ASSERT_NO_THROW(sta_->updateComponentsState());
EXPECT_NE(sta_->cmdSdc(), nullptr);
}
// set_min_pulse_width without pin/clock/instance
TEST_F(StaInitTest, SetMinPulseWidth) {
Sdc *sdc = sta_->cmdSdc();
ASSERT_NE(sdc, nullptr);
sta_->setMinPulseWidth(RiseFallBoth::rise(), 0.5, sta_->cmdSdc());
sta_->setMinPulseWidth(RiseFallBoth::fall(), 0.3, sta_->cmdSdc());
sta_->setMinPulseWidth(RiseFallBoth::riseFall(), 0.4, sta_->cmdSdc());
float min_width = 0.0f;
bool exists = false;
sdc->minPulseWidth(nullptr, nullptr, RiseFall::rise(), min_width, exists);
EXPECT_TRUE(exists);
EXPECT_FLOAT_EQ(min_width, 0.4f);
sdc->minPulseWidth(nullptr, nullptr, RiseFall::fall(), min_width, exists);
EXPECT_TRUE(exists);
EXPECT_FLOAT_EQ(min_width, 0.4f);
}
// set_timing_derate global
TEST_F(StaInitTest, SetTimingDerateGlobal) {
ASSERT_NO_THROW((sta_->setTimingDerate(TimingDerateType::cell_delay,
PathClkOrData::clk,
RiseFallBoth::riseFall(),
EarlyLate::early(),
0.95,
sta_->cmdSdc())));
ASSERT_NO_THROW((sta_->setTimingDerate(TimingDerateType::net_delay,
PathClkOrData::data,
RiseFallBoth::riseFall(),
EarlyLate::late(),
1.05,
sta_->cmdSdc())));
ASSERT_NO_THROW(sta_->unsetTimingDerate(sta_->cmdSdc()));
}
// Variables propagate all clocks via Sta
TEST_F(StaInitTest, StaPropagateAllClocksViaVariables) {
Variables *vars = sta_->variables();
vars->setPropagateAllClocks(true);
EXPECT_TRUE(vars->propagateAllClocks());
vars->setPropagateAllClocks(false);
EXPECT_FALSE(vars->propagateAllClocks());
}
// Sdc derating factors
TEST_F(StaInitTest, SdcDeratingFactors) {
Sdc *sdc = sta_->cmdSdc();
ASSERT_NE(sdc, nullptr);
ASSERT_NO_THROW((sdc->setTimingDerate(TimingDerateType::cell_delay,
PathClkOrData::clk,
RiseFallBoth::riseFall(),
EarlyLate::early(),
0.9)));
ASSERT_NO_THROW(sdc->unsetTimingDerate());
}
// Sdc clock gating check global
TEST_F(StaInitTest, SdcClockGatingCheckGlobal) {
Sdc *sdc = sta_->cmdSdc();
ASSERT_NE(sdc, nullptr);
sdc->setClockGatingCheck(RiseFallBoth::riseFall(),
SetupHold::max(),
0.5);
sdc->setClockGatingCheck(RiseFallBoth::riseFall(),
SetupHold::min(),
0.3);
bool exists = false;
float margin = 0.0f;
sdc->clockGatingMargin(RiseFall::rise(), SetupHold::max(), exists, margin);
EXPECT_TRUE(exists);
EXPECT_FLOAT_EQ(margin, 0.5f);
sdc->clockGatingMargin(RiseFall::fall(), SetupHold::min(), exists, margin);
EXPECT_TRUE(exists);
EXPECT_FLOAT_EQ(margin, 0.3f);
}
// Sdc max area
TEST_F(StaInitTest, SdcSetMaxArea) {
Sdc *sdc = sta_->cmdSdc();
ASSERT_NE(sdc, nullptr);
sdc->setMaxArea(50.0);
EXPECT_FLOAT_EQ(sdc->maxArea(), 50.0f);
}
// Sdc wireload mode
TEST_F(StaInitTest, SdcSetWireloadModeDir) {
Sdc *sdc = sta_->cmdSdc();
ASSERT_NE(sdc, nullptr);
sdc->setWireloadMode(WireloadMode::top);
EXPECT_EQ(sdc->wireloadMode(), WireloadMode::top);
sdc->setWireloadMode(WireloadMode::enclosed);
EXPECT_EQ(sdc->wireloadMode(), WireloadMode::enclosed);
}
// Sdc min pulse width
TEST_F(StaInitTest, SdcSetMinPulseWidth) {
Sdc *sdc = sta_->cmdSdc();
ASSERT_NE(sdc, nullptr);
sdc->setMinPulseWidth(RiseFallBoth::rise(), 0.1);
sdc->setMinPulseWidth(RiseFallBoth::fall(), 0.2);
float min_width = 0.0f;
bool exists = false;
sdc->minPulseWidth(nullptr, nullptr, RiseFall::rise(), min_width, exists);
EXPECT_TRUE(exists);
EXPECT_FLOAT_EQ(min_width, 0.1f);
sdc->minPulseWidth(nullptr, nullptr, RiseFall::fall(), min_width, exists);
EXPECT_TRUE(exists);
EXPECT_FLOAT_EQ(min_width, 0.2f);
}
// Sdc clear
TEST_F(StaInitTest, SdcClear) {
Sdc *sdc = sta_->cmdSdc();
ASSERT_NE(sdc, nullptr);
sdc->setMaxArea(75.0f);
sdc->setWireloadMode(WireloadMode::segmented);
sdc->clear();
EXPECT_FLOAT_EQ(sdc->maxArea(), 75.0f);
EXPECT_EQ(sdc->wireloadMode(), WireloadMode::segmented);
EXPECT_NE(sdc->defaultArrivalClock(), nullptr);
EXPECT_NE(sdc->defaultArrivalClockEdge(), nullptr);
}
// SceneSeq copy
TEST_F(StaInitTest, CornersCopy) {
const SceneSeq &corners = sta_->scenes();
SceneSeq corners2(corners);
EXPECT_EQ(corners2.size(), corners.size());
}
// SceneSeq clear
TEST_F(StaInitTest, CornersClear) {
SceneSeq corners;
corners.clear();
EXPECT_EQ(corners.size(), 0u);
}
// AnalysisType changed notification
TEST_F(StaInitTest, AnalysisTypeChanged) {
sta_->setAnalysisType(AnalysisType::bc_wc, sta_->cmdSdc());
// SceneSeq should reflect the analysis type change
const SceneSeq &corners = sta_->scenes();
EXPECT_GE(corners.size(), 1u);
}
// ParasiticAnalysisPts
TEST_F(StaInitTest, ParasiticAnalysisPts) {
const SceneSeq &corners = sta_->scenes();
// ParasiticAnalysisPtSeq removed; SceneSeq is now std::vector<Scene*>
EXPECT_FALSE(corners.empty());
}
// DcalcAnalysisPts
TEST_F(StaInitTest, DcalcAnalysisPts) {
const SceneSeq &corners = sta_->scenes();
// dcalcAnalysisPts removed; SceneSeq is now std::vector<Scene*>
EXPECT_FALSE(corners.empty());
}
// PathAnalysisPts
TEST_F(StaInitTest, PathAnalysisPts) {
const SceneSeq &corners = sta_->scenes();
// pathAnalysisPts removed; SceneSeq is now std::vector<Scene*>
EXPECT_FALSE(corners.empty());
}
// FindPathAnalysisPt
TEST_F(StaInitTest, FindPathAnalysisPt) {
Scene *corner = sta_->cmdScene();
size_t ap = corner->pathIndex(MinMax::min());
// pathIndex returns a size_t index, not a pointer
EXPECT_GE(ap, 0u);
}
// AnalysisType toggle exercises different code paths in Sta.cc
TEST_F(StaInitTest, AnalysisTypeFullCycle) {
// Start with single
sta_->setAnalysisType(AnalysisType::single, sta_->cmdSdc());
EXPECT_EQ(sta_->cmdSdc()->analysisType(), AnalysisType::single);
// Switch to bc_wc - exercises Corners::analysisTypeChanged()
sta_->setAnalysisType(AnalysisType::bc_wc, sta_->cmdSdc());
EXPECT_EQ(sta_->cmdSdc()->analysisType(), AnalysisType::bc_wc);
// Verify corners adjust
EXPECT_GE(sta_->scenes().size() * 2, 2);
// Switch to OCV
sta_->setAnalysisType(AnalysisType::ocv, sta_->cmdSdc());
EXPECT_EQ(sta_->cmdSdc()->analysisType(), AnalysisType::ocv);
EXPECT_GE(sta_->scenes().size() * 2, 2);
// Back to single
sta_->setAnalysisType(AnalysisType::single, sta_->cmdSdc());
EXPECT_EQ(sta_->cmdSdc()->analysisType(), AnalysisType::single);
}
// MakeCorners with single name
TEST_F(StaInitTest, MakeCornersSingle) {
StringSeq names;
names.push_back("typical");
sta_->makeScenes(names);
Scene *c = sta_->findScene("typical");
EXPECT_NE(c, nullptr);
EXPECT_EQ(c->name(), "typical");
EXPECT_EQ(c->index(), 0);
}
// MakeCorners then iterate
TEST_F(StaInitTest, MakeCornersIterate) {
StringSeq names;
names.push_back("fast");
names.push_back("slow");
names.push_back("typical");
sta_->makeScenes(names);
int count = 0;
for (Scene *scene : sta_->scenes()) {
EXPECT_NE(scene, nullptr);
EXPECT_FALSE(scene->name().empty());
count++;
}
EXPECT_EQ(count, 3);
}
// All derate types
TEST_F(StaInitTest, AllDerateTypes) {
// cell_delay clk early
sta_->setTimingDerate(TimingDerateType::cell_delay,
PathClkOrData::clk,
RiseFallBoth::rise(),
EarlyLate::early(), 0.95, sta_->cmdSdc());
// cell_delay data late
sta_->setTimingDerate(TimingDerateType::cell_delay,
PathClkOrData::data,
RiseFallBoth::fall(),
EarlyLate::late(), 1.05, sta_->cmdSdc());
// cell_check clk early
sta_->setTimingDerate(TimingDerateType::cell_check,
PathClkOrData::clk,
RiseFallBoth::riseFall(),
EarlyLate::early(), 0.97, sta_->cmdSdc());
// net_delay data late
sta_->setTimingDerate(TimingDerateType::net_delay,
PathClkOrData::data,
RiseFallBoth::riseFall(),
EarlyLate::late(), 1.03, sta_->cmdSdc());
sta_->unsetTimingDerate(sta_->cmdSdc());
}
// Comprehensive Variables exercise
TEST_F(StaInitTest, VariablesComprehensive) {
Variables *vars = sta_->variables();
// CRPR
vars->setCrprEnabled(true);
EXPECT_TRUE(vars->crprEnabled());
vars->setCrprMode(CrprMode::same_pin);
EXPECT_EQ(vars->crprMode(), CrprMode::same_pin);
vars->setCrprMode(CrprMode::same_transition);
EXPECT_EQ(vars->crprMode(), CrprMode::same_transition);
// POCV mode
vars->setPocvMode(PocvMode::normal);
EXPECT_EQ(vars->pocvMode(), PocvMode::normal);
vars->setPocvMode(PocvMode::scalar);
EXPECT_EQ(vars->pocvMode(), PocvMode::scalar);
// Gate clk propagation
vars->setPropagateGatedClockEnable(true);
EXPECT_TRUE(vars->propagateGatedClockEnable());
// Preset/clear arcs
vars->setPresetClrArcsEnabled(true);
EXPECT_TRUE(vars->presetClrArcsEnabled());
// Cond default arcs
vars->setCondDefaultArcsEnabled(true);
EXPECT_TRUE(vars->condDefaultArcsEnabled());
// Bidirect paths
vars->setBidirectInstPathsEnabled(true);
EXPECT_TRUE(vars->bidirectInstPathsEnabled());
// bidirectInstPathsEnabled has been removed from Variables
// Recovery/removal
vars->setRecoveryRemovalChecksEnabled(true);
EXPECT_TRUE(vars->recoveryRemovalChecksEnabled());
// Gated clk checks
vars->setGatedClkChecksEnabled(true);
EXPECT_TRUE(vars->gatedClkChecksEnabled());
// Dynamic loop breaking
vars->setDynamicLoopBreaking(true);
EXPECT_TRUE(vars->dynamicLoopBreaking());
// Propagate all clocks
vars->setPropagateAllClocks(true);
EXPECT_TRUE(vars->propagateAllClocks());
// Clk through tristate
vars->setClkThruTristateEnabled(true);
EXPECT_TRUE(vars->clkThruTristateEnabled());
// Default arrival clock
vars->setUseDefaultArrivalClock(true);
EXPECT_TRUE(vars->useDefaultArrivalClock());
}
// Clock creation with comment
TEST_F(StaInitTest, MakeClockWithComment) {
FloatSeq *waveform = new FloatSeq;
waveform->push_back(0.0);
waveform->push_back(5.0);
char *comment = new char[20];
strcpy(comment, "test clock");
sta_->makeClock("cmt_clk", PinSet(), false, 10.0, *waveform, comment, sta_->cmdMode());
Sdc *sdc = sta_->cmdSdc();
Clock *clk = sdc->findClock("cmt_clk");
EXPECT_NE(clk, nullptr);
}
// Make false path exercises ExceptionPath creation in Sta.cc
TEST_F(StaInitTest, MakeFalsePath) {
sta_->makeFalsePath(nullptr, nullptr, nullptr, MinMaxAll::all(), "", sta_->cmdSdc());
}
// Make group path
TEST_F(StaInitTest, MakeGroupPath) {
sta_->makeGroupPath("test_grp", false, nullptr, nullptr, nullptr, "", sta_->cmdSdc());
EXPECT_TRUE(sta_->isPathGroupName("test_grp", sta_->cmdSdc()));
}
// Make path delay
TEST_F(StaInitTest, MakePathDelay) {
sta_->makePathDelay(nullptr, nullptr, nullptr,
MinMax::max(),
false, // ignore_clk_latency
false, // break_path
5.0, // delay
"", sta_->cmdSdc());
}
// MakeMulticyclePath
TEST_F(StaInitTest, MakeMulticyclePath) {
sta_->makeMulticyclePath(nullptr, nullptr, nullptr,
MinMaxAll::max(),
true, // use_end_clk
2, // path_multiplier
"", sta_->cmdSdc());
}
// Reset path
TEST_F(StaInitTest, ResetPath) {
sta_->resetPath(nullptr, nullptr, nullptr, MinMaxAll::all(), sta_->cmdSdc());
}
// Set voltage
TEST_F(StaInitTest, SetVoltage) {
sta_->setVoltage(MinMax::max(), 1.1, sta_->cmdSdc());
sta_->setVoltage(MinMax::min(), 0.9, sta_->cmdSdc());
}
// Report path field order
TEST_F(StaInitTest, SetReportPathFieldOrder) {
StringSeq field_names;
field_names.push_back("fanout");
field_names.push_back("capacitance");
field_names.push_back("slew");
field_names.push_back("delay");
field_names.push_back("time");
sta_->setReportPathFieldOrder(field_names);
}
// Sdc removeNetLoadCaps
TEST_F(StaInitTest, SdcRemoveNetLoadCaps) {
Sdc *sdc = sta_->cmdSdc();
sdc->removeNetLoadCaps();
}
// Sdc findClock nonexistent
TEST_F(StaInitTest, SdcFindClockNonexistent) {
Sdc *sdc = sta_->cmdSdc();
EXPECT_EQ(sdc->findClock("no_such_clock"), nullptr);
}
// CornerFindByIndex
TEST_F(StaInitTest, CornerFindByIndex) {
const SceneSeq &corners = sta_->scenes();
EXPECT_FALSE(corners.empty());
Scene *c = corners[0];
EXPECT_NE(c, nullptr);
EXPECT_EQ(c->index(), 0);
}
// Parasitic analysis point per corner
TEST_F(StaInitTest, ParasiticApPerCorner) {
// setParasiticAnalysisPts removed from API
// parasiticAnalysisPtCount removed from API
// Just verify scenes exist (parasitic APs are per-scene now)
EXPECT_GE(sta_->scenes().size(), 1u);
}
// StaState::crprActive exercises the crpr check logic
TEST_F(StaInitTest, CrprActiveCheck) {
// With OCV + crpr enabled, crprActive should be true
sta_->setAnalysisType(AnalysisType::ocv, sta_->cmdSdc());
sta_->setCrprEnabled(true);
EXPECT_TRUE(sta_->crprActive(sta_->cmdMode()));
// With single analysis, crprActive should be false
sta_->setAnalysisType(AnalysisType::single, sta_->cmdSdc());
EXPECT_FALSE(sta_->crprActive(sta_->cmdMode()));
// With OCV but crpr disabled, should be false
sta_->setAnalysisType(AnalysisType::ocv, sta_->cmdSdc());
sta_->setCrprEnabled(false);
EXPECT_FALSE(sta_->crprActive(sta_->cmdMode()));
}
// StaState::setReport and setDebug
TEST_F(StaInitTest, StaStateSetReportDebug) {
StaState state;
Report *report = sta_->report();
Debug *debug = sta_->debug();
state.setReport(report);
state.setDebug(debug);
EXPECT_EQ(state.report(), report);
EXPECT_EQ(state.debug(), debug);
}
// StaState::copyUnits
TEST_F(StaInitTest, StaStateCopyUnits) {
// copyUnits copies unit values from one Units to another
Units *units = sta_->units();
EXPECT_NE(units, nullptr);
// Create a StaState from sta_ so it has units
StaState state(sta_);
EXPECT_NE(state.units(), nullptr);
}
// StaState const networkEdit
TEST_F(StaInitTest, StaStateConstNetworkEdit) {
const StaState *const_sta = static_cast<const StaState*>(sta_);
NetworkEdit *ne = const_sta->networkEdit();
EXPECT_NE(ne, nullptr);
}
// StaState const networkReader
TEST_F(StaInitTest, StaStateConstNetworkReader) {
const StaState *const_sta = static_cast<const StaState*>(sta_);
NetworkReader *nr = const_sta->networkReader();
EXPECT_NE(nr, nullptr);
}
// PathAnalysisPt::to_string
TEST_F(StaInitTest, PathAnalysisPtToString) {
// pathIndex returns a size_t index, not a PathAnalysisPt pointer
Scene *corner = sta_->cmdScene();
size_t idx = corner->pathIndex(MinMax::min());
EXPECT_GE(idx, 0u);
}
// PathAnalysisPt corner
TEST_F(StaInitTest, PathAnalysisPtCorner) {
// pathIndex returns a size_t index, not a pointer
Scene *corner = sta_->cmdScene();
EXPECT_NE(corner, nullptr);
EXPECT_EQ(corner->name(), "default");
}
// PathAnalysisPt pathMinMax
TEST_F(StaInitTest, PathAnalysisPtPathMinMax) {
// pathIndex returns a size_t index
Scene *corner = sta_->cmdScene();
size_t idx = corner->pathIndex(MinMax::min());
EXPECT_GE(idx, 0u);
}
// PathAnalysisPt dcalcAnalysisPt
TEST_F(StaInitTest, PathAnalysisPtDcalcAp) {
// dcalcAnalysisPtIndex returns a DcalcAPIndex
Scene *corner = sta_->cmdScene();
DcalcAPIndex idx = corner->dcalcAnalysisPtIndex(MinMax::min());
EXPECT_GE(idx, 0);
}
// PathAnalysisPt index
TEST_F(StaInitTest, PathAnalysisPtIndex) {
Scene *corner = sta_->cmdScene();
size_t idx = corner->pathIndex(MinMax::min());
EXPECT_GE(idx, 0u);
}
// PathAnalysisPt tgtClkAnalysisPt
TEST_F(StaInitTest, PathAnalysisPtTgtClkAp) {
// pathIndex returns a size_t index
Scene *corner = sta_->cmdScene();
size_t idx = corner->pathIndex(MinMax::min());
EXPECT_GE(idx, 0u);
}
// PathAnalysisPt insertionAnalysisPt
TEST_F(StaInitTest, PathAnalysisPtInsertionAp) {
// pathIndex returns a size_t index
Scene *corner = sta_->cmdScene();
size_t idx = corner->pathIndex(MinMax::min());
EXPECT_GE(idx, 0u);
}
// DcalcAnalysisPt properties
TEST_F(StaInitTest, DcalcAnalysisPtProperties) {
Scene *corner = sta_->cmdScene();
DcalcAPIndex ap = corner->dcalcAnalysisPtIndex(MinMax::max());
EXPECT_GE(ap, 0);
}
// Corner parasiticAnalysisPt
TEST_F(StaInitTest, CornerParasiticAnalysisPt) {
Scene *corner = sta_->cmdScene();
// findParasiticAnalysisPt removed; use parasitics() instead
EXPECT_NE(corner, nullptr);
}
// SigmaFactorViaStaState test removed: setSigmaFactor/sigmaFactor API removed
// ThreadCount through StaState
TEST_F(StaInitTest, ThreadCountStaState) {
sta_->setThreadCount(4);
EXPECT_EQ(sta_->threadCount(), 4);
sta_->setThreadCount(1);
EXPECT_EQ(sta_->threadCount(), 1);
}
////////////////////////////////////////////////////////////////
// Additional coverage tests for search module uncovered functions
////////////////////////////////////////////////////////////////
// Sta.cc uncovered functions - more SDC/search methods
TEST_F(StaInitTest, SdcAccessForBorrowLimit) {
Sdc *sdc = sta_->cmdSdc();
EXPECT_NE(sdc, nullptr);
}
TEST_F(StaInitTest, DefaultThreadCountValue) {
int count = sta_->defaultThreadCount();
EXPECT_GE(count, 1);
}
TEST_F(StaInitTest, CmdNamespaceSet) {
sta_->setCmdNamespace(CmdNamespace::sdc);
EXPECT_EQ(sta_->cmdNamespace(), CmdNamespace::sdc);
sta_->setCmdNamespace(CmdNamespace::sta);
EXPECT_EQ(sta_->cmdNamespace(), CmdNamespace::sta);
}
TEST_F(StaInitTest, EquivCellsNullCell) {
LibertyCellSeq *equiv = sta_->equivCells(nullptr);
EXPECT_EQ(equiv, nullptr);
}
// Search.cc uncovered functions
TEST_F(StaInitTest, SearchCrprPathPruning) {
Search *search = sta_->search();
EXPECT_NE(search, nullptr);
bool orig = search->crprPathPruningEnabled();
search->setCrprpathPruningEnabled(!orig);
EXPECT_NE(search->crprPathPruningEnabled(), orig);
search->setCrprpathPruningEnabled(orig);
}
TEST_F(StaInitTest, SearchCrprApproxMissing) {
Search *search = sta_->search();
bool orig = search->crprApproxMissingRequireds();
search->setCrprApproxMissingRequireds(!orig);
EXPECT_NE(search->crprApproxMissingRequireds(), orig);
search->setCrprApproxMissingRequireds(orig);
}
TEST_F(StaInitTest, SearchUnconstrainedPaths) {
Search *search = sta_->search();
EXPECT_FALSE(search->unconstrainedPaths());
}
TEST_F(StaInitTest, SearchFilter) {
Search *search = sta_->search();
// filter() removed from Search API
EXPECT_NE(search, nullptr);
}
TEST_F(StaInitTest, SearchDeleteFilter) {
Search *search = sta_->search();
search->deleteFilter();
EXPECT_NE(search, nullptr);
}
TEST_F(StaInitTest, SearchDeletePathGroups) {
Search *search = sta_->search();
search->deletePathGroups();
EXPECT_NE(search, nullptr);
}
TEST_F(StaInitTest, SearchHavePathGroups) {
Search *search = sta_->search();
// havePathGroups removed from Search API
EXPECT_NE(search, nullptr);
}
TEST_F(StaInitTest, SearchEndpoints) {
Search *search = sta_->search();
ASSERT_NE(search, nullptr);
EXPECT_EQ(sta_->graph(), nullptr);
EXPECT_THROW(sta_->ensureGraph(), std::exception);
}
TEST_F(StaInitTest, SearchRequiredsSeeded) {
Search *search = sta_->search();
EXPECT_FALSE(search->requiredsSeeded());
}
TEST_F(StaInitTest, SearchRequiredsExist) {
Search *search = sta_->search();
EXPECT_FALSE(search->requiredsExist());
}
TEST_F(StaInitTest, SearchArrivalsAtEndpointsExist) {
Search *search = sta_->search();
// arrivalsAtEndpointsExist removed from Search API
EXPECT_NE(search, nullptr);
}
TEST_F(StaInitTest, SearchTagCount) {
Search *search = sta_->search();
TagIndex count = search->tagCount();
EXPECT_EQ(count, 0u);
}
TEST_F(StaInitTest, SearchTagGroupCount) {
Search *search = sta_->search();
TagGroupIndex count = search->tagGroupCount();
EXPECT_EQ(count, 0u);
}
TEST_F(StaInitTest, SearchClkInfoCount) {
Search *search = sta_->search();
int count = search->clkInfoCount();
EXPECT_EQ(count, 0);
}
TEST_F(StaInitTest, SearchEvalPred) {
Search *search = sta_->search();
ASSERT_NE(search, nullptr);
EXPECT_NE(search->evalPred(), nullptr);
}
TEST_F(StaInitTest, SearchSearchAdj) {
Search *search = sta_->search();
ASSERT_NE(search, nullptr);
EXPECT_NE(search->searchAdj(), nullptr);
}
TEST_F(StaInitTest, SearchClear) {
Search *search = sta_->search();
search->clear();
EXPECT_NE(search, nullptr);
}
TEST_F(StaInitTest, SearchArrivalsInvalid) {
Search *search = sta_->search();
search->arrivalsInvalid();
// No crash
}
TEST_F(StaInitTest, SearchRequiredsInvalid) {
Search *search = sta_->search();
search->requiredsInvalid();
// No crash
}
TEST_F(StaInitTest, SearchEndpointsInvalid) {
Search *search = sta_->search();
search->endpointsInvalid();
// No crash
}
TEST_F(StaInitTest, SearchVisitPathEnds) {
Search *search = sta_->search();
VisitPathEnds *vpe = search->visitPathEnds();
EXPECT_NE(vpe, nullptr);
}
TEST_F(StaInitTest, SearchGatedClk) {
Search *search = sta_->search();
GatedClk *gated = search->gatedClk();
EXPECT_NE(gated, nullptr);
}
TEST_F(StaInitTest, SearchGenclks) {
Mode *mode = sta_->cmdMode();
Genclks *genclks = mode->genclks();
EXPECT_NE(genclks, nullptr);
}
TEST_F(StaInitTest, SearchCheckCrpr) {
Search *search = sta_->search();
CheckCrpr *crpr = search->checkCrpr();
EXPECT_NE(crpr, nullptr);
}
TEST_F(StaInitTest, SearchCopyState) {
Search *search = sta_->search();
search->copyState(sta_);
// No crash
}
// ReportPath.cc uncovered functions
TEST_F(StaInitTest, ReportPathFormat) {
ReportPath *rpt = sta_->reportPath();
EXPECT_NE(rpt, nullptr);
rpt->setPathFormat(ReportPathFormat::full);
EXPECT_EQ(rpt->pathFormat(), ReportPathFormat::full);
rpt->setPathFormat(ReportPathFormat::full_clock);
EXPECT_EQ(rpt->pathFormat(), ReportPathFormat::full_clock);
rpt->setPathFormat(ReportPathFormat::full_clock_expanded);
EXPECT_EQ(rpt->pathFormat(), ReportPathFormat::full_clock_expanded);
rpt->setPathFormat(ReportPathFormat::shorter);
EXPECT_EQ(rpt->pathFormat(), ReportPathFormat::shorter);
rpt->setPathFormat(ReportPathFormat::endpoint);
EXPECT_EQ(rpt->pathFormat(), ReportPathFormat::endpoint);
rpt->setPathFormat(ReportPathFormat::summary);
EXPECT_EQ(rpt->pathFormat(), ReportPathFormat::summary);
rpt->setPathFormat(ReportPathFormat::slack_only);
EXPECT_EQ(rpt->pathFormat(), ReportPathFormat::slack_only);
rpt->setPathFormat(ReportPathFormat::json);
EXPECT_EQ(rpt->pathFormat(), ReportPathFormat::json);
}
TEST_F(StaInitTest, ReportPathFindField) {
ReportPath *rpt = sta_->reportPath();
ReportField *field_fanout = rpt->findField("fanout");
EXPECT_NE(field_fanout, nullptr);
ReportField *field_slew = rpt->findField("slew");
EXPECT_NE(field_slew, nullptr);
ReportField *field_cap = rpt->findField("capacitance");
EXPECT_NE(field_cap, nullptr);
ReportField *field_none = rpt->findField("does_not_exist");
EXPECT_EQ(field_none, nullptr);
}
TEST_F(StaInitTest, ReportPathDigitsGetSet) {
ReportPath *rpt = sta_->reportPath();
rpt->setDigits(3);
EXPECT_EQ(rpt->digits(), 3);
rpt->setDigits(6);
EXPECT_EQ(rpt->digits(), 6);
}
TEST_F(StaInitTest, ReportPathNoSplit) {
ReportPath *rpt = sta_->reportPath();
rpt->setNoSplit(true);
rpt->setNoSplit(false);
}
// ReportPathReportSigmas test removed: setReportSigmas/reportSigmas API removed
TEST_F(StaInitTest, ReportPathSetReportFields) {
ReportPath *rpt = sta_->reportPath();
rpt->setReportFields(kAllReportFields);
rpt->setReportFields(StringSeq{});
}
TEST_F(StaInitTest, ReportPathSetFieldOrder) {
ReportPath *rpt = sta_->reportPath();
StringSeq fields;
fields.push_back("fanout");
fields.push_back("capacitance");
fields.push_back("slew");
rpt->setReportFieldOrder(fields);
}
// PathEnd.cc static methods
TEST_F(StaInitTest, PathEndTypeValues) {
// Exercise PathEnd::Type enum values
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);
}
// Property.cc - PropertyValue additional types
TEST_F(StaInitTest, PropertyValuePinSeqConstructor) {
PinSeq *pins = new PinSeq;
PropertyValue pv(pins);
EXPECT_EQ(pv.type(), PropertyValue::Type::pins);
EXPECT_EQ(pv.pins(), pins);
}
TEST_F(StaInitTest, PropertyValueClockSeqConstructor) {
ClockSeq *clks = new ClockSeq;
PropertyValue pv(clks);
EXPECT_EQ(pv.type(), PropertyValue::Type::clks);
EXPECT_NE(pv.clocks(), nullptr);
}
TEST_F(StaInitTest, PropertyValueConstPathSeqConstructor) {
ConstPathSeq *paths = new ConstPathSeq;
PropertyValue pv(paths);
EXPECT_EQ(pv.type(), PropertyValue::Type::paths);
EXPECT_NE(pv.paths(), nullptr);
}
TEST_F(StaInitTest, PropertyValuePinSetConstructor) {
PinSet *pins = new PinSet;
PropertyValue pv(pins);
EXPECT_EQ(pv.type(), PropertyValue::Type::pins);
}
TEST_F(StaInitTest, PropertyValueClockSetConstructor) {
ClockSet *clks = new ClockSet;
PropertyValue pv(clks);
EXPECT_EQ(pv.type(), PropertyValue::Type::clks);
}
TEST_F(StaInitTest, PropertyValueCopyPinSeq) {
PinSeq *pins = new PinSeq;
PropertyValue pv1(pins);
PropertyValue pv2(pv1);
EXPECT_EQ(pv2.type(), PropertyValue::Type::pins);
}
TEST_F(StaInitTest, PropertyValueCopyClockSeq) {
ClockSeq *clks = new ClockSeq;
PropertyValue pv1(clks);
PropertyValue pv2(pv1);
EXPECT_EQ(pv2.type(), PropertyValue::Type::clks);
}
TEST_F(StaInitTest, PropertyValueCopyPaths) {
ConstPathSeq *paths = new ConstPathSeq;
PropertyValue pv1(paths);
PropertyValue pv2(pv1);
EXPECT_EQ(pv2.type(), PropertyValue::Type::paths);
}
TEST_F(StaInitTest, PropertyValueMovePinSeq) {
PinSeq *pins = new PinSeq;
PropertyValue pv1(pins);
PropertyValue pv2(std::move(pv1));
EXPECT_EQ(pv2.type(), PropertyValue::Type::pins);
}
TEST_F(StaInitTest, PropertyValueMoveClockSeq) {
ClockSeq *clks = new ClockSeq;
PropertyValue pv1(clks);
PropertyValue pv2(std::move(pv1));
EXPECT_EQ(pv2.type(), PropertyValue::Type::clks);
}
TEST_F(StaInitTest, PropertyValueMovePaths) {
ConstPathSeq *paths = new ConstPathSeq;
PropertyValue pv1(paths);
PropertyValue pv2(std::move(pv1));
EXPECT_EQ(pv2.type(), PropertyValue::Type::paths);
}
TEST_F(StaInitTest, PropertyValueCopyAssignPinSeq) {
PinSeq *pins = new PinSeq;
PropertyValue pv1(pins);
PropertyValue pv2;
pv2 = pv1;
EXPECT_EQ(pv2.type(), PropertyValue::Type::pins);
}
TEST_F(StaInitTest, PropertyValueCopyAssignClockSeq) {
ClockSeq *clks = new ClockSeq;
PropertyValue pv1(clks);
PropertyValue pv2;
pv2 = pv1;
EXPECT_EQ(pv2.type(), PropertyValue::Type::clks);
}
TEST_F(StaInitTest, PropertyValueCopyAssignPaths) {
ConstPathSeq *paths = new ConstPathSeq;
PropertyValue pv1(paths);
PropertyValue pv2;
pv2 = pv1;
EXPECT_EQ(pv2.type(), PropertyValue::Type::paths);
}
TEST_F(StaInitTest, PropertyValueMoveAssignPinSeq) {
PinSeq *pins = new PinSeq;
PropertyValue pv1(pins);
PropertyValue pv2;
pv2 = std::move(pv1);
EXPECT_EQ(pv2.type(), PropertyValue::Type::pins);
}
TEST_F(StaInitTest, PropertyValueMoveAssignClockSeq) {
ClockSeq *clks = new ClockSeq;
PropertyValue pv1(clks);
PropertyValue pv2;
pv2 = std::move(pv1);
EXPECT_EQ(pv2.type(), PropertyValue::Type::clks);
}
TEST_F(StaInitTest, PropertyValueMoveAssignPaths) {
ConstPathSeq *paths = new ConstPathSeq;
PropertyValue pv1(paths);
PropertyValue pv2;
pv2 = std::move(pv1);
EXPECT_EQ(pv2.type(), PropertyValue::Type::paths);
}
TEST_F(StaInitTest, PropertyValueUnitGetter) {
PropertyValue pv(1.0f, nullptr);
EXPECT_EQ(pv.unit(), nullptr);
}
TEST_F(StaInitTest, PropertyValueToStringBasic) {
PropertyValue pv_str(std::string("hello"));
Network *network = sta_->network();
std::string result = pv_str.to_string(network);
EXPECT_EQ(result, "hello");
}
TEST_F(StaInitTest, PropertyValueToStringBool) {
PropertyValue pv_true(true);
Network *network = sta_->network();
std::string result = pv_true.to_string(network);
EXPECT_EQ(result, "1");
PropertyValue pv_false(false);
result = pv_false.to_string(network);
EXPECT_EQ(result, "0");
}
TEST_F(StaInitTest, PropertyValueToStringNone) {
PropertyValue pv;
Network *network = sta_->network();
std::string result = pv.to_string(network);
// Empty or some representation
}
TEST_F(StaInitTest, PropertyValuePinSetRef) {
PinSet pins;
PropertyValue pv(pins);
EXPECT_EQ(pv.type(), PropertyValue::Type::pins);
}
// Properties class tests (exercise getProperty for different types)
TEST_F(StaInitTest, PropertiesExist) {
sta_->properties();
// Just access it
}
// Corner.cc uncovered functions
TEST_F(StaInitTest, CornerLibraryIndex) {
Scene *corner = sta_->cmdScene();
int idx_min = corner->libertyIndex(MinMax::min());
int idx_max = corner->libertyIndex(MinMax::max());
EXPECT_GE(idx_min, 0);
EXPECT_GE(idx_max, 0);
}
TEST_F(StaInitTest, CornerLibertyLibraries) {
Scene *corner = sta_->cmdScene();
const auto &libs_min = corner->libertyLibraries(MinMax::min());
const auto &libs_max = corner->libertyLibraries(MinMax::max());
// Without reading libs, these should be empty
EXPECT_TRUE(libs_min.empty());
EXPECT_TRUE(libs_max.empty());
}
TEST_F(StaInitTest, CornerParasiticAPAccess) {
Scene *corner = sta_->cmdScene();
// findParasiticAnalysisPt removed
EXPECT_NE(corner, nullptr);
}
TEST_F(StaInitTest, CornersMultiCorner) {
const SceneSeq &corners = sta_->scenes();
// multiScene is on Sta, not SceneSeq
EXPECT_GE(corners.size(), 1u);
}
TEST_F(StaInitTest, CornersParasiticAnalysisPtCount) {
const SceneSeq &corners = sta_->scenes();
// parasiticAnalysisPtCount removed from API
EXPECT_GE(corners.size(), 0u);
}
TEST_F(StaInitTest, CornersParasiticAnalysisPts) {
const SceneSeq &corners = sta_->scenes();
// parasiticAnalysisPts removed; SceneSeq is std::vector<Scene*>
EXPECT_GE(corners.size(), 0u);
}
TEST_F(StaInitTest, CornersDcalcAnalysisPtCount) {
const SceneSeq &corners = sta_->scenes();
// dcalcAnalysisPtCount removed; SceneSeq is std::vector<Scene*>
EXPECT_GE(corners.size(), 0u);
}
TEST_F(StaInitTest, CornersDcalcAnalysisPts) {
const SceneSeq &corners = sta_->scenes();
// dcalcAnalysisPts removed; SceneSeq is std::vector<Scene*>
EXPECT_GE(corners.size(), 0u);
}
TEST_F(StaInitTest, CornersPathAnalysisPtCount) {
const SceneSeq &corners = sta_->scenes();
// pathAnalysisPtCount removed; SceneSeq is std::vector<Scene*>
EXPECT_GE(corners.size(), 0u);
}
TEST_F(StaInitTest, CornersPathAnalysisPtsConst) {
const SceneSeq &corners = sta_->scenes();
// pathAnalysisPts removed; SceneSeq is std::vector<Scene*>
EXPECT_GE(corners.size(), 0u);
}
TEST_F(StaInitTest, CornersCornerSeq) {
const SceneSeq &corners = sta_->scenes();
EXPECT_GE(corners.size(), 1u);
}
TEST_F(StaInitTest, CornersBeginEnd) {
const SceneSeq &corners = sta_->scenes();
int count = 0;
for (auto it = corners.begin(); it != corners.end(); ++it) {
count++;
}
EXPECT_EQ(static_cast<size_t>(count), corners.size());
}
// Levelize.cc uncovered functions
TEST_F(StaInitTest, LevelizeNotLevelized) {
Levelize *levelize = sta_->levelize();
EXPECT_NE(levelize, nullptr);
// Without graph, should not be levelized
}
TEST_F(StaInitTest, LevelizeClear) {
Levelize *levelize = sta_->levelize();
levelize->clear();
// No crash
}
TEST_F(StaInitTest, LevelizeSetLevelSpace) {
Levelize *levelize = sta_->levelize();
levelize->setLevelSpace(5);
// No crash
}
TEST_F(StaInitTest, LevelizeMaxLevel) {
Levelize *levelize = sta_->levelize();
int max_level = levelize->maxLevel();
EXPECT_GE(max_level, 0);
}
TEST_F(StaInitTest, LevelizeLoops) {
Levelize *levelize = sta_->levelize();
auto &loops = levelize->loops();
EXPECT_TRUE(loops.empty());
}
// Sim.cc uncovered functions
TEST_F(StaInitTest, SimExists) {
Sim *sim = sta_->cmdMode()->sim();
EXPECT_NE(sim, nullptr);
}
TEST_F(StaInitTest, SimClear) {
Sim *sim = sta_->cmdMode()->sim();
sim->clear();
// No crash
}
TEST_F(StaInitTest, SimConstantsInvalid) {
Sim *sim = sta_->cmdMode()->sim();
sim->constantsInvalid();
// No crash
}
// Genclks uncovered functions
TEST_F(StaInitTest, GenclksExists) {
Mode *mode = sta_->cmdMode();
Genclks *genclks = mode->genclks();
EXPECT_NE(genclks, nullptr);
}
TEST_F(StaInitTest, GenclksClear) {
Mode *mode = sta_->cmdMode();
Genclks *genclks = mode->genclks();
genclks->clear();
// No crash
}
// ClkNetwork uncovered functions
TEST_F(StaInitTest, ClkNetworkExists) {
ClkNetwork *clk_network = sta_->cmdMode()->clkNetwork();
EXPECT_NE(clk_network, nullptr);
}
TEST_F(StaInitTest, ClkNetworkClear) {
ClkNetwork *clk_network = sta_->cmdMode()->clkNetwork();
clk_network->clear();
// No crash
}
TEST_F(StaInitTest, ClkNetworkClkPinsInvalid) {
ClkNetwork *clk_network = sta_->cmdMode()->clkNetwork();
clk_network->clkPinsInvalid();
// No crash
}
TEST_F(StaInitTest, StaEnsureClkNetwork) {
// ensureClkNetwork requires a linked network
EXPECT_THROW(sta_->ensureClkNetwork(sta_->cmdMode()), Exception);
}
TEST_F(StaInitTest, StaClkPinsInvalid) {
// clkPinsInvalid requires a linked network; expect throw without one
EXPECT_ANY_THROW(sta_->clkPinsInvalid(sta_->cmdMode()));
}
// WorstSlack uncovered functions
TEST_F(StaInitTest, WorstSlackNoDesignMinMax) {
// worstSlack requires a linked network
Slack worst_slack;
Vertex *worst_vertex;
EXPECT_THROW(sta_->worstSlack(MinMax::max(), worst_slack, worst_vertex), Exception);
}
// Path.cc uncovered functions - Path class
TEST_F(StaInitTest, PathDefaultConstructor) {
Path path;
EXPECT_TRUE(path.isNull());
}
TEST_F(StaInitTest, PathIsEnum) {
Path path;
EXPECT_FALSE(path.isEnum());
}
TEST_F(StaInitTest, PathSetIsEnum) {
Path path;
path.setIsEnum(true);
EXPECT_TRUE(path.isEnum());
path.setIsEnum(false);
EXPECT_FALSE(path.isEnum());
}
TEST_F(StaInitTest, PathArrivalSetGet) {
Path path;
path.setArrival(1.5);
EXPECT_FLOAT_EQ(path.arrival(), 1.5);
}
TEST_F(StaInitTest, PathRequiredSetGet) {
Path path;
Required req = 2.5;
path.setRequired(req);
EXPECT_FLOAT_EQ(path.required(), 2.5);
}
TEST_F(StaInitTest, PathPrevPathNull) {
Path path;
EXPECT_EQ(path.prevPath(), nullptr);
}
TEST_F(StaInitTest, PathSetPrevPath) {
Path path1;
Path path2;
path1.setPrevPath(&path2);
EXPECT_EQ(path1.prevPath(), &path2);
path1.setPrevPath(nullptr);
EXPECT_EQ(path1.prevPath(), nullptr);
}
TEST_F(StaInitTest, PathCopyConstructorNull) {
Path path1;
Path path2(&path1);
EXPECT_TRUE(path2.isNull());
}
// PathLess comparator
TEST_F(StaInitTest, PathLessComparator) {
PathLess less(sta_);
Path path1;
Path path2;
// Two null paths should compare consistently
// (don't dereference null tag)
}
// PathGroup static names
TEST_F(StaInitTest, PathGroupsStaticNames) {
EXPECT_FALSE(PathGroups::asyncPathGroupName().empty());
EXPECT_FALSE(PathGroups::pathDelayGroupName().empty());
EXPECT_FALSE(PathGroups::gatedClkGroupName().empty());
EXPECT_FALSE(PathGroups::unconstrainedGroupName().empty());
}
TEST_F(StaInitTest, PathGroupMaxPathsDefault) {
EXPECT_GT(PathGroup::group_path_count_max, 0u);
}
// PathEnum - DiversionGreater
TEST_F(StaInitTest, DiversionGreaterDefault) {
DiversionGreater dg;
// Default constructor - just exercise
}
TEST_F(StaInitTest, DiversionGreaterWithSta) {
DiversionGreater dg(sta_);
// Constructor with state - just exercise
}
// ClkSkew default constructor
TEST_F(StaInitTest, ClkSkewDefaultConstructor) {
ClkSkew skew;
EXPECT_FLOAT_EQ(skew.skew(), 0.0);
}
// ClkSkew copy constructor
TEST_F(StaInitTest, ClkSkewCopyConstructor) {
ClkSkew skew1;
ClkSkew skew2(skew1);
EXPECT_FLOAT_EQ(skew2.skew(), 0.0);
}
// ClkSkew assignment
TEST_F(StaInitTest, ClkSkewAssignment) {
ClkSkew skew1;
ClkSkew skew2;
skew2 = skew1;
EXPECT_FLOAT_EQ(skew2.skew(), 0.0);
}
// ClkSkew src/tgt path (should be null for default)
TEST_F(StaInitTest, ClkSkewPaths) {
ClkSkew skew;
EXPECT_EQ(skew.srcPath(), nullptr);
EXPECT_EQ(skew.tgtPath(), nullptr);
}
// CheckMaxSkews
TEST_F(StaInitTest, CheckMaxSkewsExists) {
// maxSkewSlack/maxSkewViolations removed from Sta API
// Verify CheckMaxSkews class is constructible
CheckMaxSkews checks(sta_);
checks.clear();
}
// CheckMinPeriods
TEST_F(StaInitTest, CheckMinPeriodsExists) {
// minPeriodSlack/minPeriodViolations removed from Sta API
// Verify CheckMinPeriods class is constructible
CheckMinPeriods checks(sta_);
checks.clear();
}
// CheckMinPulseWidths
TEST_F(StaInitTest, CheckMinPulseWidthsExists) {
// minPulseWidthSlack/minPulseWidthViolations/minPulseWidthChecks removed from Sta API
// Verify CheckMinPulseWidths class is constructible
CheckMinPulseWidths checks(sta_);
checks.clear();
}
TEST_F(StaInitTest, MinPulseWidthCheckDefault) {
MinPulseWidthCheck check;
// Default constructor, open_path_ is null
EXPECT_EQ(check.openPath(), nullptr);
}
// Tag helper classes
TEST_F(StaInitTest, TagHashConstructor) {
TagHash hasher(sta_);
// Just exercise constructor
}
TEST_F(StaInitTest, TagEqualConstructor) {
TagEqual eq(sta_);
// Just exercise constructor
}
TEST_F(StaInitTest, TagLessConstructor) {
TagLess less(sta_);
// Just exercise constructor
}
TEST_F(StaInitTest, TagIndexLessComparator) {
TagIndexLess less;
(void)less;
// Just exercise constructor
}
// ClkInfo helper classes
TEST_F(StaInitTest, ClkInfoLessConstructor) {
ClkInfoLess less(sta_);
// Just exercise constructor
}
TEST_F(StaInitTest, ClkInfoEqualConstructor) {
ClkInfoEqual eq(sta_);
// Just exercise constructor
}
// TagMatch helpers
TEST_F(StaInitTest, TagMatchLessConstructor) {
TagMatchLess less(true, sta_);
TagMatchLess less2(false, sta_);
// Just exercise constructors
}
TEST_F(StaInitTest, TagMatchHashConstructor) {
TagMatchHash hash(true, sta_);
TagMatchHash hash2(false, sta_);
// Just exercise constructors
}
TEST_F(StaInitTest, TagMatchEqualConstructor) {
TagMatchEqual eq(true, sta_);
TagMatchEqual eq2(false, sta_);
// Just exercise constructors
}
// MaxSkewSlackLess
TEST_F(StaInitTest, MaxSkewSlackLessConstructor) {
MaxSkewSlackLess less(sta_);
// Just exercise constructor
}
// MinPeriodSlackLess
TEST_F(StaInitTest, MinPeriodSlackLessConstructor) {
MinPeriodSlackLess less(sta_);
// Just exercise constructor
}
// MinPulseWidthSlackLess
TEST_F(StaInitTest, MinPulseWidthSlackLessConstructor) {
MinPulseWidthSlackLess less(sta_);
// Just exercise constructor
}
// FanOutSrchPred
TEST_F(StaInitTest, FanOutSrchPredConstructor) {
FanOutSrchPred pred(sta_);
// Just exercise constructor
}
// SearchPred hierarchy
TEST_F(StaInitTest, SearchPred0Constructor) {
SearchPred0 pred(sta_);
// Just exercise constructor
}
TEST_F(StaInitTest, SearchPred1Constructor) {
SearchPred1 pred(sta_);
// Just exercise constructor
}
// SearchPred2, SearchPredNonLatch2, SearchPredNonReg2 removed from API
TEST_F(StaInitTest, ClkTreeSearchPredConstructor) {
ClkTreeSearchPred pred(sta_);
// Just exercise constructor
}
// PathExpanded
TEST_F(StaInitTest, PathExpandedDefault) {
PathExpanded pe(sta_);
EXPECT_EQ(pe.size(), 0u);
}
// ReportPathFormat enum coverage
TEST_F(StaInitTest, ReportPathFormatValues) {
EXPECT_NE(static_cast<int>(ReportPathFormat::full),
static_cast<int>(ReportPathFormat::json));
EXPECT_NE(static_cast<int>(ReportPathFormat::shorter),
static_cast<int>(ReportPathFormat::endpoint));
EXPECT_NE(static_cast<int>(ReportPathFormat::summary),
static_cast<int>(ReportPathFormat::slack_only));
}
// Sta::clear on empty
TEST_F(StaInitTest, StaClearEmpty) {
sta_->clear();
// Should not crash
}
// Sta findClkMinPeriod - no design
// (skipping because requires linked design)
// Additional Sta functions that exercise uncovered code paths
TEST_F(StaInitTest, StaTagCount) {
TagIndex count = sta_->tagCount();
EXPECT_GE(count, 0u);
}
TEST_F(StaInitTest, StaTagGroupCount) {
TagGroupIndex count = sta_->tagGroupCount();
EXPECT_GE(count, 0u);
}
TEST_F(StaInitTest, StaClkInfoCount) {
int count = sta_->clkInfoCount();
EXPECT_GE(count, 0);
}
TEST_F(StaInitTest, StaPathCount) {
// pathCount requires graph to be built (segfaults without design)
// Just verify the method exists by taking its address
auto fn = &Sta::pathCount;
expectCallablePointerUsable(fn);
}
TEST_F(StaInitTest, StaMaxPathCountVertex) {
// maxPathCountVertex requires graph to be built (segfaults without design)
// Just verify the method exists by taking its address
auto fn = &Sta::maxPathCountVertex;
expectCallablePointerUsable(fn);
}
// More Sta.cc function coverage
TEST_F(StaInitTest, StaOperatingConditions) {
const OperatingConditions *op = sta_->operatingConditions(MinMax::min(), sta_->cmdSdc());
(void)op;
// May be null without a liberty lib
sta_->operatingConditions(MinMax::max(), sta_->cmdSdc());
}
TEST_F(StaInitTest, StaDelaysInvalidEmpty) {
sta_->delaysInvalid();
// No crash
}
// Additional Property types coverage
TEST_F(StaInitTest, PropertyValuePwrActivity) {
PwrActivity activity;
PropertyValue pv(&activity);
EXPECT_EQ(pv.type(), PropertyValue::Type::pwr_activity);
}
TEST_F(StaInitTest, PropertyValueCopyPwrActivity) {
PwrActivity activity;
PropertyValue pv1(&activity);
PropertyValue pv2(pv1);
EXPECT_EQ(pv2.type(), PropertyValue::Type::pwr_activity);
}
TEST_F(StaInitTest, PropertyValueMovePwrActivity) {
PwrActivity activity;
PropertyValue pv1(&activity);
PropertyValue pv2(std::move(pv1));
EXPECT_EQ(pv2.type(), PropertyValue::Type::pwr_activity);
}
TEST_F(StaInitTest, PropertyValueCopyAssignPwrActivity) {
PwrActivity activity;
PropertyValue pv1(&activity);
PropertyValue pv2;
pv2 = pv1;
EXPECT_EQ(pv2.type(), PropertyValue::Type::pwr_activity);
}
TEST_F(StaInitTest, PropertyValueMoveAssignPwrActivity) {
PwrActivity activity;
PropertyValue pv1(&activity);
PropertyValue pv2;
pv2 = std::move(pv1);
EXPECT_EQ(pv2.type(), PropertyValue::Type::pwr_activity);
}
// SearchClass.hh constants coverage
TEST_F(StaInitTest, SearchClassConstants) {
EXPECT_GT(tag_index_bit_count, 0u);
EXPECT_GT(tag_index_max, 0u);
EXPECT_EQ(tag_index_null, tag_index_max);
EXPECT_GT(path_ap_index_bit_count, 0);
EXPECT_GT(scene_count_max, 0);
}
// More Search.cc methods
TEST_F(StaInitTest, SearchReportTags) {
Search *search = sta_->search();
search->reportTags();
// Just exercise - prints to report
}
TEST_F(StaInitTest, SearchReportClkInfos) {
Search *search = sta_->search();
search->reportClkInfos();
// Just exercise - prints to report
}
TEST_F(StaInitTest, SearchReportTagGroups) {
Search *search = sta_->search();
search->reportTagGroups();
// Just exercise - prints to report
}
// Sta.cc - more SDC wrapper coverage
TEST_F(StaInitTest, StaUnsetTimingDerate) {
sta_->unsetTimingDerate(sta_->cmdSdc());
// No crash on empty
}
TEST_F(StaInitTest, StaUpdateGeneratedClks) {
sta_->updateGeneratedClks();
// No crash on empty
}
// StaRemoveClockGroups* tests removed — nullptr now throws std::logic_error
// Sta.cc - more search-related functions
TEST_F(StaInitTest, StaFindLogicConstants) {
// findLogicConstants requires a linked network
EXPECT_THROW(sta_->findLogicConstants(), Exception);
}
TEST_F(StaInitTest, StaClearLogicConstants) {
sta_->clearLogicConstants();
// No crash
}
TEST_F(StaInitTest, StaDeleteParasitics) {
sta_->deleteParasitics();
// No crash on empty
}
TEST_F(StaInitTest, StaSetVoltageMinMax) {
sta_->setVoltage(MinMax::min(), 0.9f, sta_->cmdSdc());
sta_->setVoltage(MinMax::max(), 1.1f, sta_->cmdSdc());
}
// Path.cc - init methods
TEST_F(StaInitTest, PathInitVertex) {
// Path::init with null vertex segfaults because it accesses graph
// Just verify the method exists
Path path;
EXPECT_TRUE(path.isNull());
}
// WnsSlackLess
TEST_F(StaInitTest, WnsSlackLessConstructor) {
WnsSlackLess less(0, sta_);
// Just exercise constructor
}
// Sta.cc - make functions already called by makeComponents,
// but exercising the public API on the Sta
TEST_F(StaInitTest, StaGraphNotBuilt) {
// Graph is not built until ensureGraph is called
EXPECT_EQ(sta_->graph(), nullptr);
}
TEST_F(StaInitTest, StaLevelizeExists) {
EXPECT_NE(sta_->levelize(), nullptr);
}
TEST_F(StaInitTest, StaSimExists) {
EXPECT_NE(sta_->cmdMode()->sim(), nullptr);
}
TEST_F(StaInitTest, StaSearchExists) {
EXPECT_NE(sta_->search(), nullptr);
}
TEST_F(StaInitTest, StaGraphDelayCalcExists) {
EXPECT_NE(sta_->graphDelayCalc(), nullptr);
}
// parasitics() direct accessor removed; use findParasitics or scene->parasitics
TEST_F(StaInitTest, StaParasiticsViaScene) {
Scene *scene = sta_->cmdScene();
EXPECT_NE(scene, nullptr);
}
TEST_F(StaInitTest, StaArcDelayCalcExists) {
EXPECT_NE(sta_->arcDelayCalc(), nullptr);
}
// Sta.cc - network editing functions (without a real network)
TEST_F(StaInitTest, StaNetworkChangedNoDesign) {
sta_->networkChanged();
// No crash
}
// Verify SdcNetwork exists
TEST_F(StaInitTest, StaSdcNetworkExists) {
EXPECT_NE(sta_->sdcNetwork(), nullptr);
}
// Test set analysis type round trip
TEST_F(StaInitTest, AnalysisTypeSingle) {
sta_->setAnalysisType(AnalysisType::single, sta_->cmdSdc());
Sdc *sdc = sta_->cmdSdc();
EXPECT_EQ(sdc->analysisType(), AnalysisType::single);
}
// PathGroup factory methods
TEST_F(StaInitTest, PathGroupMakeSlack) {
PathGroup *pg = PathGroup::makePathGroupSlack("test_group",
10, 5, false, false,
-1e30f, 1e30f,
sta_);
EXPECT_NE(pg, nullptr);
EXPECT_EQ(pg->name(), "test_group");
EXPECT_EQ(pg->maxPaths(), 10);
const PathEndSeq &ends = pg->pathEnds();
EXPECT_TRUE(ends.empty());
pg->clear();
delete pg;
}
TEST_F(StaInitTest, PathGroupMakeArrival) {
PathGroup *pg = PathGroup::makePathGroupArrival("test_arr",
8, 4, true, false,
MinMax::max(),
sta_);
EXPECT_NE(pg, nullptr);
EXPECT_EQ(pg->name(), "test_arr");
EXPECT_EQ(pg->minMax(), MinMax::max());
delete pg;
}
TEST_F(StaInitTest, PathGroupSaveable) {
PathGroup *pg = PathGroup::makePathGroupSlack("test_save",
10, 5, false, false,
-1e30f, 1e30f,
sta_);
// Without any path ends inserted, saveable behavior depends on implementation
delete pg;
}
// Verify Sta.hh clock-related functions (without actual clocks)
TEST_F(StaInitTest, StaFindWorstClkSkew) {
// findWorstClkSkew requires a linked network
EXPECT_THROW(sta_->findWorstClkSkew(SetupHold::max(), false), Exception);
}
// Exercise SdcExceptionPath related functions
TEST_F(StaInitTest, StaMakeExceptionFrom) {
ExceptionFrom *from = sta_->makeExceptionFrom(nullptr, nullptr, nullptr,
RiseFallBoth::riseFall(),
sta_->cmdSdc());
// With all-null args, returns nullptr
EXPECT_EQ(from, nullptr);
}
TEST_F(StaInitTest, StaMakeExceptionThru) {
ExceptionThru *thru = sta_->makeExceptionThru(nullptr, nullptr, nullptr,
RiseFallBoth::riseFall(),
sta_->cmdSdc());
// With all-null args, returns nullptr
EXPECT_EQ(thru, nullptr);
}
TEST_F(StaInitTest, StaMakeExceptionTo) {
ExceptionTo *to = sta_->makeExceptionTo(nullptr, nullptr, nullptr,
RiseFallBoth::riseFall(),
RiseFallBoth::riseFall(), sta_->cmdSdc());
// With all-null args, returns nullptr
EXPECT_EQ(to, nullptr);
}
// Additional coverage for SceneSeq iteration
TEST_F(StaInitTest, CornersRangeForIteration) {
const SceneSeq &corners = sta_->scenes();
int count = 0;
for (Scene *corner : corners) {
EXPECT_NE(corner, nullptr);
count++;
}
EXPECT_EQ(count, corners.size());
}
// Additional Search method coverage
// findPathGroup moved from Search to PathGroups (via Mode)
TEST_F(StaInitTest, PathGroupsFindByNameNoGroups) {
Mode *mode = sta_->cmdMode();
PathGroups *pgs = mode->pathGroups();
(void)pgs;
// PathGroups may not be initialized yet; just verify mode access works
// PathGroup lookup requires path groups to be built first
EXPECT_NE(mode, nullptr);
}
// Sta.cc reporting coverage
TEST_F(StaInitTest, StaReportPathFormatAll) {
sta_->setReportPathFormat(ReportPathFormat::full);
sta_->setReportPathFormat(ReportPathFormat::full_clock);
sta_->setReportPathFormat(ReportPathFormat::full_clock_expanded);
sta_->setReportPathFormat(ReportPathFormat::shorter);
sta_->setReportPathFormat(ReportPathFormat::endpoint);
sta_->setReportPathFormat(ReportPathFormat::summary);
sta_->setReportPathFormat(ReportPathFormat::slack_only);
sta_->setReportPathFormat(ReportPathFormat::json);
}
// MinPulseWidthCheck default constructor
TEST_F(StaInitTest, MinPulseWidthCheckDefault2) {
MinPulseWidthCheck check;
EXPECT_TRUE(check.isNull());
EXPECT_EQ(check.openPath(), nullptr);
}
// Sta.cc makeCorners with multiple corners
TEST_F(StaInitTest, MakeMultipleCorners) {
StringSeq names;
names.push_back("fast");
names.push_back("slow");
sta_->makeScenes(names);
const SceneSeq &corners = sta_->scenes();
EXPECT_EQ(corners.size(), 2u);
EXPECT_GT(corners.size(), 1u);
Scene *fast = sta_->findScene("fast");
EXPECT_NE(fast, nullptr);
Scene *slow = sta_->findScene("slow");
EXPECT_NE(slow, nullptr);
// Reset to single corner
StringSeq reset;
reset.push_back("default");
sta_->makeScenes(reset);
}
// SearchClass constants
TEST_F(StaInitTest, SearchClassReportPathFormatEnum) {
int full_val = static_cast<int>(ReportPathFormat::full);
int json_val = static_cast<int>(ReportPathFormat::json);
EXPECT_LT(full_val, json_val);
}
// Sta.cc - setAnalysisType effects on corners
TEST_F(StaInitTest, AnalysisTypeSinglePathAPs) {
sta_->setAnalysisType(AnalysisType::single, sta_->cmdSdc());
const SceneSeq &corners = sta_->scenes();
PathAPIndex count = corners.size();
EXPECT_GE(count, 1);
}
TEST_F(StaInitTest, AnalysisTypeBcWcPathAPs) {
sta_->setAnalysisType(AnalysisType::bc_wc, sta_->cmdSdc());
const SceneSeq &corners = sta_->scenes();
// Scene count stays constant; bc_wc uses separate min/max path indices per scene
EXPECT_GE(corners.size(), static_cast<size_t>(1));
Scene *scene = sta_->cmdScene();
size_t idx_min = scene->pathIndex(MinMax::min());
size_t idx_max = scene->pathIndex(MinMax::max());
EXPECT_NE(idx_min, idx_max);
}
TEST_F(StaInitTest, AnalysisTypeOcvPathAPs) {
sta_->setAnalysisType(AnalysisType::ocv, sta_->cmdSdc());
const SceneSeq &corners = sta_->scenes();
// Scene count stays constant; ocv uses separate min/max path indices per scene
EXPECT_GE(corners.size(), static_cast<size_t>(1));
Scene *scene = sta_->cmdScene();
size_t idx_min = scene->pathIndex(MinMax::min());
size_t idx_max = scene->pathIndex(MinMax::max());
EXPECT_NE(idx_min, idx_max);
}
// Sta.cc TotalNegativeSlack
TEST_F(StaInitTest, TotalNegativeSlackNoDesign) {
// totalNegativeSlack requires a linked network
EXPECT_THROW(sta_->totalNegativeSlack(MinMax::max()), Exception);
}
// Corner findPathAnalysisPt
TEST_F(StaInitTest, CornerFindPathAnalysisPtMinMax) {
Scene *corner = sta_->cmdScene();
size_t idx_min = corner->pathIndex(MinMax::min());
size_t idx_max = corner->pathIndex(MinMax::max());
EXPECT_GE(idx_min, 0u);
EXPECT_GE(idx_max, 0u);
}
// Sta.cc worstSlack single return value
TEST_F(StaInitTest, StaWorstSlackSingleValue) {
// worstSlack requires a linked network
EXPECT_THROW(sta_->worstSlack(MinMax::max()), Exception);
}
// Additional Sta.cc coverage for SDC operations
TEST_F(StaInitTest, StaMakeClockGroupsAndRemove) {
ClockGroups *cg = sta_->makeClockGroups("test_cg",
true, false, false,
false, "", sta_->cmdSdc());
EXPECT_NE(cg, nullptr);
sta_->removeClockGroupsLogicallyExclusive("test_cg", sta_->cmdSdc());
}
// Sta.cc setClockSense (no actual clocks/pins)
// Cannot call without actual design objects
// Additional Sta.cc coverage
TEST_F(StaInitTest, StaMultiCornerCheck) {
EXPECT_FALSE(sta_->multiScene());
}
// Test findCorner returns null for non-existent
TEST_F(StaInitTest, FindCornerNonExistent) {
Scene *c = sta_->findScene("nonexistent_corner");
EXPECT_EQ(c, nullptr);
}
// ============================================================
// Round 2: Massive function coverage expansion
// ============================================================
// --- Sta.cc: SDC limit setters (require linked network) ---
TEST_F(StaInitTest, StaSetMinPulseWidthRF) {
sta_->setMinPulseWidth(RiseFallBoth::riseFall(), 1.0f, sta_->cmdSdc());
// No crash - this doesn't require linked network
}
TEST_F(StaInitTest, StaSetWireloadMode) {
sta_->setWireloadMode(WireloadMode::top, sta_->cmdSdc());
// No crash
}
TEST_F(StaInitTest, StaSetWireload) {
sta_->setWireload(nullptr, MinMaxAll::all(), sta_->cmdSdc());
// No crash with null
}
TEST_F(StaInitTest, StaSetWireloadSelection) {
sta_->setWireloadSelection(nullptr, MinMaxAll::all(), sta_->cmdSdc());
// No crash
}
TEST_F(StaInitTest, StaSetSlewLimitPort) {
// Requires valid Port - just verify EXPECT_THROW or no-crash
sta_->setSlewLimit(static_cast<Port*>(nullptr), MinMax::max(), 1.0f, sta_->cmdSdc());
}
TEST_F(StaInitTest, StaSetSlewLimitCell) {
sta_->setSlewLimit(static_cast<Cell*>(nullptr), MinMax::max(), 1.0f, sta_->cmdSdc());
}
TEST_F(StaInitTest, StaSetCapacitanceLimitCell) {
sta_->setCapacitanceLimit(static_cast<Cell*>(nullptr), MinMax::max(), 1.0f, sta_->cmdSdc());
}
TEST_F(StaInitTest, StaSetCapacitanceLimitPort) {
sta_->setCapacitanceLimit(static_cast<Port*>(nullptr), MinMax::max(), 1.0f, sta_->cmdSdc());
}
TEST_F(StaInitTest, StaSetCapacitanceLimitPin) {
sta_->setCapacitanceLimit(static_cast<Pin*>(nullptr), MinMax::max(), 1.0f, sta_->cmdSdc());
}
TEST_F(StaInitTest, StaSetFanoutLimitCell) {
sta_->setFanoutLimit(static_cast<Cell*>(nullptr), MinMax::max(), 1.0f, sta_->cmdSdc());
}
TEST_F(StaInitTest, StaSetFanoutLimitPort) {
sta_->setFanoutLimit(static_cast<Port*>(nullptr), MinMax::max(), 1.0f, sta_->cmdSdc());
}
TEST_F(StaInitTest, StaSetMaxAreaVal) {
sta_->setMaxArea(100.0f, sta_->cmdSdc());
// No crash
}
// --- Sta.cc: clock operations ---
TEST_F(StaInitTest, StaSetPropagatedClockNull) {
sta_->setPropagatedClock(static_cast<Pin*>(nullptr), sta_->cmdMode());
}
TEST_F(StaInitTest, StaRemovePropagatedClockPin) {
sta_->removePropagatedClock(static_cast<Pin*>(nullptr), sta_->cmdMode());
}
// --- Sta.cc: analysis options getters/setters ---
TEST_F(StaInitTest, StaCrprEnabled) {
bool enabled = sta_->crprEnabled();
EXPECT_TRUE(enabled || !enabled); // Just verify callable
}
TEST_F(StaInitTest, StaSetCrprEnabled) {
sta_->setCrprEnabled(true);
EXPECT_TRUE(sta_->crprEnabled());
sta_->setCrprEnabled(false);
EXPECT_FALSE(sta_->crprEnabled());
}
TEST_F(StaInitTest, StaCrprModeAccess) {
sta_->crprMode();
}
TEST_F(StaInitTest, StaSetCrprModeVal) {
sta_->setCrprMode(CrprMode::same_pin);
EXPECT_EQ(sta_->crprMode(), CrprMode::same_pin);
}
TEST_F(StaInitTest, StaPocvModeAccess) {
sta_->pocvMode();
}
TEST_F(StaInitTest, StaSetPocvMode2) {
sta_->setPocvMode(PocvMode::normal);
EXPECT_EQ(sta_->pocvMode(), PocvMode::normal);
sta_->setPocvMode(PocvMode::scalar);
}
// StaSetSigmaFactor test removed: setSigmaFactor API removed
TEST_F(StaInitTest, StaPropagateGatedClockEnable) {
sta_->propagateGatedClockEnable();
}
TEST_F(StaInitTest, StaSetPropagateGatedClockEnable) {
sta_->setPropagateGatedClockEnable(true);
EXPECT_TRUE(sta_->propagateGatedClockEnable());
sta_->setPropagateGatedClockEnable(false);
}
TEST_F(StaInitTest, StaPresetClrArcsEnabled) {
sta_->presetClrArcsEnabled();
}
TEST_F(StaInitTest, StaSetPresetClrArcsEnabled) {
sta_->setPresetClrArcsEnabled(true);
EXPECT_TRUE(sta_->presetClrArcsEnabled());
}
TEST_F(StaInitTest, StaCondDefaultArcsEnabled) {
sta_->condDefaultArcsEnabled();
}
TEST_F(StaInitTest, StaSetCondDefaultArcsEnabled) {
sta_->setCondDefaultArcsEnabled(true);
EXPECT_TRUE(sta_->condDefaultArcsEnabled());
}
TEST_F(StaInitTest, StaBidirectInstPathsEnabled) {
sta_->bidirectInstPathsEnabled();
}
TEST_F(StaInitTest, StaSetBidirectInstPathsEnabled) {
sta_->setBidirectInstPathsEnabled(true);
EXPECT_TRUE(sta_->bidirectInstPathsEnabled());
}
TEST_F(StaInitTest, StaBidirectNetPathsEnabled) {
sta_->bidirectInstPathsEnabled();
}
TEST_F(StaInitTest, StaSetBidirectNetPathsEnabled) {
sta_->setBidirectInstPathsEnabled(true);
EXPECT_TRUE(sta_->bidirectInstPathsEnabled());
}
TEST_F(StaInitTest, StaRecoveryRemovalChecksEnabled) {
sta_->recoveryRemovalChecksEnabled();
}
TEST_F(StaInitTest, StaSetRecoveryRemovalChecksEnabled) {
sta_->setRecoveryRemovalChecksEnabled(true);
EXPECT_TRUE(sta_->recoveryRemovalChecksEnabled());
}
TEST_F(StaInitTest, StaGatedClkChecksEnabled) {
sta_->gatedClkChecksEnabled();
}
TEST_F(StaInitTest, StaSetGatedClkChecksEnabled) {
sta_->setGatedClkChecksEnabled(true);
EXPECT_TRUE(sta_->gatedClkChecksEnabled());
}
TEST_F(StaInitTest, StaPropagateAllClocks) {
sta_->propagateAllClocks();
}
TEST_F(StaInitTest, StaSetPropagateAllClocks) {
sta_->setPropagateAllClocks(true);
EXPECT_TRUE(sta_->propagateAllClocks());
}
TEST_F(StaInitTest, StaClkThruTristateEnabled) {
sta_->clkThruTristateEnabled();
}
TEST_F(StaInitTest, StaSetClkThruTristateEnabled) {
sta_->setClkThruTristateEnabled(true);
EXPECT_TRUE(sta_->clkThruTristateEnabled());
}
// --- Sta.cc: corner operations ---
TEST_F(StaInitTest, StaCmdCorner) {
Scene *c = sta_->cmdScene();
EXPECT_NE(c, nullptr);
}
TEST_F(StaInitTest, StaSetCmdCorner) {
Scene *c = sta_->cmdScene();
sta_->setCmdScene(c);
EXPECT_EQ(sta_->cmdScene(), c);
}
TEST_F(StaInitTest, StaMultiCorner) {
sta_->multiScene();
}
// --- Sta.cc: functions that throw "No network has been linked" ---
TEST_F(StaInitTest, StaEnsureLinked) {
EXPECT_THROW(sta_->ensureLinked(), std::exception);
}
TEST_F(StaInitTest, StaEnsureGraph2) {
EXPECT_THROW(sta_->ensureGraph(), std::exception);
}
TEST_F(StaInitTest, StaEnsureLevelized) {
EXPECT_THROW(sta_->ensureLevelized(), std::exception);
}
TEST_F(StaInitTest, StaSearchPreamble) {
EXPECT_THROW(sta_->searchPreamble(), std::exception);
}
TEST_F(StaInitTest, StaUpdateTiming) {
EXPECT_THROW(sta_->updateTiming(false), std::exception);
}
TEST_F(StaInitTest, StaFindDelaysVoid) {
EXPECT_THROW(sta_->findDelays(), std::exception);
}
TEST_F(StaInitTest, StaFindDelaysVertex) {
// findDelays with null vertex - throws
EXPECT_THROW(sta_->findDelays(static_cast<Vertex*>(nullptr)), std::exception);
}
TEST_F(StaInitTest, StaFindRequireds) {
EXPECT_THROW(sta_->findRequireds(), std::exception);
}
TEST_F(StaInitTest, StaArrivalsInvalid) {
sta_->arrivalsInvalid();
// No crash - doesn't require linked network
}
TEST_F(StaInitTest, StaEnsureClkArrivals) {
EXPECT_THROW(sta_->ensureClkArrivals(), std::exception);
}
TEST_F(StaInitTest, StaEndpoints2) {
EXPECT_THROW(sta_->endpoints(), std::exception);
}
TEST_F(StaInitTest, StaEndpointPins) {
EXPECT_THROW(sta_->endpointPins(), std::exception);
}
TEST_F(StaInitTest, StaEndpointViolationCount) {
// endpointViolationCount segfaults without graph - just verify exists
auto fn = &Sta::endpointViolationCount;
expectCallablePointerUsable(fn);
}
TEST_F(StaInitTest, StaUpdateGeneratedClks2) {
sta_->updateGeneratedClks();
// No crash - doesn't require linked network
}
TEST_F(StaInitTest, StaGraphLoops) {
EXPECT_THROW(sta_->graphLoops(), std::exception);
}
TEST_F(StaInitTest, StaCheckTimingThrows) {
EXPECT_THROW(sta_->checkTiming(sta_->cmdMode(), true, true, true, true, true, true, true), std::exception);
}
TEST_F(StaInitTest, StaRemoveConstraints) {
sta_->clear();
// No crash
}
TEST_F(StaInitTest, StaConstraintsChanged) {
sta_->delaysInvalid();
// No crash
}
// --- Sta.cc: report path functions ---
TEST_F(StaInitTest, StaSetReportPathFormat2) {
sta_->setReportPathFormat(ReportPathFormat::full_clock_expanded);
// No crash
}
// --- Sta.cc: operating conditions ---
TEST_F(StaInitTest, StaSetOperatingConditions) {
sta_->setOperatingConditions(nullptr, MinMaxAll::all(), sta_->cmdSdc());
// No crash
}
// --- Sta.cc: timing derate ---
TEST_F(StaInitTest, StaSetTimingDerateType) {
sta_->setTimingDerate(TimingDerateType::cell_delay,
PathClkOrData::clk,
RiseFallBoth::riseFall(),
MinMax::max(), 1.0f, sta_->cmdSdc());
// No crash
}
// --- Sta.cc: input slew ---
TEST_F(StaInitTest, StaSetInputSlewNull) {
sta_->setInputSlew(nullptr, RiseFallBoth::riseFall(),
MinMaxAll::all(), 0.5f, sta_->cmdSdc());
// No crash
}
TEST_F(StaInitTest, StaSetDriveResistanceNull) {
sta_->setDriveResistance(nullptr, RiseFallBoth::riseFall(),
MinMaxAll::all(), 100.0f, sta_->cmdSdc());
// No crash
}
// --- Sta.cc: borrow limits ---
TEST_F(StaInitTest, StaSetLatchBorrowLimitPin) {
sta_->setLatchBorrowLimit(static_cast<const Pin*>(nullptr), 1.0f, sta_->cmdSdc());
// No crash
}
TEST_F(StaInitTest, StaSetLatchBorrowLimitInst) {
sta_->setLatchBorrowLimit(static_cast<const Instance*>(nullptr), 1.0f, sta_->cmdSdc());
// No crash
}
TEST_F(StaInitTest, StaSetLatchBorrowLimitClock) {
sta_->setLatchBorrowLimit(static_cast<const Clock*>(nullptr), 1.0f, sta_->cmdSdc());
// No crash
}
TEST_F(StaInitTest, StaSetMinPulseWidthPin) {
sta_->setMinPulseWidth(static_cast<const Pin*>(nullptr),
RiseFallBoth::riseFall(), 0.5f, sta_->cmdSdc());
// No crash
}
TEST_F(StaInitTest, StaSetMinPulseWidthInstance) {
sta_->setMinPulseWidth(static_cast<const Instance*>(nullptr),
RiseFallBoth::riseFall(), 0.5f, sta_->cmdSdc());
// No crash
}
TEST_F(StaInitTest, StaSetMinPulseWidthClock) {
sta_->setMinPulseWidth(static_cast<const Clock*>(nullptr),
RiseFallBoth::riseFall(), 0.5f, sta_->cmdSdc());
// No crash
}
// --- Sta.cc: network operations (throw) ---
TEST_F(StaInitTest, StaNetworkChanged) {
sta_->networkChanged();
// No crash
}
TEST_F(StaInitTest, StaFindRegisterInstancesThrows) {
EXPECT_THROW(sta_->findRegisterInstances(nullptr,
RiseFallBoth::riseFall(), false, false, sta_->cmdMode()), std::exception);
}
TEST_F(StaInitTest, StaFindRegisterDataPinsThrows) {
EXPECT_THROW(sta_->findRegisterDataPins(nullptr,
RiseFallBoth::riseFall(), false, false, sta_->cmdMode()), std::exception);
}
TEST_F(StaInitTest, StaFindRegisterClkPinsThrows) {
EXPECT_THROW(sta_->findRegisterClkPins(nullptr,
RiseFallBoth::riseFall(), false, false, sta_->cmdMode()), std::exception);
}
TEST_F(StaInitTest, StaFindRegisterAsyncPinsThrows) {
EXPECT_THROW(sta_->findRegisterAsyncPins(nullptr,
RiseFallBoth::riseFall(), false, false, sta_->cmdMode()), std::exception);
}
TEST_F(StaInitTest, StaFindRegisterOutputPinsThrows) {
EXPECT_THROW(sta_->findRegisterOutputPins(nullptr,
RiseFallBoth::riseFall(), false, false, sta_->cmdMode()), std::exception);
}
// --- Sta.cc: parasitic analysis ---
TEST_F(StaInitTest, StaDeleteParasitics2) {
sta_->deleteParasitics();
// No crash
}
// StaMakeParasiticAnalysisPts removed - protected method
// --- Sta.cc: removeNetLoadCaps ---
TEST_F(StaInitTest, StaRemoveNetLoadCaps) {
sta_->removeNetLoadCaps(sta_->cmdSdc());
// No crash (returns void)
}
// --- Sta.cc: delay calc ---
TEST_F(StaInitTest, StaSetIncrementalDelayToleranceVal) {
sta_->setIncrementalDelayTolerance(0.01f);
// No crash
}
// StaDelayCalcPreambleExists removed - protected method
// --- Sta.cc: check limit preambles (protected) ---
TEST_F(StaInitTest, StaCheckSlewLimitPreambleThrows) {
EXPECT_THROW(sta_->checkSlewsPreamble(), std::exception);
}
TEST_F(StaInitTest, StaCheckFanoutLimitPreambleThrows) {
EXPECT_THROW(sta_->checkFanoutPreamble(), std::exception);
}
TEST_F(StaInitTest, StaCheckCapacitanceLimitPreambleThrows) {
EXPECT_THROW(sta_->checkCapacitancesPreamble(sta_->scenes()), std::exception);
}
// --- Sta.cc: isClockNet ---
TEST_F(StaInitTest, StaIsClockPinFn) {
// isClock with nullptr segfaults - verify method exists
auto fn1 = static_cast<bool (Sta::*)(const Pin*, const Mode*)>(&Sta::isClock);
EXPECT_NE(fn1, nullptr);
}
TEST_F(StaInitTest, StaIsClockNetFn) {
auto fn2 = static_cast<bool (Sta::*)(const Net*, const Mode*)>(&Sta::isClock);
EXPECT_NE(fn2, nullptr);
}
TEST_F(StaInitTest, StaIsIdealClockPin) {
// isIdealClock requires a linked network; expect throw without one
EXPECT_ANY_THROW(sta_->isIdealClock(static_cast<const Pin*>(nullptr), sta_->cmdMode()));
}
TEST_F(StaInitTest, StaIsPropagatedClockPin) {
bool val = sta_->isPropagatedClock(static_cast<const Pin*>(nullptr), sta_->cmdMode());
EXPECT_FALSE(val);
}
TEST_F(StaInitTest, StaClkPinsInvalid2) {
// clkPinsInvalid requires a linked network; expect throw without one
EXPECT_ANY_THROW(sta_->clkPinsInvalid(sta_->cmdMode()));
}
// --- Sta.cc: STA misc functions ---
TEST_F(StaInitTest, StaCurrentInstance) {
sta_->currentInstance();
}
TEST_F(StaInitTest, StaRemoveDelaySlewAnnotations) {
sta_->removeDelaySlewAnnotations();
// No crash
}
// minPeriodSlack removed from API
TEST_F(StaInitTest, StaMinPeriodReportThrows) {
EXPECT_THROW(sta_->reportMinPeriodChecks(nullptr, 10, false, false, sta_->scenes()), std::exception);
}
// maxSkewViolations removed from API
// maxSkewSlack removed from API
TEST_F(StaInitTest, StaMaxSkewReportThrows) {
EXPECT_THROW(sta_->reportMaxSkewChecks(nullptr, 10, false, false, sta_->scenes()), std::exception);
}
TEST_F(StaInitTest, StaWorstSlackCornerThrows) {
Slack ws;
Vertex *v;
EXPECT_THROW(sta_->worstSlack(sta_->cmdScene(), MinMax::max(), ws, v), std::exception);
}
TEST_F(StaInitTest, StaTotalNegativeSlackCornerThrows) {
EXPECT_THROW(sta_->totalNegativeSlack(sta_->cmdScene(), MinMax::max()), std::exception);
}
// --- PathEnd subclass: PathEndUnconstrained ---
TEST_F(StaInitTest, PathEndUnconstrainedConstruct) {
Path *p = new Path();
PathEndUnconstrained *pe = new PathEndUnconstrained(p);
EXPECT_EQ(pe->type(), PathEnd::Type::unconstrained);
EXPECT_STREQ(pe->typeName(), "unconstrained");
EXPECT_TRUE(pe->isUnconstrained());
EXPECT_FALSE(pe->isCheck());
PathEnd *copy = pe->copy();
EXPECT_NE(copy, nullptr);
delete copy;
delete pe;
}
// --- PathEnd subclass: PathEndCheck ---
TEST_F(StaInitTest, PathEndCheckConstruct) {
Path *data_path = new Path();
Path *clk_path = new Path();
PathEndCheck *pe = new PathEndCheck(data_path, nullptr, nullptr,
clk_path, nullptr, nullptr, sta_);
EXPECT_EQ(pe->type(), PathEnd::Type::check);
EXPECT_STREQ(pe->typeName(), "check");
EXPECT_TRUE(pe->isCheck());
PathEnd *copy = pe->copy();
EXPECT_NE(copy, nullptr);
delete copy;
delete pe;
}
// --- PathEnd subclass: PathEndLatchCheck ---
TEST_F(StaInitTest, PathEndLatchCheckConstruct) {
// PathEndLatchCheck constructor accesses path internals - just check type enum
EXPECT_EQ(static_cast<int>(PathEnd::Type::latch_check), 3);
}
// --- PathEnd subclass: PathEndOutputDelay ---
TEST_F(StaInitTest, PathEndOutputDelayConstruct) {
Path *data_path = new Path();
Path *clk_path = new Path();
PathEndOutputDelay *pe = new PathEndOutputDelay(nullptr, data_path,
clk_path, nullptr, nullptr, sta_);
EXPECT_EQ(pe->type(), PathEnd::Type::output_delay);
EXPECT_STREQ(pe->typeName(), "output_delay");
EXPECT_TRUE(pe->isOutputDelay());
PathEnd *copy = pe->copy();
EXPECT_NE(copy, nullptr);
delete copy;
delete pe;
}
// --- PathEnd subclass: PathEndGatedClock ---
TEST_F(StaInitTest, PathEndGatedClockConstruct) {
Path *data_path = new Path();
Path *clk_path = new Path();
PathEndGatedClock *pe = new PathEndGatedClock(data_path, clk_path,
TimingRole::setup(),
nullptr, nullptr, 0.0f, sta_);
EXPECT_EQ(pe->type(), PathEnd::Type::gated_clk);
EXPECT_STREQ(pe->typeName(), "gated_clk");
EXPECT_TRUE(pe->isGatedClock());
PathEnd *copy = pe->copy();
EXPECT_NE(copy, nullptr);
delete copy;
delete pe;
}
// PathEndDataCheck, PathEndPathDelay constructors access path internals (segfault)
// Just test type enum values instead
TEST_F(StaInitTest, PathEndTypeEnums) {
EXPECT_EQ(static_cast<int>(PathEnd::Type::data_check), 2);
EXPECT_EQ(static_cast<int>(PathEnd::Type::path_delay), 6);
EXPECT_EQ(static_cast<int>(PathEnd::Type::gated_clk), 5);
}
// PathEnd::cmp and ::less with nullptr segfault - skip
// PathEndPathDelay constructor with nullptr segfaults - skip
// --- WorstSlack with corner ---
TEST_F(StaInitTest, StaWorstSlackMinThrows) {
Slack ws;
Vertex *v;
EXPECT_THROW(sta_->worstSlack(MinMax::min(), ws, v), std::exception);
}
// --- Search.cc: deletePathGroups ---
TEST_F(StaInitTest, SearchDeletePathGroupsDirect) {
Search *search = sta_->search();
search->deletePathGroups();
// No crash
}
// --- Property.cc: additional PropertyValue types ---
TEST_F(StaInitTest, PropertyValueLibCellType) {
PropertyValue pv(static_cast<LibertyCell*>(nullptr));
EXPECT_EQ(pv.type(), PropertyValue::Type::liberty_cell);
}
TEST_F(StaInitTest, PropertyValueLibPortType) {
PropertyValue pv(static_cast<LibertyPort*>(nullptr));
EXPECT_EQ(pv.type(), PropertyValue::Type::liberty_port);
}
// --- Sta.cc: MinPulseWidthChecks (minPulseWidthChecks/minPulseWidthViolations removed from Sta API) ---
TEST_F(StaInitTest, StaMinPulseWidthReportExists) {
// reportMinPulseWidthChecks is the replacement API
auto fn = &Sta::reportMinPulseWidthChecks;
expectCallablePointerUsable(fn);
}
// --- Sta.cc: findFanin/findFanout (throw) ---
TEST_F(StaInitTest, StaFindFaninPinsThrows) {
EXPECT_THROW(sta_->findFaninPins(nullptr, false, false, 10, 10, false, false, sta_->cmdMode()), std::exception);
}
TEST_F(StaInitTest, StaFindFanoutPinsThrows) {
EXPECT_THROW(sta_->findFanoutPins(nullptr, false, false, 10, 10, false, false, sta_->cmdMode()), std::exception);
}
TEST_F(StaInitTest, StaFindFaninInstancesThrows) {
EXPECT_THROW(sta_->findFaninInstances(nullptr, false, false, 10, 10, false, false, sta_->cmdMode()), std::exception);
}
TEST_F(StaInitTest, StaFindFanoutInstancesThrows) {
EXPECT_THROW(sta_->findFanoutInstances(nullptr, false, false, 10, 10, false, false, sta_->cmdMode()), std::exception);
}
// --- Sta.cc: setPortExt functions ---
// setPortExtPinCap/WireCap/Fanout with nullptr segfault - verify methods exist
TEST_F(StaInitTest, StaSetPortExtMethods) {
auto fn1 = &Sta::setPortExtPinCap;
auto fn2 = &Sta::setPortExtWireCap;
auto fn3 = &Sta::setPortExtFanout;
EXPECT_NE(fn1, nullptr);
EXPECT_NE(fn2, nullptr);
EXPECT_NE(fn3, nullptr);
}
// --- Sta.cc: delaysInvalid ---
TEST_F(StaInitTest, StaDelaysInvalid) {
sta_->delaysInvalid();
// No crash (returns void)
}
// --- Sta.cc: clock groups ---
TEST_F(StaInitTest, StaMakeClockGroupsDetailed) {
ClockGroups *groups = sta_->makeClockGroups("test_group",
true, false, false, false, "", sta_->cmdSdc());
EXPECT_NE(groups, nullptr);
}
// --- Sta.cc: setClockGatingCheck ---
TEST_F(StaInitTest, StaSetClockGatingCheckGlobal) {
sta_->setClockGatingCheck(RiseFallBoth::riseFall(), SetupHold::max(), 0.1f, sta_->cmdSdc());
// No crash
}
// disableAfter is protected - cannot test directly
// --- Sta.cc: setResistance ---
TEST_F(StaInitTest, StaSetResistanceNull) {
sta_->setResistance(nullptr, MinMaxAll::all(), 100.0f, sta_->cmdSdc());
// No crash
}
// --- PathEnd::Type::checkTgtClkDelay static ---
TEST_F(StaInitTest, PathEndCheckTgtClkDelayStatic) {
Delay insertion, latency;
PathEnd::checkTgtClkDelay(nullptr, nullptr, TimingRole::setup(), sta_,
insertion, latency);
// No crash with nulls
}
// --- PathEnd::Type::checkClkUncertainty static ---
TEST_F(StaInitTest, PathEndCheckClkUncertaintyStatic) {
float unc = PathEnd::checkClkUncertainty(nullptr, nullptr, nullptr,
TimingRole::setup(), sta_->cmdSdc());
EXPECT_FLOAT_EQ(unc, 0.0f);
}
// --- FanOutSrchPred (FanInOutSrchPred is in Sta.cc, not public) ---
TEST_F(StaInitTest, FanOutSrchPredExists) {
// FanOutSrchPred is already tested via constructor test above
// searchThru is overloaded, verify specific override
using SearchThruFn = bool (FanOutSrchPred::*)(Edge*, const Mode*) const;
SearchThruFn fn = &FanOutSrchPred::searchThru;
expectCallablePointerUsable(fn);
}
// --- PathEnd::Type::checkSetupMcpAdjustment static ---
TEST_F(StaInitTest, PathEndCheckSetupMcpAdjStatic) {
float adj = PathEnd::checkSetupMcpAdjustment(nullptr, nullptr, nullptr,
1, sta_->cmdSdc());
EXPECT_FLOAT_EQ(adj, 0.0f);
}
// --- Search class additional functions ---
TEST_F(StaInitTest, SearchClkInfoCountDirect) {
Search *search = sta_->search();
int count = search->clkInfoCount();
EXPECT_GE(count, 0);
}
TEST_F(StaInitTest, SearchTagGroupCountDirect) {
Search *search = sta_->search();
int count = search->tagGroupCount();
EXPECT_GE(count, 0);
}
// --- Sta.cc: write/report functions that throw ---
TEST_F(StaInitTest, StaWriteSdcThrows) {
EXPECT_THROW(sta_->writeSdc(sta_->cmdSdc(), "test_write_sdc_should_throw.sdc",
false, false, 4, false, false),
std::exception);
}
TEST_F(StaInitTest, StaMakeEquivCells) {
// makeEquivCells requires linked network; just verify method exists
auto fn = &Sta::makeEquivCells;
expectCallablePointerUsable(fn);
}
TEST_F(StaInitTest, StaEquivCellsNull) {
LibertyCellSeq *cells = sta_->equivCells(nullptr);
EXPECT_EQ(cells, nullptr);
}
// --- Sta.cc: setClockSense, setDataCheck ---
TEST_F(StaInitTest, StaSetClockSense) {
// setClockSense dereferences pin/clock pointers; just verify method exists
auto fn = &Sta::setClockSense;
expectCallablePointerUsable(fn);
}
// --- CheckTiming constructor ---
TEST_F(StaInitTest, CheckTimingExists) {
// CheckTiming is created by Sta::makeCheckTiming
// Just verify Sta function exists
auto fn = &Sta::checkTiming;
expectCallablePointerUsable(fn);
}
// --- MakeTimingModel exists (function is in MakeTimingModel.cc) ---
TEST_F(StaInitTest, StaWriteTimingModelExists) {
auto fn = &Sta::writeTimingModel;
expectCallablePointerUsable(fn);
}
// --- ReportPath additional functions ---
TEST_F(StaInitTest, ReportPathFieldOrderSet) {
// reportPath() is overloaded; just verify we can call it
ReportPath *rp = sta_->reportPath();
EXPECT_NE(rp, nullptr);
}
// --- Sta.cc: STA instance methods ---
TEST_F(StaInitTest, StaStaGlobal) {
Sta *global = Sta::sta();
EXPECT_NE(global, nullptr);
}
TEST_F(StaInitTest, StaTclInterpAccess) {
ASSERT_NE(sta_, nullptr);
ASSERT_NE(interp_, nullptr);
// tcl_interp_ is uninitialized before setTclInterp, so skip reading it.
sta_->setTclInterp(interp_);
Tcl_Interp *after = sta_->tclInterp();
EXPECT_EQ(after, interp_);
EXPECT_EQ(sta_->tclInterp(), interp_);
EXPECT_EQ(Sta::sta(), sta_);
EXPECT_NE(sta_->report(), nullptr);
}
TEST_F(StaInitTest, StaCmdNamespace) {
sta_->cmdNamespace();
}
// --- Sta.cc: setAnalysisType ---
TEST_F(StaInitTest, StaSetAnalysisTypeOnChip) {
sta_->setAnalysisType(AnalysisType::ocv, sta_->cmdSdc());
const SceneSeq &corners = sta_->scenes();
// Scene count stays constant; ocv uses separate min/max path indices
EXPECT_GE(corners.size(), static_cast<size_t>(1));
}
// --- Sta.cc: clearLogicConstants ---
TEST_F(StaInitTest, StaClearLogicConstants2) {
sta_->clearLogicConstants();
// No crash
}
// --- Additional Sta.cc getters ---
TEST_F(StaInitTest, StaDefaultThreadCount) {
int count = sta_->defaultThreadCount();
EXPECT_GE(count, 1);
}
TEST_F(StaInitTest, StaSetThreadCount) {
sta_->setThreadCount(2);
// No crash
}
// --- SearchPred additional coverage ---
TEST_F(StaInitTest, SearchPredSearchThru) {
// SearchPred1 already covered - verify SearchPred0 exists
SearchPred0 pred0(sta_);
// searchThru is overloaded (Edge*, const Mode*) and (Edge*); just verify pred0 exists
EXPECT_TRUE(true);
}
// --- Sim additional coverage ---
TEST_F(StaInitTest, SimLogicValueNull) {
// simLogicValue requires linked network
EXPECT_THROW(sta_->simLogicValue(nullptr, sta_->cmdMode()), Exception);
}
// --- PathEnd data_check type enum check ---
TEST_F(StaInitTest, PathEndDataCheckClkPath) {
// PathEndDataCheck constructor dereferences path internals; just check type enum
EXPECT_EQ(static_cast<int>(PathEnd::Type::data_check), 2);
}
// --- Additional PathEnd copy chain ---
TEST_F(StaInitTest, PathEndUnconstrainedCopy2) {
Path *p = new Path();
PathEndUnconstrained pe(p);
EXPECT_EQ(pe.sourceClkOffset(sta_), 0.0f);
EXPECT_FALSE(pe.isCheck());
EXPECT_FALSE(pe.isGatedClock());
EXPECT_FALSE(pe.isPathDelay());
EXPECT_FALSE(pe.isDataCheck());
EXPECT_FALSE(pe.isOutputDelay());
EXPECT_FALSE(pe.isLatchCheck());
}
// --- Sta.cc: make and remove clock groups ---
TEST_F(StaInitTest, StaRemoveClockGroupsLogExcl) {
sta_->removeClockGroupsLogicallyExclusive("nonexistent", sta_->cmdSdc());
// No crash
}
TEST_F(StaInitTest, StaRemoveClockGroupsPhysExcl) {
sta_->removeClockGroupsPhysicallyExclusive("nonexistent", sta_->cmdSdc());
// No crash
}
TEST_F(StaInitTest, StaRemoveClockGroupsAsync) {
sta_->removeClockGroupsAsynchronous("nonexistent", sta_->cmdSdc());
// No crash
}
// --- Sta.cc: setVoltage net ---
TEST_F(StaInitTest, StaSetVoltageNet) {
sta_->setVoltage(static_cast<const Net*>(nullptr), MinMax::max(), 1.0f, sta_->cmdSdc());
// No crash
}
// --- Path class copy constructor ---
TEST_F(StaInitTest, PathCopyConstructor) {
Path p1;
Path p2(p1);
EXPECT_TRUE(p2.isNull());
}
// --- Sta.cc: ensureLibLinked ---
TEST_F(StaInitTest, StaEnsureLibLinked) {
EXPECT_THROW(sta_->ensureLibLinked(), std::exception);
}
// --- Sta.cc: isGroupPathName, pathGroupNames ---
TEST_F(StaInitTest, StaIsPathGroupNameEmpty) {
bool val = sta_->isPathGroupName("nonexistent", sta_->cmdSdc());
EXPECT_FALSE(val);
}
TEST_F(StaInitTest, StaPathGroupNamesAccess) {
auto names = sta_->pathGroupNames(sta_->cmdSdc());
// Just exercise the function
}
// makeClkSkews is protected - cannot test directly
// --- PathAnalysisPt additional getters ---
TEST_F(StaInitTest, PathAnalysisPtInsertionAP) {
Scene *corner = sta_->cmdScene();
size_t ap = corner->pathIndex(MinMax::max());
EXPECT_GE(ap, 0u);
}
// --- SceneSeq additional functions ---
TEST_F(StaInitTest, CornersCountVal) {
const SceneSeq &corners = sta_->scenes();
EXPECT_GE(corners.size(), 1u);
}
TEST_F(StaInitTest, CornersFindByIndex) {
const SceneSeq &corners = sta_->scenes();
EXPECT_FALSE(corners.empty());
Scene *c = corners[0];
EXPECT_NE(c, nullptr);
}
TEST_F(StaInitTest, CornersFindByName) {
const SceneSeq &corners = sta_->scenes();
(void)corners;
Scene *c = sta_->findScene("default");
(void)c;
// May or may not find it
}
// --- GraphLoop ---
TEST_F(StaInitTest, GraphLoopEmpty) {
// GraphLoop requires edges vector
std::vector<Edge*> *edges = new std::vector<Edge*>;
GraphLoop loop(edges);
loop.isCombinational();
}
// --- Sta.cc: makeFalsePath ---
TEST_F(StaInitTest, StaMakeFalsePath) {
sta_->makeFalsePath(nullptr, nullptr, nullptr, MinMaxAll::all(), "", sta_->cmdSdc());
// No crash (with all null args)
}
// --- Sta.cc: makeMulticyclePath ---
TEST_F(StaInitTest, StaMakeMulticyclePath) {
sta_->makeMulticyclePath(nullptr, nullptr, nullptr, MinMaxAll::all(), false, 2, "", sta_->cmdSdc());
// No crash
}
// --- Sta.cc: resetPath ---
TEST_F(StaInitTest, StaResetPath) {
sta_->resetPath(nullptr, nullptr, nullptr, MinMaxAll::all(), sta_->cmdSdc());
// No crash
}
// --- Sta.cc: makeGroupPath ---
TEST_F(StaInitTest, StaMakeGroupPath) {
sta_->makeGroupPath("test_group", false, nullptr, nullptr, nullptr, "", sta_->cmdSdc());
// No crash
}
// --- Sta.cc: isPathGroupName ---
TEST_F(StaInitTest, StaIsPathGroupNameTestGroup) {
bool val = sta_->isPathGroupName("test_group", sta_->cmdSdc());
(void)val;
// May or may not find it depending on prior makeGroupPath
}
// --- VertexVisitor ---
TEST_F(StaInitTest, VertexVisitorExists) {
// VertexVisitor is abstract - just verify
auto fn = &VertexVisitor::visit;
expectCallablePointerUsable(fn);
}
////////////////////////////////////////////////////////////////
// Round 3: Deep coverage targeting 388 uncovered functions
////////////////////////////////////////////////////////////////
// --- Property.cc: Properties helper methods (protected, test via Sta public API) ---
// logicValueZeroOne removed - use logicValueString instead
TEST_F(StaInitTest, LogicValueStringZero) {
char ch = logicValueString(LogicValue::zero);
EXPECT_EQ(ch, '0');
}
TEST_F(StaInitTest, LogicValueStringOne) {
char ch = logicValueString(LogicValue::one);
EXPECT_EQ(ch, '1');
}
// --- ReportPath.cc: ReportField constructor and setEnabled ---
TEST_F(StaInitTest, ReportFieldConstruct) {
ReportField rf("test_field", "test_field", "Test Field", 10, false, nullptr,
nullptr);
rf.setEnabled(true);
EXPECT_EQ(rf.name(), "test_field");
EXPECT_EQ(rf.title(), "Test Field");
EXPECT_EQ(rf.width(), 10);
EXPECT_FALSE(rf.leftJustify());
EXPECT_EQ(rf.unit(), nullptr);
EXPECT_TRUE(rf.enabled());
}
TEST_F(StaInitTest, ReportFieldSetEnabled) {
ReportField rf("f1", "f1", "F1", 8, true, nullptr, nullptr);
rf.setEnabled(true);
EXPECT_TRUE(rf.enabled());
rf.setEnabled(false);
EXPECT_FALSE(rf.enabled());
rf.setEnabled(true);
EXPECT_TRUE(rf.enabled());
}
TEST_F(StaInitTest, ReportFieldSetWidth) {
ReportField rf("f2", "f2", "F2", 5, false, nullptr, nullptr);
EXPECT_EQ(rf.width(), 5);
rf.setWidth(12);
EXPECT_EQ(rf.width(), 12);
}
TEST_F(StaInitTest, ReportFieldSetProperties) {
ReportField rf("f3", "f3", "F3", 5, false, nullptr, nullptr);
rf.setProperties("New Title", 20, true);
EXPECT_EQ(rf.title(), "New Title");
EXPECT_EQ(rf.width(), 20);
EXPECT_TRUE(rf.leftJustify());
}
TEST_F(StaInitTest, ReportFieldBlank) {
ReportField rf("f4", "f4", "F4", 3, false, nullptr, nullptr);
const std::string &blank = rf.blank();
EXPECT_FALSE(blank.empty());
}
// --- Sta.cc: idealClockMode is protected, test via public API ---
// --- Sta.cc: setCmdNamespace1 is protected, test via public API ---
// --- Sta.cc: readLibertyFile is protected, test via public readLiberty ---
// disable/removeDisable functions segfault on null args, skip
// Many Sta methods segfault on nullptr args rather than throwing.
// Skip all nullptr-based EXPECT_THROW tests to avoid crashes.
// --- PathEnd.cc: PathEndUnconstrained virtual methods ---
TEST_F(StaInitTest, PathEndUnconstrainedSlackNoCrpr) {
Path *p = new Path();
PathEndUnconstrained pe(p);
Slack s = pe.slackNoCrpr(sta_);
EXPECT_GT(s, 0.0f); // INF
}
TEST_F(StaInitTest, PathEndUnconstrainedMargin) {
Path *p = new Path();
PathEndUnconstrained pe(p);
ArcDelay m = pe.margin(sta_);
EXPECT_FLOAT_EQ(m, 0.0f);
}
// --- PathEnd.cc: setPath ---
TEST_F(StaInitTest, PathEndSetPath) {
Path *p1 = new Path();
Path *p2 = new Path();
PathEndUnconstrained pe(p1);
pe.setPath(p2);
EXPECT_EQ(pe.path(), p2);
}
// --- PathEnd.cc: targetClkPath and multiCyclePath (default returns) ---
TEST_F(StaInitTest, PathEndTargetClkPathDefault) {
Path *p = new Path();
PathEndUnconstrained pe(p);
EXPECT_EQ(pe.targetClkPath(), nullptr);
}
TEST_F(StaInitTest, PathEndMultiCyclePathDefault) {
Path *p = new Path();
PathEndUnconstrained pe(p);
EXPECT_EQ(pe.multiCyclePath(), nullptr);
}
// --- PathEnd.cc: crpr and borrow defaults ---
TEST_F(StaInitTest, PathEndCrprDefault) {
Path *p = new Path();
PathEndUnconstrained pe(p);
Crpr c = pe.crpr(sta_);
EXPECT_FLOAT_EQ(c, 0.0f);
}
TEST_F(StaInitTest, PathEndBorrowDefault) {
Path *p = new Path();
PathEndUnconstrained pe(p);
Arrival b = pe.borrow(sta_);
EXPECT_FLOAT_EQ(b, 0.0f);
}
// --- PathEnd.cc: sourceClkLatency, sourceClkInsertionDelay defaults ---
TEST_F(StaInitTest, PathEndSourceClkLatencyDefault) {
Path *p = new Path();
PathEndUnconstrained pe(p);
Delay lat = pe.sourceClkLatency(sta_);
EXPECT_FLOAT_EQ(lat, 0.0f);
}
TEST_F(StaInitTest, PathEndSourceClkInsertionDelayDefault) {
Path *p = new Path();
PathEndUnconstrained pe(p);
Delay ins = pe.sourceClkInsertionDelay(sta_);
EXPECT_FLOAT_EQ(ins, 0.0f);
}
// --- PathEnd.cc: various default accessors ---
TEST_F(StaInitTest, PathEndCheckArcDefault) {
Path *p = new Path();
PathEndUnconstrained pe(p);
EXPECT_EQ(pe.checkArc(), nullptr);
}
TEST_F(StaInitTest, PathEndDataClkPathDefault) {
Path *p = new Path();
PathEndUnconstrained pe(p);
EXPECT_EQ(pe.dataClkPath(), nullptr);
}
TEST_F(StaInitTest, PathEndPathDelayMarginIsExternal) {
Path *p = new Path();
PathEndUnconstrained pe(p);
EXPECT_FALSE(pe.pathDelayMarginIsExternal());
}
TEST_F(StaInitTest, PathEndPathDelayDefault) {
Path *p = new Path();
PathEndUnconstrained pe(p);
EXPECT_EQ(pe.pathDelay(), nullptr);
}
TEST_F(StaInitTest, PathEndMacroClkTreeDelay) {
Path *p = new Path();
PathEndUnconstrained pe(p);
EXPECT_FLOAT_EQ(pe.macroClkTreeDelay(sta_), 0.0f);
}
TEST_F(StaInitTest, PathEndIgnoreClkLatency) {
Path *p = new Path();
PathEndUnconstrained pe(p);
EXPECT_FALSE(pe.ignoreClkLatency(sta_));
}
// --- PathEnd.cc: deletePath declared but not defined, skip ---
// --- PathEnd.cc: setPathGroup and pathGroup ---
TEST_F(StaInitTest, PathEndSetPathGroup) {
Path *p = new Path();
PathEndUnconstrained pe(p);
EXPECT_EQ(pe.pathGroup(), nullptr);
// setPathGroup(nullptr) is a no-op essentially
pe.setPathGroup(nullptr);
EXPECT_EQ(pe.pathGroup(), nullptr);
}
// --- Search.cc: Search::initVars is called during construction ---
TEST_F(StaInitTest, SearchInitVarsViaSta) {
// initVars is called as part of Search constructor
// Verify search exists and can be accessed
Search *search = sta_->search();
EXPECT_NE(search, nullptr);
}
// --- Sta.cc: isGroupPathName ---
TEST_F(StaInitTest, StaIsGroupPathNameNonexistent) {
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
bool val = sta_->isGroupPathName("nonexistent_group", sta_->cmdSdc());
#pragma GCC diagnostic pop
EXPECT_FALSE(val);
}
// --- Sta.cc: Sta::sta() global singleton ---
TEST_F(StaInitTest, StaGlobalSingleton) {
Sta *global = Sta::sta();
EXPECT_EQ(global, sta_);
}
// --- PathEnd.cc: PathEnd type enum completeness ---
TEST_F(StaInitTest, PathEndTypeEnumAll) {
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);
}
// --- Search.cc: EvalPred ---
TEST_F(StaInitTest, EvalPredSetSearchThruLatches) {
EvalPred pred(sta_);
pred.setSearchThruLatches(true);
pred.setSearchThruLatches(false);
}
// --- CheckMaxSkews.cc: CheckMaxSkews destructor via Sta ---
TEST_F(StaInitTest, CheckMaxSkewsClear) {
// maxSkewSlack removed from Sta; verify reportMaxSkewChecks exists
auto fn = &Sta::reportMaxSkewChecks;
expectCallablePointerUsable(fn);
}
// CheckMinPeriods - minPeriodSlack removed; use reportMinPeriodChecks
TEST_F(StaInitTest, CheckMinPeriodsReportExists) {
auto fn = &Sta::reportMinPeriodChecks;
expectCallablePointerUsable(fn);
}
// CheckMinPulseWidths - minPulseWidthSlack removed; use reportMinPulseWidthChecks
TEST_F(StaInitTest, CheckMinPulseWidthsReportExists) {
auto fn = &Sta::reportMinPulseWidthChecks;
expectCallablePointerUsable(fn);
}
// --- Sim.cc: Sim::findLogicConstants ---
TEST_F(StaInitTest, SimFindLogicConstantsThrows) {
EXPECT_THROW(sta_->findLogicConstants(), Exception);
}
// --- Levelize.cc: GraphLoop requires Edge* args, skip default ctor test ---
// --- WorstSlack.cc ---
TEST_F(StaInitTest, WorstSlackExists) {
Slack (Sta::*fn)(const MinMax*) = &Sta::worstSlack;
expectCallablePointerUsable(fn);
}
// --- PathGroup.cc: PathGroup count via Sta ---
// --- ClkNetwork.cc: isClock, clocks, pins ---
// isClock(Net*) segfaults on nullptr, skip
// --- Corner.cc: corner operations ---
TEST_F(StaInitTest, CornerParasiticAPCount) {
Scene *corner = sta_->cmdScene();
ASSERT_NE(corner, nullptr);
// Just verify corner exists; parasiticAnalysisPtcount not available
}
// SearchPredNonReg2 removed from API
TEST_F(StaInitTest, SearchPred1Exists2) {
SearchPred1 pred(sta_);
// Just exercise constructor
}
// --- StaState.cc: units ---
TEST_F(StaInitTest, StaStateCopyUnits2) {
Units *units = sta_->units();
EXPECT_NE(units, nullptr);
}
// vertexWorstRequiredPath segfaults on null, skip
// --- Path.cc: Path less and lessAll ---
TEST_F(StaInitTest, PathLessFunction) {
auto fn = &Path::less;
expectCallablePointerUsable(fn);
}
TEST_F(StaInitTest, PathLessAllFunction) {
auto fn = &Path::lessAll;
expectCallablePointerUsable(fn);
}
// --- Path.cc: Path::init overloads ---
TEST_F(StaInitTest, PathInitFloatExists) {
auto fn = static_cast<void (Path::*)(Vertex*, const Arrival&, const StaState*)>(&Path::init);
expectCallablePointerUsable(fn);
}
TEST_F(StaInitTest, PathInitTagExists) {
auto fn = static_cast<void (Path::*)(Vertex*, Tag*, const StaState*)>(&Path::init);
expectCallablePointerUsable(fn);
}
// --- Path.cc: prevVertex, tagIndex, checkPrevPath ---
TEST_F(StaInitTest, PathPrevVertexExists) {
auto fn = &Path::prevVertex;
expectCallablePointerUsable(fn);
}
TEST_F(StaInitTest, PathTagIndexExists) {
auto fn = &Path::tagIndex;
expectCallablePointerUsable(fn);
}
TEST_F(StaInitTest, PathCheckPrevPathExists) {
auto fn = &Path::checkPrevPath;
expectCallablePointerUsable(fn);
}
// --- Property.cc: PropertyRegistry getProperty via Properties ---
TEST_F(StaInitTest, PropertiesGetPropertyLibraryExists) {
// getProperty(Library*) segfaults on nullptr - verify Properties can be constructed
Properties{sta_};
}
TEST_F(StaInitTest, PropertiesGetPropertyCellExists) {
// getProperty(Cell*) segfaults on nullptr - verify method exists via function pointer
using FnType = PropertyValue (Properties::*)(const Cell*, std::string_view);
FnType fn = &Properties::getProperty;
expectCallablePointerUsable(fn);
}
// --- Sta.cc: Sta global singleton ---
TEST_F(StaInitTest, StaGlobalSingleton3) {
Sta *global = Sta::sta();
EXPECT_EQ(global, sta_);
}
////////////////////////////////////////////////////////////////
// Round 4: Deep coverage targeting ~170 more uncovered functions
////////////////////////////////////////////////////////////////
// === Sta.cc simple getters/setters (no network required) ===
TEST_F(StaInitTest, StaArrivalsInvalid2) {
sta_->arrivalsInvalid();
}
TEST_F(StaInitTest, StaBidirectInstPathsEnabled2) {
sta_->bidirectInstPathsEnabled();
}
TEST_F(StaInitTest, StaBidirectNetPathsEnabled2) {
sta_->bidirectInstPathsEnabled();
}
TEST_F(StaInitTest, StaClkThruTristateEnabled2) {
sta_->clkThruTristateEnabled();
}
TEST_F(StaInitTest, StaCmdCornerConst) {
const Sta *csta = sta_;
Scene *c = csta->cmdScene();
EXPECT_NE(c, nullptr);
}
TEST_F(StaInitTest, StaCmdNamespace2) {
sta_->cmdNamespace();
}
TEST_F(StaInitTest, StaCondDefaultArcsEnabled2) {
sta_->condDefaultArcsEnabled();
}
TEST_F(StaInitTest, StaCrprEnabled2) {
sta_->crprEnabled();
}
TEST_F(StaInitTest, StaCrprMode) {
sta_->crprMode();
}
TEST_F(StaInitTest, StaCurrentInstance2) {
sta_->currentInstance();
}
TEST_F(StaInitTest, StaDefaultThreadCount2) {
int tc = sta_->defaultThreadCount();
EXPECT_GE(tc, 1);
}
TEST_F(StaInitTest, StaDelaysInvalid2) {
sta_->delaysInvalid(); // void return
}
TEST_F(StaInitTest, StaDynamicLoopBreaking) {
sta_->dynamicLoopBreaking();
}
TEST_F(StaInitTest, StaGatedClkChecksEnabled2) {
sta_->gatedClkChecksEnabled();
}
TEST_F(StaInitTest, StaMultiCorner2) {
sta_->multiScene();
}
TEST_F(StaInitTest, StaPocvMode3) {
sta_->pocvMode();
}
TEST_F(StaInitTest, StaPresetClrArcsEnabled2) {
sta_->presetClrArcsEnabled();
}
TEST_F(StaInitTest, StaPropagateAllClocks2) {
sta_->propagateAllClocks();
}
TEST_F(StaInitTest, StaPropagateGatedClockEnable2) {
sta_->propagateGatedClockEnable();
}
TEST_F(StaInitTest, StaRecoveryRemovalChecksEnabled2) {
sta_->recoveryRemovalChecksEnabled();
}
TEST_F(StaInitTest, StaUseDefaultArrivalClock) {
sta_->useDefaultArrivalClock();
}
TEST_F(StaInitTest, StaTagCount2) {
int tc = sta_->tagCount();
EXPECT_GE(tc, 0);
}
TEST_F(StaInitTest, StaTagGroupCount2) {
int tgc = sta_->tagGroupCount();
EXPECT_GE(tgc, 0);
}
TEST_F(StaInitTest, StaClkInfoCount2) {
int cnt = sta_->clkInfoCount();
EXPECT_GE(cnt, 0);
}
// === Sta.cc simple setters (no network required) ===
TEST_F(StaInitTest, StaSetBidirectInstPathsEnabled2) {
sta_->setBidirectInstPathsEnabled(true);
EXPECT_TRUE(sta_->bidirectInstPathsEnabled());
sta_->setBidirectInstPathsEnabled(false);
EXPECT_FALSE(sta_->bidirectInstPathsEnabled());
}
TEST_F(StaInitTest, StaSetBidirectNetPathsEnabled2) {
// bidirectInstPathsEnabled has been removed
sta_->setBidirectInstPathsEnabled(true);
EXPECT_TRUE(sta_->bidirectInstPathsEnabled());
sta_->setBidirectInstPathsEnabled(false);
EXPECT_FALSE(sta_->bidirectInstPathsEnabled());
}
TEST_F(StaInitTest, StaSetClkThruTristateEnabled2) {
sta_->setClkThruTristateEnabled(true);
EXPECT_TRUE(sta_->clkThruTristateEnabled());
sta_->setClkThruTristateEnabled(false);
}
TEST_F(StaInitTest, StaSetCondDefaultArcsEnabled2) {
sta_->setCondDefaultArcsEnabled(true);
EXPECT_TRUE(sta_->condDefaultArcsEnabled());
sta_->setCondDefaultArcsEnabled(false);
}
TEST_F(StaInitTest, StaSetCrprEnabled2) {
sta_->setCrprEnabled(true);
EXPECT_TRUE(sta_->crprEnabled());
sta_->setCrprEnabled(false);
}
TEST_F(StaInitTest, StaSetDynamicLoopBreaking) {
sta_->setDynamicLoopBreaking(true);
EXPECT_TRUE(sta_->dynamicLoopBreaking());
sta_->setDynamicLoopBreaking(false);
}
TEST_F(StaInitTest, StaSetGatedClkChecksEnabled2) {
sta_->setGatedClkChecksEnabled(true);
EXPECT_TRUE(sta_->gatedClkChecksEnabled());
sta_->setGatedClkChecksEnabled(false);
}
TEST_F(StaInitTest, StaSetPocvMode3) {
sta_->setPocvMode(PocvMode::normal);
EXPECT_EQ(sta_->pocvMode(), PocvMode::normal);
sta_->setPocvMode(PocvMode::scalar);
}
TEST_F(StaInitTest, StaSetPresetClrArcsEnabled2) {
sta_->setPresetClrArcsEnabled(true);
EXPECT_TRUE(sta_->presetClrArcsEnabled());
sta_->setPresetClrArcsEnabled(false);
}
TEST_F(StaInitTest, StaSetPropagateAllClocks2) {
sta_->setPropagateAllClocks(true);
EXPECT_TRUE(sta_->propagateAllClocks());
sta_->setPropagateAllClocks(false);
}
TEST_F(StaInitTest, StaSetPropagateGatedClockEnable2) {
sta_->setPropagateGatedClockEnable(true);
EXPECT_TRUE(sta_->propagateGatedClockEnable());
sta_->setPropagateGatedClockEnable(false);
}
TEST_F(StaInitTest, StaSetRecoveryRemovalChecksEnabled2) {
sta_->setRecoveryRemovalChecksEnabled(true);
EXPECT_TRUE(sta_->recoveryRemovalChecksEnabled());
sta_->setRecoveryRemovalChecksEnabled(false);
}
TEST_F(StaInitTest, StaSetUseDefaultArrivalClock) {
sta_->setUseDefaultArrivalClock(true);
EXPECT_TRUE(sta_->useDefaultArrivalClock());
sta_->setUseDefaultArrivalClock(false);
}
TEST_F(StaInitTest, StaSetIncrementalDelayTolerance) {
sta_->setIncrementalDelayTolerance(0.5f);
}
// StaSetSigmaFactor2 test removed: setSigmaFactor API removed
TEST_F(StaInitTest, StaSetReportPathDigits) {
sta_->setReportPathDigits(4);
}
TEST_F(StaInitTest, StaSetReportPathFormat) {
sta_->setReportPathFormat(ReportPathFormat::full);
}
TEST_F(StaInitTest, StaSetReportPathNoSplit) {
sta_->setReportPathNoSplit(true);
sta_->setReportPathNoSplit(false);
}
// StaSetReportPathSigmas test removed: setReportPathSigmas API removed
TEST_F(StaInitTest, StaSetMaxArea) {
sta_->setMaxArea(100.0f, sta_->cmdSdc());
}
TEST_F(StaInitTest, StaSetWireloadMode2) {
sta_->setWireloadMode(WireloadMode::top, sta_->cmdSdc());
}
TEST_F(StaInitTest, StaSetThreadCount2) {
sta_->setThreadCount(1);
}
// setThreadCount1 is protected, skip
TEST_F(StaInitTest, StaConstraintsChanged2) {
sta_->delaysInvalid();
}
TEST_F(StaInitTest, StaDeleteParasitics3) {
sta_->deleteParasitics();
}
// networkCmdEdit is protected, skip
TEST_F(StaInitTest, StaClearLogicConstants3) {
sta_->clearLogicConstants();
}
TEST_F(StaInitTest, StaRemoveDelaySlewAnnotations2) {
sta_->removeDelaySlewAnnotations();
}
TEST_F(StaInitTest, StaRemoveNetLoadCaps2) {
sta_->removeNetLoadCaps(sta_->cmdSdc());
}
TEST_F(StaInitTest, StaClkPinsInvalid3) {
// clkPinsInvalid requires a linked network; expect throw without one
EXPECT_ANY_THROW(sta_->clkPinsInvalid(sta_->cmdMode()));
}
// disableAfter is protected, skip
TEST_F(StaInitTest, StaNetworkChanged2) {
sta_->networkChanged();
}
TEST_F(StaInitTest, StaUnsetTimingDerate2) {
sta_->unsetTimingDerate(sta_->cmdSdc());
}
TEST_F(StaInitTest, StaSetCmdNamespace) {
sta_->setCmdNamespace(CmdNamespace::sdc);
}
TEST_F(StaInitTest, StaSetCmdCorner2) {
Scene *corner = sta_->cmdScene();
sta_->setCmdScene(corner);
}
} // namespace sta