@@ -45,7 +45,6 @@ void ClusteringEngine::run()
4545 createRoot ();
4646 setBaseThresholds ();
4747
48- mapIOPinsAndPads ();
4948 createDataFlow ();
5049 createIOClusters ();
5150
@@ -78,7 +77,8 @@ void ClusteringEngine::setTree(PhysicalHierarchy* tree)
7877}
7978
8079// Check if macro placement is both needed and feasible.
81- // Also report some design data relevant for the user.
80+ // Also report some design data relevant for the user and
81+ // initialize the tree with data from the design.
8282void ClusteringEngine::init ()
8383{
8484 const std::vector<odb::dbInst*> unfixed_macros = getUnfixedMacros ();
@@ -105,6 +105,8 @@ void ClusteringEngine::init()
105105 tree_->floorplan_shape .getArea ());
106106 }
107107
108+ tree_->io_pads = getIOPads ();
109+
108110 reportDesignData ();
109111}
110112
@@ -222,6 +224,27 @@ Metrics* ClusteringEngine::computeModuleMetrics(odb::dbModule* module)
222224 return tree_->maps .module_to_metrics [module ].get ();
223225}
224226
227+ std::vector<odb::dbInst*> ClusteringEngine::getIOPads () const
228+ {
229+ std::vector<odb::dbInst*> io_pads;
230+
231+ for (odb::dbInst* inst : block_->getInsts ()) {
232+ const odb::dbMasterType& master_type = inst->getMaster ()->getType ();
233+
234+ // Skip PADs without core signal connections.
235+ if (master_type == odb::dbMasterType::PAD_POWER
236+ || master_type == odb::dbMasterType::PAD_SPACER) {
237+ continue ;
238+ }
239+
240+ if (inst->isPad ()) {
241+ io_pads.push_back (inst);
242+ }
243+ }
244+
245+ return io_pads;
246+ }
247+
225248void ClusteringEngine::reportDesignData ()
226249{
227250 const odb::Rect& die = block_->getDieArea ();
@@ -357,7 +380,7 @@ void ClusteringEngine::setBaseThresholds()
357380// shape is the die area.
358381void ClusteringEngine::createIOClusters ()
359382{
360- if (!tree_->maps . pad_to_bterm .empty ()) {
383+ if (!tree_->io_pads .empty ()) {
361384 createIOPadClusters ();
362385 return ;
363386 }
@@ -432,64 +455,17 @@ void ClusteringEngine::createClusterOfUnplacedIOs(odb::dbBTerm* bterm)
432455 tree_->root ->addChild (std::move (cluster));
433456}
434457
435- void ClusteringEngine::mapIOPinsAndPads ()
436- {
437- bool design_has_io_pads = false ;
438- for (auto inst : block_->getInsts ()) {
439- if (inst->getMaster ()->isPad ()) {
440- design_has_io_pads = true ;
441- break ;
442- }
443- }
444-
445- if (!design_has_io_pads) {
446- return ;
447- }
448-
449- for (odb::dbNet* net : block_->getNets ()) {
450- if (net->getBTerms ().size () == 0 ) {
451- continue ;
452- }
453-
454- for (odb::dbBTerm* bterm : net->getBTerms ()) {
455- for (odb::dbITerm* iterm : net->getITerms ()) {
456- odb::dbInst* inst = iterm->getInst ();
457- tree_->maps .pad_to_bterm [inst] = bterm;
458- tree_->maps .bterm_to_pad [bterm] = inst;
459- }
460- }
461- }
462- }
463-
464458void ClusteringEngine::createIOPadClusters ()
465459{
466- for (const auto & io_pad_path : data_connections_.io_and_regs ) {
467- // Registers or Macros
468- const PathInsts& connected_insts = io_pad_path.second ;
469- bool path_is_empty = true ;
470- for (const std::set<odb::dbInst*>& insts_of_curr_hop_dist :
471- connected_insts) {
472- if (!insts_of_curr_hop_dist.empty ()) {
473- path_is_empty = false ;
474- break ;
475- }
476- }
477-
478- if (path_is_empty) {
479- continue ;
480- }
481-
482- odb::dbBTerm* bterm = io_pad_path.first ;
483- odb::dbInst* pad = tree_->maps .bterm_to_pad .at (bterm);
484-
485- createIOPadCluster (pad, bterm);
460+ for (odb::dbInst* pad : tree_->io_pads ) {
461+ createIOPadCluster (pad);
486462 }
487463}
488464
489- void ClusteringEngine::createIOPadCluster (odb::dbInst* pad, odb::dbBTerm* bterm )
465+ void ClusteringEngine::createIOPadCluster (odb::dbInst* pad)
490466{
491467 auto cluster = std::make_unique<Cluster>(id_, pad->getName (), logger_);
492- tree_->maps .bterm_to_cluster_id [bterm ] = id_;
468+ tree_->maps .inst_to_cluster_id [pad ] = id_;
493469 tree_->maps .id_to_cluster [id_++] = cluster.get ();
494470
495471 const odb::Rect& pad_bbox = pad->getBBox ()->getBox ();
@@ -567,7 +543,13 @@ bool ClusteringEngine::stdCellsHaveLiberty()
567543VerticesMaps ClusteringEngine::computeVertices ()
568544{
569545 VerticesMaps vertices_maps;
570- computeIOVertices (vertices_maps);
546+
547+ if (tree_->io_pads .empty ()) {
548+ computeIOVertices (vertices_maps);
549+ } else {
550+ computePadVertices (vertices_maps);
551+ }
552+
571553 computeStdCellVertices (vertices_maps);
572554 computeMacroPinVertices (vertices_maps);
573555
@@ -591,6 +573,16 @@ void ClusteringEngine::computeIOVertices(VerticesMaps& vertices_maps)
591573 }
592574}
593575
576+ void ClusteringEngine::computePadVertices (VerticesMaps& vertices_maps)
577+ {
578+ for (odb::dbInst* pad : tree_->io_pads ) {
579+ const int id = static_cast <int >(vertices_maps.stoppers .size ());
580+ odb::dbIntProperty::create (pad, " vertex_id" , id);
581+ vertices_maps.id_to_std_cell [id] = pad;
582+ vertices_maps.stoppers .push_back (true );
583+ }
584+ }
585+
594586void ClusteringEngine::computeStdCellVertices (VerticesMaps& vertices_maps)
595587{
596588 for (odb::dbInst* inst : block_->getInsts ()) {
@@ -656,11 +648,7 @@ DataFlowHypergraph ClusteringEngine::computeHypergraph(
656648 if (inst->isBlock ()) {
657649 vertex_id = odb::dbIntProperty::find (iterm, " vertex_id" )->getValue ();
658650 } else if (inst->isPad ()) {
659- // To properly consider the path of a signal that travels from a PAD
660- // to the core we use the path's bterm as the vertex.
661- odb::dbBTerm* pad_bterm = tree_->maps .pad_to_bterm .at (inst);
662- vertex_id
663- = odb::dbIntProperty::find (pad_bterm, " vertex_id" )->getValue ();
651+ vertex_id = odb::dbIntProperty::find (inst, " vertex_id" )->getValue ();
664652 } else {
665653 odb::dbIntProperty* int_prop
666654 = odb::dbIntProperty::find (inst, " vertex_id" );
@@ -974,18 +962,35 @@ void ClusteringEngine::incorporateNewCluster(std::unique_ptr<Cluster> cluster,
974962 parent->addChild (std::move (cluster));
975963}
976964
965+ // We don't change the association of ignored instances throughout
966+ // the multilevel autoclustering process. I.e., ignored instances
967+ // should remain at the root.
968+ //
969+ // Attention: A pad is a special ignored instance in the sense that
970+ // it will be associated with a pad cluster. By not changing the
971+ // association of ignored instances during autoclustering, we prevent
972+ // the autoclustering process from messing up the association of
973+ // PAD inst -> PAD Cluster as these last ones are created beforehand.
977974void ClusteringEngine::updateInstancesAssociation (Cluster* cluster)
978975{
979976 const int cluster_id = cluster->getId ();
980977 const ClusterType cluster_type = cluster->getClusterType ();
981978 if (cluster_type == HardMacroCluster || cluster_type == MixedCluster) {
982979 for (odb::dbInst* inst : cluster->getLeafMacros ()) {
980+ if (isIgnoredInst (inst)) {
981+ continue ;
982+ }
983+
983984 tree_->maps .inst_to_cluster_id [inst] = cluster_id;
984985 }
985986 }
986987
987988 if (cluster_type == StdCellCluster || cluster_type == MixedCluster) {
988989 for (odb::dbInst* inst : cluster->getLeafStdCells ()) {
990+ if (isIgnoredInst (inst)) {
991+ continue ;
992+ }
993+
989994 tree_->maps .inst_to_cluster_id [inst] = cluster_id;
990995 }
991996 }
@@ -1008,19 +1013,18 @@ void ClusteringEngine::updateInstancesAssociation(odb::dbModule* module,
10081013 int cluster_id,
10091014 bool include_macro)
10101015{
1011- if (include_macro ) {
1012- for (odb::dbInst* inst : module -> getInsts ( )) {
1013- tree_-> maps . inst_to_cluster_id [inst] = cluster_id ;
1016+ for (odb::dbInst* inst : module -> getInsts () ) {
1017+ if ( isIgnoredInst (inst )) {
1018+ continue ;
10141019 }
1015- } else { // only consider standard cells
1016- for (odb::dbInst* inst : module ->getInsts ()) {
1017- if (isIgnoredInst (inst) || inst->isBlock ()) {
1018- continue ;
1019- }
10201020
1021- tree_->maps .inst_to_cluster_id [inst] = cluster_id;
1021+ if (!include_macro && inst->isBlock ()) {
1022+ continue ;
10221023 }
1024+
1025+ tree_->maps .inst_to_cluster_id [inst] = cluster_id;
10231026 }
1027+
10241028 for (odb::dbModInst* child_module_inst : module ->getChildren ()) {
10251029 updateInstancesAssociation (
10261030 child_module_inst->getMaster (), cluster_id, include_macro);
@@ -1727,14 +1731,16 @@ void ClusteringEngine::buildNetListConnections()
17271731 }
17281732
17291733 bool net_has_io_pin = false ;
1730- for (odb::dbBTerm* bterm : net->getBTerms ()) {
1731- const int cluster_id = tree_->maps .bterm_to_cluster_id .at (bterm);
1732- net_has_io_pin = true ;
1734+ if (tree_->io_pads .empty ()) {
1735+ for (odb::dbBTerm* bterm : net->getBTerms ()) {
1736+ const int cluster_id = tree_->maps .bterm_to_cluster_id .at (bterm);
1737+ net_has_io_pin = true ;
17331738
1734- if (bterm->getIoType () == odb::dbIoType::INPUT) {
1735- driver_cluster_id = cluster_id;
1736- } else {
1737- load_clusters_ids.push_back (cluster_id);
1739+ if (bterm->getIoType () == odb::dbIoType::INPUT) {
1740+ driver_cluster_id = cluster_id;
1741+ } else {
1742+ load_clusters_ids.push_back (cluster_id);
1743+ }
17381744 }
17391745 }
17401746
0 commit comments