@@ -474,7 +474,7 @@ void TritonCTS::writeDataToDb()
474474 for (auto & builder : builders_) {
475475 writeClockNetsToDb (builder.get (), clkLeafNets);
476476 if (options_->applyNDR ()) {
477- writeClockNDRsToDb (clkLeafNets);
477+ writeClockNDRsToDb (builder. get (), clkLeafNets);
478478 }
479479 if (options_->dummyLoadEnabled ()) {
480480 writeDummyLoadsToDb (builder->getClock (), clkDummies);
@@ -1419,6 +1419,7 @@ void TritonCTS::writeClockNetsToDb(TreeBuilder* builder,
14191419 }
14201420 odb::dbNet* clkSubNet
14211421 = odb::dbNet::create (block_, subNet.getName ().c_str ());
1422+ subNet.setNetObj (clkSubNet);
14221423
14231424 ++numClkNets_;
14241425 clkSubNet->setSigType (odb::dbSigType::CLOCK);
@@ -1539,44 +1540,43 @@ void TritonCTS::writeClockNetsToDb(TreeBuilder* builder,
15391540}
15401541
15411542// Function to extract level number from clock net name
1542- int TritonCTS::extractClockTreeLevelFromNetName (const std::string& netName)
1543- {
1544- // Pattern to find number between underscores (e.g., "clknet_2_clk_i")
1545- std::regex pattern (" _([0-9]+)_" );
1546- std::smatch match;
1547-
1548- if (std::regex_search (netName, match, pattern)) {
1549- return std::stoi (match[1 ]);
1550- }
1551-
1552- // If no number found between underscores, it's level 0
1553- return 0 ;
1554- }
1555-
1556- // Utility function to get all unique clock tree levels in the design
1557- std::vector<int > TritonCTS::getAllClockTreeLevels (
1558- odb::dbBlock* block_,
1559- const std::set<odb::dbNet*>& clkLeafNets)
1560- {
1561- std::set<int > uniqueLevels;
1562-
1563- for (odb::dbNet* net : block_->getNets ()) {
1564- if (net->getSigType () == odb::dbSigType::CLOCK
1565- && (clkLeafNets.find (net) == clkLeafNets.end ())) {
1566- int level = extractClockTreeLevelFromNetName (net->getConstName ());
1567- uniqueLevels.insert (level);
1568- }
1569- }
1570-
1571- return std::vector<int >(uniqueLevels.begin (), uniqueLevels.end ());
1572- ;
1573- }
1543+ // int TritonCTS::extractClockTreeLevelFromNetName(const std::string& netName)
1544+ // {
1545+ // // Pattern to find number between underscores (e.g., "clknet_2_clk_i")
1546+ // std::regex pattern("_([0-9]+)_");
1547+ // std::smatch match;
1548+
1549+ // if (std::regex_search(netName, match, pattern)) {
1550+ // return std::stoi(match[1]);
1551+ // }
1552+
1553+ // // If no number found between underscores, it's level 0
1554+ // return 0;
1555+ // }
1556+
1557+ // // Utility function to get all unique clock tree levels in the design
1558+ // std::vector<int> TritonCTS::getAllClockTreeLevels(
1559+ // odb::dbBlock* block_,
1560+ // const std::set<odb::dbNet*>& clkLeafNets)
1561+ // {
1562+ // std::set<int> uniqueLevels;
1563+
1564+ // for (odb::dbNet* net : block_->getNets()) {
1565+ // if (net->getSigType() == odb::dbSigType::CLOCK
1566+ // && (clkLeafNets.find(net) == clkLeafNets.end())) {
1567+ // int level = extractClockTreeLevelFromNetName(net->getConstName());
1568+ // uniqueLevels.insert(level);
1569+ // }
1570+ // }
1571+
1572+ // return std::vector<int>(uniqueLevels.begin(), uniqueLevels.end());
1573+ // ;
1574+ // }
15741575
15751576// Function to apply NDR to specific clock tree levels and return the number of
15761577// NDR applied nets
1577- int TritonCTS::applyNDRToClockLevels (odb::dbBlock* block_ ,
1578+ int TritonCTS::applyNDRToClockLevels (Clock& clockNet ,
15781579 odb::dbTechNonDefaultRule* clockNDR,
1579- const std::set<odb::dbNet*>& clkLeafNets,
15801580 const std::vector<int >& targetLevels)
15811581{
15821582 int ndrAppliedNets = 0 ;
@@ -1587,75 +1587,114 @@ int TritonCTS::applyNDRToClockLevels(odb::dbBlock* block_,
15871587 debugPrint (logger_, CTS, " clustering" , 1 , " {} " , level);
15881588 }
15891589
1590- // Single pass: check clock nets and apply NDR if level matches
1591- for (odb::dbNet* net : block_->getNets ()) {
1592- if (net->getSigType () == odb::dbSigType::CLOCK
1593- && (clkLeafNets.find (net) == clkLeafNets.end ())) {
1594- const std::string netName = net->getConstName ();
1595- const int level = extractClockTreeLevelFromNetName (netName);
1596-
1597- // Apply NDR if this level is in the target list
1598- if (std::find (targetLevels.begin (), targetLevels.end (), level)
1599- != targetLevels.end ()) {
1590+ // Check if the main clock net (level 0) is in the level list
1591+ if (std::find (targetLevels.begin (), targetLevels.end (), 0 )
1592+ != targetLevels.end ())
1593+ {
1594+ odb::dbNet* clk_net = clockNet.getNetObj ();
1595+ clk_net->setNonDefaultRule (clockNDR);
1596+ ndrAppliedNets++;
1597+ // clang-format off
1598+ debugPrint (logger_, CTS, " clustering" , 1 ,
1599+ " Applied NDR to: {} (level {})" , clockNet.getName (), 0 );
1600+ // clang-format on
1601+ }
1602+
1603+ // //////////////////////////////////
1604+ // Check clock sub nets list and apply NDR if level matches
1605+ clockNet.forEachSubNet ([&](ClockSubNet& subNet) {
1606+ int level = subNet.getTreeLevel ();
1607+ if (!subNet.isLeafLevel ())
1608+ logger_->report (" Net {} - Level: {}" ,subNet.getName (), level);
1609+ if (std::find (targetLevels.begin (), targetLevels.end (), level)
1610+ != targetLevels.end ())
1611+ {
1612+ odb::dbNet* net = subNet.getNetObj ();
1613+ if (!subNet.isLeafLevel ())
1614+ {
16001615 net->setNonDefaultRule (clockNDR);
16011616 ndrAppliedNets++;
1617+ std::string net_name = net->getName ();
16021618 // clang-format off
16031619 debugPrint (logger_, CTS, " clustering" , 1 ,
1604- " Applied NDR to: {} (level {})" , netName , level);
1620+ " Applied NDR to: {} (level {})" , net_name , level);
16051621 // clang-format on
16061622 }
16071623 }
1608- }
1609-
1610- return ndrAppliedNets;
1611- }
1612-
1613- // Alternative function to apply NDR to a range of clock tree levels
1614- int TritonCTS::applyNDRToClockLevelRange (
1615- odb::dbBlock* block_,
1616- odb::dbTechNonDefaultRule* clockNDR,
1617- const std::set<odb::dbNet*>& clkLeafNets,
1618- const int minLevel,
1619- const int maxLevel)
1620- {
1621- std::vector<int > targetLevels;
1622- for (int i = minLevel; i <= maxLevel; i++) {
1623- targetLevels.push_back (i);
1624- }
1625-
1626- return applyNDRToClockLevels (block_, clockNDR, clkLeafNets, targetLevels);
1627- }
1628-
1629- // Function to apply NDR to the first half of clock tree levels
1630- int TritonCTS::applyNDRToFirstHalfLevels (
1631- odb::dbBlock* block_,
1632- odb::dbTechNonDefaultRule* clockNDR,
1633- const std::set<odb::dbNet*>& clkLeafNets)
1634- {
1635- // Get all unique levels in the design
1636- const std::vector<int > allLevels = getAllClockTreeLevels (block_, clkLeafNets);
1637-
1638- // Calculate first half (rounding up if odd number of levels)
1639- const size_t halfCount = (allLevels.size () + 1 ) / 2 ;
1624+ });
16401625
1641- // Create vector with first half of levels
1642- std::vector<int > firstHalfLevels (allLevels.begin (),
1643- allLevels.begin () + halfCount);
1626+ // ////////////////////////////////////
16441627
1645- // clang-format off
1646- debugPrint (logger_, CTS, " clustering" , 1 , " Total clock tree levels found: {}"
1647- " Applying NDR to first {} levels" , allLevels.size (), halfCount);
1648- // clang-format on
1628+ // Single pass: check clock nets and apply NDR if level matches
1629+ // for (odb::dbNet* net : block_->getNets()) {
1630+ // if (net->getSigType() == odb::dbSigType::CLOCK
1631+ // && (clkLeafNets.find(net) == clkLeafNets.end())) {
1632+ // const std::string netName = net->getConstName();
1633+ // const int level = extractClockTreeLevelFromNetName(netName);
1634+
1635+ // // Apply NDR if this level is in the target list
1636+ // if (std::find(targetLevels.begin(), targetLevels.end(), level)
1637+ // != targetLevels.end()) {
1638+ // net->setNonDefaultRule(clockNDR);
1639+ // ndrAppliedNets++;
1640+ // // clang-format off
1641+ // debugPrint(logger_, CTS, "clustering", 1,
1642+ // "Applied NDR to: {} (level {})", netName, level);
1643+ // // clang-format on
1644+ // }
1645+ // }
1646+ // }
16491647
1650- // Apply NDR to the first half
1651- return applyNDRToClockLevels (block_, clockNDR, clkLeafNets, firstHalfLevels);
1648+ return ndrAppliedNets;
16521649}
16531650
1654- void TritonCTS::writeClockNDRsToDb (const std::set<odb::dbNet*>& clkLeafNets)
1651+ // Alternative function to apply NDR to a range of clock tree levels
1652+ // int TritonCTS::applyNDRToClockLevelRange(
1653+ // odb::dbBlock* block_,
1654+ // odb::dbTechNonDefaultRule* clockNDR,
1655+ // const std::set<odb::dbNet*>& clkLeafNets,
1656+ // const int minLevel,
1657+ // const int maxLevel)
1658+ // {
1659+ // std::vector<int> targetLevels;
1660+ // for (int i = minLevel; i <= maxLevel; i++) {
1661+ // targetLevels.push_back(i);
1662+ // }
1663+
1664+ // return applyNDRToClockLevels(block_, clockNDR, clkLeafNets, targetLevels);
1665+ // }
1666+
1667+ // // Function to apply NDR to the first half of clock tree levels
1668+ // int TritonCTS::applyNDRToFirstHalfLevels(
1669+ // odb::dbBlock* block_,
1670+ // odb::dbTechNonDefaultRule* clockNDR,
1671+ // const std::set<odb::dbNet*>& clkLeafNets)
1672+ // {
1673+ // // Get all unique levels in the design
1674+ // const std::vector<int> allLevels = getAllClockTreeLevels(block_, clkLeafNets);
1675+
1676+ // // Calculate first half (rounding up if odd number of levels)
1677+ // const size_t halfCount = (allLevels.size() + 1) / 2;
1678+
1679+ // // Create vector with first half of levels
1680+ // std::vector<int> firstHalfLevels(allLevels.begin(),
1681+ // allLevels.begin() + halfCount);
1682+
1683+ // // clang-format off
1684+ // debugPrint(logger_, CTS, "clustering", 1, "Total clock tree levels found: {}"
1685+ // "Applying NDR to first {} levels", allLevels.size(), halfCount);
1686+ // // clang-format on
1687+
1688+ // // Apply NDR to the first half
1689+ // return applyNDRToClockLevels(block_, clockNDR, clkLeafNets, firstHalfLevels);
1690+ // }
1691+
1692+ void TritonCTS::writeClockNDRsToDb (TreeBuilder* builder, const std::set<odb::dbNet*>& clkLeafNets)
16551693{
16561694 char ruleName[64 ];
16571695 int ruleIndex = 0 ;
16581696 odb::dbTechNonDefaultRule* clockNDR;
1697+ Clock& clockNet = builder->getClock ();
16591698
16601699 // create a new non-default rule in *block* not tech
16611700 while (ruleIndex >= 0 ) {
@@ -1693,9 +1732,8 @@ void TritonCTS::writeClockNDRsToDb(const std::set<odb::dbNet*>& clkLeafNets)
16931732
16941733 // TODO: Add user specified args to choose the NDR strategy
16951734 // Option 1: Apply NDR to specific levels
1696- // std::vector<int> specificLevels = {0}; // Apply to level 0
1697- // clkNets = applyNDRToClockLevels(block_, clockNDR, clkLeafNets,
1698- // specificLevels);
1735+ std::vector<int > specificLevels = {0 ,1 ,2 }; // Apply to level 0
1736+ clkNets = applyNDRToClockLevels (clockNet, clockNDR, specificLevels);
16991737
17001738 // Option 2: Apply NDR to a range of levels (e.g., Levels 0-3)
17011739 // clkNets = applyNDRToClockLevelRange(block_, clockNDR, clkLeafNets, 0, 3);
@@ -1705,13 +1743,13 @@ void TritonCTS::writeClockNDRsToDb(const std::set<odb::dbNet*>& clkLeafNets)
17051743 // clkNets = applyNDRToFirstHalfLevels(block_, clockNDR, clkLeafNets);
17061744
17071745 // Option 4: Apply NDR to all non-leaf clock nets (default)
1708- for (odb::dbNet* net : block_->getNets ()) {
1709- if (net->getSigType () == odb::dbSigType::CLOCK
1710- && (clkLeafNets.find (net) == clkLeafNets.end ())) {
1711- net->setNonDefaultRule (clockNDR);
1712- clkNets++;
1713- }
1714- }
1746+ // for (odb::dbNet* net : block_->getNets()) {
1747+ // if (net->getSigType() == odb::dbSigType::CLOCK
1748+ // && (clkLeafNets.find(net) == clkLeafNets.end())) {
1749+ // net->setNonDefaultRule(clockNDR);
1750+ // clkNets++;
1751+ // }
1752+ // }
17151753
17161754 logger_->info (CTS,
17171755 202 ,
0 commit comments