@@ -107,13 +107,11 @@ static void init_molecule_chain_info(const AtomBlockId blk_id,
107
107
const AtomNetlist& atom_nlist);
108
108
109
109
static AtomBlockId get_sink_block (const AtomBlockId block_id,
110
- const t_model_ports* model_port,
111
- const BitIndex pin_number,
110
+ const t_pack_pattern_connections& connections,
112
111
const AtomNetlist& atom_nlist);
113
112
114
113
static AtomBlockId get_driving_block (const AtomBlockId block_id,
115
- const t_model_ports* model_port,
116
- const BitIndex pin_number,
114
+ const t_pack_pattern_connections& connections,
117
115
const AtomNetlist& atom_nlist);
118
116
119
117
static void print_chain_starting_points (t_pack_patterns* chain_pattern);
@@ -1047,17 +1045,13 @@ static bool try_expand_molecule(t_pack_molecule& molecule,
1047
1045
// this block is the driver of this connection
1048
1046
if (block_connection->from_block == pattern_block) {
1049
1047
// find the block this connection is driving and add it to the queue
1050
- auto port_model = block_connection->from_pin ->port ->model_port ;
1051
- auto ipin = block_connection->from_pin ->pin_number ;
1052
- auto sink_blk_id = get_sink_block (block_id, port_model, ipin, atom_nlist);
1048
+ auto sink_blk_id = get_sink_block (block_id, *block_connection, atom_nlist);
1053
1049
// add this sink block id with its corresponding pattern block to the queue
1054
1050
pattern_block_queue.push (std::make_pair (block_connection->to_block , sink_blk_id));
1055
1051
// this block is being driven by this connection
1056
1052
} else if (block_connection->to_block == pattern_block) {
1057
1053
// find the block that is driving this connection and it to the queue
1058
- auto port_model = block_connection->to_pin ->port ->model_port ;
1059
- auto ipin = block_connection->to_pin ->pin_number ;
1060
- auto driver_blk_id = get_driving_block (block_id, port_model, ipin, atom_nlist);
1054
+ auto driver_blk_id = get_driving_block (block_id, *block_connection, atom_nlist);
1061
1055
// add this driver block id with its corresponding pattern block to the queue
1062
1056
pattern_block_queue.push (std::make_pair (block_connection->from_block , driver_blk_id));
1063
1057
}
@@ -1076,62 +1070,94 @@ static bool try_expand_molecule(t_pack_molecule& molecule,
1076
1070
/* *
1077
1071
* Find the atom block in the netlist driven by this pin of the input atom block
1078
1072
* If doesn't exist return AtomBlockId::INVALID()
1079
- * Limitation: The block should be driving only one sink block
1073
+ * TODO: Limitation — For pack patterns other than chains,
1074
+ * the block should be driven by only one block
1080
1075
* block_id : id of the atom block that is driving the net connected to the sink block
1081
- * model_port : the model of the port driving the net
1082
- * pin_number : the pin_number of the pin driving the net (pin index within the port)
1076
+ * connections : pack pattern connections from the given block
1083
1077
*/
1084
1078
static AtomBlockId get_sink_block (const AtomBlockId block_id,
1085
- const t_model_ports* model_port,
1086
- const BitIndex pin_number,
1079
+ const t_pack_pattern_connections& connections,
1087
1080
const AtomNetlist& atom_nlist) {
1088
- auto port_id = atom_nlist.find_atom_port (block_id, model_port);
1089
-
1090
- if (port_id) {
1091
- auto net_id = atom_nlist.port_net (port_id, pin_number);
1092
- if (net_id && atom_nlist.net_sinks (net_id).size () == 1 ) { /* Single fanout assumption */
1093
- auto net_sinks = atom_nlist.net_sinks (net_id);
1094
- auto sink_pin_id = *(net_sinks.begin ());
1095
- return atom_nlist.pin_block (sink_pin_id);
1096
- }
1081
+ const t_model_ports* from_port_model = connections.from_pin ->port ->model_port ;
1082
+ const int from_pin_number = connections.from_pin ->pin_number ;
1083
+ auto from_port_id = atom_nlist.find_atom_port (block_id, from_port_model);
1084
+
1085
+ const t_model_ports* to_port_model = connections.to_pin ->port ->model_port ;
1086
+ const int to_pin_number = connections.to_pin ->pin_number ;
1087
+ const auto & to_pb_type = connections.to_block ->pb_type ;
1088
+
1089
+ if (!from_port_id.is_valid ()) {
1090
+ return AtomBlockId::INVALID ();
1097
1091
}
1098
1092
1099
- return AtomBlockId::INVALID ();
1093
+ auto net_id = atom_nlist.port_net (from_port_id, from_pin_number);
1094
+ if (!net_id.is_valid ()) {
1095
+ return AtomBlockId::INVALID ();
1096
+ }
1097
+
1098
+ const auto & net_sinks = atom_nlist.net_sinks (net_id);
1099
+ // Iterate through all sink blocks and check whether any of them
1100
+ // is compatible with the block specified in the pack pattern.
1101
+ bool connected_to_latch = false ;
1102
+ AtomBlockId pattern_sink_block_id = AtomBlockId::INVALID ();
1103
+ for (const auto & sink_pin_id : net_sinks) {
1104
+ auto sink_block_id = atom_nlist.pin_block (sink_pin_id);
1105
+ if (atom_nlist.block_model (sink_block_id)->name == std::string (MODEL_LATCH)) {
1106
+ connected_to_latch = true ;
1107
+ }
1108
+ if (primitive_type_feasible (sink_block_id, to_pb_type)) {
1109
+ auto to_port_id = atom_nlist.find_atom_port (sink_block_id, to_port_model);
1110
+ auto to_pin_id = atom_nlist.find_pin (to_port_id, BitIndex (to_pin_number));
1111
+ if (to_pin_id == sink_pin_id) {
1112
+ pattern_sink_block_id = sink_block_id;
1113
+ }
1114
+ }
1115
+ }
1116
+ // If the number of sinks is greater than 1, and one of the connected blocks is a latch,
1117
+ // then we drop the block to avoid a situation where only registers or unregistered output
1118
+ // of the block can use the output pin.
1119
+ // TODO: This is a conservative assumption, and ideally we need to do analysis of the architecture
1120
+ // before to determine which pattern is supported by the architecture.
1121
+ if (connected_to_latch && net_sinks.size () > 1 ) {
1122
+ pattern_sink_block_id = AtomBlockId::INVALID ();
1123
+ }
1124
+ return pattern_sink_block_id;
1100
1125
}
1101
1126
1102
1127
/* *
1103
1128
* Find the atom block in the netlist driving this pin of the input atom block
1104
1129
* If doesn't exist return AtomBlockId::INVALID()
1105
1130
* Limitation: This driving block should be driving only the input block
1106
1131
* block_id : id of the atom block that is connected to a net driven by the driving block
1107
- * model_port : the model of the port driven by the net
1108
- * pin_number : the pin_number of the pin driven by the net (pin index within the port)
1132
+ * connections : pack pattern connections from the given block
1109
1133
*/
1110
1134
static AtomBlockId get_driving_block (const AtomBlockId block_id,
1111
- const t_model_ports* model_port,
1112
- const BitIndex pin_number,
1135
+ const t_pack_pattern_connections& connections,
1113
1136
const AtomNetlist& atom_nlist) {
1114
- auto port_id = atom_nlist.find_atom_port (block_id, model_port);
1115
-
1116
- if (port_id) {
1117
- auto net_id = atom_nlist.port_net (port_id, pin_number);
1118
- if (net_id && atom_nlist.net_sinks (net_id).size () == 1 ) { /* Single fanout assumption */
1137
+ auto to_port_model = connections.to_pin ->port ->model_port ;
1138
+ auto to_pin_number = connections.to_pin ->pin_number ;
1139
+ auto to_port_id = atom_nlist.find_atom_port (block_id, to_port_model);
1119
1140
1120
- auto driver_blk_id = atom_nlist.net_driver_block (net_id);
1141
+ if (!to_port_id.is_valid ()) {
1142
+ return AtomBlockId::INVALID ();
1143
+ }
1121
1144
1122
- if (model_port->is_clock ) {
1123
- auto driver_blk_type = atom_nlist.block_type (driver_blk_id);
1145
+ auto net_id = atom_nlist.port_net (to_port_id, to_pin_number);
1146
+ if (net_id && atom_nlist.net_sinks (net_id).size () == 1 ) { /* Single fanout assumption */
1147
+ auto driver_blk_id = atom_nlist.net_driver_block (net_id);
1124
1148
1125
- // TODO: support multi-clock primitives.
1126
- // If the driver block is a .input block, this assertion should not
1127
- // be triggered as the sink block might have only one input pin, which
1128
- // would be a clock pin in case the sink block primitive is a clock generator,
1129
- // resulting in a pin_number == 0.
1130
- VTR_ASSERT (pin_number == 1 || (pin_number == 0 && driver_blk_type == AtomBlockType::INPAD));
1131
- }
1149
+ if (to_port_model->is_clock ) {
1150
+ auto driver_blk_type = atom_nlist.block_type (driver_blk_id);
1132
1151
1133
- return atom_nlist.net_driver_block (net_id);
1152
+ // TODO: support multi-clock primitives.
1153
+ // If the driver block is a .input block, this assertion should not
1154
+ // be triggered as the sink block might have only one input pin, which
1155
+ // would be a clock pin in case the sink block primitive is a clock generator,
1156
+ // resulting in a pin_number == 0.
1157
+ VTR_ASSERT (to_pin_number == 1 || (to_pin_number == 0 && driver_blk_type == AtomBlockType::INPAD));
1134
1158
}
1159
+
1160
+ return driver_blk_id;
1135
1161
}
1136
1162
1137
1163
return AtomBlockId::INVALID ();
0 commit comments