4040
4141// Partitioner note : currently we are still using MLPart to partition large
4242// flat clusters Later this will be replaced by our TritonPart
43- // #include "par/MLPart.h"
44-
4543#include " SACoreHardMacro.h"
4644#include " SACoreSoftMacro.h"
4745#include " bus_synthesis.h"
4846#include " db_sta/dbNetwork.hh"
4947#include " graphics.h"
5048#include " object.h"
5149#include " odb/db.h"
50+ #include " par/MLPart.h"
5251#include " sta/Liberty.hh"
5352#include " utl/Logger.h"
5453
@@ -113,6 +112,11 @@ void HierRTLMP::setNotchWeight(float weight)
113112 notch_weight_ = weight;
114113}
115114
115+ void HierRTLMP::setMacroBlockageWeight (float weight)
116+ {
117+ macro_blockage_weight_ = weight;
118+ }
119+
116120void HierRTLMP::setGlobalFence (float fence_lx,
117121 float fence_ly,
118122 float fence_ux,
@@ -135,10 +139,10 @@ void HierRTLMP::setNumBundledIOsPerBoundary(int num_bundled_ios)
135139 num_bundled_IOs_ = num_bundled_ios;
136140}
137141
138- void HierRTLMP::setTopLevelClusterSize (int max_num_macro,
139- int min_num_macro,
140- int max_num_inst,
141- int min_num_inst)
142+ void HierRTLMP::setClusterSize (int max_num_macro,
143+ int min_num_macro,
144+ int max_num_inst,
145+ int min_num_inst)
142146{
143147 max_num_macro_base_ = max_num_macro;
144148 min_num_macro_base_ = min_num_macro;
@@ -324,10 +328,14 @@ void HierRTLMP::hierRTLMacroPlacer()
324328 // create data flow information
325329 createDataFlow ();
326330
327- logger_->report (" Finish Calculate Data Flow detailed CR done " );
331+ logger_->report (" Finish Calculate Data Flow" );
328332
329333 // Create physical hierarchy tree in a post-order DFS manner
334+ logger_->report (" Call multi level clustering max level: {}" , max_num_level_);
335+
330336 multiLevelCluster (root_cluster_); // Recursive call for creating the tree
337+ logger_->report (" Print Physical Hierarchy Tree ** max_hier_level: {}" ,
338+ max_hier_level_);
331339 printPhysicalHierarchyTree (root_cluster_, 0 );
332340
333341 //
@@ -351,6 +359,8 @@ void HierRTLMP::hierRTLMacroPlacer()
351359 // and they can tune the options to get better
352360 // clustering results
353361 //
362+ logger_->report (
363+ " Print Physical Hierarchy Tree after breaking mixed clusters **" );
354364 printPhysicalHierarchyTree (root_cluster_, 0 );
355365
356366 // Map the macros in each cluster to their HardMacro objects
@@ -439,6 +449,8 @@ Metric* HierRTLMP::computeMetric(odb::dbModule* module)
439449
440450 for (odb::dbInst* inst : module ->getInsts ()) {
441451 const sta::LibertyCell* liberty_cell = network_->libertyCell (inst);
452+ if (liberty_cell == nullptr )
453+ continue ;
442454 odb::dbMaster* master = inst->getMaster ();
443455 // check if the instance is a pad or a cover macro
444456 if (master->isPad () || master->isCover ()) {
@@ -713,7 +725,7 @@ void HierRTLMP::createBundledIOs()
713725 // delete the IO clusters that do not have any pins assigned to them
714726 for (auto & [cluster_id, flag] : cluster_io_map) {
715727 if (!flag) {
716- logger_->report (" remove cluster : {}, id: {}" ,
728+ logger_->report (" remove bundled pin cluster : {}, id: {}" ,
717729 cluster_map_[cluster_id]->getName (),
718730 cluster_id);
719731 cluster_map_[cluster_id]->getParent ()->removeChild (
@@ -724,25 +736,37 @@ void HierRTLMP::createBundledIOs()
724736 }
725737}
726738
739+ //
727740// Create physical hierarchy tree in a post-order DFS manner
728741// Recursive call for creating the physical hierarchy tree
742+ //
729743void HierRTLMP::multiLevelCluster (Cluster* parent)
730744{
745+ bool force_split = false ;
746+ if (level_ == 0 ) {
747+ // check if root cluster is below the max size of a leaf cluster
748+ // Force create child clusters in this case
749+ const int leaf_cluster_size
750+ = max_num_inst_base_ / std::pow (coarsening_ratio_, max_num_level_ - 1 );
751+ if (parent->getNumStdCell () < leaf_cluster_size)
752+ force_split = true ;
753+ logger_->report (
754+ " Set force split: leaf cluster size: {} root cluster size: {}" ,
755+ leaf_cluster_size,
756+ parent->getNumStdCell ());
757+ }
731758 if (level_ >= max_num_level_) { // limited by the user-specified parameter
732759 return ;
733760 }
734761 level_++;
735- // for debug
736- if (1 ) {
737- logger_->report (
738- " [Debug][HierRTLMP::MultiLevelCluster] {} {}: num_macro {} "
739- " num_stdcell {}" ,
740- parent->getName (),
741- level_,
742- parent->getNumMacro (),
743- parent->getNumStdCell ());
744- }
745- // end debug
762+
763+ logger_->report (
764+ " [Debug][HierRTLMP::MultiLevelCluster] {} {}: num_macro {} num_stdcell "
765+ " {}" ,
766+ parent->getName (),
767+ level_,
768+ parent->getNumMacro (),
769+ parent->getNumStdCell ());
746770
747771 // a large coarsening_ratio_ helps the clustering process converge fast
748772 max_num_macro_
@@ -758,8 +782,9 @@ void HierRTLMP::multiLevelCluster(Cluster* parent)
758782 max_num_macro_ = max_num_macro_ * (1 + tolerance_);
759783 min_num_macro_ = min_num_macro_ * (1 - tolerance_);
760784
761- if (parent->getNumMacro () > max_num_macro_
762- || parent->getNumStdCell () > max_num_inst_) {
785+ if (force_split || (parent->getNumStdCell () > max_num_inst_)) {
786+ if ((max_num_level_ - level_) > max_hier_level_)
787+ max_hier_level_ = max_num_level_ - level_;
763788 breakCluster (parent); // Break the parent cluster into children clusters
764789 updateSubTree (parent); // update the subtree to the physical hierarchy tree
765790 for (auto & child : parent->getChildren ()) {
@@ -836,18 +861,22 @@ void HierRTLMP::setInstProperty(odb::dbModule* module,
836861 }
837862}
838863
864+ //
839865// Break the parent cluster into children clusters
840866// We expand the parent cluster into a subtree based on logical
841867// hierarchy in a DFS manner. During the expansion process,
842868// we merge small clusters in the same logical hierarchy
869+ //
843870void HierRTLMP::breakCluster (Cluster* parent)
844871{
845872 logger_->report (" [Debug][HierRTLMP::BreakCluster] cluster_name : {}" ,
846873 parent->getName ());
874+ //
847875 // Consider three different cases:
848876 // (a) parent is an empty cluster
849877 // (b) parent is a cluster corresponding to a logical module
850878 // (c) parent is a cluster generated by merging small clusters
879+ //
851880 if ((parent->getLeafStdCells ().size () == 0 )
852881 && (parent->getLeafMacros ().size () == 0 )
853882 && (parent->getDbModules ().size () == 0 )) {
@@ -868,10 +897,11 @@ void HierRTLMP::breakCluster(Cluster* parent)
868897 if (module ->getChildren ().size () == 0 ) {
869898 for (odb::dbInst* inst : module ->getInsts ()) {
870899 const sta::LibertyCell* liberty_cell = network_->libertyCell (inst);
900+ if (liberty_cell == nullptr )
901+ continue ;
871902 odb::dbMaster* master = inst->getMaster ();
872903 // check if the instance is a Pad, Cover or empty block (such as marker)
873- if (master->isPad () || master->isCover ()
874- || (master->isBlock () && liberty_cell == nullptr )) {
904+ if (master->isPad () || master->isCover ()) {
875905 continue ;
876906 } else if (master->isBlock ()) {
877907 parent->addLeafMacro (inst);
@@ -887,6 +917,7 @@ void HierRTLMP::breakCluster(Cluster* parent)
887917 // we first model each child logical module as a cluster
888918 for (odb::dbModInst* child : module ->getChildren ()) {
889919 std::string cluster_name = child->getMaster ()->getHierarchicalName ();
920+ // Create a new cluster for the child module
890921 Cluster* cluster = new Cluster (cluster_id_, cluster_name, logger_);
891922 cluster->addDbModule (child->getMaster ());
892923 setInstProperty (cluster);
@@ -897,23 +928,28 @@ void HierRTLMP::breakCluster(Cluster* parent)
897928 parent->addChild (cluster);
898929 }
899930 // Check the glue logics
931+ // Glue logic instances are loose instances in a given module that also
932+ // contain module instances
933+ //
900934 std::string cluster_name
901935 = std::string (" (" ) + parent->getName () + " )_glue_logic" ;
902936 Cluster* cluster = new Cluster (cluster_id_, cluster_name, logger_);
903937 for (odb::dbInst* inst : module ->getInsts ()) {
904938 const sta::LibertyCell* liberty_cell = network_->libertyCell (inst);
939+ if (liberty_cell == nullptr )
940+ continue ;
905941 odb::dbMaster* master = inst->getMaster ();
906942 // check if the instance is a Pad, Cover or empty block (such as marker)
907- if (master->isPad () || master->isCover ()
908- || (master->isBlock () && liberty_cell == nullptr )) {
943+ if (master->isPad () || master->isCover ()) {
909944 continue ;
910945 } else if (master->isBlock ()) {
911946 cluster->addLeafMacro (inst);
912947 } else {
913948 cluster->addLeafStdCell (inst);
914949 }
915950 }
916- // if the module has no meaningful glue instances
951+ //
952+ // if the module has no meaningful glue instances, delete it
917953 if (cluster->getLeafStdCells ().size () == 0
918954 && cluster->getLeafMacros ().size () == 0 ) {
919955 delete cluster;
@@ -986,6 +1022,7 @@ void HierRTLMP::breakCluster(Cluster* parent)
9861022 setInstProperty (parent);
9871023}
9881024
1025+ //
9891026// Merge small clusters with the same parent cluster
9901027// Recursively merge clusters
9911028// Here is an example process based on connection signature
@@ -1005,6 +1042,7 @@ void HierRTLMP::breakCluster(Cluster* parent)
10051042// have the same connection signature, A and C have the same connection
10061043// signature, then B and C also have the same connection signature.
10071044// Note in both types, we only merge clusters with the same parent cluster
1045+ //
10081046void HierRTLMP::mergeClusters (std::vector<Cluster*>& candidate_clusters)
10091047{
10101048 // for debug
@@ -1257,11 +1295,12 @@ void HierRTLMP::createDataFlow()
12571295 for (odb::dbITerm* iterm : net->getITerms ()) {
12581296 odb::dbInst* inst = iterm->getInst ();
12591297 const sta::LibertyCell* liberty_cell = network_->libertyCell (inst);
1298+ if (liberty_cell == nullptr )
1299+ continue ;
12601300 odb::dbMaster* master = inst->getMaster ();
12611301 // check if the instance is a Pad, Cover or empty block (such as marker)
12621302 // We ignore nets connecting Pads, Covers, or markers
1263- if (master->isPad () || master->isCover ()
1264- || (master->isBlock () && liberty_cell == nullptr )) {
1303+ if (master->isPad () || master->isCover ()) {
12651304 pad_flag = true ;
12661305 break ;
12671306 }
@@ -2078,10 +2117,11 @@ void HierRTLMP::getHardMacros(odb::dbModule* module,
20782117{
20792118 for (odb::dbInst* inst : module ->getInsts ()) {
20802119 const sta::LibertyCell* liberty_cell = network_->libertyCell (inst);
2120+ if (liberty_cell == nullptr )
2121+ continue ;
20812122 odb::dbMaster* master = inst->getMaster ();
20822123 // check if the instance is a pad or empty block (such as marker)
2083- if (master->isPad () || master->isCover ()
2084- || (master->isBlock () && liberty_cell == nullptr )) {
2124+ if (master->isPad () || master->isCover ()) {
20852125 continue ;
20862126 }
20872127 if (master->isBlock ()) {
@@ -2794,7 +2834,7 @@ void HierRTLMP::multiLevelMacroPlacement(Cluster* parent)
27942834 // update the connnection
27952835 calculateConnection ();
27962836 logger_->report (" finish calculate connection" );
2797- updateDataFlow ();
2837+ // updateDataFlow();
27982838 logger_->report (" finish updating dataflow" );
27992839 if (parent->getParent () != nullptr ) {
28002840 // the parent cluster is not the root cluster
@@ -3179,12 +3219,14 @@ void HierRTLMP::multiLevelMacroPlacement(Cluster* parent)
31793219 }
31803220
31813221 // check if the parent cluster still need bus planning
3182- for (auto & child : parent->getChildren ()) {
3183- if (child->getClusterType () == MixedCluster) {
3184- logger_->report (" \n\n Call Bus Synthesis\n\n " );
3185- // Call Path Synthesis to route buses
3186- callBusPlanning (shaped_macros, nets);
3187- break ;
3222+ if (max_hier_level_ > 0 ) {
3223+ for (auto & child : parent->getChildren ()) {
3224+ if (child->getClusterType () == MixedCluster) {
3225+ logger_->report (" \n\n Call Bus Synthesis\n\n " );
3226+ // Call Path Synthesis to route buses
3227+ // callBusPlanning(shaped_macros, nets);
3228+ break ;
3229+ }
31883230 }
31893231 }
31903232
0 commit comments