diff --git a/vpr/src/tileable_rr_graph/rr_gsb.cpp b/vpr/src/tileable_rr_graph/rr_gsb.cpp index 5b558fffd..1390a9714 100644 --- a/vpr/src/tileable_rr_graph/rr_gsb.cpp +++ b/vpr/src/tileable_rr_graph/rr_gsb.cpp @@ -22,8 +22,13 @@ namespace openfpga { RRGSB::RRGSB() { /* Set a clean start! */ coordinate_.set(0, 0); + + chan_node_.clear(); chan_node_direction_.clear(); + chan_node_in_edges_.clear(); + ipin_node_.clear(); + opin_node_.clear(); } @@ -184,10 +189,10 @@ RRNodeId RRGSB::get_opin_node(const e_side& side, const size_t& node_id) const { VTR_ASSERT(side_manager.validate()); /* Ensure the side is valid in the context of this switch block */ - VTR_ASSERT( validate_side(side) ); + VTR_ASSERT(validate_side(side) ); /* Ensure the track is valid in the context of this switch block at a specific side */ - VTR_ASSERT( validate_opin_node_id(side, node_id) ); + VTR_ASSERT(validate_opin_node_id(side, node_id) ); return opin_node_[side_manager.to_size_t()][node_id]; } @@ -731,7 +736,9 @@ void RRGSB::init_num_sides(const size_t& num_sides) { } /* Add a node to the chan_node_ list and also assign its direction in chan_node_direction_ */ -void RRGSB::add_chan_node(const e_side& node_side, RRChan& rr_chan, const std::vector& rr_chan_dir) { +void RRGSB::add_chan_node(const e_side& node_side, + const RRChan& rr_chan, + const std::vector& rr_chan_dir) { /* Validate: 1. side is valid, the type of node is valid */ VTR_ASSERT(validate_side(node_side)); @@ -757,6 +764,86 @@ void RRGSB::add_opin_node(const RRNodeId& node, const e_side& node_side) { opin_node_[size_t(node_side)].push_back(node); } +void RRGSB::sort_chan_node_in_edges(const RRGraph& rr_graph, + const e_side& chan_side, + const size_t& track_id) { + std::map> from_grid_edge_map; + std::map> from_track_edge_map; + + const RRNodeId& chan_node = chan_node_[size_t(chan_side)].get_node(track_id); + + /* Count the edges and ensure every of them has been sorted */ + size_t edge_counter = 0; + + /* For each incoming edge, find the node side and index in this GSB. + * and cache these. Then we will use the data to sort the edge in the + * following sequence: + * 0----------------------------------------------------------------> num_in_edges() + * |<--TOP side-->|<--RIGHT side-->|<--BOTTOM side-->|<--LEFT side-->| + * For each side, the edge will be sorted by the node index starting from 0 + * For each side, the edge from grid pins will be the 1st part + * while the edge from routing tracks will be the 2nd part + */ + for (const RREdgeId& edge : rr_graph.node_in_edges(chan_node)) { + /* We care the source node of this edge, and it should be an input of the GSB!!! */ + const RRNodeId& src_node = rr_graph.edge_src_node(edge); + e_side side = NUM_SIDES; + int index = 0; + get_node_side_and_index(rr_graph, src_node, IN_PORT, side, index); + + /* Must have valid side and index */ + VTR_ASSERT(NUM_SIDES != side); + VTR_ASSERT(OPEN != index); + + if (OPIN == rr_graph.node_type(src_node)) { + from_grid_edge_map[side][index] = edge; + } else { + VTR_ASSERT( (CHANX == rr_graph.node_type(src_node)) + || (CHANY == rr_graph.node_type(src_node)) ); + from_track_edge_map[side][index] = edge; + } + + edge_counter++; + } + + /* Store the sorted edge */ + for (size_t side = 0; side < get_num_sides(); ++side) { + /* Edges from grid outputs are the 1st part */ + for (size_t opin_id = 0; opin_id < opin_node_[side].size(); ++opin_id) { + if ( (0 < from_grid_edge_map.count(side)) + && (0 < from_grid_edge_map.at(side).count(opin_id)) ) { + chan_node_in_edges_[size_t(chan_side)][track_id].push_back(from_grid_edge_map[side][opin_id]); + } + } + + /* Edges from routing tracks are the 2nd part */ + for (size_t itrack = 0; itrack < chan_node_[side].get_chan_width(); ++itrack) { + if ( (0 < from_track_edge_map.count(side)) + && (0 < from_track_edge_map.at(side).count(itrack)) ) { + chan_node_in_edges_[size_t(chan_side)][track_id].push_back(from_track_edge_map[side][itrack]); + } + } + } + + VTR_ASSERT(edge_counter == chan_node_in_edges_[size_t(chan_side)][track_id].size()); +} + +void RRGSB::sort_chan_node_in_edges(const RRGraph& rr_graph) { + /* Allocate here, as sort edge is optional, we do not allocate when adding nodes */ + chan_node_in_edges_.resize(get_num_sides()); + + for (size_t side = 0; side < get_num_sides(); ++side) { + SideManager side_manager(side); + chan_node_in_edges_[side].resize(chan_node_[side].get_chan_width()); + for (size_t track_id = 0; track_id < chan_node_[side].get_chan_width(); ++track_id) { + /* Only sort the output nodes */ + if (OUT_PORT == chan_node_direction_[side][track_id]) { + sort_chan_node_in_edges(rr_graph, side_manager.get_side(), track_id); + } + } + } +} + /************************************************************************ * Public Mutators: clean-up functions ***********************************************************************/ diff --git a/vpr/src/tileable_rr_graph/rr_gsb.h b/vpr/src/tileable_rr_graph/rr_gsb.h index 8d729139a..76633bcb2 100644 --- a/vpr/src/tileable_rr_graph/rr_gsb.h +++ b/vpr/src/tileable_rr_graph/rr_gsb.h @@ -173,12 +173,35 @@ class RRGSB { vtr::Point get_side_block_coordinate(const e_side& side) const; vtr::Point get_grid_coordinate() const; public: /* Mutators */ - void set(const RRGSB& src); /* get a copy from a source */ + /* get a copy from a source */ + void set(const RRGSB& src); void set_coordinate(const size_t& x, const size_t& y); - void init_num_sides(const size_t& num_sides); /* Allocate the vectors with the given number of sides */ - void add_chan_node(const e_side& node_side, RRChan& rr_chan, const std::vector& rr_chan_dir); /* Add a node to the chan_rr_node_ list and also assign its direction in chan_rr_node_direction_ */ - void add_ipin_node(const RRNodeId& node, const e_side& node_side); /* Add a node to the chan_rr_node_ list and also assign its direction in chan_rr_node_direction_ */ - void add_opin_node(const RRNodeId& node, const e_side& node_side); /* Add a node to the chan_rr_node_ list and also assign its direction in chan_rr_node_direction_ */ + + /* Allocate the vectors with the given number of sides */ + void init_num_sides(const size_t& num_sides); + + /* Add a node to the chan_rr_node_ list and also + * assign its direction in chan_rr_node_direction_ + */ + void add_chan_node(const e_side& node_side, + const RRChan& rr_chan, + const std::vector& rr_chan_dir); + + /* Add a node to the chan_rr_node_ list and also + * assign its direction in chan_rr_node_direction_ + */ + void add_ipin_node(const RRNodeId& node, + const e_side& node_side); + + /* Add a node to the chan_rr_node_ list and also + * assign its direction in chan_rr_node_direction_ + */ + void add_opin_node(const RRNodeId& node, + const e_side& node_side); + + /* Sort all the incoming edges for routing channel rr_node */ + void sort_chan_node_in_edges(const RRGraph& rr_graph); + public: /* Mutators: cleaners */ void clear(); @@ -193,6 +216,13 @@ class RRGSB { /* Clean chan/opin/ipin nodes at one side */ void clear_one_side(const e_side& node_side); + + private: /* Private Mutators: edge sorting */ + /* Sort all the incoming edges for one channel rr_node */ + void sort_chan_node_in_edges(const RRGraph& rr_graph, + const e_side& chan_side, + const size_t& track_id); + private: /* internal functions */ bool is_sb_node_mirror(const RRGraph& rr_graph, const RRGSB& cand, @@ -217,10 +247,29 @@ class RRGSB { private: /* Internal Data */ /* Coordinator */ vtr::Point coordinate_; - /* Routing channel data */ + + /* Routing channel data + * Each GSB may have four sides of routing track nodes + */ + /* Node id in rr_graph denoting each routing track */ std::vector chan_node_; + + /* Direction of a port when the channel node appear in the GSB module */ std::vector> chan_node_direction_; + /* Sequence of edge ids for each routing channel node, + * this is sorted by the location of edge source nodes in the context of GSB + * The edge sorting is critical to uniquify the routing modules in OpenFPGA + * This is due to that VPR allocate and sort edges randomly when building the rr_graph + * As a result, previous nodes of a chan node may be the same in different GSBs + * but their sequence is not. This will cause graph comparison to fail when uniquifying + * the routing modules. Therefore, edge sorting can be done inside the GSB + * + * Storage organization: + * [chan_side][chan_node][edge_id_in_gsb_context] + */ + std::vector>> chan_node_in_edges_; + /* Logic Block Inputs data */ std::vector> ipin_node_;