@@ -217,26 +217,73 @@ std::string FasmWriterVisitor::build_clb_prefix(const t_pb *pb, const t_pb_graph
217
217
return clb_prefix;
218
218
}
219
219
220
- static const t_pb_graph_pin* is_node_used (const t_pb_routes &top_pb_route, const t_pb_graph_node* pb_graph_node) {
221
- // Is the node used at all?
222
- const t_pb_graph_pin* pin = nullptr ;
223
- for (int port_index = 0 ; port_index < pb_graph_node->num_output_ports ; ++port_index) {
224
- for (int pin_index = 0 ; pin_index < pb_graph_node->num_output_pins [port_index]; ++pin_index) {
225
- pin = &pb_graph_node->output_pins [port_index][pin_index];
226
- if (top_pb_route.count (pin->pin_count_in_cluster ) > 0 && top_pb_route[pin->pin_count_in_cluster ].atom_net_id != AtomNetId::INVALID ()) {
227
- return pin;
220
+ /* *
221
+ * @brief Returns true if the given pin is used (i.e. is not "open").
222
+ */
223
+ static bool is_pin_used (const t_pb_graph_pin* pin, const t_pb_routes &top_pb_route) {
224
+ // A pin is used if it has a pb_route that is connected to an atom net.
225
+ if (top_pb_route.count (pin->pin_count_in_cluster ) == 0 )
226
+ return false ;
227
+ if (!top_pb_route[pin->pin_count_in_cluster ].atom_net_id .is_valid ())
228
+ return false ;
229
+ return true ;
230
+ }
231
+
232
+ /* *
233
+ * @brief Returns the input pin for the given wire.
234
+ *
235
+ * Wires in VPR are a special primitive which is a LUT which acts like a wire
236
+ * pass-through. Only one input of this LUT should be used.
237
+ *
238
+ * @param top_pb_route
239
+ * The top pb route for the cluster that contains the wire.
240
+ * @param pb_graph_node
241
+ * The pb_graph_node of the wire primitive that we are getting the input
242
+ * pin for.
243
+ */
244
+ static const t_pb_graph_pin* get_wire_input_pin (const t_pb_routes &top_pb_route, const t_pb_graph_node* pb_graph_node) {
245
+ const t_pb_graph_pin* wire_input_pin = nullptr ;
246
+ for (int port_index = 0 ; port_index < pb_graph_node->num_input_ports ; ++port_index) {
247
+ for (int pin_index = 0 ; pin_index < pb_graph_node->num_input_pins [port_index]; ++pin_index) {
248
+ const t_pb_graph_pin* pin = &pb_graph_node->input_pins [port_index][pin_index];
249
+ if (is_pin_used (pin, top_pb_route)) {
250
+ VTR_ASSERT_MSG (wire_input_pin == nullptr ,
251
+ " Wire found with more than 1 used input" );
252
+ wire_input_pin = pin;
228
253
}
229
254
}
230
255
}
231
- for (int port_index = 0 ; port_index < pb_graph_node->num_input_ports ; ++port_index) {
232
- for (int pin_index = 0 ; pin_index < pb_graph_node->num_input_pins [port_index]; ++pin_index) {
233
- pin = &pb_graph_node->input_pins [port_index][pin_index];
234
- if (top_pb_route.count (pin->pin_count_in_cluster ) > 0 && top_pb_route[pin->pin_count_in_cluster ].atom_net_id != AtomNetId::INVALID ()) {
235
- return pin;
256
+ return wire_input_pin;
257
+ }
258
+
259
+ /* *
260
+ * @brief Returns true if the given wire is used.
261
+ *
262
+ * A wire is used if it has a used output pin.
263
+ *
264
+ * @param top_pb_route
265
+ * The top pb route for the cluster that contains the wire.
266
+ * @param pb_graph_node
267
+ * The pb_graph_node of the wire primitive that we are checking is used.
268
+ */
269
+ static bool is_wire_used (const t_pb_routes &top_pb_route, const t_pb_graph_node* pb_graph_node) {
270
+ // A wire is used if it has a used output pin.
271
+ const t_pb_graph_pin* wire_output_pin = nullptr ;
272
+ for (int port_index = 0 ; port_index < pb_graph_node->num_output_ports ; ++port_index) {
273
+ for (int pin_index = 0 ; pin_index < pb_graph_node->num_output_pins [port_index]; ++pin_index) {
274
+ const t_pb_graph_pin* pin = &pb_graph_node->output_pins [port_index][pin_index];
275
+ if (is_pin_used (pin, top_pb_route)) {
276
+ VTR_ASSERT_MSG (wire_output_pin == nullptr ,
277
+ " Wire found with more than 1 used output" );
278
+ wire_output_pin = pin;
236
279
}
237
280
}
238
281
}
239
- return nullptr ;
282
+
283
+ if (wire_output_pin != nullptr )
284
+ return true ;
285
+
286
+ return false ;
240
287
}
241
288
242
289
void FasmWriterVisitor::check_features (const t_metadata_dict *meta) const {
@@ -278,14 +325,31 @@ void FasmWriterVisitor::visit_all_impl(const t_pb_routes &pb_routes, const t_pb*
278
325
}
279
326
280
327
if (mode != nullptr && std::string (mode->name ) == " wire" ) {
281
- auto io_pin = is_node_used (pb_routes, pb_graph_node);
282
- if (io_pin != nullptr ) {
283
- const auto & route = pb_routes.at (io_pin->pin_count_in_cluster );
328
+ // Check if the wire is used. If the wire is unused (i.e. it does not connect
329
+ // to anything), it does not need to be created.
330
+ if (is_wire_used (pb_routes, pb_graph_node)) {
331
+ // Get the input pin of the LUT that feeds the wire. There should be one
332
+ // and only one.
333
+ const t_pb_graph_pin* wire_input_pin = get_wire_input_pin (pb_routes, pb_graph_node);
334
+ VTR_ASSERT_MSG (wire_input_pin != nullptr ,
335
+ " Wire found with no used input pins" );
336
+
337
+ // Get the route going into this pin.
338
+ const auto & route = pb_routes.at (wire_input_pin->pin_count_in_cluster );
339
+
340
+ // Find the lut definition for the parent of this wire.
284
341
const int num_inputs = *route.pb_graph_pin ->parent_node ->num_input_pins ;
285
342
const auto *lut_definition = find_lut (route.pb_graph_pin ->parent_node );
286
343
VTR_ASSERT (lut_definition->num_inputs == num_inputs);
287
344
345
+ // Create a wire implementation for the LUT.
288
346
output_fasm_features (lut_definition->CreateWire (route.pb_graph_pin ->pin_number ));
347
+ } else {
348
+ // If the wire is not used, ensure that the inputs to the wire are also
349
+ // unused. This is just a sanity check to ensure that all wires are
350
+ // either completely unused or have one input and one output.
351
+ VTR_ASSERT_MSG (get_wire_input_pin (pb_routes, pb_graph_node) == nullptr ,
352
+ " Wire found with a used input pin, but no used output pin" );
289
353
}
290
354
}
291
355
0 commit comments