diff --git a/vpr/src/pack/prepack.cpp b/vpr/src/pack/prepack.cpp index 3307472ac79..36f993b151f 100644 --- a/vpr/src/pack/prepack.cpp +++ b/vpr/src/pack/prepack.cpp @@ -79,7 +79,7 @@ static t_pb_graph_node* get_expected_lowest_cost_primitive_for_atom_block(const static t_pb_graph_node* get_expected_lowest_cost_primitive_for_atom_block_in_pb_graph_node(const AtomBlockId blk_id, t_pb_graph_node* curr_pb_graph_node, float* cost); -static AtomBlockId find_new_root_atom_for_chain(const AtomBlockId blk_id, const t_pack_patterns* list_of_pack_pattern); +static AtomBlockId find_new_root_atom_for_chain(const AtomBlockId blk_id, const t_pack_patterns* list_of_pack_pattern, bool is_nontrivial_chain); static std::vector find_end_of_path(t_pb_graph_pin* input_pin, int pattern_index); @@ -948,7 +948,7 @@ static t_pack_molecule* try_create_molecule(t_pack_patterns* list_of_pack_patter // If a chain pattern extends beyond a single logic block, we must find // the furthest blk_id up the chain that is not mapped to a molecule yet. if (pack_pattern->is_chain) { - blk_id = find_new_root_atom_for_chain(blk_id, pack_pattern); + blk_id = find_new_root_atom_for_chain(blk_id, pack_pattern, false); if (!blk_id) return nullptr; } @@ -1292,6 +1292,25 @@ static int compare_pack_pattern(const t_pack_patterns* pattern_a, const t_pack_p } return 0; } +/* checks whether or not this block drives a pattern connection (e.g. its cout drives another block's cin) */ +static bool drives_pattern_connection(const t_pack_patterns* pack_pattern, AtomBlockId blk_id) { + auto& atom_ctx = g_vpr_ctx.atom(); + auto iconn = pack_pattern->root_block->connections; + + while (iconn != NULL) { + t_pb_graph_pin* cur_pin = iconn->from_pin; + t_model_ports* cur_model_port = cur_pin->port->model_port; + AtomPortId cur_port = atom_ctx.nlist.find_atom_port(blk_id, cur_model_port); + if (cur_port) { + AtomNetId cur_net = atom_ctx.nlist.port_net(cur_port, cur_pin->pin_number); + + if (cur_net) + return true; + } + iconn = iconn->next; + } + return false; +} /* A chain can extend across multiple atom blocks. Must segment the chain to fit in an atom * block by identifying the actual atom that forms the root of the new chain. @@ -1300,8 +1319,9 @@ static int compare_pack_pattern(const t_pack_patterns* pattern_a, const t_pack_p * Assumes that the root of a chain is the primitive that starts the chain or is driven from outside the logic block * block_index: index of current atom * list_of_pack_pattern: ptr to current chain pattern + * is_nontrivial_chain: true if this function was called from an atom driven by the current atom (so we know this atom is part of a chain of length > 1) */ -static AtomBlockId find_new_root_atom_for_chain(const AtomBlockId blk_id, const t_pack_patterns* list_of_pack_pattern) { +static AtomBlockId find_new_root_atom_for_chain(const AtomBlockId blk_id, const t_pack_patterns* list_of_pack_pattern, bool is_nontrivial_chain) { AtomBlockId new_root_blk_id; t_pb_graph_pin* root_ipin; t_pb_graph_node* root_pb_graph_node; @@ -1324,11 +1344,24 @@ static AtomBlockId find_new_root_atom_for_chain(const AtomBlockId blk_id, const // find the block id of the atom block driving the input of this block AtomBlockId driver_blk_id = atom_ctx.nlist.find_atom_pin_driver(blk_id, model_port, root_ipin->pin_number); - // if there is no driver block for this net - // then it is the furthest up the chain + // if there is no driver block for this net, then + // if it drives a pattern connection, it is furthest up the chain + // if it does not drive a pattern connection and has no driver, it is not in a chain if (!driver_blk_id) { - return blk_id; + // if this block was reached from further down the chain, then this is a chain + if (is_nontrivial_chain) { + return blk_id; + } else { + // if this is the first chain block encountered, check to see if it drives a pattern connection + if (drives_pattern_connection(list_of_pack_pattern, blk_id)) { + return blk_id; + } + } + // if this block does not drive, and is not driven by, a pattern connection, then this is not a chain + + return AtomBlockId::INVALID(); } + // check if driver atom is already packed auto rng = atom_ctx.atom_molecules.equal_range(driver_blk_id); bool rng_empty = (rng.first == rng.second); @@ -1338,7 +1371,8 @@ static AtomBlockId find_new_root_atom_for_chain(const AtomBlockId blk_id, const } // didn't find furthest atom up the chain, keep searching further up the chain - new_root_blk_id = find_new_root_atom_for_chain(driver_blk_id, list_of_pack_pattern); + // if the function reaches this point then the current block has a driver, so this is a nontrivial chain + new_root_blk_id = find_new_root_atom_for_chain(driver_blk_id, list_of_pack_pattern, true); if (!new_root_blk_id) { return blk_id;