diff --git a/src/cts/include/cts/TritonCTS.h b/src/cts/include/cts/TritonCTS.h index c8f3f563028..4bdc943ebb0 100644 --- a/src/cts/include/cts/TritonCTS.h +++ b/src/cts/include/cts/TritonCTS.h @@ -120,11 +120,16 @@ class TritonCTS void incrementNumClocks() { ++numberOfClocks_; } void clearNumClocks() { numberOfClocks_ = 0; } unsigned getNumClocks() const { return numberOfClocks_; } - void cloneClockGaters(odb::dbNet* clkNet); + void cloneClockGaters(odb::dbNet* clkNet, + std::set& occupiedPositions); void findLongEdges( stt::Tree& clkSteiner, odb::Point driverPt, - std::map>& point2pin); + std::map>& point2pin, + std::set& occupiedPositions); + void resolveLocationCollision(odb::dbInst* clone, + odb::Point location, + std::set& occupiedPositions); void initOneClockTree(odb::dbNet* driverNet, odb::dbNet* clkInputNet, const std::string& sdcClockName, diff --git a/src/cts/src/TritonCTS.cpp b/src/cts/src/TritonCTS.cpp index bcaae1198bb..c8ae25a5bf1 100644 --- a/src/cts/src/TritonCTS.cpp +++ b/src/cts/src/TritonCTS.cpp @@ -855,7 +855,8 @@ std::string TritonCTS::selectBestMaxCapBuffer( // db functions -void TritonCTS::cloneClockGaters(odb::dbNet* clkNet) +void TritonCTS::cloneClockGaters(odb::dbNet* clkNet, + std::set& occupiedPositions) { odb::dbITerm* driver = clkNet->getFirstOutput(); std::vector xs; @@ -888,7 +889,7 @@ void TritonCTS::cloneClockGaters(odb::dbNet* clkNet) if (libertyCell->isInverter() || libertyCell->isBuffer()) { continue; } - cloneClockGaters(outputNet); + cloneClockGaters(outputNet, occupiedPositions); } } if (!driver) { @@ -906,13 +907,14 @@ void TritonCTS::cloneClockGaters(odb::dbNet* clkNet) point2pin[{drvrX, drvrY}].push_back(driver); stt::Tree ftree = options_->getSttBuilder()->makeSteinerTree(clkNet, xs, ys, 0); - findLongEdges(ftree, {drvrX, drvrY}, point2pin); + findLongEdges(ftree, {drvrX, drvrY}, point2pin, occupiedPositions); } void TritonCTS::findLongEdges( stt::Tree& clkSteiner, odb::Point driverPt, - std::map>& point2pin) + std::map>& point2pin, + std::set& occupiedPositions) { const int threshold = options_->getMaxWl(); debugPrint( @@ -1031,7 +1033,7 @@ void TritonCTS::findLongEdges( validClusters); // Insert original ICG to its closest cluster, create clones to drive the - // other clusters + // other clusters. int nClones = 0; // hierarchy fix, make the clone net in the right scope sta::Pin* driver = nullptr; @@ -1162,14 +1164,33 @@ void TritonCTS::findLongEdges( } } - // Move ICG (clone or original) to the center of its sinks - clone->setLocation(sinksBbox.xCenter(), sinksBbox.yCenter()); - clone->setPlacementStatus(odb::dbPlacementStatus::PLACED); + // Resolve location collision and finalize placement. + resolveLocationCollision( + clone, {sinksBbox.xCenter(), sinksBbox.yCenter()}, occupiedPositions); } debugPrint( logger_, CTS, "clock gate cloning", 1, "Created {} clones", nClones); } +void TritonCTS::resolveLocationCollision( + odb::dbInst* clone, + odb::Point location, + std::set& occupiedPositions) +{ + // Ensure position is unique among both other clones and pre-existing + // instances to prevent mapLocationToSink_ key collision. + odb::Point cloneLoc = location; + // Shift by 1 DBU to guarantee unique coordinates on collision case. + // Site-legal placement is handled by downstream DPL. + int shift = 1; + while (occupiedPositions.contains(cloneLoc)) { + cloneLoc.setX(cloneLoc.getX() + shift); + } + occupiedPositions.insert(cloneLoc); + clone->setLocation(cloneLoc.getX(), cloneLoc.getY()); + clone->setPlacementStatus(odb::dbPlacementStatus::PLACED); +} + void TritonCTS::populateTritonCTS() { clearNumClocks(); @@ -1207,13 +1228,23 @@ void TritonCTS::populateTritonCTS() allClkNets.insert(clkNets.begin(), clkNets.end()); } } + // Seed with all existing instance positions to prevent clones from + // landing on a pre-existing cell and causing mapLocationToSink_ + // key collision in HTreeBuilder. + std::set occupiedPositions; + for (odb::dbInst* inst : block_->getInsts()) { + int x, y; + inst->getLocation(x, y); + occupiedPositions.emplace(x, y); + } + // Iterate over all the nets found by the user-input and dbSta for (const auto& clockInfo : clockNetsInfo) { std::set clockNets = clockInfo.first; std::string clkName = clockInfo.second; for (odb::dbNet* net : clockNets) { if (net != nullptr) { - cloneClockGaters(net); + cloneClockGaters(net, occupiedPositions); if (clkName.empty()) { logger_->info(CTS, 95, "Net \"{}\" found.", net->getName()); } else { diff --git a/src/cts/test/BUILD b/src/cts/test/BUILD index 0f93eaba4a6..b86f8f198bd 100644 --- a/src/cts/test/BUILD +++ b/src/cts/test/BUILD @@ -26,6 +26,7 @@ COMPULSORY_TESTS = [ "check_max_fanout3", "check_wire_rc_cts", "clock_buffer_footprint", + "colocated_sinks", "dummy_load", "find_clock", # cmake gives 17.47 um ave sink WL vs. bazel 11.54 um diff --git a/src/cts/test/CMakeLists.txt b/src/cts/test/CMakeLists.txt index 70f72013f33..d9aae7bc1cf 100644 --- a/src/cts/test/CMakeLists.txt +++ b/src/cts/test/CMakeLists.txt @@ -11,6 +11,7 @@ or_integration_tests( array_repair_clock_nets check_buffers check_buffers_blockages + colocated_sinks check_buffers_blockages_merge check_buffer_inference1 check_buffer_inference2 diff --git a/src/cts/test/colocated_sinks.def b/src/cts/test/colocated_sinks.def new file mode 100644 index 00000000000..684e2214d01 --- /dev/null +++ b/src/cts/test/colocated_sinks.def @@ -0,0 +1,258 @@ +VERSION 5.8 ; +DIVIDERCHAR "/" ; +BUSBITCHARS "[]" ; +DESIGN colocated_icg ; +UNITS DISTANCE MICRONS 2000 ; + +DIEAREA ( 0 0 ) ( 400000 400000 ) ; + +ROW ROW_0 FreePDK45_38x28_10R_NP_162NW_34O 0 0 N DO 1052 BY 1 STEP 380 0 ; +ROW ROW_1 FreePDK45_38x28_10R_NP_162NW_34O 0 2800 FS DO 1052 BY 1 STEP 380 0 ; +ROW ROW_2 FreePDK45_38x28_10R_NP_162NW_34O 0 5600 N DO 1052 BY 1 STEP 380 0 ; +ROW ROW_3 FreePDK45_38x28_10R_NP_162NW_34O 0 8400 FS DO 1052 BY 1 STEP 380 0 ; +ROW ROW_4 FreePDK45_38x28_10R_NP_162NW_34O 0 11200 N DO 1052 BY 1 STEP 380 0 ; +ROW ROW_5 FreePDK45_38x28_10R_NP_162NW_34O 0 14000 FS DO 1052 BY 1 STEP 380 0 ; +ROW ROW_6 FreePDK45_38x28_10R_NP_162NW_34O 0 16800 N DO 1052 BY 1 STEP 380 0 ; +ROW ROW_7 FreePDK45_38x28_10R_NP_162NW_34O 0 19600 FS DO 1052 BY 1 STEP 380 0 ; +ROW ROW_8 FreePDK45_38x28_10R_NP_162NW_34O 0 22400 N DO 1052 BY 1 STEP 380 0 ; +ROW ROW_9 FreePDK45_38x28_10R_NP_162NW_34O 0 25200 FS DO 1052 BY 1 STEP 380 0 ; +ROW ROW_10 FreePDK45_38x28_10R_NP_162NW_34O 0 28000 N DO 1052 BY 1 STEP 380 0 ; +ROW ROW_11 FreePDK45_38x28_10R_NP_162NW_34O 0 30800 FS DO 1052 BY 1 STEP 380 0 ; +ROW ROW_12 FreePDK45_38x28_10R_NP_162NW_34O 0 33600 N DO 1052 BY 1 STEP 380 0 ; +ROW ROW_13 FreePDK45_38x28_10R_NP_162NW_34O 0 36400 FS DO 1052 BY 1 STEP 380 0 ; +ROW ROW_14 FreePDK45_38x28_10R_NP_162NW_34O 0 39200 N DO 1052 BY 1 STEP 380 0 ; +ROW ROW_15 FreePDK45_38x28_10R_NP_162NW_34O 0 42000 FS DO 1052 BY 1 STEP 380 0 ; +ROW ROW_16 FreePDK45_38x28_10R_NP_162NW_34O 0 44800 N DO 1052 BY 1 STEP 380 0 ; +ROW ROW_17 FreePDK45_38x28_10R_NP_162NW_34O 0 47600 FS DO 1052 BY 1 STEP 380 0 ; +ROW ROW_18 FreePDK45_38x28_10R_NP_162NW_34O 0 50400 N DO 1052 BY 1 STEP 380 0 ; +ROW ROW_19 FreePDK45_38x28_10R_NP_162NW_34O 0 53200 FS DO 1052 BY 1 STEP 380 0 ; +ROW ROW_20 FreePDK45_38x28_10R_NP_162NW_34O 0 56000 N DO 1052 BY 1 STEP 380 0 ; +ROW ROW_21 FreePDK45_38x28_10R_NP_162NW_34O 0 58800 FS DO 1052 BY 1 STEP 380 0 ; +ROW ROW_22 FreePDK45_38x28_10R_NP_162NW_34O 0 61600 N DO 1052 BY 1 STEP 380 0 ; +ROW ROW_23 FreePDK45_38x28_10R_NP_162NW_34O 0 64400 FS DO 1052 BY 1 STEP 380 0 ; +ROW ROW_24 FreePDK45_38x28_10R_NP_162NW_34O 0 67200 N DO 1052 BY 1 STEP 380 0 ; +ROW ROW_25 FreePDK45_38x28_10R_NP_162NW_34O 0 70000 FS DO 1052 BY 1 STEP 380 0 ; +ROW ROW_26 FreePDK45_38x28_10R_NP_162NW_34O 0 72800 N DO 1052 BY 1 STEP 380 0 ; +ROW ROW_27 FreePDK45_38x28_10R_NP_162NW_34O 0 75600 FS DO 1052 BY 1 STEP 380 0 ; +ROW ROW_28 FreePDK45_38x28_10R_NP_162NW_34O 0 78400 N DO 1052 BY 1 STEP 380 0 ; +ROW ROW_29 FreePDK45_38x28_10R_NP_162NW_34O 0 81200 FS DO 1052 BY 1 STEP 380 0 ; +ROW ROW_30 FreePDK45_38x28_10R_NP_162NW_34O 0 84000 N DO 1052 BY 1 STEP 380 0 ; +ROW ROW_31 FreePDK45_38x28_10R_NP_162NW_34O 0 86800 FS DO 1052 BY 1 STEP 380 0 ; +ROW ROW_32 FreePDK45_38x28_10R_NP_162NW_34O 0 89600 N DO 1052 BY 1 STEP 380 0 ; +ROW ROW_33 FreePDK45_38x28_10R_NP_162NW_34O 0 92400 FS DO 1052 BY 1 STEP 380 0 ; +ROW ROW_34 FreePDK45_38x28_10R_NP_162NW_34O 0 95200 N DO 1052 BY 1 STEP 380 0 ; +ROW ROW_35 FreePDK45_38x28_10R_NP_162NW_34O 0 98000 FS DO 1052 BY 1 STEP 380 0 ; +ROW ROW_36 FreePDK45_38x28_10R_NP_162NW_34O 0 100800 N DO 1052 BY 1 STEP 380 0 ; +ROW ROW_37 FreePDK45_38x28_10R_NP_162NW_34O 0 103600 FS DO 1052 BY 1 STEP 380 0 ; +ROW ROW_38 FreePDK45_38x28_10R_NP_162NW_34O 0 106400 N DO 1052 BY 1 STEP 380 0 ; +ROW ROW_39 FreePDK45_38x28_10R_NP_162NW_34O 0 109200 FS DO 1052 BY 1 STEP 380 0 ; +ROW ROW_40 FreePDK45_38x28_10R_NP_162NW_34O 0 112000 N DO 1052 BY 1 STEP 380 0 ; +ROW ROW_41 FreePDK45_38x28_10R_NP_162NW_34O 0 114800 FS DO 1052 BY 1 STEP 380 0 ; +ROW ROW_42 FreePDK45_38x28_10R_NP_162NW_34O 0 117600 N DO 1052 BY 1 STEP 380 0 ; +ROW ROW_43 FreePDK45_38x28_10R_NP_162NW_34O 0 120400 FS DO 1052 BY 1 STEP 380 0 ; +ROW ROW_44 FreePDK45_38x28_10R_NP_162NW_34O 0 123200 N DO 1052 BY 1 STEP 380 0 ; +ROW ROW_45 FreePDK45_38x28_10R_NP_162NW_34O 0 126000 FS DO 1052 BY 1 STEP 380 0 ; +ROW ROW_46 FreePDK45_38x28_10R_NP_162NW_34O 0 128800 N DO 1052 BY 1 STEP 380 0 ; +ROW ROW_47 FreePDK45_38x28_10R_NP_162NW_34O 0 131600 FS DO 1052 BY 1 STEP 380 0 ; +ROW ROW_48 FreePDK45_38x28_10R_NP_162NW_34O 0 134400 N DO 1052 BY 1 STEP 380 0 ; +ROW ROW_49 FreePDK45_38x28_10R_NP_162NW_34O 0 137200 FS DO 1052 BY 1 STEP 380 0 ; +ROW ROW_50 FreePDK45_38x28_10R_NP_162NW_34O 0 140000 N DO 1052 BY 1 STEP 380 0 ; +ROW ROW_51 FreePDK45_38x28_10R_NP_162NW_34O 0 142800 FS DO 1052 BY 1 STEP 380 0 ; +ROW ROW_52 FreePDK45_38x28_10R_NP_162NW_34O 0 145600 N DO 1052 BY 1 STEP 380 0 ; +ROW ROW_53 FreePDK45_38x28_10R_NP_162NW_34O 0 148400 FS DO 1052 BY 1 STEP 380 0 ; +ROW ROW_54 FreePDK45_38x28_10R_NP_162NW_34O 0 151200 N DO 1052 BY 1 STEP 380 0 ; +ROW ROW_55 FreePDK45_38x28_10R_NP_162NW_34O 0 154000 FS DO 1052 BY 1 STEP 380 0 ; +ROW ROW_56 FreePDK45_38x28_10R_NP_162NW_34O 0 156800 N DO 1052 BY 1 STEP 380 0 ; +ROW ROW_57 FreePDK45_38x28_10R_NP_162NW_34O 0 159600 FS DO 1052 BY 1 STEP 380 0 ; +ROW ROW_58 FreePDK45_38x28_10R_NP_162NW_34O 0 162400 N DO 1052 BY 1 STEP 380 0 ; +ROW ROW_59 FreePDK45_38x28_10R_NP_162NW_34O 0 165200 FS DO 1052 BY 1 STEP 380 0 ; +ROW ROW_60 FreePDK45_38x28_10R_NP_162NW_34O 0 168000 N DO 1052 BY 1 STEP 380 0 ; +ROW ROW_61 FreePDK45_38x28_10R_NP_162NW_34O 0 170800 FS DO 1052 BY 1 STEP 380 0 ; +ROW ROW_62 FreePDK45_38x28_10R_NP_162NW_34O 0 173600 N DO 1052 BY 1 STEP 380 0 ; +ROW ROW_63 FreePDK45_38x28_10R_NP_162NW_34O 0 176400 FS DO 1052 BY 1 STEP 380 0 ; +ROW ROW_64 FreePDK45_38x28_10R_NP_162NW_34O 0 179200 N DO 1052 BY 1 STEP 380 0 ; +ROW ROW_65 FreePDK45_38x28_10R_NP_162NW_34O 0 182000 FS DO 1052 BY 1 STEP 380 0 ; +ROW ROW_66 FreePDK45_38x28_10R_NP_162NW_34O 0 184800 N DO 1052 BY 1 STEP 380 0 ; +ROW ROW_67 FreePDK45_38x28_10R_NP_162NW_34O 0 187600 FS DO 1052 BY 1 STEP 380 0 ; +ROW ROW_68 FreePDK45_38x28_10R_NP_162NW_34O 0 190400 N DO 1052 BY 1 STEP 380 0 ; +ROW ROW_69 FreePDK45_38x28_10R_NP_162NW_34O 0 193200 FS DO 1052 BY 1 STEP 380 0 ; +ROW ROW_70 FreePDK45_38x28_10R_NP_162NW_34O 0 196000 N DO 1052 BY 1 STEP 380 0 ; +ROW ROW_71 FreePDK45_38x28_10R_NP_162NW_34O 0 198800 FS DO 1052 BY 1 STEP 380 0 ; +ROW ROW_72 FreePDK45_38x28_10R_NP_162NW_34O 0 201600 N DO 1052 BY 1 STEP 380 0 ; +ROW ROW_73 FreePDK45_38x28_10R_NP_162NW_34O 0 204400 FS DO 1052 BY 1 STEP 380 0 ; +ROW ROW_74 FreePDK45_38x28_10R_NP_162NW_34O 0 207200 N DO 1052 BY 1 STEP 380 0 ; +ROW ROW_75 FreePDK45_38x28_10R_NP_162NW_34O 0 210000 FS DO 1052 BY 1 STEP 380 0 ; +ROW ROW_76 FreePDK45_38x28_10R_NP_162NW_34O 0 212800 N DO 1052 BY 1 STEP 380 0 ; +ROW ROW_77 FreePDK45_38x28_10R_NP_162NW_34O 0 215600 FS DO 1052 BY 1 STEP 380 0 ; +ROW ROW_78 FreePDK45_38x28_10R_NP_162NW_34O 0 218400 N DO 1052 BY 1 STEP 380 0 ; +ROW ROW_79 FreePDK45_38x28_10R_NP_162NW_34O 0 221200 FS DO 1052 BY 1 STEP 380 0 ; +ROW ROW_80 FreePDK45_38x28_10R_NP_162NW_34O 0 224000 N DO 1052 BY 1 STEP 380 0 ; +ROW ROW_81 FreePDK45_38x28_10R_NP_162NW_34O 0 226800 FS DO 1052 BY 1 STEP 380 0 ; +ROW ROW_82 FreePDK45_38x28_10R_NP_162NW_34O 0 229600 N DO 1052 BY 1 STEP 380 0 ; +ROW ROW_83 FreePDK45_38x28_10R_NP_162NW_34O 0 232400 FS DO 1052 BY 1 STEP 380 0 ; +ROW ROW_84 FreePDK45_38x28_10R_NP_162NW_34O 0 235200 N DO 1052 BY 1 STEP 380 0 ; +ROW ROW_85 FreePDK45_38x28_10R_NP_162NW_34O 0 238000 FS DO 1052 BY 1 STEP 380 0 ; +ROW ROW_86 FreePDK45_38x28_10R_NP_162NW_34O 0 240800 N DO 1052 BY 1 STEP 380 0 ; +ROW ROW_87 FreePDK45_38x28_10R_NP_162NW_34O 0 243600 FS DO 1052 BY 1 STEP 380 0 ; +ROW ROW_88 FreePDK45_38x28_10R_NP_162NW_34O 0 246400 N DO 1052 BY 1 STEP 380 0 ; +ROW ROW_89 FreePDK45_38x28_10R_NP_162NW_34O 0 249200 FS DO 1052 BY 1 STEP 380 0 ; +ROW ROW_90 FreePDK45_38x28_10R_NP_162NW_34O 0 252000 N DO 1052 BY 1 STEP 380 0 ; +ROW ROW_91 FreePDK45_38x28_10R_NP_162NW_34O 0 254800 FS DO 1052 BY 1 STEP 380 0 ; +ROW ROW_92 FreePDK45_38x28_10R_NP_162NW_34O 0 257600 N DO 1052 BY 1 STEP 380 0 ; +ROW ROW_93 FreePDK45_38x28_10R_NP_162NW_34O 0 260400 FS DO 1052 BY 1 STEP 380 0 ; +ROW ROW_94 FreePDK45_38x28_10R_NP_162NW_34O 0 263200 N DO 1052 BY 1 STEP 380 0 ; +ROW ROW_95 FreePDK45_38x28_10R_NP_162NW_34O 0 266000 FS DO 1052 BY 1 STEP 380 0 ; +ROW ROW_96 FreePDK45_38x28_10R_NP_162NW_34O 0 268800 N DO 1052 BY 1 STEP 380 0 ; +ROW ROW_97 FreePDK45_38x28_10R_NP_162NW_34O 0 271600 FS DO 1052 BY 1 STEP 380 0 ; +ROW ROW_98 FreePDK45_38x28_10R_NP_162NW_34O 0 274400 N DO 1052 BY 1 STEP 380 0 ; +ROW ROW_99 FreePDK45_38x28_10R_NP_162NW_34O 0 277200 FS DO 1052 BY 1 STEP 380 0 ; +ROW ROW_100 FreePDK45_38x28_10R_NP_162NW_34O 0 280000 N DO 1052 BY 1 STEP 380 0 ; +ROW ROW_101 FreePDK45_38x28_10R_NP_162NW_34O 0 282800 FS DO 1052 BY 1 STEP 380 0 ; +ROW ROW_102 FreePDK45_38x28_10R_NP_162NW_34O 0 285600 N DO 1052 BY 1 STEP 380 0 ; +ROW ROW_103 FreePDK45_38x28_10R_NP_162NW_34O 0 288400 FS DO 1052 BY 1 STEP 380 0 ; +ROW ROW_104 FreePDK45_38x28_10R_NP_162NW_34O 0 291200 N DO 1052 BY 1 STEP 380 0 ; +ROW ROW_105 FreePDK45_38x28_10R_NP_162NW_34O 0 294000 FS DO 1052 BY 1 STEP 380 0 ; +ROW ROW_106 FreePDK45_38x28_10R_NP_162NW_34O 0 296800 N DO 1052 BY 1 STEP 380 0 ; +ROW ROW_107 FreePDK45_38x28_10R_NP_162NW_34O 0 299600 FS DO 1052 BY 1 STEP 380 0 ; +ROW ROW_108 FreePDK45_38x28_10R_NP_162NW_34O 0 302400 N DO 1052 BY 1 STEP 380 0 ; +ROW ROW_109 FreePDK45_38x28_10R_NP_162NW_34O 0 305200 FS DO 1052 BY 1 STEP 380 0 ; +ROW ROW_110 FreePDK45_38x28_10R_NP_162NW_34O 0 308000 N DO 1052 BY 1 STEP 380 0 ; +ROW ROW_111 FreePDK45_38x28_10R_NP_162NW_34O 0 310800 FS DO 1052 BY 1 STEP 380 0 ; +ROW ROW_112 FreePDK45_38x28_10R_NP_162NW_34O 0 313600 N DO 1052 BY 1 STEP 380 0 ; +ROW ROW_113 FreePDK45_38x28_10R_NP_162NW_34O 0 316400 FS DO 1052 BY 1 STEP 380 0 ; +ROW ROW_114 FreePDK45_38x28_10R_NP_162NW_34O 0 319200 N DO 1052 BY 1 STEP 380 0 ; +ROW ROW_115 FreePDK45_38x28_10R_NP_162NW_34O 0 322000 FS DO 1052 BY 1 STEP 380 0 ; +ROW ROW_116 FreePDK45_38x28_10R_NP_162NW_34O 0 324800 N DO 1052 BY 1 STEP 380 0 ; +ROW ROW_117 FreePDK45_38x28_10R_NP_162NW_34O 0 327600 FS DO 1052 BY 1 STEP 380 0 ; +ROW ROW_118 FreePDK45_38x28_10R_NP_162NW_34O 0 330400 N DO 1052 BY 1 STEP 380 0 ; +ROW ROW_119 FreePDK45_38x28_10R_NP_162NW_34O 0 333200 FS DO 1052 BY 1 STEP 380 0 ; +ROW ROW_120 FreePDK45_38x28_10R_NP_162NW_34O 0 336000 N DO 1052 BY 1 STEP 380 0 ; +ROW ROW_121 FreePDK45_38x28_10R_NP_162NW_34O 0 338800 FS DO 1052 BY 1 STEP 380 0 ; +ROW ROW_122 FreePDK45_38x28_10R_NP_162NW_34O 0 341600 N DO 1052 BY 1 STEP 380 0 ; +ROW ROW_123 FreePDK45_38x28_10R_NP_162NW_34O 0 344400 FS DO 1052 BY 1 STEP 380 0 ; +ROW ROW_124 FreePDK45_38x28_10R_NP_162NW_34O 0 347200 N DO 1052 BY 1 STEP 380 0 ; +ROW ROW_125 FreePDK45_38x28_10R_NP_162NW_34O 0 350000 FS DO 1052 BY 1 STEP 380 0 ; +ROW ROW_126 FreePDK45_38x28_10R_NP_162NW_34O 0 352800 N DO 1052 BY 1 STEP 380 0 ; +ROW ROW_127 FreePDK45_38x28_10R_NP_162NW_34O 0 355600 FS DO 1052 BY 1 STEP 380 0 ; +ROW ROW_128 FreePDK45_38x28_10R_NP_162NW_34O 0 358400 N DO 1052 BY 1 STEP 380 0 ; +ROW ROW_129 FreePDK45_38x28_10R_NP_162NW_34O 0 361200 FS DO 1052 BY 1 STEP 380 0 ; +ROW ROW_130 FreePDK45_38x28_10R_NP_162NW_34O 0 364000 N DO 1052 BY 1 STEP 380 0 ; +ROW ROW_131 FreePDK45_38x28_10R_NP_162NW_34O 0 366800 FS DO 1052 BY 1 STEP 380 0 ; +ROW ROW_132 FreePDK45_38x28_10R_NP_162NW_34O 0 369600 N DO 1052 BY 1 STEP 380 0 ; +ROW ROW_133 FreePDK45_38x28_10R_NP_162NW_34O 0 372400 FS DO 1052 BY 1 STEP 380 0 ; +ROW ROW_134 FreePDK45_38x28_10R_NP_162NW_34O 0 375200 N DO 1052 BY 1 STEP 380 0 ; +ROW ROW_135 FreePDK45_38x28_10R_NP_162NW_34O 0 378000 FS DO 1052 BY 1 STEP 380 0 ; +ROW ROW_136 FreePDK45_38x28_10R_NP_162NW_34O 0 380800 N DO 1052 BY 1 STEP 380 0 ; +ROW ROW_137 FreePDK45_38x28_10R_NP_162NW_34O 0 383600 FS DO 1052 BY 1 STEP 380 0 ; +ROW ROW_138 FreePDK45_38x28_10R_NP_162NW_34O 0 386400 N DO 1052 BY 1 STEP 380 0 ; +ROW ROW_139 FreePDK45_38x28_10R_NP_162NW_34O 0 389200 FS DO 1052 BY 1 STEP 380 0 ; +ROW ROW_140 FreePDK45_38x28_10R_NP_162NW_34O 0 392000 N DO 1052 BY 1 STEP 380 0 ; +ROW ROW_141 FreePDK45_38x28_10R_NP_162NW_34O 0 394800 FS DO 1052 BY 1 STEP 380 0 ; + + +COMPONENTS 38 ; +- icg_a CLKGATE_X1 + PLACED ( 190000 10000 ) N + ; +- icg_b CLKGATE_X1 + PLACED ( 200000 10000 ) N + ; +- ffa_0 DFF_X1 + PLACED ( 50000 50000 ) N + ; +- ffa_1 DFF_X1 + PLACED ( 150000 50000 ) N + ; +- ffa_2 DFF_X1 + PLACED ( 50000 150000 ) N + ; +- ffa_3 DFF_X1 + PLACED ( 150000 150000 ) N + ; +- ffa_4 DFF_X1 + PLACED ( 70000 90000 ) N + ; +- ffa_5 DFF_X1 + PLACED ( 130000 90000 ) N + ; +- ffa_6 DFF_X1 + PLACED ( 70000 110000 ) N + ; +- ffa_7 DFF_X1 + PLACED ( 130000 110000 ) N + ; +- ffb_0 DFF_X1 + PLACED ( 60000 60000 ) N + ; +- ffb_1 DFF_X1 + PLACED ( 140000 60000 ) N + ; +- ffb_2 DFF_X1 + PLACED ( 60000 140000 ) N + ; +- ffb_3 DFF_X1 + PLACED ( 140000 140000 ) N + ; +- ffb_4 DFF_X1 + PLACED ( 80000 85000 ) N + ; +- ffb_5 DFF_X1 + PLACED ( 120000 85000 ) N + ; +- ffb_6 DFF_X1 + PLACED ( 80000 115000 ) N + ; +- ffb_7 DFF_X1 + PLACED ( 120000 115000 ) N + ; +- reg_0 DFF_X1 + PLACED ( 30000 230000 ) N + ; +- reg_1 DFF_X1 + PLACED ( 110000 230000 ) N + ; +- reg_2 DFF_X1 + PLACED ( 190000 230000 ) N + ; +- reg_3 DFF_X1 + PLACED ( 270000 230000 ) N + ; +- reg_4 DFF_X1 + PLACED ( 350000 230000 ) N + ; +- reg_5 DFF_X1 + PLACED ( 30000 280000 ) N + ; +- reg_6 DFF_X1 + PLACED ( 110000 280000 ) N + ; +- reg_7 DFF_X1 + PLACED ( 190000 280000 ) N + ; +- reg_8 DFF_X1 + PLACED ( 270000 280000 ) N + ; +- reg_9 DFF_X1 + PLACED ( 350000 280000 ) N + ; +- reg_10 DFF_X1 + PLACED ( 30000 330000 ) N + ; +- reg_11 DFF_X1 + PLACED ( 110000 330000 ) N + ; +- reg_12 DFF_X1 + PLACED ( 190000 330000 ) N + ; +- reg_13 DFF_X1 + PLACED ( 270000 330000 ) N + ; +- reg_14 DFF_X1 + PLACED ( 350000 330000 ) N + ; +- reg_15 DFF_X1 + PLACED ( 30000 380000 ) N + ; +- reg_16 DFF_X1 + PLACED ( 110000 380000 ) N + ; +- reg_17 DFF_X1 + PLACED ( 190000 380000 ) N + ; +- reg_18 DFF_X1 + PLACED ( 270000 380000 ) N + ; +- reg_19 DFF_X1 + PLACED ( 350000 380000 ) N + ; +END COMPONENTS + +PINS 1 ; +- clk + NET clk + DIRECTION INPUT + USE SIGNAL + + LAYER metal6 ( -140 0 ) ( 140 280 ) + + FIXED ( 200000 400000 ) S ; +END PINS + +NETS 3 ; +- clk + ( PIN clk ) ( icg_a CK ) ( icg_b CK ) + ( reg_0 CK ) ( reg_1 CK ) ( reg_2 CK ) ( reg_3 CK ) ( reg_4 CK ) + ( reg_5 CK ) ( reg_6 CK ) ( reg_7 CK ) ( reg_8 CK ) ( reg_9 CK ) + ( reg_10 CK ) ( reg_11 CK ) ( reg_12 CK ) ( reg_13 CK ) ( reg_14 CK ) + ( reg_15 CK ) ( reg_16 CK ) ( reg_17 CK ) ( reg_18 CK ) ( reg_19 CK ) + ; +- gclk_a + ( icg_a GCK ) + ( ffa_0 CK ) ( ffa_1 CK ) ( ffa_2 CK ) ( ffa_3 CK ) + ( ffa_4 CK ) ( ffa_5 CK ) ( ffa_6 CK ) ( ffa_7 CK ) + ; +- gclk_b + ( icg_b GCK ) + ( ffb_0 CK ) ( ffb_1 CK ) ( ffb_2 CK ) ( ffb_3 CK ) + ( ffb_4 CK ) ( ffb_5 CK ) ( ffb_6 CK ) ( ffb_7 CK ) + ; +END NETS + +END DESIGN diff --git a/src/cts/test/colocated_sinks.ok b/src/cts/test/colocated_sinks.ok new file mode 100644 index 00000000000..4fd4b6b0667 --- /dev/null +++ b/src/cts/test/colocated_sinks.ok @@ -0,0 +1,141 @@ +[INFO ODB-0227] LEF file: Nangate45/Nangate45.lef, created 22 layers, 27 vias, 135 library cells +[INFO ODB-0128] Design: colocated_icg +[INFO ODB-0130] Created 1 pins. +[INFO ODB-0131] Created 38 components and 226 component-terminals. +[INFO ODB-0133] Created 3 nets and 40 connections. +[INFO CTS-0050] Root buffer is CLKBUF_X3. +[INFO CTS-0051] Sink buffer is CLKBUF_X3. +[INFO CTS-0052] The following clock buffers will be used for CTS: + CLKBUF_X3 +[INFO CTS-0049] Characterization buffer is CLKBUF_X3. +[INFO CTS-0007] Net "clk" found for clock "clk". +[INFO CTS-0011] Clock net "clk" for macros has 2 sinks. +[INFO CTS-0011] Clock net "clk_regs" for registers has 20 sinks. +[INFO CTS-0010] Clock net "gclk_a" has 8 sinks. +[INFO CTS-0010] Clock net "gclk_b" has 8 sinks. +[INFO CTS-0008] TritonCTS found 4 clock nets. +[INFO CTS-0097] Characterization used 1 buffer(s) types. +[INFO CTS-0201] 0 blockages from hard placement blockages and placed macros will be used. +[INFO CTS-0027] Generating H-Tree topology for net clk. +[INFO CTS-0028] Total number of sinks: 2. +[INFO CTS-0029] Macro sinks will be clustered in groups of up to 4 and with maximum cluster diameter of 50.0 um. +[INFO CTS-0030] Number of static layers: 1. +[INFO CTS-0020] Wire segment unit: 14000 dbu (7 um). +[INFO CTS-0021] Distance between buffers: 7 units (100 um). +[INFO CTS-0023] Original sink region: [(106665, 102210), (106666, 102210)]. +[INFO CTS-0024] Normalized sink region: [(7.61893, 7.30071), (7.619, 7.30071)]. +[INFO CTS-0025] Width: 0.0001. +[INFO CTS-0026] Height: 0.0000. + Level 1 + Direction: Horizontal + Sinks per sub-region: 1 + Sub-region size: 0.0000 X 0.0000 +[INFO CTS-0034] Segment length (rounded): 1. +[INFO CTS-0032] Stop criterion found. Max number of sinks is 15. +[INFO CTS-0035] Number of sinks covered: 2. +[INFO CTS-0201] 0 blockages from hard placement blockages and placed macros will be used. +[INFO CTS-0027] Generating H-Tree topology for net clk_regs. +[INFO CTS-0028] Total number of sinks: 20. +[INFO CTS-0090] Sinks will be clustered based on buffer max cap. +[INFO CTS-0030] Number of static layers: 1. +[INFO CTS-0020] Wire segment unit: 14000 dbu (7 um). +[INFO CTS-0021] Distance between buffers: 7 units (100 um). +[INFO CTS-0023] Original sink region: [(33230, 231230), (353230, 381230)]. +[INFO CTS-0024] Normalized sink region: [(2.37357, 16.5164), (25.2307, 27.2307)]. +[INFO CTS-0025] Width: 22.8571. +[INFO CTS-0026] Height: 10.7143. + Level 1 + Direction: Horizontal + Sinks per sub-region: 10 + Sub-region size: 11.4286 X 10.7143 +[INFO CTS-0034] Segment length (rounded): 6. +[INFO CTS-0032] Stop criterion found. Max number of sinks is 15. +[INFO CTS-0035] Number of sinks covered: 20. +[INFO CTS-0201] 0 blockages from hard placement blockages and placed macros will be used. +[INFO CTS-0027] Generating H-Tree topology for net gclk_a. +[INFO CTS-0028] Total number of sinks: 8. +[INFO CTS-0090] Sinks will be clustered based on buffer max cap. +[INFO CTS-0030] Number of static layers: 1. +[INFO CTS-0020] Wire segment unit: 14000 dbu (7 um). +[INFO CTS-0021] Distance between buffers: 7 units (100 um). +[INFO CTS-0023] Original sink region: [(53230, 51230), (153230, 151230)]. +[INFO CTS-0024] Normalized sink region: [(3.80214, 3.65929), (10.945, 10.8021)]. +[INFO CTS-0025] Width: 7.1429. +[INFO CTS-0026] Height: 7.1429. + Level 1 + Direction: Vertical + Sinks per sub-region: 4 + Sub-region size: 7.1429 X 3.5714 +[INFO CTS-0034] Segment length (rounded): 2. +[INFO CTS-0032] Stop criterion found. Max number of sinks is 15. +[INFO CTS-0035] Number of sinks covered: 8. +[INFO CTS-0201] 0 blockages from hard placement blockages and placed macros will be used. +[INFO CTS-0027] Generating H-Tree topology for net gclk_b. +[INFO CTS-0028] Total number of sinks: 8. +[INFO CTS-0090] Sinks will be clustered based on buffer max cap. +[INFO CTS-0030] Number of static layers: 1. +[INFO CTS-0020] Wire segment unit: 14000 dbu (7 um). +[INFO CTS-0021] Distance between buffers: 7 units (100 um). +[INFO CTS-0023] Original sink region: [(63230, 61230), (143230, 141230)]. +[INFO CTS-0024] Normalized sink region: [(4.51643, 4.37357), (10.2307, 10.0879)]. +[INFO CTS-0025] Width: 5.7143. +[INFO CTS-0026] Height: 5.7143. + Level 1 + Direction: Vertical + Sinks per sub-region: 4 + Sub-region size: 5.7143 X 2.8571 +[INFO CTS-0034] Segment length (rounded): 1. +[INFO CTS-0032] Stop criterion found. Max number of sinks is 15. +[INFO CTS-0035] Number of sinks covered: 8. +[INFO CTS-0018] Created 3 clock buffers. +[INFO CTS-0012] Minimum number of buffers in the clock path: 2. +[INFO CTS-0013] Maximum number of buffers in the clock path: 2. +[INFO CTS-0015] Created 3 clock nets. +[INFO CTS-0016] Fanout distribution for the current clock = 1:2.. +[INFO CTS-0017] Max level of the clock tree: 1. +[INFO CTS-0018] Created 3 clock buffers. +[INFO CTS-0012] Minimum number of buffers in the clock path: 2. +[INFO CTS-0013] Maximum number of buffers in the clock path: 2. +[INFO CTS-0015] Created 3 clock nets. +[INFO CTS-0016] Fanout distribution for the current clock = 8:1, 12:1.. +[INFO CTS-0017] Max level of the clock tree: 1. +[INFO CTS-0018] Created 3 clock buffers. +[INFO CTS-0012] Minimum number of buffers in the clock path: 2. +[INFO CTS-0013] Maximum number of buffers in the clock path: 2. +[INFO CTS-0015] Created 3 clock nets. +[INFO CTS-0016] Fanout distribution for the current clock = 4:2.. +[INFO CTS-0017] Max level of the clock tree: 1. +[INFO CTS-0018] Created 3 clock buffers. +[INFO CTS-0012] Minimum number of buffers in the clock path: 2. +[INFO CTS-0013] Maximum number of buffers in the clock path: 2. +[INFO CTS-0015] Created 3 clock nets. +[INFO CTS-0016] Fanout distribution for the current clock = 4:2.. +[INFO CTS-0017] Max level of the clock tree: 1. +[INFO CTS-0098] Clock net "clk" +[INFO CTS-0099] Sinks 2 +[INFO CTS-0100] Leaf buffers 0 +[INFO CTS-0101] Average sink wire length 209.23 um +[INFO CTS-0102] Path depth 2 - 2 +[INFO CTS-0207] Dummy loads inserted 0 +[INFO CTS-0098] Clock net "clk_regs" +[INFO CTS-0099] Sinks 21 +[INFO CTS-0100] Leaf buffers 0 +[INFO CTS-0101] Average sink wire length 89.65 um +[INFO CTS-0102] Path depth 2 - 2 +[INFO CTS-0207] Dummy loads inserted 1 +[INFO CTS-0098] Clock net "gclk_a" +[INFO CTS-0099] Sinks 8 +[INFO CTS-0100] Leaf buffers 0 +[INFO CTS-0101] Average sink wire length 46.78 um +[INFO CTS-0102] Path depth 2 - 2 +[INFO CTS-0207] Dummy loads inserted 0 +[INFO CTS-0098] Clock net "gclk_b" +[INFO CTS-0099] Sinks 8 +[INFO CTS-0100] Leaf buffers 0 +[INFO CTS-0101] Average sink wire length 31.58 um +[INFO CTS-0102] Path depth 2 - 2 +[INFO CTS-0207] Dummy loads inserted 0 +[INFO CTS-0033] Balancing latency for clock clk +[INFO CTS-0036] inserted 1 delay buffers +[INFO CTS-0037] Total number of delay buffers: 1 +PASS: Both ICGs properly connected to CTS tree diff --git a/src/cts/test/colocated_sinks.tcl b/src/cts/test/colocated_sinks.tcl new file mode 100644 index 00000000000..f1eadc38292 --- /dev/null +++ b/src/cts/test/colocated_sinks.tcl @@ -0,0 +1,66 @@ +# Test: CTS handles co-located ICGs whose sinksBbox centers coincide. +# +# Related issue #9816 +# Two ICGs (icg_a, icg_b) drive FFs arranged symmetrically around the +# same center point (100000, 100000). cloneClockGaters() moves each ICG +# to its sinksBbox center, producing identical positions. Without the +# fix in findLongEdges(), mapLocationToSink_ (single-valued map) silently +# overwrites the first ICG entry, losing it from the clock tree. +# The fix nudges co-located clones by 1 DBU. +source "helpers.tcl" + +read_liberty Nangate45/Nangate45_typ.lib +read_lef Nangate45/Nangate45.lef +read_def colocated_sinks.def + +create_clock -period 5 clk + +source Nangate45/Nangate45.rc +set_wire_rc -signal -layer metal1 +set_wire_rc -clock -layer metal2 + +clock_tree_synthesis -root_buf CLKBUF_X3 \ + -buf_list CLKBUF_X3 \ + -wire_unit 20 \ + -sink_clustering_enable \ + -distance_between_buffers 100 \ + -num_static_layers 1 + +# Verify both ICGs are connected to CTS buffer drivers after CTS. +# Without the fix, one ICG is lost from the tree due to map collision. +set block [ord::get_db_block] +set missing 0 + +foreach icg_name {icg_a icg_b} { + set inst [$block findInst $icg_name] + set ck_iterm [$inst findITerm "CK"] + set net [$ck_iterm getNet] + + if { $net eq "NULL" } { + puts "FAIL: $icg_name CK is disconnected" + incr missing + continue + } + + set has_buf_driver 0 + foreach it [$net getITerms] { + if { [$it isOutputSignal] } { + set driver_name [[$it getInst] getName] + if { [string match "clkbuf_*" $driver_name] } { + set has_buf_driver 1 + break + } + } + } + + if { !$has_buf_driver } { + puts "FAIL: $icg_name CK on net [$net getName] has no CTS buffer driver" + incr missing + } +} + +if { $missing == 0 } { + puts "PASS: Both ICGs properly connected to CTS tree" +} else { + puts "FAIL: $missing ICGs lost from CTS tree due to co-location" +}