@@ -1099,47 +1099,33 @@ static AtomBlockId get_sink_block(const AtomBlockId block_id,
10991099 }
11001100
11011101 const auto & net_sinks = atom_nlist.net_sinks (net_id);
1102- if (is_chain_pattern) {
1103- // If the pattern is a chain, allow nets with multiple sinks.
1104- // This enables forming chains where the COUT is connected both to
1105- // the next element in the chain and to the block's output pin.
1106- bool connected_to_latch = false ;
1107- AtomBlockId pattern_sink_block_id = AtomBlockId::INVALID ();
1108- for (const auto & sink_pin_id : net_sinks) {
1109- auto sink_block_id = atom_nlist.pin_block (sink_pin_id);
1110- if (atom_nlist.block_model (sink_block_id)->name == std::string (MODEL_LATCH)) {
1111- connected_to_latch = true ;
1112- }
1113- if (primitive_type_feasible (sink_block_id, to_pb_type)) {
1114- auto to_port_id = atom_nlist.find_atom_port (sink_block_id, to_port_model);
1115- auto to_pin_id = atom_nlist.find_pin (to_port_id, BitIndex (to_pin_number));
1116- if (to_pin_id == sink_pin_id) {
1117- pattern_sink_block_id = sink_block_id;
1118- }
1119- }
1102+ // If the pattern is a chain, allow nets with multiple sinks.
1103+ // This enables forming chains where the COUT is connected both to
1104+ // the next element in the chain and to the block's output pin.
1105+ bool connected_to_latch = false ;
1106+ AtomBlockId pattern_sink_block_id = AtomBlockId::INVALID ();
1107+ for (const auto & sink_pin_id : net_sinks) {
1108+ auto sink_block_id = atom_nlist.pin_block (sink_pin_id);
1109+ if (atom_nlist.block_model (sink_block_id)->name == std::string (MODEL_LATCH)) {
1110+ connected_to_latch = true ;
11201111 }
1121- // If the number of sinks is greater than 1, and one of the connected blocks is a latch,
1122- // then we drop the block to avoid a situation where only registers or unregistered output
1123- // of the block can use the output pin.
1124- // TODO: This is a conservative assumption, and ideally we need to do analysis of the architecture
1125- // before to determine which pattern is supported by the architecture.
1126- if (connected_to_latch && net_sinks.size () > 1 ) {
1127- return AtomBlockId::INVALID ();
1128- }
1129- return pattern_sink_block_id;
1130- } else {
1131- // For non-chain patterns, we conservatively only consider the sink block
1132- // if the net fanout is 1. To clarify, consider a case where the output of a LUT
1133- // is connected to both a register and an unregistered output that feeds another block.
1134- // If the intra-cluster architecture doesn't support having both registered and
1135- // unregistered outputs simultaneously, this could lead to a packing failure.
1136- if (net_sinks.size () == 1 ) {
1137- auto sink_pin_id = *(net_sinks.begin ());
1138- return atom_nlist.pin_block (sink_pin_id);
1112+ if (primitive_type_feasible (sink_block_id, to_pb_type)) {
1113+ auto to_port_id = atom_nlist.find_atom_port (sink_block_id, to_port_model);
1114+ auto to_pin_id = atom_nlist.find_pin (to_port_id, BitIndex (to_pin_number));
1115+ if (to_pin_id == sink_pin_id) {
1116+ pattern_sink_block_id = sink_block_id;
1117+ }
11391118 }
11401119 }
1141-
1142- return AtomBlockId::INVALID ();
1120+ // If the number of sinks is greater than 1, and one of the connected blocks is a latch,
1121+ // then we drop the block to avoid a situation where only registers or unregistered output
1122+ // of the block can use the output pin.
1123+ // TODO: This is a conservative assumption, and ideally we need to do analysis of the architecture
1124+ // before to determine which pattern is supported by the architecture.
1125+ if (connected_to_latch && net_sinks.size () > 1 ) {
1126+ pattern_sink_block_id = AtomBlockId::INVALID ();
1127+ }
1128+ return pattern_sink_block_id;
11431129}
11441130
11451131/* *
0 commit comments