Skip to content

More fixes to sync_netlists_to_routing_flat #2867

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 22 commits into from
Apr 28, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
06d02f4
more fixes for bitstream generation with flat router
fkosar-ql Jan 21, 2025
9ca4776
Merge branch 'master' of https://github.com/verilog-to-routing/vtr-ve…
amin1377 Apr 23, 2025
ad8bfce
[vpr][pack] fix merge issues w/ flat sync list
amin1377 Apr 23, 2025
fbd2015
make format
amin1377 Apr 23, 2025
8b15437
make format 2
amin1377 Apr 23, 2025
ae07129
[vpr][base] fix assigned pb_graph_pin when graph node is not primitive
amin1377 Apr 25, 2025
b78b3eb
[vpr][pack] pass logical type to alloc_and_laod_pb_route
amin1377 Apr 25, 2025
b0d7afc
[vpr][pack] update alloc_and_load_pb_route header file
amin1377 Apr 25, 2025
250329b
[vpr][pack] fix pb_graph_pin assignment in load_trace_to_pb_route
amin1377 Apr 25, 2025
f9c1714
Merge branch 'master' of https://github.com/verilog-to-routing/vtr-ve…
amin1377 Apr 25, 2025
a839dc2
[vpr][pack] add intra_lb_pb_pin_lookup_ to cluster legalizer
amin1377 Apr 26, 2025
de84b8a
[vpr][pack] initializer intra_lb_pb_pin_lookup and pass it to alloc_a…
amin1377 Apr 26, 2025
8902090
[vpr][pack] use intra_lb_pb_pin_lookup to get pb_pin from pin number
amin1377 Apr 26, 2025
3594124
make format
amin1377 Apr 26, 2025
623132e
[vpr][pack] remove casting net id
amin1377 Apr 28, 2025
2468e8a
[vpr][pack] add doxygen comment for alloc_and_load_pb_route
amin1377 Apr 28, 2025
86491fd
[vpr][pack] remove redundant parameters
amin1377 Apr 28, 2025
798055c
[vpr][pack] polish load_trace_to_pb_route
amin1377 Apr 28, 2025
241589b
make format
amin1377 Apr 28, 2025
cffeaa1
Merge branch 'master' of https://github.com/verilog-to-routing/vtr-ve…
amin1377 Apr 28, 2025
f5bb0eb
[vpr][pack] fix parameter shadowing
amin1377 Apr 28, 2025
b79a174
Merge branch 'master' of https://github.com/verilog-to-routing/vtr-ve…
amin1377 Apr 28, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion vpr/src/base/netlist_writer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1275,7 +1275,10 @@ class NetlistWriterVisitor : public NetlistVisitor {

//Add the single output connection
{
auto atom_net_id = top_pb_route[sink_cluster_pin_idx].atom_net_id; //Connected net in atom netlist
/* Check if the output is connected */
AtomNetId atom_net_id = AtomNetId::INVALID();
if (top_pb_route.count(sink_cluster_pin_idx))
atom_net_id = top_pb_route[sink_cluster_pin_idx].atom_net_id; //Connected net in atom netlist

std::string net;
if (!atom_net_id) {
Expand Down
2 changes: 1 addition & 1 deletion vpr/src/base/read_netlist.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -823,7 +823,7 @@ static void processPorts(pugi::xml_node Parent, t_pb* pb, t_pb_routes& pb_route,
//Why does this not use the output pin used to deterimine the rr node index?
pb_route.insert(std::make_pair(rr_node_index, t_pb_route()));
pb_route[rr_node_index].driver_pb_pin_id = pin_node[0][0]->pin_count_in_cluster;
pb_route[rr_node_index].pb_graph_pin = pin_node[0][0];
pb_route[rr_node_index].pb_graph_pin = &pb->pb_graph_node->output_pins[out_port][i];

found = false;
for (j = 0; j < pin_node[0][0]->num_output_edges; j++) {
Expand Down
29 changes: 29 additions & 0 deletions vpr/src/base/vpr_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,12 @@ static void free_complex_block_types();
static void free_device(const t_det_routing_arch& routing_arch);
static void free_circuit();

/** Set all port equivalences in the architecture to NONE. This is used in the
* case of the flat router where port equivalence does not make sense.
* We could just keep it set and ignore it, but that prevents compatibility
* with OpenFPGA which takes it seriously. */
static void unset_port_equivalences(DeviceContext& device_ctx);

/* Local subroutines end */

///@brief Display general VPR information
Expand Down Expand Up @@ -365,6 +371,25 @@ void vpr_init_with_options(const t_options* options, t_vpr_setup* vpr_setup, t_a
device_ctx.pad_loc_type = vpr_setup->PlacerOpts.pad_loc_type;
}

/** Port equivalence does not make sense during flat routing.
* Remove port equivalence from all ports in the architecture */
static void unset_port_equivalences(DeviceContext& device_ctx) {
for (auto& physical_type : device_ctx.physical_tile_types) {
for (auto& sub_tile : physical_type.sub_tiles) {
for (auto& port : sub_tile.ports) {
port.equivalent = PortEquivalence::NONE;
}
}
}
for (auto& logical_type : device_ctx.logical_block_types) {
if (!logical_type.pb_type)
continue;
for (int i = 0; i < logical_type.pb_type->num_ports; i++) {
logical_type.pb_type->ports[i].equivalent = PortEquivalence::NONE;
}
}
}

bool vpr_flow(t_vpr_setup& vpr_setup, t_arch& arch) {
if (vpr_setup.exit_before_pack) {
VTR_LOG_WARN("Exiting before packing as requested.\n");
Expand Down Expand Up @@ -443,6 +468,10 @@ bool vpr_flow(t_vpr_setup& vpr_setup, t_arch& arch) {

bool is_flat = vpr_setup.RouterOpts.flat_routing;
const Netlist<>& router_net_list = is_flat ? (const Netlist<>&)g_vpr_ctx.atom().netlist() : (const Netlist<>&)g_vpr_ctx.clustering().clb_nlist;
if (is_flat) {
VTR_LOG_WARN("Disabling port equivalence in the architecture since flat routing is enabled.\n");
unset_port_equivalences(g_vpr_ctx.mutable_device());
}
RouteStatus route_status;
{ //Route
route_status = vpr_route_flow(router_net_list, vpr_setup, arch, is_flat);
Expand Down
4 changes: 2 additions & 2 deletions vpr/src/pack/cluster_legalizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1571,8 +1571,7 @@ void ClusterLegalizer::clean_cluster(LegalizationClusterId cluster_id) {
// Load the pb_route so we can free the cluster router data.
// The pb_route is used when creating a netlist from the legalized clusters.
std::vector<t_intra_lb_net>* saved_lb_nets = cluster.router_data->saved_lb_nets;
t_pb_graph_node* pb_graph_node = cluster.pb->pb_graph_node;
cluster.pb->pb_route = alloc_and_load_pb_route(saved_lb_nets, pb_graph_node);
cluster.pb->pb_route = alloc_and_load_pb_route(saved_lb_nets, cluster.type, intra_lb_pb_pin_lookup_);
// Free the router data.
free_router_data(cluster.router_data);
cluster.router_data = nullptr;
Expand Down Expand Up @@ -1632,6 +1631,7 @@ ClusterLegalizer::ClusterLegalizer(const AtomNetlist& atom_netlist,
log_verbosity_ = log_verbosity;
VTR_ASSERT(g_vpr_ctx.atom().lookup().atom_pb_bimap().is_empty());
atom_pb_lookup_ = AtomPBBimap();
intra_lb_pb_pin_lookup_ = IntraLbPbPinLookup(g_vpr_ctx.device().logical_block_types);
}

void ClusterLegalizer::reset() {
Expand Down
6 changes: 6 additions & 0 deletions vpr/src/pack/cluster_legalizer.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "vtr_vector.h"
#include "vtr_vector_map.h"
#include "atom_pb_bimap.h"
#include "vpr_utils.h"

// Forward declarations
class Prepacker;
Expand Down Expand Up @@ -524,6 +525,8 @@ class ClusterLegalizer {
inline const AtomPBBimap& atom_pb_lookup() const { return atom_pb_lookup_; }
inline AtomPBBimap& mutable_atom_pb_lookup() { return atom_pb_lookup_; }

inline const IntraLbPbPinLookup& intra_lb_pb_pin_lookup() const { return intra_lb_pb_pin_lookup_; }

/// @brief Destructor of the class. Frees allocated data.
~ClusterLegalizer();

Expand Down Expand Up @@ -595,4 +598,7 @@ class ClusterLegalizer {
/// @brief A two way map between AtomBlockIds and pb types. This is a copy
/// of the AtomPBBimap in the global context's AtomLookup
AtomPBBimap atom_pb_lookup_;

/// @brief A lookup table for the pin mapping of the intra-lb pb pins.
IntraLbPbPinLookup intra_lb_pb_pin_lookup_;
};
44 changes: 33 additions & 11 deletions vpr/src/pack/cluster_router.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,23 @@ static bool is_route_success(t_lb_router_data* router_data);
static t_lb_trace* find_node_in_rt(t_lb_trace* rt, int rt_index);
static void reset_explored_node_tb(t_lb_router_data* router_data);
static void save_and_reset_lb_route(t_lb_router_data* router_data);
static void load_trace_to_pb_route(t_pb_routes& pb_route, const int total_pins, const AtomNetId net_id, const int prev_pin_id, const t_lb_trace* trace);

/**
* @brief Recurse through route tree trace to populate pb pin to atom net lookup array.
*
* @param pb_route Array of pb pin to atom net lookup to be populated in this routine.
* @param net_id Atom net ID of the current net.
* @param prev_pin_id ID of the previous pin in the route tree trace.
* @param trace Current trace node in the route tree.
* @param logic_block_type Logic block type of the current cluster.
* @param intra_lb_pb_pin_lookup Intra-logic block pin lookup to get t_pb_graph_pin from a pin ID.
*/
static void load_trace_to_pb_route(t_pb_routes& pb_route,
const AtomNetId net_id,
const int prev_pin_id,
const t_lb_trace* trace,
t_logical_block_type_ptr logic_block_type,
const IntraLbPbPinLookup& intra_lb_pb_pin_lookup);

static std::string describe_lb_type_rr_node(int inode,
const t_lb_router_data* router_data);
Expand Down Expand Up @@ -543,15 +559,14 @@ bool try_intra_lb_route(t_lb_router_data* router_data,
* Accessor Functions
******************************************************************************************/

/* Creates an array [0..num_pb_graph_pins-1] lookup for intra-logic block routing. Given pb_graph_pin id for clb, lookup atom net that uses that pin.
* If pin is not used, stores OPEN at that pin location */
t_pb_routes alloc_and_load_pb_route(const std::vector<t_intra_lb_net>* intra_lb_nets, t_pb_graph_node* pb_graph_head) {
t_pb_routes alloc_and_load_pb_route(const std::vector<t_intra_lb_net>* intra_lb_nets,
t_logical_block_type_ptr logic_block_type,
const IntraLbPbPinLookup& intra_lb_pb_pin_lookup) {
const std::vector<t_intra_lb_net>& lb_nets = *intra_lb_nets;
int total_pins = pb_graph_head->total_pb_pins;
t_pb_routes pb_route;

for (int inet = 0; inet < (int)lb_nets.size(); inet++) {
load_trace_to_pb_route(pb_route, total_pins, lb_nets[inet].atom_net_id, OPEN, lb_nets[inet].rt_tree);
for (const auto& lb_net : lb_nets) {
load_trace_to_pb_route(pb_route, lb_net.atom_net_id, OPEN, lb_net.rt_tree, logic_block_type, intra_lb_pb_pin_lookup);
}

return pb_route;
Expand Down Expand Up @@ -581,24 +596,31 @@ void free_intra_lb_nets(std::vector<t_intra_lb_net>* intra_lb_nets) {
* Internal Functions
****************************************************************************/

/* Recurse through route tree trace to populate pb pin to atom net lookup array */
static void load_trace_to_pb_route(t_pb_routes& pb_route, const int total_pins, const AtomNetId net_id, const int prev_pin_id, const t_lb_trace* trace) {
static void load_trace_to_pb_route(t_pb_routes& pb_route,
const AtomNetId net_id,
const int prev_pin_id,
const t_lb_trace* trace,
t_logical_block_type_ptr logic_block_type,
const IntraLbPbPinLookup& intra_lb_pb_pin_lookup) {
int ipin = trace->current_node;
int driver_pb_pin_id = prev_pin_id;
int cur_pin_id = OPEN;
const int total_pins = logic_block_type->pb_graph_head->total_pb_pins;
if (ipin < total_pins) {
/* This routing node corresponds with a pin. This node is virtual (ie. sink or source node) */
cur_pin_id = ipin;
if (!pb_route.count(ipin)) {
pb_route.insert(std::make_pair(cur_pin_id, t_pb_route()));
pb_route[cur_pin_id].atom_net_id = net_id;
pb_route[cur_pin_id].driver_pb_pin_id = driver_pb_pin_id;
const t_pb_graph_pin* pb_graph_pin = intra_lb_pb_pin_lookup.pb_gpin(logic_block_type->index, cur_pin_id);
pb_route[cur_pin_id].pb_graph_pin = pb_graph_pin;
} else {
VTR_ASSERT(pb_route[cur_pin_id].atom_net_id == net_id);
}
}
for (int itrace = 0; itrace < (int)trace->next_nodes.size(); itrace++) {
load_trace_to_pb_route(pb_route, total_pins, net_id, cur_pin_id, &trace->next_nodes[itrace]);
for (const auto& nxt_trace : trace->next_nodes) {
load_trace_to_pb_route(pb_route, net_id, cur_pin_id, &nxt_trace, logic_block_type, intra_lb_pb_pin_lookup);
}
}

Expand Down
15 changes: 13 additions & 2 deletions vpr/src/pack/cluster_router.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,19 @@ void set_reset_pb_modes(t_lb_router_data* router_data, const t_pb* pb, const boo
bool try_intra_lb_route(t_lb_router_data* router_data, int verbosity, t_mode_selection_status* mode_status);
void reset_intra_lb_route(t_lb_router_data* router_data);

/* Accessor Functions */
t_pb_routes alloc_and_load_pb_route(const std::vector<t_intra_lb_net>* intra_lb_nets, t_pb_graph_node* pb_graph_head);
/**
* @brief Creates an array [0..num_pb_graph_pins-1] for intra-logic block routing lookup.
* Given a pb_graph_pin ID for a CLB, this lookup returns t_pb_route corresponding to that
* pin.
*
* @param intra_lb_nets Vector of intra-logic block nets.
* @param logic_block_type Logic block type of the current cluster.
* @param intra_lb_pb_pin_lookup Intra-logic block pin lookup to get t_pb_graph_pin from a pin ID.
* @return t_pb_routes An array [0..num_pb_graph_pins-1] for intra-logic block routing lookup.
*/
t_pb_routes alloc_and_load_pb_route(const std::vector<t_intra_lb_net>* intra_lb_nets,
t_logical_block_type_ptr logic_block_type,
const IntraLbPbPinLookup& intra_lb_pb_pin_lookup);
void free_pb_route(t_pb_route* free_pb_route);

#endif
1 change: 1 addition & 0 deletions vpr/src/pack/post_routing_pb_pin_fixup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1033,6 +1033,7 @@ void sync_netlists_to_routing(const Netlist<>& net_list,
/* Create net-to-rr_node mapping */
vtr::vector<RRNodeId, ClusterNetId> rr_node_nets = annotate_rr_node_nets(clustering_ctx,
device_ctx,
atom_ctx,
verbose);

IntraLbPbPinLookup intra_lb_pb_pin_lookup(device_ctx.logical_block_types);
Expand Down
89 changes: 46 additions & 43 deletions vpr/src/pack/sync_netlists_to_routing_flat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,23 +42,6 @@ static void fixup_atom_pb_graph_pin_mapping(void);

/* Function definitions */

/** Is the clock net found in the routing results?
* (If not, clock_modeling is probably ideal and we should preserve clock routing while rebuilding.) */
inline bool is_clock_net_routed(void) {
auto& atom_ctx = g_vpr_ctx.atom();
auto& route_ctx = g_vpr_ctx.routing();

for (auto net_id : atom_ctx.netlist().nets()) {
auto& tree = route_ctx.route_trees[net_id];
if (!tree)
continue;
if (route_ctx.is_clock_net[net_id]) /* Clock net has routing */
return true;
}

return false;
}

/** Get the ClusterBlockId for a given RRNodeId. */
inline ClusterBlockId get_cluster_block_from_rr_node(RRNodeId inode) {
auto& device_ctx = g_vpr_ctx.device();
Expand Down Expand Up @@ -185,18 +168,22 @@ static void sync_pb_routes_to_routing(void) {
auto& route_ctx = g_vpr_ctx.routing();
auto& rr_graph = device_ctx.rr_graph;

/* Was the clock net routed? */
bool clock_net_is_routed = is_clock_net_routed();

/* Clear out existing pb_routes: they were made by the intra cluster router and are invalid now */
for (ClusterBlockId clb_blk_id : cluster_ctx.clb_nlist.blocks()) {
/* If we don't have routing for the clock net, don't erase entries associated with a clock net.
* Otherwise we won't have data to rebuild them */
/* Don't erase entries for nets without routing in place (clocks, globals...) */
std::vector<int> pins_to_erase;
auto& pb_routes = cluster_ctx.clb_nlist.block_pb(clb_blk_id)->pb_route;
t_pb_routes& pb_routes = cluster_ctx.clb_nlist.block_pb(clb_blk_id)->pb_route;
for (auto& [pin, pb_route] : pb_routes) {
if (clock_net_is_routed || !route_ctx.is_clock_net[pb_route.atom_net_id])
pins_to_erase.push_back(pin);
/*
* Given that this function is called when flat routing is enabled,
* we can safely assume that the net IDs to index into route_ctx.route_trees
* correspond to the atom net IDs.
*/
if (!route_ctx.route_trees[pb_route.atom_net_id]) {
/* No route tree: no routing in place, it is global or clock */
continue;
}
pins_to_erase.push_back(pin);
}

for (int pin : pins_to_erase) {
Expand Down Expand Up @@ -276,37 +263,37 @@ static void sync_clustered_netlist_to_routing(void) {
auto& atom_ctx = g_vpr_ctx.mutable_atom();
auto& atom_lookup = atom_ctx.lookup();

bool clock_net_is_routed = is_clock_net_routed();

/* 1. Remove all nets, pins and ports from the clustered netlist.
* If the clock net is not routed, don't remove entries for the clock net
* otherwise we won't have data to rebuild them. */
* Do not remove entries for nets without an existing route tree,
* since we don't have the information to rebuild those parts. */
std::vector<ClusterNetId> nets_to_remove;
std::vector<ClusterPinId> pins_to_remove;
std::vector<ClusterPortId> ports_to_remove;

for (auto net_id : clb_netlist.nets()) {
auto atom_net_id = atom_lookup.atom_net(net_id);
if (!clock_net_is_routed && route_ctx.is_clock_net[atom_net_id])
if (!route_ctx.route_trees[atom_net_id])
continue;

nets_to_remove.push_back(net_id);
}
for (auto pin_id : clb_netlist.pins()) {
ClusterNetId clb_net_id = clb_netlist.pin_net(pin_id);
auto atom_net_id = atom_lookup.atom_net(clb_net_id);
if (!clock_net_is_routed && atom_net_id && route_ctx.is_clock_net[atom_net_id])
continue;

pins_to_remove.push_back(pin_id);
}
/* Mark ports and pins for removal. Don't remove a port if
* it has at least one pin remaining */
for (auto port_id : clb_netlist.ports()) {
ClusterNetId clb_net_id = clb_netlist.port_net(port_id, 0);
auto atom_net_id = atom_lookup.atom_net(clb_net_id);
if (!clock_net_is_routed && atom_net_id && route_ctx.is_clock_net[atom_net_id])
continue;
size_t skipped_pins = 0;

for (auto pin_id : clb_netlist.port_pins(port_id)) {
ClusterNetId clb_net_id = clb_netlist.pin_net(pin_id);
auto atom_net_id = atom_lookup.atom_net(clb_net_id);
if (atom_net_id && !route_ctx.route_trees[atom_net_id]) {
skipped_pins++;
} else {
pins_to_remove.push_back(pin_id);
}
}

ports_to_remove.push_back(port_id);
if (!skipped_pins) // All pins have been removed, remove port
ports_to_remove.push_back(port_id);
}

/* ClusteredNetlist's iterators rely on internal lookups, so we mark for removal
Expand Down Expand Up @@ -363,6 +350,7 @@ static void sync_clustered_netlist_to_routing(void) {

t_pb_graph_pin* pb_graph_pin = get_pb_graph_node_pin_from_block_pin(clb, pin_index);

/* Get or create port */
ClusterPortId port_id = clb_netlist.find_port(clb, pb_graph_pin->port->name);
if (!port_id) {
PortType port_type;
Expand All @@ -378,6 +366,15 @@ static void sync_clustered_netlist_to_routing(void) {
}
PinType pin_type = node_type == e_rr_type::OPIN ? PinType::DRIVER : PinType::SINK;

/* Pin already exists. This means a global net that was not routed (i.e. 'ideal' mode). */
if (clb_netlist.port_pin(port_id, pb_graph_pin->pin_number)) {
VTR_LOG_WARN("Pin %s of block %s has a global or clock net"
" connected and it has a routing clash with the flat router."
" This may cause inconsistent results.\n",
pb_graph_pin->to_string().c_str(),
clb_netlist.block_name(clb).c_str());
continue;
}
ClusterPinId new_pin = clb_netlist.create_pin(port_id, pb_graph_pin->pin_number, clb_net_id, pin_type, pb_graph_pin->pin_count_in_cluster);
clb_netlist.set_pin_net(new_pin, pin_type, clb_net_id);
}
Expand Down Expand Up @@ -419,6 +416,12 @@ static void fixup_atom_pb_graph_pin_mapping(void) {

/* Find atom port from pbg pin's model port */
AtomPortId atom_port = atom_ctx.netlist().find_atom_port(atb, atom_pbg_pin->port->model_port);

/* Not an equivalent port, so no need to do fixup */
if (atom_pbg_pin->port->equivalent != PortEquivalence::FULL) {
continue;
}

for (AtomPinId atom_pin : atom_ctx.netlist().port_pins(atom_port)) {
/* Match net IDs from pb_route and atom netlist and connect in lookup */
if (pb_route.atom_net_id == atom_ctx.netlist().pin_net(atom_pin)) {
Expand Down
Loading