Skip to content

Commit 261abb6

Browse files
Merge pull request #3067 from verilog-to-routing/feature-fasm-wire-fix
[FASM] Fixed Bug With Wire Creation
2 parents 1232d6f + 472db87 commit 261abb6

File tree

3 files changed

+82
-20
lines changed

3 files changed

+82
-20
lines changed

utils/fasm/src/fasm.cpp

Lines changed: 81 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -217,26 +217,73 @@ std::string FasmWriterVisitor::build_clb_prefix(const t_pb *pb, const t_pb_graph
217217
return clb_prefix;
218218
}
219219

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;
228253
}
229254
}
230255
}
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;
236279
}
237280
}
238281
}
239-
return nullptr;
282+
283+
if (wire_output_pin != nullptr)
284+
return true;
285+
286+
return false;
240287
}
241288

242289
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*
278325
}
279326

280327
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.
284341
const int num_inputs = *route.pb_graph_pin->parent_node->num_input_pins;
285342
const auto *lut_definition = find_lut(route.pb_graph_pin->parent_node);
286343
VTR_ASSERT(lut_definition->num_inputs == num_inputs);
287344

345+
// Create a wire implementation for the LUT.
288346
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");
289353
}
290354
}
291355

vpr/src/base/read_netlist.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -755,6 +755,7 @@ static void processPorts(pugi::xml_node Parent, t_pb* pb, t_pb_routes& pb_route,
755755
pb_route.insert(std::make_pair(rr_node_index, t_pb_route()));
756756
pb_route[rr_node_index].driver_pb_pin_id = pin_node[0][0]->pin_count_in_cluster;
757757
pb_route[rr_node_index].pb_graph_pin = pb_gpin;
758+
VTR_ASSERT(pb_route[rr_node_index].pb_graph_pin->pin_number == i);
758759

759760
found = false;
760761
for (j = 0; j < pin_node[0][0]->num_output_edges; j++) {

vpr/src/route/route_utils.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,7 @@
1919
#include "route_tree.h"
2020
#include "rr_graph.h"
2121
#include "tatum/TimingReporter.hpp"
22-
23-
#ifdef VPR_USE_TBB
2422
#include "stats.h"
25-
#endif // VPR_USE_TBB
2623

2724
bool check_net_delays(const Netlist<>& net_list, NetPinsMatrix<float>& net_delay) {
2825
constexpr float ERROR_TOL = 0.0001;

0 commit comments

Comments
 (0)