diff --git a/vpr/src/base/atom_lookup.cpp b/vpr/src/base/atom_lookup.cpp index 8f8195e60e8..f771b8af154 100644 --- a/vpr/src/base/atom_lookup.cpp +++ b/vpr/src/base/atom_lookup.cpp @@ -1,5 +1,7 @@ +#include "clustered_netlist_fwd.h" #include "vtr_assert.h" #include "vtr_log.h" +#include "vtr_optional.h" #include "atom_lookup.h" /* @@ -85,35 +87,51 @@ void AtomLookup::set_atom_clb(const AtomBlockId blk_id, const ClusterBlockId clb * Nets */ AtomNetId AtomLookup::atom_net(const ClusterNetId clb_net_index) const { - auto iter = atom_net_to_clb_net_.find(clb_net_index); - if (iter == atom_net_to_clb_net_.inverse_end()) { + auto iter = clb_net_to_atom_net_.find(clb_net_index); + if (iter == clb_net_to_atom_net_.end()) { //Not found return AtomNetId::INVALID(); } return iter->second; } -ClusterNetId AtomLookup::clb_net(const AtomNetId net_id) const { - auto iter = atom_net_to_clb_net_.find(net_id); - if (iter == atom_net_to_clb_net_.end()) { +vtr::optional&> AtomLookup::clb_nets(const AtomNetId atom_net) const { + auto iter = atom_net_to_clb_nets_.find(atom_net); + if (iter == atom_net_to_clb_nets_.end()) { //Not found - return ClusterNetId::INVALID(); + return vtr::nullopt; } return iter->second; } -void AtomLookup::set_atom_clb_net(const AtomNetId net_id, const ClusterNetId clb_net_index) { - //If either are invalid remove any mapping - if (!net_id && clb_net_index != ClusterNetId::INVALID()) { - //Remove - atom_net_to_clb_net_.erase(clb_net_index); - } else if (net_id && clb_net_index == ClusterNetId::INVALID()) { - //Remove - atom_net_to_clb_net_.erase(net_id); - } else if (net_id && clb_net_index != ClusterNetId::INVALID()) { - //Store - atom_net_to_clb_net_.update(net_id, clb_net_index); +void AtomLookup::add_atom_clb_net(const AtomNetId atom_net, const ClusterNetId clb_net) { + VTR_ASSERT(atom_net && clb_net); + + /* Use the default behavior of [] operator */ + atom_net_to_clb_nets_[atom_net].push_back(clb_net); + clb_net_to_atom_net_[clb_net] = atom_net; +} + +void AtomLookup::remove_clb_net(const ClusterNetId clb_net){ + if(!clb_net_to_atom_net_.count(clb_net)) + return; + + auto atom_net = clb_net_to_atom_net_[clb_net]; + auto& all_clb_nets = atom_net_to_clb_nets_[atom_net]; + /* This is o(n), but an AtomNetId rarely has >5 ClusterNetIds */ + all_clb_nets.erase(std::remove(all_clb_nets.begin(), all_clb_nets.end(), clb_net), all_clb_nets.end()); +} + +/* Remove mapping for given atom net */ +void AtomLookup::remove_atom_net(const AtomNetId atom_net) { + if(!atom_net_to_clb_nets_.count(atom_net)) + return; + + auto cluster_nets = atom_net_to_clb_nets_[atom_net]; + for(auto c: cluster_nets){ + clb_net_to_atom_net_.erase(c); } + atom_net_to_clb_nets_.erase(atom_net); } /* diff --git a/vpr/src/base/atom_lookup.h b/vpr/src/base/atom_lookup.h index c87807056f8..fdf17cddd46 100644 --- a/vpr/src/base/atom_lookup.h +++ b/vpr/src/base/atom_lookup.h @@ -13,6 +13,8 @@ #include "vpr_types.h" #include "tatum/TimingGraphFwd.hpp" +#include "vtr_optional.h" + /** * @brief The AtomLookup class describes the mapping between components in the AtomNetlist * and other netlists/entities (i.e. atom block <-> t_pb, atom block <-> clb) @@ -76,17 +78,21 @@ class AtomLookup { */ ///@brief Returns the atom net id associated with the clb_net_index - AtomNetId atom_net(const ClusterNetId clb_net_index) const; + AtomNetId atom_net(const ClusterNetId cluster_net_id) const; - ///@brief Returns the clb net index associated with net_id - ClusterNetId clb_net(const AtomNetId net_id) const; + ///@brief Returns the clb net indices associated with atom_net_id + vtr::optional&> clb_nets(const AtomNetId atom_net_id) const; /** * @brief Sets the bidirectional mapping between an atom net and a clb net - * - * If either net_id or clb_net_index are not valid any existing mapping is removed */ - void set_atom_clb_net(const AtomNetId net_id, const ClusterNetId clb_net_index); + void add_atom_clb_net(const AtomNetId atom_net, const ClusterNetId clb_net); + + /** Remove given clb net from the mapping */ + void remove_clb_net(const ClusterNetId clb_net); + + /** Remove given atom net from the mapping */ + void remove_atom_net(const AtomNetId atom_net); /* * Timing Nodes @@ -112,7 +118,8 @@ class AtomLookup { vtr::vector_map atom_to_clb_; - vtr::bimap atom_net_to_clb_net_; + vtr::linear_map> atom_net_to_clb_nets_; + vtr::linear_map clb_net_to_atom_net_; vtr::linear_map atom_pin_tnode_external_; vtr::linear_map atom_pin_tnode_internal_; diff --git a/vpr/src/base/read_netlist.cpp b/vpr/src/base/read_netlist.cpp index 6aee712a04b..4f2d5f6da06 100644 --- a/vpr/src/base/read_netlist.cpp +++ b/vpr/src/base/read_netlist.cpp @@ -218,14 +218,14 @@ ClusteredNetlist read_netlist(const char* net_file, /* load mapping between external nets and all nets */ for (auto net_id : atom_ctx.nlist.nets()) { - atom_ctx.lookup.set_atom_clb_net(net_id, ClusterNetId::INVALID()); + atom_ctx.lookup.remove_atom_net(net_id); } //Save the mapping between clb and atom nets for (auto clb_net_id : clb_nlist.nets()) { AtomNetId net_id = atom_ctx.nlist.find_net(clb_nlist.net_name(clb_net_id)); VTR_ASSERT(net_id); - atom_ctx.lookup.set_atom_clb_net(net_id, clb_net_id); + atom_ctx.lookup.add_atom_clb_net(net_id, clb_net_id); } // Mark ignored and global atom nets diff --git a/vpr/src/draw/search_bar.cpp b/vpr/src/draw/search_bar.cpp index 756dfd9d976..c97aeea3336 100644 --- a/vpr/src/draw/search_bar.cpp +++ b/vpr/src/draw/search_bar.cpp @@ -167,8 +167,9 @@ void search_and_highlight(GtkWidget* /*widget*/, ezgl::application* app) { warning_dialog_box("Invalid Net Name"); return; //name not exist } - ClusterNetId clb_net_id = atom_ctx.lookup.clb_net(atom_net_id); - highlight_nets(clb_net_id); + for(auto clb_net_id: atom_ctx.lookup.clb_nets(atom_net_id).value()){ + highlight_nets(clb_net_id); + } } else diff --git a/vpr/src/pack/pack.cpp b/vpr/src/pack/pack.cpp index e8c68ea2244..04574974c1f 100644 --- a/vpr/src/pack/pack.cpp +++ b/vpr/src/pack/pack.cpp @@ -225,7 +225,7 @@ bool try_pack(t_packer_opts* packer_opts, g_vpr_ctx.mutable_atom().lookup.set_atom_pb(blk, nullptr); } for (auto net : g_vpr_ctx.atom().nlist.nets()) { - g_vpr_ctx.mutable_atom().lookup.set_atom_clb_net(net, ClusterNetId::INVALID()); + g_vpr_ctx.mutable_atom().lookup.remove_atom_net(net); } g_vpr_ctx.mutable_floorplanning().cluster_constraints.clear(); //attraction_groups.reset_attraction_groups(); diff --git a/vpr/src/pack/re_cluster_util.cpp b/vpr/src/pack/re_cluster_util.cpp index 46eb04955a5..5d121565e20 100644 --- a/vpr/src/pack/re_cluster_util.cpp +++ b/vpr/src/pack/re_cluster_util.cpp @@ -437,7 +437,8 @@ static void fix_cluster_pins_after_moving(const ClusterBlockId clb_index) { atom_net_id = pb->pb_route[rr_node_index].atom_net_id; if (atom_net_id) { clb_net_id = cluster_ctx.clb_nlist.create_net(atom_ctx.nlist.net_name(atom_net_id)); - atom_ctx.lookup.set_atom_clb_net(atom_net_id, clb_net_id); + atom_ctx.lookup.remove_atom_net(atom_net_id); + atom_ctx.lookup.add_atom_clb_net(atom_net_id, clb_net_id); ClusterPinId cur_pin_id = cluster_ctx.clb_nlist.find_pin(input_port_id, (BitIndex)ipb_pin); if (!cur_pin_id) cluster_ctx.clb_nlist.create_pin(input_port_id, (BitIndex)ipb_pin, clb_net_id, PinType::SINK, ipin); @@ -463,7 +464,8 @@ static void fix_cluster_pins_after_moving(const ClusterBlockId clb_index) { atom_net_id = pb->pb_route[rr_node_index].atom_net_id; if (atom_net_id) { clb_net_id = cluster_ctx.clb_nlist.create_net(atom_ctx.nlist.net_name(atom_net_id)); - atom_ctx.lookup.set_atom_clb_net(atom_net_id, clb_net_id); + atom_ctx.lookup.remove_atom_net(atom_net_id); + atom_ctx.lookup.add_atom_clb_net(atom_net_id, clb_net_id); ClusterPinId cur_pin_id = cluster_ctx.clb_nlist.find_pin(output_port_id, (BitIndex)ipb_pin); AtomPinId atom_net_driver = atom_ctx.nlist.net_driver(atom_net_id); bool driver_is_constant = atom_ctx.nlist.pin_is_constant(atom_net_driver); @@ -494,7 +496,8 @@ static void fix_cluster_pins_after_moving(const ClusterBlockId clb_index) { atom_net_id = pb->pb_route[rr_node_index].atom_net_id; if (atom_net_id) { clb_net_id = cluster_ctx.clb_nlist.create_net(atom_ctx.nlist.net_name(atom_net_id)); - atom_ctx.lookup.set_atom_clb_net(atom_net_id, clb_net_id); + atom_ctx.lookup.remove_atom_net(atom_net_id); + atom_ctx.lookup.add_atom_clb_net(atom_net_id, clb_net_id); ClusterPinId cur_pin_id = cluster_ctx.clb_nlist.find_pin(clock_port_id, (BitIndex)ipb_pin); if (!cur_pin_id) cluster_ctx.clb_nlist.create_pin(clock_port_id, (BitIndex)ipb_pin, clb_net_id, PinType::SINK, ipin); @@ -518,7 +521,8 @@ static std::pair check_net_absorption(const AtomNetId atom_net_id, AtomBlockId atom_block_id; ClusterBlockId clb_index; - ClusterNetId clb_net_id = atom_ctx.lookup.clb_net(atom_net_id); + /* XXX: Do this properly instead of grabbing the first associated clb net */ + ClusterNetId clb_net_id = atom_ctx.lookup.clb_nets(atom_net_id).value()[0]; bool previously_absorbed; if (clb_net_id == ClusterNetId::INVALID()) diff --git a/vpr/src/pack/sync_netlists_to_routing_flat.cpp b/vpr/src/pack/sync_netlists_to_routing_flat.cpp index 16d5c9de113..a0461f2e8c2 100644 --- a/vpr/src/pack/sync_netlists_to_routing_flat.cpp +++ b/vpr/src/pack/sync_netlists_to_routing_flat.cpp @@ -267,11 +267,15 @@ inline void rebuild_atom_nets_lookup(ClusteredNetlist::IdRemapper& remapped){ for(auto parent_net_id: atom_ctx.nlist.nets()){ auto atom_net_id = convert_to_atom_net_id(parent_net_id); - ClusterNetId old_clb_net = atom_lookup.clb_net(atom_net_id); - if(!old_clb_net) + auto old_clb_nets_opt = atom_lookup.clb_nets(atom_net_id); + if(!old_clb_nets_opt) continue; - ClusterNetId new_clb_net = remapped.new_net_id(old_clb_net); - atom_lookup.set_atom_clb_net(atom_net_id, new_clb_net); + std::vector old_clb_nets = old_clb_nets_opt.value(); + atom_lookup.remove_atom_net(atom_net_id); + for(auto old_clb_net: old_clb_nets){ + ClusterNetId new_clb_net = remapped.new_net_id(old_clb_net); + atom_lookup.add_atom_clb_net(atom_net_id, new_clb_net); + } } } @@ -297,7 +301,7 @@ static void sync_clustered_netlist_to_routing(void){ continue; clb_netlist.remove_net(net_id); - atom_lookup.set_atom_clb_net(AtomNetId::INVALID(), net_id); + atom_lookup.remove_clb_net(net_id); } for(auto pin_id: clb_netlist.pins()){ ClusterNetId clb_net_id = clb_netlist.pin_net(pin_id); @@ -324,6 +328,7 @@ static void sync_clustered_netlist_to_routing(void){ AtomNetId atom_net_id = convert_to_atom_net_id(parent_net_id); ClusterNetId clb_net_id; + int clb_nets_so_far = 0; for(auto& rt_node: tree->all_nodes()){ auto node_type = rr_graph.node_type(rt_node.inode); if(node_type != IPIN && node_type != OPIN) @@ -349,9 +354,18 @@ static void sync_clustered_netlist_to_routing(void){ if(!is_pin_on_tile(physical_tile, pin_index)) continue; - if(!clb_net_id){ - clb_net_id = clb_netlist.create_net(atom_ctx.nlist.net_name(parent_net_id)); - atom_lookup.set_atom_clb_net(atom_net_id, clb_net_id); + /* OPIN on the tile: create a new clb_net_id and add all ports & pins into here + * Due to how the route tree is traversed, all nodes until the next OPIN on the tile will + * be under this OPIN, so this is valid (we don't need to get the branch explicitly) */ + if(node_type == OPIN){ + std::string net_name; + if(clb_nets_so_far == 0) + net_name = atom_ctx.nlist.net_name(parent_net_id); + else + net_name = atom_ctx.nlist.net_name(parent_net_id) + "_" + std::to_string(clb_nets_so_far); + clb_net_id = clb_netlist.create_net(net_name); + atom_lookup.add_atom_clb_net(atom_net_id, clb_net_id); + clb_nets_so_far++; } t_pb_graph_pin* pb_graph_pin = get_pb_graph_node_pin_from_block_pin(clb, pin_index);