Skip to content

Commit d901af3

Browse files
authored
Merge pull request #10733 from The-OpenROAD-Project-staging/odb-design-is-routed-cpp-tests
test/odb: replace design_is_routed golden tests with C++ unit tests
2 parents 165dbe2 + 2e44977 commit d901af3

21 files changed

Lines changed: 149 additions & 2282 deletions

src/odb/test/BUILD

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -156,11 +156,6 @@ COMPULSORY_TESTS = [
156156
"create_sboxes",
157157
"def_dup_net",
158158
"def_parser",
159-
"design_is_routed1",
160-
"design_is_routed2",
161-
"design_is_routed3",
162-
"design_is_routed_fail1",
163-
"design_is_routed_fail2",
164159
"dont_touch",
165160
"dump_netlists",
166161
"dump_netlists_withfill",
@@ -366,9 +361,6 @@ filegroup(
366361
"all_pins_placed1": [
367362
"floorplan_initialize3.def",
368363
],
369-
"all_pins_placed2": [
370-
"design_is_routed1.def",
371-
],
372364
"create_obstruction": [
373365
"create_blockage.def",
374366
],

src/odb/test/CMakeLists.txt

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,6 @@ or_integration_tests(
1212
create_sboxes
1313
def_dup_net
1414
def_parser
15-
design_is_routed1
16-
design_is_routed2
17-
design_is_routed3
18-
design_is_routed_fail1
19-
design_is_routed_fail2
2015
dont_touch
2116
dump_netlists
2217
dump_netlists_withfill

src/odb/test/all_pins_placed2.tcl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# test if all pins are placed
22
source "helpers.tcl"
33
read_lef Nangate45/Nangate45.lef
4-
read_def design_is_routed1.def
4+
read_def all_pins_placed2.def
55

66
if { [all_pins_placed] } {
77
puts "All pins are placed"

src/odb/test/cpp/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,7 @@ cc_test(
207207
"TestAbstractLef.cc",
208208
"TestDbNet.cpp",
209209
"TestDbWire.cc",
210+
"TestDesignIsRouted.cpp",
210211
"TestPolygonalFloorplan.cc",
211212
],
212213
args = [],

src/odb/test/cpp/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ set(TEST_LIBS
2020
GTest::gmock
2121
)
2222

23-
add_executable(OdbGTests TestDbWire.cc TestDbNet.cpp TestAbstractLef.cc TestPolygonalFloorplan.cc)
23+
add_executable(OdbGTests TestDbWire.cc TestDbNet.cpp TestDesignIsRouted.cpp TestAbstractLef.cc TestPolygonalFloorplan.cc)
2424
add_executable(TestCallBacks TestCallBacks.cpp)
2525
add_executable(TestGeom TestGeom.cpp)
2626
add_executable(TestModule TestModule.cpp)
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
// SPDX-License-Identifier: BSD-3-Clause
2+
// Copyright (c) 2026, The OpenROAD Authors
3+
4+
#include <string>
5+
6+
#include "gtest/gtest.h"
7+
#include "odb/db.h"
8+
#include "odb/dbWireCodec.h"
9+
#include "tst/fixture.h"
10+
11+
namespace odb {
12+
13+
// Unit tests for dbBlock::designIsRouted(): a design is "routed" when every
14+
// signal (non-special) net with more than one pin either has routing
15+
// (wires/vias) or is connected by abutment. Special nets are ignored.
16+
class TestDesignIsRouted : public tst::Fixture
17+
{
18+
protected:
19+
void SetUp() override
20+
{
21+
loadTechAndLib(
22+
"tech", "Nangate45.lef", "_main/test/Nangate45/Nangate45.lef");
23+
dbChip* chip = dbChip::create(db_.get(), db_->getTech());
24+
block_ = dbBlock::create(chip, "top");
25+
}
26+
27+
// Create a 2-pin signal net connecting the output of one inverter to the
28+
// input of another (pin_count == 2, so it must be routed to pass).
29+
dbNet* makeMultiPinNet(const std::string& name)
30+
{
31+
dbNet* net = dbNet::create(block_, name.c_str());
32+
dbMaster* inv = db_->findMaster("INV_X1");
33+
dbInst* i0 = dbInst::create(block_, inv, (name + "_i0").c_str());
34+
dbInst* i1 = dbInst::create(block_, inv, (name + "_i1").c_str());
35+
i0->findITerm("ZN")->connect(net);
36+
i1->findITerm("A")->connect(net);
37+
return net;
38+
}
39+
40+
// Attach a trivial metal1 wire so the net counts as routed.
41+
void routeNet(dbNet* net)
42+
{
43+
dbTechLayer* metal1 = db_->getTech()->findLayer("metal1");
44+
dbWire* wire = dbWire::create(net);
45+
dbWireEncoder encoder;
46+
encoder.begin(wire);
47+
encoder.newPath(metal1, dbWireType::ROUTED);
48+
encoder.addPoint(0, 0);
49+
encoder.addPoint(0, 1000);
50+
encoder.end();
51+
}
52+
53+
dbBlock* block_;
54+
};
55+
56+
// A design whose multi-pin signal net carries wires is fully routed.
57+
TEST_F(TestDesignIsRouted, RoutedSignalNet)
58+
{
59+
dbNet* net = makeMultiPinNet("n1");
60+
routeNet(net);
61+
62+
EXPECT_TRUE(block_->designIsRouted(/*verbose=*/false));
63+
}
64+
65+
// Special (power/ground) nets are skipped entirely: an unrouted special net
66+
// does not make the design unrouted.
67+
TEST_F(TestDesignIsRouted, SpecialNetsAreIgnored)
68+
{
69+
dbNet* net = makeMultiPinNet("vdd");
70+
net->setSpecial();
71+
// Intentionally left unrouted.
72+
73+
EXPECT_TRUE(block_->designIsRouted(/*verbose=*/false));
74+
}
75+
76+
// A mix of an (ignored) special net and a routed signal net is fully routed.
77+
TEST_F(TestDesignIsRouted, MixedSpecialAndRoutedSignalNets)
78+
{
79+
dbNet* special = makeMultiPinNet("vdd");
80+
special->setSpecial();
81+
82+
dbNet* signal = makeMultiPinNet("n1");
83+
routeNet(signal);
84+
85+
EXPECT_TRUE(block_->designIsRouted(/*verbose=*/false));
86+
}
87+
88+
// A net with a single pin needs no routing and never makes a design unrouted.
89+
TEST_F(TestDesignIsRouted, SinglePinNetIsRouted)
90+
{
91+
dbNet* net = dbNet::create(block_, "n1");
92+
dbInst* inst = dbInst::create(block_, db_->findMaster("INV_X1"), "i0");
93+
inst->findITerm("A")->connect(net);
94+
95+
EXPECT_TRUE(block_->designIsRouted(/*verbose=*/false));
96+
}
97+
98+
// A design with no nets is trivially routed.
99+
TEST_F(TestDesignIsRouted, EmptyDesignIsRouted)
100+
{
101+
EXPECT_TRUE(block_->designIsRouted(/*verbose=*/false));
102+
}
103+
104+
// A multi-pin signal net with no wires (and no abutment) is unrouted.
105+
TEST_F(TestDesignIsRouted, UnroutedSignalNetFails)
106+
{
107+
makeMultiPinNet("n1");
108+
109+
EXPECT_FALSE(block_->designIsRouted(/*verbose=*/false));
110+
}
111+
112+
// An unrouted signal net is detected even when ignored special nets coexist.
113+
TEST_F(TestDesignIsRouted, UnroutedSignalNetWithSpecialNetsFails)
114+
{
115+
dbNet* special = makeMultiPinNet("vdd");
116+
special->setSpecial();
117+
118+
makeMultiPinNet("n1"); // unrouted signal net
119+
120+
EXPECT_FALSE(block_->designIsRouted(/*verbose=*/false));
121+
}
122+
123+
// Non-verbose mode reports an unrouted design without emitting any warning.
124+
TEST_F(TestDesignIsRouted, NonVerboseEmitsNoWarning)
125+
{
126+
makeMultiPinNet("n1");
127+
makeMultiPinNet("n2");
128+
129+
const int warnings_before = logger_.getWarningCount();
130+
EXPECT_FALSE(block_->designIsRouted(/*verbose=*/false));
131+
EXPECT_EQ(logger_.getWarningCount(), warnings_before);
132+
}
133+
134+
// Verbose mode returns false and warns once per unrouted net (ODB-0232),
135+
// scanning all nets rather than short-circuiting.
136+
TEST_F(TestDesignIsRouted, VerboseWarnsForEachUnroutedNet)
137+
{
138+
makeMultiPinNet("n1");
139+
makeMultiPinNet("n2");
140+
141+
const int warnings_before = logger_.getWarningCount();
142+
EXPECT_FALSE(block_->designIsRouted(/*verbose=*/true));
143+
EXPECT_EQ(logger_.getWarningCount(), warnings_before + 2);
144+
}
145+
146+
} // namespace odb

src/odb/test/design_is_routed1.ok

Lines changed: 0 additions & 5 deletions
This file was deleted.

src/odb/test/design_is_routed1.tcl

Lines changed: 0 additions & 10 deletions
This file was deleted.

0 commit comments

Comments
 (0)