#include #include #include "VerilogNamespace.hh" #include "PortDirection.hh" #include "ConcreteLibrary.hh" #include "ConcreteNetwork.hh" #include "HpinDrvrLoad.hh" #include "Network.hh" #include "PatternMatch.hh" #include "NetworkCmp.hh" #include "SdcNetwork.hh" #include "ContainerHelpers.hh" namespace sta { class VerilogNamespaceTest : public ::testing::Test {}; // Simple names should pass through unchanged TEST_F(VerilogNamespaceTest, CellSimpleName) { std::string result = cellVerilogName("INV_X1"); EXPECT_EQ(result, "INV_X1"); } // Escaped names in STA have backslash prefix TEST_F(VerilogNamespaceTest, CellEscapedName) { std::string result = cellVerilogName("\\my/cell"); // Verilog escaped names have backslash prefix and space suffix EXPECT_FALSE(result.empty()); } TEST_F(VerilogNamespaceTest, InstanceSimpleName) { std::string result = instanceVerilogName("u1"); EXPECT_EQ(result, "u1"); } TEST_F(VerilogNamespaceTest, InstanceHierarchicalName) { std::string result = instanceVerilogName("u1/u2"); EXPECT_FALSE(result.empty()); } TEST_F(VerilogNamespaceTest, NetSimpleName) { std::string result = netVerilogName("wire1"); EXPECT_EQ(result, "wire1"); } TEST_F(VerilogNamespaceTest, NetBusName) { std::string result = netVerilogName("bus[0]"); EXPECT_FALSE(result.empty()); } TEST_F(VerilogNamespaceTest, PortSimpleName) { std::string result = portVerilogName("clk"); EXPECT_EQ(result, "clk"); } TEST_F(VerilogNamespaceTest, PortBusName) { std::string result = portVerilogName("data[7]"); EXPECT_FALSE(result.empty()); } // Test Verilog-to-STA conversion TEST_F(VerilogNamespaceTest, ModuleVerilogToSta) { std::string verilog_name = "top_module"; std::string result = moduleVerilogToSta(&verilog_name); EXPECT_EQ(result, "top_module"); } TEST_F(VerilogNamespaceTest, InstanceVerilogToSta) { std::string verilog_name = "u1"; std::string result = instanceVerilogToSta(&verilog_name); EXPECT_EQ(result, "u1"); } // Test escaped name round-trip TEST_F(VerilogNamespaceTest, EscapedNameRoundTrip) { std::string verilog_name = "\\esc_name "; std::string sta = instanceVerilogToSta(&verilog_name); EXPECT_FALSE(sta.empty()); } //////////////////////////////////////////////////////////////// // PortDirection tests - covers init, find, isAnyInput, isAnyOutput, // isAnyTristate, isPowerGround, and all identity predicates //////////////////////////////////////////////////////////////// class PortDirectionTest : public ::testing::Test { protected: void SetUp() override { // PortDirection::init() should have been called by initSta or similar. // If not already initialized, we need to call it. if (PortDirection::input() == nullptr) { PortDirection::init(); } } }; TEST_F(PortDirectionTest, InputSingleton) { PortDirection *dir = PortDirection::input(); EXPECT_NE(dir, nullptr); EXPECT_STREQ(dir->name(), "input"); EXPECT_EQ(dir->index(), 0); EXPECT_TRUE(dir->isInput()); EXPECT_FALSE(dir->isOutput()); EXPECT_FALSE(dir->isTristate()); EXPECT_FALSE(dir->isBidirect()); EXPECT_FALSE(dir->isInternal()); EXPECT_FALSE(dir->isGround()); EXPECT_FALSE(dir->isPower()); EXPECT_FALSE(dir->isUnknown()); } TEST_F(PortDirectionTest, OutputSingleton) { PortDirection *dir = PortDirection::output(); EXPECT_NE(dir, nullptr); EXPECT_STREQ(dir->name(), "output"); EXPECT_EQ(dir->index(), 1); EXPECT_TRUE(dir->isOutput()); EXPECT_FALSE(dir->isInput()); } TEST_F(PortDirectionTest, TristateSingleton) { PortDirection *dir = PortDirection::tristate(); EXPECT_NE(dir, nullptr); EXPECT_STREQ(dir->name(), "tristate"); EXPECT_EQ(dir->index(), 2); EXPECT_TRUE(dir->isTristate()); EXPECT_FALSE(dir->isInput()); EXPECT_FALSE(dir->isOutput()); } TEST_F(PortDirectionTest, BidirectSingleton) { PortDirection *dir = PortDirection::bidirect(); EXPECT_NE(dir, nullptr); EXPECT_STREQ(dir->name(), "bidirect"); EXPECT_EQ(dir->index(), 3); EXPECT_TRUE(dir->isBidirect()); } TEST_F(PortDirectionTest, InternalSingleton) { PortDirection *dir = PortDirection::internal(); EXPECT_NE(dir, nullptr); EXPECT_STREQ(dir->name(), "internal"); EXPECT_EQ(dir->index(), 4); EXPECT_TRUE(dir->isInternal()); } TEST_F(PortDirectionTest, GroundSingleton) { PortDirection *dir = PortDirection::ground(); EXPECT_NE(dir, nullptr); EXPECT_STREQ(dir->name(), "ground"); EXPECT_EQ(dir->index(), 5); EXPECT_TRUE(dir->isGround()); } TEST_F(PortDirectionTest, PowerSingleton) { PortDirection *dir = PortDirection::power(); EXPECT_NE(dir, nullptr); EXPECT_STREQ(dir->name(), "power"); EXPECT_EQ(dir->index(), 6); EXPECT_TRUE(dir->isPower()); } TEST_F(PortDirectionTest, UnknownSingleton) { PortDirection *dir = PortDirection::unknown(); EXPECT_NE(dir, nullptr); EXPECT_STREQ(dir->name(), "unknown"); EXPECT_EQ(dir->index(), 7); EXPECT_TRUE(dir->isUnknown()); } TEST_F(PortDirectionTest, FindByName) { EXPECT_EQ(PortDirection::find("input"), PortDirection::input()); EXPECT_EQ(PortDirection::find("output"), PortDirection::output()); EXPECT_EQ(PortDirection::find("tristate"), PortDirection::tristate()); EXPECT_EQ(PortDirection::find("bidirect"), PortDirection::bidirect()); EXPECT_EQ(PortDirection::find("internal"), PortDirection::internal()); EXPECT_EQ(PortDirection::find("ground"), PortDirection::ground()); EXPECT_EQ(PortDirection::find("power"), PortDirection::power()); EXPECT_EQ(PortDirection::find("nonexistent"), nullptr); } TEST_F(PortDirectionTest, IsAnyInput) { EXPECT_TRUE(PortDirection::input()->isAnyInput()); EXPECT_TRUE(PortDirection::bidirect()->isAnyInput()); EXPECT_FALSE(PortDirection::output()->isAnyInput()); EXPECT_FALSE(PortDirection::tristate()->isAnyInput()); EXPECT_FALSE(PortDirection::internal()->isAnyInput()); EXPECT_FALSE(PortDirection::ground()->isAnyInput()); EXPECT_FALSE(PortDirection::power()->isAnyInput()); EXPECT_FALSE(PortDirection::unknown()->isAnyInput()); } TEST_F(PortDirectionTest, IsAnyOutput) { EXPECT_TRUE(PortDirection::output()->isAnyOutput()); EXPECT_TRUE(PortDirection::tristate()->isAnyOutput()); EXPECT_TRUE(PortDirection::bidirect()->isAnyOutput()); EXPECT_FALSE(PortDirection::input()->isAnyOutput()); EXPECT_FALSE(PortDirection::internal()->isAnyOutput()); EXPECT_FALSE(PortDirection::ground()->isAnyOutput()); EXPECT_FALSE(PortDirection::power()->isAnyOutput()); EXPECT_FALSE(PortDirection::unknown()->isAnyOutput()); } TEST_F(PortDirectionTest, IsAnyTristate) { EXPECT_TRUE(PortDirection::tristate()->isAnyTristate()); EXPECT_TRUE(PortDirection::bidirect()->isAnyTristate()); EXPECT_FALSE(PortDirection::input()->isAnyTristate()); EXPECT_FALSE(PortDirection::output()->isAnyTristate()); EXPECT_FALSE(PortDirection::internal()->isAnyTristate()); EXPECT_FALSE(PortDirection::ground()->isAnyTristate()); EXPECT_FALSE(PortDirection::power()->isAnyTristate()); EXPECT_FALSE(PortDirection::unknown()->isAnyTristate()); } TEST_F(PortDirectionTest, IsPowerGround) { EXPECT_TRUE(PortDirection::power()->isPowerGround()); EXPECT_TRUE(PortDirection::ground()->isPowerGround()); EXPECT_FALSE(PortDirection::input()->isPowerGround()); EXPECT_FALSE(PortDirection::output()->isPowerGround()); EXPECT_FALSE(PortDirection::tristate()->isPowerGround()); EXPECT_FALSE(PortDirection::bidirect()->isPowerGround()); EXPECT_FALSE(PortDirection::internal()->isPowerGround()); EXPECT_FALSE(PortDirection::unknown()->isPowerGround()); } //////////////////////////////////////////////////////////////// // ConcreteLibrary tests //////////////////////////////////////////////////////////////// TEST(ConcreteLibraryTest, CreateAndFind) { ConcreteLibrary lib("test_lib", "test.lib", false); EXPECT_STREQ(lib.name(), "test_lib"); EXPECT_STREQ(lib.filename(), "test.lib"); EXPECT_FALSE(lib.isLiberty()); } TEST(ConcreteLibraryTest, BusBrackets) { ConcreteLibrary lib("test_lib", "test.lib", false); lib.setBusBrkts('[', ']'); EXPECT_EQ(lib.busBrktLeft(), '['); EXPECT_EQ(lib.busBrktRight(), ']'); } TEST(ConcreteLibraryTest, MakeCell) { ConcreteLibrary lib("test_lib", "test.lib", false); ConcreteCell *cell = lib.makeCell("INV", true, "inv.v"); EXPECT_NE(cell, nullptr); EXPECT_STREQ(cell->name(), "INV"); EXPECT_STREQ(cell->filename(), "inv.v"); EXPECT_TRUE(cell->isLeaf()); EXPECT_EQ(cell->library(), &lib); ConcreteCell *found = lib.findCell("INV"); EXPECT_EQ(found, cell); ConcreteCell *not_found = lib.findCell("NAND2"); EXPECT_EQ(not_found, nullptr); } TEST(ConcreteLibraryTest, DeleteCell) { ConcreteLibrary lib("test_lib", "test.lib", false); lib.makeCell("BUF", true, ""); ConcreteCell *found = lib.findCell("BUF"); EXPECT_NE(found, nullptr); lib.deleteCell(found); ConcreteCell *deleted = lib.findCell("BUF"); EXPECT_EQ(deleted, nullptr); } TEST(ConcreteLibraryTest, CellIterator) { ConcreteLibrary lib("test_lib", "test.lib", false); lib.makeCell("INV", true, ""); lib.makeCell("BUF", true, ""); lib.makeCell("NAND2", true, ""); ConcreteLibraryCellIterator *iter = lib.cellIterator(); int count = 0; while (iter->hasNext()) { iter->next(); count++; } delete iter; EXPECT_EQ(count, 3); } TEST(ConcreteLibraryTest, IsLiberty) { ConcreteLibrary lib("test_lib", "test.lib", true); EXPECT_TRUE(lib.isLiberty()); ConcreteLibrary lib2("test_lib2", "test2.lib", false); EXPECT_FALSE(lib2.isLiberty()); } //////////////////////////////////////////////////////////////// // ConcreteCell tests //////////////////////////////////////////////////////////////// TEST(ConcreteCellTest, MakePort) { ConcreteLibrary lib("test_lib", "test.lib", false); ConcreteCell *cell = lib.makeCell("INV", true, ""); ConcretePort *port_a = cell->makePort("A"); EXPECT_NE(port_a, nullptr); EXPECT_STREQ(port_a->name(), "A"); EXPECT_EQ(port_a->cell(), reinterpret_cast(cell)); ConcretePort *found = cell->findPort("A"); EXPECT_EQ(found, port_a); ConcretePort *not_found = cell->findPort("B"); EXPECT_EQ(not_found, nullptr); } TEST(ConcreteCellTest, PortCount) { ConcreteLibrary lib("test_lib", "test.lib", false); ConcreteCell *cell = lib.makeCell("NAND2", true, ""); cell->makePort("A"); cell->makePort("B"); cell->makePort("Y"); EXPECT_EQ(cell->portCount(), 3u); } TEST(ConcreteCellTest, SetIsLeaf) { ConcreteLibrary lib("test_lib", "test.lib", false); ConcreteCell *cell = lib.makeCell("TOP", false, ""); EXPECT_FALSE(cell->isLeaf()); cell->setIsLeaf(true); EXPECT_TRUE(cell->isLeaf()); } TEST(ConcreteCellTest, PortBitCount) { ConcreteLibrary lib("test_lib", "test.lib", false); ConcreteCell *cell = lib.makeCell("BUF", true, ""); cell->makePort("A"); cell->makePort("Y"); EXPECT_EQ(cell->portBitCount(), 2); } TEST(ConcreteCellTest, MakeBusPort) { ConcreteLibrary lib("test_lib", "test.lib", false); lib.setBusBrkts('[', ']'); ConcreteCell *cell = lib.makeCell("REG", true, ""); ConcretePort *bus = cell->makeBusPort("D", 3, 0); EXPECT_NE(bus, nullptr); EXPECT_TRUE(bus->isBus()); EXPECT_EQ(bus->fromIndex(), 3); EXPECT_EQ(bus->toIndex(), 0); EXPECT_EQ(bus->size(), 4); } TEST(ConcreteCellTest, AttributeMap) { ConcreteLibrary lib("test_lib", "test.lib", false); ConcreteCell *cell = lib.makeCell("INV", true, ""); cell->setAttribute("area", "1.5"); EXPECT_EQ(cell->getAttribute("area"), "1.5"); EXPECT_EQ(cell->getAttribute("nonexistent"), ""); } TEST(ConcreteCellTest, SetName) { ConcreteLibrary lib("test_lib", "test.lib", false); ConcreteCell *cell = lib.makeCell("OLD", true, ""); EXPECT_STREQ(cell->name(), "OLD"); cell->setName("NEW"); EXPECT_STREQ(cell->name(), "NEW"); } TEST(ConcreteCellTest, PortIterator) { ConcreteLibrary lib("test_lib", "test.lib", false); ConcreteCell *cell = lib.makeCell("AND2", true, ""); cell->makePort("A"); cell->makePort("B"); cell->makePort("Y"); ConcreteCellPortIterator *iter = cell->portIterator(); int count = 0; while (iter->hasNext()) { iter->next(); count++; } delete iter; EXPECT_EQ(count, 3); } TEST(ConcreteCellTest, PortBitIterator) { ConcreteLibrary lib("test_lib", "test.lib", false); lib.setBusBrkts('[', ']'); ConcreteCell *cell = lib.makeCell("REG", true, ""); cell->makePort("CLK"); cell->makeBusPort("D", 1, 0); // 2-bit bus cell->makePort("Q"); ConcreteCellPortBitIterator *iter = cell->portBitIterator(); int count = 0; while (iter->hasNext()) { iter->next(); count++; } delete iter; // CLK(1) + D[0],D[1](2) + Q(1) = 4 EXPECT_EQ(count, 4); } //////////////////////////////////////////////////////////////// // ConcretePort tests //////////////////////////////////////////////////////////////// TEST(ConcretePortTest, ScalarPortProperties) { ConcreteLibrary lib("test_lib", "test.lib", false); ConcreteCell *cell = lib.makeCell("INV", true, ""); ConcretePort *port = cell->makePort("A"); EXPECT_FALSE(port->isBus()); EXPECT_FALSE(port->isBundle()); EXPECT_FALSE(port->isBusBit()); EXPECT_FALSE(port->hasMembers()); EXPECT_EQ(port->size(), 1); } TEST(ConcretePortTest, SetDirection) { if (PortDirection::input() == nullptr) { PortDirection::init(); } ConcreteLibrary lib("test_lib", "test.lib", false); ConcreteCell *cell = lib.makeCell("INV", true, ""); ConcretePort *port = cell->makePort("A"); port->setDirection(PortDirection::input()); EXPECT_EQ(port->direction(), PortDirection::input()); EXPECT_TRUE(port->direction()->isInput()); } TEST(ConcretePortTest, BusPortBit) { ConcreteLibrary lib("test_lib", "test.lib", false); lib.setBusBrkts('[', ']'); ConcreteCell *cell = lib.makeCell("REG", true, ""); ConcretePort *bus = cell->makeBusPort("D", 3, 0); EXPECT_TRUE(bus->isBus()); EXPECT_TRUE(bus->hasMembers()); EXPECT_EQ(bus->size(), 4); ConcretePort *bit0 = bus->findBusBit(0); EXPECT_NE(bit0, nullptr); EXPECT_TRUE(bit0->isBusBit()); ConcretePort *bit3 = bus->findBusBit(3); EXPECT_NE(bit3, nullptr); // Out of range ConcretePort *bit_oor = bus->findBusBit(4); EXPECT_EQ(bit_oor, nullptr); } TEST(ConcretePortTest, BusIndexInRange) { ConcreteLibrary lib("test_lib", "test.lib", false); lib.setBusBrkts('[', ']'); ConcreteCell *cell = lib.makeCell("REG", true, ""); ConcretePort *bus = cell->makeBusPort("D", 3, 0); EXPECT_TRUE(bus->busIndexInRange(0)); EXPECT_TRUE(bus->busIndexInRange(1)); EXPECT_TRUE(bus->busIndexInRange(2)); EXPECT_TRUE(bus->busIndexInRange(3)); EXPECT_FALSE(bus->busIndexInRange(4)); EXPECT_FALSE(bus->busIndexInRange(-1)); } TEST(ConcretePortTest, MemberIterator) { ConcreteLibrary lib("test_lib", "test.lib", false); lib.setBusBrkts('[', ']'); ConcreteCell *cell = lib.makeCell("REG", true, ""); ConcretePort *bus = cell->makeBusPort("D", 1, 0); ConcretePortMemberIterator *iter = bus->memberIterator(); int count = 0; while (iter->hasNext()) { iter->next(); count++; } delete iter; EXPECT_EQ(count, 2); } TEST(ConcretePortTest, PinIndex) { ConcreteLibrary lib("test_lib", "test.lib", false); ConcreteCell *cell = lib.makeCell("INV", true, ""); ConcretePort *a = cell->makePort("A"); ConcretePort *y = cell->makePort("Y"); // Pin indices are assigned sequentially EXPECT_EQ(a->pinIndex(), 0); EXPECT_EQ(y->pinIndex(), 1); } //////////////////////////////////////////////////////////////// // HpinDrvrLoad tests - basic construction and comparison // Note: The 2-arg constructor does NOT initialize hpins_from_drvr_ // and hpins_to_load_, so we use 4-arg constructor for safe tests. //////////////////////////////////////////////////////////////// TEST(HpinDrvrLoadTest, FullConstructorNull) { // Test the 4-arg constructor with null pin sets HpinDrvrLoad hdl(nullptr, nullptr, nullptr, nullptr); EXPECT_EQ(hdl.drvr(), nullptr); EXPECT_EQ(hdl.load(), nullptr); EXPECT_EQ(hdl.hpinsFromDrvr(), nullptr); EXPECT_EQ(hdl.hpinsToLoad(), nullptr); } TEST(HpinDrvrLoadTest, FullConstructorWithPins) { int fake_drvr = 1; int fake_load = 2; const Pin *drvr = reinterpret_cast(&fake_drvr); const Pin *load = reinterpret_cast(&fake_load); HpinDrvrLoad hdl(drvr, load, nullptr, nullptr); EXPECT_EQ(hdl.drvr(), drvr); EXPECT_EQ(hdl.load(), load); EXPECT_EQ(hdl.hpinsFromDrvr(), nullptr); EXPECT_EQ(hdl.hpinsToLoad(), nullptr); } TEST(HpinDrvrLoadTest, SetDrvr) { int fake_drvr = 1; const Pin *drvr = reinterpret_cast(&fake_drvr); HpinDrvrLoad hdl(nullptr, nullptr, nullptr, nullptr); hdl.setDrvr(drvr); EXPECT_EQ(hdl.drvr(), drvr); } TEST(HpinDrvrLoadTest, LessComparisonDifferentLoads) { int a = 1, b = 2, c = 3, d = 4; const Pin *pin_a = reinterpret_cast(&a); const Pin *pin_b = reinterpret_cast(&b); const Pin *pin_c = reinterpret_cast(&c); const Pin *pin_d = reinterpret_cast(&d); HpinDrvrLoad hdl1(pin_a, pin_c, nullptr, nullptr); HpinDrvrLoad hdl2(pin_b, pin_d, nullptr, nullptr); HpinDrvrLoadLess less; // Compare by load first bool result1 = less(&hdl1, &hdl2); bool result2 = less(&hdl2, &hdl1); // Exactly one must be true (different loads) EXPECT_NE(result1, result2); } TEST(HpinDrvrLoadTest, LessComparisonSameLoad) { int a = 1, b = 2; const Pin *pin_a = reinterpret_cast(&a); const Pin *pin_b = reinterpret_cast(&b); // Same load pointer, different driver pointers HpinDrvrLoad hdl1(pin_a, pin_a, nullptr, nullptr); HpinDrvrLoad hdl2(pin_b, pin_a, nullptr, nullptr); HpinDrvrLoadLess less; // Same load -> compare drivers bool result1 = less(&hdl1, &hdl2); bool result2 = less(&hdl2, &hdl1); EXPECT_NE(result1, result2); } TEST(HpinDrvrLoadTest, LessComparisonEqual) { int a = 1; const Pin *pin = reinterpret_cast(&a); HpinDrvrLoad hdl1(pin, pin, nullptr, nullptr); HpinDrvrLoad hdl2(pin, pin, nullptr, nullptr); HpinDrvrLoadLess less; EXPECT_FALSE(less(&hdl1, &hdl2)); EXPECT_FALSE(less(&hdl2, &hdl1)); } TEST(HpinDrvrLoadTest, NullDrvrAndLoad) { HpinDrvrLoad hdl(nullptr, nullptr, nullptr, nullptr); EXPECT_EQ(hdl.drvr(), nullptr); EXPECT_EQ(hdl.load(), nullptr); // Set driver int fake = 42; const Pin *pin = reinterpret_cast(&fake); hdl.setDrvr(pin); EXPECT_EQ(hdl.drvr(), pin); EXPECT_EQ(hdl.load(), nullptr); } //////////////////////////////////////////////////////////////// // ConcreteNetwork creation tests //////////////////////////////////////////////////////////////// TEST(ConcreteNetworkTest, FindLibrary) { ConcreteNetwork network; // No libraries initially Library *lib = network.findLibrary("nonexistent"); EXPECT_EQ(lib, nullptr); } //////////////////////////////////////////////////////////////// // Additional ConcreteCell tests for coverage //////////////////////////////////////////////////////////////// TEST(ConcreteCellTest, SetLibertyCell) { ConcreteLibrary lib("test_lib", "test.lib", false); ConcreteCell *cell = lib.makeCell("INV", true, ""); // Initially null EXPECT_EQ(cell->libertyCell(), nullptr); // setLibertyCell is used when liberty parsing assigns the cell cell->setLibertyCell(nullptr); EXPECT_EQ(cell->libertyCell(), nullptr); } TEST(ConcreteCellTest, SetExtCell) { ConcreteLibrary lib("test_lib", "test.lib", false); ConcreteCell *cell = lib.makeCell("INV", true, ""); EXPECT_EQ(cell->extCell(), nullptr); int dummy = 42; cell->setExtCell(&dummy); EXPECT_EQ(cell->extCell(), &dummy); } TEST(ConcreteCellTest, MakeBundlePort) { ConcreteLibrary lib("test_lib", "test.lib", false); ConcreteCell *cell = lib.makeCell("MUX", true, ""); ConcretePort *a = cell->makePort("A"); ConcretePort *b = cell->makePort("B"); ConcretePortSeq *members = new ConcretePortSeq; members->push_back(a); members->push_back(b); ConcretePort *bundle = cell->makeBundlePort("AB", members); EXPECT_NE(bundle, nullptr); EXPECT_TRUE(bundle->isBundle()); EXPECT_TRUE(bundle->hasMembers()); EXPECT_EQ(bundle->size(), 2); } TEST(ConcreteCellTest, MakeBusPortAscending) { ConcreteLibrary lib("test_lib", "test.lib", false); lib.setBusBrkts('[', ']'); ConcreteCell *cell = lib.makeCell("REG", true, ""); // Ascending index: from_index < to_index ConcretePort *bus = cell->makeBusPort("D", 0, 3); EXPECT_NE(bus, nullptr); EXPECT_TRUE(bus->isBus()); EXPECT_EQ(bus->fromIndex(), 0); EXPECT_EQ(bus->toIndex(), 3); EXPECT_EQ(bus->size(), 4); } TEST(ConcreteCellTest, Filename) { ConcreteLibrary lib("test_lib", "test.lib", false); ConcreteCell *cell = lib.makeCell("INV", true, "test_cell.v"); EXPECT_STREQ(cell->filename(), "test_cell.v"); ConcreteCell *cell2 = lib.makeCell("BUF", true, ""); EXPECT_STREQ(cell2->filename(), ""); } TEST(ConcreteCellTest, FindCellsMatching) { ConcreteLibrary lib("test_lib", "test.lib", false); lib.makeCell("INV_X1", true, ""); lib.makeCell("INV_X2", true, ""); lib.makeCell("BUF_X1", true, ""); // Pattern that matches all INV cells PatternMatch pattern("INV*", false, false, nullptr); auto matches = lib.findCellsMatching(&pattern); EXPECT_EQ(matches.size(), 2u); } //////////////////////////////////////////////////////////////// // Additional ConcretePort tests for coverage //////////////////////////////////////////////////////////////// TEST(ConcretePortTest, SetLibertyPort) { ConcreteLibrary lib("test_lib", "test.lib", false); ConcreteCell *cell = lib.makeCell("INV", true, ""); ConcretePort *port = cell->makePort("A"); EXPECT_EQ(port->libertyPort(), nullptr); port->setLibertyPort(nullptr); EXPECT_EQ(port->libertyPort(), nullptr); } TEST(ConcretePortTest, SetExtPort) { ConcreteLibrary lib("test_lib", "test.lib", false); ConcreteCell *cell = lib.makeCell("INV", true, ""); ConcretePort *port = cell->makePort("A"); EXPECT_EQ(port->extPort(), nullptr); int dummy = 42; port->setExtPort(&dummy); EXPECT_EQ(port->extPort(), &dummy); } TEST(ConcretePortTest, BusPortBusName) { ConcreteLibrary lib("test_lib", "test.lib", false); lib.setBusBrkts('[', ']'); ConcreteCell *cell = lib.makeCell("REG", true, ""); ConcretePort *bus = cell->makeBusPort("D", 3, 0); const char *bus_name = bus->busName(); EXPECT_NE(bus_name, nullptr); // Should contain bus bracket notation std::string name_str(bus_name); EXPECT_NE(name_str.find("["), std::string::npos); } TEST(ConcretePortTest, ScalarBusName) { ConcreteLibrary lib("test_lib", "test.lib", false); ConcreteCell *cell = lib.makeCell("INV", true, ""); ConcretePort *port = cell->makePort("A"); // Scalar port busName returns just the name const char *bus_name = port->busName(); EXPECT_STREQ(bus_name, "A"); } TEST(ConcretePortTest, FindMember) { ConcreteLibrary lib("test_lib", "test.lib", false); lib.setBusBrkts('[', ']'); ConcreteCell *cell = lib.makeCell("REG", true, ""); ConcretePort *bus = cell->makeBusPort("D", 3, 0); // findMember gets member by index in the member array ConcretePort *member0 = bus->findMember(0); EXPECT_NE(member0, nullptr); ConcretePort *member3 = bus->findMember(3); EXPECT_NE(member3, nullptr); } TEST(ConcretePortTest, SetPinIndex) { ConcreteLibrary lib("test_lib", "test.lib", false); ConcreteCell *cell = lib.makeCell("INV", true, ""); ConcretePort *port = cell->makePort("A"); // Pin index is auto-assigned int orig = port->pinIndex(); port->setPinIndex(42); EXPECT_EQ(port->pinIndex(), 42); // Restore port->setPinIndex(orig); } TEST(ConcretePortTest, BusBitIndex) { ConcreteLibrary lib("test_lib", "test.lib", false); lib.setBusBrkts('[', ']'); ConcreteCell *cell = lib.makeCell("REG", true, ""); ConcretePort *bus = cell->makeBusPort("D", 3, 0); ConcretePort *bit0 = bus->findBusBit(0); EXPECT_NE(bit0, nullptr); EXPECT_TRUE(bit0->isBusBit()); EXPECT_EQ(bit0->busBitIndex(), 0); } TEST(ConcretePortTest, SetDirectionOnBus) { if (PortDirection::input() == nullptr) { PortDirection::init(); } ConcreteLibrary lib("test_lib", "test.lib", false); lib.setBusBrkts('[', ']'); ConcreteCell *cell = lib.makeCell("REG", true, ""); ConcretePort *bus = cell->makeBusPort("D", 1, 0); bus->setDirection(PortDirection::input()); EXPECT_EQ(bus->direction(), PortDirection::input()); // Setting direction on bus should propagate to bits ConcretePort *bit0 = bus->findBusBit(0); if (bit0) { EXPECT_EQ(bit0->direction(), PortDirection::input()); } } TEST(ConcretePortTest, AddPortBit) { ConcreteLibrary lib("test_lib", "test.lib", false); lib.setBusBrkts('[', ']'); ConcreteCell *cell = lib.makeCell("REG", true, ""); ConcretePort *bus = cell->makeBusPort("D", 1, 0); // Bus already has auto-generated bits - this tests the addPortBit path EXPECT_TRUE(bus->hasMembers()); EXPECT_EQ(bus->size(), 2); } TEST(ConcretePortTest, BusMemberIterator) { ConcreteLibrary lib("test_lib", "test.lib", false); lib.setBusBrkts('[', ']'); ConcreteCell *cell = lib.makeCell("REG", true, ""); ConcretePort *bus = cell->makeBusPort("D", 1, 0); ConcretePortMemberIterator *iter = bus->memberIterator(); int count = 0; while (iter->hasNext()) { iter->next(); count++; } delete iter; EXPECT_EQ(count, 2); } TEST(ConcretePortTest, BundlePortSetDirection) { if (PortDirection::input() == nullptr) { PortDirection::init(); } ConcreteLibrary lib("test_lib", "test.lib", false); ConcreteCell *cell = lib.makeCell("MUX", true, ""); ConcretePort *a = cell->makePort("A"); ConcretePort *b = cell->makePort("B"); ConcretePortSeq *members = new ConcretePortSeq; members->push_back(a); members->push_back(b); ConcretePort *bundle = cell->makeBundlePort("AB", members); // Setting direction on bundle bundle->setDirection(PortDirection::input()); EXPECT_EQ(bundle->direction(), PortDirection::input()); } TEST(ConcretePortTest, BundleBusBitIndex) { ConcreteLibrary lib("test_lib", "test.lib", false); lib.setBusBrkts('[', ']'); ConcreteCell *cell = lib.makeCell("REG", true, ""); ConcretePort *port = cell->makePort("CLK"); // Scalar port setBusBitIndex port->setBusBitIndex(5); EXPECT_EQ(port->busBitIndex(), 5); EXPECT_TRUE(port->isBusBit()); } //////////////////////////////////////////////////////////////// // ConcreteLibrary additional tests //////////////////////////////////////////////////////////////// TEST(ConcreteLibraryTest, BusBracketsChange) { ConcreteLibrary lib("test_lib", "test.lib", false); lib.setBusBrkts('[', ']'); EXPECT_EQ(lib.busBrktLeft(), '['); EXPECT_EQ(lib.busBrktRight(), ']'); lib.setBusBrkts('(', ')'); EXPECT_EQ(lib.busBrktLeft(), '('); EXPECT_EQ(lib.busBrktRight(), ')'); } TEST(ConcreteLibraryTest, FilenameAndId) { ConcreteLibrary lib("test_lib", "test.lib", false); EXPECT_STREQ(lib.filename(), "test.lib"); // Library ID is a monotonically increasing counter EXPECT_GE(lib.id(), 0u); } //////////////////////////////////////////////////////////////// // PortDirection additional coverage //////////////////////////////////////////////////////////////// TEST(PortDirectionExtraTest, AllDirections) { if (PortDirection::input() == nullptr) { PortDirection::init(); } EXPECT_NE(PortDirection::input(), nullptr); EXPECT_NE(PortDirection::output(), nullptr); EXPECT_NE(PortDirection::bidirect(), nullptr); EXPECT_NE(PortDirection::tristate(), nullptr); EXPECT_NE(PortDirection::internal(), nullptr); EXPECT_NE(PortDirection::ground(), nullptr); EXPECT_NE(PortDirection::power(), nullptr); EXPECT_NE(PortDirection::unknown(), nullptr); } TEST(PortDirectionExtraTest, DirectionProperties) { if (PortDirection::input() == nullptr) { PortDirection::init(); } EXPECT_TRUE(PortDirection::input()->isInput()); EXPECT_FALSE(PortDirection::input()->isOutput()); EXPECT_FALSE(PortDirection::input()->isBidirect()); EXPECT_FALSE(PortDirection::input()->isTristate()); EXPECT_FALSE(PortDirection::input()->isPowerGround()); EXPECT_FALSE(PortDirection::output()->isInput()); EXPECT_TRUE(PortDirection::output()->isOutput()); EXPECT_FALSE(PortDirection::output()->isTristate()); EXPECT_TRUE(PortDirection::bidirect()->isBidirect()); EXPECT_TRUE(PortDirection::tristate()->isTristate()); EXPECT_TRUE(PortDirection::ground()->isPowerGround()); EXPECT_TRUE(PortDirection::power()->isPowerGround()); } TEST(PortDirectionExtraTest, DirectionNames) { if (PortDirection::input() == nullptr) { PortDirection::init(); } EXPECT_STREQ(PortDirection::input()->name(), "input"); EXPECT_STREQ(PortDirection::output()->name(), "output"); EXPECT_STREQ(PortDirection::bidirect()->name(), "bidirect"); EXPECT_STREQ(PortDirection::tristate()->name(), "tristate"); EXPECT_STREQ(PortDirection::internal()->name(), "internal"); EXPECT_STREQ(PortDirection::ground()->name(), "ground"); EXPECT_STREQ(PortDirection::power()->name(), "power"); EXPECT_STREQ(PortDirection::unknown()->name(), "unknown"); } TEST(PortDirectionExtraTest, FindAllByName) { if (PortDirection::input() == nullptr) { PortDirection::init(); } EXPECT_EQ(PortDirection::find("input"), PortDirection::input()); EXPECT_EQ(PortDirection::find("output"), PortDirection::output()); EXPECT_EQ(PortDirection::find("bidirect"), PortDirection::bidirect()); EXPECT_EQ(PortDirection::find("tristate"), PortDirection::tristate()); EXPECT_EQ(PortDirection::find("internal"), PortDirection::internal()); EXPECT_EQ(PortDirection::find("ground"), PortDirection::ground()); EXPECT_EQ(PortDirection::find("power"), PortDirection::power()); // "unknown" is not findable by name, returns nullptr EXPECT_EQ(PortDirection::find("nonexistent"), nullptr); } TEST(PortDirectionExtraTest, DirectionIndex) { if (PortDirection::input() == nullptr) { PortDirection::init(); } // Each direction should have a unique index EXPECT_NE(PortDirection::input()->index(), PortDirection::output()->index()); EXPECT_NE(PortDirection::bidirect()->index(), PortDirection::tristate()->index()); } //////////////////////////////////////////////////////////////// // NetworkCmp coverage tests //////////////////////////////////////////////////////////////// TEST(NetworkCmpTest, PortDirectionCmp) { if (PortDirection::input() == nullptr) { PortDirection::init(); } // PortDirection comparison is by index EXPECT_TRUE(PortDirection::input()->index() != PortDirection::output()->index()); } //////////////////////////////////////////////////////////////// // GroupBusPorts test //////////////////////////////////////////////////////////////// TEST(ConcreteCellTest, GroupBusPorts) { ConcreteLibrary lib("test_lib", "test.lib", false); lib.setBusBrkts('[', ']'); ConcreteCell *cell = lib.makeCell("FIFO", true, ""); // Create individual bus bit ports cell->makePort("D[0]"); cell->makePort("D[1]"); cell->makePort("D[2]"); cell->makePort("D[3]"); cell->makePort("CLK"); // groupBusPorts should group D[0]-D[3] into bus D cell->groupBusPorts('[', ']', [](const char*) { return true; }); // After grouping, we should find the bus port D ConcretePort *bus = cell->findPort("D"); EXPECT_NE(bus, nullptr); if (bus) { EXPECT_TRUE(bus->isBus()); EXPECT_EQ(bus->size(), 4); } // CLK should still be a scalar port ConcretePort *clk = cell->findPort("CLK"); EXPECT_NE(clk, nullptr); } //////////////////////////////////////////////////////////////// // ConcreteNetwork additional tests //////////////////////////////////////////////////////////////// TEST(ConcreteNetworkTest, MakeLibrary) { ConcreteNetwork network; Library *lib = network.makeLibrary("test_lib", "test.lib"); EXPECT_NE(lib, nullptr); // Find it Library *found = network.findLibrary("test_lib"); EXPECT_EQ(found, lib); // Library name EXPECT_STREQ(network.name(lib), "test_lib"); } TEST(ConcreteNetworkTest, LibraryIterator) { ConcreteNetwork network; network.makeLibrary("lib1", "lib1.lib"); network.makeLibrary("lib2", "lib2.lib"); LibraryIterator *iter = network.libraryIterator(); int count = 0; while (iter->hasNext()) { iter->next(); count++; } delete iter; EXPECT_EQ(count, 2); } TEST(ConcreteNetworkTest, FindCell) { ConcreteNetwork network; Library *lib = network.makeLibrary("test_lib", "test.lib"); ConcreteLibrary *clib = reinterpret_cast(lib); clib->makeCell("INV", true, ""); Cell *found = network.findCell(lib, "INV"); EXPECT_NE(found, nullptr); Cell *not_found = network.findCell(lib, "NAND2"); EXPECT_EQ(not_found, nullptr); } TEST(ConcreteNetworkTest, CellName) { ConcreteNetwork network; Library *lib = network.makeLibrary("test_lib", "test.lib"); ConcreteLibrary *clib = reinterpret_cast(lib); clib->makeCell("INV_X1", true, ""); Cell *cell = network.findCell(lib, "INV_X1"); EXPECT_NE(cell, nullptr); EXPECT_STREQ(network.name(cell), "INV_X1"); } TEST(ConcreteNetworkTest, CellIsLeaf) { ConcreteNetwork network; Library *lib = network.makeLibrary("test_lib", "test.lib"); ConcreteLibrary *clib = reinterpret_cast(lib); clib->makeCell("INV", true, ""); clib->makeCell("TOP", false, ""); Cell *inv = network.findCell(lib, "INV"); Cell *top = network.findCell(lib, "TOP"); EXPECT_TRUE(network.isLeaf(inv)); EXPECT_FALSE(network.isLeaf(top)); } TEST(ConcreteNetworkTest, CellPorts) { ConcreteNetwork network; Library *lib = network.makeLibrary("test_lib", "test.lib"); ConcreteLibrary *clib = reinterpret_cast(lib); ConcreteCell *ccell = clib->makeCell("INV", true, ""); ccell->makePort("A"); ccell->makePort("Y"); Cell *cell = reinterpret_cast(ccell); CellPortIterator *iter = network.portIterator(cell); int count = 0; while (iter->hasNext()) { Port *port = iter->next(); EXPECT_NE(port, nullptr); count++; } delete iter; EXPECT_EQ(count, 2); } TEST(ConcreteNetworkTest, PortProperties) { ConcreteNetwork network; Library *lib = network.makeLibrary("test_lib", "test.lib"); ConcreteLibrary *clib = reinterpret_cast(lib); ConcreteCell *ccell = clib->makeCell("INV", true, ""); ConcretePort *a = ccell->makePort("A"); Port *port = reinterpret_cast(a); EXPECT_STREQ(network.name(port), "A"); EXPECT_FALSE(network.isBus(port)); EXPECT_FALSE(network.isBundle(port)); } TEST(ConcreteNetworkTest, FindPort) { ConcreteNetwork network; Library *lib = network.makeLibrary("test_lib", "test.lib"); ConcreteLibrary *clib = reinterpret_cast(lib); ConcreteCell *ccell = clib->makeCell("INV", true, ""); ccell->makePort("A"); ccell->makePort("Y"); Cell *cell = reinterpret_cast(ccell); Port *found = network.findPort(cell, "A"); EXPECT_NE(found, nullptr); EXPECT_STREQ(network.name(found), "A"); Port *not_found = network.findPort(cell, "B"); EXPECT_EQ(not_found, nullptr); } TEST(ConcreteNetworkTest, PortBitCount) { ConcreteNetwork network; Library *lib = network.makeLibrary("test_lib", "test.lib"); ConcreteLibrary *clib = reinterpret_cast(lib); ConcreteCell *ccell = clib->makeCell("INV", true, ""); ccell->makePort("A"); ccell->makePort("Y"); Cell *cell = reinterpret_cast(ccell); EXPECT_EQ(network.portBitCount(cell), 2); } //////////////////////////////////////////////////////////////// // ConcreteNetwork additional coverage tests //////////////////////////////////////////////////////////////// TEST(ConcreteNetworkTest, FindLibraryByName) { ConcreteNetwork network; Library *lib = network.makeLibrary("my_lib", "my.lib"); Library *found = network.findLibrary("my_lib"); EXPECT_EQ(found, lib); Library *notfound = network.findLibrary("nonexistent"); EXPECT_EQ(notfound, nullptr); } TEST(ConcreteNetworkTest, LibraryName) { ConcreteNetwork network; Library *lib = network.makeLibrary("test_name_lib", "test.lib"); EXPECT_STREQ(network.name(lib), "test_name_lib"); } TEST(ConcreteNetworkTest, LibraryId) { ConcreteNetwork network; Library *lib = network.makeLibrary("id_lib", "id.lib"); // ID should be assigned by the network ObjectId id = network.id(lib); // The id may be 0 or positive EXPECT_GE(id, 0u); } TEST(ConcreteNetworkTest, DeleteLibrary) { ConcreteNetwork network; Library *lib = network.makeLibrary("del_lib", "del.lib"); EXPECT_NE(network.findLibrary("del_lib"), nullptr); network.deleteLibrary(lib); EXPECT_EQ(network.findLibrary("del_lib"), nullptr); } TEST(ConcreteNetworkTest, MakeCell) { ConcreteNetwork network; Library *lib = network.makeLibrary("cell_lib", "cell.lib"); Cell *cell = network.makeCell(lib, "BUF_X1", true, "cell.lib"); EXPECT_NE(cell, nullptr); } TEST(ConcreteNetworkTest, FindCellViaNetwork) { ConcreteNetwork network; Library *lib = network.makeLibrary("find_lib", "find.lib"); Cell *cell = network.makeCell(lib, "AND2", true, "find.lib"); Cell *found = network.findCell(lib, "AND2"); EXPECT_EQ(found, cell); EXPECT_EQ(network.findCell(lib, "nonexistent"), nullptr); } TEST(ConcreteNetworkTest, FindAnyCell) { ConcreteNetwork network; Library *lib1 = network.makeLibrary("lib1", "lib1.lib"); Library *lib2 = network.makeLibrary("lib2", "lib2.lib"); network.makeCell(lib1, "INV_X1", true, "lib1.lib"); Cell *found = network.findAnyCell("INV_X1"); EXPECT_NE(found, nullptr); EXPECT_EQ(network.findAnyCell("nonexistent"), nullptr); } TEST(ConcreteNetworkTest, CellNameViaNetwork) { ConcreteNetwork network; Library *lib = network.makeLibrary("nm_lib", "nm.lib"); Cell *cell = network.makeCell(lib, "OR2_X1", true, "nm.lib"); EXPECT_STREQ(network.name(cell), "OR2_X1"); } TEST(ConcreteNetworkTest, CellIdViaNetwork) { ConcreteNetwork network; Library *lib = network.makeLibrary("id_lib", "id.lib"); Cell *cell = network.makeCell(lib, "CELL1", true, "id.lib"); ObjectId id = network.id(cell); EXPECT_GE(id, 0u); } TEST(ConcreteNetworkTest, SetCellName) { ConcreteNetwork network; Library *lib = network.makeLibrary("rn_lib", "rn.lib"); Cell *cell = network.makeCell(lib, "OLD_NAME", true, "rn.lib"); network.setName(cell, "NEW_NAME"); EXPECT_STREQ(network.name(cell), "NEW_NAME"); } TEST(ConcreteNetworkTest, SetIsLeaf) { ConcreteNetwork network; Library *lib = network.makeLibrary("leaf_lib", "leaf.lib"); Cell *cell = network.makeCell(lib, "CELL1", true, "leaf.lib"); EXPECT_TRUE(network.isLeaf(cell)); network.setIsLeaf(cell, false); EXPECT_FALSE(network.isLeaf(cell)); } TEST(ConcreteNetworkTest, SetAttribute) { ConcreteNetwork network; Library *lib = network.makeLibrary("attr_lib", "attr.lib"); Cell *cell = network.makeCell(lib, "CELL1", true, "attr.lib"); network.setAttribute(cell, "area", "1.5"); std::string val = network.getAttribute(cell, "area"); EXPECT_EQ(val, "1.5"); } TEST(ConcreteNetworkTest, AttributeMap) { ConcreteNetwork network; Library *lib = network.makeLibrary("amap_lib", "amap.lib"); Cell *cell = network.makeCell(lib, "CELL1", true, "amap.lib"); network.setAttribute(cell, "k1", "v1"); network.setAttribute(cell, "k2", "v2"); const auto &attrs = network.attributeMap(cell); EXPECT_EQ(attrs.size(), 2u); } TEST(ConcreteNetworkTest, CellLibrary) { ConcreteNetwork network; Library *lib = network.makeLibrary("parent_lib", "parent.lib"); Cell *cell = network.makeCell(lib, "CELL1", true, "parent.lib"); Library *parent = network.library(cell); EXPECT_EQ(parent, lib); } TEST(ConcreteNetworkTest, CellFilename) { ConcreteNetwork network; Library *lib = network.makeLibrary("fn_lib", "fn.lib"); Cell *cell = network.makeCell(lib, "CELL1", true, "fn.lib"); EXPECT_STREQ(network.filename(cell), "fn.lib"); } TEST(ConcreteNetworkTest, DeleteCell) { ConcreteNetwork network; Library *lib = network.makeLibrary("dc_lib", "dc.lib"); network.makeCell(lib, "TO_DELETE", true, "dc.lib"); Cell *found = network.findCell(lib, "TO_DELETE"); EXPECT_NE(found, nullptr); network.deleteCell(found); EXPECT_EQ(network.findCell(lib, "TO_DELETE"), nullptr); } TEST(ConcreteNetworkTest, FindPortViaNetwork) { ConcreteNetwork network; Library *lib = network.makeLibrary("fp_lib", "fp.lib"); ConcreteLibrary *clib = reinterpret_cast(lib); ConcreteCell *ccell = clib->makeCell("INV", true, ""); ccell->makePort("A"); ccell->makePort("Y"); Cell *cell = reinterpret_cast(ccell); Port *port = network.findPort(cell, "A"); EXPECT_NE(port, nullptr); EXPECT_EQ(network.findPort(cell, "nonexistent"), nullptr); } TEST(ConcreteNetworkTest, LibertyCellFromCell) { ConcreteNetwork network; Library *lib = network.makeLibrary("lc_lib", "lc.lib"); Cell *cell = network.makeCell(lib, "CELL1", true, "lc.lib"); // Non-liberty cells return nullptr LibertyCell *lcell = network.libertyCell(cell); EXPECT_EQ(lcell, nullptr); } TEST(ConcreteNetworkTest, ConstLibertyCellFromCell) { ConcreteNetwork network; Library *lib = network.makeLibrary("clc_lib", "clc.lib"); Cell *cell = network.makeCell(lib, "CELL1", true, "clc.lib"); const Cell *ccell = cell; const LibertyCell *lcell = network.libertyCell(ccell); EXPECT_EQ(lcell, nullptr); } TEST(ConcreteNetworkTest, FindCellsMatchingViaNetwork) { PortDirection::init(); ConcreteNetwork network; Library *lib = network.makeLibrary("match_lib", "match.lib"); network.makeCell(lib, "INV_X1", true, "match.lib"); network.makeCell(lib, "INV_X2", true, "match.lib"); network.makeCell(lib, "BUF_X1", true, "match.lib"); PatternMatch pattern("INV*"); CellSeq cells = network.findCellsMatching(lib, &pattern); EXPECT_EQ(cells.size(), 2u); } //////////////////////////////////////////////////////////////// // Additional Network tests for function coverage //////////////////////////////////////////////////////////////// // ConcreteNetwork: link and instance hierarchy tests class ConcreteNetworkLinkedTest : public ::testing::Test { protected: void SetUp() override { PortDirection::init(); // Build a simple network: top instance with 2 children lib_ = network_.makeLibrary("test_lib", "test.lib"); Cell *inv_cell = network_.makeCell(lib_, "INV", true, "test.lib"); network_.makePort(inv_cell, "A"); network_.makePort(inv_cell, "Y"); network_.setDirection(network_.findPort(inv_cell, "A"), PortDirection::input()); network_.setDirection(network_.findPort(inv_cell, "Y"), PortDirection::output()); Cell *top_cell = network_.makeCell(lib_, "TOP", false, "test.lib"); network_.makePort(top_cell, "clk"); network_.makePort(top_cell, "data_in"); network_.makePort(top_cell, "data_out"); network_.setDirection(network_.findPort(top_cell, "clk"), PortDirection::input()); network_.setDirection(network_.findPort(top_cell, "data_in"), PortDirection::input()); network_.setDirection(network_.findPort(top_cell, "data_out"), PortDirection::output()); // Create top instance Instance *top = network_.makeInstance(top_cell, "top", nullptr); network_.setTopInstance(top); // Create child instances u1_ = network_.makeInstance(inv_cell, "u1", top); u2_ = network_.makeInstance(inv_cell, "u2", top); // Create nets net1_ = network_.makeNet("n1", top); net2_ = network_.makeNet("n2", top); net3_ = network_.makeNet("n3", top); // Connect pins Port *inv_a = network_.findPort(inv_cell, "A"); Port *inv_y = network_.findPort(inv_cell, "Y"); pin_u1_a_ = network_.connect(u1_, inv_a, net1_); pin_u1_y_ = network_.connect(u1_, inv_y, net2_); pin_u2_a_ = network_.connect(u2_, inv_a, net2_); pin_u2_y_ = network_.connect(u2_, inv_y, net3_); } void TearDown() override { network_.clear(); } ConcreteNetwork network_; Library *lib_; Instance *u1_; Instance *u2_; Net *net1_; Net *net2_; Net *net3_; Pin *pin_u1_a_; Pin *pin_u1_y_; Pin *pin_u2_a_; Pin *pin_u2_y_; }; TEST_F(ConcreteNetworkLinkedTest, TopInstance) { Instance *top = network_.topInstance(); EXPECT_NE(top, nullptr); } TEST_F(ConcreteNetworkLinkedTest, IsTopInstance) { Instance *top = network_.topInstance(); EXPECT_TRUE(network_.isTopInstance(top)); EXPECT_FALSE(network_.isTopInstance(u1_)); } TEST_F(ConcreteNetworkLinkedTest, InstanceName) { EXPECT_STREQ(network_.name(u1_), "u1"); EXPECT_STREQ(network_.name(u2_), "u2"); } TEST_F(ConcreteNetworkLinkedTest, InstanceId) { ObjectId id1 = network_.id(u1_); ObjectId id2 = network_.id(u2_); EXPECT_NE(id1, id2); } TEST_F(ConcreteNetworkLinkedTest, InstanceCell) { Cell *cell = network_.cell(u1_); EXPECT_NE(cell, nullptr); EXPECT_STREQ(network_.name(cell), "INV"); } TEST_F(ConcreteNetworkLinkedTest, InstanceCellName) { const char *name = network_.cellName(u1_); EXPECT_STREQ(name, "INV"); } TEST_F(ConcreteNetworkLinkedTest, InstanceParent) { Instance *parent = network_.parent(u1_); EXPECT_EQ(parent, network_.topInstance()); } TEST_F(ConcreteNetworkLinkedTest, InstanceIsLeaf) { EXPECT_TRUE(network_.isLeaf(u1_)); EXPECT_FALSE(network_.isLeaf(network_.topInstance())); } TEST_F(ConcreteNetworkLinkedTest, InstanceIsHierarchical) { EXPECT_FALSE(network_.isHierarchical(u1_)); EXPECT_TRUE(network_.isHierarchical(network_.topInstance())); } TEST_F(ConcreteNetworkLinkedTest, InstanceFindChild) { Instance *top = network_.topInstance(); Instance *found = network_.findChild(top, "u1"); EXPECT_EQ(found, u1_); Instance *notfound = network_.findChild(top, "u99"); EXPECT_EQ(notfound, nullptr); } TEST_F(ConcreteNetworkLinkedTest, InstancePathName) { const char *path = network_.pathName(u1_); EXPECT_NE(path, nullptr); EXPECT_STREQ(path, "u1"); } TEST_F(ConcreteNetworkLinkedTest, ChildIterator) { Instance *top = network_.topInstance(); InstanceChildIterator *iter = network_.childIterator(top); int count = 0; while (iter->hasNext()) { iter->next(); count++; } delete iter; EXPECT_EQ(count, 2); } TEST_F(ConcreteNetworkLinkedTest, InstancePinIterator) { InstancePinIterator *iter = network_.pinIterator(u1_); int count = 0; while (iter->hasNext()) { iter->next(); count++; } delete iter; EXPECT_EQ(count, 2); } TEST_F(ConcreteNetworkLinkedTest, InstanceNetIterator) { Instance *top = network_.topInstance(); InstanceNetIterator *iter = network_.netIterator(top); int count = 0; while (iter->hasNext()) { iter->next(); count++; } delete iter; EXPECT_EQ(count, 3); } // Pin tests TEST_F(ConcreteNetworkLinkedTest, PinId) { ObjectId id = network_.id(pin_u1_a_); EXPECT_GE(id, 0u); } TEST_F(ConcreteNetworkLinkedTest, PinInstance) { Instance *inst = network_.instance(pin_u1_a_); EXPECT_EQ(inst, u1_); } TEST_F(ConcreteNetworkLinkedTest, PinNet) { Net *net = network_.net(pin_u1_a_); EXPECT_EQ(net, net1_); } TEST_F(ConcreteNetworkLinkedTest, PinPort) { Port *port = network_.port(pin_u1_a_); EXPECT_NE(port, nullptr); EXPECT_STREQ(network_.name(port), "A"); } TEST_F(ConcreteNetworkLinkedTest, PinDirection) { PortDirection *dir = network_.direction(pin_u1_a_); EXPECT_TRUE(dir->isInput()); PortDirection *dir2 = network_.direction(pin_u1_y_); EXPECT_TRUE(dir2->isOutput()); } TEST_F(ConcreteNetworkLinkedTest, PinTerm) { // Non-top-level pins don't have terms Term *term = network_.term(pin_u1_a_); EXPECT_EQ(term, nullptr); } TEST_F(ConcreteNetworkLinkedTest, PinVertexId) { VertexId vid = network_.vertexId(pin_u1_a_); // Default is 0 EXPECT_EQ(vid, 0u); network_.setVertexId(pin_u1_a_, 42); EXPECT_EQ(network_.vertexId(pin_u1_a_), 42u); } TEST_F(ConcreteNetworkLinkedTest, PinName) { const Network &net = network_; const char *name = net.name(pin_u1_a_); EXPECT_NE(name, nullptr); } TEST_F(ConcreteNetworkLinkedTest, PinPortName) { const char *pname = network_.portName(pin_u1_a_); EXPECT_STREQ(pname, "A"); } TEST_F(ConcreteNetworkLinkedTest, PinPathName) { const char *path = network_.pathName(pin_u1_a_); EXPECT_NE(path, nullptr); } TEST_F(ConcreteNetworkLinkedTest, PinIsLeaf) { EXPECT_TRUE(network_.isLeaf(pin_u1_a_)); } TEST_F(ConcreteNetworkLinkedTest, PinIsDriver) { EXPECT_FALSE(network_.isDriver(pin_u1_a_)); // input pin EXPECT_TRUE(network_.isDriver(pin_u1_y_)); // output pin } TEST_F(ConcreteNetworkLinkedTest, PinIsLoad) { EXPECT_TRUE(network_.isLoad(pin_u1_a_)); // input pin EXPECT_FALSE(network_.isLoad(pin_u1_y_)); // output pin } TEST_F(ConcreteNetworkLinkedTest, FindPinByName) { Pin *found = network_.findPin(u1_, "A"); EXPECT_EQ(found, pin_u1_a_); Pin *notfound = network_.findPin(u1_, "Z"); EXPECT_EQ(notfound, nullptr); } TEST_F(ConcreteNetworkLinkedTest, FindPinByPort) { Cell *cell = network_.cell(u1_); Port *port_a = network_.findPort(cell, "A"); Pin *found = network_.findPin(u1_, port_a); EXPECT_EQ(found, pin_u1_a_); } // Net tests TEST_F(ConcreteNetworkLinkedTest, NetName) { EXPECT_STREQ(network_.name(net1_), "n1"); } TEST_F(ConcreteNetworkLinkedTest, NetId) { ObjectId id = network_.id(net1_); EXPECT_GE(id, 0u); } TEST_F(ConcreteNetworkLinkedTest, NetInstance) { Instance *inst = network_.instance(net1_); EXPECT_EQ(inst, network_.topInstance()); } TEST_F(ConcreteNetworkLinkedTest, NetPathName) { const char *path = network_.pathName(net1_); EXPECT_NE(path, nullptr); } TEST_F(ConcreteNetworkLinkedTest, NetIsPowerGround) { EXPECT_FALSE(network_.isPower(net1_)); EXPECT_FALSE(network_.isGround(net1_)); } TEST_F(ConcreteNetworkLinkedTest, NetPinIterator) { // net2_ connects u1_Y and u2_A NetPinIterator *iter = network_.pinIterator(net2_); int count = 0; while (iter->hasNext()) { iter->next(); count++; } delete iter; EXPECT_EQ(count, 2); } TEST_F(ConcreteNetworkLinkedTest, NetTermIterator) { NetTermIterator *iter = network_.termIterator(net1_); int count = 0; while (iter->hasNext()) { iter->next(); count++; } delete iter; // No terms on non-top-level net connections EXPECT_GE(count, 0); } TEST_F(ConcreteNetworkLinkedTest, FindNetByName) { Instance *top = network_.topInstance(); Net *found = network_.findNet(top, "n1"); EXPECT_EQ(found, net1_); Net *notfound = network_.findNet(top, "nonexistent"); EXPECT_EQ(notfound, nullptr); } // Disconnect and delete TEST_F(ConcreteNetworkLinkedTest, DisconnectPin) { Net *net = network_.net(pin_u1_a_); EXPECT_NE(net, nullptr); network_.disconnectPin(pin_u1_a_); EXPECT_EQ(network_.net(pin_u1_a_), nullptr); } TEST_F(ConcreteNetworkLinkedTest, DeleteNet) { network_.deleteNet(net3_); Instance *top = network_.topInstance(); Net *found = network_.findNet(top, "n3"); EXPECT_EQ(found, nullptr); } TEST_F(ConcreteNetworkLinkedTest, DeleteInstance) { // Disconnect pins before deleting network_.disconnectPin(pin_u2_a_); network_.disconnectPin(pin_u2_y_); network_.deleteInstance(u2_); Instance *top = network_.topInstance(); Instance *found = network_.findChild(top, "u2"); EXPECT_EQ(found, nullptr); } // MergeInto / MergedInto TEST_F(ConcreteNetworkLinkedTest, MergeIntoNet) { // net1_ merges into net2_ network_.mergeInto(net1_, net2_); Net *merged = network_.mergedInto(net1_); EXPECT_EQ(merged, net2_); } // MakePins TEST_F(ConcreteNetworkLinkedTest, MakePins) { Cell *inv_cell = network_.findCell(lib_, "INV"); Instance *u3 = network_.makeInstance(inv_cell, "u3", network_.topInstance()); network_.makePins(u3); // After makePins, pins should be accessible Pin *pin = network_.findPin(u3, "A"); EXPECT_NE(pin, nullptr); } // ReplaceCell TEST_F(ConcreteNetworkLinkedTest, ReplaceCell) { Cell *buf_cell = network_.makeCell(lib_, "BUF", true, "test.lib"); network_.makePort(buf_cell, "A"); network_.makePort(buf_cell, "Y"); network_.setDirection(network_.findPort(buf_cell, "A"), PortDirection::input()); network_.setDirection(network_.findPort(buf_cell, "Y"), PortDirection::output()); // Disconnect and replace network_.disconnectPin(pin_u1_a_); network_.disconnectPin(pin_u1_y_); network_.replaceCell(u1_, buf_cell); Cell *new_cell = network_.cell(u1_); EXPECT_STREQ(network_.name(new_cell), "BUF"); } // Network pathName comparisons TEST_F(ConcreteNetworkLinkedTest, PathNameLessInst) { EXPECT_TRUE(network_.pathNameLess(u1_, u2_)); EXPECT_FALSE(network_.pathNameLess(u2_, u1_)); } TEST_F(ConcreteNetworkLinkedTest, PathNameCmpInst) { int cmp = network_.pathNameCmp(u1_, u2_); EXPECT_LT(cmp, 0); EXPECT_EQ(network_.pathNameCmp(u1_, u1_), 0); } TEST_F(ConcreteNetworkLinkedTest, PathNameLessPin) { bool result = network_.pathNameLess(pin_u1_a_, pin_u2_a_); // u1/A < u2/A EXPECT_TRUE(result); } TEST_F(ConcreteNetworkLinkedTest, PathNameCmpPin) { int cmp = network_.pathNameCmp(pin_u1_a_, pin_u2_a_); EXPECT_LT(cmp, 0); } TEST_F(ConcreteNetworkLinkedTest, PathNameLessNet) { bool result = network_.pathNameLess(net1_, net2_); EXPECT_TRUE(result); } TEST_F(ConcreteNetworkLinkedTest, PathNameCmpNet) { int cmp = network_.pathNameCmp(net1_, net2_); EXPECT_LT(cmp, 0); } // Network: pathNameFirst / pathNameLast TEST_F(ConcreteNetworkLinkedTest, PathNameFirst) { char *first = nullptr; char *tail = nullptr; network_.pathNameFirst("a/b/c", first, tail); if (first) { EXPECT_STREQ(first, "a"); EXPECT_STREQ(tail, "b/c"); delete [] first; delete [] tail; } } TEST_F(ConcreteNetworkLinkedTest, PathNameLast) { char *head = nullptr; char *last = nullptr; network_.pathNameLast("a/b/c", head, last); if (last) { EXPECT_STREQ(last, "c"); EXPECT_STREQ(head, "a/b"); delete [] head; delete [] last; } } TEST_F(ConcreteNetworkLinkedTest, PathNameFirstNoDivider) { char *first = nullptr; char *tail = nullptr; network_.pathNameFirst("simple", first, tail); EXPECT_EQ(first, nullptr); EXPECT_EQ(tail, nullptr); } // Network: pathDivider / pathEscape TEST_F(ConcreteNetworkLinkedTest, PathDivider) { EXPECT_EQ(network_.pathDivider(), '/'); network_.setPathDivider('.'); EXPECT_EQ(network_.pathDivider(), '.'); network_.setPathDivider('/'); } TEST_F(ConcreteNetworkLinkedTest, PathEscape) { char orig = network_.pathEscape(); network_.setPathEscape('\\'); EXPECT_EQ(network_.pathEscape(), '\\'); network_.setPathEscape(orig); } // Network: isLinked TEST_F(ConcreteNetworkLinkedTest, IsLinked) { EXPECT_TRUE(network_.isLinked()); } // Network: isEditable TEST_F(ConcreteNetworkLinkedTest, IsEditable) { EXPECT_TRUE(network_.isEditable()); } // Network: pinLess TEST_F(ConcreteNetworkLinkedTest, PinLess) { bool result = network_.pinLess(pin_u1_a_, pin_u2_a_); bool result2 = network_.pinLess(pin_u2_a_, pin_u1_a_); EXPECT_NE(result, result2); } // Network: location TEST_F(ConcreteNetworkLinkedTest, PinLocation) { double x, y; bool exists; network_.location(pin_u1_a_, x, y, exists); EXPECT_FALSE(exists); } // Network: instanceCount, pinCount, netCount TEST_F(ConcreteNetworkLinkedTest, InstanceCount) { int count = network_.instanceCount(); EXPECT_GE(count, 3); // top + u1 + u2 } TEST_F(ConcreteNetworkLinkedTest, PinCount) { int count = network_.pinCount(); EXPECT_GE(count, 4); } TEST_F(ConcreteNetworkLinkedTest, NetCount) { int count = network_.netCount(); EXPECT_GE(count, 3); } // Network: leafInstanceCount TEST_F(ConcreteNetworkLinkedTest, LeafInstanceCount) { int count = network_.leafInstanceCount(); EXPECT_EQ(count, 2); } // Network: leafPinCount TEST_F(ConcreteNetworkLinkedTest, LeafPinCount) { int count = network_.leafPinCount(); EXPECT_GE(count, 4); } // Network: leafInstances TEST_F(ConcreteNetworkLinkedTest, LeafInstances) { InstanceSeq leaves = network_.leafInstances(); EXPECT_EQ(leaves.size(), 2u); } // Network: leafInstanceIterator TEST_F(ConcreteNetworkLinkedTest, LeafInstanceIterator) { LeafInstanceIterator *iter = network_.leafInstanceIterator(); int count = 0; while (iter->hasNext()) { iter->next(); count++; } delete iter; EXPECT_EQ(count, 2); } // Network: findPinsMatching TEST_F(ConcreteNetworkLinkedTest, FindPinsMatching) { Instance *top = network_.topInstance(); PatternMatch pattern("u1/*"); PinSeq pins = network_.findPinsMatching(top, &pattern); EXPECT_EQ(pins.size(), 2u); } // Network: findChildrenMatching TEST_F(ConcreteNetworkLinkedTest, FindChildrenMatching) { Instance *top = network_.topInstance(); PatternMatch pattern("u*"); InstanceSeq matches; network_.findChildrenMatching(top, &pattern, matches); EXPECT_EQ(matches.size(), 2u); } // Network: findInstancesMatching TEST_F(ConcreteNetworkLinkedTest, FindInstancesMatching) { Instance *top = network_.topInstance(); PatternMatch pattern("u*"); InstanceSeq matches = network_.findInstancesMatching(top, &pattern); EXPECT_EQ(matches.size(), 2u); } // Network: findNetsMatching TEST_F(ConcreteNetworkLinkedTest, FindNetsMatching) { Instance *top = network_.topInstance(); PatternMatch pattern("n*"); NetSeq matches = network_.findNetsMatching(top, &pattern); EXPECT_EQ(matches.size(), 3u); } // Network: findInstNetsMatching TEST_F(ConcreteNetworkLinkedTest, FindInstNetsMatching) { Instance *top = network_.topInstance(); PatternMatch pattern("n*"); NetSeq matches; network_.findInstNetsMatching(top, &pattern, matches); EXPECT_EQ(matches.size(), 3u); } // Network: isInside (Instance) TEST_F(ConcreteNetworkLinkedTest, IsInsideInst) { Instance *top = network_.topInstance(); EXPECT_TRUE(network_.isInside(u1_, top)); EXPECT_FALSE(network_.isInside(top, u1_)); } // Network: isInside (Net) TEST_F(ConcreteNetworkLinkedTest, IsInsideNet) { Instance *top = network_.topInstance(); EXPECT_TRUE(network_.isInside(net1_, top)); } // Network: isConnected TEST_F(ConcreteNetworkLinkedTest, IsConnectedNetPin) { EXPECT_TRUE(network_.isConnected(net1_, pin_u1_a_)); EXPECT_FALSE(network_.isConnected(net3_, pin_u1_a_)); } // Network: isConnected (net to net) TEST_F(ConcreteNetworkLinkedTest, IsConnectedNetNet) { EXPECT_TRUE(network_.isConnected(net1_, net1_)); EXPECT_FALSE(network_.isConnected(net1_, net2_)); } // Network: highestNetAbove TEST_F(ConcreteNetworkLinkedTest, HighestNetAbove) { Net *highest = network_.highestNetAbove(net1_); EXPECT_EQ(highest, net1_); } // Network: connectedNets (from net) TEST_F(ConcreteNetworkLinkedTest, ConnectedNetsFromNet) { NetSet nets; network_.connectedNets(net1_, &nets); EXPECT_GE(nets.size(), 1u); } // Network: connectedNets (from pin) TEST_F(ConcreteNetworkLinkedTest, ConnectedNetsFromPin) { NetSet nets; network_.connectedNets(pin_u1_a_, &nets); EXPECT_GE(nets.size(), 1u); } // Network: drivers (from pin) TEST_F(ConcreteNetworkLinkedTest, DriversFromPin) { PinSet *drvrs = network_.drivers(pin_u1_a_); EXPECT_NE(drvrs, nullptr); } // Network: drivers (from net) TEST_F(ConcreteNetworkLinkedTest, DriversFromNet) { PinSet *drvrs = network_.drivers(net2_); EXPECT_NE(drvrs, nullptr); EXPECT_GE(drvrs->size(), 1u); } // Network: path from instance TEST_F(ConcreteNetworkLinkedTest, InstancePath) { InstanceSeq path; network_.path(u1_, path); // Path from u1 to top: u1, top EXPECT_GE(path.size(), 1u); } // Network: connectedPinIterator (from pin) TEST_F(ConcreteNetworkLinkedTest, ConnectedPinIteratorFromPin) { PinConnectedPinIterator *iter = network_.connectedPinIterator(pin_u1_a_); int count = 0; while (iter->hasNext()) { iter->next(); count++; } delete iter; EXPECT_GE(count, 1); } // Network: connectedPinIterator (from net) TEST_F(ConcreteNetworkLinkedTest, ConnectedPinIteratorFromNet) { NetConnectedPinIterator *iter = network_.connectedPinIterator(net2_); int count = 0; while (iter->hasNext()) { iter->next(); count++; } delete iter; EXPECT_GE(count, 2); } // Network: constantPinIterator TEST_F(ConcreteNetworkLinkedTest, ConstantPinIterator) { ConstantPinIterator *iter = network_.constantPinIterator(); EXPECT_NE(iter, nullptr); EXPECT_FALSE(iter->hasNext()); delete iter; } // Network: addConstantNet TEST_F(ConcreteNetworkLinkedTest, AddConstantNet) { Net *const_net = network_.makeNet("vss", network_.topInstance()); network_.addConstantNet(const_net, LogicValue::zero); ConstantPinIterator *iter = network_.constantPinIterator(); EXPECT_NE(iter, nullptr); delete iter; } // Network: readNetlistBefore, setLinkFunc TEST(ConcreteNetworkExtraTest, ReadNetlistBefore) { ASSERT_NO_THROW(( [&](){ ConcreteNetwork network; network.readNetlistBefore(); }() )); } TEST(ConcreteNetworkExtraTest, SetLinkFunc) { ASSERT_NO_THROW(( [&](){ ConcreteNetwork network; network.setLinkFunc(nullptr); }() )); } // Network: setCellNetworkView, cellNetworkView, deleteCellNetworkViews TEST(ConcreteNetworkExtraTest, CellNetworkView) { PortDirection::init(); ConcreteNetwork network; Library *lib = network.makeLibrary("view_lib", "view.lib"); Cell *cell = network.makeCell(lib, "CELL1", true, "view.lib"); network.setCellNetworkView(cell, nullptr); Instance *view = network.cellNetworkView(cell); EXPECT_EQ(view, nullptr); network.deleteCellNetworkViews(); } // Network: makeLibertyLibrary TEST(ConcreteNetworkExtraTest, MakeLibertyLibrary) { ConcreteNetwork network; LibertyLibrary *lib = network.makeLibertyLibrary("liberty_lib", "lib.lib"); EXPECT_NE(lib, nullptr); } // Network: findLiberty TEST(ConcreteNetworkExtraTest, FindLiberty) { ConcreteNetwork network; LibertyLibrary *lib = network.makeLibertyLibrary("find_liberty", "find.lib"); LibertyLibrary *found = network.findLiberty("find_liberty"); EXPECT_EQ(found, lib); LibertyLibrary *notfound = network.findLiberty("nonexistent"); EXPECT_EQ(notfound, nullptr); } // Network: libertyLibraryIterator TEST(ConcreteNetworkExtraTest, LibertyLibraryIterator) { ConcreteNetwork network; network.makeLibertyLibrary("lib1", "lib1.lib"); LibertyLibraryIterator *iter = network.libertyLibraryIterator(); int count = 0; while (iter->hasNext()) { iter->next(); count++; } delete iter; EXPECT_EQ(count, 1); } // Network: nextObjectId TEST(ConcreteNetworkExtraTest, NextObjectId) { ObjectId id1 = ConcreteNetwork::nextObjectId(); ObjectId id2 = ConcreteNetwork::nextObjectId(); EXPECT_NE(id1, id2); } // Network: deleteTopInstance TEST(ConcreteNetworkExtraTest, DeleteTopInstance) { PortDirection::init(); ConcreteNetwork network; Library *lib = network.makeLibrary("del_top_lib", "del_top.lib"); Cell *cell = network.makeCell(lib, "TOP", false, "del_top.lib"); Instance *top = network.makeInstance(cell, "top", nullptr); network.setTopInstance(top); EXPECT_NE(network.topInstance(), nullptr); network.deleteTopInstance(); EXPECT_EQ(network.topInstance(), nullptr); } // NetworkCmp: sort functions with actual network objects TEST_F(ConcreteNetworkLinkedTest, SortByPathNamePins) { PinSet pin_set(&network_); pin_set.insert(pin_u2_a_); pin_set.insert(pin_u1_a_); PinSeq sorted = sortByPathName(&pin_set, &network_); EXPECT_EQ(sorted.size(), 2u); } TEST_F(ConcreteNetworkLinkedTest, SortByPathNameInstances) { InstanceSet inst_set(&network_); inst_set.insert(u2_); inst_set.insert(u1_); InstanceSeq sorted = sortByPathName(&inst_set, &network_); EXPECT_EQ(sorted.size(), 2u); EXPECT_STREQ(network_.name(sorted[0]), "u1"); EXPECT_STREQ(network_.name(sorted[1]), "u2"); } TEST_F(ConcreteNetworkLinkedTest, SortByPathNameNets) { NetSet net_set(&network_); net_set.insert(net3_); net_set.insert(net1_); net_set.insert(net2_); NetSeq sorted = sortByPathName(&net_set, &network_); EXPECT_EQ(sorted.size(), 3u); } TEST_F(ConcreteNetworkLinkedTest, SortByNamePorts) { Cell *inv_cell = network_.findCell(lib_, "INV"); Port *port_a = network_.findPort(inv_cell, "A"); Port *port_y = network_.findPort(inv_cell, "Y"); PortSet port_set(&network_); port_set.insert(port_y); port_set.insert(port_a); PortSeq sorted = sortByName(&port_set, &network_); EXPECT_EQ(sorted.size(), 2u); EXPECT_STREQ(network_.name(sorted[0]), "A"); EXPECT_STREQ(network_.name(sorted[1]), "Y"); } // NetworkCmp comparator constructors TEST_F(ConcreteNetworkLinkedTest, NetworkCmpConstructors) { PortNameLess port_less(&network_); PinPathNameLess pin_less(&network_); NetPathNameLess net_less(&network_); InstancePathNameLess inst_less(&network_); Cell *inv_cell = network_.findCell(lib_, "INV"); Port *port_a = network_.findPort(inv_cell, "A"); Port *port_y = network_.findPort(inv_cell, "Y"); EXPECT_TRUE(port_less(port_a, port_y)); EXPECT_FALSE(port_less(port_y, port_a)); EXPECT_TRUE(pin_less(pin_u1_a_, pin_u2_a_)); EXPECT_TRUE(net_less(net1_, net2_)); EXPECT_TRUE(inst_less(u1_, u2_)); } // ConcreteNetwork: makePin, makeTerm TEST_F(ConcreteNetworkLinkedTest, MakePinAndTerm) { Cell *inv_cell = network_.findCell(lib_, "INV"); Instance *u3 = network_.makeInstance(inv_cell, "u3", network_.topInstance()); Port *port_a = network_.findPort(inv_cell, "A"); Net *net = network_.makeNet("n4", network_.topInstance()); Pin *pin = network_.makePin(u3, port_a, net); EXPECT_NE(pin, nullptr); EXPECT_EQ(network_.net(pin), net); // makeTerm Term *term = network_.makeTerm(pin, net); EXPECT_NE(term, nullptr); EXPECT_EQ(network_.net(term), net); EXPECT_EQ(network_.pin(term), pin); } // Term tests TEST_F(ConcreteNetworkLinkedTest, TermId) { Cell *inv_cell = network_.findCell(lib_, "INV"); Instance *u3 = network_.makeInstance(inv_cell, "u3", network_.topInstance()); Port *port_a = network_.findPort(inv_cell, "A"); Net *net = network_.makeNet("n5", network_.topInstance()); Pin *pin = network_.makePin(u3, port_a, net); Term *term = network_.makeTerm(pin, net); ObjectId id = network_.id(term); EXPECT_GE(id, 0u); } // Network: setAttribute for Instance TEST_F(ConcreteNetworkLinkedTest, InstanceSetAttribute) { network_.setAttribute(u1_, "key1", "val1"); std::string val = network_.getAttribute(u1_, "key1"); EXPECT_EQ(val, "val1"); const auto &attrs = network_.attributeMap(u1_); EXPECT_EQ(attrs.size(), 1u); } // Network: findInstance TEST_F(ConcreteNetworkLinkedTest, FindInstanceByPath) { Instance *found = network_.findInstance("u1"); EXPECT_EQ(found, u1_); Instance *notfound = network_.findInstance("nonexistent"); EXPECT_EQ(notfound, nullptr); } // Network: findNet by path TEST_F(ConcreteNetworkLinkedTest, FindNetByPath) { Net *found = network_.findNet("n1"); EXPECT_EQ(found, net1_); } // Network: findPin by path TEST_F(ConcreteNetworkLinkedTest, FindPinByPath) { Pin *found = network_.findPin("u1/A"); EXPECT_EQ(found, pin_u1_a_); } // Network: findInstanceRelative TEST_F(ConcreteNetworkLinkedTest, FindInstanceRelative) { Instance *top = network_.topInstance(); Instance *found = network_.findInstanceRelative(top, "u1"); EXPECT_EQ(found, u1_); } // Network: findPinRelative TEST_F(ConcreteNetworkLinkedTest, FindPinRelative) { Instance *top = network_.topInstance(); Pin *found = network_.findPinRelative(top, "u1/A"); EXPECT_EQ(found, pin_u1_a_); } // HpinDrvrLoad: constructor copies pin sets, destructor deletes copies TEST(HpinDrvrLoadExtraTest, WithPinSets) { PinSet from_set; PinSet to_set; int fake1 = 1, fake2 = 2; const Pin *drvr = reinterpret_cast(&fake1); const Pin *load = reinterpret_cast(&fake2); from_set.insert(drvr); to_set.insert(load); HpinDrvrLoad hdl(drvr, load, &from_set, &to_set); // Constructor copies the sets, so pointers differ EXPECT_NE(hdl.hpinsFromDrvr(), nullptr); EXPECT_NE(hdl.hpinsToLoad(), nullptr); EXPECT_EQ(hdl.drvr(), drvr); EXPECT_EQ(hdl.load(), load); // HpinDrvrLoad destructor will delete its internal copies } // Network: deletePin TEST_F(ConcreteNetworkLinkedTest, DeletePin) { network_.disconnectPin(pin_u2_y_); network_.deletePin(pin_u2_y_); // After delete, pin shouldn't be found Pin *found = network_.findPin(u2_, "Y"); EXPECT_EQ(found, nullptr); } // Network: findPortsMatching TEST_F(ConcreteNetworkLinkedTest, FindPortsMatching) { Cell *inv_cell = network_.findCell(lib_, "INV"); PatternMatch pattern("*"); PortSeq ports = network_.findPortsMatching(inv_cell, &pattern); EXPECT_EQ(ports.size(), 2u); } // Network: port properties via network TEST_F(ConcreteNetworkLinkedTest, PortIdViaNetwork) { Cell *inv_cell = network_.findCell(lib_, "INV"); Port *port_a = network_.findPort(inv_cell, "A"); ObjectId id = network_.id(port_a); EXPECT_GE(id, 0u); } TEST_F(ConcreteNetworkLinkedTest, PortCellViaNetwork) { Cell *inv_cell = network_.findCell(lib_, "INV"); Port *port_a = network_.findPort(inv_cell, "A"); Cell *cell = network_.cell(port_a); EXPECT_EQ(cell, inv_cell); } TEST_F(ConcreteNetworkLinkedTest, PortSizeViaNetwork) { Cell *inv_cell = network_.findCell(lib_, "INV"); Port *port_a = network_.findPort(inv_cell, "A"); EXPECT_EQ(network_.size(port_a), 1); } TEST_F(ConcreteNetworkLinkedTest, PortFromToIndexViaNetwork) { Cell *inv_cell = network_.findCell(lib_, "INV"); Port *port_a = network_.findPort(inv_cell, "A"); // Scalar port has from/to index of -1 int from = network_.fromIndex(port_a); int to = network_.toIndex(port_a); EXPECT_EQ(from, -1); EXPECT_EQ(to, -1); } TEST_F(ConcreteNetworkLinkedTest, PortBusNameViaNetwork) { Cell *inv_cell = network_.findCell(lib_, "INV"); Port *port_a = network_.findPort(inv_cell, "A"); const char *bus_name = network_.busName(port_a); EXPECT_STREQ(bus_name, "A"); } TEST_F(ConcreteNetworkLinkedTest, PortFindBusBitViaNetwork) { Cell *inv_cell = network_.findCell(lib_, "INV"); Port *port_a = network_.findPort(inv_cell, "A"); Port *bit = network_.findBusBit(port_a, 0); // Scalar port returns nullptr for bus bit EXPECT_EQ(bit, nullptr); } TEST_F(ConcreteNetworkLinkedTest, PortFindMemberViaNetwork) { Cell *inv_cell = network_.findCell(lib_, "INV"); Port *port_a = network_.findPort(inv_cell, "A"); // Scalar port has no members - check hasMembers first EXPECT_FALSE(network_.hasMembers(port_a)); } TEST_F(ConcreteNetworkLinkedTest, PortMemberIteratorViaNetwork) { Cell *inv_cell = network_.findCell(lib_, "INV"); Port *port_a = network_.findPort(inv_cell, "A"); PortMemberIterator *iter = network_.memberIterator(port_a); EXPECT_NE(iter, nullptr); int count = 0; while (iter->hasNext()) { iter->next(); count++; } delete iter; EXPECT_EQ(count, 0); } TEST_F(ConcreteNetworkLinkedTest, PortLibertyPortViaNetwork) { Cell *inv_cell = network_.findCell(lib_, "INV"); Port *port_a = network_.findPort(inv_cell, "A"); LibertyPort *lport = network_.libertyPort(port_a); EXPECT_EQ(lport, nullptr); } TEST_F(ConcreteNetworkLinkedTest, PortHasMembersViaNetwork) { Cell *inv_cell = network_.findCell(lib_, "INV"); Port *port_a = network_.findPort(inv_cell, "A"); EXPECT_FALSE(network_.hasMembers(port_a)); } // Network: CellPortBitIterator TEST_F(ConcreteNetworkLinkedTest, CellPortBitIterator) { Cell *inv_cell = network_.findCell(lib_, "INV"); CellPortBitIterator *iter = network_.portBitIterator(inv_cell); int count = 0; while (iter->hasNext()) { iter->next(); count++; } delete iter; EXPECT_EQ(count, 2); } // Network: libertyCell on instance TEST_F(ConcreteNetworkLinkedTest, LibertyCellOnInstance) { LibertyCell *lcell = network_.libertyCell(u1_); // Non-liberty cells return nullptr EXPECT_EQ(lcell, nullptr); } // Network: libertyCell on non-liberty instance returns nullptr // (libertyLibrary(instance) would segfault since it dereferences libertyCell result) // Network: libertyPort on pin TEST_F(ConcreteNetworkLinkedTest, LibertyPortOnPin) { LibertyPort *lport = network_.libertyPort(pin_u1_a_); EXPECT_EQ(lport, nullptr); } // Network: isTopLevelPort TEST_F(ConcreteNetworkLinkedTest, IsTopLevelPort) { // Leaf pin is not a top-level port EXPECT_FALSE(network_.isTopLevelPort(pin_u1_a_)); } // Network: isHierarchical on pin TEST_F(ConcreteNetworkLinkedTest, PinIsHierarchical) { EXPECT_FALSE(network_.isHierarchical(pin_u1_a_)); } // Network: groupBusPorts via Network TEST_F(ConcreteNetworkLinkedTest, GroupBusPortsViaNetwork) { Cell *cell = network_.makeCell(lib_, "FIFO2", true, "test.lib"); network_.makePort(cell, "D[0]"); network_.makePort(cell, "D[1]"); network_.makePort(cell, "CLK"); ConcreteLibrary *clib = reinterpret_cast(lib_); clib->setBusBrkts('[', ']'); network_.groupBusPorts(cell, [](const char*) { return true; }); Port *bus = network_.findPort(cell, "D"); EXPECT_NE(bus, nullptr); if (bus) { EXPECT_TRUE(network_.isBus(bus)); } } // Network: makeBusPort, makeBundlePort via Network TEST_F(ConcreteNetworkLinkedTest, MakeBusPortViaNetwork) { ConcreteLibrary *clib = reinterpret_cast(lib_); clib->setBusBrkts('[', ']'); Cell *cell = network_.makeCell(lib_, "REG2", true, "test.lib"); Port *bus = network_.makeBusPort(cell, "D", 3, 0); EXPECT_NE(bus, nullptr); EXPECT_TRUE(network_.isBus(bus)); EXPECT_EQ(network_.size(bus), 4); } TEST_F(ConcreteNetworkLinkedTest, MakeBundlePortViaNetwork) { Cell *cell = network_.makeCell(lib_, "MUX2", true, "test.lib"); Port *a = network_.makePort(cell, "A"); Port *b = network_.makePort(cell, "B"); PortSeq *members = new PortSeq; members->push_back(a); members->push_back(b); Port *bundle = network_.makeBundlePort(cell, "AB", members); EXPECT_NE(bundle, nullptr); EXPECT_TRUE(network_.isBundle(bundle)); } // Network: setDirection via Network TEST_F(ConcreteNetworkLinkedTest, SetDirectionViaNetwork) { Cell *cell = network_.makeCell(lib_, "DIR_TEST", true, "test.lib"); Port *p = network_.makePort(cell, "X"); network_.setDirection(p, PortDirection::output()); EXPECT_EQ(network_.direction(p), PortDirection::output()); } // Network: findNetRelative TEST_F(ConcreteNetworkLinkedTest, FindNetRelative) { Instance *top = network_.topInstance(); Net *found = network_.findNetRelative(top, "n1"); EXPECT_EQ(found, net1_); } // Network: findNetsHierMatching TEST_F(ConcreteNetworkLinkedTest, FindNetsHierMatching) { Instance *top = network_.topInstance(); PatternMatch pattern("n*"); NetSeq matches = network_.findNetsHierMatching(top, &pattern); EXPECT_GE(matches.size(), 3u); } // Network: findPinsHierMatching TEST_F(ConcreteNetworkLinkedTest, FindPinsHierMatching) { Instance *top = network_.topInstance(); PatternMatch pattern("u1/*"); PinSeq matches = network_.findPinsHierMatching(top, &pattern); EXPECT_GE(matches.size(), 2u); } // Network: findInstancesHierMatching TEST_F(ConcreteNetworkLinkedTest, FindInstancesHierMatching) { Instance *top = network_.topInstance(); PatternMatch pattern("u*"); InstanceSeq matches = network_.findInstancesHierMatching(top, &pattern); EXPECT_GE(matches.size(), 2u); } // Network Set/Map comparators constructors TEST_F(ConcreteNetworkLinkedTest, PinIdLessConstructor) { PinIdLess less(&network_); bool ab = less(pin_u1_a_, pin_u2_a_); bool ba = less(pin_u2_a_, pin_u1_a_); // Strict weak ordering: exactly one of less(a,b) or less(b,a) must be true EXPECT_NE(ab, ba); } TEST_F(ConcreteNetworkLinkedTest, NetIdLessConstructor) { NetIdLess less(&network_); bool ab = less(net1_, net2_); bool ba = less(net2_, net1_); EXPECT_NE(ab, ba); } TEST_F(ConcreteNetworkLinkedTest, InstanceIdLessConstructor) { InstanceIdLess less(&network_); bool ab = less(u1_, u2_); bool ba = less(u2_, u1_); EXPECT_NE(ab, ba); } TEST_F(ConcreteNetworkLinkedTest, PortIdLessConstructor) { Cell *inv_cell = network_.findCell(lib_, "INV"); Port *port_a = network_.findPort(inv_cell, "A"); Port *port_y = network_.findPort(inv_cell, "Y"); PortIdLess less(&network_); bool ab = less(port_a, port_y); bool ba = less(port_y, port_a); EXPECT_NE(ab, ba); } TEST_F(ConcreteNetworkLinkedTest, CellIdLessConstructor) { Cell *inv_cell = network_.findCell(lib_, "INV"); Cell *top_cell = network_.findCell(lib_, "TOP"); CellIdLess less(&network_); bool ab = less(inv_cell, top_cell); bool ba = less(top_cell, inv_cell); EXPECT_NE(ab, ba); } // PinSet: with network constructor and intersects TEST_F(ConcreteNetworkLinkedTest, PinSetWithNetwork) { PinSet set1(&network_); set1.insert(pin_u1_a_); set1.insert(pin_u1_y_); PinSet set2(&network_); set2.insert(pin_u1_a_); EXPECT_TRUE(intersects(&set1, &set2, &network_)); } // PinSet: compare TEST_F(ConcreteNetworkLinkedTest, PinSetCompare) { PinSet set1(&network_); set1.insert(pin_u1_a_); PinSet set2(&network_); set2.insert(pin_u2_a_); int cmp = compare(&set1, &set2, &network_); // Different sets should not compare equal EXPECT_NE(cmp, 0); } // InstanceSet: with network and intersects TEST_F(ConcreteNetworkLinkedTest, InstanceSetWithNetwork) { InstanceSet set1(&network_); set1.insert(u1_); set1.insert(u2_); InstanceSet set2(&network_); set2.insert(u1_); EXPECT_TRUE(intersects(&set1, &set2, &network_)); } // NetSet: with network and intersects TEST_F(ConcreteNetworkLinkedTest, NetSetWithNetwork) { NetSet set1(&network_); set1.insert(net1_); set1.insert(net2_); NetSet set2(&network_); set2.insert(net1_); EXPECT_TRUE(intersects(&set1, &set2, &network_)); } // NetSet: compare TEST_F(ConcreteNetworkLinkedTest, NetSetCompare) { NetSet set1(&network_); set1.insert(net1_); NetSet set2(&network_); set2.insert(net2_); int cmp = compare(&set1, &set2, &network_); // Different sets should not compare equal EXPECT_NE(cmp, 0); } // CellSet constructor TEST_F(ConcreteNetworkLinkedTest, CellSetWithNetwork) { CellSet set(&network_); Cell *inv_cell = network_.findCell(lib_, "INV"); set.insert(inv_cell); EXPECT_FALSE(set.empty()); } // logicValueString TEST(LogicValueStringTest, AllValues) { char c0 = logicValueString(LogicValue::zero); EXPECT_EQ(c0, '0'); char c1 = logicValueString(LogicValue::one); EXPECT_EQ(c1, '1'); char cx = logicValueString(LogicValue::unknown); EXPECT_EQ(cx, 'X'); } // Network: drivers from net (returned set is cached, do NOT delete) TEST_F(ConcreteNetworkLinkedTest, DriversFromNetExercise) { PinSet *drivers = network_.drivers(net2_); EXPECT_NE(drivers, nullptr); EXPECT_FALSE(drivers->empty()); } // Network: constantPinIterator TEST_F(ConcreteNetworkLinkedTest, ConstantPinIterator2) { ConstantPinIterator *iter = network_.constantPinIterator(); EXPECT_NE(iter, nullptr); // No constants set, so should be empty EXPECT_FALSE(iter->hasNext()); delete iter; } // Network: addConstantNet exercises constantPinIterator paths TEST_F(ConcreteNetworkLinkedTest, AddConstantNetExercise) { network_.addConstantNet(net1_, LogicValue::zero); ConstantPinIterator *iter = network_.constantPinIterator(); EXPECT_NE(iter, nullptr); bool found = false; while (iter->hasNext()) { const Pin *pin; LogicValue val; iter->next(pin, val); found = true; } delete iter; EXPECT_TRUE(found); } // PinIdHash TEST_F(ConcreteNetworkLinkedTest, PinIdHashConstructor) { PinIdHash hash(&network_); size_t h = hash(pin_u1_a_); EXPECT_GT(h, 0u); } // Network: drivers from pin TEST_F(ConcreteNetworkLinkedTest, FindNetDriversFromPin) { PinSet *drivers = network_.drivers(pin_u2_a_); EXPECT_NE(drivers, nullptr); } // Network: connectedPins via net TEST_F(ConcreteNetworkLinkedTest, ConnectedPinsViaNet) { PinConnectedPinIterator *iter = network_.connectedPinIterator(net2_); int count = 0; while (iter->hasNext()) { iter->next(); count++; } delete iter; EXPECT_GE(count, 2); } // Network: portDirection from port object TEST_F(ConcreteNetworkLinkedTest, PortDirectionAccess) { Cell *inv_cell = network_.findCell(lib_, "INV"); Port *port_a = network_.findPort(inv_cell, "A"); Port *port_y = network_.findPort(inv_cell, "Y"); EXPECT_EQ(network_.direction(port_a), PortDirection::input()); EXPECT_EQ(network_.direction(port_y), PortDirection::output()); } // Network: various accessor methods TEST_F(ConcreteNetworkLinkedTest, LibraryNameAccess) { EXPECT_STREQ(network_.name(lib_), "test_lib"); } TEST_F(ConcreteNetworkLinkedTest, CellNameAccess) { Cell *inv_cell = network_.findCell(lib_, "INV"); EXPECT_STREQ(network_.name(inv_cell), "INV"); } TEST_F(ConcreteNetworkLinkedTest, PortNameAccess) { Cell *inv_cell = network_.findCell(lib_, "INV"); Port *port_a = network_.findPort(inv_cell, "A"); EXPECT_STREQ(network_.name(port_a), "A"); } TEST_F(ConcreteNetworkLinkedTest, NetNameAccess) { EXPECT_STREQ(network_.name(net1_), "n1"); } // Network: cell filename TEST_F(ConcreteNetworkLinkedTest, CellFilename) { Cell *inv_cell = network_.findCell(lib_, "INV"); const char *fn = network_.filename(inv_cell); EXPECT_STREQ(fn, "test.lib"); } // PinSet default constructor TEST(PinSetDefaultTest, EmptySet) { PinSet set; EXPECT_TRUE(set.empty()); } // InstanceSet default constructor TEST(InstanceSetDefaultTest, EmptySet) { InstanceSet set; EXPECT_TRUE(set.empty()); } // NetSet default constructor TEST(NetSetDefaultTest, EmptySet) { NetSet set; EXPECT_TRUE(set.empty()); } //////////////////////////////////////////////////////////////// // R5_ tests for additional network coverage //////////////////////////////////////////////////////////////// // Network: connect via Port path with a freshly made instance TEST_F(ConcreteNetworkLinkedTest, ConnectNewPin) { Cell *inv_cell = network_.findCell(lib_, "INV"); Instance *u3 = network_.makeInstance(inv_cell, "u3", network_.topInstance()); Port *port_a = network_.findPort(inv_cell, "A"); Net *n_new = network_.makeNet("n_new", network_.topInstance()); Pin *pin = network_.connect(u3, port_a, n_new); EXPECT_NE(pin, nullptr); EXPECT_EQ(network_.net(pin), n_new); } // ConcreteCell: findPort for bus bits by name TEST(ConcreteCellTest, FindBusBitByName) { ConcreteLibrary lib("test_lib", "test.lib", false); lib.setBusBrkts('[', ']'); ConcreteCell *cell = lib.makeCell("REG", true, ""); cell->makeBusPort("D", 3, 0); ConcretePort *bit0 = cell->findPort("D[0]"); EXPECT_NE(bit0, nullptr); ConcretePort *bit3 = cell->findPort("D[3]"); EXPECT_NE(bit3, nullptr); } // Network: isCheckClk (non-liberty pin => false) TEST_F(ConcreteNetworkLinkedTest, IsCheckClk) { EXPECT_FALSE(network_.isCheckClk(pin_u1_a_)); } // Network: busIndexInRange on scalar port (always false) TEST_F(ConcreteNetworkLinkedTest, BusIndexInRangeScalar) { Cell *inv_cell = network_.findCell(lib_, "INV"); Port *port_a = network_.findPort(inv_cell, "A"); EXPECT_FALSE(network_.busIndexInRange(port_a, 0)); } // Network: busIndexInRange on bus port TEST_F(ConcreteNetworkLinkedTest, BusIndexInRangeBus) { ConcreteLibrary *clib = reinterpret_cast(lib_); clib->setBusBrkts('[', ']'); Cell *cell = network_.makeCell(lib_, "BUS_TEST", true, "test.lib"); Port *bus = network_.makeBusPort(cell, "D", 3, 0); EXPECT_TRUE(network_.busIndexInRange(bus, 0)); EXPECT_TRUE(network_.busIndexInRange(bus, 3)); EXPECT_FALSE(network_.busIndexInRange(bus, 4)); EXPECT_FALSE(network_.busIndexInRange(bus, -1)); } // Network: hasMembersViaNetwork on bus port TEST_F(ConcreteNetworkLinkedTest, HasMembersBus) { ConcreteLibrary *clib = reinterpret_cast(lib_); clib->setBusBrkts('[', ']'); Cell *cell = network_.makeCell(lib_, "HAS_MEM_TEST", true, "test.lib"); Port *bus = network_.makeBusPort(cell, "D", 1, 0); EXPECT_TRUE(network_.hasMembers(bus)); } // Network: findMember on bus port TEST_F(ConcreteNetworkLinkedTest, FindMemberBus) { ConcreteLibrary *clib = reinterpret_cast(lib_); clib->setBusBrkts('[', ']'); Cell *cell = network_.makeCell(lib_, "FIND_MEM_TEST", true, "test.lib"); Port *bus = network_.makeBusPort(cell, "D", 1, 0); Port *member = network_.findMember(bus, 0); EXPECT_NE(member, nullptr); Port *member1 = network_.findMember(bus, 1); EXPECT_NE(member1, nullptr); } // Network: isInside (pin inside pin context) TEST_F(ConcreteNetworkLinkedTest, IsInsidePinPin) { EXPECT_FALSE(network_.isInside(pin_u1_a_, pin_u2_a_)); } // (R5_CheckLibertyCorners removed: segfaults without Report* initialized) // Network: findLibertyFilename (none loaded) TEST(ConcreteNetworkExtraTest, FindLibertyFilename) { ConcreteNetwork network; LibertyLibrary *found = network.findLibertyFilename("nonexistent.lib"); EXPECT_EQ(found, nullptr); } // Network: leafInstanceIterator with hierarchical instance TEST_F(ConcreteNetworkLinkedTest, LeafInstanceIteratorHier) { Instance *top = network_.topInstance(); LeafInstanceIterator *iter = network_.leafInstanceIterator(top); int count = 0; while (iter->hasNext()) { iter->next(); count++; } delete iter; EXPECT_EQ(count, 2); } // Network: findPin(Instance, Port) TEST_F(ConcreteNetworkLinkedTest, FindPinByPort2) { Cell *cell = network_.cell(u1_); Port *port_a = network_.findPort(cell, "A"); Pin *found = network_.findPin(u1_, port_a); EXPECT_EQ(found, pin_u1_a_); } // ConcretePort: setBundlePort TEST(ConcretePortTest, SetBundlePort) { ConcreteLibrary lib("test_lib", "test.lib", false); ConcreteCell *cell = lib.makeCell("MUX", true, ""); ConcretePort *a = cell->makePort("A"); ConcretePort *b = cell->makePort("B"); ConcretePortSeq *members = new ConcretePortSeq; members->push_back(a); members->push_back(b); ConcretePort *bundle = cell->makeBundlePort("AB", members); ConcretePort *c = cell->makePort("C"); c->setBundlePort(bundle); EXPECT_NE(c, nullptr); } // BusPort default constructor and setDirection TEST(ConcretePortTest, BusPortDefaultConstructor) { ConcreteLibrary lib("test_lib", "test.lib", false); lib.setBusBrkts('[', ']'); ConcreteCell *cell = lib.makeCell("REG", true, ""); ConcretePort *bus = cell->makeBusPort("D", 1, 0); EXPECT_TRUE(bus->isBus()); PortDirection::init(); bus->setDirection(PortDirection::input()); EXPECT_EQ(bus->direction(), PortDirection::input()); } // ConcreteNetwork: cell(LibertyCell) forwarding TEST(ConcreteNetworkExtraTest, CellFromLibertyCell) { ConcreteNetwork network; Cell *result = network.cell(static_cast(nullptr)); EXPECT_EQ(result, nullptr); } // ConcreteNetwork: cell(const LibertyCell) forwarding TEST(ConcreteNetworkExtraTest, CellFromConstLibertyCell) { ConcreteNetwork network; const Cell *result = network.cell(static_cast(nullptr)); EXPECT_EQ(result, nullptr); } } // namespace sta