vpr/src/pack/cluster.cpp
/**
 * Score unclustered atoms that are two hops away from current cluster
 * For example, consider a cluster that has a FF feeding an adder in another
 * cluster. Since this FF is feeding an adder that is packed in another cluster
 * this function should find other FFs that are feeding other inputs of this adder
 * since they are two hops away from the FF packed in this cluster
 */
Score unclustered atoms that are two hops away from current cluster
For example, consider a cluster that has a FF feeding an adder in another
cluster. Since this FF is feeding an adder that is packed in another cluster
this function should find other FFs that are feeding other inputs of this adder
since they are two hops away from the FF packed in this cluster
Score unclustered atoms that are two hops away from current cluster For example consider a cluster that has a FF feeding an adder in another cluster . Since this FF is feeding an adder that is packed in another cluster this function should find other FFs that are feeding other inputs of this adder since they are two hops away from the FF packed in this cluster
static void load_transitive_fanout_candidates(ClusterBlockId clb_index,
                                              const std::multimap<AtomBlockId, t_pack_molecule*>& atom_molecules,
                                              t_pb_stats* pb_stats,
                                              vtr::vector<ClusterBlockId, std::vector<AtomNetId>>& clb_inter_blk_nets,
                                              int transitive_fanout_threshold) {
    auto& atom_ctx = g_vpr_ctx.atom();
    for (const auto net_id : pb_stats->marked_nets) {
        if (int(atom_ctx.nlist.net_pins(net_id).size()) < transitive_fanout_threshold + 1) {
            for (const auto pin_id : atom_ctx.nlist.net_pins(net_id)) {
                AtomBlockId atom_blk_id = atom_ctx.nlist.pin_block(pin_id);
                ClusterBlockId tclb = atom_ctx.lookup.atom_clb(atom_blk_id);
                if (tclb != clb_index && tclb != ClusterBlockId::INVALID()) {
                    for (AtomNetId tnet : clb_inter_blk_nets[tclb]) {
                        for (AtomPinId tpin : atom_ctx.nlist.net_pins(tnet)) {
                            auto blk_id = atom_ctx.nlist.pin_block(tpin);
                            if (atom_ctx.lookup.atom_clb(blk_id) == ClusterBlockId::INVALID()) {
                                auto& transitive_fanout_candidates = pb_stats->transitive_fanout_candidates;
                                if (pb_stats->gain.count(blk_id) == 0) {
                                    pb_stats->gain[blk_id] = 0.001;
                                } else {
                                    pb_stats->gain[blk_id] += 0.001;
                                }
                                auto rng = atom_molecules.equal_range(blk_id);
                                for (const auto& kv : vtr::make_range(rng.first, rng.second)) {
                                    t_pack_molecule* molecule = kv.second;
                                    if (molecule->valid) {
                                        transitive_fanout_candidates.insert({molecule->atom_block_ids[molecule->root], molecule});
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
static void load_transitive_fanout_candidates ( ClusterBlockId clb_index , const std :: multimap < AtomBlockId , t_pack_molecule * > & atom_molecules , t_pb_stats * pb_stats , vtr :: vector < ClusterBlockId , std :: vector < AtomNetId > > & clb_inter_blk_nets , int transitive_fanout_threshold ) { auto & atom_ctx = g_vpr_ctx . atom ( ) ; for ( const auto net_id : pb_stats -> marked_nets ) { if ( int ( atom_ctx . nlist . net_pins ( net_id ) . size ( ) ) < transitive_fanout_threshold + 1 ) { for ( const auto pin_id : atom_ctx . nlist . net_pins ( net_id ) ) { AtomBlockId atom_blk_id = atom_ctx . nlist . pin_block ( pin_id ) ; ClusterBlockId tclb = atom_ctx . lookup . atom_clb ( atom_blk_id ) ; if ( tclb != clb_index && tclb != ClusterBlockId :: INVALID ( ) ) { for ( AtomNetId tnet : clb_inter_blk_nets [ tclb ] ) { for ( AtomPinId tpin : atom_ctx . nlist . net_pins ( tnet ) ) { auto blk_id = atom_ctx . nlist . pin_block ( tpin ) ; if ( atom_ctx . lookup . atom_clb ( blk_id ) == ClusterBlockId :: INVALID ( ) ) { auto & transitive_fanout_candidates = pb_stats -> transitive_fanout_candidates ; if ( pb_stats -> gain . count ( blk_id ) == 0 ) { pb_stats -> gain [ blk_id ] = 0.001 ; } else { pb_stats -> gain [ blk_id ] += 0.001 ; } auto rng = atom_molecules . equal_range ( blk_id ) ; for ( const auto & kv : vtr :: make_range ( rng . first , rng . second ) ) { t_pack_molecule * molecule = kv . second ; if ( molecule -> valid ) { transitive_fanout_candidates . insert ( { molecule -> atom_block_ids [ molecule -> root ] , molecule } ) ; } } } } } } } } } }
Score unclustered atoms that are two hops away from current cluster
 For example, consider a cluster that has a FF feeding an adder in another
 cluster.
Score unclustered atoms that are two hops away from current cluster For example consider a cluster that has a FF feeding an adder in another cluster .
// iterate over all the nets that have pins in this cluster // only consider small nets to constrain runtime // iterate over all the pins of the net // get the transitive cluster // if the block connected to this pin is packed in another cluster // explore transitive nets from already packed cluster // iterate over all the pins of the net // This transitive atom is not packed, score and add