diff --git a/vpr/src/pack/prepack.cpp b/vpr/src/pack/prepack.cpp index 4f14aa9483..1f9f1a717b 100644 --- a/vpr/src/pack/prepack.cpp +++ b/vpr/src/pack/prepack.cpp @@ -99,7 +99,17 @@ static void find_all_equivalent_chains(t_pack_patterns* chain_pattern, const t_p static void update_chain_root_pins(t_pack_patterns* chain_pattern, const std::vector& chain_input_pins); -static void get_all_connected_primitive_pins(const t_pb_graph_pin* cluster_input_pin, std::vector& connected_primitive_pins); +/** + * @brief Get all primitive pins connected to the given cluster input pin + * + * @param cluster_input_pin Cluster input pin to get connected primitive pins from + * @param pattern_blocks Set of pb_types in the pack pattern. Pins on the blocks in this set will + * be added to the connected_primitive_pins vector + * @param connected_primitive_pins Vector to store connected primitive pins + */ +static void get_all_connected_primitive_pins(const t_pb_graph_pin* cluster_input_pin, + const std::unordered_set& pattern_blocks, + std::vector& connected_primitive_pins); static void init_molecule_chain_info(const AtomBlockId blk_id, t_pack_molecule& molecule, @@ -117,6 +127,14 @@ static AtomBlockId get_driving_block(const AtomBlockId block_id, const t_pack_pattern_connections& connections, const AtomNetlist& atom_nlist); +/** + * @brief Get an unordered set of all pb_types in the given pack pattern + * + * @param pack_pattern Pack pattern to get pb_types from + * @return std::unordered_set Set of pb_types in the pack pattern + */ +static std::unordered_set get_pattern_blocks(const t_pack_patterns& pack_pattern); + static void print_chain_starting_points(t_pack_patterns* chain_pattern); /*****************************************/ @@ -1172,6 +1190,51 @@ static AtomBlockId get_driving_block(const AtomBlockId block_id, return AtomBlockId::INVALID(); } +static std::unordered_set get_pattern_blocks(const t_pack_patterns& pack_pattern) { + std::unordered_set pattern_blocks; + + t_pack_pattern_connections* connections = pack_pattern.root_block->connections; + if (connections == nullptr) { + return pattern_blocks; + } + std::unordered_set visited_from_pins; + std::unordered_set visited_to_pins; + std::queue pack_pattern_blocks; + pack_pattern_blocks.push(connections->from_block); + + /** Start from the root block of the pack pattern and add the connected block to the queue */ + while (!pack_pattern_blocks.empty()) { + t_pack_pattern_block* current_pattern_block = pack_pattern_blocks.front(); + pack_pattern_blocks.pop(); + t_pack_pattern_connections* current_connenction = current_pattern_block->connections; + /* + * Iterate through all the connections of the current pattern block to + * add the connected block to the queue + */ + while (current_connenction != nullptr) { + if (visited_from_pins.find(current_connenction->from_pin) != visited_from_pins.end()) { + if (visited_to_pins.find(current_connenction->to_pin) != visited_to_pins.end()) { + /* We've already seen this connection */ + current_connenction = current_connenction->next; + continue; + } + } + /* + * To avoid visiting the same connection twice, since it is both stored in from_pin and to_pin, + * add the from_pin and to_pin to the visited sets + */ + visited_from_pins.insert(current_connenction->from_pin); + visited_to_pins.insert(current_connenction->to_pin); + + /* The from_pin block belongs to the pattern block */ + pattern_blocks.insert(current_connenction->from_pin->port->parent_pb_type); + pack_pattern_blocks.push(current_connenction->to_block); + current_connenction = current_connenction->next; + } + } + return pattern_blocks; +} + static void print_pack_molecules(const char* fname, const std::vector& list_of_pack_patterns, const int num_pack_patterns, @@ -1564,9 +1627,10 @@ static void update_chain_root_pins(t_pack_patterns* chain_pattern, const std::vector& chain_input_pins) { std::vector> primitive_input_pins; + std::unordered_set pattern_blocks = get_pattern_blocks(*chain_pattern); for (const auto pin_ptr : chain_input_pins) { std::vector connected_primitive_pins; - get_all_connected_primitive_pins(pin_ptr, connected_primitive_pins); + get_all_connected_primitive_pins(pin_ptr, pattern_blocks, connected_primitive_pins); /** * It is required that the chain pins are connected inside a complex @@ -1590,7 +1654,9 @@ static void update_chain_root_pins(t_pack_patterns* chain_pattern, * the Cin pin of all the adder primitives connected to this pin. Which is for typical architectures * will be only one pin connected to the very first adder in the cluster. */ -static void get_all_connected_primitive_pins(const t_pb_graph_pin* cluster_input_pin, std::vector& connected_primitive_pins) { +static void get_all_connected_primitive_pins(const t_pb_graph_pin* cluster_input_pin, + const std::unordered_set& pattern_blocks, + std::vector& connected_primitive_pins) { /* Skip pins for modes that are disabled for packing*/ if ((nullptr != cluster_input_pin->parent_node->pb_type->parent_mode) && (true == cluster_input_pin->parent_node->pb_type->parent_mode->disable_packing)) { @@ -1601,9 +1667,12 @@ static void get_all_connected_primitive_pins(const t_pb_graph_pin* cluster_input const auto& output_edge = cluster_input_pin->output_edges[iedge]; for (int ipin = 0; ipin < output_edge->num_output_pins; ipin++) { if (output_edge->output_pins[ipin]->is_primitive_pin()) { - connected_primitive_pins.push_back(output_edge->output_pins[ipin]); + /** Add the output pin to the vector only if it belongs to a pb_type registered in the pattern_blocks set */ + if (pattern_blocks.find(output_edge->output_pins[ipin]->parent_node->pb_type) != pattern_blocks.end()) { + connected_primitive_pins.push_back(output_edge->output_pins[ipin]); + } } else { - get_all_connected_primitive_pins(output_edge->output_pins[ipin], connected_primitive_pins); + get_all_connected_primitive_pins(output_edge->output_pins[ipin], pattern_blocks, connected_primitive_pins); } } }