From b7cba400c43153ac9640fc9da0304952d276c018 Mon Sep 17 00:00:00 2001 From: taoli4rs Date: Thu, 16 Jun 2022 19:12:16 -0700 Subject: [PATCH 001/147] WIP: Allow source node query in rr graph view. --- libs/librrgraph/src/base/rr_graph_storage.h | 19 ++++-- libs/librrgraph/src/base/rr_graph_view.h | 67 ++++++++++++--------- 2 files changed, 52 insertions(+), 34 deletions(-) diff --git a/libs/librrgraph/src/base/rr_graph_storage.h b/libs/librrgraph/src/base/rr_graph_storage.h index 63dc4c9b38d..d67f0d3ce32 100644 --- a/libs/librrgraph/src/base/rr_graph_storage.h +++ b/libs/librrgraph/src/base/rr_graph_storage.h @@ -63,13 +63,13 @@ struct alignas(16) t_rr_node_data { t_rr_type type_ = NUM_RR_TYPES; /* The character is a hex number which is a 4-bit truth table for node sides - * The 4-bits in serial represent 4 sides on which a node could appear - * It follows a fixed sequence, which is (LEFT, BOTTOM, RIGHT, TOP) whose indices are (3, 2, 1, 0) + * The 4-bits in serial represent 4 sides on which a node could appear + * It follows a fixed sequence, which is (LEFT, BOTTOM, RIGHT, TOP) whose indices are (3, 2, 1, 0) * - When a node appears on a given side, it is set to "1" * - When a node does not appear on a given side, it is set to "0" * For example, - * - '1' means '0001' in hex number, which means the node appears on TOP - * - 'A' means '1100' in hex number, which means the node appears on LEFT and BOTTOM sides, + * - '1' means '0001' in hex number, which means the node appears on TOP + * - 'A' means '1100' in hex number, which means the node appears on LEFT and BOTTOM sides, */ union { Direction direction; //Valid only for CHANX/CHANY @@ -252,6 +252,7 @@ class t_rr_graph_storage { * - num_non_configurable_edges(RRNodeId) * - edge_id(RRNodeId, t_edge_size) * - edge_sink_node(RRNodeId, t_edge_size) + * - edge_source_node(RRNodeId, t_edge_size) * - edge_switch(RRNodeId, t_edge_size) * * Only call these methods after partition_edges has been invoked. */ @@ -316,6 +317,11 @@ class t_rr_graph_storage { return edge_dest_node_[edge]; } + // Get the source node for the specified edge. + RRNodeId edge_source_node(const RREdgeId& edge) const { + return edge_src_node_[edge]; + } + // Call the `apply` function with the edge id, source, and sink nodes of every edge. void for_each_edge(std::function apply) const { for (size_t i = 0; i < edge_dest_node_.size(); i++) { @@ -332,6 +338,11 @@ class t_rr_graph_storage { return edge_sink_node(edge_id(id, iedge)); } + // Get the source node for the iedge'th edge from specified RRNodeId. + RRNodeId edge_source_node(const RRNodeId& id, t_edge_size iedge) const { + return edge_source_node(edge_id(id, iedge)); + } + // Get the switch used for the specified edge. short edge_switch(const RREdgeId& edge) const { return edge_switch_[edge]; diff --git a/libs/librrgraph/src/base/rr_graph_view.h b/libs/librrgraph/src/base/rr_graph_view.h index 1c7e88260db..6d0c995864b 100644 --- a/libs/librrgraph/src/base/rr_graph_view.h +++ b/libs/librrgraph/src/base/rr_graph_view.h @@ -25,9 +25,9 @@ * - This avoids massive changes for each client on using the APIs * as each frame view provides adhoc APIs for each client * - * TODO: more compact frame views will be created, e.g., + * TODO: more compact frame views will be created, e.g., * - a mini frame view: contains only node and edges, representing the connectivity of the graph - * - a geometry frame view: an extended mini frame view with node-level attributes, + * - a geometry frame view: an extended mini frame view with node-level attributes, * in particular geometry information (type, x, y etc). * */ @@ -45,29 +45,29 @@ class RRGraphView { const vtr::vector& rr_switch_inf); /* Disable copy constructors and copy assignment operator - * This is to avoid accidental copy because it could be an expensive operation considering that the + * This is to avoid accidental copy because it could be an expensive operation considering that the * memory footprint of the data structure could ~ Gb - * Using the following syntax, we prohibit accidental 'pass-by-value' which can be immediately caught + * Using the following syntax, we prohibit accidental 'pass-by-value' which can be immediately caught * by compiler */ RRGraphView(const RRGraphView&) = delete; void operator=(const RRGraphView&) = delete; /* -- Accessors -- */ - /* TODO: The accessors may be turned into private later if they are replacable by 'questionin' + /* TODO: The accessors may be turned into private later if they are replacable by 'questionin' * kind of accessors */ public: /* Aggregates: create range-based loops for nodes - * To iterate over the nodes in a RRGraph, - * using a range-based loop is suggested. - * ----------------------------------------------------------------- - * Example: iterate over all the nodes - * // Strongly suggest to use a read-only rr_graph object - * const RRGraph& rr_graph; - * for (const RRNodeId& node : rr_graph.nodes()) { - * // Do something with each node - * } + * To iterate over the nodes in a RRGraph, + * using a range-based loop is suggested. + * ----------------------------------------------------------------- + * Example: iterate over all the nodes + * // Strongly suggest to use a read-only rr_graph object + * const RRGraph& rr_graph; + * for (const RRNodeId& node : rr_graph.nodes()) { + * // Do something with each node + * } */ inline vtr::StrongIdRange nodes() const { return vtr::StrongIdRange(RRNodeId(0), RRNodeId(num_nodes())); @@ -188,7 +188,7 @@ class RRGraphView { && (node_xhigh(node) == -1) && (node_yhigh(node) == -1)); } - /** @brief Check if two routing resource nodes are adjacent (must be a CHANX and a CHANY). + /** @brief Check if two routing resource nodes are adjacent (must be a CHANX and a CHANY). * This function is used for error checking; it checks if two nodes are physically adjacent (could be connected) based on their geometry. * It does not check the routing edges to see if they are, in fact, possible to connect in the current routing graph. * This function is inlined for runtime optimization. */ @@ -203,7 +203,7 @@ class RRGraphView { return true; } - /** @brief Check if node is within bounding box. + /** @brief Check if node is within bounding box. * To return true, the RRNode must be completely contained within the specified bounding box, with the edges of the bounding box being inclusive. *This function is inlined for runtime optimization. */ inline bool node_is_inside_bounding_box(RRNodeId node, vtr::Rect bounding_box) const { @@ -307,6 +307,13 @@ class RRGraphView { return node_storage_.edge_sink_node(id, iedge); } + /** @brief Get the source node for the iedge'th edge from specified RRNodeId. + * This method should generally not be used, and instead first_edge and + * last_edge should be used.*/ + inline RRNodeId edge_source_node(RRNodeId id, t_edge_size iedge) const { + return node_storage_.edge_source_node(id, iedge); + } + /** @brief Detect if the edge is a configurable edge (controlled by a programmable routing multipler or a tri-state switch). */ inline bool edge_is_configurable(RRNodeId id, t_edge_size iedge) const { return node_storage_.edge_is_configurable(id, iedge, rr_switch_inf_); @@ -322,16 +329,16 @@ class RRGraphView { return node_storage_.num_non_configurable_edges(node, rr_switch_inf_); } - /** @brief A configurable edge represents a programmable switch between routing resources, which could be + /** @brief A configurable edge represents a programmable switch between routing resources, which could be * a multiplexer * a tri-state buffer - * a pass gate + * a pass gate * This API gets ID range for configurable edges. This function is inlined for runtime optimization. */ inline edge_idx_range configurable_edges(RRNodeId node) const { return vtr::make_range(edge_idx_iterator(0), edge_idx_iterator(node_storage_.num_edges(node) - num_non_configurable_edges(node))); } - /** @brief A non-configurable edge represents a hard-wired connection between routing resources, which could be + /** @brief A non-configurable edge represents a hard-wired connection between routing resources, which could be * a non-configurable buffer that can not be turned off * a short metal connection that can not be turned off * This API gets ID range for non-configurable edges. This function is inlined for runtime optimization. */ @@ -357,26 +364,26 @@ class RRGraphView { return node_storage_.num_edges(node); } - /** @brief The ptc_num carries different meanings for different node types - * (true in VPR RRG that is currently supported, may not be true in customized RRG) - * CHANX or CHANY: the track id in routing channels - * OPIN or IPIN: the index of pins in the logic block data structure - * SOURCE and SINK: the class id of a pin (indicating logic equivalence of pins) in the logic block data structure - * @note - * This API is very powerful and developers should not use it unless it is necessary, - * e.g the node type is unknown. If the node type is known, the more specific routines, `node_pin_num()`, + /** @brief The ptc_num carries different meanings for different node types + * (true in VPR RRG that is currently supported, may not be true in customized RRG) + * CHANX or CHANY: the track id in routing channels + * OPIN or IPIN: the index of pins in the logic block data structure + * SOURCE and SINK: the class id of a pin (indicating logic equivalence of pins) in the logic block data structure + * @note + * This API is very powerful and developers should not use it unless it is necessary, + * e.g the node type is unknown. If the node type is known, the more specific routines, `node_pin_num()`, * `node_track_num()`and `node_class_num()`, for different types of nodes should be used.*/ inline short node_ptc_num(RRNodeId node) const { return node_storage_.node_ptc_num(node); } - /** @brief Get the pin num of a routing resource node. This is designed for logic blocks, + /** @brief Get the pin num of a routing resource node. This is designed for logic blocks, * which are IPIN and OPIN nodes. This function is inlined for runtime optimization. */ inline short node_pin_num(RRNodeId node) const { return node_storage_.node_pin_num(node); } - /** @brief Get the track num of a routing resource node. This is designed for routing tracks, + /** @brief Get the track num of a routing resource node. This is designed for routing tracks, * which are CHANX and CHANY nodes. This function is inlined for runtime optimization. */ inline short node_track_num(RRNodeId node) const { return node_storage_.node_track_num(node); @@ -498,7 +505,7 @@ class RRGraphView { /* rr_indexed_data_ and rr_segments_ are needed to lookup the segment information in node_coordinate_to_string() */ const vtr::vector& rr_indexed_data_; - /* RC data for nodes. This is a flyweight data */ + /* RC data for nodes. This is a flyweight data */ const std::vector& rr_rc_data_; /* Segment info for rr nodes */ From 4a05cade293995865aaf9a52dac061c76966538c Mon Sep 17 00:00:00 2001 From: taoli4rs Date: Mon, 25 Jul 2022 23:24:40 -0700 Subject: [PATCH 002/147] Add tileable rr graph support. --- libs/libarchfpga/src/physical_types.h | 18 +- libs/libvtrutil/src/vtr_geometry.h | 3 + .../tileable_rr_graph/chan_node_details.cpp | 299 ++++ vpr/src/tileable_rr_graph/chan_node_details.h | 77 + vpr/src/tileable_rr_graph/clb2clb_directs.h | 16 + vpr/src/tileable_rr_graph/openfpga_port.h | 96 ++ .../openfpga_rr_graph_utils.cpp | 184 +++ .../openfpga_rr_graph_utils.h | 46 + .../tileable_rr_graph/openfpga_side_manager.h | 49 + vpr/src/tileable_rr_graph/rr_chan.cpp | 225 +++ vpr/src/tileable_rr_graph/rr_chan.h | 94 ++ .../rr_graph_builder_utils.cpp | 556 +++++++ .../rr_graph_builder_utils.h | 98 ++ vpr/src/tileable_rr_graph/rr_graph_obj_util.h | 35 + vpr/src/tileable_rr_graph/rr_graph_types.h | 46 + vpr/src/tileable_rr_graph/rr_gsb.cpp | 1149 +++++++++++++ vpr/src/tileable_rr_graph/rr_gsb.h | 289 ++++ .../tileable_chan_details_builder.cpp | 234 +++ .../tileable_chan_details_builder.h | 32 + .../tileable_rr_graph_builder.cpp | 370 +++++ .../tileable_rr_graph_builder.h | 39 + .../tileable_rr_graph_edge_builder.cpp | 170 ++ .../tileable_rr_graph_edge_builder.h | 45 + .../tileable_rr_graph_gsb.cpp | 1447 +++++++++++++++++ .../tileable_rr_graph/tileable_rr_graph_gsb.h | 80 + .../tileable_rr_graph_node_builder.cpp | 1061 ++++++++++++ .../tileable_rr_graph_node_builder.h | 47 + 27 files changed, 6800 insertions(+), 5 deletions(-) create mode 100644 vpr/src/tileable_rr_graph/chan_node_details.cpp create mode 100644 vpr/src/tileable_rr_graph/chan_node_details.h create mode 100644 vpr/src/tileable_rr_graph/clb2clb_directs.h create mode 100644 vpr/src/tileable_rr_graph/openfpga_port.h create mode 100644 vpr/src/tileable_rr_graph/openfpga_rr_graph_utils.cpp create mode 100644 vpr/src/tileable_rr_graph/openfpga_rr_graph_utils.h create mode 100644 vpr/src/tileable_rr_graph/openfpga_side_manager.h create mode 100644 vpr/src/tileable_rr_graph/rr_chan.cpp create mode 100644 vpr/src/tileable_rr_graph/rr_chan.h create mode 100644 vpr/src/tileable_rr_graph/rr_graph_builder_utils.cpp create mode 100644 vpr/src/tileable_rr_graph/rr_graph_builder_utils.h create mode 100644 vpr/src/tileable_rr_graph/rr_graph_obj_util.h create mode 100644 vpr/src/tileable_rr_graph/rr_graph_types.h create mode 100644 vpr/src/tileable_rr_graph/rr_gsb.cpp create mode 100644 vpr/src/tileable_rr_graph/rr_gsb.h create mode 100644 vpr/src/tileable_rr_graph/tileable_chan_details_builder.cpp create mode 100644 vpr/src/tileable_rr_graph/tileable_chan_details_builder.h create mode 100644 vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp create mode 100644 vpr/src/tileable_rr_graph/tileable_rr_graph_builder.h create mode 100644 vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp create mode 100644 vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.h create mode 100755 vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp create mode 100755 vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.h create mode 100644 vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp create mode 100644 vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.h diff --git a/libs/libarchfpga/src/physical_types.h b/libs/libarchfpga/src/physical_types.h index 3c0b1c760ac..b8cbd664f34 100644 --- a/libs/libarchfpga/src/physical_types.h +++ b/libs/libarchfpga/src/physical_types.h @@ -613,6 +613,8 @@ struct t_physical_tile_type { std::vector class_inf; /* [0..num_class-1] */ + int num_class = 0; + std::vector pin_width_offset; // [0..num_pins-1] std::vector pin_height_offset; // [0..num_pins-1] std::vector pin_class; // [0..num_pins-1] @@ -1397,7 +1399,7 @@ enum e_directionality { BI_DIRECTIONAL }; /* X_AXIS: Data that describes an x-directed wire segment (CHANX) * - * Y_AXIS: Data that describes an y-directed wire segment (CHANY) * + * Y_AXIS: Data that describes an y-directed wire segment (CHANY) * * BOTH_AXIS: Data that can be applied to both x-directed and y-directed wire segment */ enum e_parallel_axis { X_AXIS, @@ -1442,7 +1444,7 @@ enum e_Fc_type { * Cmetal: Capacitance of a routing track, per unit logic block length. * * Rmetal: Resistance of a routing track, per unit logic block length. * * (UDSD by AY) drivers: How do signals driving a routing track connect to * - * the track? + * the track? * seg_index: The index of the segment as stored in the appropriate Segs list* * Upon loading the architecture, we use this field to keep track * * the segment's index in the unified segment_inf vector. This is * @@ -1498,12 +1500,12 @@ constexpr std::array SWITCH_T /* Constant/Reserved names for switches in architecture XML * Delayless switch: - * The zero-delay switch created by VPR internally + * The zero-delay switch created by VPR internally * This is a special switch just to ease CAD algorithms * It is mainly used in - * - the edges between SOURCE and SINK nodes in routing resource graphs + * - the edges between SOURCE and SINK nodes in routing resource graphs * - the edges in CLB-to-CLB connections (defined by in arch XML) - * + * */ constexpr const char* VPR_DELAYLESS_SWITCH_NAME = "__vpr_delayless_switch__"; @@ -1798,12 +1800,18 @@ struct t_arch { char* architecture_id; //Secure hash digest of the architecture file to uniquely identify this architecture + /* Xifan Tang: options for tileable routing architectures */ + bool tileable; + bool through_channel; + t_chan_width_dist Chans; enum e_switch_block_type SBType; + enum e_switch_block_type SBSubType; std::vector switchblocks; float R_minW_nmos; float R_minW_pmos; int Fs; + int subFs; float grid_logic_tile_area; std::vector Segments; t_arch_switch_inf* Switches = nullptr; diff --git a/libs/libvtrutil/src/vtr_geometry.h b/libs/libvtrutil/src/vtr_geometry.h index 3685c308653..1e11f87e1d7 100644 --- a/libs/libvtrutil/src/vtr_geometry.h +++ b/libs/libvtrutil/src/vtr_geometry.h @@ -61,6 +61,9 @@ bool operator!=(const RectUnion& lhs, const RectUnion& rhs); template class Point { public: //Constructors + // below is to create a no argument constructor for libopenfpga/libopenfpgautil/src/openfpga_pb_parser.cpp + // need to figure out a better solution to avoid change this in libs from vtr + Point(); Point(T x_val, T y_val) noexcept; public: //Accessors diff --git a/vpr/src/tileable_rr_graph/chan_node_details.cpp b/vpr/src/tileable_rr_graph/chan_node_details.cpp new file mode 100644 index 00000000000..6f0f38e820c --- /dev/null +++ b/vpr/src/tileable_rr_graph/chan_node_details.cpp @@ -0,0 +1,299 @@ +/************************************************************************ + * This file contains member functions for class ChanNodeDetails + ***********************************************************************/ +#include + +/* Headers from vtrutil library */ +#include "vtr_assert.h" + +#include "chan_node_details.h" + +/* begin namespace openfpga */ +namespace openfpga { + +/************************************************************************ + * Constructors + ***********************************************************************/ +ChanNodeDetails::ChanNodeDetails(const ChanNodeDetails& src) { + /* duplicate */ + size_t chan_width = src.get_chan_width(); + this->reserve(chan_width); + for (size_t itrack = 0; itrack < chan_width; ++itrack) { + track_node_ids_.push_back(src.get_track_node_id(itrack)); + track_direction_.push_back(src.get_track_direction(itrack)); + seg_ids_.push_back(src.get_track_segment_id(itrack)); + seg_length_.push_back(src.get_track_segment_length(itrack)); + track_start_.push_back(src.is_track_start(itrack)); + track_end_.push_back(src.is_track_end(itrack)); + } +} + +ChanNodeDetails::ChanNodeDetails() { + this->clear(); +} + +/************************************************************************ + * Accessors + ***********************************************************************/ +size_t ChanNodeDetails::get_chan_width() const { + VTR_ASSERT(validate_chan_width()); + return track_node_ids_.size(); +} + +size_t ChanNodeDetails::get_track_node_id(const size_t& track_id) const { + VTR_ASSERT(validate_track_id(track_id)); + return track_node_ids_[track_id]; +} + +/* Return a copy of vector */ +std::vector ChanNodeDetails::get_track_node_ids() const { + std::vector copy; + for (size_t inode = 0; inode < get_chan_width(); ++inode) { + copy.push_back(track_node_ids_[inode]); + } + return copy; +} + +Direction ChanNodeDetails::get_track_direction(const size_t& track_id) const { + VTR_ASSERT(validate_track_id(track_id)); + return track_direction_[track_id]; +} + +size_t ChanNodeDetails::get_track_segment_length(const size_t& track_id) const { + VTR_ASSERT(validate_track_id(track_id)); + return seg_length_[track_id]; +} + +size_t ChanNodeDetails::get_track_segment_id(const size_t& track_id) const { + VTR_ASSERT(validate_track_id(track_id)); + return seg_ids_[track_id]; +} + +bool ChanNodeDetails::is_track_start(const size_t& track_id) const { + VTR_ASSERT(validate_track_id(track_id)); + return track_start_[track_id]; +} + +bool ChanNodeDetails::is_track_end(const size_t& track_id) const { + VTR_ASSERT(validate_track_id(track_id)); + return track_end_[track_id]; +} + +/* Track_id is the starting point of group (whose is_start should be true) + * This function will try to find the track_ids with the same directionality as track_id and seg_length + * A group size is the number of such nodes between the starting points (include the 1st starting point) + */ +std::vector ChanNodeDetails::get_seg_group(const size_t& track_id) const { + VTR_ASSERT(validate_chan_width()); + VTR_ASSERT(validate_track_id(track_id)); + VTR_ASSERT(is_track_start(track_id)); + + std::vector group; + /* Make sure a clean start */ + group.clear(); + + for (size_t itrack = track_id; itrack < get_chan_width(); ++itrack) { + if ( (get_track_direction(itrack) != get_track_direction(track_id) ) + || (get_track_segment_id(itrack) != get_track_segment_id(track_id)) ) { + /* Bypass any nodes in different direction and segment information*/ + continue; + } + if ( (false == is_track_start(itrack)) + || ( (true == is_track_start(itrack)) && (itrack == track_id)) ) { + group.push_back(itrack); + continue; + } + /* Stop if this another starting point */ + if (true == is_track_start(itrack)) { + break; + } + } + return group; +} + +/* Get a list of track_ids with the given list of track indices */ +std::vector ChanNodeDetails::get_seg_group_node_id(const std::vector& seg_group) const { + std::vector group; + /* Make sure a clean start */ + group.clear(); + + for (size_t id = 0; id < seg_group.size(); ++id) { + VTR_ASSERT(validate_track_id(seg_group[id])); + group.push_back(get_track_node_id(seg_group[id])); + } + + return group; +} + +/* Get the number of tracks that starts in this routing channel */ +size_t ChanNodeDetails::get_num_starting_tracks(const Direction& track_direction) const { + size_t counter = 0; + for (size_t itrack = 0; itrack < get_chan_width(); ++itrack) { + /* Bypass unmatched track_direction */ + if (track_direction != get_track_direction(itrack)) { + continue; + } + if (false == is_track_start(itrack)) { + continue; + } + counter++; + } + return counter; +} + +/* Get the number of tracks that ends in this routing channel */ +size_t ChanNodeDetails::get_num_ending_tracks(const Direction& track_direction) const { + size_t counter = 0; + for (size_t itrack = 0; itrack < get_chan_width(); ++itrack) { + /* Bypass unmatched track_direction */ + if (track_direction != get_track_direction(itrack)) { + continue; + } + if (false == is_track_end(itrack)) { + continue; + } + counter++; + } + return counter; +} + + +/************************************************************************ + * Mutators + ***********************************************************************/ +/* Reserve the capacitcy of vectors */ +void ChanNodeDetails::reserve(const size_t& chan_width) { + track_node_ids_.reserve(chan_width); + track_direction_.reserve(chan_width); + seg_length_.reserve(chan_width); + seg_ids_.reserve(chan_width); + track_start_.reserve(chan_width); + track_end_.reserve(chan_width); +} + +/* Add a track to the channel */ +void ChanNodeDetails::add_track(const size_t& track_node_id, const Direction& track_direction, + const size_t& seg_id, const size_t& seg_length, + const size_t& is_start, const size_t& is_end) { + track_node_ids_.push_back(track_node_id); + track_direction_.push_back(track_direction); + seg_ids_.push_back(seg_id); + seg_length_.push_back(seg_length); + track_start_.push_back(is_start); + track_end_.push_back(is_end); +} + +/* Update the node_id of a given track */ +void ChanNodeDetails::set_track_node_id(const size_t& track_index, const size_t& track_node_id) { + VTR_ASSERT(validate_track_id(track_index)); + track_node_ids_[track_index] = track_node_id; +} + +/* Update the node_ids from a vector */ +void ChanNodeDetails::set_track_node_ids(const std::vector& track_node_ids) { + /* the size of vector should match chan_width */ + VTR_ASSERT ( get_chan_width() == track_node_ids.size() ); + for (size_t inode = 0; inode < track_node_ids.size(); ++inode) { + track_node_ids_[inode] = track_node_ids[inode]; + } +} + +/* Set tracks with a given direction to start */ +void ChanNodeDetails::set_tracks_start(const Direction& track_direction) { + for (size_t inode = 0; inode < get_chan_width(); ++inode) { + /* Bypass non-match tracks */ + if (track_direction != get_track_direction(inode)) { + continue; /* Pass condition*/ + } + track_start_[inode] = true; + } +} + +/* Set tracks with a given direction to end */ +void ChanNodeDetails::set_tracks_end(const Direction& track_direction) { + for (size_t inode = 0; inode < get_chan_width(); ++inode) { + /* Bypass non-match tracks */ + if (track_direction != get_track_direction(inode)) { + continue; /* Pass condition*/ + } + track_end_[inode] = true; + } +} + +/* rotate the track_node_id by an offset */ +void ChanNodeDetails::rotate_track_node_id(const size_t& offset, const Direction& track_direction, const bool& counter_rotate) { + /* Direct return if offset = 0*/ + if (0 == offset) { + return; + } + + /* Rotate the node_ids by groups + * A group begins from a track_start and ends before another track_start + */ + VTR_ASSERT(validate_chan_width()); + for (size_t itrack = 0; itrack < get_chan_width(); ++itrack) { + /* Bypass non-start segment */ + if (false == is_track_start(itrack) ) { + continue; + } + /* Bypass segments do not match track_direction */ + if (track_direction != get_track_direction(itrack) ) { + continue; + } + /* Find the group nodes */ + std::vector track_group = get_seg_group(itrack); + /* Build a vector of the node ids of the tracks */ + std::vector track_group_node_id = get_seg_group_node_id(track_group); + /* adapt offset to the range of track_group_node_id */ + size_t actual_offset = offset % track_group_node_id.size(); + /* Rotate or Counter rotate */ + if (true == counter_rotate) { + std::rotate(track_group_node_id.rbegin(), track_group_node_id.rbegin() + actual_offset, track_group_node_id.rend()); + } else { + std::rotate(track_group_node_id.begin(), track_group_node_id.begin() + actual_offset, track_group_node_id.end()); + } + /* Update the node_ids */ + for (size_t inode = 0; inode < track_group.size(); ++inode) { + track_node_ids_[track_group[inode]] = track_group_node_id[inode]; + } + } + return; +} + +void ChanNodeDetails::clear() { + track_node_ids_.clear(); + track_direction_.clear(); + seg_ids_.clear(); + seg_length_.clear(); + track_start_.clear(); + track_end_.clear(); +} + +/************************************************************************ + * Validators + ***********************************************************************/ +bool ChanNodeDetails::validate_chan_width() const { + size_t chan_width = track_node_ids_.size(); + if ( (chan_width == track_direction_.size()) + &&(chan_width == seg_ids_.size()) + &&(chan_width == seg_length_.size()) + &&(chan_width == track_start_.size()) + &&(chan_width == track_end_.size()) ) { + return true; + } + return false; +} + +bool ChanNodeDetails::validate_track_id(const size_t& track_id) const { + if ( (track_id < track_node_ids_.size()) + && (track_id < track_direction_.size()) + && (track_id < seg_ids_.size()) + && (track_id < seg_length_.size()) + && (track_id < track_start_.size()) + && (track_id < track_end_.size()) ) { + return true; + } + return false; +} + +} /* end namespace openfpga */ diff --git a/vpr/src/tileable_rr_graph/chan_node_details.h b/vpr/src/tileable_rr_graph/chan_node_details.h new file mode 100644 index 00000000000..b2426ae56a1 --- /dev/null +++ b/vpr/src/tileable_rr_graph/chan_node_details.h @@ -0,0 +1,77 @@ +#ifndef CHAN_NODE_DETAILS_H +#define CHAN_NODE_DETAILS_H + +/******************************************************************** + * Include header files that are required by function declaration + *******************************************************************/ +#include +#include "vpr_types.h" +#include "rr_node_types.h" +#include "rr_graph_types.h" + +/************************************************************************ + * This file contains a class to model the details of routing node + * in a channel: + * 1. segment information: length, frequency etc. + * 2. starting point of segment + * 3. ending point of segment + * 4. potentail track_id(ptc_num) of each segment + ***********************************************************************/ + +/* begin namespace openfpga */ +namespace openfpga { + +/************************************************************************ + * ChanNodeDetails records segment length, directionality and starting of routing tracks + * +---------------------------------+ + * | Index | Direction | Start Point | + * +---------------------------------+ + * | 0 | --------> | Yes | + * +---------------------------------+ + ***********************************************************************/ + +class ChanNodeDetails { + public : /* Constructor */ + ChanNodeDetails(const ChanNodeDetails&); /* Duplication */ + ChanNodeDetails(); /* Initilization */ + public: /* Accessors */ + size_t get_chan_width() const; + size_t get_track_node_id(const size_t& track_id) const; + std::vector get_track_node_ids() const; + Direction get_track_direction(const size_t& track_id) const; + size_t get_track_segment_length(const size_t& track_id) const; + size_t get_track_segment_id(const size_t& track_id) const; + bool is_track_start(const size_t& track_id) const; + bool is_track_end(const size_t& track_id) const; + std::vector get_seg_group(const size_t& track_id) const; + std::vector get_seg_group_node_id(const std::vector& seg_group) const; + size_t get_num_starting_tracks(const Direction& track_direction) const; + size_t get_num_ending_tracks(const Direction& track_direction) const; + public: /* Mutators */ + void reserve(const size_t& chan_width); /* Reserve the capacitcy of vectors */ + void add_track(const size_t& track_node_id, const Direction& track_direction, + const size_t& seg_id, const size_t& seg_length, + const size_t& is_start, const size_t& is_end); + void set_track_node_id(const size_t& track_index, const size_t& track_node_id); + void set_track_node_ids(const std::vector& track_node_ids); + void set_tracks_start(const Direction& track_direction); + void set_tracks_end(const Direction& track_direction); + void rotate_track_node_id(const size_t& offset, + const Direction& track_direction, + const bool& counter_rotate); /* rotate the track_node_id by an offset */ + void clear(); + private: /* validators */ + bool validate_chan_width() const; + bool validate_track_id(const size_t& track_id) const; + private: /* Internal data */ + std::vector track_node_ids_; /* indices of each track */ + std::vector track_direction_; /* direction of each track */ + std::vector seg_ids_; /* id of segment of each track */ + std::vector seg_length_; /* Length of each segment */ + std::vector track_start_; /* flag to identify if this is the starting point of the track */ + std::vector track_end_; /* flag to identify if this is the ending point of the track */ +}; + +} /* end namespace openfpga */ + +#endif diff --git a/vpr/src/tileable_rr_graph/clb2clb_directs.h b/vpr/src/tileable_rr_graph/clb2clb_directs.h new file mode 100644 index 00000000000..7cc54bb8813 --- /dev/null +++ b/vpr/src/tileable_rr_graph/clb2clb_directs.h @@ -0,0 +1,16 @@ +#ifndef CLB2CLB_DIRECTS_H +#define CLB2CLB_DIRECTS_H + +#include "physical_types.h" + +struct t_clb_to_clb_directs { + t_physical_tile_type_ptr from_clb_type; + int from_clb_pin_start_index; + int from_clb_pin_end_index; + t_physical_tile_type_ptr to_clb_type; + int to_clb_pin_start_index; + int to_clb_pin_end_index; + int switch_index; //The switch type used by this direct connection +}; + +#endif diff --git a/vpr/src/tileable_rr_graph/openfpga_port.h b/vpr/src/tileable_rr_graph/openfpga_port.h new file mode 100644 index 00000000000..3df6d0efa40 --- /dev/null +++ b/vpr/src/tileable_rr_graph/openfpga_port.h @@ -0,0 +1,96 @@ +#ifndef OPENFPGA_PORT_H +#define OPENFPGA_PORT_H + +/******************************************************************** + * Include header files that are required by data structure declaration + *******************************************************************/ +#include +#include + +/* namespace openfpga begins */ +namespace openfpga { + +/* A basic port */ +class BasicPort { + public: /* Constructors */ + BasicPort(); + BasicPort(const char* name, const size_t& lsb, const size_t& msb); + BasicPort(const char* name, const size_t& width); + BasicPort(const std::string& name, const size_t& lsb, const size_t& msb); + BasicPort(const std::string& name, const size_t& width); + public: /* Overloaded operators */ + bool operator== (const BasicPort& portA) const; + bool operator< (const BasicPort& portA) const; + public: /* Accessors */ + size_t get_width() const; /* get the port width */ + size_t get_msb() const; /* get the LSB */ + size_t get_lsb() const; /* get the LSB */ + std::string get_name() const; /* get the name */ + bool is_valid() const; /* check if port size is valid > 0 */ + std::vector pins() const; /* Make a range of the pin indices */ + bool mergeable(const BasicPort& portA) const; /* Check if a port can be merged with this port */ + bool contained(const BasicPort& portA) const; /* Check if a port is contained by this port */ + size_t get_origin_port_width() const; + public: /* Mutators */ + void set(const BasicPort& basic_port); /* copy */ + void set_name(const std::string& name); /* set the port LSB and MSB */ + void set_width(const size_t& width); /* set the port LSB and MSB */ + void set_width(const size_t& lsb, const size_t& msb); /* set the port LSB and MSB */ + void set_lsb(const size_t& lsb); + void set_msb(const size_t& msb); + void expand(const size_t& width); /* Increase the port width */ + void revert(); /* Swap lsb and msb */ + bool rotate(const size_t& offset); /* rotate */ + bool counter_rotate(const size_t& offset); /* counter rotate */ + void reset(); /* Reset to initial port */ + void combine(const BasicPort& port); /* Combine two ports */ + void merge(const BasicPort& portA); + void set_origin_port_width(const size_t& origin_port_width); + private: /* internal functions */ + void make_invalid(); /* Make a port invalid */ + private: /* Internal Data */ + std::string name_; /* Name of this port */ + size_t msb_; /* Most Significant Bit of this port */ + size_t lsb_; /* Least Significant Bit of this port */ + size_t origin_port_width_; /* Original port width of a port, used by traceback port conversion history */ +}; + +/* Configuration ports: + * 1. reserved configuration port, which is used by RRAM FPGA architecture + * 2. regular configuration port, which is used by any FPGA architecture + */ +class ConfPorts { + public: /* Constructors */ + ConfPorts(); /* default port */ + ConfPorts(const ConfPorts& conf_ports); /* copy */ + public: /* Accessors */ + size_t get_reserved_port_width() const; + size_t get_reserved_port_lsb() const; + size_t get_reserved_port_msb() const; + size_t get_regular_port_width() const; + size_t get_regular_port_lsb() const; + size_t get_regular_port_msb() const; + public: /* Mutators */ + void set(const ConfPorts& conf_ports); + void set_reserved_port(size_t width); + void set_regular_port(size_t width); + void set_regular_port(size_t lsb, size_t msb); + void set_regular_port_lsb(size_t lsb); + void set_regular_port_msb(size_t msb); + void expand_reserved_port(size_t width); /* Increase the port width of reserved port */ + void expand_regular_port(size_t width); /* Increase the port width of regular port */ + void expand(size_t width); /* Increase the port width of both ports */ + bool rotate_regular_port(size_t offset); /* rotate */ + bool counter_rotate_regular_port(size_t offset); /* counter rotate */ + void reset(); /* Reset to initial port */ + private: /* Internal Data */ + BasicPort reserved_; + BasicPort regular_; +}; + +/* TODO: create a class for BL and WL ports */ + +} /* namespace openfpga ends */ + +#endif + diff --git a/vpr/src/tileable_rr_graph/openfpga_rr_graph_utils.cpp b/vpr/src/tileable_rr_graph/openfpga_rr_graph_utils.cpp new file mode 100644 index 00000000000..60a8698f8e7 --- /dev/null +++ b/vpr/src/tileable_rr_graph/openfpga_rr_graph_utils.cpp @@ -0,0 +1,184 @@ +/******************************************************************** + * This file includes most utilized functions for the rr_graph + * data structure in the OpenFPGA context + *******************************************************************/ +#include + +/* Headers from vtrutil library */ +#include "vtr_assert.h" +#include "vtr_log.h" + +#include "openfpga_rr_graph_utils.h" +#include "rr_graph_types.h" + +/* begin namespace openfpga */ +namespace openfpga { + +/************************************************************************ + * Get the coordinator of a starting point of a routing track + * For routing tracks in INC_DIRECTION + * (xlow, ylow) should be the starting point + * + * For routing tracks in DEC_DIRECTION + * (xhigh, yhigh) should be the starting point + ***********************************************************************/ +vtr::Point get_track_rr_node_start_coordinate(const RRGraph& rr_graph, + const RRNodeId& track_rr_node) { + /* Make sure we have CHANX or CHANY */ + VTR_ASSERT( (CHANX == rr_graph.node_type(track_rr_node)) + || (CHANY == rr_graph.node_type(track_rr_node)) ); + + vtr::Point start_coordinator; + + if (Direction::INC == rr_graph.node_direction(track_rr_node)) { + start_coordinator.set(rr_graph.node_xlow(track_rr_node), rr_graph.node_ylow(track_rr_node)); + } else { + VTR_ASSERT(Direction::DEC == rr_graph.node_direction(track_rr_node)); + start_coordinator.set(rr_graph.node_xhigh(track_rr_node), rr_graph.node_yhigh(track_rr_node)); + } + + return start_coordinator; +} + +/************************************************************************ + * Get the coordinator of a end point of a routing track + * For routing tracks in INC_DIRECTION + * (xhigh, yhigh) should be the starting point + * + * For routing tracks in DEC_DIRECTION + * (xlow, ylow) should be the starting point + ***********************************************************************/ +vtr::Point get_track_rr_node_end_coordinate(const RRGraph& rr_graph, + const RRNodeId& track_rr_node) { + /* Make sure we have CHANX or CHANY */ + VTR_ASSERT( (CHANX == rr_graph.node_type(track_rr_node)) + || (CHANY == rr_graph.node_type(track_rr_node)) ); + + vtr::Point end_coordinator; + + if (Direction::INC == rr_graph.node_direction(track_rr_node)) { + end_coordinator.set(rr_graph.node_xhigh(track_rr_node), rr_graph.node_yhigh(track_rr_node)); + } else { + VTR_ASSERT(Direction::DEC == rr_graph.node_direction(track_rr_node)); + end_coordinator.set(rr_graph.node_xlow(track_rr_node), rr_graph.node_ylow(track_rr_node)); + } + + return end_coordinator; +} + +/************************************************************************ + * Find the driver switches for a node in the rr_graph + * This function only return unique driver switches + ***********************************************************************/ +std::vector get_rr_graph_driver_switches(const RRGraph& rr_graph, + const RRNodeId& node) { + std::vector driver_switches; + for (const RREdgeId& edge : rr_graph.node_in_edges(node)) { + if (driver_switches.end() == std::find(driver_switches.begin(), driver_switches.end(), rr_graph.edge_switch(edge))) { + driver_switches.push_back(rr_graph.edge_switch(edge)); + } + } + + return driver_switches; +} + +/************************************************************************ + * Find the driver nodes for a node in the rr_graph + ***********************************************************************/ +std::vector get_rr_graph_driver_nodes(const RRGraph& rr_graph, + const RRNodeId& node) { + std::vector driver_nodes; + for (const RREdgeId& edge : rr_graph.node_in_edges(node)) { + driver_nodes.push_back(rr_graph.edge_src_node(edge)); + } + + return driver_nodes; +} + +/************************************************************************ + * Find the configurable driver nodes for a node in the rr_graph + ***********************************************************************/ +std::vector get_rr_graph_configurable_driver_nodes(const RRGraph& rr_graph, + const RRNodeId& node) { + std::vector driver_nodes; + for (const RREdgeId& edge : rr_graph.node_in_edges(node)) { + /* Bypass non-configurable edges */ + if (false == rr_graph.edge_is_configurable(edge)) { + continue; + } + driver_nodes.push_back(rr_graph.edge_src_node(edge)); + } + + return driver_nodes; +} + +/************************************************************************ + * Find the configurable driver nodes for a node in the rr_graph + ***********************************************************************/ +std::vector get_rr_graph_non_configurable_driver_nodes(const RRGraph& rr_graph, + const RRNodeId& node) { + std::vector driver_nodes; + for (const RREdgeId& edge : rr_graph.node_in_edges(node)) { + /* Bypass configurable edges */ + if (true == rr_graph.edge_is_configurable(edge)) { + continue; + } + driver_nodes.push_back(rr_graph.edge_src_node(edge)); + } + + return driver_nodes; +} + +/************************************************************************ + * Check if an OPIN of a rr_graph is directly driving an IPIN + * To meet this requirement, the OPIN must: + * - Have only 1 fan-out + * - The only fan-out is an IPIN + ***********************************************************************/ +bool is_opin_direct_connected_ipin(const RRGraph& rr_graph, + const RRNodeId& node) { + /* We only accept OPIN */ + VTR_ASSERT(OPIN == rr_graph.node_type(node)); + + if (1 != rr_graph.node_out_edges(node).size()) { + return false; + } + + VTR_ASSERT(1 == rr_graph.node_out_edges(node).size()); + for (const RREdgeId& edge: rr_graph.node_out_edges(node)) { + const RRNodeId& sink_node = rr_graph.edge_sink_node(edge); + if (IPIN != rr_graph.node_type(sink_node)) { + return false; + } + } + + return true; +} + +/************************************************************************ + * Check if an IPIN of a rr_graph is directly connected to an OPIN + * To meet this requirement, the IPIN must: + * - Have only 1 fan-in + * - The only fan-in is an OPIN + ***********************************************************************/ +bool is_ipin_direct_connected_opin(const RRGraph& rr_graph, + const RRNodeId& node) { + /* We only accept IPIN */ + VTR_ASSERT(IPIN == rr_graph.node_type(node)); + + if (1 != rr_graph.node_in_edges(node).size()) { + return false; + } + + VTR_ASSERT(1 == rr_graph.node_in_edges(node).size()); + for (const RREdgeId& edge: rr_graph.node_in_edges(node)) { + const RRNodeId& src_node = rr_graph.edge_src_node(edge); + if (OPIN != rr_graph.node_type(src_node)) { + return false; + } + } + + return true; +} + +} /* end namespace openfpga */ diff --git a/vpr/src/tileable_rr_graph/openfpga_rr_graph_utils.h b/vpr/src/tileable_rr_graph/openfpga_rr_graph_utils.h new file mode 100644 index 00000000000..ebf741f8d97 --- /dev/null +++ b/vpr/src/tileable_rr_graph/openfpga_rr_graph_utils.h @@ -0,0 +1,46 @@ +#ifndef OPENFPGA_RR_GRAPH_UTILS_H +#define OPENFPGA_RR_GRAPH_UTILS_H + +/******************************************************************** + * Include header files that are required by function declaration + *******************************************************************/ +/* Headers from vtrutil library */ +#include "vtr_geometry.h" + +/* Headers from vpr library */ +#include "rr_graph_obj.h" + +/******************************************************************** + * Function declaration + *******************************************************************/ + +/* begin namespace openfpga */ +namespace openfpga { + +vtr::Point get_track_rr_node_start_coordinate(const RRGraph& rr_graph, + const RRNodeId& track_rr_node); + +vtr::Point get_track_rr_node_end_coordinate(const RRGraph& rr_graph, + const RRNodeId& track_rr_node); + +std::vector get_rr_graph_driver_switches(const RRGraph& rr_graph, + const RRNodeId& node); + +std::vector get_rr_graph_driver_nodes(const RRGraph& rr_graph, + const RRNodeId& node); + +std::vector get_rr_graph_configurable_driver_nodes(const RRGraph& rr_graph, + const RRNodeId& node); + +std::vector get_rr_graph_non_configurable_driver_nodes(const RRGraph& rr_graph, + const RRNodeId& node); + +bool is_opin_direct_connected_ipin(const RRGraph& rr_graph, + const RRNodeId& node); + +bool is_ipin_direct_connected_opin(const RRGraph& rr_graph, + const RRNodeId& node); + +} /* end namespace openfpga */ + +#endif diff --git a/vpr/src/tileable_rr_graph/openfpga_side_manager.h b/vpr/src/tileable_rr_graph/openfpga_side_manager.h new file mode 100644 index 00000000000..4903f7b4bba --- /dev/null +++ b/vpr/src/tileable_rr_graph/openfpga_side_manager.h @@ -0,0 +1,49 @@ +#ifndef OPENFPGA_SIDE_MANAGER_H +#define OPENFPGA_SIDE_MANAGER_H + +/******************************************************************** + * Include header files that are required by function declaration + *******************************************************************/ +#include +#include + +/* Header files form archfpga library */ +#include "physical_types.h" + +/* namespace openfpga begins */ +namespace openfpga { + +/******************************************************************** + * Define a class for the sides of a physical block in FPGA architecture + * Basically, each block has four sides : + * TOP, RIGHT, BOTTOM, LEFT + * This class aims to provide a easy proctol for manipulating a side + ********************************************************************/ + +class SideManager { + public: /* Constructor */ + SideManager(enum e_side side); + SideManager(); + SideManager(size_t side); + public: /* Accessors */ + enum e_side get_side() const; + enum e_side get_opposite() const; + enum e_side get_rotate_clockwise() const; + enum e_side get_rotate_counterclockwise() const; + bool validate() const; + size_t to_size_t() const; + const char* c_str() const; + std::string to_string() const; + public: /* Mutators */ + void set_side(size_t side); + void set_side(enum e_side side); + void set_opposite(); + void rotate_clockwise(); + void rotate_counterclockwise(); + private: /* internal data */ + enum e_side side_; +}; + +} /* namespace openfpga ends */ + +#endif diff --git a/vpr/src/tileable_rr_graph/rr_chan.cpp b/vpr/src/tileable_rr_graph/rr_chan.cpp new file mode 100644 index 00000000000..0aea3cee48a --- /dev/null +++ b/vpr/src/tileable_rr_graph/rr_chan.cpp @@ -0,0 +1,225 @@ +/************************************************************************ + * Member functions for class RRChan + ***********************************************************************/ +#include "vtr_log.h" +#include "vtr_assert.h" +#include "rr_chan.h" + +/* namespace openfpga begins */ +namespace openfpga { + +/************************************************************************ + * Constructors + ***********************************************************************/ +/* default constructor */ +RRChan::RRChan() { + type_ = NUM_RR_TYPES; + nodes_.resize(0); + node_segments_.resize(0); +} + +/************************************************************************ + * Accessors + ***********************************************************************/ +t_rr_type RRChan::get_type() const { + return type_; +} + +/* get the number of tracks in this channel */ +size_t RRChan::get_chan_width() const { + return nodes_.size(); +} + +/* get the track_id of a node */ +int RRChan::get_node_track_id(const RRNodeId& node) const { + /* if the given node is NULL, we return an invalid id */ + if (RRNodeId::INVALID() == node) { + return -1; + } + /* check each member and return if we find a match in content */ + std::vector::const_iterator it = std::find(nodes_.begin(), nodes_.end(), node); + if (nodes_.end() == it) { + return -1; + } + return it - nodes_.begin(); +} + +/* get the rr_node with the track_id */ +RRNodeId RRChan::get_node(const size_t& track_num) const { + if ( false == valid_node_id(track_num) ) { + return RRNodeId::INVALID(); + } + return nodes_[track_num]; +} + +/* get the segment id of a node */ +RRSegmentId RRChan::get_node_segment(const RRNodeId& node) const { + int node_id = get_node_track_id(node); + if ( false == valid_node_id(node_id)) { + return RRSegmentId::INVALID(); + } + return get_node_segment(node_id); +} + +/* get the segment id of a node */ +RRSegmentId RRChan::get_node_segment(const size_t& track_num) const { + if ( false == valid_node_id(track_num)) { + return RRSegmentId::INVALID(); + } + return node_segments_[track_num]; +} + +/* evaluate if two RRChan is mirror to each other */ +bool RRChan::is_mirror(const RRGraph& rr_graph, const RRChan& cand) const { + /* If any following element does not match, it is not mirror */ + /* 1. type */ + if (this->get_type() != cand.get_type()) { + return false; + } + /* 2. track_width */ + if (this->get_chan_width() != cand.get_chan_width()) { + return false; + } + /* 3. for each node */ + for (size_t inode = 0; inode < this->get_chan_width(); ++inode) { + /* 3.1 check node type */ + if (rr_graph.node_type(this->get_node(inode)) != rr_graph.node_type(cand.get_node(inode))) { + return false; + } + /* 3.2 check node directionality */ + if (rr_graph.node_direction(this->get_node(inode)) != rr_graph.node_direction(cand.get_node(inode))) { + return false; + } + /* 3.3 check node segment */ + if (this->get_node_segment(inode) != cand.get_node_segment(inode)) { + return false; + } + } + + return true; +} + +/* Get a list of segments used in this routing channel */ +std::vector RRChan::get_segment_ids() const { + std::vector seg_list; + + /* make sure a clean start */ + seg_list.clear(); + + /* Traverse node_segments */ + for (size_t inode = 0; inode < get_chan_width(); ++inode) { + std::vector::iterator it; + /* Try to find the node_segment id in the list */ + it = find(seg_list.begin(), seg_list.end(), node_segments_[inode]); + if ( it == seg_list.end() ) { + /* Not found, add it to the list */ + seg_list.push_back(node_segments_[inode]); + } + } + + return seg_list; +} + +/* Get a list of nodes whose segment_id is specified */ +std::vector RRChan::get_node_ids_by_segment_ids(const RRSegmentId& seg_id) const { + std::vector node_list; + + /* make sure a clean start */ + node_list.clear(); + + /* Traverse node_segments */ + for (size_t inode = 0; inode < get_chan_width(); ++inode) { + /* Try to find the node_segment id in the list */ + if ( seg_id == node_segments_[inode] ) { + node_list.push_back(inode); + } + } + + return node_list; +} + +/************************************************************************ + * Mutators + ***********************************************************************/ +void RRChan::set(const RRChan& rr_chan) { + /* Ensure a clean start */ + this->clear(); + /* Assign type of this routing channel */ + this->type_ = rr_chan.get_type(); + /* Copy node and node_segments */ + this->nodes_.resize(rr_chan.get_chan_width()); + this->node_segments_.resize(rr_chan.get_chan_width()); + for (size_t inode = 0; inode < rr_chan.get_chan_width(); ++inode) { + this->nodes_[inode] = rr_chan.get_node(inode); + this->node_segments_[inode] = rr_chan.get_node_segment(inode); + } + return; +} + +/* modify type */ +void RRChan::set_type(const t_rr_type& type) { + VTR_ASSERT(valid_type(type)); + type_ = type; +} + +/* Reserve node list */ +void RRChan::reserve_node(const size_t& node_size) { + nodes_.reserve(node_size); /* reserve to the maximum */ + node_segments_.reserve(node_size); /* reserve to the maximum */ +} + +/* add a node to the array */ +void RRChan::add_node(const RRGraph& rr_graph, const RRNodeId& node, const RRSegmentId& node_segment) { + /* fill the dedicated element in the vector */ + nodes_.push_back(node); + node_segments_.push_back(node_segment); + + if (NUM_RR_TYPES == type_) { + type_ = rr_graph.node_type(node); + } else { + VTR_ASSERT(type_ == rr_graph.node_type(node)); + } + + VTR_ASSERT(valid_node_type(rr_graph, node)); +} + +/* Clear content */ +void RRChan::clear() { + nodes_.clear(); + node_segments_.clear(); +} + +/************************************************************************ + * Internal validators + ***********************************************************************/ +/* for type, only valid type is CHANX and CHANY */ +bool RRChan::valid_type(const t_rr_type& type) const { + if ((CHANX == type) || (CHANY == type)) { + return true; + } + return false; +} + +/* Check each node, see if the node type is consistent with the type */ +bool RRChan::valid_node_type(const RRGraph& rr_graph, const RRNodeId& node) const { + valid_type(rr_graph.node_type(node)); + if (NUM_RR_TYPES == type_) { + return true; + } + valid_type(type_); + if (type_ != rr_graph.node_type(node)) { + return false; + } + return true; +} + +/* check if the node id is valid */ +bool RRChan::valid_node_id(const size_t& node_id) const { + if (node_id < nodes_.size()) { + return true; + } + + return false; +} + +} /* End namespace openfpga*/ diff --git a/vpr/src/tileable_rr_graph/rr_chan.h b/vpr/src/tileable_rr_graph/rr_chan.h new file mode 100644 index 00000000000..d06d894caa8 --- /dev/null +++ b/vpr/src/tileable_rr_graph/rr_chan.h @@ -0,0 +1,94 @@ +#ifndef RR_CHAN_H +#define RR_CHAN_H + +/******************************************************************** + * Include header files required by the data structure definition + *******************************************************************/ +#include + +/* Headers from vtrutil library */ +#include "vtr_geometry.h" + +/* Headers from openfpgautil library */ +#include "openfpga_port.h" + +/* Headers from vpr library */ +#include "rr_graph_obj.h" + +/* Begin namespace openfpga */ +namespace openfpga { + +/******************************************************************** + * RRChan object aim to describe a routing channel in a routing resource graph + * - What are the nodes in the RRGraph object, for each routing track + * - What are routing segments used by each node in the channel + * - What are the directions of each routing channel + * being either X-direction or Y-direction + * + * Note : + * - This is a collection of rr_nodes from the RRGraph Object + * It does not rebuild or contruct any connects between rr_nodes + * It is just an annotation on an existing RRGraph + * ------------- ------ + * | | | | + * | | | Y | + * | CLB | | Chan | + * | | | | + * | | | | + * ------------- ------ + * ------------- + * | X | + * | Channel | + * ------------- + *******************************************************************/ +class RRChan { + public: /* Constructors */ + RRChan(); + public: /* Accessors */ + t_rr_type get_type() const; + size_t get_chan_width() const; /* get the number of tracks in this channel */ + int get_node_track_id(const RRNodeId& node) const; /* get the track_id of a node */ + RRNodeId get_node(const size_t& track_num) const; /* get the rr_node with the track_id */ + RRSegmentId get_node_segment(const RRNodeId& node) const; + RRSegmentId get_node_segment(const size_t& track_num) const; + bool is_mirror(const RRGraph& rr_graph, const RRChan& cand) const; /* evaluate if two RR_chan is mirror to each other */ + std::vector get_segment_ids() const; /* Get a list of segments used in this routing channel */ + std::vector get_node_ids_by_segment_ids(const RRSegmentId& seg_id) const; /* Get a list of segments used in this routing channel */ + public: /* Mutators */ + /* copy */ + void set(const RRChan&); + + /* modify the type of routing channel */ + void set_type(const t_rr_type& type); + + /* reseve a number of nodes to the array */ + void reserve_node(const size_t& node_size); + + /* add a node to the routing channel */ + void add_node(const RRGraph& rr_graph, const RRNodeId& node, const RRSegmentId& node_segment); + + /* clear the content */ + void clear(); + + private: /* internal functions */ + + /* For the type of a routing channel, only valid type is CHANX and CHANY */ + bool valid_type(const t_rr_type& type) const; + + /* Check each node, see if the node type is consistent with the type of routing channel */ + bool valid_node_type(const RRGraph& rr_graph, const RRNodeId& node) const; + + /* Validate if the track number in the range */ + bool valid_node_id(const size_t& node_id) const; + + private: /* Internal Data */ + t_rr_type type_; /* channel type: CHANX or CHANY */ + std::vector nodes_; /* rr nodes of each track in the channel */ + std::vector node_segments_; /* segment of each track */ +}; + + + +} /* End namespace openfpga*/ + +#endif diff --git a/vpr/src/tileable_rr_graph/rr_graph_builder_utils.cpp b/vpr/src/tileable_rr_graph/rr_graph_builder_utils.cpp new file mode 100644 index 00000000000..3aaba3e1ac2 --- /dev/null +++ b/vpr/src/tileable_rr_graph/rr_graph_builder_utils.cpp @@ -0,0 +1,556 @@ +/************************************************************************ + * This file contains most utilized functions for rr_graph builders + ***********************************************************************/ +#include +#include + +/* Headers from vtrutil library */ +#include "vtr_assert.h" +#include "vtr_log.h" + +#include "vpr_utils.h" + +#include "rr_graph_builder_utils.h" + +/* begin namespace openfpga */ +namespace openfpga { + +/************************************************************************ + * Correct number of routing channel width to be compatible to + * uni-directional routing architecture + ***********************************************************************/ +size_t find_unidir_routing_channel_width(const size_t& chan_width) { + size_t actual_chan_width = chan_width; + /* Correct the chan_width: it should be an even number */ + if (0 != actual_chan_width % 2) { + actual_chan_width++; /* increment it to be even */ + } + VTR_ASSERT(0 == actual_chan_width % 2); + + return actual_chan_width; +} + +/************************************************************************ + * Get the class index of a grid pin + ***********************************************************************/ +int get_grid_pin_class_index(const t_grid_tile& cur_grid, + const int pin_index) { + /* check */ + VTR_ASSERT(pin_index < cur_grid.type->num_pins); + return cur_grid.type->pin_class[pin_index]; +} + +/* Deteremine the side of a io grid */ +e_side determine_io_grid_pin_side(const vtr::Point& device_size, + const vtr::Point& grid_coordinate) { + /* TOP side IO of FPGA */ + if (device_size.y() == grid_coordinate.y()) { + return BOTTOM; /* Such I/O has only Bottom side pins */ + } else if (device_size.x() == grid_coordinate.x()) { /* RIGHT side IO of FPGA */ + return LEFT; /* Such I/O has only Left side pins */ + } else if (0 == grid_coordinate.y()) { /* BOTTOM side IO of FPGA */ + return TOP; /* Such I/O has only Top side pins */ + } else if (0 == grid_coordinate.x()) { /* LEFT side IO of FPGA */ + return RIGHT; /* Such I/O has only Right side pins */ + } else if ((grid_coordinate.x() < device_size.x()) && (grid_coordinate.y() < device_size.y())) { + /* I/O grid in the center grid */ + return NUM_SIDES; + } + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid coordinate (%lu, %lu) for I/O Grid whose size is (%lu, %lu)!\n", + grid_coordinate.x(), grid_coordinate.y(), + device_size.x(), device_size.y()); + exit(1); +} + +/* Deteremine the side of a pin of a grid */ +std::vector find_grid_pin_sides(const t_grid_tile& grid, + const size_t& pin_id) { + std::vector pin_sides; + + for (const e_side& side : {TOP, RIGHT, BOTTOM, LEFT} ) { + if (true == grid.type->pinloc[grid.width_offset][grid.height_offset][size_t(side)][pin_id]) { + pin_sides.push_back(side); + } + } + + return pin_sides; +} + +/************************************************************************ + * Get a list of pin_index for a grid (either OPIN or IPIN) + * For IO_TYPE, only one side will be used, we consider one side of pins + * For others, we consider all the sides + ***********************************************************************/ +std::vector get_grid_side_pins(const t_grid_tile& cur_grid, + const e_pin_type& pin_type, + const e_side& pin_side, + const int& pin_width, + const int& pin_height) { + std::vector pin_list; + /* Make sure a clear start */ + pin_list.clear(); + + for (int ipin = 0; ipin < cur_grid.type->num_pins; ++ipin) { + int class_id = cur_grid.type->pin_class[ipin]; + if ( (1 == cur_grid.type->pinloc[pin_width][pin_height][pin_side][ipin]) + && (pin_type == cur_grid.type->class_inf[class_id].type) ) { + pin_list.push_back(ipin); + } + } + return pin_list; +} + +/************************************************************************ + * Get the number of pins for a grid (either OPIN or IPIN) + * For IO_TYPE, only one side will be used, we consider one side of pins + * For others, we consider all the sides + ***********************************************************************/ +size_t get_grid_num_pins(const t_grid_tile& cur_grid, + const e_pin_type& pin_type, + const e_side& io_side) { + size_t num_pins = 0; + + /* For IO_TYPE sides */ + for (const e_side& side : {TOP, RIGHT, BOTTOM, LEFT}) { + /* skip unwanted sides */ + if ( (true == is_io_type(cur_grid.type)) + && (side != io_side) && (NUM_SIDES != io_side)) { + continue; + } + /* Get pin list */ + for (int width = 0; width < cur_grid.type->width; ++width) { + for (int height = 0; height < cur_grid.type->height; ++height) { + std::vector pin_list = get_grid_side_pins(cur_grid, pin_type, side, width, height); + num_pins += pin_list.size(); + } + } + } + + return num_pins; +} + +/************************************************************************ + * Get the number of pins for a grid (either OPIN or IPIN) + * For IO_TYPE, only one side will be used, we consider one side of pins + * For others, we consider all the sides + ***********************************************************************/ +size_t get_grid_num_classes(const t_grid_tile& cur_grid, + const e_pin_type& pin_type) { + size_t num_classes = 0; + + for (int iclass = 0; iclass < cur_grid.type->num_class; ++iclass) { + /* Bypass unmatched pin_type */ + if (pin_type != cur_grid.type->class_inf[iclass].type) { + continue; + } + num_classes++; + } + + return num_classes; +} + +/************************************************************************ + * Idenfity if a X-direction routing channel exist in the fabric + * This could be entirely possible that a routig channel + * is in the middle of a multi-width and multi-height grid + * + * As the chanx always locates on top of a grid with the same coord + * + * +----------+ + * | CHANX | + * | [x][y] | + * +----------+ + * + * +----------+ + * | Grid | height_offset = height - 1 + * | [x][y] | + * +----------+ + * + * +----------+ + * | Grid | height_offset = height - 2 + * | [x][y-1] | + * +----------+ + * If the CHANX is in the middle of a multi-width and multi-height grid + * it should locate at a grid whose height_offset is lower than the its height defined in physical_tile + * When height_offset == height - 1, it means that the grid is at the top side of this multi-width and multi-height block + ***********************************************************************/ +bool is_chanx_exist(const DeviceGrid& grids, + const vtr::Point& chanx_coord, + const bool& through_channel) { + + if ((1 > chanx_coord.x()) || (chanx_coord.x() > grids.width() - 2)) { + return false; + } + + if (chanx_coord.y() > grids.height() - 2) { + return false; + } + + if (true == through_channel) { + return true; + } + + return (grids[chanx_coord.x()][chanx_coord.y()].height_offset == grids[chanx_coord.x()][chanx_coord.y()].type->height - 1); +} + +/************************************************************************ + * Idenfity if a Y-direction routing channel exist in the fabric + * This could be entirely possible that a routig channel + * is in the middle of a multi-width and multi-height grid + * + * As the chany always locates on right of a grid with the same coord + * + * +-----------+ +---------+ +--------+ + * | Grid | | Grid | | CHANY | + * | [x-1][y] | | [x][y] | | [x][y] | + * +-----------+ +---------+ +--------+ + * width_offset width_offset + * = width - 2 = width -1 + * If the CHANY is in the middle of a multi-width and multi-height grid + * it should locate at a grid whose width_offset is lower than the its width defined in physical_tile + * When height_offset == height - 1, it means that the grid is at the top side of this multi-width and multi-height block + * + * If through channel is allowed, the chany will always exists + * unless it falls out of the grid array + ***********************************************************************/ +bool is_chany_exist(const DeviceGrid& grids, + const vtr::Point& chany_coord, + const bool& through_channel) { + + if (chany_coord.x() > grids.width() - 2) { + return false; + } + + if ((1 > chany_coord.y()) || (chany_coord.y() > grids.height() - 2)) { + return false; + } + + if (true == through_channel) { + return true; + } + + return (grids[chany_coord.x()][chany_coord.y()].width_offset == grids[chany_coord.x()][chany_coord.y()].type->width - 1); +} + +/************************************************************************ + * Identify if a X-direction routing channel is at the right side of a + * multi-height grid + * + * +-----------------+ + * | | + * | | +-------------+ + * | Grid | | CHANX | + * | [x-1][y] | | [x][y] | + * | | +-------------+ + * | | + * +-----------------+ + ***********************************************************************/ +bool is_chanx_right_to_multi_height_grid(const DeviceGrid& grids, + const vtr::Point& chanx_coord, + const bool& through_channel) { + VTR_ASSERT(0 < chanx_coord.x()); + if (1 == chanx_coord.x()) { + /* This is already the LEFT side of FPGA fabric, + * it is the same results as chanx is right to a multi-height grid + */ + return true; + } + + if (false == through_channel) { + /* We check the left neighbor of chanx, if it does not exist, the chanx is left to a multi-height grid */ + vtr::Point left_chanx_coord(chanx_coord.x() - 1, chanx_coord.y()); + if (false == is_chanx_exist(grids, left_chanx_coord)) { + return true; + } + } + + return false; +} + +/************************************************************************ + * Identify if a X-direction routing channel is at the left side of a + * multi-height grid + * + * +-----------------+ + * | | + * +---------------+ | | + * | CHANX | | Grid | + * | [x][y] | | [x+1][y] | + * +---------------+ | | + * | | + * +-----------------+ + ***********************************************************************/ +bool is_chanx_left_to_multi_height_grid(const DeviceGrid& grids, + const vtr::Point& chanx_coord, + const bool& through_channel) { + VTR_ASSERT(chanx_coord.x() < grids.width() - 1); + if (grids.width() - 2 == chanx_coord.x()) { + /* This is already the RIGHT side of FPGA fabric, + * it is the same results as chanx is right to a multi-height grid + */ + return true; + } + + + if (false == through_channel) { + /* We check the right neighbor of chanx, if it does not exist, the chanx is left to a multi-height grid */ + vtr::Point right_chanx_coord(chanx_coord.x() + 1, chanx_coord.y()); + if (false == is_chanx_exist(grids, right_chanx_coord)) { + return true; + } + } + + return false; +} + +/************************************************************************ + * Identify if a Y-direction routing channel is at the top side of a + * multi-width grid + * + * +--------+ + * | CHANY | + * | [x][y] | + * +--------+ + * + * +-----------------+ + * | | + * | | + * | Grid | + * | [x-1][y] | + * | | + * | | + * +-----------------+ + ***********************************************************************/ +bool is_chany_top_to_multi_width_grid(const DeviceGrid& grids, + const vtr::Point& chany_coord, + const bool& through_channel) { + VTR_ASSERT(0 < chany_coord.y()); + if (1 == chany_coord.y()) { + /* This is already the BOTTOM side of FPGA fabric, + * it is the same results as chany is at the top of a multi-width grid + */ + return true; + } + + if (false == through_channel) { + /* We check the bottom neighbor of chany, if it does not exist, the chany is top to a multi-height grid */ + vtr::Point bottom_chany_coord(chany_coord.x(), chany_coord.y() - 1); + if (false == is_chany_exist(grids, bottom_chany_coord)) { + return true; + } + } + + return false; +} + +/************************************************************************ + * Identify if a Y-direction routing channel is at the bottom side of a + * multi-width grid + * + * +-----------------+ + * | | + * | | + * | Grid | + * | [x][y+1] | + * | | + * | | + * +-----------------+ + * +--------+ + * | CHANY | + * | [x][y] | + * +--------+ + * + ***********************************************************************/ +bool is_chany_bottom_to_multi_width_grid(const DeviceGrid& grids, + const vtr::Point& chany_coord, + const bool& through_channel) { + VTR_ASSERT(chany_coord.y() < grids.height() - 1); + if (grids.height() - 2 == chany_coord.y()) { + /* This is already the TOP side of FPGA fabric, + * it is the same results as chany is at the bottom of a multi-width grid + */ + return true; + } + + if (false == through_channel) { + /* We check the top neighbor of chany, if it does not exist, the chany is left to a multi-height grid */ + vtr::Point top_chany_coord(chany_coord.x(), chany_coord.y() + 1); + if (false == is_chany_exist(grids, top_chany_coord)) { + return true; + } + } + + return false; +} + +/************************************************************************ + * Get the track_id of a routing track w.r.t its coordinator + * In tileable routing architecture, the track_id changes SB by SB. + * Therefore the track_ids are stored in a vector, indexed by the relative coordinator + * based on the starting point of the track + * For routing tracks in INC_DIRECTION + * (xlow, ylow) should be the starting point + * + * (xlow, ylow) (xhigh, yhigh) + * track_id[0] -------------------------------> track_id[xhigh - xlow + yhigh - ylow] + * + * For routing tracks in DEC_DIRECTION + * (xhigh, yhigh) should be the starting point + * + * (xlow, ylow) (xhigh, yhigh) + * track_id[0] <------------------------------- track_id[xhigh - xlow + yhigh - ylow] + * + * + ***********************************************************************/ +short get_rr_node_actual_track_id(const RRGraph& rr_graph, + const RRNodeId& track_rr_node, + const vtr::Point& coord, + const vtr::vector>& tileable_rr_graph_node_track_ids) { + vtr::Point low_coord(rr_graph.node_xlow(track_rr_node), rr_graph.node_ylow(track_rr_node)); + size_t offset = (int)abs((int)coord.x() - (int)low_coord.x() + (int)coord.y() - (int)low_coord.y()); + return tileable_rr_graph_node_track_ids[track_rr_node][offset]; +} + +/************************************************************************ + * Get the ptc of a routing track in the channel where it ends + * For routing tracks in INC_DIRECTION + * the ptc is the last of track_ids + * + * For routing tracks in DEC_DIRECTION + * the ptc is the first of track_ids + ***********************************************************************/ +short get_track_rr_node_end_track_id(const RRGraph& rr_graph, + const RRNodeId& track_rr_node, + const vtr::vector>& tileable_rr_graph_node_track_ids) { + /* Make sure we have CHANX or CHANY */ + VTR_ASSERT( (CHANX == rr_graph.node_type(track_rr_node)) + || (CHANY == rr_graph.node_type(track_rr_node)) ); + + if (Direction::INC == rr_graph.node_direction(track_rr_node)) { + return tileable_rr_graph_node_track_ids[track_rr_node].back(); + } + + VTR_ASSERT(Direction::DEC == rr_graph.node_direction(track_rr_node)); + return tileable_rr_graph_node_track_ids[track_rr_node].front(); +} + +/************************************************************************ + * Find the number of nodes in the same class + * in a routing resource graph + ************************************************************************/ +short find_rr_graph_num_nodes(const RRGraph& rr_graph, + const std::vector& node_types) { + short counter = 0; + + for (const RRNodeId& node : rr_graph.nodes()) { + /* Bypass the nodes not in the class */ + if (node_types.end() == std::find(node_types.begin(), node_types.end(), rr_graph.node_type(node))) { + continue; + } + counter++; + } + + return counter; +} + +/************************************************************************ + * Find the maximum fan-in for a given class of nodes + * in a routing resource graph + ************************************************************************/ +short find_rr_graph_max_fan_in(const RRGraph& rr_graph, + const std::vector& node_types) { + short max_fan_in = 0; + + for (const RRNodeId& node : rr_graph.nodes()) { + /* Bypass the nodes not in the class */ + if (node_types.end() == std::find(node_types.begin(), node_types.end(), rr_graph.node_type(node))) { + continue; + } + max_fan_in = std::max(rr_graph.node_fan_in(node), max_fan_in); + } + + return max_fan_in; +} + +/************************************************************************ + * Find the minimum fan-in for a given class of nodes + * in a routing resource graph + ************************************************************************/ +short find_rr_graph_min_fan_in(const RRGraph& rr_graph, + const std::vector& node_types) { + short min_fan_in = 0; + + for (const RRNodeId& node : rr_graph.nodes()) { + /* Bypass the nodes not in the class */ + if (node_types.end() == std::find(node_types.begin(), node_types.end(), rr_graph.node_type(node))) { + continue; + } + min_fan_in = std::min(rr_graph.node_fan_in(node), min_fan_in); + } + + + return min_fan_in; +} + +/************************************************************************ + * Find the average fan-in for a given class of nodes + * in a routing resource graph + ************************************************************************/ +short find_rr_graph_average_fan_in(const RRGraph& rr_graph, + const std::vector& node_types) { + /* Get the maximum SB mux size */ + size_t sum = 0; + size_t counter = 0; + + for (const RRNodeId& node : rr_graph.nodes()) { + /* Bypass the nodes not in the class */ + if (node_types.end() == std::find(node_types.begin(), node_types.end(), rr_graph.node_type(node))) { + continue; + } + + sum += rr_graph.node_fan_in(node); + counter++; + } + + return sum / counter; +} + +/************************************************************************ + * Print statistics of multiplexers in a routing resource graph + ************************************************************************/ +void print_rr_graph_mux_stats(const RRGraph& rr_graph) { + + /* Print MUX size distribution */ + std::vector sb_node_types; + sb_node_types.push_back(CHANX); + sb_node_types.push_back(CHANY); + + /* Print statistics */ + VTR_LOG("------------------------------------------------\n"); + VTR_LOG("Total No. of Switch Block multiplexer size: %d\n", + find_rr_graph_num_nodes(rr_graph, sb_node_types)); + VTR_LOG("Maximum Switch Block multiplexer size: %d\n", + find_rr_graph_max_fan_in(rr_graph, sb_node_types)); + VTR_LOG("Minimum Switch Block multiplexer size: %d\n", + find_rr_graph_min_fan_in(rr_graph, sb_node_types)); + VTR_LOG("Average Switch Block multiplexer size: %lu\n", + find_rr_graph_average_fan_in(rr_graph, sb_node_types)); + VTR_LOG("------------------------------------------------\n"); + + /* Get the maximum CB mux size */ + std::vector cb_node_types(1, IPIN); + + VTR_LOG("------------------------------------------------\n"); + VTR_LOG("Total No. of Connection Block Multiplexer size: %d\n", + find_rr_graph_num_nodes(rr_graph, cb_node_types)); + VTR_LOG("Maximum Connection Block Multiplexer size: %d\n", + find_rr_graph_max_fan_in(rr_graph, cb_node_types)); + VTR_LOG("Minimum Connection Block Multiplexer size: %d\n", + find_rr_graph_min_fan_in(rr_graph, cb_node_types)); + VTR_LOG("Average Connection Block Multiplexer size: %lu\n", + find_rr_graph_average_fan_in(rr_graph, cb_node_types)); + VTR_LOG("------------------------------------------------\n"); +} + +} /* end namespace openfpga */ diff --git a/vpr/src/tileable_rr_graph/rr_graph_builder_utils.h b/vpr/src/tileable_rr_graph/rr_graph_builder_utils.h new file mode 100644 index 00000000000..6ff78412f06 --- /dev/null +++ b/vpr/src/tileable_rr_graph/rr_graph_builder_utils.h @@ -0,0 +1,98 @@ +#ifndef RR_GRAPH_BUILDER_UTILS_H +#define RR_GRAPH_BUILDER_UTILS_H + +/******************************************************************** + * Include header files that are required by function declaration + *******************************************************************/ +#include "device_grid.h" +#include "rr_graph_obj.h" +#include "vtr_geometry.h" + +/******************************************************************** + * Function declaration + *******************************************************************/ + +/* begin namespace openfpga */ +namespace openfpga { + +size_t find_unidir_routing_channel_width(const size_t& chan_width); + +int get_grid_pin_class_index(const t_grid_tile& cur_grid, + const int pin_index); + +std::vector find_grid_pin_sides(const t_grid_tile& grid, + const size_t& pin_id); + +e_side determine_io_grid_pin_side(const vtr::Point& device_size, + const vtr::Point& grid_coordinate); + +std::vector get_grid_side_pins(const t_grid_tile& cur_grid, + const e_pin_type& pin_type, + const e_side& pin_side, + const int& pin_width, + const int& pin_height); + +size_t get_grid_num_pins(const t_grid_tile& cur_grid, + const e_pin_type& pin_type, + const e_side& io_side); + +size_t get_grid_num_classes(const t_grid_tile& cur_grid, + const e_pin_type& pin_type); + +bool is_chanx_exist(const DeviceGrid& grids, + const vtr::Point& chanx_coord, + const bool& through_channel=false); + +bool is_chany_exist(const DeviceGrid& grids, + const vtr::Point& chany_coord, + const bool& through_channel=false); + +bool is_chanx_right_to_multi_height_grid(const DeviceGrid& grids, + const vtr::Point& chanx_coord, + const bool& through_channel); + +bool is_chanx_left_to_multi_height_grid(const DeviceGrid& grids, + const vtr::Point& chanx_coord, + const bool& through_channel); + +bool is_chany_top_to_multi_width_grid(const DeviceGrid& grids, + const vtr::Point& chany_coord, + const bool& through_channel); + +bool is_chany_bottom_to_multi_width_grid(const DeviceGrid& grids, + const vtr::Point& chany_coord, + const bool& through_channel); + +short get_rr_node_actual_track_id(const RRGraph& rr_graph, + const RRNodeId& track_rr_node, + const vtr::Point& coord, + const vtr::vector>& tileable_rr_graph_node_track_ids); + +vtr::Point get_track_rr_node_start_coordinator(const RRGraph& rr_graph, + const RRNodeId& track_rr_node); + +vtr::Point get_track_rr_node_end_coordinator(const RRGraph& rr_graph, + const RRNodeId& track_rr_node); + +short get_track_rr_node_end_track_id(const RRGraph& rr_graph, + const RRNodeId& track_rr_node, + const vtr::vector>& tileable_rr_graph_node_track_ids); + +short find_rr_graph_num_nodes(const RRGraph& rr_graph, + const std::vector& node_types); + +short find_rr_graph_max_fan_in(const RRGraph& rr_graph, + const std::vector& node_types); + +short find_rr_graph_min_fan_in(const RRGraph& rr_graph, + const std::vector& node_types); + +short find_rr_graph_average_fan_in(const RRGraph& rr_graph, + const std::vector& node_types); + +void print_rr_graph_mux_stats(const RRGraph& rr_graph); + +} /* end namespace openfpga */ + +#endif + diff --git a/vpr/src/tileable_rr_graph/rr_graph_obj_util.h b/vpr/src/tileable_rr_graph/rr_graph_obj_util.h new file mode 100644 index 00000000000..01f753ddcf6 --- /dev/null +++ b/vpr/src/tileable_rr_graph/rr_graph_obj_util.h @@ -0,0 +1,35 @@ +#ifndef RR_GRAPH_OBJ_UTIL_H +#define RR_GRAPH_OBJ_UTIL_H + +/* Include header files which include data structures used by + * the function declaration + */ +#include +#include "rr_graph_obj.h" +#include "device_grid.h" + +/* Get node-to-node switches in a RRGraph */ +std::vector find_rr_graph_switches(const RRGraph& rr_graph, + const RRNodeId& from_node, + const RRNodeId& to_node); + +std::vector find_rr_graph_nodes(const RRGraph& rr_graph, + const int& x, + const int& y, + const t_rr_type& rr_type, + const int& ptc); + +std::vector find_rr_graph_chan_nodes(const RRGraph& rr_graph, + const int& x, + const int& y, + const t_rr_type& rr_type); + +std::vector find_rr_graph_grid_nodes(const RRGraph& rr_graph, + const DeviceGrid& device_grid, + const int& x, + const int& y, + const t_rr_type& rr_type, + const e_side& side); + + +#endif diff --git a/vpr/src/tileable_rr_graph/rr_graph_types.h b/vpr/src/tileable_rr_graph/rr_graph_types.h new file mode 100644 index 00000000000..6cf7e1b56eb --- /dev/null +++ b/vpr/src/tileable_rr_graph/rr_graph_types.h @@ -0,0 +1,46 @@ +#ifndef RR_GRAPH_TYPES +#define RR_GRAPH_TYPES + +/******************************************************************** + * Data types required by routing resource graph (RRGraph) definition + *******************************************************************/ + +/******************************************************************** + * Directionality of a routing track (node type CHANX and CHANY) in + * a routing resource graph + *******************************************************************/ +enum e_direction : unsigned char { + INC_DIRECTION = 0, + DEC_DIRECTION = 1, + BI_DIRECTION = 2, + NO_DIRECTION = 3, + NUM_DIRECTIONS +}; + +/* Xifan Tang - string used in describe_rr_node() and write_xml_rr_graph_obj() */ +constexpr std::array DIRECTION_STRING_WRITE_XML = {{"INC_DIR", "DEC_DIR", "BI_DIR", "NO_DIR"}}; + +#if 0 +/* Type of a routing resource node. x-directed channel segment, * + * y-directed channel segment, input pin to a clb to pad, output * + * from a clb or pad (i.e. output pin of a net) and: * + * SOURCE: A dummy node that is a logical output within a block * + * -- i.e., the gate that generates a signal. * + * SINK: A dummy node that is a logical input within a block * + * -- i.e. the gate that needs a signal. */ +typedef enum e_rr_type : unsigned char { + SOURCE = 0, + SINK, + IPIN, + OPIN, + CHANX, + CHANY, + NUM_RR_TYPES +} t_rr_type; +#endif + +// constexpr std::array RR_TYPES = {{SOURCE, SINK, IPIN, OPIN, CHANX, CHANY}}; +// constexpr std::array rr_node_typename{{"SOURCE", "SINK", "IPIN", "OPIN", "CHANX", "CHANY"}}; + + +#endif diff --git a/vpr/src/tileable_rr_graph/rr_gsb.cpp b/vpr/src/tileable_rr_graph/rr_gsb.cpp new file mode 100644 index 00000000000..badaa663bac --- /dev/null +++ b/vpr/src/tileable_rr_graph/rr_gsb.cpp @@ -0,0 +1,1149 @@ +/************************************************************************ + * Member functions for class RRGSB + ***********************************************************************/ +/* Headers from vtrutil library */ +#include "vtr_log.h" +#include "vtr_assert.h" + +#include "openfpga_rr_graph_utils.h" +#include "openfpga_side_manager.h" + +#include "rr_gsb.h" + +/* namespace openfpga begins */ +namespace openfpga { + +/************************************************************************ + * Constructors + ***********************************************************************/ +/* Constructor for an empty object */ +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(); +} + +/************************************************************************ + * Accessors + ***********************************************************************/ +/* Get the number of sides of this SB */ +size_t RRGSB::get_num_sides() const { + VTR_ASSERT (validate_num_sides()); + return chan_node_direction_.size(); +} + +/* Get the number of routing tracks on a side */ +size_t RRGSB::get_chan_width(const e_side& side) const { + SideManager side_manager(side); + VTR_ASSERT(side_manager.validate()); + return chan_node_[side_manager.to_size_t()].get_chan_width(); +} + +/* Get the number of routing tracks on a side */ +t_rr_type RRGSB::get_chan_type(const e_side& side) const { + SideManager side_manager(side); + VTR_ASSERT(side_manager.validate()); + return chan_node_[side_manager.to_size_t()].get_type(); +} + +/* Get the maximum number of routing tracks on all sides */ +size_t RRGSB::get_max_chan_width() const { + size_t max_chan_width = 0; + for (size_t side = 0; side < get_num_sides(); ++side) { + SideManager side_manager(side); + max_chan_width = std::max(max_chan_width, get_chan_width(side_manager.get_side())); + } + return max_chan_width; +} + +/* Get the number of routing tracks of a X/Y-direction CB */ +size_t RRGSB::get_cb_chan_width(const t_rr_type& cb_type) const { + return get_chan_width(get_cb_chan_side(cb_type)); +} + +/* Get the sides of ipin_nodes belong to the cb */ +std::vector RRGSB::get_cb_ipin_sides(const t_rr_type& cb_type) const { + VTR_ASSERT (validate_cb_type(cb_type)); + + std::vector ipin_sides; + + /* Make sure a clean start */ + ipin_sides.clear(); + + switch(cb_type) { + case CHANX: + ipin_sides.push_back(TOP); + ipin_sides.push_back(BOTTOM); + break; + case CHANY: + ipin_sides.push_back(RIGHT); + ipin_sides.push_back(LEFT); + break; + default: + VTR_LOG("Invalid type of connection block!\n"); + exit(1); + } + + return ipin_sides; +} + +/* Get the direction of a rr_node at a given side and track_id */ +enum PORTS RRGSB::get_chan_node_direction(const e_side& side, const size_t& track_id) const { + SideManager side_manager(side); + VTR_ASSERT(side_manager.validate()); + + /* Ensure the side is valid in the context of this switch block */ + VTR_ASSERT( validate_side(side) ); + + /* Ensure the track is valid in the context of this switch block at a specific side */ + VTR_ASSERT( validate_track_id(side, track_id) ); + + return chan_node_direction_[side_manager.to_size_t()][track_id]; +} + +/* Get a list of segments used in this routing channel */ +std::vector RRGSB::get_chan_segment_ids(const e_side& side) const { + SideManager side_manager(side); + VTR_ASSERT(side_manager.validate()); + + /* Ensure the side is valid in the context of this switch block */ + VTR_ASSERT( validate_side(side) ); + + return chan_node_[side_manager.to_size_t()].get_segment_ids(); +} + +/* Get a list of rr_nodes whose sed_id is specified */ +std::vector RRGSB::get_chan_node_ids_by_segment_ids(const e_side& side, + const RRSegmentId& seg_id) const { + return chan_node_[size_t(side)].get_node_ids_by_segment_ids(seg_id); +} + +/* get a rr_node at a given side and track_id */ +RRNodeId RRGSB::get_chan_node(const e_side& side, const size_t& track_id) const { + SideManager side_manager(side); + VTR_ASSERT(side_manager.validate()); + + /* Ensure the side is valid in the context of this switch block */ + VTR_ASSERT( validate_side(side) ); + + /* Ensure the track is valid in the context of this switch block at a specific side */ + VTR_ASSERT( validate_track_id(side, track_id) ); + + return chan_node_[side_manager.to_size_t()].get_node(track_id); +} + +std::vector RRGSB::get_chan_node_in_edges(const RRGraph& rr_graph, + const e_side& side, + const size_t& track_id) const { + SideManager side_manager(side); + VTR_ASSERT(side_manager.validate()); + + /* Ensure the side is valid in the context of this switch block */ + VTR_ASSERT( validate_side(side) ); + + /* Ensure the track is valid in the context of this switch block at a specific side */ + VTR_ASSERT( validate_track_id(side, track_id) ); + + /* The chan node must be an output port for the GSB, we allow users to access input edges*/ + VTR_ASSERT(OUT_PORT == get_chan_node_direction(side, track_id)); + + /* if sorted, we give sorted edges + * if not sorted, we give the empty vector + */ + if (0 == chan_node_in_edges_.size()) { + std::vector unsorted_edges; + for (const RREdgeId& edge : rr_graph.node_in_edges(get_chan_node(side, track_id))) { + unsorted_edges.push_back(edge); + } + + return unsorted_edges; + } + + return chan_node_in_edges_[side_manager.to_size_t()][track_id]; +} + +/* get the segment id of a channel rr_node */ +RRSegmentId RRGSB::get_chan_node_segment(const e_side& side, const size_t& track_id) const { + SideManager side_manager(side); + VTR_ASSERT(side_manager.validate()); + + /* Ensure the side is valid in the context of this switch block */ + VTR_ASSERT( validate_side(side) ); + + /* Ensure the track is valid in the context of this switch block at a specific side */ + VTR_ASSERT( validate_track_id(side, track_id) ); + + return chan_node_[side_manager.to_size_t()].get_node_segment(track_id); +} + +/* Get the number of IPIN rr_nodes on a side */ +size_t RRGSB::get_num_ipin_nodes(const e_side& side) const { + SideManager side_manager(side); + VTR_ASSERT(side_manager.validate()); + return ipin_node_[side_manager.to_size_t()].size(); +} + +/* get a opin_node at a given side and track_id */ +RRNodeId RRGSB::get_ipin_node(const e_side& side, const size_t& node_id) const { + SideManager side_manager(side); + VTR_ASSERT(side_manager.validate()); + + /* Ensure the side is valid in the context of this switch block */ + VTR_ASSERT( validate_side(side) ); + + /* Ensure the track is valid in the context of this switch block at a specific side */ + VTR_ASSERT( validate_ipin_node_id(side, node_id) ); + + return ipin_node_[side_manager.to_size_t()][node_id]; +} + +/* Get the number of OPIN rr_nodes on a side */ +size_t RRGSB::get_num_opin_nodes(const e_side& side) const { + SideManager side_manager(side); + VTR_ASSERT(side_manager.validate()); + return opin_node_[side_manager.to_size_t()].size(); +} + +/* get a opin_node at a given side and track_id */ +RRNodeId RRGSB::get_opin_node(const e_side& side, const size_t& node_id) const { + SideManager side_manager(side); + VTR_ASSERT(side_manager.validate()); + + /* Ensure the side is valid in the context of this switch block */ + 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) ); + + return opin_node_[side_manager.to_size_t()][node_id]; +} + +/* Get the node index of a routing track of a connection block, return -1 if not found */ +int RRGSB::get_cb_chan_node_index(const t_rr_type& cb_type, const RRNodeId& node) const { + enum e_side chan_side = get_cb_chan_side(cb_type); + return get_chan_node_index(chan_side, node); +} + +/* Get the node index in the array, return -1 if not found */ +int RRGSB::get_chan_node_index(const e_side& node_side, const RRNodeId& node) const { + VTR_ASSERT (validate_side(node_side)); + return chan_node_[size_t(node_side)].get_node_track_id(node); +} + +/* Get the node index in the array, return -1 if not found */ +int RRGSB::get_node_index(const RRGraph& rr_graph, + const RRNodeId& node, + const e_side& node_side, + const PORTS& node_direction) const { + size_t cnt; + int ret; + + cnt = 0; + ret = -1; + + /* Depending on the type of rr_node, we search different arrays */ + switch (rr_graph.node_type(node)) { + case CHANX: + case CHANY: + for (size_t inode = 0; inode < get_chan_width(node_side); ++inode){ + if ((node == chan_node_[size_t(node_side)].get_node(inode)) + /* Check if direction meets specification */ + &&(node_direction == chan_node_direction_[size_t(node_side)][inode])) { + cnt++; + ret = inode; + break; + } + } + break; + case IPIN: + for (size_t inode = 0; inode < get_num_ipin_nodes(node_side); ++inode) { + if (node == ipin_node_[size_t(node_side)][inode]) { + cnt++; + ret = inode; + break; + } + } + break; + case OPIN: + for (size_t inode = 0; inode < get_num_opin_nodes(node_side); ++inode) { + if (node == opin_node_[size_t(node_side)][inode]) { + cnt++; + ret = inode; + break; + } + } + break; + default: + VTR_LOG("Invalid cur_rr_node type! Should be [CHANX|CHANY|IPIN|OPIN]\n"); + exit(1); + } + + VTR_ASSERT((0 == cnt)||(1 == cnt)); + + return ret; /* Return an invalid value: nonthing is found*/ +} + +/* Get the side of a node in this SB */ +void RRGSB::get_node_side_and_index(const RRGraph& rr_graph, + const RRNodeId& node, + const PORTS& node_direction, + e_side& node_side, + int& node_index) const { + size_t side; + SideManager side_manager; + + /* Count the number of existence of cur_rr_node in cur_sb_info + * It could happen that same cur_rr_node appears on different sides of a SB + * For example, a routing track go vertically across the SB. + * Then its corresponding rr_node appears on both TOP and BOTTOM sides of this SB. + * We need to ensure that the found rr_node has the same direction as user want. + * By specifying the direction of rr_node, There should be only one rr_node can satisfy! + */ + for (side = 0; side < get_num_sides(); ++side) { + side_manager.set_side(side); + node_index = get_node_index(rr_graph, node, side_manager.get_side(), node_direction); + if (-1 != node_index) { + break; + } + } + + if (side == get_num_sides()) { + /* we find nothing, return NUM_SIDES, and a OPEN node (-1) */ + node_side = NUM_SIDES; + VTR_ASSERT(-1 == node_index); + return; + } + + node_side = side_manager.get_side(); + VTR_ASSERT(-1 != node_index); + + return; +} + +/* Check if the node exist in the opposite side of this Switch Block */ +bool RRGSB::is_sb_node_exist_opposite_side(const RRGraph& rr_graph, + const RRNodeId& node, + const e_side& node_side) const { + SideManager side_manager(node_side); + int index; + + VTR_ASSERT((CHANX == rr_graph.node_type(node)) || (CHANY == rr_graph.node_type(node))); + + /* See if we can find the same src_rr_node in the opposite chan_side + * if there is one, it means a shorted wire across the SB + */ + index = get_node_index(rr_graph, node, side_manager.get_opposite(), IN_PORT); + + return (-1 != index); +} + +/* check if the candidate CB is a mirror of the current one */ +bool RRGSB::is_cb_mirror(const RRGraph& rr_graph, const RRGSB& cand, const t_rr_type& cb_type) const { + /* Check if channel width is the same */ + if ( get_cb_chan_width(cb_type) != cand.get_cb_chan_width(cb_type) ) { + return false; + } + + enum e_side chan_side = get_cb_chan_side(cb_type); + + /* check the numbers/directionality of channel rr_nodes */ + if ( false == chan_node_[size_t(chan_side)].is_mirror(rr_graph, cand.chan_node_[size_t(chan_side)]) ) { + return false; + } + + /* check the equivalence of ipins */ + std::vector ipin_side = get_cb_ipin_sides(cb_type); + for (size_t side = 0; side < ipin_side.size(); ++side) { + /* Ensure we have the same number of IPINs on this side */ + if ( get_num_ipin_nodes(ipin_side[side]) != cand.get_num_ipin_nodes(ipin_side[side]) ) { + return false; + } + for (size_t inode = 0; inode < get_num_ipin_nodes(ipin_side[side]); ++inode) { + if (false == is_cb_node_mirror(rr_graph, cand, cb_type, ipin_side[side], inode)) { + return false; + } + } + } + + return true; +} + +/* check if the CB exist in this GSB */ +bool RRGSB::is_cb_exist(const t_rr_type& cb_type) const { + /* if channel width is zero, there is no CB */ + return (0 != get_cb_chan_width(cb_type)); +} + +/* check if the SB exist in this GSB */ +bool RRGSB::is_sb_exist() const { + /* if all the channel width is zero and number of OPINs are zero, there is no SB */ + for (size_t side = 0; side < get_num_sides(); ++side) { + SideManager side_manager(side); + if (0 != get_chan_width(side_manager.get_side())) { + return true; + } + if (0 != get_num_opin_nodes(side_manager.get_side())) { + return true; + } + } + + return false; +} + +/************************************************************************ + * Check if the node indicates a passing wire across the Switch Block part of the GSB + * Therefore, we actually do the following check + * Check if a track starts from this GSB or not + * For INC_DIRECTION + * (xlow, ylow) should be same as the GSB side coordinate + * For DEC_DIRECTION + * (xhigh, yhigh) should be same as the GSB side coordinate + ***********************************************************************/ +bool RRGSB::is_sb_node_passing_wire(const RRGraph& rr_graph, + const e_side& node_side, + const size_t& track_id) const { + + /* Get the rr_node */ + RRNodeId track_node = get_chan_node(node_side, track_id); + /* Get the coordinates */ + vtr::Point side_coordinate = get_side_block_coordinate(node_side); + + /* Get the coordinate of where the track starts */ + vtr::Point track_start = get_track_rr_node_start_coordinate(rr_graph, track_node); + + /* INC_DIRECTION start_track: (xlow, ylow) should be same as the GSB side coordinate */ + /* DEC_DIRECTION start_track: (xhigh, yhigh) should be same as the GSB side coordinate */ + if ( (track_start.x() == side_coordinate.x()) + && (track_start.y() == side_coordinate.y()) + && (OUT_PORT == get_chan_node_direction(node_side, track_id)) ) { + /* Double check: start track should be an OUTPUT PORT of the GSB */ + return false; /* This is a starting point */ + } + + /* Get the coordinate of where the track ends */ + vtr::Point track_end = get_track_rr_node_end_coordinate(rr_graph, track_node); + + /* INC_DIRECTION end_track: (xhigh, yhigh) should be same as the GSB side coordinate */ + /* DEC_DIRECTION end_track: (xlow, ylow) should be same as the GSB side coordinate */ + if ( (track_end.x() == side_coordinate.x()) + && (track_end.y() == side_coordinate.y()) + && (IN_PORT == get_chan_node_direction(node_side, track_id)) ) { + /* Double check: end track should be an INPUT PORT of the GSB */ + return false; /* This is an ending point */ + } + + /* Reach here it means that this will be a passing wire, + * we should be able to find the node on the opposite side of the GSB! + */ + if (true != is_sb_node_exist_opposite_side(rr_graph, track_node, node_side)) { + VTR_LOG("GSB[%lu][%lu] track node[%lu] at %s:\n", + get_x(), get_y(), track_id, SIDE_STRING[node_side]); + rr_graph.print_node(track_node); + } + VTR_ASSERT (true == is_sb_node_exist_opposite_side(rr_graph, track_node, node_side)); + + return true; +} + +/* check if the candidate SB satisfy the basic requirements on being a mirror of the current one */ +/* Idenify mirror Switch blocks + * Check each two switch blocks: + * Number of channel/opin/ipin rr_nodes are same + * If all above are satisfied, the two switch blocks may be mirrors ! + */ +bool RRGSB::is_sb_mirrorable(const RRGraph& rr_graph, const RRGSB& cand) const { + /* check the numbers of sides */ + if (get_num_sides() != cand.get_num_sides()) { + return false; + } + + /* check the numbers/directionality of channel rr_nodes */ + for (size_t side = 0; side < get_num_sides(); ++side) { + SideManager side_manager(side); + + /* Ensure we have the same channel width on this side */ + if (get_chan_width(side_manager.get_side()) != cand.get_chan_width(side_manager.get_side())) { + return false; + } + + if ( ((size_t(-1) == get_track_id_first_short_connection(rr_graph, side_manager.get_side())) + && (size_t(-1) != cand.get_track_id_first_short_connection(rr_graph, side_manager.get_side()))) + || ((size_t(-1) != get_track_id_first_short_connection(rr_graph, side_manager.get_side()) ) + && ( size_t(-1) == cand.get_track_id_first_short_connection(rr_graph, side_manager.get_side()))) ) { + return false; + } + } + + /* check the numbers of opin_rr_nodes */ + for (size_t side = 0; side < get_num_sides(); ++side) { + SideManager side_manager(side); + + if (get_num_opin_nodes(side_manager.get_side()) != cand.get_num_opin_nodes(side_manager.get_side())) { + return false; + } + } + + return true; +} + +/* check if all the routing segments of a side of candidate SB is a mirror of the current one */ +bool RRGSB::is_sb_side_segment_mirror(const RRGraph& rr_graph, const RRGSB& cand, + const e_side& side, const RRSegmentId& seg_id) const { + /* Create a side manager */ + SideManager side_manager(side); + + /* Make sure both Switch blocks has this side!!! */ + VTR_ASSERT ( side_manager.to_size_t() < get_num_sides() ); + VTR_ASSERT ( side_manager.to_size_t() < cand.get_num_sides() ); + + /* check the numbers/directionality of channel rr_nodes */ + /* Ensure we have the same channel width on this side */ + if (get_chan_width(side) != cand.get_chan_width(side)) { + return false; + } + for (size_t itrack = 0; itrack < get_chan_width(side); ++itrack) { + /* Bypass unrelated segments */ + if (seg_id != get_chan_node_segment(side, itrack)) { + continue; + } + /* Check the directionality of each node */ + if (get_chan_node_direction(side, itrack) != cand.get_chan_node_direction(side, itrack)) { + return false; + } + /* Check the track_id of each node + * ptc is not necessary, we care the connectivity! + */ + /* For OUT_PORT rr_node, we need to check fan-in */ + if (OUT_PORT != get_chan_node_direction(side, itrack)) { + continue; /* skip IN_PORT */ + } + + if (false == is_sb_node_mirror(rr_graph, cand, side, itrack)) { + return false; + } + } + + /* check the numbers of opin_rr_nodes */ + if (get_num_opin_nodes(side) != cand.get_num_opin_nodes(side)) { + return false; + } + + /* check the numbers of ipin_rr_nodes */ + if (get_num_ipin_nodes(side) != cand.get_num_ipin_nodes(side)) { + return false; + } + + return true; +} + +/* check if a side of candidate SB is a mirror of the current one */ +bool RRGSB::is_sb_side_mirror(const RRGraph& rr_graph, const RRGSB& cand, const e_side& side) const { + + /* get a list of segments */ + std::vector seg_ids = chan_node_[size_t(side)].get_segment_ids(); + + for (size_t iseg = 0; iseg < seg_ids.size(); ++iseg) { + if (false == is_sb_side_segment_mirror(rr_graph, cand, side, seg_ids[iseg])) { + return false; + } + } + + return true; +} + +/* check if the candidate SB is a mirror of the current one */ +bool RRGSB::is_sb_mirror(const RRGraph& rr_graph, const RRGSB& cand) const { + /* check the numbers of sides */ + if (get_num_sides() != cand.get_num_sides()) { + return false; + } + + /* check the numbers/directionality of channel rr_nodes */ + for (size_t side = 0; side < get_num_sides(); ++side) { + SideManager side_manager(side); + if (false == is_sb_side_mirror(rr_graph, cand, side_manager.get_side())) { + return false; + } + } + + return true; +} + +/* Public Accessors: Cooridinator conversion */ + +/* get the x coordinate of this GSB */ +size_t RRGSB::get_x() const { + return coordinate_.x(); +} + +/* get the y coordinate of this GSB */ +size_t RRGSB::get_y() const { + return coordinate_.y(); +} + + +/* get the x coordinate of this switch block */ +size_t RRGSB::get_sb_x() const { + return coordinate_.x(); +} + +/* get the y coordinate of this switch block */ +size_t RRGSB::get_sb_y() const { + return coordinate_.y(); +} + +/* Get the number of sides of this SB */ +vtr::Point RRGSB::get_sb_coordinate() const { + return coordinate_; +} + +/* get the x coordinate of this X/Y-direction block */ +size_t RRGSB::get_cb_x(const t_rr_type& cb_type) const { + VTR_ASSERT (validate_cb_type(cb_type)); + switch(cb_type) { + case CHANX: + return get_side_block_coordinate(LEFT).x(); + case CHANY: + return get_side_block_coordinate(TOP).x(); + default: + VTR_LOG("Invalid type of connection block!\n"); + exit(1); + } +} + +/* get the y coordinate of this X/Y-direction block */ +size_t RRGSB::get_cb_y(const t_rr_type& cb_type) const { + VTR_ASSERT (validate_cb_type(cb_type)); + switch(cb_type) { + case CHANX: + return get_side_block_coordinate(LEFT).y(); + case CHANY: + return get_side_block_coordinate(TOP).y(); + default: + VTR_LOG("Invalid type of connection block!\n"); + exit(1); + } +} + +/* Get the coordinate of the X/Y-direction CB */ +vtr::Point RRGSB::get_cb_coordinate(const t_rr_type& cb_type) const { + VTR_ASSERT (validate_cb_type(cb_type)); + switch(cb_type) { + case CHANX: + return get_side_block_coordinate(LEFT); + case CHANY: + return get_side_block_coordinate(TOP); + default: + VTR_LOG("Invalid type of connection block!\n"); + exit(1); + } +} + +e_side RRGSB::get_cb_chan_side(const t_rr_type& cb_type) const { + VTR_ASSERT (validate_cb_type(cb_type)); + switch(cb_type) { + case CHANX: + return LEFT; + case CHANY: + return TOP; + default: + VTR_LOG("Invalid type of connection block!\n"); + exit(1); + } +} + +/* Get the side of routing channel in the GSB according to the side of IPIN */ +e_side RRGSB::get_cb_chan_side(const e_side& ipin_side) const { + switch(ipin_side) { + case TOP: + return LEFT; + case RIGHT: + return TOP; + case BOTTOM: + return LEFT; + case LEFT: + return TOP; + default: + VTR_LOG("Invalid type of ipin_side!\n"); + exit(1); + } +} + +vtr::Point RRGSB::get_side_block_coordinate(const e_side& side) const { + SideManager side_manager(side); + VTR_ASSERT(side_manager.validate()); + vtr::Point ret(get_sb_x(), get_sb_y()); + + switch (side_manager.get_side()) { + case TOP: + /* (0 == side) */ + /* 1. Channel Y [x][y+1] inputs */ + ret.set_y(ret.y() + 1); + break; + case RIGHT: + /* 1 == side */ + /* 2. Channel X [x+1][y] inputs */ + ret.set_x(ret.x() + 1); + break; + case BOTTOM: + /* 2 == side */ + /* 3. Channel Y [x][y] inputs */ + break; + case LEFT: + /* 3 == side */ + /* 4. Channel X [x][y] inputs */ + break; + default: + VTR_LOG(" Invalid side!\n"); + exit(1); + } + + return ret; +} + +vtr::Point RRGSB::get_grid_coordinate() const { + vtr::Point ret(get_sb_x(), get_sb_y()); + ret.set_y(ret.y() + 1); + + return ret; +} + +/************************************************************************ + * Public Mutators + ***********************************************************************/ +/* get a copy from a source */ +void RRGSB::set(const RRGSB& src) { + /* Copy coordinate */ + this->set_coordinate(src.get_sb_coordinate().x(), src.get_sb_coordinate().y()); + + /* Initialize sides */ + this->init_num_sides(src.get_num_sides()); + + /* Copy vectors */ + for (size_t side = 0; side < src.get_num_sides(); ++side) { + SideManager side_manager(side); + /* Copy chan_nodes */ + /* skip if there is no channel width */ + if ( 0 < src.get_chan_width(side_manager.get_side()) ) { + this->chan_node_[side_manager.get_side()].set(src.chan_node_[side_manager.get_side()]); + /* Copy chan_node_direction_*/ + this->chan_node_direction_[side_manager.get_side()].clear(); + for (size_t inode = 0; inode < src.get_chan_width(side_manager.get_side()); ++inode) { + this->chan_node_direction_[side_manager.get_side()].push_back(src.get_chan_node_direction(side_manager.get_side(), inode)); + } + } + + /* Copy opin_node and opin_node_grid_side_ */ + this->opin_node_[side_manager.get_side()].clear(); + for (size_t inode = 0; inode < src.get_num_opin_nodes(side_manager.get_side()); ++inode) { + this->opin_node_[side_manager.get_side()].push_back(src.get_opin_node(side_manager.get_side(), inode)); + } + + /* Copy ipin_node and ipin_node_grid_side_ */ + this->ipin_node_[side_manager.get_side()].clear(); + for (size_t inode = 0; inode < src.get_num_ipin_nodes(side_manager.get_side()); ++inode) { + this->ipin_node_[side_manager.get_side()].push_back(src.get_ipin_node(side_manager.get_side(), inode)); + } + } +} + +/* Set the coordinate (x,y) for the switch block */ +void RRGSB::set_coordinate(const size_t& x, const size_t& y) { + coordinate_.set(x, y); +} + +/* Allocate the vectors with the given number of sides */ +void RRGSB::init_num_sides(const size_t& num_sides) { + /* Initialize the vectors */ + chan_node_.resize(num_sides); + chan_node_direction_.resize(num_sides); + ipin_node_.resize(num_sides); + opin_node_.resize(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, + 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)); + + /* fill the dedicated element in the vector */ + chan_node_[size_t(node_side)].set(rr_chan); + chan_node_direction_[size_t(node_side)].resize(rr_chan_dir.size()); + for (size_t inode = 0; inode < rr_chan_dir.size(); ++inode) { + chan_node_direction_[size_t(node_side)][inode] = rr_chan_dir[inode]; + } +} + +/* Add a node to the chan_node_ list and also assign its direction in chan_node_direction_ */ +void RRGSB::add_ipin_node(const RRNodeId& node, const e_side& node_side) { + VTR_ASSERT(validate_side(node_side)); + /* push pack the dedicated element in the vector */ + ipin_node_[size_t(node_side)].push_back(node); +} + +/* Add a node to the chan_node_ list and also assign its direction in chan_node_direction_ */ +void RRGSB::add_opin_node(const RRNodeId& node, const e_side& node_side) { + VTR_ASSERT(validate_side(node_side)); + /* push pack the dedicated element in the vector */ + 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 */ + if (NUM_SIDES == side) { + VTR_LOG("GSB[%lu][%lu]:\n", get_x(), get_y()); + VTR_LOG("SRC node:\n"); + rr_graph.print_node(src_node); + VTR_LOG("Channel node:\n"); + rr_graph.print_node(chan_node); + } + + 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 and bypass passing wires */ + if ( (OUT_PORT == chan_node_direction_[side][track_id]) + && (false == is_sb_node_passing_wire(rr_graph, side_manager.get_side(), track_id)) ) { + sort_chan_node_in_edges(rr_graph, side_manager.get_side(), track_id); + } + } + } +} + +/************************************************************************ + * Public Mutators: clean-up functions + ***********************************************************************/ +/* Reset the RRGSB to pristine state */ +void RRGSB::clear() { + /* Clean all the vectors */ + VTR_ASSERT(validate_num_sides()); + /* Clear the inner vector of each matrix */ + for (size_t side = 0; side < get_num_sides(); ++side) { + chan_node_direction_[side].clear(); + chan_node_[side].clear(); + ipin_node_[side].clear(); + opin_node_[side].clear(); + } + chan_node_direction_.clear(); + chan_node_.clear(); + ipin_node_.clear(); + opin_node_.clear(); +} + +/* Clean the chan_width of a side */ +void RRGSB::clear_chan_nodes(const e_side& node_side) { + VTR_ASSERT(validate_side(node_side)); + + chan_node_[size_t(node_side)].clear(); + chan_node_direction_[size_t(node_side)].clear(); +} + +/* Clean the number of IPINs of a side */ +void RRGSB::clear_ipin_nodes(const e_side& node_side) { + VTR_ASSERT(validate_side(node_side)); + + ipin_node_[size_t(node_side)].clear(); +} + +/* Clean the number of OPINs of a side */ +void RRGSB::clear_opin_nodes(const e_side& node_side) { + VTR_ASSERT(validate_side(node_side)); + + opin_node_[size_t(node_side)].clear(); +} + +/* Clean chan/opin/ipin nodes at one side */ +void RRGSB::clear_one_side(const e_side& node_side) { + clear_chan_nodes(node_side); + clear_ipin_nodes(node_side); + clear_opin_nodes(node_side); +} + +/************************************************************************ + * Internal Accessors: identify mirrors + ***********************************************************************/ + +/* check if two rr_nodes have a similar set of drive_rr_nodes + * for each drive_rr_node: + * 1. CHANX or CHANY: should have the same side and index + * 2. OPIN or IPIN: should have the same side and index + * 3. each drive_rr_switch should be the same + */ +bool RRGSB::is_sb_node_mirror(const RRGraph& rr_graph, + const RRGSB& cand, + const e_side& node_side, + const size_t& track_id) const { + /* Ensure rr_nodes are either the output of short-connection or multiplexer */ + bool is_short_conkt = this->is_sb_node_passing_wire(rr_graph, node_side, track_id); + + if (is_short_conkt != cand.is_sb_node_passing_wire(rr_graph, node_side, track_id)) { + return false; + } + + if (true == is_short_conkt) { + /* Since, both are pass wires, + * The two node should be equivalent + * we can return here + */ + return true; + } + + /* Use unsorted/sorted edges */ + std::vector node_in_edges = get_chan_node_in_edges(rr_graph, node_side, track_id); + std::vector cand_node_in_edges = cand.get_chan_node_in_edges(rr_graph, node_side, track_id); + + /* For non-passing wires, check driving rr_nodes */ + if (node_in_edges.size() != cand_node_in_edges.size()) { + return false; + } + + VTR_ASSERT(node_in_edges.size() == cand_node_in_edges.size()); + + for (size_t iedge = 0; iedge < node_in_edges.size(); ++iedge) { + RREdgeId src_edge = node_in_edges[iedge]; + RREdgeId src_cand_edge = cand_node_in_edges[iedge]; + RRNodeId src_node = rr_graph.edge_src_node(src_edge); + RRNodeId src_cand_node = rr_graph.edge_src_node(src_cand_edge); + /* node type should be the same */ + if (rr_graph.node_type(src_node) != rr_graph.node_type(src_cand_node)) { + return false; + } + /* switch type should be the same */ + if (rr_graph.edge_switch(src_edge) != rr_graph.edge_switch(src_cand_edge)) { + return false; + } + int src_node_id, des_node_id; + enum e_side src_node_side, des_node_side; + this->get_node_side_and_index(rr_graph, src_node, OUT_PORT, src_node_side, src_node_id); + cand.get_node_side_and_index(rr_graph, src_cand_node, OUT_PORT, des_node_side, des_node_id); + if (src_node_id != des_node_id) { + return false; + } + if (src_node_side != des_node_side) { + return false; + } + } + + return true; +} + +/* check if two ipin_nodes have a similar set of drive_rr_nodes + * for each drive_rr_node: + * 1. CHANX or CHANY: should have the same side and index + * 2. each drive_rr_switch should be the same + */ +bool RRGSB::is_cb_node_mirror(const RRGraph& rr_graph, + const RRGSB& cand, + const t_rr_type& cb_type, + const e_side& node_side, + const size_t& node_id) const { + /* Ensure rr_nodes are either the output of short-connection or multiplexer */ + RRNodeId node = this->get_ipin_node(node_side, node_id); + RRNodeId cand_node = cand.get_ipin_node(node_side, node_id); + + if ( rr_graph.node_in_edges(node).size() != rr_graph.node_in_edges(cand_node).size() ) { + return false; + } + + std::vector node_in_edges; + for (const RREdgeId& edge : rr_graph.node_in_edges(node)) { + node_in_edges.push_back(edge); + } + + std::vector cand_node_in_edges; + for (const RREdgeId& edge : rr_graph.node_in_edges(cand_node)) { + cand_node_in_edges.push_back(edge); + } + VTR_ASSERT(node_in_edges.size() == cand_node_in_edges.size()); + + for (size_t iedge = 0; iedge < node_in_edges.size(); ++iedge) { + RREdgeId src_edge = node_in_edges[iedge]; + RREdgeId src_cand_edge = cand_node_in_edges[iedge]; + RRNodeId src_node = rr_graph.edge_src_node(src_edge); + RRNodeId src_cand_node = rr_graph.edge_src_node(src_cand_edge); + /* node type should be the same */ + if (rr_graph.node_type(src_node) != rr_graph.node_type(src_cand_node)) { + return false; + } + /* switch type should be the same */ + if (rr_graph.edge_switch(src_edge)!= rr_graph.edge_switch(src_cand_edge)) { + return false; + } + + int src_node_id, des_node_id; + enum e_side src_node_side, des_node_side; + enum e_side chan_side = get_cb_chan_side(cb_type); + switch (rr_graph.node_type(src_node)) { + case CHANX: + case CHANY: + /* if the drive rr_nodes are routing tracks, find index */ + src_node_id = this->get_chan_node_index(chan_side, src_node); + des_node_id = cand.get_chan_node_index(chan_side, src_cand_node); + break; + case OPIN: + this->get_node_side_and_index(rr_graph, src_node, OUT_PORT, src_node_side, src_node_id); + cand.get_node_side_and_index(rr_graph, src_cand_node, OUT_PORT, des_node_side, des_node_id); + if (src_node_side != des_node_side) { + return false; + } + break; + default: + VTR_LOG("Invalid type of drive_rr_nodes for ipin_node!\n"); + exit(1); + } + if (src_node_id != des_node_id) { + return false; + } + } + + return true; +} + +size_t RRGSB::get_track_id_first_short_connection(const RRGraph& rr_graph, const e_side& node_side) const { + VTR_ASSERT(validate_side(node_side)); + + /* Walk through chan_nodes and find the first short connection */ + for (size_t inode = 0; inode < get_chan_width(node_side); ++inode) { + if (true == is_sb_node_passing_wire(rr_graph, node_side, inode)) { + return inode; + } + } + + return size_t(-1); +} + + +/************************************************************************ + * Internal validators + ***********************************************************************/ +/* Validate if the number of sides are consistent among internal data arrays ! */ +bool RRGSB::validate_num_sides() const { + size_t num_sides = chan_node_direction_.size(); + + if ( num_sides != chan_node_.size() ) { + return false; + } + + if ( num_sides != ipin_node_.size() ) { + return false; + } + + if ( num_sides != opin_node_.size() ) { + return false; + } + + return true; +} + +/* Check if the side valid in the context: does the switch block have the side? */ +bool RRGSB::validate_side(const e_side& side) const { + return (size_t(side) < get_num_sides()); +} + +/* Check the track_id is valid for chan_node_ and chan_node_direction_ */ +bool RRGSB::validate_track_id(const e_side& side, const size_t& track_id) const { + if (false == validate_side(side)) { + return false; + } + + return ( ( track_id < chan_node_[size_t(side)].get_chan_width()) + && ( track_id < chan_node_direction_[size_t(side)].size()) ); +} + +/* Check the opin_node_id is valid for opin_node_ and opin_node_grid_side_ */ +bool RRGSB::validate_opin_node_id(const e_side& side, const size_t& node_id) const { + if (false == validate_side(side)) { + return false; + } + return (node_id < opin_node_[size_t(side)].size()); +} + +/* Check the ipin_node_id is valid for opin_node_ and opin_node_grid_side_ */ +bool RRGSB::validate_ipin_node_id(const e_side& side, const size_t& node_id) const { + if (false == validate_side(side)) { + return false; + } + return (node_id < ipin_node_[size_t(side)].size()); +} + +bool RRGSB::validate_cb_type(const t_rr_type& cb_type) const { + return ( (CHANX == cb_type) || (CHANY == cb_type) ); +} + +} /* End namespace openfpga*/ diff --git a/vpr/src/tileable_rr_graph/rr_gsb.h b/vpr/src/tileable_rr_graph/rr_gsb.h new file mode 100644 index 00000000000..279f206f9da --- /dev/null +++ b/vpr/src/tileable_rr_graph/rr_gsb.h @@ -0,0 +1,289 @@ +#ifndef RR_GSB_H +#define RR_GSB_H + +/******************************************************************** + * Include header files required by the data structure definition + *******************************************************************/ +/* Headers from vtrutil library */ +#include "vtr_geometry.h" + +#include "rr_chan.h" + +/* Begin namespace openfpga */ +namespace openfpga { + +/******************************************************************** + * Object Generic Switch Block + * This block contains + * 1. A switch block + * 2. A X-direction Connection block locates at the left side of the switch block + * 2. A Y-direction Connection block locates at the top side of the switch block + * + * +-------------+ +---------------------------------+ + * | | | Y-direction CB | + * | Grid | | [x][y + 1] | + * | [x][y+1] | +---------------------------------+ + * +-------------+ + * TOP SIDE + * +-------------+ +---------------------------------+ + * | | | OPIN_NODE CHAN_NODES OPIN_NODES | + * | | | | + * | | | OPIN_NODES OPIN_NODES | + * | X-direction | | | + * | CB | LEFT SIDE | Switch Block | RIGHT SIDE + * | [x][y] | | [x][y] | + * | | | | + * | | | CHAN_NODES CHAN_NODES | + * | | | | + * | | | OPIN_NODES OPIN_NODES | + * | | | | + * | | | OPIN_NODE CHAN_NODES OPIN_NODES | + * +-------------+ +---------------------------------+ + * BOTTOM SIDE + * num_sides: number of sides of this switch block + * chan_rr_node: a collection of rr_nodes as routing tracks locating at each side of the Switch block <0..num_sides-1><0..chan_width-1> + * chan_rr_node_direction: Indicate if this rr_node is an input or an output of the Switch block <0..num_sides-1><0..chan_width-1> + * ipin_rr_node: a collection of rr_nodes as IPIN of a GRID locating at each side of the Switch block <0..num_sides-1><0..num_ipin_rr_nodes-1> + * ipin_rr_node_grid_side: specify the side of the input pins on which side of a GRID <0..num_sides-1><0..num_ipin_rr_nodes-1> + * opin_rr_node: a collection of rr_nodes as OPIN of a GRID locating at each side of the Switch block <0..num_sides-1><0..num_opin_rr_nodes-1> + * opin_rr_node_grid_side: specify the side of the output pins on which side of a GRID <0..num_sides-1><0..num_opin_rr_nodes-1> + * num_reserved_conf_bits: number of reserved configuration bits this switch block requires (mainly due to RRAM-based multiplexers) + * num_conf_bits: number of configuration bits this switch block requires + *******************************************************************/ +class RRGSB { + public: /* Contructors */ + RRGSB();/* Default constructor */ + public: /* Accessors */ + /* Get the number of sides of this SB */ + size_t get_num_sides() const; + + /* Get the number of routing tracks on a side */ + size_t get_chan_width(const e_side& side) const; + + /* Get the type of routing tracks on a side */ + t_rr_type get_chan_type(const e_side& side) const; + + /* Get the maximum number of routing tracks on all sides */ + size_t get_max_chan_width() const; + + /* Get the number of routing tracks of a X/Y-direction CB */ + size_t get_cb_chan_width(const t_rr_type& cb_type) const; + + /* Get the sides of CB ipins in the array */ + std::vector get_cb_ipin_sides(const t_rr_type& cb_type) const; + + /* Get the direction of a rr_node at a given side and track_id */ + enum PORTS get_chan_node_direction(const e_side& side, const size_t& track_id) const; + + /* Get a list of segments used in this routing channel */ + std::vector get_chan_segment_ids(const e_side& side) const; + + /* Get a list of segments used in this routing channel */ + std::vector get_chan_node_ids_by_segment_ids(const e_side& side, + const RRSegmentId& seg_id) const; + + /* get a rr_node at a given side and track_id */ + RRNodeId get_chan_node(const e_side& side, const size_t& track_id) const; + + /* get all the sorted incoming edges for a rr_node at a given side and track_id */ + std::vector get_chan_node_in_edges(const RRGraph& rr_graph, + const e_side& side, + const size_t& track_id) const; + + /* get the segment id of a channel rr_node */ + RRSegmentId get_chan_node_segment(const e_side& side, const size_t& track_id) const; + + /* Get the number of IPIN rr_nodes on a side */ + size_t get_num_ipin_nodes(const e_side& side) const; + + /* get a rr_node at a given side and track_id */ + RRNodeId get_ipin_node(const e_side& side, const size_t& node_id) const; + + /* Get the number of OPIN rr_nodes on a side */ + size_t get_num_opin_nodes(const e_side& side) const; + + /* get a rr_node at a given side and track_id */ + RRNodeId get_opin_node(const e_side& side, const size_t& node_id) const; + + int get_cb_chan_node_index(const t_rr_type& cb_type, const RRNodeId& node) const; + + int get_chan_node_index(const e_side& node_side, const RRNodeId& node) const; + + /* Get the node index in the array, return -1 if not found */ + int get_node_index(const RRGraph& rr_graph, const RRNodeId& node, const e_side& node_side, const PORTS& node_direction) const; + + /* Given a rr_node, try to find its side and index in the Switch block */ + void get_node_side_and_index(const RRGraph& rr_graph, const RRNodeId& node, const PORTS& node_direction, e_side& node_side, int& node_index) const; + + /* Check if the node exist in the opposite side of this Switch Block */ + bool is_sb_node_exist_opposite_side(const RRGraph& rr_graph, const RRNodeId& node, const e_side& node_side) const; + public: /* Accessors: to identify mirrors */ + /* check if the candidate SB is a mirror of the current one */ + bool is_cb_mirror(const RRGraph& rr_graph, const RRGSB& cand, const t_rr_type& cb_type) const; + + /* check if the connect block exists in the GSB */ + bool is_cb_exist(const t_rr_type& cb_type) const; + + /* check if the switch block exists in the GSB */ + bool is_sb_exist() const; + + /* Check if the node imply a short connection inside the SB, which happens to long wires across a FPGA fabric */ + bool is_sb_node_passing_wire(const RRGraph& rr_graph, const e_side& node_side, const size_t& track_id) const; + + /* check if the candidate SB satisfy the basic requirements + * on being a mirror of the current one + */ + bool is_sb_mirrorable(const RRGraph& rr_graph, const RRGSB& cand) const; + + /* check if all the routing segments of a side of candidate SB is a mirror of the current one */ + bool is_sb_side_segment_mirror(const RRGraph& rr_graph, const RRGSB& cand, + const e_side& side, const RRSegmentId& seg_id) const; + + /* check if a side of candidate SB is a mirror of the current one + * Check the specified side of two switch blocks: + * 1. Number of channel/opin/ipin rr_nodes are same + * For channel rr_nodes + * 2. check if their track_ids (ptc_num) are same + * 3. Check if the switches (ids) are same + * For opin/ipin rr_nodes, + * 4. check if their parent type_descriptors same, + * 5. check if pin class id and pin id are same + * If all above are satisfied, the side of the two switch blocks are mirrors! + */ + bool is_sb_side_mirror(const RRGraph& rr_graph, const RRGSB& cand, const e_side& side) const; + + /* check if the candidate SB is a mirror of the current one + * Idenify mirror Switch blocks + * Check each two switch blocks: + * 1. Number of channel/opin/ipin rr_nodes are same + * For channel rr_nodes + * 2. check if their track_ids (ptc_num) are same + * 3. Check if the switches (ids) are same + * For opin/ipin rr_nodes, + * 4. check if their parent type_descriptors same, + * 5. check if pin class id and pin id are same + * If all above are satisfied, the two switch blocks are mirrors! + */ + bool is_sb_mirror(const RRGraph& rr_graph, const RRGSB& cand) const; + + public: /* Cooridinator conversion and output */ + size_t get_x() const; /* get the x coordinate of this switch block */ + size_t get_y() const; /* get the y coordinate of this switch block */ + size_t get_sb_x() const; /* get the x coordinate of this switch block */ + size_t get_sb_y() const; /* get the y coordinate of this switch block */ + vtr::Point get_sb_coordinate() const; /* Get the coordinate of the SB */ + size_t get_cb_x(const t_rr_type& cb_type) const; /* get the x coordinate of this X/Y-direction block */ + size_t get_cb_y(const t_rr_type& cb_type) const; /* get the y coordinate of this X/Y-direction block */ + vtr::Point get_cb_coordinate(const t_rr_type& cb_type) const; /* Get the coordinate of the X/Y-direction CB */ + e_side get_cb_chan_side(const t_rr_type& cb_type) const; /* get the side of a Connection block */ + e_side get_cb_chan_side(const e_side& ipin_side) const; /* get the side of a Connection block */ + vtr::Point get_side_block_coordinate(const e_side& side) const; + vtr::Point get_grid_coordinate() const; + public: /* Mutators */ + /* get a copy from a source */ + void set(const RRGSB& src); + void set_coordinate(const size_t& x, const size_t& y); + + /* 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(); + + /* Clean the chan_width of a side */ + void clear_chan_nodes(const e_side& node_side); + + /* Clean the number of IPINs of a side */ + void clear_ipin_nodes(const e_side& node_side); + + /* Clean the number of OPINs of a side */ + void clear_opin_nodes(const e_side& node_side); + + /* 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, + const e_side& node_side, + const size_t& track_id) const; + + bool is_cb_node_mirror(const RRGraph& rr_graph, + const RRGSB& cand, + const t_rr_type& cb_type, + const e_side& node_side, + const size_t& node_id) const; + + size_t get_track_id_first_short_connection(const RRGraph& rr_graph, const e_side& node_side) const; + + private: /* internal validators */ + bool validate_num_sides() const; + bool validate_side(const e_side& side) const; + bool validate_track_id(const e_side& side, const size_t& track_id) const; + bool validate_opin_node_id(const e_side& side, const size_t& node_id) const; + bool validate_ipin_node_id(const e_side& side, const size_t& node_id) const; + bool validate_cb_type(const t_rr_type& cb_type) const; + private: /* Internal Data */ + /* Coordinator */ + vtr::Point coordinate_; + + /* 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_; + + /* Logic Block Outputs data */ + std::vector> opin_node_; +}; + +} /* End namespace openfpga*/ + +#endif diff --git a/vpr/src/tileable_rr_graph/tileable_chan_details_builder.cpp b/vpr/src/tileable_rr_graph/tileable_chan_details_builder.cpp new file mode 100644 index 00000000000..2436d170c6d --- /dev/null +++ b/vpr/src/tileable_rr_graph/tileable_chan_details_builder.cpp @@ -0,0 +1,234 @@ +/************************************************************************ + * This file contains a builder for the ChanNodeDetails data structure + * Different from VPR rr_graph builders, this builder aims to create a + * highly regular routing channel. Thus, it is called tileable, + * which brings significant advantage in producing large FPGA fabrics. + ***********************************************************************/ +#include +#include + +/* Headers from vtrutil library */ +#include "vtr_assert.h" +#include "vtr_log.h" + +#include "rr_graph_builder_utils.h" +#include "tileable_chan_details_builder.h" + +/* begin namespace openfpga */ +namespace openfpga { + +/************************************************************************ + * Generate the number of tracks for each types of routing segments + * w.r.t. the frequency of each of segments and channel width + * Note that if we dertermine the number of tracks per type using + * chan_width * segment_frequency / total_freq may cause + * The total track num may not match the chan_width, + * therefore, we assign tracks one by one until we meet the frequency requirement + * In this way, we can assign the number of tracks with repect to frequency + ***********************************************************************/ +std::vector get_num_tracks_per_seg_type(const size_t& chan_width, + const std::vector& segment_inf, + const bool& use_full_seg_groups) { + std::vector result; + std::vector demand; + /* Make sure a clean start */ + result.resize(segment_inf.size()); + demand.resize(segment_inf.size()); + + /* Scale factor so we can divide by any length + * and still use integers */ + /* Get the sum of frequency */ + size_t scale = 1; + size_t freq_sum = 0; + for (size_t iseg = 0; iseg < segment_inf.size(); ++iseg) { + scale *= segment_inf[iseg].length; + freq_sum += segment_inf[iseg].frequency; + } + size_t reduce = scale * freq_sum; + + /* Init assignments to 0 and set the demand values */ + /* Get the fraction of each segment type considering the frequency: + * num_track_per_seg = chan_width * (freq_of_seg / sum_freq) + */ + for (size_t iseg = 0; iseg < segment_inf.size(); ++iseg) { + result[iseg] = 0; + demand[iseg] = scale * chan_width * segment_inf[iseg].frequency; + if (true == use_full_seg_groups) { + demand[iseg] /= segment_inf[iseg].length; + } + } + + /* check if the sum of num_tracks, matches the chan_width */ + /* Keep assigning tracks until we use them up */ + size_t assigned = 0; + size_t size = 0; + size_t imax = 0; + while (assigned < chan_width) { + /* Find current maximum demand */ + double max = 0; + for (size_t iseg = 0; iseg < segment_inf.size(); ++iseg) { + if (demand[iseg] > max) { + imax = iseg; + } + max = std::max(demand[iseg], max); + } + + /* Assign tracks to the type and reduce the types demand */ + size = (use_full_seg_groups ? segment_inf[imax].length : 1); + demand[imax] -= reduce; + result[imax] += size; + assigned += size; + } + + /* Undo last assignment if we were closer to goal without it */ + if ((assigned - chan_width) > (size / 2)) { + result[imax] -= size; + } + + return result; +} + +/************************************************************************ + * Adapt the number of channel width to a tileable routing architecture + ***********************************************************************/ +int adapt_to_tileable_route_chan_width(const int& chan_width, + const std::vector& segment_infs) { + int tileable_chan_width = 0; + + /* Estimate the number of segments per type by the given ChanW*/ + std::vector num_tracks_per_seg_type = get_num_tracks_per_seg_type(chan_width, + segment_infs, + true); /* Force to use the full segment group */ + /* Sum-up the number of tracks */ + for (size_t iseg = 0; iseg < num_tracks_per_seg_type.size(); ++iseg) { + tileable_chan_width += num_tracks_per_seg_type[iseg]; + } + + return tileable_chan_width; +} + +/************************************************************************ + * Build details of routing tracks in a channel + * The function will + * 1. Assign the segments for each routing channel, + * To be specific, for each routing track, we assign a routing segment. + * The assignment is subject to users' specifications, such as + * a. length of each type of segment + * b. frequency of each type of segment. + * c. routing channel width + * + * 2. The starting point of each segment in the channel will be assigned + * For each segment group with same directionality (tracks have the same length), + * every L track will be a starting point (where L denotes the length of segments) + * In this case, if the number of tracks is not a multiple of L, + * indeed we may have some | Yes | No | + * +---------------------------------------+--------------+ + * | 1 | <--------MUX | Yes | No | + * +---------------------------------------+--------------+ + * | 2 | --------> | No | No | + * +---------------------------------------+--------------+ + * | 3 | <-------- | No | No | + * +---------------------------------------+--------------+ + * | 4 | --------> | No | No | + * +---------------------------------------+--------------+ + * | 5 | <-------- | No | No | + * +---------------------------------------+--------------+ + * | 7 | -------->MUX | No | Yes | + * +---------------------------------------+--------------+ + * | 8 | MUX<-------- | No | Yes | + * +---------------------------------------+--------------+ + * | 9 | MUX--------> | Yes | No | + * +---------------------------------------+--------------+ + * | 10 | <--------MUX | Yes | No | + * +---------------------------------------+--------------+ + * | 11 | -------->MUX | No | Yes | + * +------------------------------------------------------+ + * | 12 | <-------- | No | No | + * +------------------------------------------------------+ + * + * 3. SPECIAL for fringes: TOP|RIGHT|BOTTOM|RIGHT + * if device_side is NUM_SIDES, we assume this channel does not locate on borders + * All segments will start and ends with no exception + * + * 4. IMPORTANT: we should be aware that channel width maybe different + * in X-direction and Y-direction channels!!! + * So we will load segment details for different channels + ***********************************************************************/ +ChanNodeDetails build_unidir_chan_node_details(const size_t& chan_width, + const size_t& max_seg_length, + const bool& force_start, + const bool& force_end, + const std::vector& segment_inf) { + ChanNodeDetails chan_node_details; + size_t actual_chan_width = find_unidir_routing_channel_width(chan_width); + VTR_ASSERT(0 == actual_chan_width % 2); + + /* Reserve channel width */ + chan_node_details.reserve(chan_width); + /* Return if zero width is forced */ + if (0 == actual_chan_width) { + return chan_node_details; + } + + /* Find the number of segments required by each group */ + std::vector num_tracks = get_num_tracks_per_seg_type(actual_chan_width / 2, segment_inf, false); + + /* Add node to ChanNodeDetails */ + size_t cur_track = 0; + for (size_t iseg = 0; iseg < segment_inf.size(); ++iseg) { + /* segment length will be set to maxium segment length if this is a longwire */ + size_t seg_len = segment_inf[iseg].length; + if (true == segment_inf[iseg].longline) { + seg_len = max_seg_length; + } + for (size_t itrack = 0; itrack < num_tracks[iseg]; ++itrack) { + bool seg_start = false; + bool seg_end = false; + /* Every first track of a group of Length-N wires, we set a starting point */ + if (0 == itrack % seg_len) { + seg_start = true; + } + /* Every last track of a group of Length-N wires or this is the last track in this group, we set an ending point */ + if ( (seg_len - 1 == itrack % seg_len) + || (itrack == num_tracks[iseg] - 1) ) { + seg_end = true; + } + /* Since this is a unidirectional routing architecture, + * Add a pair of tracks, 1 INC track and 1 DEC track + */ + chan_node_details.add_track(cur_track, Direction::INC, iseg, seg_len, seg_start, seg_end); + cur_track++; + chan_node_details.add_track(cur_track, Direction::DEC, iseg, seg_len, seg_start, seg_end); + cur_track++; + } + } + /* Check if all the tracks have been satisified */ + VTR_ASSERT(cur_track == actual_chan_width); + + /* If this is on the border of a device/heterogeneous blocks, segments should start/end */ + if (true == force_start) { + /* INC should all start */ + chan_node_details.set_tracks_start(Direction::INC); + /* DEC should all end */ + chan_node_details.set_tracks_end(Direction::DEC); + } + + /* If this is on the border of a device/heterogeneous blocks, segments should start/end */ + if (true == force_end) { + /* INC should all end */ + chan_node_details.set_tracks_end(Direction::INC); + /* DEC should all start */ + chan_node_details.set_tracks_start(Direction::DEC); + } + + return chan_node_details; +} + +} /* end namespace openfpga */ diff --git a/vpr/src/tileable_rr_graph/tileable_chan_details_builder.h b/vpr/src/tileable_rr_graph/tileable_chan_details_builder.h new file mode 100644 index 00000000000..e6adb71621b --- /dev/null +++ b/vpr/src/tileable_rr_graph/tileable_chan_details_builder.h @@ -0,0 +1,32 @@ +#ifndef TILEABLE_CHAN_DETAILS_BUILDER_H +#define TILEABLE_CHAN_DETAILS_BUILDER_H + +/******************************************************************** + * Include header files that are required by function declaration + *******************************************************************/ +#include +#include "physical_types.h" +#include "chan_node_details.h" + +/******************************************************************** + * Function declaration + *******************************************************************/ + +/* begin namespace openfpga */ +namespace openfpga { + +std::vector get_num_tracks_per_seg_type(const size_t& chan_width, + const std::vector& segment_inf, + const bool& use_full_seg_groups); + +int adapt_to_tileable_route_chan_width(const int& chan_width, const std::vector& segment_inf); + +ChanNodeDetails build_unidir_chan_node_details(const size_t& chan_width, + const size_t& max_seg_length, + const bool& force_start, + const bool& force_end, + const std::vector& segment_inf); + +} /* end namespace openfpga */ + +#endif diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp new file mode 100644 index 00000000000..43c41de5416 --- /dev/null +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp @@ -0,0 +1,370 @@ +/************************************************************************ + * This file contains a builder for the complex rr_graph data structure + * Different from VPR rr_graph builders, this builder aims to create a + * highly regular rr_graph, where each Connection Block (CB), Switch + * Block (SB) is the same (except for those on the borders). Thus, the + * rr_graph is called tileable, which brings significant advantage in + * producing large FPGA fabrics. + ***********************************************************************/ +/* Headers from vtrutil library */ +#include "vtr_assert.h" +#include "vtr_time.h" +#include "vtr_log.h" +#include "vtr_memory.h" + +#include "vpr_error.h" +#include "vpr_utils.h" + +#include "rr_graph.h" +#include "check_rr_graph.h" +#include "check_rr_graph_obj.h" + +#include "rr_graph_builder_utils.h" +#include "tileable_chan_details_builder.h" +#include "tileable_rr_graph_node_builder.h" +#include "tileable_rr_graph_edge_builder.h" +#include "tileable_rr_graph_builder.h" + +#include "globals.h" + +/* begin namespace openfpga */ +namespace openfpga { + +/************************************************************************ + * Main function of this file + * Builder for a detailed uni-directional tileable rr_graph + * Global graph is not supported here, the VPR rr_graph generator can be used + * It follows the procedures to complete the rr_graph generation + * 1. Assign the segments for each routing channel, + * To be specific, for each routing track, we assign a routing segment. + * The assignment is subject to users' specifications, such as + * a. length of each type of segment + * b. frequency of each type of segment. + * c. routing channel width + * 2. Estimate the number of nodes in the rr_graph + * This will estimate the number of + * a. IPINs, input pins of each grid + * b. OPINs, output pins of each grid + * c. SOURCE, virtual node which drives OPINs + * d. SINK, virtual node which is connected to IPINs + * e. CHANX and CHANY, routing segments of each channel + * 3. Create the connectivity of OPINs + * a. Evenly assign connections to OPINs to routing tracks + * b. the connection pattern should be same across the fabric + * 4. Create the connectivity of IPINs + * a. Evenly assign connections from routing tracks to IPINs + * b. the connection pattern should be same across the fabric + * 5. Create the switch block patterns, + * It is based on the type of switch block, the supported patterns are + * a. Disjoint, which connects routing track (i)th from (i)th and (i)th routing segments + * b. Universal, which connects routing track (i)th from (i)th and (M-i)th routing segments + * c. Wilton, which rotates the connection of Disjoint by 1 track + * 6. Allocate rr_graph, fill the node information + * For each node, fill + * a. basic information: coordinate(xlow, xhigh, ylow, yhigh), ptc_num + * b. edges (both incoming and outcoming) + * c. handle direct-connections + * 7. Build fast look-up for the rr_graph + * 8. Allocate external data structures + * a. cost_index + * b. RC tree + ***********************************************************************/ + +// external functions: in vpr/src/route/rr_graph.cpp +extern std::vector> alloc_and_load_actual_fc(const std::vector& types, + const int max_pins, + const std::vector& segment_inf, + + const int* sets_per_seg_type, + const int max_chan_width, + const e_fc_type fc_type, + const enum e_directionality directionality, + bool* Fc_clipped); +extern t_clb_to_clb_directs* alloc_and_load_clb_to_clb_directs(const t_direct_inf* directs, const int num_directs, int delayless_switch); +extern void alloc_and_load_rr_switch_inf(const int num_arch_switches, + const float R_minW_nmos, + const float R_minW_pmos, + const int wire_to_arch_ipin_switch, + int* wire_to_rr_ipin_switch); +extern void rr_graph_externals(const std::vector& segment_inf, + int wire_to_rr_ipin_switch, + enum e_base_cost_type base_cost_type); + +void build_tileable_unidir_rr_graph(const std::vector& types, + const DeviceGrid& grids, + const t_chan_width& chan_width, + const e_switch_block_type& sb_type, const int& Fs, + const e_switch_block_type& sb_subtype, const int& subFs, + const std::vector& segment_inf, + const int& delayless_switch, + const int& wire_to_arch_ipin_switch, + const float R_minW_nmos, + const float R_minW_pmos, + const enum e_base_cost_type& base_cost_type, + const t_direct_inf *directs, + const int& num_directs, + int* wire_to_rr_ipin_switch, + const bool& through_channel, + const bool& wire_opposite_side, + int *Warnings) { + + vtr::ScopedStartFinishTimer timer("Build tileable routing resource graph"); + + /* Reset warning flag */ + *Warnings = RR_GRAPH_NO_WARN; + + /* Create a matrix of grid */ + /* Create a vector of channel width, we support X-direction and Y-direction has different W */ + vtr::Point device_chan_width(chan_width.x_max, chan_width.y_max); + + VTR_LOG("X-direction routing channel width is %lu\n", device_chan_width.x()); + VTR_LOG("Y-direction routing channel width is %lu\n", device_chan_width.y()); + + /* Get a mutable device ctx so that we have a mutable rr_graph */ + DeviceContext& device_ctx = g_vpr_ctx.mutable_device(); + + /* The number of segments are in general small, reserve segments may not bring + * significant memory efficiency */ + device_ctx.rr_graph_builder.reserve_segments(segment_inf.size()); + /* Create the segments */ + for (size_t iseg = 0; iseg < segment_inf.size(); ++iseg) { + device_ctx.rr_graph_builder.add_rr_segment(segment_inf[iseg]); + } + + /* TODO: Load architecture switch to rr_graph switches + * Draft the switches as internal data of RRGraph object + * These are temporary switches copied from arch switches + * We use them to build the edges + * We will reset all the switches in the function + * alloc_and_load_rr_switch_inf() + */ + /* TODO: Spot the switch id in the architecture switch list */ + RRSwitchId wire_to_ipin_rr_switch = RRSwitchId::INVALID(); + RRSwitchId delayless_rr_switch = RRSwitchId::INVALID(); + + device_ctx.rr_graph_builder.reserve_switches(device_ctx.num_arch_switches); + /* Create the switches */ + for (int iswitch = 0; iswitch < device_ctx.num_arch_switches; ++iswitch) { + const t_rr_switch_inf& temp_rr_switch = create_rr_switch_from_arch_switch(iswitch, R_minW_nmos, R_minW_pmos); + RRSwitchId rr_switch = device_ctx.rr_graph_builder.add_rr_switch(temp_rr_switch); + if (iswitch == wire_to_arch_ipin_switch) { + wire_to_ipin_rr_switch = rr_switch; + } + if (iswitch == delayless_switch) { + delayless_rr_switch = rr_switch; + } + } + // NYI + #if 0 + /* Validate the special switches */ + VTR_ASSERT(true == device_ctx.rr_graph_builder.valid_switch_id(wire_to_ipin_rr_switch)); + VTR_ASSERT(true == device_ctx.rr_graph_builder.valid_switch_id(delayless_rr_switch)); + #endif + + /* A temp data about the driver switch ids for each rr_node */ + vtr::vector rr_node_driver_switches; + + /* A temp data about the track ids for each CHANX and CHANY rr_node */ + std::map> rr_node_track_ids; + + /************************ + * Allocate the rr_nodes + ************************/ + alloc_tileable_rr_graph_nodes(device_ctx.rr_graph_builder, + rr_node_driver_switches, + grids, + device_chan_width, + segment_inf, + through_channel); + + /************************ + * Create all the rr_nodes + ************************/ + create_tileable_rr_graph_nodes(device_ctx.rr_graph, + device_ctx.rr_graph_builder, + rr_node_driver_switches, + rr_node_track_ids, + grids, + device_chan_width, + segment_inf, + wire_to_ipin_rr_switch, + delayless_rr_switch, + through_channel); + + /************************************************************************ + * Create the connectivity of OPINs + * a. Evenly assign connections to OPINs to routing tracks + * b. the connection pattern should be same across the fabric + * + * Create the connectivity of IPINs + * a. Evenly assign connections from routing tracks to IPINs + * b. the connection pattern should be same across the fabric + ***********************************************************************/ + /* Global routing uses a single longwire track */ + int max_chan_width = find_unidir_routing_channel_width(chan_width.max); + VTR_ASSERT(max_chan_width > 0); + + /* get maximum number of pins across all blocks */ + int max_pins = types[0].num_pins; + for (const auto& type : types) { + if (is_empty_type(&type)) { + continue; + } + + if (type.num_pins > max_pins) { + max_pins = type.num_pins; + } + } + + /* Fc assignment still uses the old function from VPR. + * Should use tileable version so that we have can have full control + */ + std::vector num_tracks = get_num_tracks_per_seg_type(max_chan_width / 2, segment_inf, false); + int* sets_per_seg_type = (int*)vtr::malloc(sizeof(int) * segment_inf.size()); + VTR_ASSERT(num_tracks.size() == segment_inf.size()); + for (size_t iseg = 0; iseg < num_tracks.size(); ++iseg) { + sets_per_seg_type[iseg] = num_tracks[iseg]; + } + + bool Fc_clipped = false; + /* [0..num_types-1][0..num_pins-1] */ + std::vector> Fc_in; + Fc_in = alloc_and_load_actual_fc(types, max_pins, segment_inf, sets_per_seg_type, max_chan_width, + e_fc_type::IN, UNI_DIRECTIONAL, &Fc_clipped); + if (Fc_clipped) { + *Warnings |= RR_GRAPH_WARN_FC_CLIPPED; + } + + Fc_clipped = false; + /* [0..num_types-1][0..num_pins-1] */ + std::vector> Fc_out; + Fc_out = alloc_and_load_actual_fc(types, max_pins, segment_inf, sets_per_seg_type, max_chan_width, + e_fc_type::OUT, UNI_DIRECTIONAL, &Fc_clipped); + + if (Fc_clipped) { + *Warnings |= RR_GRAPH_WARN_FC_CLIPPED; + } + + /************************************************************************ + * Build the connections tile by tile: + * We classify rr_nodes into a general switch block (GSB) data structure + * where we create edges to each rr_nodes in the GSB with respect to + * Fc_in and Fc_out, switch block patterns + * In addition, we will also handle direct-connections: + * Add edges that bridge OPINs and IPINs to the rr_graph + ***********************************************************************/ + /* Create edges for a tileable rr_graph */ + build_rr_graph_edges(device_ctx.rr_graph, + rr_node_driver_switches, + grids, + device_chan_width, + segment_inf, + Fc_in, Fc_out, + sb_type, Fs, sb_subtype, subFs, + wire_opposite_side); + + /************************************************************************ + * Build direction connection lists + * TODO: use tile direct builder + ***********************************************************************/ + /* Create data structure of direct-connections */ + t_clb_to_clb_directs* clb_to_clb_directs = NULL; + if (num_directs > 0) { + clb_to_clb_directs = alloc_and_load_clb_to_clb_directs(directs, num_directs, delayless_switch); + } + std::vector arch_directs; + std::vector clb2clb_directs; + for (int idirect = 0; idirect < num_directs; ++idirect) { + arch_directs.push_back(directs[idirect]); + clb2clb_directs.push_back(clb_to_clb_directs[idirect]); + } + + build_rr_graph_direct_connections(device_ctx.rr_graph, grids, delayless_rr_switch, + arch_directs, clb2clb_directs); + +//NYI +#if 0 + /* First time to build edges so that we can remap the architecture switch to rr_switch + * This is a must-do before function alloc_and_load_rr_switch_inf() + */ + device_ctx.rr_graph.rebuild_node_edges(); +#endif + + /* Allocate and load routing resource switches, which are derived from the switches from the architecture file, + * based on their fanin in the rr graph. This routine also adjusts the rr nodes to point to these new rr switches */ + alloc_and_load_rr_switch_inf(device_ctx.num_arch_switches, R_minW_nmos, R_minW_pmos, wire_to_arch_ipin_switch, wire_to_rr_ipin_switch); + + /* Save the channel widths for the newly constructed graph */ + device_ctx.chan_width = chan_width; + +//NYI +#if 0 + /* Save the track ids for tileable routing resource graph */ + device_ctx.rr_node_track_ids = rr_node_track_ids; +#endif + + /************************************************************************ + * Allocate external data structures + * a. cost_index + * b. RC tree + ***********************************************************************/ + rr_graph_externals(segment_inf, + *wire_to_rr_ipin_switch, base_cost_type); + + /* Rebuild the link between RRGraph node and segments + * Should be called only AFTER the function + * rr_graph_externals() + */ + for (const RRNodeId& inode : device_ctx.rr_graph.nodes()) { + if ( (CHANX != device_ctx.rr_graph.node_type(inode)) + && (CHANY != device_ctx.rr_graph.node_type(inode)) ) { + continue; + } +//NYI +#if 0 + RRIndexedDataId irc_data = device_ctx.rr_graph.node_cost_index(inode); + short iseg = device_ctx.rr_indexed_data[irc_data].seg_index; + device_ctx.rr_graph_builder.set_node_segment(inode, RRSegmentId(iseg)); // NYI +#endif + + } + + /************************************************************************ + * Sanitizer for the rr_graph, check connectivities of rr_nodes + ***********************************************************************/ + /* Essential check for rr_graph, build look-up and */ + if (false == device_ctx.rr_graph_builder.validate()) { + /* Error out if built-in validator of rr_graph fails */ + vpr_throw(VPR_ERROR_ROUTE, + __FILE__, + __LINE__, + "Fundamental errors occurred when validating rr_graph object!\n"); + } + + check_rr_graph(GRAPH_UNIDIR, grids, types); + + // NYI + // vpr integration: DeviceContext does not provide direct RRGraph access + // we can skip it since check_rr_graph(GRAPH_UNDIR, GRIDS, TYPES) has been called above +#if 0 + /* Error out if advanced checker of rr_graph fails */ + if (false == check_rr_graph(device_ctx.rr_graph)) { + vpr_throw(VPR_ERROR_ROUTE, + __FILE__, + __LINE__, + "Advanced checking rr_graph object fails! Routing may still work " + "but not smooth\n"); + } +#endif + + /************************************************************************ + * Free all temp stucts + ***********************************************************************/ + free(sets_per_seg_type); + + if (nullptr != clb_to_clb_directs) { + free(clb_to_clb_directs); + } +} + +} /* end namespace openfpga */ diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.h b/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.h new file mode 100644 index 00000000000..46be3817d76 --- /dev/null +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.h @@ -0,0 +1,39 @@ +#ifndef TILEABLE_RR_GRAPH_BUILDER_H +#define TILEABLE_RR_GRAPH_BUILDER_H + +/******************************************************************** + * Include header files that are required by function declaration + *******************************************************************/ +#include + +#include "physical_types.h" +#include "device_grid.h" + +/******************************************************************** + * Function declaration + *******************************************************************/ + +/* begin namespace openfpga */ +namespace openfpga { + +void build_tileable_unidir_rr_graph(const std::vector& types, + const DeviceGrid& grids, + const t_chan_width& chan_width, + const e_switch_block_type& sb_type, const int& Fs, + const e_switch_block_type& sb_subtype, const int& subFs, + const std::vector& segment_inf, + const int& delayless_switch, + const int& wire_to_arch_ipin_switch, + const float R_minW_nmos, + const float R_minW_pmos, + const enum e_base_cost_type& base_cost_type, + const t_direct_inf *directs, + const int& num_directs, + int* wire_to_rr_ipin_switch, + const bool& through_channel, + const bool& wire_opposite_side, + int *Warnings); + +} /* end namespace openfpga */ + +#endif diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp new file mode 100644 index 00000000000..fd2d4db62d8 --- /dev/null +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp @@ -0,0 +1,170 @@ +/************************************************************************ + * This file contains functions that are used to build edges + * between nodes of a tileable routing resource graph + ***********************************************************************/ +#include + +/* Headers from vtrutil library */ +#include "vtr_assert.h" +#include "vtr_log.h" +#include "vtr_time.h" + +#include "vpr_utils.h" + +#include "rr_graph_builder_utils.h" +#include "tileable_rr_graph_gsb.h" +#include "tileable_rr_graph_edge_builder.h" + +/* begin namespace openfpga */ +namespace openfpga { + +/************************************************************************ + * Build the edges for all the SOURCE and SINKs nodes: + * 1. create edges between SOURCE and OPINs + ***********************************************************************/ +static +void build_rr_graph_edges_for_source_nodes(RRGraph& rr_graph, + const vtr::vector& rr_node_driver_switches, + const DeviceGrid& grids) { + for (const RRNodeId& node : rr_graph.nodes()) { + /* Bypass all the non OPIN nodes */ + if (OPIN != rr_graph.node_type(node)) { + continue; + } + /* Now, we have an OPIN node, we get the source node index */ + short xlow = rr_graph.node_xlow(node); + short ylow = rr_graph.node_ylow(node); + short src_node_class_num = get_grid_pin_class_index(grids[xlow][ylow], + rr_graph.node_pin_num(node)); + + /* Create edges between SOURCE and OPINs */ + const RRNodeId& src_node = rr_graph.find_node(xlow - grids[xlow][ylow].width_offset, + ylow - grids[xlow][ylow].height_offset, + SOURCE, src_node_class_num); + VTR_ASSERT(true == rr_graph.valid_node_id(src_node)); + + /* add edges to the src_node */ + rr_graph.create_edge(src_node, node, rr_node_driver_switches[node]); + } +} + +/************************************************************************ + * Build the edges for all the SINKs nodes: + * 1. create edges between IPINs and SINKs + ***********************************************************************/ +static +void build_rr_graph_edges_for_sink_nodes(RRGraph& rr_graph, + const vtr::vector& rr_node_driver_switches, + const DeviceGrid& grids) { + for (const RRNodeId& node : rr_graph.nodes()) { + /* Bypass all the non IPIN nodes */ + if (IPIN != rr_graph.node_type(node)) { + continue; + } + /* Now, we have an OPIN node, we get the source node index */ + short xlow = rr_graph.node_xlow(node); + short ylow = rr_graph.node_ylow(node); + short sink_node_class_num = get_grid_pin_class_index(grids[xlow][ylow], + rr_graph.node_pin_num(node)); + /* 1. create edges between IPINs and SINKs */ + const RRNodeId& sink_node = rr_graph.find_node(xlow - grids[xlow][ylow].width_offset, + ylow - grids[xlow][ylow].height_offset, + SINK, sink_node_class_num); + VTR_ASSERT(true == rr_graph.valid_node_id(sink_node)); + + /* add edges to connect the IPIN node to SINK nodes */ + rr_graph.create_edge(node, sink_node, rr_node_driver_switches[sink_node]); + } +} + +/************************************************************************ + * Build the edges of each rr_node tile by tile: + * We classify rr_nodes into a general switch block (GSB) data structure + * where we create edges to each rr_nodes in the GSB with respect to + * Fc_in and Fc_out, switch block patterns + * For each GSB: + * 1. create edges between CHANX | CHANY and IPINs (connections inside connection blocks) + * 2. create edges between OPINs, CHANX and CHANY (connections inside switch blocks) + * 3. create edges between OPINs and IPINs (direct-connections) + ***********************************************************************/ +void build_rr_graph_edges(RRGraph& rr_graph, + const vtr::vector& rr_node_driver_switches, + const DeviceGrid& grids, + const vtr::Point& device_chan_width, + const std::vector& segment_inf, + const std::vector>& Fc_in, + const std::vector>& Fc_out, + const e_switch_block_type& sb_type, const int& Fs, + const e_switch_block_type& sb_subtype, const int& subFs, + const bool& wire_opposite_side) { + + /* Create edges for SOURCE and SINK nodes for a tileable rr_graph */ + build_rr_graph_edges_for_source_nodes(rr_graph, rr_node_driver_switches, grids); + build_rr_graph_edges_for_sink_nodes(rr_graph, rr_node_driver_switches, grids); + + vtr::Point gsb_range(grids.width() - 2, grids.height() - 2); + + /* Go Switch Block by Switch Block */ + for (size_t ix = 0; ix <= gsb_range.x(); ++ix) { + for (size_t iy = 0; iy <= gsb_range.y(); ++iy) { + //vpr_printf(TIO_MESSAGE_INFO, "Building edges for GSB[%lu][%lu]\n", ix, iy); + + vtr::Point gsb_coord(ix, iy); + /* Create a GSB object */ + const RRGSB& rr_gsb = build_one_tileable_rr_gsb(grids, rr_graph, + device_chan_width, segment_inf, + gsb_coord); + + /* adapt the track_to_ipin_lookup for the GSB nodes */ + t_track2pin_map track2ipin_map; /* [0..track_gsb_side][0..num_tracks][ipin_indices] */ + track2ipin_map = build_gsb_track_to_ipin_map(rr_graph, rr_gsb, grids, segment_inf, Fc_in); + + /* adapt the opin_to_track_map for the GSB nodes */ + t_pin2track_map opin2track_map; /* [0..gsb_side][0..num_opin_node][track_indices] */ + opin2track_map = build_gsb_opin_to_track_map(rr_graph, rr_gsb, grids, segment_inf, Fc_out); + + /* adapt the switch_block_conn for the GSB nodes */ + t_track2track_map sb_conn; /* [0..from_gsb_side][0..chan_width-1][track_indices] */ + sb_conn = build_gsb_track_to_track_map(rr_graph, rr_gsb, + sb_type, Fs, sb_subtype, subFs, wire_opposite_side, + segment_inf); + + /* Build edges for a GSB */ + build_edges_for_one_tileable_rr_gsb(rr_graph, rr_gsb, + track2ipin_map, opin2track_map, + sb_conn, rr_node_driver_switches); + /* Finish this GSB, go to the next*/ + } + } +} + +/************************************************************************ + * Build direct edges for Grids * + ***********************************************************************/ +void build_rr_graph_direct_connections(RRGraph& rr_graph, + const DeviceGrid& grids, + const RRSwitchId& delayless_switch, + const std::vector& directs, + const std::vector& clb_to_clb_directs) { + for (size_t ix = 0; ix < grids.width(); ++ix) { + for (size_t iy = 0; iy < grids.height(); ++iy) { + /* Skip EMPTY tiles */ + if (true == is_empty_type(grids[ix][iy].type)) { + continue; + } + /* Skip height > 1 or width > 1 tiles (mostly heterogeneous blocks) */ + if ( (0 < grids[ix][iy].width_offset) + || (0 < grids[ix][iy].height_offset) ) { + continue; + } + vtr::Point from_grid_coordinate(ix, iy); + build_direct_connections_for_one_gsb(rr_graph, + grids, + from_grid_coordinate, + delayless_switch, + directs, clb_to_clb_directs); + } + } +} + +} /* end namespace openfpga */ diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.h b/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.h new file mode 100644 index 00000000000..a20cef71712 --- /dev/null +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.h @@ -0,0 +1,45 @@ +#ifndef TILEABLE_RR_GRAPH_EDGE_BUILDER_H +#define TILEABLE_RR_GRAPH_EDGE_BUILDER_H + +/******************************************************************** + * Include header files that are required by function declaration + *******************************************************************/ +#include + +/* Headers from vtrutil library */ +#include "vtr_ndmatrix.h" +#include "vtr_geometry.h" + +#include "physical_types.h" +#include "device_grid.h" +#include "rr_graph_obj.h" +#include "clb2clb_directs.h" +#include "rr_graph_view.h" + +/******************************************************************** + * Function declaration + *******************************************************************/ + +/* begin namespace openfpga */ +namespace openfpga { + +void build_rr_graph_edges(RRGraphView& rr_graph, + const vtr::vector& rr_node_driver_switches, + const DeviceGrid& grids, + const vtr::Point& device_chan_width, + const std::vector& segment_inf, + const std::vector>& Fc_in, + const std::vector>& Fc_out, + const e_switch_block_type& sb_type, const int& Fs, + const e_switch_block_type& sb_subtype, const int& subFs, + const bool& wire_opposite_side); + +void build_rr_graph_direct_connections(RRGraphView& rr_graph, + const DeviceGrid& grids, + const RRSwitchId& delayless_switch, + const std::vector& directs, + const std::vector& clb_to_clb_directs); + +} /* end namespace openfpga */ + +#endif diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp new file mode 100755 index 00000000000..0fc75853dfb --- /dev/null +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp @@ -0,0 +1,1447 @@ +/************************************************************************ + * This file contains a builder for track-to-track connections inside a + * tileable General Switch Block (GSB). + ***********************************************************************/ +#include +#include +#include + +/* Headers from vtrutil library */ +#include "vtr_assert.h" +#include "vtr_log.h" + +/* Headers from openfpgautil library */ +#include "openfpga_side_manager.h" + +#include "vpr_utils.h" +#include "rr_graph_obj_util.h" +#include "openfpga_rr_graph_utils.h" +#include "rr_graph_builder_utils.h" +#include "tileable_chan_details_builder.h" +#include "tileable_rr_graph_gsb.h" + +/* begin namespace openfpga */ +namespace openfpga { + +/************************************************************************ + * Internal data structures + ***********************************************************************/ +typedef std::vector> t_track_group; + +/************************************************************************ + * A enumeration to list the status of a track inside a GSB + * 1. start; 2. end; 3. passing + * This is used to group tracks which ease the building of + * track-to-track mapping matrix + ***********************************************************************/ +enum e_track_status { + TRACK_START, + TRACK_END, + TRACK_PASS, + NUM_TRACK_STATUS /* just a place holder to get the number of status */ +}; + +/************************************************************************ + * Check if a track starts from this GSB or not + * (xlow, ylow) should be same as the GSB side coordinate + * + * Check if a track ends at this GSB or not + * (xhigh, yhigh) should be same as the GSB side coordinate + ***********************************************************************/ +static +enum e_track_status determine_track_status_of_gsb(const RRGraph& rr_graph, + const RRGSB& rr_gsb, + const enum e_side& gsb_side, + const size_t& track_id) { + enum e_track_status track_status = TRACK_PASS; + /* Get the rr_node */ + RRNodeId track_node = rr_gsb.get_chan_node(gsb_side, track_id); + /* Get the coordinates */ + vtr::Point side_coordinate = rr_gsb.get_side_block_coordinate(gsb_side); + + /* Get the coordinate of where the track starts */ + vtr::Point track_start = get_track_rr_node_start_coordinate(rr_graph, track_node); + + /* INC_DIRECTION start_track: (xlow, ylow) should be same as the GSB side coordinate */ + /* DEC_DIRECTION start_track: (xhigh, yhigh) should be same as the GSB side coordinate */ + if ( (track_start.x() == side_coordinate.x()) + && (track_start.y() == side_coordinate.y()) + && (OUT_PORT == rr_gsb.get_chan_node_direction(gsb_side, track_id)) ) { + /* Double check: start track should be an OUTPUT PORT of the GSB */ + track_status = TRACK_START; + } + + /* Get the coordinate of where the track ends */ + vtr::Point track_end = get_track_rr_node_end_coordinate(rr_graph, track_node); + + /* INC_DIRECTION end_track: (xhigh, yhigh) should be same as the GSB side coordinate */ + /* DEC_DIRECTION end_track: (xlow, ylow) should be same as the GSB side coordinate */ + if ( (track_end.x() == side_coordinate.x()) + && (track_end.y() == side_coordinate.y()) + && (IN_PORT == rr_gsb.get_chan_node_direction(gsb_side, track_id)) ) { + /* Double check: end track should be an INPUT PORT of the GSB */ + track_status = TRACK_END; + } + + return track_status; +} + +/************************************************************************ + * Check if the GSB is in the Connection Block (CB) population list of the segment + * SB population of a L4 wire: 1 0 0 1 + * + * +----+ +----+ +----+ +----+ + * | CB |--->| CB |--->| CB |--->| CB | + * +----+ +----+ +----+ +----+ + * Engage CB connection Yes No No Yes + * + * We will find the offset between gsb_side_coordinate and (xlow,ylow) of the track + * Use the offset to check if the tracks should engage in this GSB connection + ***********************************************************************/ +static +bool is_gsb_in_track_cb_population(const RRGraph& rr_graph, + const RRGSB& rr_gsb, + const e_side& gsb_side, + const int& track_id, + const std::vector& segment_inf) { + /* Get the rr_node */ + RRNodeId track_node = rr_gsb.get_chan_node(gsb_side, track_id); + /* Get the coordinates */ + vtr::Point side_coordinate = rr_gsb.get_side_block_coordinate(gsb_side); + + vtr::Point track_start = get_track_rr_node_start_coordinate(rr_graph, track_node); + + /* Get the offset */ + size_t offset = std::abs((int)side_coordinate.x() - (int)track_start.x()) + + std::abs((int)side_coordinate.y() - (int)track_start.y()); + + /* Get segment id */ + RRSegmentId seg_id = rr_gsb.get_chan_node_segment(gsb_side, track_id); + /* validate offset */ + VTR_ASSERT(offset < segment_inf[size_t(seg_id)].cb.size()); + + /* Get the SB population */ + bool in_cb_population = false; + if (true == segment_inf[size_t(seg_id)].cb[offset]) { + in_cb_population = true; + } + + return in_cb_population; +} + +/************************************************************************ + * Check if the GSB is in the Switch Block (SB) population list of the segment + * SB population of a L3 wire: 1 0 0 1 + * + * +----+ +----+ +----+ +----+ + * | SB |--->| SB |--->| SB |--->| SB | + * +----+ +----+ +----+ +----+ + * Engage SB connection Yes No No Yes + * + * We will find the offset between gsb_side_coordinate and (xlow,ylow) of the track + * Use the offset to check if the tracks should engage in this GSB connection + ***********************************************************************/ +static +bool is_gsb_in_track_sb_population(const RRGraph& rr_graph, + const RRGSB& rr_gsb, + const e_side& gsb_side, + const int& track_id, + const std::vector& segment_inf) { + /* Get the rr_node */ + const RRNodeId& track_node = rr_gsb.get_chan_node(gsb_side, track_id); + /* Get the coordinates */ + vtr::Point side_coordinate = rr_gsb.get_side_block_coordinate(gsb_side); + + vtr::Point track_start = get_track_rr_node_start_coordinate(rr_graph, track_node); + + /* Get the offset */ + size_t offset = std::abs((int)side_coordinate.x() - (int)track_start.x()) + + std::abs((int)side_coordinate.y() - (int)track_start.y()); + + /* Get segment id */ + RRSegmentId seg_id = rr_gsb.get_chan_node_segment(gsb_side, track_id); + /* validate offset */ + VTR_ASSERT(offset < segment_inf[size_t(seg_id)].sb.size()); + + /* Get the SB population */ + bool in_sb_population = false; + if (true == segment_inf[size_t(seg_id)].sb[offset]) { + in_sb_population = true; + } + + return in_sb_population; +} + +/************************************************************************ + * Create a list of track_id based on the to_track and num_to_tracks + * We consider the following list [to_track, to_track + Fs/3 - 1] + * if the [to_track + Fs/3 - 1] exceeds the num_to_tracks, we start over from 0! +***********************************************************************/ +static +std::vector get_to_track_list(const int& Fs, const int& to_track, const int& num_to_tracks) { + std::vector to_tracks; + + for (int i = 0; i < Fs; i = i + 3) { + /* TODO: currently, for Fs > 3, I always search the next from_track until Fs is satisfied + * The optimal track selection should be done in a more scientific way!!! + */ + int to_track_i = to_track + i; + /* make sure the track id is still in range */ + if ( to_track_i > num_to_tracks - 1) { + to_track_i = to_track_i % num_to_tracks; + } + /* Ensure we are in the range */ + VTR_ASSERT(to_track_i < num_to_tracks); + /* from track must be connected */ + to_tracks.push_back(to_track_i); + } + return to_tracks; +} + +/************************************************************************ + * This function aims to return the track indices that drive the from_track + * in a Switch Block + * The track_ids to return will depend on different topologies of SB + * SUBSET, UNIVERSAL, and WILTON. + ***********************************************************************/ +static +std::vector get_switch_block_to_track_id(const e_switch_block_type& switch_block_type, + const int& Fs, + const e_side& from_side, + const int& from_track, + const e_side& to_side, + const int& num_to_tracks) { + + /* This routine returns the track number to which the from_track should + * connect. It supports any Fs % 3 == 0, switch blocks. + */ + std::vector to_tracks; + + /* TODO: currently, for Fs > 3, I always search the next from_track until Fs is satisfied + * The optimal track selection should be done in a more scientific way!!! + */ + VTR_ASSERT(0 == Fs % 3); + + /* Adapt from_track to fit in the range of num_to_tracks */ + size_t actual_from_track = from_track % num_to_tracks; + + switch (switch_block_type) { + case SUBSET: /* NB: Global routing uses SUBSET too */ + to_tracks = get_to_track_list(Fs, actual_from_track, num_to_tracks); + /* Finish, we return */ + return to_tracks; + case UNIVERSAL: + if ( (from_side == LEFT) + || (from_side == RIGHT) ) { + /* For the prev_side, to_track is from_track + * For the next_side, to_track is num_to_tracks - 1 - from_track + * For the opposite_side, to_track is always from_track + */ + SideManager side_manager(from_side); + if ( (to_side == side_manager.get_opposite()) + || (to_side == side_manager.get_rotate_counterclockwise()) ) { + to_tracks = get_to_track_list(Fs, actual_from_track, num_to_tracks); + } else if (to_side == side_manager.get_rotate_clockwise()) { + to_tracks = get_to_track_list(Fs, num_to_tracks - 1 - actual_from_track, num_to_tracks); + } + } + + if ( (from_side == TOP) + || (from_side == BOTTOM) ) { + /* For the next_side, to_track is from_track + * For the prev_side, to_track is num_to_tracks - 1 - from_track + * For the opposite_side, to_track is always from_track + */ + SideManager side_manager(from_side); + if ( (to_side == side_manager.get_opposite()) + || (to_side == side_manager.get_rotate_clockwise()) ) { + to_tracks = get_to_track_list(Fs, actual_from_track, num_to_tracks); + } else if (to_side == side_manager.get_rotate_counterclockwise()) { + to_tracks = get_to_track_list(Fs, num_to_tracks - 1 - actual_from_track, num_to_tracks); + } + } + /* Finish, we return */ + return to_tracks; + /* End switch_block_type == UNIVERSAL case. */ + case WILTON: + /* See S. Wilton Phd thesis, U of T, 1996 p. 103 for details on following. */ + if (from_side == LEFT) { + if (to_side == RIGHT) { /* CHANX to CHANX */ + to_tracks = get_to_track_list(Fs, actual_from_track, num_to_tracks); + } else if (to_side == TOP) { /* from CHANX to CHANY */ + to_tracks = get_to_track_list(Fs, (num_to_tracks - actual_from_track ) % num_to_tracks, num_to_tracks); + } else if (to_side == BOTTOM) { + to_tracks = get_to_track_list(Fs, (num_to_tracks + actual_from_track - 1) % num_to_tracks, num_to_tracks); + } + } else if (from_side == RIGHT) { + if (to_side == LEFT) { /* CHANX to CHANX */ + to_tracks = get_to_track_list(Fs, actual_from_track, num_to_tracks); + } else if (to_side == TOP) { /* from CHANX to CHANY */ + to_tracks = get_to_track_list(Fs, (num_to_tracks + actual_from_track - 1) % num_to_tracks, num_to_tracks); + } else if (to_side == BOTTOM) { + to_tracks = get_to_track_list(Fs, (2 * num_to_tracks - 2 - actual_from_track) % num_to_tracks, num_to_tracks); + } + } else if (from_side == BOTTOM) { + if (to_side == TOP) { /* CHANY to CHANY */ + to_tracks = get_to_track_list(Fs, actual_from_track, num_to_tracks); + } else if (to_side == LEFT) { /* from CHANY to CHANX */ + to_tracks = get_to_track_list(Fs, (actual_from_track + 1) % num_to_tracks, num_to_tracks); + } else if (to_side == RIGHT) { + to_tracks = get_to_track_list(Fs, (2 * num_to_tracks - 2 - actual_from_track) % num_to_tracks, num_to_tracks); + } + } else if (from_side == TOP) { + if (to_side == BOTTOM) { /* CHANY to CHANY */ + to_tracks = get_to_track_list(Fs, from_track, num_to_tracks); + } else if (to_side == LEFT) { /* from CHANY to CHANX */ + to_tracks = get_to_track_list(Fs, (num_to_tracks - actual_from_track) % num_to_tracks, num_to_tracks); + } else if (to_side == RIGHT) { + to_tracks = get_to_track_list(Fs, (actual_from_track + 1) % num_to_tracks, num_to_tracks); + } + } + /* Finish, we return */ + return to_tracks; + /* End switch_block_type == WILTON case. */ + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid switch block pattern !\n"); + exit(1); + } + + return to_tracks; +} + + +/************************************************************************ + * Build the track_to_track_map[from_side][0..chan_width-1][to_side][track_indices] + * For a group of from_track nodes and to_track nodes + * For each side of from_tracks, we call a routine to get the list of to_tracks + * Then, we fill the track2track_map + ***********************************************************************/ +static +void build_gsb_one_group_track_to_track_map(const RRGraph& rr_graph, + const RRGSB& rr_gsb, + const e_switch_block_type& sb_type, + const int& Fs, + const bool& wire_opposite_side, + const t_track_group& from_tracks, /* [0..gsb_side][track_indices] */ + const t_track_group& to_tracks, /* [0..gsb_side][track_indices] */ + t_track2track_map& track2track_map) { + for (size_t side = 0; side < from_tracks.size(); ++side) { + SideManager side_manager(side); + e_side from_side = side_manager.get_side(); + /* Find the other sides where the start tracks will locate */ + std::vector to_track_sides; + /* 0. opposite side */ + to_track_sides.push_back(side_manager.get_opposite()); + /* 1. prev side */ + /* Previous side definition: TOP => LEFT; RIGHT=>TOP; BOTTOM=>RIGHT; LEFT=>BOTTOM */ + to_track_sides.push_back(side_manager.get_rotate_counterclockwise()); + /* 2. next side */ + /* Next side definition: TOP => RIGHT; RIGHT=>BOTTOM; BOTTOM=>LEFT; LEFT=>TOP */ + to_track_sides.push_back(side_manager.get_rotate_clockwise()); + + for (size_t inode = 0; inode < from_tracks[side].size(); ++inode) { + for (size_t to_side_id = 0; to_side_id < to_track_sides.size(); ++to_side_id) { + enum e_side to_side = to_track_sides[to_side_id]; + SideManager to_side_manager(to_side); + size_t to_side_index = to_side_manager.to_size_t(); + /* Bypass those to_sides have no nodes */ + if (0 == to_tracks[to_side_index].size()) { + continue; + } + /* Bypass those from_side is same as to_side */ + if (from_side == to_side) { + continue; + } + /* Bypass those from_side is opposite to to_side if required */ + if ( (true == wire_opposite_side) + && (to_side_manager.get_opposite() == from_side) ) { + continue; + } + /* Get other track_ids depending on the switch block pattern */ + /* Find the track ids that will start at the other sides */ + std::vector to_track_ids = get_switch_block_to_track_id(sb_type, Fs, from_side, inode, + to_side, + to_tracks[to_side_index].size()); + /* Update the track2track_map: */ + for (size_t to_track_id = 0; to_track_id < to_track_ids.size(); ++to_track_id) { + size_t from_side_index = side_manager.to_size_t(); + size_t from_track_index = from_tracks[side][inode]; + /* Check the id is still in the range !*/ + VTR_ASSERT( to_track_ids[to_track_id] < to_tracks[to_side_index].size() ); + size_t to_track_index = to_tracks[to_side_index][to_track_ids[to_track_id]]; + //printf("from_track(size=%lu): %lu , to_track_ids[%lu]:%lu, to_track_index: %lu in a group of %lu tracks\n", + // from_tracks[side].size(), inode, to_track_id, to_track_ids[to_track_id], + // to_track_index, to_tracks[to_side_index].size()); + const RRNodeId& to_track_node = rr_gsb.get_chan_node(to_side, to_track_index); + VTR_ASSERT(true == rr_graph.valid_node_id(to_track_node)); + + /* from_track should be IN_PORT */ + VTR_ASSERT(IN_PORT == rr_gsb.get_chan_node_direction(from_side, from_track_index)); + /* to_track should be OUT_PORT */ + VTR_ASSERT(OUT_PORT == rr_gsb.get_chan_node_direction(to_side, to_track_index)); + + /* Check if the to_track_node is already in the list ! */ + std::vector::iterator it = std::find(track2track_map[from_side_index][from_track_index].begin(), + track2track_map[from_side_index][from_track_index].end(), + to_track_node); + if (it != track2track_map[from_side_index][from_track_index].end()) { + continue; /* the node_id is already in the list, go for the next */ + } + /* Clear, we should add to the list */ + track2track_map[from_side_index][from_track_index].push_back(to_track_node); + } + } + } + } +} + +/************************************************************************ + * Build the track_to_track_map[from_side][0..chan_width-1][to_side][track_indices] + * based on the existing routing resources in the General Switch Block (GSB) + * The track_indices is the indices of tracks that the node at from_side and [0..chan_width-1] will drive + * IMPORTANT: the track_indices are the indicies in the GSB context, but not the rr_graph!!! + * We separate the connections into two groups: + * Group 1: the routing tracks start from this GSB + * We will apply switch block patterns (SUBSET, UNIVERSAL, WILTON) + * Group 2: the routing tracks do not start from this GSB (bypassing wires) + * We will apply switch block patterns (SUBSET, UNIVERSAL, WILTON) + * but we will check the Switch Block (SB) population of these + * routing segments, and determine which requires connections + * + * CHANY CHANY CHANY CHANY + * [0] [1] [2] [3] + * start yes no yes no + * end +-------------------------+ start Group 1 Group 2 + * no CHANX[0] | TOP | CHANX[0] yes TOP/BOTTOM TOP/BOTTOM + * | | CHANY[0,2] CHANY[1,3] + * yes CHANX[1] | | CHANX[1] no + * | LEFT RIGHT | + * no CHANX[2] | | CHANX[2] yes + * | | + * yes CHANX[3] | BOTTOM | CHANX[3] no + * +-------------------------+ + * CHANY CHANY CHANY CHANY + * [0] [1] [2] [3] + * start yes no yes no + * + * The mapping is done in the following steps: (For each side of the GSB) + * 1. Build a list of tracks that will start from this side + * if a track starts, its xlow/ylow is the same as the x,y of this gsb + * 2. Build a list of tracks on the other sides belonging to Group 1. + * Take the example of RIGHT side, we will collect + * a. tracks that will end at the LEFT side + * b. tracks that will start at the TOP side + * c. tracks that will start at the BOTTOM side + * 3. Apply switch block patterns to Group 1 (SUBSET, UNIVERSAL, WILTON) + * 4. Build a list of tracks on the other sides belonging to Group 1. + * Take the example of RIGHT side, we will collect + * a. tracks that will bypass at the TOP side + * b. tracks that will bypass at the BOTTOM side + * 5. Apply switch block patterns to Group 2 (SUBSET, UNIVERSAL, WILTON) + ***********************************************************************/ +t_track2track_map build_gsb_track_to_track_map(const RRGraph& rr_graph, + const RRGSB& rr_gsb, + const e_switch_block_type& sb_type, + const int& Fs, + const e_switch_block_type& sb_subtype, + const int& subFs, + const bool& wire_opposite_side, + const std::vector& segment_inf) { + t_track2track_map track2track_map; /* [0..gsb_side][0..chan_width][track_indices] */ + + /* Categorize tracks into 3 groups: + * (1) tracks will start here + * (2) tracks will end here + * (2) tracks will just pass through the SB */ + t_track_group start_tracks; /* [0..gsb_side][track_indices] */ + t_track_group end_tracks; /* [0..gsb_side][track_indices] */ + t_track_group pass_tracks; /* [0..gsb_side][track_indices] */ + + /* resize to the number of sides */ + start_tracks.resize(rr_gsb.get_num_sides()); + end_tracks.resize(rr_gsb.get_num_sides()); + pass_tracks.resize(rr_gsb.get_num_sides()); + + /* Walk through each side */ + for (size_t side = 0; side < rr_gsb.get_num_sides(); ++side) { + SideManager side_manager(side); + e_side gsb_side = side_manager.get_side(); + /* Build a list of tracks that will start from this side */ + for (size_t inode = 0; inode < rr_gsb.get_chan_width(gsb_side); ++inode) { + /* We need to check Switch block population of this track + * The track node will not be considered if there supposed to be no SB at this position + */ + if (false == is_gsb_in_track_sb_population(rr_graph, rr_gsb, gsb_side, inode, segment_inf)) { + continue; /* skip this node and go to the next */ + } + /* check if this track will start from here */ + enum e_track_status track_status = determine_track_status_of_gsb(rr_graph, rr_gsb, gsb_side, inode); + + switch (track_status) { + case TRACK_START: + /* update starting track list */ + start_tracks[side].push_back(inode); + break; + case TRACK_END: + /* Update end track list */ + end_tracks[side].push_back(inode); + break; + case TRACK_PASS: + /* Update passing track list */ + /* Note that the pass_track should be IN_PORT only !!! */ + if (IN_PORT == rr_gsb.get_chan_node_direction(gsb_side, inode)) { + pass_tracks[side].push_back(inode); + } + break; + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid track status!\n"); + exit(1); + } + } + } + + /* Allocate track2track map */ + track2track_map.resize(rr_gsb.get_num_sides()); + for (size_t side = 0; side < rr_gsb.get_num_sides(); ++side) { + SideManager side_manager(side); + enum e_side gsb_side = side_manager.get_side(); + /* allocate track2track_map[gsb_side] */ + track2track_map[side].resize(rr_gsb.get_chan_width(gsb_side)); + for (size_t inode = 0; inode < rr_gsb.get_chan_width(gsb_side); ++inode) { + /* allocate track2track_map[gsb_side][inode] */ + track2track_map[side][inode].clear(); + } + } + + /* For Group 1: we build connections between end_tracks and start_tracks*/ + build_gsb_one_group_track_to_track_map(rr_graph, rr_gsb, + sb_type, Fs, + true, /* End tracks should always to wired to start tracks */ + end_tracks, start_tracks, + track2track_map); + + /* For Group 2: we build connections between end_tracks and start_tracks*/ + /* Currently, I use the same Switch Block pattern for the passing tracks and end tracks, + * TODO: This can be improved with different patterns! + */ + build_gsb_one_group_track_to_track_map(rr_graph, rr_gsb, + sb_subtype, subFs, + wire_opposite_side, /* Pass tracks may not be wired to start tracks */ + pass_tracks, start_tracks, + track2track_map); + + return track2track_map; +} + +/* Build a RRChan Object with the given channel type and coorindators */ +static +RRChan build_one_tileable_rr_chan(const vtr::Point& chan_coordinate, + const t_rr_type& chan_type, + const RRGraph& rr_graph, + const ChanNodeDetails& chan_details) { + std::vector chan_rr_nodes; + + /* Create a rr_chan object and check if it is unique in the graph */ + RRChan rr_chan; + + /* Fill the information */ + rr_chan.set_type(chan_type); + + /* Collect rr_nodes for this channel */ + chan_rr_nodes = find_rr_graph_chan_nodes(rr_graph, + chan_coordinate.x(), chan_coordinate.y(), + chan_type); + + /* Reserve */ + /* rr_chan.reserve_node(size_t(chan_width)); */ + + /* Fill the rr_chan */ + for (size_t itrack = 0; itrack < chan_rr_nodes.size(); ++itrack) { + size_t iseg = chan_details.get_track_segment_id(itrack); + rr_chan.add_node(rr_graph, chan_rr_nodes[itrack], RRSegmentId(iseg)); + } + + return rr_chan; +} + +/*********************************************************************** + * Build a General Switch Block (GSB) + * which includes: + * [I] A Switch Box subckt consists of following ports: + * 1. Channel Y [x][y] inputs + * 2. Channel X [x+1][y] inputs + * 3. Channel Y [x][y-1] outputs + * 4. Channel X [x][y] outputs + * 5. Grid[x][y+1] Right side outputs pins + * 6. Grid[x+1][y+1] Left side output pins + * 7. Grid[x+1][y+1] Bottom side output pins + * 8. Grid[x+1][y] Top side output pins + * 9. Grid[x+1][y] Left side output pins + * 10. Grid[x][y] Right side output pins + * 11. Grid[x][y] Top side output pins + * 12. Grid[x][y+1] Bottom side output pins + * + * -------------- -------------- + * | | CBY | | + * | Grid | ChanY | Grid | + * | [x][y+1] | [x][y+1] | [x+1][y+1] | + * | | | | + * -------------- -------------- + * ---------- + * ChanX & CBX | Switch | ChanX + * [x][y] | Box | [x+1][y] + * | [x][y] | + * ---------- + * -------------- -------------- + * | | | | + * | Grid | ChanY | Grid | + * | [x][y] | [x][y] | [x+1][y] | + * | | | | + * -------------- -------------- + * For channels chanY with INC_DIRECTION on the top side, they should be marked as outputs + * For channels chanY with DEC_DIRECTION on the top side, they should be marked as inputs + * For channels chanY with INC_DIRECTION on the bottom side, they should be marked as inputs + * For channels chanY with DEC_DIRECTION on the bottom side, they should be marked as outputs + * For channels chanX with INC_DIRECTION on the left side, they should be marked as inputs + * For channels chanX with DEC_DIRECTION on the left side, they should be marked as outputs + * For channels chanX with INC_DIRECTION on the right side, they should be marked as outputs + * For channels chanX with DEC_DIRECTION on the right side, they should be marked as inputs + * + * [II] A X-direction Connection Block [x][y] + * The connection block shares the same routing channel[x][y] with the Switch Block + * We just need to fill the ipin nodes at TOP and BOTTOM sides + * as well as properly fill the ipin_grid_side information + * [III] A Y-direction Connection Block [x][y+1] + * The connection block shares the same routing channel[x][y+1] with the Switch Block + * We just need to fill the ipin nodes at LEFT and RIGHT sides + * as well as properly fill the ipin_grid_side information + ***********************************************************************/ +RRGSB build_one_tileable_rr_gsb(const DeviceGrid& grids, + const RRGraph& rr_graph, + const vtr::Point& device_chan_width, + const std::vector& segment_inf, + const vtr::Point& gsb_coordinate) { + /* Create an object to return */ + RRGSB rr_gsb; + + /* Check */ + VTR_ASSERT(gsb_coordinate.x() <= grids.width()); + VTR_ASSERT(gsb_coordinate.y() <= grids.height()); + + /* Coordinator initialization */ + rr_gsb.set_coordinate(gsb_coordinate.x(), gsb_coordinate.y()); + + /* Basic information*/ + rr_gsb.init_num_sides(4); /* Fixed number of sides */ + + /* Find all rr_nodes of channels */ + /* SideManager: TOP => 0, RIGHT => 1, BOTTOM => 2, LEFT => 3 */ + for (size_t side = 0; side < rr_gsb.get_num_sides(); ++side) { + /* Local variables inside this for loop */ + SideManager side_manager(side); + vtr::Point coordinate = rr_gsb.get_side_block_coordinate(side_manager.get_side()); + RRChan rr_chan; + std::vector> temp_opin_rr_nodes(2); + enum e_side opin_grid_side[2] = {NUM_SIDES, NUM_SIDES}; + enum PORTS chan_dir_to_port_dir_mapping[2] = {OUT_PORT, IN_PORT}; /* 0: INC_DIRECTION => ?; 1: DEC_DIRECTION => ? */ + + /* Build a segment details, where we need the segment ids for building rr_chan + * We do not care starting and ending points here, so set chan_side as NUM_SIDES + */ + ChanNodeDetails chanx_details = build_unidir_chan_node_details(device_chan_width.x(), grids.width() - 1, + false, false, segment_inf); + ChanNodeDetails chany_details = build_unidir_chan_node_details(device_chan_width.y(), grids.height() - 1, + false, false, segment_inf); + + switch (side) { + case TOP: /* TOP = 0 */ + /* For the bording, we should take special care */ + if (gsb_coordinate.y() == grids.height() - 1) { + rr_gsb.clear_one_side(side_manager.get_side()); + break; + } + /* Routing channels*/ + /* SideManager: TOP => 0, RIGHT => 1, BOTTOM => 2, LEFT => 3 */ + /* Create a rr_chan object and check if it is unique in the graph */ + rr_chan = build_one_tileable_rr_chan(coordinate, CHANY, rr_graph, chany_details); + chan_dir_to_port_dir_mapping[0] = OUT_PORT; /* INC_DIRECTION => OUT_PORT */ + chan_dir_to_port_dir_mapping[1] = IN_PORT; /* DEC_DIRECTION => IN_PORT */ + + /* Assign grid side of OPIN */ + /* Grid[x][y+1] RIGHT side outputs pins */ + opin_grid_side[0] = RIGHT; + /* Grid[x+1][y+1] left side outputs pins */ + opin_grid_side[1] = LEFT; + + /* Build the Switch block: opin and opin_grid_side */ + /* Include Grid[x][y+1] RIGHT side outputs pins */ + temp_opin_rr_nodes[0] = find_rr_graph_grid_nodes(rr_graph, grids, + gsb_coordinate.x(), gsb_coordinate.y() + 1, + OPIN, opin_grid_side[0]); + /* Include Grid[x+1][y+1] Left side output pins */ + temp_opin_rr_nodes[1] = find_rr_graph_grid_nodes(rr_graph, grids, + gsb_coordinate.x() + 1, gsb_coordinate.y() + 1, + OPIN, opin_grid_side[1]); + + break; + case RIGHT: /* RIGHT = 1 */ + /* For the bording, we should take special care */ + if (gsb_coordinate.x() == grids.width() - 1) { + rr_gsb.clear_one_side(side_manager.get_side()); + break; + } + /* Routing channels*/ + /* SideManager: TOP => 0, RIGHT => 1, BOTTOM => 2, LEFT => 3 */ + /* Collect rr_nodes for Tracks for top: chany[x][y+1] */ + /* Create a rr_chan object and check if it is unique in the graph */ + rr_chan = build_one_tileable_rr_chan(coordinate, CHANX, rr_graph, chanx_details); + chan_dir_to_port_dir_mapping[0] = OUT_PORT; /* INC_DIRECTION => OUT_PORT */ + chan_dir_to_port_dir_mapping[1] = IN_PORT; /* DEC_DIRECTION => IN_PORT */ + + /* Assign grid side of OPIN */ + /* Grid[x+1][y+1] BOTTOM side outputs pins */ + opin_grid_side[0] = BOTTOM; + /* Grid[x+1][y] TOP side outputs pins */ + opin_grid_side[1] = TOP; + + /* Build the Switch block: opin and opin_grid_side */ + /* include Grid[x+1][y+1] Bottom side output pins */ + temp_opin_rr_nodes[0] = find_rr_graph_grid_nodes(rr_graph, grids, + gsb_coordinate.x() + 1, gsb_coordinate.y() + 1, + OPIN, opin_grid_side[0]); + /* include Grid[x+1][y] Top side output pins */ + temp_opin_rr_nodes[1] = find_rr_graph_grid_nodes(rr_graph, grids, + gsb_coordinate.x() + 1, gsb_coordinate.y(), + OPIN, opin_grid_side[1]); + break; + case BOTTOM: /* BOTTOM = 2*/ + /* For the bording, we should take special care */ + if (gsb_coordinate.y() == 0) { + rr_gsb.clear_one_side(side_manager.get_side()); + break; + } + /* Routing channels*/ + /* SideManager: TOP => 0, RIGHT => 1, BOTTOM => 2, LEFT => 3 */ + /* Collect rr_nodes for Tracks for bottom: chany[x][y] */ + /* Create a rr_chan object and check if it is unique in the graph */ + rr_chan = build_one_tileable_rr_chan(coordinate, CHANY, rr_graph, chany_details); + chan_dir_to_port_dir_mapping[0] = IN_PORT; /* INC_DIRECTION => IN_PORT */ + chan_dir_to_port_dir_mapping[1] = OUT_PORT; /* DEC_DIRECTION => OUT_PORT */ + + /* Assign grid side of OPIN */ + /* Grid[x+1][y] LEFT side outputs pins */ + opin_grid_side[0] = LEFT; + /* Grid[x][y] RIGHT side outputs pins */ + opin_grid_side[1] = RIGHT; + + /* Build the Switch block: opin and opin_grid_side */ + /* include Grid[x+1][y] Left side output pins */ + temp_opin_rr_nodes[0] = find_rr_graph_grid_nodes(rr_graph, grids, + gsb_coordinate.x() + 1, gsb_coordinate.y(), + OPIN, opin_grid_side[0]); + /* include Grid[x][y] Right side output pins */ + temp_opin_rr_nodes[1] = find_rr_graph_grid_nodes(rr_graph, grids, + gsb_coordinate.x(), gsb_coordinate.y(), + OPIN, opin_grid_side[1]); + break; + case LEFT: /* LEFT = 3 */ + /* For the bording, we should take special care */ + if (gsb_coordinate.x() == 0) { + rr_gsb.clear_one_side(side_manager.get_side()); + break; + } + /* Routing channels*/ + /* SideManager: TOP => 0, RIGHT => 1, BOTTOM => 2, LEFT => 3 */ + /* Collect rr_nodes for Tracks for left: chanx[x][y] */ + /* Create a rr_chan object and check if it is unique in the graph */ + rr_chan = build_one_tileable_rr_chan(coordinate, CHANX, rr_graph, chanx_details); + chan_dir_to_port_dir_mapping[0] = IN_PORT; /* INC_DIRECTION => IN_PORT */ + chan_dir_to_port_dir_mapping[1] = OUT_PORT; /* DEC_DIRECTION => OUT_PORT */ + + /* Grid[x][y+1] BOTTOM side outputs pins */ + opin_grid_side[0] = BOTTOM; + /* Grid[x][y] TOP side outputs pins */ + opin_grid_side[1] = TOP; + + /* Build the Switch block: opin and opin_grid_side */ + /* include Grid[x][y+1] Bottom side outputs pins */ + temp_opin_rr_nodes[0] = find_rr_graph_grid_nodes(rr_graph, grids, + gsb_coordinate.x(), gsb_coordinate.y() + 1, + OPIN, opin_grid_side[0]); + /* include Grid[x][y] Top side output pins */ + temp_opin_rr_nodes[1] = find_rr_graph_grid_nodes(rr_graph, grids, + gsb_coordinate.x(), gsb_coordinate.y(), + OPIN, opin_grid_side[1]); + + break; + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid side index!\n"); + exit(1); + } + + /* Organize a vector of port direction */ + if (0 < rr_chan.get_chan_width()) { + std::vector rr_chan_dir; + rr_chan_dir.resize(rr_chan.get_chan_width()); + for (size_t itrack = 0; itrack < rr_chan.get_chan_width(); ++itrack) { + /* Identify the directionality, record it in rr_node_direction */ + if (Direction::INC == rr_graph.node_direction(rr_chan.get_node(itrack))) { + rr_chan_dir[itrack] = chan_dir_to_port_dir_mapping[0]; + } else { + VTR_ASSERT(Direction::DEC == rr_graph.node_direction(rr_chan.get_node(itrack))); + rr_chan_dir[itrack] = chan_dir_to_port_dir_mapping[1]; + } + } + /* Fill chan_rr_nodes */ + rr_gsb.add_chan_node(side_manager.get_side(), rr_chan, rr_chan_dir); + } + + /* Fill opin_rr_nodes */ + /* Copy from temp_opin_rr_node to opin_rr_node */ + for (const RRNodeId& inode : temp_opin_rr_nodes[0]) { + /* Grid[x+1][y+1] Bottom side outputs pins */ + rr_gsb.add_opin_node(inode, side_manager.get_side()); + } + for (const RRNodeId& inode : temp_opin_rr_nodes[1]) { + /* Grid[x+1][y] TOP side outputs pins */ + rr_gsb.add_opin_node(inode, side_manager.get_side()); + } + + /* Clean ipin_rr_nodes */ + /* We do not have any IPIN for a Switch Block */ + rr_gsb.clear_ipin_nodes(side_manager.get_side()); + + /* Clear the temp data */ + temp_opin_rr_nodes[0].clear(); + temp_opin_rr_nodes[1].clear(); + opin_grid_side[0] = NUM_SIDES; + opin_grid_side[1] = NUM_SIDES; + } + + /* Add IPIN nodes from adjacent grids: the 4 grids sitting on the 4 corners of the Switch Block + * + * - The concept of top/bottom side of connection block in GSB domain: + * + * | Grid[x][y+1] | + * | BOTTOM side | + * +-----------------------+ + * | + * v + * +-----------------------+ + * | TOP side | + * | X- Connection Block | + * | BOTTOM side | + * +-----------------------+ + * ^ + * | + * +-----------------------+ + * | TOP side | + * | Grid[x][y] | + * + * - The concept of top/bottom side of connection block in GSB domain: + * + * ---------------+ +---------------------- ... ---------------------+ +---------------- + * Grid[x][y+1] |->| Y- Connection Block Y- Connection Block |<-| Grid[x+1][y+1] + * RIGHT side | | LEFT side ... RIGHT side | | LEFT side + * --------------+ +---------------------- ... ---------------------+ +---------------- + * + */ + for (size_t side = 0; side < rr_gsb.get_num_sides(); ++side) { + SideManager side_manager(side); + size_t ix; + size_t iy; + enum e_side chan_side; + std::vector temp_ipin_rr_nodes; + enum e_side ipin_rr_node_grid_side; + + switch (side) { + case TOP: + /* Consider the routing channel that is connected to the left side of the switch block */ + chan_side = LEFT; + /* The input pins of the routing channel come from the bottom side of Grid[x][y+1] */ + ix = rr_gsb.get_sb_x(); + iy = rr_gsb.get_sb_y() + 1; + ipin_rr_node_grid_side = BOTTOM; + break; + case RIGHT: + /* Consider the routing channel that is connected to the top side of the switch block */ + chan_side = TOP; + /* The input pins of the routing channel come from the left side of Grid[x+1][y+1] */ + ix = rr_gsb.get_sb_x() + 1; + iy = rr_gsb.get_sb_y() + 1; + ipin_rr_node_grid_side = LEFT; + break; + case BOTTOM: + /* Consider the routing channel that is connected to the left side of the switch block */ + chan_side = LEFT; + /* The input pins of the routing channel come from the top side of Grid[x][y] */ + ix = rr_gsb.get_sb_x(); + iy = rr_gsb.get_sb_y(); + ipin_rr_node_grid_side = TOP; + break; + case LEFT: + /* Consider the routing channel that is connected to the top side of the switch block */ + chan_side = TOP; + /* The input pins of the routing channel come from the right side of Grid[x][y+1] */ + ix = rr_gsb.get_sb_x(); + iy = rr_gsb.get_sb_y() + 1; + ipin_rr_node_grid_side = RIGHT; + break; + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid side index!\n"); + exit(1); + } + + /* If there is no channel at this side, we skip ipin_node annotation */ + if (0 == rr_gsb.get_chan_width(chan_side)) { + continue; + } + /* Collect IPIN rr_nodes*/ + temp_ipin_rr_nodes = find_rr_graph_grid_nodes(rr_graph, grids, + ix, iy, IPIN, ipin_rr_node_grid_side); + /* Fill the ipin nodes of RRGSB */ + for (const RRNodeId& inode : temp_ipin_rr_nodes) { + rr_gsb.add_ipin_node(inode, side_manager.get_side()); + } + /* Clear the temp data */ + temp_ipin_rr_nodes.clear(); + } + + return rr_gsb; +} + +/************************************************************************ + * Create edges for each rr_node of a General Switch Blocks (GSB): + * 1. create edges between CHANX | CHANY and IPINs (connections inside connection blocks) + * 2. create edges between OPINs, CHANX and CHANY (connections inside switch blocks) + * 3. create edges between OPINs and IPINs (direct-connections) + ***********************************************************************/ +void build_edges_for_one_tileable_rr_gsb(RRGraph& rr_graph, + const RRGSB& rr_gsb, + const t_track2pin_map& track2ipin_map, + const t_pin2track_map& opin2track_map, + const t_track2track_map& track2track_map, + const vtr::vector& rr_node_driver_switches) { + + /* Walk through each sides */ + for (size_t side = 0; side < rr_gsb.get_num_sides(); ++side) { + SideManager side_manager(side); + enum e_side gsb_side = side_manager.get_side(); + + /* Find OPINs */ + for (size_t inode = 0; inode < rr_gsb.get_num_opin_nodes(gsb_side); ++inode) { + const RRNodeId& opin_node = rr_gsb.get_opin_node(gsb_side, inode); + + /* 1. create edges between OPINs and CHANX|CHANY, using opin2track_map */ + /* add edges to the opin_node */ + for (const RRNodeId& track_node : opin2track_map[gsb_side][inode]) { + rr_graph.create_edge(opin_node, track_node, rr_node_driver_switches[track_node]); + } + } + + /* Find CHANX or CHANY */ + /* For TRACKs to IPINs, we only care LEFT and TOP sides + * Skip RIGHT and BOTTOM for the ipin2track_map since they should be handled in other GSBs + */ + if ( (side_manager.get_side() == rr_gsb.get_cb_chan_side(CHANX)) + || (side_manager.get_side() == rr_gsb.get_cb_chan_side(CHANY)) ) { + /* 2. create edges between CHANX|CHANY and IPINs, using ipin2track_map */ + for (size_t inode = 0; inode < rr_gsb.get_chan_width(gsb_side); ++inode) { + const RRNodeId& chan_node = rr_gsb.get_chan_node(gsb_side, inode); + for (const RRNodeId& ipin_node : track2ipin_map[gsb_side][inode]) { + rr_graph.create_edge(chan_node, ipin_node, rr_node_driver_switches[ipin_node]); + } + } + } + + /* 3. create edges between CHANX|CHANY and CHANX|CHANY, using track2track_map */ + for (size_t inode = 0; inode < rr_gsb.get_chan_width(gsb_side); ++inode) { + const RRNodeId& chan_node = rr_gsb.get_chan_node(gsb_side, inode); + for (const RRNodeId& track_node : track2track_map[gsb_side][inode]) { + rr_graph.create_edge(chan_node, track_node, rr_node_driver_switches[track_node]); + } + } + } +} + +/************************************************************************ + * Build track2ipin_map for an IPIN + * 1. build a list of routing tracks which are allowed for connections + * We will check the Connection Block (CB) population of each routing track. + * By comparing current chan_y - ylow, we can determine if a CB connection + * is required for each routing track + * 2. Divide the routing tracks by segment types, so that we can balance + * the connections between IPINs and different types of routing tracks. + * 3. Scale the Fc of each pin to the actual number of routing tracks + * actual_Fc = (int) Fc * num_tracks / chan_width + ***********************************************************************/ +static +void build_gsb_one_ipin_track2pin_map(const RRGraph& rr_graph, + const RRGSB& rr_gsb, + const enum e_side& ipin_side, + const size_t& ipin_node_id, + const std::vector& Fc, + const size_t& offset, + const std::vector& segment_inf, + t_track2pin_map& track2ipin_map) { + /* Get a list of segment_ids*/ + enum e_side chan_side = rr_gsb.get_cb_chan_side(ipin_side); + SideManager chan_side_manager(chan_side); + std::vector seg_list = rr_gsb.get_chan_segment_ids(chan_side); + size_t chan_width = rr_gsb.get_chan_width(chan_side); + SideManager ipin_side_manager(ipin_side); + const RRNodeId& ipin_node = rr_gsb.get_ipin_node(ipin_side, ipin_node_id); + + for (size_t iseg = 0; iseg < seg_list.size(); ++iseg) { + /* Get a list of node that have the segment id */ + std::vector track_list = rr_gsb.get_chan_node_ids_by_segment_ids(chan_side, seg_list[iseg]); + /* Refine the track_list: keep those will have connection blocks in the GSB */ + std::vector actual_track_list; + for (size_t inode = 0; inode < track_list.size(); ++inode) { + /* Check if tracks allow connection blocks in the GSB*/ + if (false == is_gsb_in_track_cb_population(rr_graph, rr_gsb, chan_side, track_list[inode], segment_inf)) { + continue; /* Bypass condition */ + } + /* Push the node to actual_track_list */ + actual_track_list.push_back(track_list[inode]); + } + /* Check the actual track list */ + VTR_ASSERT(0 == actual_track_list.size() % 2); + + /* Scale Fc */ + int actual_Fc = std::ceil((float)Fc[iseg] * (float)actual_track_list.size() / (float)chan_width); + /* Minimum Fc should be 2 : ensure we will connect to a pair of routing tracks */ + actual_Fc = std::max(1, actual_Fc); + /* Compute the step between two connection from this IPIN to tracks: + * step = W' / Fc', W' and Fc' are the adapted W and Fc from actual_track_list and Fc_in + */ + size_t track_step = std::floor((float)actual_track_list.size() / (float)actual_Fc); + /* Make sure step should be at least 2 */ + track_step = std::max(1, (int)track_step); + /* Adapt offset to the range of actual_track_list */ + size_t actual_offset = offset % actual_track_list.size(); + /* rotate the track list by an offset */ + if (0 < actual_offset) { + std::rotate(actual_track_list.begin(), actual_track_list.begin() + actual_offset, actual_track_list.end()); + } + + /* Assign tracks: since we assign 2 track per round, we increment itrack by 2* step */ + int track_cnt = 0; + /* Keep assigning until we meet the Fc requirement */ + for (size_t itrack = 0; itrack < actual_track_list.size(); itrack = itrack + 2 * track_step) { + /* Update pin2track map */ + size_t chan_side_index = chan_side_manager.to_size_t(); + /* itrack may exceed the size of actual_track_list, adapt it */ + size_t actual_itrack = itrack % actual_track_list.size(); + /* track_index may exceed the chan_width(), adapt it */ + size_t track_index = actual_track_list[actual_itrack] % chan_width; + + track2ipin_map[chan_side_index][track_index].push_back(ipin_node); + + /* track_index may exceed the chan_width(), adapt it */ + track_index = (actual_track_list[actual_itrack] + 1) % chan_width; + + track2ipin_map[chan_side_index][track_index].push_back(ipin_node); + + track_cnt += 2; + } + + /* Ensure the number of tracks is similar to Fc */ + /* Give a warning if Fc is < track_cnt */ + /* + if (actual_Fc != track_cnt) { + vpr_printf(TIO_MESSAGE_INFO, + "IPIN Node(%lu) will have a different Fc(=%lu) than specified(=%lu)!\n", + ipin_node - rr_graph->rr_node, track_cnt, actual_Fc); + } + */ + } +} + +/************************************************************************ + * Build opin2track_map for an OPIN + * 1. build a list of routing tracks which are allowed for connections + * We will check the Switch Block (SB) population of each routing track. + * By comparing current chan_y - ylow, we can determine if a SB connection + * is required for each routing track + * 2. Divide the routing tracks by segment types, so that we can balance + * the connections between OPINs and different types of routing tracks. + * 3. Scale the Fc of each pin to the actual number of routing tracks + * actual_Fc = (int) Fc * num_tracks / chan_width + ***********************************************************************/ +static +void build_gsb_one_opin_pin2track_map(const RRGraph& rr_graph, + const RRGSB& rr_gsb, + const enum e_side& opin_side, + const size_t& opin_node_id, + const std::vector& Fc, + const size_t& offset, + const std::vector& segment_inf, + t_pin2track_map& opin2track_map) { + /* Get a list of segment_ids*/ + std::vector seg_list = rr_gsb.get_chan_segment_ids(opin_side); + enum e_side chan_side = opin_side; + size_t chan_width = rr_gsb.get_chan_width(chan_side); + SideManager opin_side_manager(opin_side); + + for (size_t iseg = 0; iseg < seg_list.size(); ++iseg) { + /* Get a list of node that have the segment id */ + std::vector track_list = rr_gsb.get_chan_node_ids_by_segment_ids(chan_side, seg_list[iseg]); + /* Refine the track_list: keep those will have connection blocks in the GSB */ + std::vector actual_track_list; + for (size_t inode = 0; inode < track_list.size(); ++inode) { + /* Check if tracks allow connection blocks in the GSB*/ + if (false == is_gsb_in_track_sb_population(rr_graph, rr_gsb, chan_side, + track_list[inode], segment_inf)) { + continue; /* Bypass condition */ + } + if (TRACK_START != determine_track_status_of_gsb(rr_graph, rr_gsb, chan_side, track_list[inode])) { + continue; /* Bypass condition */ + } + /* Push the node to actual_track_list */ + actual_track_list.push_back(track_list[inode]); + } + + /* Go the next segment if offset is zero or actual_track_list is empty */ + if (0 == actual_track_list.size()) { + continue; + } + + /* Scale Fc */ + int actual_Fc = std::ceil((float)Fc[iseg] * (float)actual_track_list.size() / (float)chan_width); + /* Minimum Fc should be 1 : ensure we will drive 1 routing track */ + actual_Fc = std::max(1, actual_Fc); + /* Compute the step between two connection from this IPIN to tracks: + * step = W' / Fc', W' and Fc' are the adapted W and Fc from actual_track_list and Fc_in + */ + size_t track_step = std::floor((float)actual_track_list.size() / (float)actual_Fc); + /* Track step mush be a multiple of 2!!!*/ + /* Make sure step should be at least 1 */ + track_step = std::max(1, (int)track_step); + /* Adapt offset to the range of actual_track_list */ + size_t actual_offset = offset % actual_track_list.size(); + + /* No need to rotate if offset is zero */ + if (0 < actual_offset) { + /* rotate the track list by an offset */ + std::rotate(actual_track_list.begin(), actual_track_list.begin() + actual_offset, actual_track_list.end()); + } + + /* Assign tracks */ + int track_cnt = 0; + /* Keep assigning until we meet the Fc requirement */ + for (size_t itrack = 0; itrack < actual_track_list.size(); itrack = itrack + track_step) { + /* Update pin2track map */ + size_t opin_side_index = opin_side_manager.to_size_t(); + /* itrack may exceed the size of actual_track_list, adapt it */ + size_t actual_itrack = itrack % actual_track_list.size(); + size_t track_index = actual_track_list[actual_itrack]; + const RRNodeId& track_rr_node_index = rr_gsb.get_chan_node(chan_side, track_index); + opin2track_map[opin_side_index][opin_node_id].push_back(track_rr_node_index); + /* update track counter */ + track_cnt++; + /* Stop when we have enough Fc: this may lead to some tracks have zero drivers. + * So I comment it. And we just make sure its track_cnt >= actual_Fc + if (actual_Fc == track_cnt) { + break; + } + */ + } + + /* Ensure the number of tracks is similar to Fc */ + /* Give a warning if Fc is < track_cnt */ + /* + if (actual_Fc != track_cnt) { + vpr_printf(TIO_MESSAGE_INFO, + "OPIN Node(%lu) will have a different Fc(=%lu) than specified(=%lu)!\n", + opin_node_id, track_cnt, actual_Fc); + } + */ + } +} + + +/************************************************************************ + * Build the track_to_ipin_map[gsb_side][0..chan_width-1][ipin_indices] + * based on the existing routing resources in the General Switch Block (GSB) + * This function supports both X-directional and Y-directional tracks + * The mapping is done in the following steps: + * 1. Build ipin_to_track_map[gsb_side][0..num_ipin_nodes-1][track_indices] + * For each IPIN, we ensure at least one connection to the tracks. + * Then, we assign IPINs to tracks evenly while satisfying the actual_Fc + * 2. Convert the ipin_to_track_map to track_to_ipin_map + ***********************************************************************/ +t_track2pin_map build_gsb_track_to_ipin_map(const RRGraph& rr_graph, + const RRGSB& rr_gsb, + const DeviceGrid& grids, + const std::vector& segment_inf, + const std::vector>& Fc_in) { + t_track2pin_map track2ipin_map; + /* Resize the matrix */ + track2ipin_map.resize(rr_gsb.get_num_sides()); + + /* offset counter: it aims to balance the track-to-IPIN for each connection block */ + size_t offset_size = 0; + std::vector offset; + for (size_t side = 0; side < rr_gsb.get_num_sides(); ++side) { + SideManager side_manager(side); + enum e_side ipin_side = side_manager.get_side(); + /* Get the chan_side */ + enum e_side chan_side = rr_gsb.get_cb_chan_side(ipin_side); + SideManager chan_side_manager(chan_side); + /* resize offset to the maximum chan_side*/ + offset_size = std::max(offset_size, chan_side_manager.to_size_t() + 1); + } + /* Initial offset */ + offset.resize(offset_size); + offset.assign(offset.size(), 0); + + /* Walk through each side */ + for (size_t side = 0; side < rr_gsb.get_num_sides(); ++side) { + SideManager side_manager(side); + enum e_side ipin_side = side_manager.get_side(); + /* Get the chan_side */ + enum e_side chan_side = rr_gsb.get_cb_chan_side(ipin_side); + SideManager chan_side_manager(chan_side); + /* This track2pin mapping is for Connection Blocks, so we only care two sides! */ + /* Get channel width and resize the matrix */ + size_t chan_width = rr_gsb.get_chan_width(chan_side); + track2ipin_map[chan_side_manager.to_size_t()].resize(chan_width); + /* Find the ipin/opin nodes */ + for (size_t inode = 0; inode < rr_gsb.get_num_ipin_nodes(ipin_side); ++inode) { + const RRNodeId& ipin_node = rr_gsb.get_ipin_node(ipin_side, inode); + /* Skip EMPTY type */ + if (true == is_empty_type(grids[rr_graph.node_xlow(ipin_node)][rr_graph.node_ylow(ipin_node)].type)) { + continue; + } + + int grid_type_index = grids[rr_graph.node_xlow(ipin_node)][rr_graph.node_ylow(ipin_node)].type->index; + /* Get Fc of the ipin */ + /* skip Fc = 0 or unintialized, those pins are in the */ + bool skip_conn2track = true; + std::vector ipin_Fc_out; + for (size_t iseg = 0; iseg < segment_inf.size(); ++iseg) { + int ipin_Fc = Fc_in[grid_type_index][rr_graph.node_pin_num(ipin_node)][iseg]; + ipin_Fc_out.push_back(ipin_Fc); + if (0 != ipin_Fc) { + skip_conn2track = false; + continue; + } + } + + if (true == skip_conn2track) { + continue; + } + + VTR_ASSERT(ipin_Fc_out.size() == segment_inf.size()); + + /* Build track2ipin_map for this IPIN */ + build_gsb_one_ipin_track2pin_map(rr_graph, rr_gsb, ipin_side, inode, ipin_Fc_out, + /* Give an offset for the first track that this ipin will connect to */ + offset[chan_side_manager.to_size_t()], + segment_inf, track2ipin_map); + /* update offset */ + offset[chan_side_manager.to_size_t()] += 2; + //printf("offset[%lu]=%lu\n", chan_side_manager.to_size_t(), offset[chan_side_manager.to_size_t()]); + } + } + + return track2ipin_map; +} + +/************************************************************************ + * Build the opin_to_track_map[gsb_side][0..num_opin_nodes-1][track_indices] + * based on the existing routing resources in the General Switch Block (GSB) + * This function supports both X-directional and Y-directional tracks + * The mapping is done in the following steps: + * 1. Build a list of routing tracks whose starting points locate at this GSB + * (xlow - gsb_x == 0) + * 2. Divide the routing tracks by segment types, so that we can balance + * the connections between OPINs and different types of routing tracks. + * 3. Scale the Fc of each pin to the actual number of routing tracks + * actual_Fc = (int) Fc * num_tracks / chan_width + ***********************************************************************/ +t_pin2track_map build_gsb_opin_to_track_map(const RRGraph& rr_graph, + const RRGSB& rr_gsb, + const DeviceGrid& grids, + const std::vector& segment_inf, + const std::vector>& Fc_out) { + t_pin2track_map opin2track_map; + /* Resize the matrix */ + opin2track_map.resize(rr_gsb.get_num_sides()); + + /* offset counter: it aims to balance the OPIN-to-track for each switch block */ + std::vector offset; + /* Get the chan_side: which is the same as the opin side */ + offset.resize(rr_gsb.get_num_sides()); + /* Initial offset */ + offset.assign(offset.size(), 0); + + /* Walk through each side */ + for (size_t side = 0; side < rr_gsb.get_num_sides(); ++side) { + SideManager side_manager(side); + enum e_side opin_side = side_manager.get_side(); + /* Get the chan_side */ + /* This track2pin mapping is for Connection Blocks, so we only care two sides! */ + /* Get channel width and resize the matrix */ + size_t num_opin_nodes = rr_gsb.get_num_opin_nodes(opin_side); + opin2track_map[side].resize(num_opin_nodes); + /* Find the ipin/opin nodes */ + for (size_t inode = 0; inode < num_opin_nodes; ++inode) { + const RRNodeId& opin_node = rr_gsb.get_opin_node(opin_side, inode); + /* Skip EMPTY type */ + if (true == is_empty_type(grids[rr_graph.node_xlow(opin_node)][rr_graph.node_ylow(opin_node)].type)) { + continue; + } + int grid_type_index = grids[rr_graph.node_xlow(opin_node)][rr_graph.node_ylow(opin_node)].type->index; + + /* Get Fc of the ipin */ + /* skip Fc = 0 or unintialized, those pins are in the */ + bool skip_conn2track = true; + std::vector opin_Fc_out; + for (size_t iseg = 0; iseg < segment_inf.size(); ++iseg) { + int opin_Fc = Fc_out[grid_type_index][rr_graph.node_pin_num(opin_node)][iseg]; + opin_Fc_out.push_back(opin_Fc); + if (0 != opin_Fc) { + skip_conn2track = false; + continue; + } + } + + if (true == skip_conn2track) { + continue; + } + VTR_ASSERT(opin_Fc_out.size() == segment_inf.size()); + + /* Build track2ipin_map for this IPIN */ + build_gsb_one_opin_pin2track_map(rr_graph, rr_gsb, opin_side, inode, opin_Fc_out, + /* Give an offset for the first track that this ipin will connect to */ + offset[side_manager.to_size_t()], + segment_inf, opin2track_map); + /* update offset: aim to rotate starting tracks by 1*/ + offset[side_manager.to_size_t()] += 1; + } + + /* Check: + * 1. We want to ensure that each OPIN will drive at least one track + * 2. We want to ensure that each track will be driven by at least 1 OPIN */ + } + + return opin2track_map; +} + +/************************************************************************ + * Add all direct clb-pin-to-clb-pin edges to given opin + ***********************************************************************/ +void build_direct_connections_for_one_gsb(RRGraph& rr_graph, + const DeviceGrid& grids, + const vtr::Point& from_grid_coordinate, + const RRSwitchId& delayless_switch, + const std::vector& directs, + const std::vector& clb_to_clb_directs) { + VTR_ASSERT(directs.size() == clb_to_clb_directs.size()); + + const t_grid_tile& from_grid = grids[from_grid_coordinate.x()][from_grid_coordinate.y()]; + t_physical_tile_type_ptr grid_type = from_grid.type; + + /* Iterate through all direct connections */ + for (size_t i = 0; i < directs.size(); ++i) { + /* Bypass unmatched direct clb-to-clb connections */ + if (grid_type != clb_to_clb_directs[i].from_clb_type) { + continue; + } + + /* This opin is specified to connect directly to an ipin, + * now compute which ipin to connect to + */ + vtr::Point to_grid_coordinate(from_grid_coordinate.x() + directs[i].x_offset, + from_grid_coordinate.y() + directs[i].y_offset); + + /* Bypass unmatched direct clb-to-clb connections */ + t_physical_tile_type_ptr to_grid_type = grids[to_grid_coordinate.x()][to_grid_coordinate.y()].type; + /* Check if to_grid if the same grid */ + if (to_grid_type != clb_to_clb_directs[i].to_clb_type) { + continue; + } + + bool swap; + int max_index, min_index; + /* Compute index of opin with regards to given pins */ + if ( clb_to_clb_directs[i].from_clb_pin_start_index + > clb_to_clb_directs[i].from_clb_pin_end_index) { + swap = true; + max_index = clb_to_clb_directs[i].from_clb_pin_start_index; + min_index = clb_to_clb_directs[i].from_clb_pin_end_index; + } else { + swap = false; + min_index = clb_to_clb_directs[i].from_clb_pin_start_index; + max_index = clb_to_clb_directs[i].from_clb_pin_end_index; + } + + /* get every opin in the range */ + for (int opin = min_index; opin <= max_index; ++opin) { + int offset = opin - min_index; + + if ( (to_grid_coordinate.x() < grids.width() - 1) + && (to_grid_coordinate.y() < grids.height() - 1) ) { + int ipin = OPEN; + if ( clb_to_clb_directs[i].to_clb_pin_start_index + > clb_to_clb_directs[i].to_clb_pin_end_index) { + if (true == swap) { + ipin = clb_to_clb_directs[i].to_clb_pin_end_index + offset; + } else { + ipin = clb_to_clb_directs[i].to_clb_pin_start_index - offset; + } + } else { + if(true == swap) { + ipin = clb_to_clb_directs[i].to_clb_pin_end_index - offset; + } else { + ipin = clb_to_clb_directs[i].to_clb_pin_start_index + offset; + } + } + + /* Get the pin index in the rr_graph */ + int from_grid_width_ofs = from_grid.width_offset; + int from_grid_height_ofs = from_grid.height_offset; + int to_grid_width_ofs = grids[to_grid_coordinate.x()][to_grid_coordinate.y()].width_offset; + int to_grid_height_ofs = grids[to_grid_coordinate.x()][to_grid_coordinate.y()].height_offset; + + /* Find the side of grid pins, the pin location should be unique! + * Pin location is required by searching a node in rr_graph + */ + std::vector opin_grid_side = find_grid_pin_sides(from_grid, opin); + VTR_ASSERT(1 == opin_grid_side.size()); + + std::vector ipin_grid_side = find_grid_pin_sides(grids[to_grid_coordinate.x()][to_grid_coordinate.y()], ipin); + VTR_ASSERT(1 == ipin_grid_side.size()); + + const RRNodeId& opin_node_id = rr_graph.find_node(from_grid_coordinate.x() - from_grid_width_ofs, + from_grid_coordinate.y() - from_grid_height_ofs, + OPIN, opin, opin_grid_side[0]); + const RRNodeId& ipin_node_id = rr_graph.find_node(to_grid_coordinate.x() - to_grid_width_ofs, + to_grid_coordinate.y() - to_grid_height_ofs, + IPIN, ipin, ipin_grid_side[0]); + /* + VTR_LOG("Direct connection: from grid[%lu][%lu].pin[%lu] at side %s to grid[%lu][%lu].pin[%lu] at side %s\n", + from_grid_coordinate.x() - from_grid_width_ofs, + from_grid_coordinate.y() - from_grid_height_ofs, + opin, SIDE_STRING[opin_grid_side[0]], + to_grid_coordinate.x() - to_grid_width_ofs, + to_grid_coordinate.y() - to_grid_height_ofs, + ipin, SIDE_STRING[ipin_grid_side[0]]); + */ + + /* add edges to the opin_node */ + rr_graph.create_edge(opin_node_id, ipin_node_id, + delayless_switch); + } + } + } +} + + +} /* end namespace openfpga */ diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.h b/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.h new file mode 100755 index 00000000000..adf6118fbbe --- /dev/null +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.h @@ -0,0 +1,80 @@ +#ifndef TILEABLE_RR_GRAPH_GSB_H +#define TILEABLE_RR_GRAPH_GSB_H + +/******************************************************************** + * Include header files that are required by function declaration + *******************************************************************/ +#include + +#include "vtr_vector.h" +#include "vtr_geometry.h" + +#include "physical_types.h" +#include "device_grid.h" + +#include "rr_gsb.h" +#include "rr_graph_obj.h" +#include "clb2clb_directs.h" + +/******************************************************************** + * Function declaration + *******************************************************************/ + +/* begin namespace openfpga */ +namespace openfpga { + +/************************************************************************ + * Data stuctures related to the functions + ***********************************************************************/ +typedef std::vector>> t_track2track_map; +typedef std::vector>> t_track2pin_map; +typedef std::vector>> t_pin2track_map; + +/************************************************************************ + * Functions + ***********************************************************************/ +t_track2track_map build_gsb_track_to_track_map(const RRGraph& rr_graph, + const RRGSB& rr_gsb, + const e_switch_block_type& sb_type, + const int& Fs, + const e_switch_block_type& sb_subtype, + const int& subFs, + const bool& wire_opposite_side, + const std::vector& segment_inf); + +RRGSB build_one_tileable_rr_gsb(const DeviceGrid& grids, + const RRGraph& rr_graph, + const vtr::Point& device_chan_width, + const std::vector& segment_inf, + const vtr::Point& gsb_coordinate); + +void build_edges_for_one_tileable_rr_gsb(RRGraph& rr_graph, + const RRGSB& rr_gsb, + const t_track2pin_map& track2ipin_map, + const t_pin2track_map& opin2track_map, + const t_track2track_map& track2track_map, + const vtr::vector& rr_node_driver_switches); + +t_track2pin_map build_gsb_track_to_ipin_map(const RRGraph& rr_graph, + const RRGSB& rr_gsb, + const DeviceGrid& grids, + const std::vector& segment_inf, + const std::vector>& Fc_in); + +t_pin2track_map build_gsb_opin_to_track_map(const RRGraph& rr_graph, + const RRGSB& rr_gsb, + const DeviceGrid& grids, + const std::vector& segment_inf, + const std::vector>& Fc_out); + +void build_direct_connections_for_one_gsb(RRGraph& rr_graph, + const DeviceGrid& grids, + const vtr::Point& from_grid_coordinate, + const RRSwitchId& delayless_switch, + const std::vector& directs, + const std::vector& clb_to_clb_directs); + +} /* end namespace openfpga */ + +#endif + diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp new file mode 100644 index 00000000000..89a0e264904 --- /dev/null +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp @@ -0,0 +1,1061 @@ +/************************************************************************ + * This file contains functions that are used to allocate nodes + * for the tileable routing resource graph builder + ***********************************************************************/ +/* Headers from vtrutil library */ +#include "vtr_assert.h" +#include "vtr_log.h" +#include "vtr_geometry.h" + +/* Headers from openfpgautil library */ +#include "openfpga_side_manager.h" + +#include "vpr_types.h" +#include "vpr_utils.h" + +#include "rr_node.h" + +#include "rr_graph_builder_utils.h" +#include "rr_graph_builder.h" +#include "tileable_chan_details_builder.h" +#include "tileable_rr_graph_node_builder.h" +#include "rr_rc_data.h" + +/* begin namespace openfpga */ +namespace openfpga { + +/************************************************************************ + * Find the number output pins by considering all the grid + ***********************************************************************/ +static +size_t estimate_num_grid_rr_nodes_by_type(const DeviceGrid& grids, + const t_rr_type& node_type) { + size_t num_grid_rr_nodes = 0; + + for (size_t ix = 0; ix < grids.width(); ++ix) { + for (size_t iy = 0; iy < grids.height(); ++iy) { + + /* Skip EMPTY tiles */ + if (true == is_empty_type(grids[ix][iy].type)) { + continue; + } + + /* Skip height > 1 or width > 1 tiles (mostly heterogeneous blocks) */ + if ( (0 < grids[ix][iy].width_offset) + || (0 < grids[ix][iy].height_offset) ) { + continue; + } + + enum e_side io_side = NUM_SIDES; + + /* If this is the block on borders, we consider IO side */ + if (true == is_io_type(grids[ix][iy].type)) { + vtr::Point io_device_size(grids.width() - 1, grids.height() - 1); + vtr::Point grid_coordinate(ix, iy); + io_side = determine_io_grid_pin_side(io_device_size, grid_coordinate); + } + + switch (node_type) { + case OPIN: + /* get the number of OPINs */ + num_grid_rr_nodes += get_grid_num_pins(grids[ix][iy], DRIVER, io_side); + break; + case IPIN: + /* get the number of IPINs */ + num_grid_rr_nodes += get_grid_num_pins(grids[ix][iy], RECEIVER, io_side); + break; + case SOURCE: + /* SOURCE: number of classes whose type is DRIVER */ + num_grid_rr_nodes += get_grid_num_classes(grids[ix][iy], DRIVER); + break; + case SINK: + /* SINK: number of classes whose type is RECEIVER */ + num_grid_rr_nodes += get_grid_num_classes(grids[ix][iy], RECEIVER); + break; + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid routing resource node!\n"); + exit(1); + } + } + } + + return num_grid_rr_nodes; +} + +/************************************************************************ + * For X-direction Channel: CHANX + * We pair each x-direction routing channel to the grid below it + * as they share the same coordinate + * + * As such, the range of CHANX coordinate starts from x = 1, y = 0 + * which is the grid (I/O) at the left bottom of the fabric + * + * As such, the range of CHANX coordinate ends to x = width - 2, y = height - 2 + * which is the grid at the top right of the core fabric + * Note that the I/O ring is + * + * TOP SIDE OF FPGA + * + * +-------------+ +-------------+ +---------------------+ + * | Grid | | Grid | ... | Grid | + * | [1][0] | | [2][0] | | [width-2][height-1] | + * +-------------+ +-------------+ +---------------------+ + * + * +-------------+ +-------------+ +---------------------+ + * | X-Channel | | X-Channel | ... | X-Channel | + * | [1][0] | | [2][0] | | [width-2][height-2] | + * +-------------+ +-------------+ +---------------------+ + * + * +-------------+ +-------------+ +---------------------+ + * | Grid | | Grid | ... | Grid | + * | [1][0] | | [2][0] | | [width-2][height-2] | + * +-------------+ +-------------+ +---------------------+ + * + * ... ... ... + * + * +-------------+ +-------------+ +--------------+ + * | X-Channel | | X-Channel | ... | X-Channel | + * | [1][1] | | [2][1] | | [width-2][1] | + * +-------------+ +-------------+ +--------------+ + * + * LEFT +-------------+ +-------------+ +--------------+ RIGHT + * SIDE | Grid | | Grid | ... | Grid | SIDE + * GRID | [1][1] | | [2][1] | | [width-2][1] | GRID + * +-------------+ +-------------+ +--------------+ + * + * +-------------+ +-------------+ +--------------+ + * | X-Channel | | X-Channel | ... | X-Channel | + * | [1][0] | | [2][0] | | [width-2][0] | + * +-------------+ +-------------+ +--------------+ + * + * +-------------+ +-------------+ +--------------+ + * | Grid | | Grid | ... | Grid | + * | [1][0] | | [2][0] | | [width-2][0] | + * +-------------+ +-------------+ +--------------+ + * + * BOTTOM SIDE OF FPGA + * + * The figure above describe how the X-direction routing channels are + * organized in a homogeneous FPGA fabric + * Note that we talk about general-purpose uni-directional routing architecture here + * It means that a routing track may span across multiple grids + * However, the hard limits are as follows + * All the routing tracks will start at the most LEFT routing channel + * All the routing tracks will end at the most RIGHT routing channel + * + * Things will become more complicated in terms of track starting and end + * in the context of heterogeneous FPGAs + * We may have a grid which span multiple column and rows, as exemplified in the figure below + * In such case, + * all the routing tracks [x-1][y] at the left side of the grid [x][y] are forced to end + * all the routing tracks [x+2][y] at the right side of the grid [x][y] are forced to start + * And there are no routing tracks inside the grid[x][y] + * It means that X-channel [x][y] & [x+1][y] will no exist + * + * +------------+ +-------------+ +-------------+ +--------------+ + * | X-Channel | | X-Channel | | X-Channel | | X-Channel | + * | [x-1][y+2] | | [x][y+2] | | [x+1][y+2] | | [x+2][y+2] | + * +------------+ +-------------+ +-------------+ +--------------+ + * + * +------------+ +-----------------------------------+ +--------------+ + * | Grid | | | | Grid | + * | [x-1][y+1] | | | | [x+2][y+1] | + * +------------+ | | +--------------+ + * | | + * +------------+ | | +--------------+ + * | X-channel | | Grid | | X-Channel | + * | [x-1][y] | | [x][y] - [x+1][y+1] | | [x+2][y] | + * +------------+ | | +--------------+ + * | | + * +------------+ | | +--------------+ + * | Grid | | | | Grid | + * | [x-1][y] | | | | [x+2][y] | + * +------------+ +-----------------------------------+ +--------------+ + * + * + * + ***********************************************************************/ +static +size_t estimate_num_chanx_rr_nodes(const DeviceGrid& grids, + const size_t& chan_width, + const std::vector& segment_infs, + const bool& through_channel) { + size_t num_chanx_rr_nodes = 0; + + for (size_t iy = 0; iy < grids.height() - 1; ++iy) { + for (size_t ix = 1; ix < grids.width() - 1; ++ix) { + vtr::Point chanx_coord(ix, iy); + + /* Bypass if the routing channel does not exist when through channels are not allowed */ + if ( (false == through_channel) + && (false == is_chanx_exist(grids, chanx_coord))) { + continue; + } + + bool force_start = false; + bool force_end = false; + + /* All the tracks have to start when + * - the routing channel touch the RIGHT side a heterogeneous block + * - the routing channel touch the LEFT side of FPGA + */ + if (true == is_chanx_right_to_multi_height_grid(grids, chanx_coord, through_channel)) { + force_start = true; + } + + /* All the tracks have to end when + * - the routing channel touch the LEFT side a heterogeneous block + * - the routing channel touch the RIGHT side of FPGA + */ + if (true == is_chanx_left_to_multi_height_grid(grids, chanx_coord, through_channel)) { + force_end = true; + } + + /* Evaluate if the routing channel locates in the middle of a grid */ + ChanNodeDetails chanx_details = build_unidir_chan_node_details(chan_width, grids.width() - 2, force_start, force_end, segment_infs); + /* When an INC_DIRECTION CHANX starts, we need a new rr_node */ + num_chanx_rr_nodes += chanx_details.get_num_starting_tracks(Direction::INC); + /* When an DEC_DIRECTION CHANX ends, we need a new rr_node */ + num_chanx_rr_nodes += chanx_details.get_num_ending_tracks(Direction::DEC); + } + } + + return num_chanx_rr_nodes; +} + +/************************************************************************ + * Estimate the number of CHANY rr_nodes for Y-direction routing channels + * The technical rationale is very similar to the X-direction routing channel + * Refer to the detailed explanation there + ***********************************************************************/ +static +size_t estimate_num_chany_rr_nodes(const DeviceGrid& grids, + const size_t& chan_width, + const std::vector& segment_infs, + const bool& through_channel) { + size_t num_chany_rr_nodes = 0; + + for (size_t ix = 0; ix < grids.width() - 1; ++ix) { + for (size_t iy = 1; iy < grids.height() - 1; ++iy) { + vtr::Point chany_coord(ix, iy); + + /* Bypass if the routing channel does not exist when through channel are not allowed */ + if ( (false == through_channel) + && (false == is_chany_exist(grids, chany_coord))) { + continue; + } + + + bool force_start = false; + bool force_end = false; + + /* All the tracks have to start when + * - the routing channel touch the TOP side a heterogeneous block + * - the routing channel touch the BOTTOM side of FPGA + */ + if (true == is_chany_top_to_multi_width_grid(grids, chany_coord, through_channel)) { + force_start = true; + } + + /* All the tracks have to end when + * - the routing channel touch the BOTTOM side a heterogeneous block + * - the routing channel touch the TOP side of FPGA + */ + if (true == is_chany_bottom_to_multi_width_grid(grids, chany_coord, through_channel)) { + force_end = true; + } + + ChanNodeDetails chany_details = build_unidir_chan_node_details(chan_width, grids.height() - 2, force_start, force_end, segment_infs); + /* When an INC_DIRECTION CHANX starts, we need a new rr_node */ + num_chany_rr_nodes += chany_details.get_num_starting_tracks(Direction::INC); + /* When an DEC_DIRECTION CHANX ends, we need a new rr_node */ + num_chany_rr_nodes += chany_details.get_num_ending_tracks(Direction::DEC); + } + } + + return num_chany_rr_nodes; +} + +/************************************************************************ + * Estimate the number of nodes by each type in a routing resource graph + ***********************************************************************/ +static +std::vector estimate_num_rr_nodes(const DeviceGrid& grids, + const vtr::Point& chan_width, + const std::vector& segment_infs, + const bool& through_channel) { + + /* Reset the OPIN, IPIN, SOURCE, SINK counter to be zero */ + std::vector num_rr_nodes_per_type(NUM_RR_TYPES, 0); + + /** + * 1 Find number of rr nodes related to grids + */ + num_rr_nodes_per_type[OPIN] = estimate_num_grid_rr_nodes_by_type(grids, OPIN); + num_rr_nodes_per_type[IPIN] = estimate_num_grid_rr_nodes_by_type(grids, IPIN); + num_rr_nodes_per_type[SOURCE] = estimate_num_grid_rr_nodes_by_type(grids, SOURCE); + num_rr_nodes_per_type[SINK] = estimate_num_grid_rr_nodes_by_type(grids, SINK); + + /** + * 2. Assign the segments for each routing channel, + * To be specific, for each routing track, we assign a routing segment. + * The assignment is subject to users' specifications, such as + * a. length of each type of segment + * b. frequency of each type of segment. + * c. routing channel width + * + * SPECIAL for fringes: + * All segments will start and ends with no exception + * + * IMPORTANT: we should be aware that channel width maybe different + * in X-direction and Y-direction channels!!! + * So we will load segment details for different channels + */ + num_rr_nodes_per_type[CHANX] = estimate_num_chanx_rr_nodes(grids, + chan_width.x(), + segment_infs, + through_channel); + num_rr_nodes_per_type[CHANY] = estimate_num_chany_rr_nodes(grids, + chan_width.y(), + segment_infs, + through_channel); + + return num_rr_nodes_per_type; +} + +/************************************************************************ + * Allocate rr_nodes to a rr_graph object + * This function just allocate the memory and ensure its efficiency + * It will NOT fill detailed information for each node!!! + * + * Note: ensure that there are NO nodes in the rr_graph + ***********************************************************************/ +void alloc_tileable_rr_graph_nodes(RRGraphBuilder& rr_graph_builder, + vtr::vector& rr_node_driver_switches, + const DeviceGrid& grids, + const vtr::Point& chan_width, + const std::vector& segment_infs, + const bool& through_channel) { + VTR_ASSERT(0 == rr_graph_builder.rr_nodes().size()); + + std::vector num_rr_nodes_per_type = estimate_num_rr_nodes(grids, + chan_width, + segment_infs, + through_channel); + + /* Reserve the number of node to be memory efficient */ + size_t num_nodes = 0; + for (const size_t& num_node_per_type : num_rr_nodes_per_type) { + num_nodes += num_node_per_type; + } + + rr_graph_builder.reserve_nodes(num_nodes); + + rr_node_driver_switches.reserve(num_nodes); +} + +/************************************************************************ + * Configure OPIN rr_nodes for this grid + * coordinates: xlow, ylow, xhigh, yhigh, + * features: capacity, ptc_num (pin_num), + * + * Note: this function should be applied ONLY to grid with 0 width offset and 0 height offset!!! + ***********************************************************************/ +static +void load_one_grid_opin_nodes_basic_info(RRGraphBuilder& rr_graph_builder, + vtr::vector& rr_node_driver_switches, + const vtr::Point& grid_coordinate, + const t_grid_tile& cur_grid, + const e_side& io_side, + const RRSwitchId& delayless_switch) { + SideManager io_side_manager(io_side); + + /* Walk through the width height of each grid, + * get pins and configure the rr_nodes + */ + for (int width = 0; width < cur_grid.type->width; ++width) { + for (int height = 0; height < cur_grid.type->height; ++height) { + /* Walk through sides */ + for (e_side side : SIDES) { + SideManager side_manager(side); + /* skip unwanted sides */ + if ( (true == is_io_type(cur_grid.type)) + && (side != io_side_manager.to_size_t()) && (NUM_SIDES != io_side) ) { + continue; + } + /* Find OPINs */ + /* Configure pins by pins */ + std::vector opin_list = get_grid_side_pins(cur_grid, DRIVER, side_manager.get_side(), + width, height); + for (const int& pin_num : opin_list) { + /* Create a new node and fill information */ + const RRNodeId& node = rr_graph_builder.node_lookup().find_node(width, height, OPIN, pin_num, side); + + /* node bounding box */ + rr_graph_builder.set_node_coordinates(node, grid_coordinate.x() + width, + grid_coordinate.y() + height, + grid_coordinate.x() + width, + grid_coordinate.y() + height); + rr_graph_builder.add_node_side(node, side_manager.get_side()); + rr_graph_builder.set_node_pin_num(node, pin_num); + + rr_graph_builder.set_node_capacity(node, 1); + + /* cost index is a FIXED value for OPIN */ + rr_graph_builder.set_node_cost_index(node, RRIndexedDataId(OPIN_COST_INDEX)); + + /* Switch info */ + VTR_ASSERT(size_t(node) == rr_node_driver_switches.size()); + rr_node_driver_switches.push_back(delayless_switch); + + /* RC data */ + rr_graph_builder.set_node_rc_index(node, NodeRCIndex(find_create_rr_rc_data(0., 0.))); + + } /* End of loading OPIN rr_nodes */ + } /* End of side enumeration */ + } /* End of height enumeration */ + } /* End of width enumeration */ + +} + +/************************************************************************ + * Configure IPIN rr_nodes for this grid + * coordinates: xlow, ylow, xhigh, yhigh, + * features: capacity, ptc_num (pin_num), + * + * Note: this function should be applied ONLY to grid with 0 width offset and 0 height offset!!! + ***********************************************************************/ +static +void load_one_grid_ipin_nodes_basic_info(RRGraphBuilder& rr_graph_builder, + vtr::vector& rr_node_driver_switches, + const vtr::Point& grid_coordinate, + const t_grid_tile& cur_grid, + const e_side& io_side, + const RRSwitchId& wire_to_ipin_switch) { + SideManager io_side_manager(io_side); + + /* Walk through the width and height of each grid, + * get pins and configure the rr_nodes + */ + for (int width = 0; width < cur_grid.type->width; ++width) { + for (int height = 0; height < cur_grid.type->height; ++height) { + /* Walk through sides */ + for (e_side side : SIDES) { + SideManager side_manager(side); + /* skip unwanted sides */ + if ( (true == is_io_type(cur_grid.type)) + && (side != io_side_manager.to_size_t()) && (NUM_SIDES != io_side) ) { + continue; + } + + /* Find IPINs */ + /* Configure pins by pins */ + std::vector ipin_list = get_grid_side_pins(cur_grid, RECEIVER, side_manager.get_side(), width, height); + for (const int& pin_num : ipin_list) { + /* Create a new node and fill information */ + const RRNodeId& node = rr_graph_builder.node_lookup().find_node(width, height, IPIN, pin_num, side); + + /* node bounding box */ + rr_graph_builder.set_node_coordinates(node, grid_coordinate.x() + width, + grid_coordinate.y() + height, + grid_coordinate.x() + width, + grid_coordinate.y() + height); + rr_graph_builder.add_node_side(node, side_manager.get_side()); + rr_graph_builder.set_node_pin_num(node, pin_num); + + rr_graph_builder.set_node_capacity(node, 1); + + /* cost index is a FIXED value for OPIN */ + rr_graph_builder.set_node_cost_index(node, RRIndexedDataId(IPIN_COST_INDEX)); + + /* Switch info */ + VTR_ASSERT(size_t(node) == rr_node_driver_switches.size()); + rr_node_driver_switches.push_back(wire_to_ipin_switch); + + /* RC data */ + rr_graph_builder.set_node_rc_index(node, NodeRCIndex(find_create_rr_rc_data(0., 0.))); + + } /* End of loading IPIN rr_nodes */ + } /* End of side enumeration */ + } /* End of height enumeration */ + } /* End of width enumeration */ +} + +/************************************************************************ + * Configure SOURCE rr_nodes for this grid + * coordinates: xlow, ylow, xhigh, yhigh, + * features: capacity, ptc_num (pin_num), + * + * Note: this function should be applied ONLY to grid with 0 width offset and 0 height offset!!! + ***********************************************************************/ +static +void load_one_grid_source_nodes_basic_info(RRGraphBuilder& rr_graph_builder, + vtr::vector& rr_node_driver_switches, + const vtr::Point& grid_coordinate, + const t_grid_tile& cur_grid, + const e_side& io_side, + const RRSwitchId& delayless_switch) { + SideManager io_side_manager(io_side); + + /* Set a SOURCE rr_node for each DRIVER class */ + for (int iclass = 0; iclass < cur_grid.type->num_class; ++iclass) { + /* Set a SINK rr_node for the OPIN */ + if (DRIVER != cur_grid.type->class_inf[iclass].type) { + continue; + } + + /* Create a new node and fill information */ + const RRNodeId& node = rr_graph_builder.node_lookup().find_node(grid_coordinate.x(), grid_coordinate.y(), SOURCE, iclass); + + /* node bounding box */ + rr_graph_builder.set_node_coordinates(node, grid_coordinate.x(), + grid_coordinate.y(), + grid_coordinate.x() + cur_grid.type->width - 1, + grid_coordinate.y() + cur_grid.type->height - 1); + rr_graph_builder.set_node_class_num(node, iclass); + + rr_graph_builder.set_node_capacity(node, 1); + + /* The capacity should be the number of pins in this class*/ + rr_graph_builder.set_node_capacity(node, cur_grid.type->class_inf[iclass].num_pins); + + /* cost index is a FIXED value for SOURCE */ + rr_graph_builder.set_node_cost_index(node, RRIndexedDataId(SOURCE_COST_INDEX)); + + /* Switch info */ + VTR_ASSERT(size_t(node) == rr_node_driver_switches.size()); + rr_node_driver_switches.push_back(delayless_switch); + + /* RC data */ + rr_graph_builder.set_node_rc_index(node, NodeRCIndex(find_create_rr_rc_data(0., 0.))); + + } /* End of class enumeration */ +} + +/************************************************************************ + * Configure SINK rr_nodes for this grid + * coordinates: xlow, ylow, xhigh, yhigh, + * features: capacity, ptc_num (pin_num), + * + * Note: this function should be applied ONLY to grid with 0 width offset and 0 height offset!!! + ***********************************************************************/ +static +void load_one_grid_sink_nodes_basic_info(RRGraphBuilder& rr_graph_builder, + vtr::vector& rr_node_driver_switches, + const vtr::Point& grid_coordinate, + const t_grid_tile& cur_grid, + const e_side& io_side, + const RRSwitchId& delayless_switch) { + SideManager io_side_manager(io_side); + + /* Set a SINK rr_node for each RECEIVER class */ + for (int iclass = 0; iclass < cur_grid.type->num_class; ++iclass) { + /* Set a SINK rr_node for the OPIN */ + if (RECEIVER != cur_grid.type->class_inf[iclass].type) { + continue; + } + + /* Create a new node and fill information */ + const RRNodeId& node = rr_graph_builder.node_lookup().find_node(grid_coordinate.x(), grid_coordinate.y(), SINK, iclass); + + /* node bounding box */ + rr_graph_builder.set_node_coordinates(node, grid_coordinate.x(), + grid_coordinate.y(), + grid_coordinate.x() + cur_grid.type->width - 1, + grid_coordinate.y() + cur_grid.type->height - 1); + rr_graph_builder.set_node_class_num(node, iclass); + + rr_graph_builder.set_node_capacity(node, 1); + + /* The capacity should be the number of pins in this class*/ + rr_graph_builder.set_node_capacity(node, cur_grid.type->class_inf[iclass].num_pins); + + /* cost index is a FIXED value for SINK */ + rr_graph_builder.set_node_cost_index(node, RRIndexedDataId(SINK_COST_INDEX)); + + /* Switch info */ + VTR_ASSERT(size_t(node) == rr_node_driver_switches.size()); + rr_node_driver_switches.push_back(delayless_switch); + + /* RC data */ + rr_graph_builder.set_node_rc_index(node, NodeRCIndex(find_create_rr_rc_data(0., 0.))); + + } /* End of class enumeration */ +} + +/************************************************************************ + * Create all the rr_nodes for grids + ***********************************************************************/ +static +void load_grid_nodes_basic_info(RRGraphBuilder& rr_graph_builder, + vtr::vector& rr_node_driver_switches, + const DeviceGrid& grids, + const RRSwitchId& wire_to_ipin_switch, + const RRSwitchId& delayless_switch) { + + for (size_t iy = 0; iy < grids.height(); ++iy) { + for (size_t ix = 0; ix < grids.width(); ++ix) { + /* Skip EMPTY tiles */ + if (true == is_empty_type(grids[ix][iy].type)) { + continue; + } + + /* We only build rr_nodes for grids with width_offset = 0 and height_offset = 0 */ + if ( (0 < grids[ix][iy].width_offset) + || (0 < grids[ix][iy].height_offset) ) { + continue; + } + + vtr::Point grid_coordinate(ix, iy); + enum e_side io_side = NUM_SIDES; + + /* If this is the block on borders, we consider IO side */ + if (true == is_io_type(grids[ix][iy].type)) { + vtr::Point io_device_size(grids.width() - 1, grids.height() - 1); + io_side = determine_io_grid_pin_side(io_device_size, grid_coordinate); + } + + /* Configure source rr_nodes for this grid */ + load_one_grid_source_nodes_basic_info(rr_graph_builder, + rr_node_driver_switches, + grid_coordinate, + grids[ix][iy], + io_side, + delayless_switch); + + /* Configure sink rr_nodes for this grid */ + load_one_grid_sink_nodes_basic_info(rr_graph_builder, + rr_node_driver_switches, + grid_coordinate, + grids[ix][iy], + io_side, + delayless_switch); + + /* Configure opin rr_nodes for this grid */ + load_one_grid_opin_nodes_basic_info(rr_graph_builder, + rr_node_driver_switches, + grid_coordinate, + grids[ix][iy], + io_side, + delayless_switch); + + /* Configure ipin rr_nodes for this grid */ + load_one_grid_ipin_nodes_basic_info(rr_graph_builder, + rr_node_driver_switches, + grid_coordinate, + grids[ix][iy], + io_side, + wire_to_ipin_switch); + + } + } +} + +/************************************************************************ + * Initialize the basic information of routing track rr_nodes + * coordinates: xlow, ylow, xhigh, yhigh, + * features: capacity, track_ids, ptc_num, direction + ***********************************************************************/ +static +void load_one_chan_rr_nodes_basic_info(RRGraphView& rr_graph, + RRGraphBuilder& rr_graph_builder, + vtr::vector& rr_node_driver_switches, + std::map>& rr_node_track_ids, + const vtr::Point& chan_coordinate, + const t_rr_type& chan_type, + ChanNodeDetails& chan_details, + const std::vector& segment_infs, + const int& cost_index_offset) { + /* Check each node_id(potential ptc_num) in the channel : + * If this is a starting point, we set a new rr_node with xlow/ylow, ptc_num + * If this is a ending point, we set xhigh/yhigh and track_ids + * For other nodes, we set changes in track_ids + */ + for (size_t itrack = 0; itrack < chan_details.get_chan_width(); ++itrack) { + /* For INC direction, a starting point requires a new chan rr_node */ + if ( ( (true == chan_details.is_track_start(itrack)) + && (Direction::INC == chan_details.get_track_direction(itrack)) ) + /* For DEC direction, an ending point requires a new chan rr_node */ + || + ( (true == chan_details.is_track_end(itrack)) + && (Direction::DEC == chan_details.get_track_direction(itrack)) ) ) { + + /* Create a new chan rr_node */ + const RRNodeId& node = rr_graph_builder.node_lookup().find_node(chan_coordinate.x(), chan_coordinate.y(), chan_type, itrack); + + rr_graph_builder.set_node_direction(node, chan_details.get_track_direction(itrack)); + rr_graph_builder.set_node_track_num(node, itrack); + rr_node_track_ids[node].push_back(itrack); + + rr_graph_builder.set_node_capacity(node, 1); + + /* assign switch id */ + size_t seg_id = chan_details.get_track_segment_id(itrack); + VTR_ASSERT(size_t(node) == rr_node_driver_switches.size()); + rr_node_driver_switches.push_back(RRSwitchId(segment_infs[seg_id].arch_opin_switch)); + + /* Update chan_details with node_id */ + chan_details.set_track_node_id(itrack, size_t(node)); + + /* cost index depends on the segment index */ + rr_graph_builder.set_node_cost_index(node, RRIndexedDataId(cost_index_offset + seg_id)); + /* Finish here, go to next */ + } + + /* For INC direction, an ending point requires an update on xhigh and yhigh */ + if ( ( (true == chan_details.is_track_end(itrack)) + && (Direction::INC == chan_details.get_track_direction(itrack)) ) + || + /* For DEC direction, an starting point requires an update on xlow and ylow */ + ( (true == chan_details.is_track_start(itrack)) + && (Direction::DEC == chan_details.get_track_direction(itrack)) ) ) { + + /* Get the node_id */ + const RRNodeId& rr_node_id = RRNodeId(chan_details.get_track_node_id(itrack)); + + /* Do a quick check, make sure we do not mistakenly modify other nodes */ + VTR_ASSERT(chan_type == rr_graph.node_type(rr_node_id)); + VTR_ASSERT(chan_details.get_track_direction(itrack) == rr_graph.node_direction(rr_node_id)); + + /* set xhigh/yhigh and push changes to track_ids */ + rr_graph_builder.set_node_coordinates(rr_node_id, rr_graph.node_xlow(rr_node_id), + rr_graph.node_ylow(rr_node_id), + chan_coordinate.x(), + chan_coordinate.y()); + + /* Do not update track_ids for length-1 wires, they should have only 1 track_id */ + if ( (rr_graph.node_xhigh(rr_node_id) > rr_graph.node_xlow(rr_node_id)) + || (rr_graph.node_yhigh(rr_node_id) > rr_graph.node_ylow(rr_node_id)) ) { + rr_node_track_ids[rr_node_id].push_back(itrack); + rr_graph_builder.set_node_track_num(rr_node_id, itrack); + } + /* Finish here, go to next */ + } + + /* Finish processing starting and ending tracks */ + if ( (true == chan_details.is_track_start(itrack)) + || (true == chan_details.is_track_end(itrack)) ) { + /* Finish here, go to next */ + continue; + } + + /* For other nodes, we get the node_id and just update track_ids */ + /* Ensure those nodes are neither starting nor ending points */ + VTR_ASSERT( (false == chan_details.is_track_start(itrack)) + && (false == chan_details.is_track_end(itrack)) ); + + /* Get the node_id */ + const RRNodeId& rr_node_id = RRNodeId(chan_details.get_track_node_id(itrack)); + + /* Do a quick check, make sure we do not mistakenly modify other nodes */ + VTR_ASSERT(chan_type == rr_graph.node_type(rr_node_id)); + VTR_ASSERT(chan_details.get_track_direction(itrack) == rr_graph.node_direction(rr_node_id)); + + /* Deposit xhigh and yhigh using the current chan_coordinate + * We will update when this track ends + */ + rr_graph_builder.set_node_coordinates(rr_node_id, rr_graph.node_xlow(rr_node_id), + rr_graph.node_ylow(rr_node_id), + chan_coordinate.x(), + chan_coordinate.y()); + + /* Update track_ids */ + rr_node_track_ids[rr_node_id].push_back(itrack); + rr_graph_builder.set_node_track_num(rr_node_id, itrack); + /* Finish here, go to next */ + } +} + +/************************************************************************ + * Initialize the basic information of X-channel rr_nodes: + * coordinates: xlow, ylow, xhigh, yhigh, + * features: capacity, track_ids, ptc_num, direction + * grid_info : pb_graph_pin + ***********************************************************************/ +static +void load_chanx_rr_nodes_basic_info(RRGraphView& rr_graph, + RRGraphBuilder& rr_graph_builder, + vtr::vector& rr_node_driver_switches, + std::map>& rr_node_track_ids, + const DeviceGrid& grids, + const size_t& chan_width, + const std::vector& segment_infs, + const bool& through_channel) { + + /* For X-direction Channel: CHANX */ + for (size_t iy = 0; iy < grids.height() - 1; ++iy) { + /* Keep a vector of node_ids for the channels, because we will rotate them when walking through ix */ + std::vector track_node_ids; + + for (size_t ix = 1; ix < grids.width() - 1; ++ix) { + vtr::Point chanx_coord(ix, iy); + + /* Bypass if the routing channel does not exist when through channels are not allowed */ + if ( (false == through_channel) + && (false == is_chanx_exist(grids, chanx_coord))) { + continue; + } + + bool force_start = false; + bool force_end = false; + + /* All the tracks have to start when + * - the routing channel touch the RIGHT side a heterogeneous block + * - the routing channel touch the LEFT side of FPGA + */ + if (true == is_chanx_right_to_multi_height_grid(grids, chanx_coord, through_channel)) { + force_start = true; + } + + /* All the tracks have to end when + * - the routing channel touch the LEFT side a heterogeneous block + * - the routing channel touch the RIGHT side of FPGA + */ + if (true == is_chanx_left_to_multi_height_grid(grids, chanx_coord, through_channel)) { + force_end = true; + } + + ChanNodeDetails chanx_details = build_unidir_chan_node_details(chan_width, grids.width() - 2, + force_start, force_end, segment_infs); + /* Force node_ids from the previous chanx */ + if (0 < track_node_ids.size()) { + /* Rotate should be done based on a typical case of routing tracks. + * Tracks on the borders are not regularly started and ended, + * which causes the node_rotation malfunction + */ + ChanNodeDetails chanx_details_tt = build_unidir_chan_node_details(chan_width, grids.width() - 2, + false, false, segment_infs); + chanx_details_tt.set_track_node_ids(track_node_ids); + + /* TODO: + * Do NOT rotate the tracks when the routing channel + * locates inside a multi-height and multi-width grid + * Let the routing channel passing through the grid (if through channel is allowed!) + * An example: + * + * +------------------------------ + * | | + * | Grid | + * track0 ----->+-----------------------------+----> track0 + * | | + */ + if (true == is_chanx_exist(grids, chanx_coord, through_channel)) { + /* Rotate the chanx_details by an offset of ix - 1, the distance to the most left channel */ + /* For INC_DIRECTION, we use clockwise rotation + * node_id A ----> -----> node_id D + * node_id B ----> / ----> node_id A + * node_id C ----> / ----> node_id B + * node_id D ----> ----> node_id C + */ + chanx_details_tt.rotate_track_node_id(1, Direction::INC, true); + /* For DEC_DIRECTION, we use clockwise rotation + * node_id A <----- <----- node_id B + * node_id B <----- \ <----- node_id C + * node_id C <----- \ <----- node_id D + * node_id D <----- <----- node_id A + */ + chanx_details_tt.rotate_track_node_id(1, Direction::DEC, false); + } + + track_node_ids = chanx_details_tt.get_track_node_ids(); + chanx_details.set_track_node_ids(track_node_ids); + } + + /* Configure CHANX in this channel */ + load_one_chan_rr_nodes_basic_info(rr_graph, + rr_graph_builder, + rr_node_driver_switches, + rr_node_track_ids, + chanx_coord, CHANX, + chanx_details, + segment_infs, + CHANX_COST_INDEX_START); + /* Get a copy of node_ids */ + track_node_ids = chanx_details.get_track_node_ids(); + } + } +} + +/************************************************************************ + * Initialize the basic information of Y-channel rr_nodes: + * coordinates: xlow, ylow, xhigh, yhigh, + * features: capacity, track_ids, ptc_num, direction + ***********************************************************************/ +static +void load_chany_rr_nodes_basic_info(RRGraphView& rr_graph, + RRGraphBuilder& rr_graph_builder, + vtr::vector& rr_node_driver_switches, + std::map>& rr_node_track_ids, + const DeviceGrid& grids, + const size_t& chan_width, + const std::vector& segment_infs, + const bool& through_channel) { + + /* For Y-direction Channel: CHANY */ + for (size_t ix = 0; ix < grids.width() - 1; ++ix) { + /* Keep a vector of node_ids for the channels, because we will rotate them when walking through ix */ + std::vector track_node_ids; + + for (size_t iy = 1; iy < grids.height() - 1; ++iy) { + vtr::Point chany_coord(ix, iy); + + /* Bypass if the routing channel does not exist when through channel are not allowed */ + if ( (false == through_channel) + && (false == is_chany_exist(grids, chany_coord))) { + continue; + } + + bool force_start = false; + bool force_end = false; + + /* All the tracks have to start when + * - the routing channel touch the TOP side a heterogeneous block + * - the routing channel touch the BOTTOM side of FPGA + */ + if (true == is_chany_top_to_multi_width_grid(grids, chany_coord, through_channel)) { + force_start = true; + } + + /* All the tracks have to end when + * - the routing channel touch the BOTTOM side a heterogeneous block + * - the routing channel touch the TOP side of FPGA + */ + if (true == is_chany_bottom_to_multi_width_grid(grids, chany_coord, through_channel)) { + force_end = true; + } + + ChanNodeDetails chany_details = build_unidir_chan_node_details(chan_width, grids.height() - 2, + force_start, force_end, segment_infs); + /* Force node_ids from the previous chany + * This will not be applied when the routing channel is cut off (force to start) + */ + if (0 < track_node_ids.size()) { + /* Rotate should be done based on a typical case of routing tracks. + * Tracks on the borders are not regularly started and ended, + * which causes the node_rotation malfunction + */ + ChanNodeDetails chany_details_tt = build_unidir_chan_node_details(chan_width, grids.height() - 2, + false, false, segment_infs); + + chany_details_tt.set_track_node_ids(track_node_ids); + + /* TODO: + * Do NOT rotate the tracks when the routing channel + * locates inside a multi-height and multi-width grid + * Let the routing channel passing through the grid (if through channel is allowed!) + * An example: + * + * +------------------------------ + * | | + * | Grid | + * track0 ----->+-----------------------------+----> track0 + * | | + * we should rotate only once at the bottom side of a grid + */ + if (true == is_chany_exist(grids, chany_coord, through_channel)) { + /* Rotate the chany_details by an offset of 1*/ + /* For INC_DIRECTION, we use clockwise rotation + * node_id A ----> -----> node_id D + * node_id B ----> / ----> node_id A + * node_id C ----> / ----> node_id B + * node_id D ----> ----> node_id C + */ + chany_details_tt.rotate_track_node_id(1, Direction::INC, true); + /* For DEC_DIRECTION, we use clockwise rotation + * node_id A <----- <----- node_id B + * node_id B <----- \ <----- node_id C + * node_id C <----- \ <----- node_id D + * node_id D <----- <----- node_id A + */ + chany_details_tt.rotate_track_node_id(1, Direction::DEC, false); + } + + track_node_ids = chany_details_tt.get_track_node_ids(); + chany_details.set_track_node_ids(track_node_ids); + } + /* Configure CHANX in this channel */ + load_one_chan_rr_nodes_basic_info(rr_graph, + rr_graph_builder, + rr_node_driver_switches, + rr_node_track_ids, + chany_coord, CHANY, + chany_details, + segment_infs, + CHANX_COST_INDEX_START + segment_infs.size()); + /* Get a copy of node_ids */ + track_node_ids = chany_details.get_track_node_ids(); + } + } +} + +/************************************************************************ + * Reverse the track_ids of CHANX and CHANY nodes in DEC_DIRECTION + * This is required as the track ids are allocated in the sequence + * of incrementing x and y + * However, DEC direction routing tracks should have a reversed sequence in + * track ids + ***********************************************************************/ +static +void reverse_dec_chan_rr_node_track_ids(const RRGraphView& rr_graph, + std::map>& rr_node_track_ids) { + // this should call rr_graph_view to do the job + +for (auto& node : rr_graph.nodes()) { + /* Bypass condition: only focus on CHANX and CHANY in DEC_DIRECTION */ + if ( (CHANX != rr_graph.node_type(node)) + && (CHANY != rr_graph.node_type(node)) ) { + continue; + } + /* Reach here, we must have a node of CHANX or CHANY */ + if (Direction::DEC != rr_graph.node_direction(node)) { + continue; + } + std::reverse(rr_node_track_ids[node].begin(), + rr_node_track_ids[node].end() ); + } +} + +/************************************************************************ + * Create all the rr_nodes covering both grids and routing channels + ***********************************************************************/ +void create_tileable_rr_graph_nodes(RRGraphView& rr_graph, + RRGraphBuilder& rr_graph_builder, + vtr::vector& rr_node_driver_switches, + std::map>& rr_node_track_ids, + const DeviceGrid& grids, + const vtr::Point& chan_width, + const std::vector& segment_infs, + const RRSwitchId& wire_to_ipin_switch, + const RRSwitchId& delayless_switch, + const bool& through_channel) { + load_grid_nodes_basic_info(rr_graph_builder, + rr_node_driver_switches, + grids, + wire_to_ipin_switch, + delayless_switch); + + load_chanx_rr_nodes_basic_info(rr_graph, + rr_graph_builder, + rr_node_driver_switches, + rr_node_track_ids, + grids, + chan_width.x(), + segment_infs, + through_channel); + + load_chany_rr_nodes_basic_info(rr_graph, + rr_graph_builder, + rr_node_driver_switches, + rr_node_track_ids, + grids, + chan_width.y(), + segment_infs, + through_channel); + + reverse_dec_chan_rr_node_track_ids(rr_graph, + rr_node_track_ids); + +} + +} /* end namespace openfpga */ diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.h b/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.h new file mode 100644 index 00000000000..1e90fc2feda --- /dev/null +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.h @@ -0,0 +1,47 @@ +#ifndef TILEABLE_RR_GRAPH_NODE_BUILDER_H +#define TILEABLE_RR_GRAPH_NODE_BUILDER_H + +/******************************************************************** + * Include header files that are required by function declaration + *******************************************************************/ +/* Headers from vtrutil library */ +#include "vtr_geometry.h" + +/* Headers from readarch library */ +#include "physical_types.h" + +/* Headers from vpr library */ +#include "rr_graph_obj.h" +#include "device_grid.h" +#include "rr_graph_view.h" +#include "rr_graph_builder.h" + +/******************************************************************** + * Function declaration + *******************************************************************/ + +/* begin namespace openfpga */ +namespace openfpga { + +void alloc_tileable_rr_graph_nodes(RRGraphBuilder& rr_graph_builder, + vtr::vector& driver_switches, + const DeviceGrid& grids, + const vtr::Point& chan_width, + const std::vector& segment_infs, + const bool& through_channel); + +void create_tileable_rr_graph_nodes(RRGraphView& rr_graph, + RRGraphBuilder& rr_graph_builder, + vtr::vector& rr_node_driver_switches, + std::map>& rr_node_track_ids, + const DeviceGrid& grids, + const vtr::Point& chan_width, + const std::vector& segment_infs, + const RRSwitchId& wire_to_ipin_switch, + const RRSwitchId& delayless_switch, + const bool& through_channel); + + +} /* end namespace openfpga */ + +#endif From 619caea32c36e087d620c0b6aba64455369edc70 Mon Sep 17 00:00:00 2001 From: taoli4rs Date: Tue, 26 Jul 2022 12:54:51 -0700 Subject: [PATCH 003/147] Fix format issue. --- .../tileable_rr_graph/chan_node_details.cpp | 355 ++- .../openfpga_rr_graph_utils.cpp | 178 +- vpr/src/tileable_rr_graph/rr_chan.cpp | 252 +- .../rr_graph_builder_utils.cpp | 477 ++-- vpr/src/tileable_rr_graph/rr_gsb.cpp | 1523 ++++++------ .../tileable_chan_details_builder.cpp | 254 +-- .../tileable_rr_graph_builder.cpp | 350 +-- .../tileable_rr_graph_edge_builder.cpp | 219 +- .../tileable_rr_graph_edge_builder.h | 5 - .../tileable_rr_graph_gsb.cpp | 2031 ++++++++--------- .../tileable_rr_graph_node_builder.cpp | 1297 ++++++----- .../tileable_rr_graph_node_builder.h | 13 +- 12 files changed, 3445 insertions(+), 3509 deletions(-) diff --git a/vpr/src/tileable_rr_graph/chan_node_details.cpp b/vpr/src/tileable_rr_graph/chan_node_details.cpp index 6f0f38e820c..3da5f2f29de 100644 --- a/vpr/src/tileable_rr_graph/chan_node_details.cpp +++ b/vpr/src/tileable_rr_graph/chan_node_details.cpp @@ -15,68 +15,68 @@ namespace openfpga { * Constructors ***********************************************************************/ ChanNodeDetails::ChanNodeDetails(const ChanNodeDetails& src) { - /* duplicate */ - size_t chan_width = src.get_chan_width(); - this->reserve(chan_width); - for (size_t itrack = 0; itrack < chan_width; ++itrack) { - track_node_ids_.push_back(src.get_track_node_id(itrack)); - track_direction_.push_back(src.get_track_direction(itrack)); - seg_ids_.push_back(src.get_track_segment_id(itrack)); - seg_length_.push_back(src.get_track_segment_length(itrack)); - track_start_.push_back(src.is_track_start(itrack)); - track_end_.push_back(src.is_track_end(itrack)); - } + /* duplicate */ + size_t chan_width = src.get_chan_width(); + this->reserve(chan_width); + for (size_t itrack = 0; itrack < chan_width; ++itrack) { + track_node_ids_.push_back(src.get_track_node_id(itrack)); + track_direction_.push_back(src.get_track_direction(itrack)); + seg_ids_.push_back(src.get_track_segment_id(itrack)); + seg_length_.push_back(src.get_track_segment_length(itrack)); + track_start_.push_back(src.is_track_start(itrack)); + track_end_.push_back(src.is_track_end(itrack)); + } } ChanNodeDetails::ChanNodeDetails() { - this->clear(); + this->clear(); } /************************************************************************ * Accessors ***********************************************************************/ size_t ChanNodeDetails::get_chan_width() const { - VTR_ASSERT(validate_chan_width()); - return track_node_ids_.size(); + VTR_ASSERT(validate_chan_width()); + return track_node_ids_.size(); } size_t ChanNodeDetails::get_track_node_id(const size_t& track_id) const { - VTR_ASSERT(validate_track_id(track_id)); - return track_node_ids_[track_id]; + VTR_ASSERT(validate_track_id(track_id)); + return track_node_ids_[track_id]; } /* Return a copy of vector */ std::vector ChanNodeDetails::get_track_node_ids() const { - std::vector copy; - for (size_t inode = 0; inode < get_chan_width(); ++inode) { - copy.push_back(track_node_ids_[inode]); - } - return copy; + std::vector copy; + for (size_t inode = 0; inode < get_chan_width(); ++inode) { + copy.push_back(track_node_ids_[inode]); + } + return copy; } Direction ChanNodeDetails::get_track_direction(const size_t& track_id) const { - VTR_ASSERT(validate_track_id(track_id)); - return track_direction_[track_id]; + VTR_ASSERT(validate_track_id(track_id)); + return track_direction_[track_id]; } size_t ChanNodeDetails::get_track_segment_length(const size_t& track_id) const { - VTR_ASSERT(validate_track_id(track_id)); - return seg_length_[track_id]; + VTR_ASSERT(validate_track_id(track_id)); + return seg_length_[track_id]; } size_t ChanNodeDetails::get_track_segment_id(const size_t& track_id) const { - VTR_ASSERT(validate_track_id(track_id)); - return seg_ids_[track_id]; + VTR_ASSERT(validate_track_id(track_id)); + return seg_ids_[track_id]; } -bool ChanNodeDetails::is_track_start(const size_t& track_id) const { - VTR_ASSERT(validate_track_id(track_id)); - return track_start_[track_id]; +bool ChanNodeDetails::is_track_start(const size_t& track_id) const { + VTR_ASSERT(validate_track_id(track_id)); + return track_start_[track_id]; } -bool ChanNodeDetails::is_track_end(const size_t& track_id) const { - VTR_ASSERT(validate_track_id(track_id)); - return track_end_[track_id]; +bool ChanNodeDetails::is_track_end(const size_t& track_id) const { + VTR_ASSERT(validate_track_id(track_id)); + return track_end_[track_id]; } /* Track_id is the starting point of group (whose is_start should be true) @@ -84,216 +84,213 @@ bool ChanNodeDetails::is_track_end(const size_t& track_id) const { * A group size is the number of such nodes between the starting points (include the 1st starting point) */ std::vector ChanNodeDetails::get_seg_group(const size_t& track_id) const { - VTR_ASSERT(validate_chan_width()); - VTR_ASSERT(validate_track_id(track_id)); - VTR_ASSERT(is_track_start(track_id)); - - std::vector group; - /* Make sure a clean start */ - group.clear(); - - for (size_t itrack = track_id; itrack < get_chan_width(); ++itrack) { - if ( (get_track_direction(itrack) != get_track_direction(track_id) ) - || (get_track_segment_id(itrack) != get_track_segment_id(track_id)) ) { - /* Bypass any nodes in different direction and segment information*/ - continue; - } - if ( (false == is_track_start(itrack)) - || ( (true == is_track_start(itrack)) && (itrack == track_id)) ) { - group.push_back(itrack); - continue; - } - /* Stop if this another starting point */ - if (true == is_track_start(itrack)) { - break; + VTR_ASSERT(validate_chan_width()); + VTR_ASSERT(validate_track_id(track_id)); + VTR_ASSERT(is_track_start(track_id)); + + std::vector group; + /* Make sure a clean start */ + group.clear(); + + for (size_t itrack = track_id; itrack < get_chan_width(); ++itrack) { + if ((get_track_direction(itrack) != get_track_direction(track_id)) + || (get_track_segment_id(itrack) != get_track_segment_id(track_id))) { + /* Bypass any nodes in different direction and segment information*/ + continue; + } + if ((false == is_track_start(itrack)) + || ((true == is_track_start(itrack)) && (itrack == track_id))) { + group.push_back(itrack); + continue; + } + /* Stop if this another starting point */ + if (true == is_track_start(itrack)) { + break; + } } - } - return group; + return group; } /* Get a list of track_ids with the given list of track indices */ std::vector ChanNodeDetails::get_seg_group_node_id(const std::vector& seg_group) const { - std::vector group; - /* Make sure a clean start */ - group.clear(); + std::vector group; + /* Make sure a clean start */ + group.clear(); - for (size_t id = 0; id < seg_group.size(); ++id) { - VTR_ASSERT(validate_track_id(seg_group[id])); - group.push_back(get_track_node_id(seg_group[id])); - } + for (size_t id = 0; id < seg_group.size(); ++id) { + VTR_ASSERT(validate_track_id(seg_group[id])); + group.push_back(get_track_node_id(seg_group[id])); + } - return group; + return group; } /* Get the number of tracks that starts in this routing channel */ size_t ChanNodeDetails::get_num_starting_tracks(const Direction& track_direction) const { - size_t counter = 0; - for (size_t itrack = 0; itrack < get_chan_width(); ++itrack) { - /* Bypass unmatched track_direction */ - if (track_direction != get_track_direction(itrack)) { - continue; + size_t counter = 0; + for (size_t itrack = 0; itrack < get_chan_width(); ++itrack) { + /* Bypass unmatched track_direction */ + if (track_direction != get_track_direction(itrack)) { + continue; + } + if (false == is_track_start(itrack)) { + continue; + } + counter++; } - if (false == is_track_start(itrack)) { - continue; - } - counter++; - } - return counter; + return counter; } /* Get the number of tracks that ends in this routing channel */ size_t ChanNodeDetails::get_num_ending_tracks(const Direction& track_direction) const { - size_t counter = 0; - for (size_t itrack = 0; itrack < get_chan_width(); ++itrack) { - /* Bypass unmatched track_direction */ - if (track_direction != get_track_direction(itrack)) { - continue; + size_t counter = 0; + for (size_t itrack = 0; itrack < get_chan_width(); ++itrack) { + /* Bypass unmatched track_direction */ + if (track_direction != get_track_direction(itrack)) { + continue; + } + if (false == is_track_end(itrack)) { + continue; + } + counter++; } - if (false == is_track_end(itrack)) { - continue; - } - counter++; - } - return counter; + return counter; } - /************************************************************************ * Mutators ***********************************************************************/ /* Reserve the capacitcy of vectors */ void ChanNodeDetails::reserve(const size_t& chan_width) { - track_node_ids_.reserve(chan_width); - track_direction_.reserve(chan_width); - seg_length_.reserve(chan_width); - seg_ids_.reserve(chan_width); - track_start_.reserve(chan_width); - track_end_.reserve(chan_width); + track_node_ids_.reserve(chan_width); + track_direction_.reserve(chan_width); + seg_length_.reserve(chan_width); + seg_ids_.reserve(chan_width); + track_start_.reserve(chan_width); + track_end_.reserve(chan_width); } /* Add a track to the channel */ -void ChanNodeDetails::add_track(const size_t& track_node_id, const Direction& track_direction, - const size_t& seg_id, const size_t& seg_length, - const size_t& is_start, const size_t& is_end) { - track_node_ids_.push_back(track_node_id); - track_direction_.push_back(track_direction); - seg_ids_.push_back(seg_id); - seg_length_.push_back(seg_length); - track_start_.push_back(is_start); - track_end_.push_back(is_end); +void ChanNodeDetails::add_track(const size_t& track_node_id, const Direction& track_direction, const size_t& seg_id, const size_t& seg_length, const size_t& is_start, const size_t& is_end) { + track_node_ids_.push_back(track_node_id); + track_direction_.push_back(track_direction); + seg_ids_.push_back(seg_id); + seg_length_.push_back(seg_length); + track_start_.push_back(is_start); + track_end_.push_back(is_end); } /* Update the node_id of a given track */ void ChanNodeDetails::set_track_node_id(const size_t& track_index, const size_t& track_node_id) { - VTR_ASSERT(validate_track_id(track_index)); - track_node_ids_[track_index] = track_node_id; + VTR_ASSERT(validate_track_id(track_index)); + track_node_ids_[track_index] = track_node_id; } /* Update the node_ids from a vector */ void ChanNodeDetails::set_track_node_ids(const std::vector& track_node_ids) { - /* the size of vector should match chan_width */ - VTR_ASSERT ( get_chan_width() == track_node_ids.size() ); - for (size_t inode = 0; inode < track_node_ids.size(); ++inode) { - track_node_ids_[inode] = track_node_ids[inode]; - } + /* the size of vector should match chan_width */ + VTR_ASSERT(get_chan_width() == track_node_ids.size()); + for (size_t inode = 0; inode < track_node_ids.size(); ++inode) { + track_node_ids_[inode] = track_node_ids[inode]; + } } /* Set tracks with a given direction to start */ void ChanNodeDetails::set_tracks_start(const Direction& track_direction) { - for (size_t inode = 0; inode < get_chan_width(); ++inode) { - /* Bypass non-match tracks */ - if (track_direction != get_track_direction(inode)) { - continue; /* Pass condition*/ + for (size_t inode = 0; inode < get_chan_width(); ++inode) { + /* Bypass non-match tracks */ + if (track_direction != get_track_direction(inode)) { + continue; /* Pass condition*/ + } + track_start_[inode] = true; } - track_start_[inode] = true; - } } /* Set tracks with a given direction to end */ void ChanNodeDetails::set_tracks_end(const Direction& track_direction) { - for (size_t inode = 0; inode < get_chan_width(); ++inode) { - /* Bypass non-match tracks */ - if (track_direction != get_track_direction(inode)) { - continue; /* Pass condition*/ + for (size_t inode = 0; inode < get_chan_width(); ++inode) { + /* Bypass non-match tracks */ + if (track_direction != get_track_direction(inode)) { + continue; /* Pass condition*/ + } + track_end_[inode] = true; } - track_end_[inode] = true; - } } /* rotate the track_node_id by an offset */ void ChanNodeDetails::rotate_track_node_id(const size_t& offset, const Direction& track_direction, const bool& counter_rotate) { - /* Direct return if offset = 0*/ - if (0 == offset) { - return; - } - - /* Rotate the node_ids by groups + /* Direct return if offset = 0*/ + if (0 == offset) { + return; + } + + /* Rotate the node_ids by groups * A group begins from a track_start and ends before another track_start */ - VTR_ASSERT(validate_chan_width()); - for (size_t itrack = 0; itrack < get_chan_width(); ++itrack) { - /* Bypass non-start segment */ - if (false == is_track_start(itrack) ) { - continue; - } - /* Bypass segments do not match track_direction */ - if (track_direction != get_track_direction(itrack) ) { - continue; - } - /* Find the group nodes */ - std::vector track_group = get_seg_group(itrack); - /* Build a vector of the node ids of the tracks */ - std::vector track_group_node_id = get_seg_group_node_id(track_group); - /* adapt offset to the range of track_group_node_id */ - size_t actual_offset = offset % track_group_node_id.size(); - /* Rotate or Counter rotate */ - if (true == counter_rotate) { - std::rotate(track_group_node_id.rbegin(), track_group_node_id.rbegin() + actual_offset, track_group_node_id.rend()); - } else { - std::rotate(track_group_node_id.begin(), track_group_node_id.begin() + actual_offset, track_group_node_id.end()); + VTR_ASSERT(validate_chan_width()); + for (size_t itrack = 0; itrack < get_chan_width(); ++itrack) { + /* Bypass non-start segment */ + if (false == is_track_start(itrack)) { + continue; + } + /* Bypass segments do not match track_direction */ + if (track_direction != get_track_direction(itrack)) { + continue; + } + /* Find the group nodes */ + std::vector track_group = get_seg_group(itrack); + /* Build a vector of the node ids of the tracks */ + std::vector track_group_node_id = get_seg_group_node_id(track_group); + /* adapt offset to the range of track_group_node_id */ + size_t actual_offset = offset % track_group_node_id.size(); + /* Rotate or Counter rotate */ + if (true == counter_rotate) { + std::rotate(track_group_node_id.rbegin(), track_group_node_id.rbegin() + actual_offset, track_group_node_id.rend()); + } else { + std::rotate(track_group_node_id.begin(), track_group_node_id.begin() + actual_offset, track_group_node_id.end()); + } + /* Update the node_ids */ + for (size_t inode = 0; inode < track_group.size(); ++inode) { + track_node_ids_[track_group[inode]] = track_group_node_id[inode]; + } } - /* Update the node_ids */ - for (size_t inode = 0; inode < track_group.size(); ++inode) { - track_node_ids_[track_group[inode]] = track_group_node_id[inode]; - } - } - return; + return; } void ChanNodeDetails::clear() { - track_node_ids_.clear(); - track_direction_.clear(); - seg_ids_.clear(); - seg_length_.clear(); - track_start_.clear(); - track_end_.clear(); + track_node_ids_.clear(); + track_direction_.clear(); + seg_ids_.clear(); + seg_length_.clear(); + track_start_.clear(); + track_end_.clear(); } /************************************************************************ * Validators ***********************************************************************/ bool ChanNodeDetails::validate_chan_width() const { - size_t chan_width = track_node_ids_.size(); - if ( (chan_width == track_direction_.size()) - &&(chan_width == seg_ids_.size()) - &&(chan_width == seg_length_.size()) - &&(chan_width == track_start_.size()) - &&(chan_width == track_end_.size()) ) { - return true; - } - return false; + size_t chan_width = track_node_ids_.size(); + if ((chan_width == track_direction_.size()) + && (chan_width == seg_ids_.size()) + && (chan_width == seg_length_.size()) + && (chan_width == track_start_.size()) + && (chan_width == track_end_.size())) { + return true; + } + return false; } bool ChanNodeDetails::validate_track_id(const size_t& track_id) const { - if ( (track_id < track_node_ids_.size()) - && (track_id < track_direction_.size()) - && (track_id < seg_ids_.size()) - && (track_id < seg_length_.size()) - && (track_id < track_start_.size()) - && (track_id < track_end_.size()) ) { - return true; - } - return false; + if ((track_id < track_node_ids_.size()) + && (track_id < track_direction_.size()) + && (track_id < seg_ids_.size()) + && (track_id < seg_length_.size()) + && (track_id < track_start_.size()) + && (track_id < track_end_.size())) { + return true; + } + return false; } } /* end namespace openfpga */ diff --git a/vpr/src/tileable_rr_graph/openfpga_rr_graph_utils.cpp b/vpr/src/tileable_rr_graph/openfpga_rr_graph_utils.cpp index 60a8698f8e7..231781a69b2 100644 --- a/vpr/src/tileable_rr_graph/openfpga_rr_graph_utils.cpp +++ b/vpr/src/tileable_rr_graph/openfpga_rr_graph_utils.cpp @@ -24,20 +24,20 @@ namespace openfpga { ***********************************************************************/ vtr::Point get_track_rr_node_start_coordinate(const RRGraph& rr_graph, const RRNodeId& track_rr_node) { - /* Make sure we have CHANX or CHANY */ - VTR_ASSERT( (CHANX == rr_graph.node_type(track_rr_node)) - || (CHANY == rr_graph.node_type(track_rr_node)) ); - - vtr::Point start_coordinator; - - if (Direction::INC == rr_graph.node_direction(track_rr_node)) { - start_coordinator.set(rr_graph.node_xlow(track_rr_node), rr_graph.node_ylow(track_rr_node)); - } else { - VTR_ASSERT(Direction::DEC == rr_graph.node_direction(track_rr_node)); - start_coordinator.set(rr_graph.node_xhigh(track_rr_node), rr_graph.node_yhigh(track_rr_node)); - } - - return start_coordinator; + /* Make sure we have CHANX or CHANY */ + VTR_ASSERT((CHANX == rr_graph.node_type(track_rr_node)) + || (CHANY == rr_graph.node_type(track_rr_node))); + + vtr::Point start_coordinator; + + if (Direction::INC == rr_graph.node_direction(track_rr_node)) { + start_coordinator.set(rr_graph.node_xlow(track_rr_node), rr_graph.node_ylow(track_rr_node)); + } else { + VTR_ASSERT(Direction::DEC == rr_graph.node_direction(track_rr_node)); + start_coordinator.set(rr_graph.node_xhigh(track_rr_node), rr_graph.node_yhigh(track_rr_node)); + } + + return start_coordinator; } /************************************************************************ @@ -50,20 +50,20 @@ vtr::Point get_track_rr_node_start_coordinate(const RRGraph& rr_graph, ***********************************************************************/ vtr::Point get_track_rr_node_end_coordinate(const RRGraph& rr_graph, const RRNodeId& track_rr_node) { - /* Make sure we have CHANX or CHANY */ - VTR_ASSERT( (CHANX == rr_graph.node_type(track_rr_node)) - || (CHANY == rr_graph.node_type(track_rr_node)) ); - - vtr::Point end_coordinator; - - if (Direction::INC == rr_graph.node_direction(track_rr_node)) { - end_coordinator.set(rr_graph.node_xhigh(track_rr_node), rr_graph.node_yhigh(track_rr_node)); - } else { - VTR_ASSERT(Direction::DEC == rr_graph.node_direction(track_rr_node)); - end_coordinator.set(rr_graph.node_xlow(track_rr_node), rr_graph.node_ylow(track_rr_node)); - } - - return end_coordinator; + /* Make sure we have CHANX or CHANY */ + VTR_ASSERT((CHANX == rr_graph.node_type(track_rr_node)) + || (CHANY == rr_graph.node_type(track_rr_node))); + + vtr::Point end_coordinator; + + if (Direction::INC == rr_graph.node_direction(track_rr_node)) { + end_coordinator.set(rr_graph.node_xhigh(track_rr_node), rr_graph.node_yhigh(track_rr_node)); + } else { + VTR_ASSERT(Direction::DEC == rr_graph.node_direction(track_rr_node)); + end_coordinator.set(rr_graph.node_xlow(track_rr_node), rr_graph.node_ylow(track_rr_node)); + } + + return end_coordinator; } /************************************************************************ @@ -72,14 +72,14 @@ vtr::Point get_track_rr_node_end_coordinate(const RRGraph& rr_graph, ***********************************************************************/ std::vector get_rr_graph_driver_switches(const RRGraph& rr_graph, const RRNodeId& node) { - std::vector driver_switches; - for (const RREdgeId& edge : rr_graph.node_in_edges(node)) { - if (driver_switches.end() == std::find(driver_switches.begin(), driver_switches.end(), rr_graph.edge_switch(edge))) { - driver_switches.push_back(rr_graph.edge_switch(edge)); + std::vector driver_switches; + for (const RREdgeId& edge : rr_graph.node_in_edges(node)) { + if (driver_switches.end() == std::find(driver_switches.begin(), driver_switches.end(), rr_graph.edge_switch(edge))) { + driver_switches.push_back(rr_graph.edge_switch(edge)); + } } - } - return driver_switches; + return driver_switches; } /************************************************************************ @@ -87,12 +87,12 @@ std::vector get_rr_graph_driver_switches(const RRGraph& rr_graph, ***********************************************************************/ std::vector get_rr_graph_driver_nodes(const RRGraph& rr_graph, const RRNodeId& node) { - std::vector driver_nodes; - for (const RREdgeId& edge : rr_graph.node_in_edges(node)) { - driver_nodes.push_back(rr_graph.edge_src_node(edge)); - } + std::vector driver_nodes; + for (const RREdgeId& edge : rr_graph.node_in_edges(node)) { + driver_nodes.push_back(rr_graph.edge_src_node(edge)); + } - return driver_nodes; + return driver_nodes; } /************************************************************************ @@ -100,16 +100,16 @@ std::vector get_rr_graph_driver_nodes(const RRGraph& rr_graph, ***********************************************************************/ std::vector get_rr_graph_configurable_driver_nodes(const RRGraph& rr_graph, const RRNodeId& node) { - std::vector driver_nodes; - for (const RREdgeId& edge : rr_graph.node_in_edges(node)) { - /* Bypass non-configurable edges */ - if (false == rr_graph.edge_is_configurable(edge)) { - continue; - } - driver_nodes.push_back(rr_graph.edge_src_node(edge)); - } - - return driver_nodes; + std::vector driver_nodes; + for (const RREdgeId& edge : rr_graph.node_in_edges(node)) { + /* Bypass non-configurable edges */ + if (false == rr_graph.edge_is_configurable(edge)) { + continue; + } + driver_nodes.push_back(rr_graph.edge_src_node(edge)); + } + + return driver_nodes; } /************************************************************************ @@ -117,16 +117,16 @@ std::vector get_rr_graph_configurable_driver_nodes(const RRGraph& rr_g ***********************************************************************/ std::vector get_rr_graph_non_configurable_driver_nodes(const RRGraph& rr_graph, const RRNodeId& node) { - std::vector driver_nodes; - for (const RREdgeId& edge : rr_graph.node_in_edges(node)) { - /* Bypass configurable edges */ - if (true == rr_graph.edge_is_configurable(edge)) { - continue; - } - driver_nodes.push_back(rr_graph.edge_src_node(edge)); - } - - return driver_nodes; + std::vector driver_nodes; + for (const RREdgeId& edge : rr_graph.node_in_edges(node)) { + /* Bypass configurable edges */ + if (true == rr_graph.edge_is_configurable(edge)) { + continue; + } + driver_nodes.push_back(rr_graph.edge_src_node(edge)); + } + + return driver_nodes; } /************************************************************************ @@ -137,22 +137,22 @@ std::vector get_rr_graph_non_configurable_driver_nodes(const RRGraph& ***********************************************************************/ bool is_opin_direct_connected_ipin(const RRGraph& rr_graph, const RRNodeId& node) { - /* We only accept OPIN */ - VTR_ASSERT(OPIN == rr_graph.node_type(node)); - - if (1 != rr_graph.node_out_edges(node).size()) { - return false; - } - - VTR_ASSERT(1 == rr_graph.node_out_edges(node).size()); - for (const RREdgeId& edge: rr_graph.node_out_edges(node)) { - const RRNodeId& sink_node = rr_graph.edge_sink_node(edge); - if (IPIN != rr_graph.node_type(sink_node)) { - return false; + /* We only accept OPIN */ + VTR_ASSERT(OPIN == rr_graph.node_type(node)); + + if (1 != rr_graph.node_out_edges(node).size()) { + return false; + } + + VTR_ASSERT(1 == rr_graph.node_out_edges(node).size()); + for (const RREdgeId& edge : rr_graph.node_out_edges(node)) { + const RRNodeId& sink_node = rr_graph.edge_sink_node(edge); + if (IPIN != rr_graph.node_type(sink_node)) { + return false; + } } - } - - return true; + + return true; } /************************************************************************ @@ -163,22 +163,22 @@ bool is_opin_direct_connected_ipin(const RRGraph& rr_graph, ***********************************************************************/ bool is_ipin_direct_connected_opin(const RRGraph& rr_graph, const RRNodeId& node) { - /* We only accept IPIN */ - VTR_ASSERT(IPIN == rr_graph.node_type(node)); - - if (1 != rr_graph.node_in_edges(node).size()) { - return false; - } - - VTR_ASSERT(1 == rr_graph.node_in_edges(node).size()); - for (const RREdgeId& edge: rr_graph.node_in_edges(node)) { - const RRNodeId& src_node = rr_graph.edge_src_node(edge); - if (OPIN != rr_graph.node_type(src_node)) { - return false; + /* We only accept IPIN */ + VTR_ASSERT(IPIN == rr_graph.node_type(node)); + + if (1 != rr_graph.node_in_edges(node).size()) { + return false; } - } - - return true; + + VTR_ASSERT(1 == rr_graph.node_in_edges(node).size()); + for (const RREdgeId& edge : rr_graph.node_in_edges(node)) { + const RRNodeId& src_node = rr_graph.edge_src_node(edge); + if (OPIN != rr_graph.node_type(src_node)) { + return false; + } + } + + return true; } } /* end namespace openfpga */ diff --git a/vpr/src/tileable_rr_graph/rr_chan.cpp b/vpr/src/tileable_rr_graph/rr_chan.cpp index 0aea3cee48a..556f1893a74 100644 --- a/vpr/src/tileable_rr_graph/rr_chan.cpp +++ b/vpr/src/tileable_rr_graph/rr_chan.cpp @@ -13,180 +13,180 @@ namespace openfpga { ***********************************************************************/ /* default constructor */ RRChan::RRChan() { - type_ = NUM_RR_TYPES; - nodes_.resize(0); - node_segments_.resize(0); + type_ = NUM_RR_TYPES; + nodes_.resize(0); + node_segments_.resize(0); } /************************************************************************ * Accessors ***********************************************************************/ t_rr_type RRChan::get_type() const { - return type_; + return type_; } /* get the number of tracks in this channel */ -size_t RRChan::get_chan_width() const { - return nodes_.size(); +size_t RRChan::get_chan_width() const { + return nodes_.size(); } /* get the track_id of a node */ int RRChan::get_node_track_id(const RRNodeId& node) const { - /* if the given node is NULL, we return an invalid id */ - if (RRNodeId::INVALID() == node) { - return -1; - } - /* check each member and return if we find a match in content */ - std::vector::const_iterator it = std::find(nodes_.begin(), nodes_.end(), node); - if (nodes_.end() == it) { - return -1; - } - return it - nodes_.begin(); + /* if the given node is NULL, we return an invalid id */ + if (RRNodeId::INVALID() == node) { + return -1; + } + /* check each member and return if we find a match in content */ + std::vector::const_iterator it = std::find(nodes_.begin(), nodes_.end(), node); + if (nodes_.end() == it) { + return -1; + } + return it - nodes_.begin(); } /* get the rr_node with the track_id */ RRNodeId RRChan::get_node(const size_t& track_num) const { - if ( false == valid_node_id(track_num) ) { - return RRNodeId::INVALID(); - } - return nodes_[track_num]; -} + if (false == valid_node_id(track_num)) { + return RRNodeId::INVALID(); + } + return nodes_[track_num]; +} /* get the segment id of a node */ RRSegmentId RRChan::get_node_segment(const RRNodeId& node) const { - int node_id = get_node_track_id(node); - if ( false == valid_node_id(node_id)) { - return RRSegmentId::INVALID(); - } - return get_node_segment(node_id); + int node_id = get_node_track_id(node); + if (false == valid_node_id(node_id)) { + return RRSegmentId::INVALID(); + } + return get_node_segment(node_id); } /* get the segment id of a node */ RRSegmentId RRChan::get_node_segment(const size_t& track_num) const { - if ( false == valid_node_id(track_num)) { - return RRSegmentId::INVALID(); - } - return node_segments_[track_num]; + if (false == valid_node_id(track_num)) { + return RRSegmentId::INVALID(); + } + return node_segments_[track_num]; } /* evaluate if two RRChan is mirror to each other */ bool RRChan::is_mirror(const RRGraph& rr_graph, const RRChan& cand) const { - /* If any following element does not match, it is not mirror */ - /* 1. type */ - if (this->get_type() != cand.get_type()) { - return false; - } - /* 2. track_width */ - if (this->get_chan_width() != cand.get_chan_width()) { - return false; - } - /* 3. for each node */ - for (size_t inode = 0; inode < this->get_chan_width(); ++inode) { - /* 3.1 check node type */ - if (rr_graph.node_type(this->get_node(inode)) != rr_graph.node_type(cand.get_node(inode))) { - return false; + /* If any following element does not match, it is not mirror */ + /* 1. type */ + if (this->get_type() != cand.get_type()) { + return false; } - /* 3.2 check node directionality */ - if (rr_graph.node_direction(this->get_node(inode)) != rr_graph.node_direction(cand.get_node(inode))) { - return false; + /* 2. track_width */ + if (this->get_chan_width() != cand.get_chan_width()) { + return false; } - /* 3.3 check node segment */ - if (this->get_node_segment(inode) != cand.get_node_segment(inode)) { - return false; + /* 3. for each node */ + for (size_t inode = 0; inode < this->get_chan_width(); ++inode) { + /* 3.1 check node type */ + if (rr_graph.node_type(this->get_node(inode)) != rr_graph.node_type(cand.get_node(inode))) { + return false; + } + /* 3.2 check node directionality */ + if (rr_graph.node_direction(this->get_node(inode)) != rr_graph.node_direction(cand.get_node(inode))) { + return false; + } + /* 3.3 check node segment */ + if (this->get_node_segment(inode) != cand.get_node_segment(inode)) { + return false; + } } - } - - return true; + + return true; } /* Get a list of segments used in this routing channel */ -std::vector RRChan::get_segment_ids() const { - std::vector seg_list; - - /* make sure a clean start */ - seg_list.clear(); - - /* Traverse node_segments */ - for (size_t inode = 0; inode < get_chan_width(); ++inode) { - std::vector::iterator it; - /* Try to find the node_segment id in the list */ - it = find(seg_list.begin(), seg_list.end(), node_segments_[inode]); - if ( it == seg_list.end() ) { - /* Not found, add it to the list */ - seg_list.push_back(node_segments_[inode]); +std::vector RRChan::get_segment_ids() const { + std::vector seg_list; + + /* make sure a clean start */ + seg_list.clear(); + + /* Traverse node_segments */ + for (size_t inode = 0; inode < get_chan_width(); ++inode) { + std::vector::iterator it; + /* Try to find the node_segment id in the list */ + it = find(seg_list.begin(), seg_list.end(), node_segments_[inode]); + if (it == seg_list.end()) { + /* Not found, add it to the list */ + seg_list.push_back(node_segments_[inode]); + } } - } - return seg_list; + return seg_list; } /* Get a list of nodes whose segment_id is specified */ std::vector RRChan::get_node_ids_by_segment_ids(const RRSegmentId& seg_id) const { - std::vector node_list; + std::vector node_list; - /* make sure a clean start */ - node_list.clear(); + /* make sure a clean start */ + node_list.clear(); - /* Traverse node_segments */ - for (size_t inode = 0; inode < get_chan_width(); ++inode) { - /* Try to find the node_segment id in the list */ - if ( seg_id == node_segments_[inode] ) { - node_list.push_back(inode); + /* Traverse node_segments */ + for (size_t inode = 0; inode < get_chan_width(); ++inode) { + /* Try to find the node_segment id in the list */ + if (seg_id == node_segments_[inode]) { + node_list.push_back(inode); + } } - } - return node_list; -} + return node_list; +} /************************************************************************ * Mutators ***********************************************************************/ void RRChan::set(const RRChan& rr_chan) { - /* Ensure a clean start */ - this->clear(); - /* Assign type of this routing channel */ - this->type_ = rr_chan.get_type(); - /* Copy node and node_segments */ - this->nodes_.resize(rr_chan.get_chan_width()); - this->node_segments_.resize(rr_chan.get_chan_width()); - for (size_t inode = 0; inode < rr_chan.get_chan_width(); ++inode) { - this->nodes_[inode] = rr_chan.get_node(inode); - this->node_segments_[inode] = rr_chan.get_node_segment(inode); - } - return; + /* Ensure a clean start */ + this->clear(); + /* Assign type of this routing channel */ + this->type_ = rr_chan.get_type(); + /* Copy node and node_segments */ + this->nodes_.resize(rr_chan.get_chan_width()); + this->node_segments_.resize(rr_chan.get_chan_width()); + for (size_t inode = 0; inode < rr_chan.get_chan_width(); ++inode) { + this->nodes_[inode] = rr_chan.get_node(inode); + this->node_segments_[inode] = rr_chan.get_node_segment(inode); + } + return; } /* modify type */ void RRChan::set_type(const t_rr_type& type) { - VTR_ASSERT(valid_type(type)); - type_ = type; -} + VTR_ASSERT(valid_type(type)); + type_ = type; +} /* Reserve node list */ void RRChan::reserve_node(const size_t& node_size) { - nodes_.reserve(node_size); /* reserve to the maximum */ - node_segments_.reserve(node_size); /* reserve to the maximum */ + nodes_.reserve(node_size); /* reserve to the maximum */ + node_segments_.reserve(node_size); /* reserve to the maximum */ } /* add a node to the array */ void RRChan::add_node(const RRGraph& rr_graph, const RRNodeId& node, const RRSegmentId& node_segment) { - /* fill the dedicated element in the vector */ - nodes_.push_back(node); - node_segments_.push_back(node_segment); - - if (NUM_RR_TYPES == type_) { - type_ = rr_graph.node_type(node); - } else { - VTR_ASSERT(type_ == rr_graph.node_type(node)); - } + /* fill the dedicated element in the vector */ + nodes_.push_back(node); + node_segments_.push_back(node_segment); + + if (NUM_RR_TYPES == type_) { + type_ = rr_graph.node_type(node); + } else { + VTR_ASSERT(type_ == rr_graph.node_type(node)); + } - VTR_ASSERT(valid_node_type(rr_graph, node)); + VTR_ASSERT(valid_node_type(rr_graph, node)); } /* Clear content */ void RRChan::clear() { - nodes_.clear(); - node_segments_.clear(); + nodes_.clear(); + node_segments_.clear(); } /************************************************************************ @@ -194,32 +194,32 @@ void RRChan::clear() { ***********************************************************************/ /* for type, only valid type is CHANX and CHANY */ bool RRChan::valid_type(const t_rr_type& type) const { - if ((CHANX == type) || (CHANY == type)) { - return true; - } - return false; -} + if ((CHANX == type) || (CHANY == type)) { + return true; + } + return false; +} /* Check each node, see if the node type is consistent with the type */ bool RRChan::valid_node_type(const RRGraph& rr_graph, const RRNodeId& node) const { - valid_type(rr_graph.node_type(node)); - if (NUM_RR_TYPES == type_) { + valid_type(rr_graph.node_type(node)); + if (NUM_RR_TYPES == type_) { + return true; + } + valid_type(type_); + if (type_ != rr_graph.node_type(node)) { + return false; + } return true; - } - valid_type(type_); - if (type_ != rr_graph.node_type(node)) { - return false; - } - return true; } /* check if the node id is valid */ bool RRChan::valid_node_id(const size_t& node_id) const { - if (node_id < nodes_.size()) { - return true; - } + if (node_id < nodes_.size()) { + return true; + } - return false; + return false; } } /* End namespace openfpga*/ diff --git a/vpr/src/tileable_rr_graph/rr_graph_builder_utils.cpp b/vpr/src/tileable_rr_graph/rr_graph_builder_utils.cpp index 3aaba3e1ac2..c3653ac3b73 100644 --- a/vpr/src/tileable_rr_graph/rr_graph_builder_utils.cpp +++ b/vpr/src/tileable_rr_graph/rr_graph_builder_utils.cpp @@ -20,14 +20,14 @@ namespace openfpga { * uni-directional routing architecture ***********************************************************************/ size_t find_unidir_routing_channel_width(const size_t& chan_width) { - size_t actual_chan_width = chan_width; - /* Correct the chan_width: it should be an even number */ - if (0 != actual_chan_width % 2) { - actual_chan_width++; /* increment it to be even */ - } - VTR_ASSERT(0 == actual_chan_width % 2); - - return actual_chan_width; + size_t actual_chan_width = chan_width; + /* Correct the chan_width: it should be an even number */ + if (0 != actual_chan_width % 2) { + actual_chan_width++; /* increment it to be even */ + } + VTR_ASSERT(0 == actual_chan_width % 2); + + return actual_chan_width; } /************************************************************************ @@ -35,46 +35,46 @@ size_t find_unidir_routing_channel_width(const size_t& chan_width) { ***********************************************************************/ int get_grid_pin_class_index(const t_grid_tile& cur_grid, const int pin_index) { - /* check */ - VTR_ASSERT(pin_index < cur_grid.type->num_pins); - return cur_grid.type->pin_class[pin_index]; + /* check */ + VTR_ASSERT(pin_index < cur_grid.type->num_pins); + return cur_grid.type->pin_class[pin_index]; } /* Deteremine the side of a io grid */ -e_side determine_io_grid_pin_side(const vtr::Point& device_size, +e_side determine_io_grid_pin_side(const vtr::Point& device_size, const vtr::Point& grid_coordinate) { - /* TOP side IO of FPGA */ - if (device_size.y() == grid_coordinate.y()) { - return BOTTOM; /* Such I/O has only Bottom side pins */ - } else if (device_size.x() == grid_coordinate.x()) { /* RIGHT side IO of FPGA */ - return LEFT; /* Such I/O has only Left side pins */ - } else if (0 == grid_coordinate.y()) { /* BOTTOM side IO of FPGA */ - return TOP; /* Such I/O has only Top side pins */ - } else if (0 == grid_coordinate.x()) { /* LEFT side IO of FPGA */ - return RIGHT; /* Such I/O has only Right side pins */ - } else if ((grid_coordinate.x() < device_size.x()) && (grid_coordinate.y() < device_size.y())) { - /* I/O grid in the center grid */ - return NUM_SIDES; - } - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid coordinate (%lu, %lu) for I/O Grid whose size is (%lu, %lu)!\n", - grid_coordinate.x(), grid_coordinate.y(), - device_size.x(), device_size.y()); - exit(1); + /* TOP side IO of FPGA */ + if (device_size.y() == grid_coordinate.y()) { + return BOTTOM; /* Such I/O has only Bottom side pins */ + } else if (device_size.x() == grid_coordinate.x()) { /* RIGHT side IO of FPGA */ + return LEFT; /* Such I/O has only Left side pins */ + } else if (0 == grid_coordinate.y()) { /* BOTTOM side IO of FPGA */ + return TOP; /* Such I/O has only Top side pins */ + } else if (0 == grid_coordinate.x()) { /* LEFT side IO of FPGA */ + return RIGHT; /* Such I/O has only Right side pins */ + } else if ((grid_coordinate.x() < device_size.x()) && (grid_coordinate.y() < device_size.y())) { + /* I/O grid in the center grid */ + return NUM_SIDES; + } + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid coordinate (%lu, %lu) for I/O Grid whose size is (%lu, %lu)!\n", + grid_coordinate.x(), grid_coordinate.y(), + device_size.x(), device_size.y()); + exit(1); } /* Deteremine the side of a pin of a grid */ -std::vector find_grid_pin_sides(const t_grid_tile& grid, +std::vector find_grid_pin_sides(const t_grid_tile& grid, const size_t& pin_id) { - std::vector pin_sides; + std::vector pin_sides; - for (const e_side& side : {TOP, RIGHT, BOTTOM, LEFT} ) { - if (true == grid.type->pinloc[grid.width_offset][grid.height_offset][size_t(side)][pin_id]) { - pin_sides.push_back(side); + for (const e_side& side : {TOP, RIGHT, BOTTOM, LEFT}) { + if (true == grid.type->pinloc[grid.width_offset][grid.height_offset][size_t(side)][pin_id]) { + pin_sides.push_back(side); + } } - } - return pin_sides; + return pin_sides; } /************************************************************************ @@ -82,23 +82,23 @@ std::vector find_grid_pin_sides(const t_grid_tile& grid, * For IO_TYPE, only one side will be used, we consider one side of pins * For others, we consider all the sides ***********************************************************************/ -std::vector get_grid_side_pins(const t_grid_tile& cur_grid, - const e_pin_type& pin_type, - const e_side& pin_side, +std::vector get_grid_side_pins(const t_grid_tile& cur_grid, + const e_pin_type& pin_type, + const e_side& pin_side, const int& pin_width, const int& pin_height) { - std::vector pin_list; - /* Make sure a clear start */ - pin_list.clear(); - - for (int ipin = 0; ipin < cur_grid.type->num_pins; ++ipin) { - int class_id = cur_grid.type->pin_class[ipin]; - if ( (1 == cur_grid.type->pinloc[pin_width][pin_height][pin_side][ipin]) - && (pin_type == cur_grid.type->class_inf[class_id].type) ) { - pin_list.push_back(ipin); + std::vector pin_list; + /* Make sure a clear start */ + pin_list.clear(); + + for (int ipin = 0; ipin < cur_grid.type->num_pins; ++ipin) { + int class_id = cur_grid.type->pin_class[ipin]; + if ((1 == cur_grid.type->pinloc[pin_width][pin_height][pin_side][ipin]) + && (pin_type == cur_grid.type->class_inf[class_id].type)) { + pin_list.push_back(ipin); + } } - } - return pin_list; + return pin_list; } /************************************************************************ @@ -106,28 +106,28 @@ std::vector get_grid_side_pins(const t_grid_tile& cur_grid, * For IO_TYPE, only one side will be used, we consider one side of pins * For others, we consider all the sides ***********************************************************************/ -size_t get_grid_num_pins(const t_grid_tile& cur_grid, - const e_pin_type& pin_type, +size_t get_grid_num_pins(const t_grid_tile& cur_grid, + const e_pin_type& pin_type, const e_side& io_side) { - size_t num_pins = 0; - - /* For IO_TYPE sides */ - for (const e_side& side : {TOP, RIGHT, BOTTOM, LEFT}) { - /* skip unwanted sides */ - if ( (true == is_io_type(cur_grid.type)) - && (side != io_side) && (NUM_SIDES != io_side)) { - continue; + size_t num_pins = 0; + + /* For IO_TYPE sides */ + for (const e_side& side : {TOP, RIGHT, BOTTOM, LEFT}) { + /* skip unwanted sides */ + if ((true == is_io_type(cur_grid.type)) + && (side != io_side) && (NUM_SIDES != io_side)) { + continue; + } + /* Get pin list */ + for (int width = 0; width < cur_grid.type->width; ++width) { + for (int height = 0; height < cur_grid.type->height; ++height) { + std::vector pin_list = get_grid_side_pins(cur_grid, pin_type, side, width, height); + num_pins += pin_list.size(); + } + } } - /* Get pin list */ - for (int width = 0; width < cur_grid.type->width; ++width) { - for (int height = 0; height < cur_grid.type->height; ++height) { - std::vector pin_list = get_grid_side_pins(cur_grid, pin_type, side, width, height); - num_pins += pin_list.size(); - } - } - } - - return num_pins; + + return num_pins; } /************************************************************************ @@ -135,19 +135,19 @@ size_t get_grid_num_pins(const t_grid_tile& cur_grid, * For IO_TYPE, only one side will be used, we consider one side of pins * For others, we consider all the sides ***********************************************************************/ -size_t get_grid_num_classes(const t_grid_tile& cur_grid, +size_t get_grid_num_classes(const t_grid_tile& cur_grid, const e_pin_type& pin_type) { - size_t num_classes = 0; - - for (int iclass = 0; iclass < cur_grid.type->num_class; ++iclass) { - /* Bypass unmatched pin_type */ - if (pin_type != cur_grid.type->class_inf[iclass].type) { - continue; + size_t num_classes = 0; + + for (int iclass = 0; iclass < cur_grid.type->num_class; ++iclass) { + /* Bypass unmatched pin_type */ + if (pin_type != cur_grid.type->class_inf[iclass].type) { + continue; + } + num_classes++; } - num_classes++; - } - return num_classes; + return num_classes; } /************************************************************************ @@ -178,20 +178,19 @@ size_t get_grid_num_classes(const t_grid_tile& cur_grid, bool is_chanx_exist(const DeviceGrid& grids, const vtr::Point& chanx_coord, const bool& through_channel) { + if ((1 > chanx_coord.x()) || (chanx_coord.x() > grids.width() - 2)) { + return false; + } - if ((1 > chanx_coord.x()) || (chanx_coord.x() > grids.width() - 2)) { - return false; - } - - if (chanx_coord.y() > grids.height() - 2) { - return false; - } + if (chanx_coord.y() > grids.height() - 2) { + return false; + } - if (true == through_channel) { - return true; - } + if (true == through_channel) { + return true; + } - return (grids[chanx_coord.x()][chanx_coord.y()].height_offset == grids[chanx_coord.x()][chanx_coord.y()].type->height - 1); + return (grids[chanx_coord.x()][chanx_coord.y()].height_offset == grids[chanx_coord.x()][chanx_coord.y()].type->height - 1); } /************************************************************************ @@ -217,20 +216,19 @@ bool is_chanx_exist(const DeviceGrid& grids, bool is_chany_exist(const DeviceGrid& grids, const vtr::Point& chany_coord, const bool& through_channel) { + if (chany_coord.x() > grids.width() - 2) { + return false; + } - if (chany_coord.x() > grids.width() - 2) { - return false; - } - - if ((1 > chany_coord.y()) || (chany_coord.y() > grids.height() - 2)) { - return false; - } + if ((1 > chany_coord.y()) || (chany_coord.y() > grids.height() - 2)) { + return false; + } - if (true == through_channel) { - return true; - } + if (true == through_channel) { + return true; + } - return (grids[chany_coord.x()][chany_coord.y()].width_offset == grids[chany_coord.x()][chany_coord.y()].type->width - 1); + return (grids[chany_coord.x()][chany_coord.y()].width_offset == grids[chany_coord.x()][chany_coord.y()].type->width - 1); } /************************************************************************ @@ -249,23 +247,23 @@ bool is_chany_exist(const DeviceGrid& grids, bool is_chanx_right_to_multi_height_grid(const DeviceGrid& grids, const vtr::Point& chanx_coord, const bool& through_channel) { - VTR_ASSERT(0 < chanx_coord.x()); - if (1 == chanx_coord.x()) { - /* This is already the LEFT side of FPGA fabric, + VTR_ASSERT(0 < chanx_coord.x()); + if (1 == chanx_coord.x()) { + /* This is already the LEFT side of FPGA fabric, * it is the same results as chanx is right to a multi-height grid */ - return true; - } - - if (false == through_channel) { - /* We check the left neighbor of chanx, if it does not exist, the chanx is left to a multi-height grid */ - vtr::Point left_chanx_coord(chanx_coord.x() - 1, chanx_coord.y()); - if (false == is_chanx_exist(grids, left_chanx_coord)) { - return true; + return true; + } + + if (false == through_channel) { + /* We check the left neighbor of chanx, if it does not exist, the chanx is left to a multi-height grid */ + vtr::Point left_chanx_coord(chanx_coord.x() - 1, chanx_coord.y()); + if (false == is_chanx_exist(grids, left_chanx_coord)) { + return true; + } } - } - return false; + return false; } /************************************************************************ @@ -284,24 +282,23 @@ bool is_chanx_right_to_multi_height_grid(const DeviceGrid& grids, bool is_chanx_left_to_multi_height_grid(const DeviceGrid& grids, const vtr::Point& chanx_coord, const bool& through_channel) { - VTR_ASSERT(chanx_coord.x() < grids.width() - 1); - if (grids.width() - 2 == chanx_coord.x()) { - /* This is already the RIGHT side of FPGA fabric, + VTR_ASSERT(chanx_coord.x() < grids.width() - 1); + if (grids.width() - 2 == chanx_coord.x()) { + /* This is already the RIGHT side of FPGA fabric, * it is the same results as chanx is right to a multi-height grid */ - return true; - } - - - if (false == through_channel) { - /* We check the right neighbor of chanx, if it does not exist, the chanx is left to a multi-height grid */ - vtr::Point right_chanx_coord(chanx_coord.x() + 1, chanx_coord.y()); - if (false == is_chanx_exist(grids, right_chanx_coord)) { - return true; + return true; + } + + if (false == through_channel) { + /* We check the right neighbor of chanx, if it does not exist, the chanx is left to a multi-height grid */ + vtr::Point right_chanx_coord(chanx_coord.x() + 1, chanx_coord.y()); + if (false == is_chanx_exist(grids, right_chanx_coord)) { + return true; + } } - } - return false; + return false; } /************************************************************************ @@ -325,23 +322,23 @@ bool is_chanx_left_to_multi_height_grid(const DeviceGrid& grids, bool is_chany_top_to_multi_width_grid(const DeviceGrid& grids, const vtr::Point& chany_coord, const bool& through_channel) { - VTR_ASSERT(0 < chany_coord.y()); - if (1 == chany_coord.y()) { - /* This is already the BOTTOM side of FPGA fabric, + VTR_ASSERT(0 < chany_coord.y()); + if (1 == chany_coord.y()) { + /* This is already the BOTTOM side of FPGA fabric, * it is the same results as chany is at the top of a multi-width grid */ - return true; - } - - if (false == through_channel) { - /* We check the bottom neighbor of chany, if it does not exist, the chany is top to a multi-height grid */ - vtr::Point bottom_chany_coord(chany_coord.x(), chany_coord.y() - 1); - if (false == is_chany_exist(grids, bottom_chany_coord)) { - return true; + return true; + } + + if (false == through_channel) { + /* We check the bottom neighbor of chany, if it does not exist, the chany is top to a multi-height grid */ + vtr::Point bottom_chany_coord(chany_coord.x(), chany_coord.y() - 1); + if (false == is_chany_exist(grids, bottom_chany_coord)) { + return true; + } } - } - return false; + return false; } /************************************************************************ @@ -365,23 +362,23 @@ bool is_chany_top_to_multi_width_grid(const DeviceGrid& grids, bool is_chany_bottom_to_multi_width_grid(const DeviceGrid& grids, const vtr::Point& chany_coord, const bool& through_channel) { - VTR_ASSERT(chany_coord.y() < grids.height() - 1); - if (grids.height() - 2 == chany_coord.y()) { - /* This is already the TOP side of FPGA fabric, + VTR_ASSERT(chany_coord.y() < grids.height() - 1); + if (grids.height() - 2 == chany_coord.y()) { + /* This is already the TOP side of FPGA fabric, * it is the same results as chany is at the bottom of a multi-width grid */ - return true; - } - - if (false == through_channel) { - /* We check the top neighbor of chany, if it does not exist, the chany is left to a multi-height grid */ - vtr::Point top_chany_coord(chany_coord.x(), chany_coord.y() + 1); - if (false == is_chany_exist(grids, top_chany_coord)) { - return true; + return true; } - } - return false; + if (false == through_channel) { + /* We check the top neighbor of chany, if it does not exist, the chany is left to a multi-height grid */ + vtr::Point top_chany_coord(chany_coord.x(), chany_coord.y() + 1); + if (false == is_chany_exist(grids, top_chany_coord)) { + return true; + } + } + + return false; } /************************************************************************ @@ -407,9 +404,9 @@ short get_rr_node_actual_track_id(const RRGraph& rr_graph, const RRNodeId& track_rr_node, const vtr::Point& coord, const vtr::vector>& tileable_rr_graph_node_track_ids) { - vtr::Point low_coord(rr_graph.node_xlow(track_rr_node), rr_graph.node_ylow(track_rr_node)); - size_t offset = (int)abs((int)coord.x() - (int)low_coord.x() + (int)coord.y() - (int)low_coord.y()); - return tileable_rr_graph_node_track_ids[track_rr_node][offset]; + vtr::Point low_coord(rr_graph.node_xlow(track_rr_node), rr_graph.node_ylow(track_rr_node)); + size_t offset = (int)abs((int)coord.x() - (int)low_coord.x() + (int)coord.y() - (int)low_coord.y()); + return tileable_rr_graph_node_track_ids[track_rr_node][offset]; } /************************************************************************ @@ -423,16 +420,16 @@ short get_rr_node_actual_track_id(const RRGraph& rr_graph, short get_track_rr_node_end_track_id(const RRGraph& rr_graph, const RRNodeId& track_rr_node, const vtr::vector>& tileable_rr_graph_node_track_ids) { - /* Make sure we have CHANX or CHANY */ - VTR_ASSERT( (CHANX == rr_graph.node_type(track_rr_node)) - || (CHANY == rr_graph.node_type(track_rr_node)) ); - - if (Direction::INC == rr_graph.node_direction(track_rr_node)) { - return tileable_rr_graph_node_track_ids[track_rr_node].back(); - } - - VTR_ASSERT(Direction::DEC == rr_graph.node_direction(track_rr_node)); - return tileable_rr_graph_node_track_ids[track_rr_node].front(); + /* Make sure we have CHANX or CHANY */ + VTR_ASSERT((CHANX == rr_graph.node_type(track_rr_node)) + || (CHANY == rr_graph.node_type(track_rr_node))); + + if (Direction::INC == rr_graph.node_direction(track_rr_node)) { + return tileable_rr_graph_node_track_ids[track_rr_node].back(); + } + + VTR_ASSERT(Direction::DEC == rr_graph.node_direction(track_rr_node)); + return tileable_rr_graph_node_track_ids[track_rr_node].front(); } /************************************************************************ @@ -441,17 +438,17 @@ short get_track_rr_node_end_track_id(const RRGraph& rr_graph, ************************************************************************/ short find_rr_graph_num_nodes(const RRGraph& rr_graph, const std::vector& node_types) { - short counter = 0; - - for (const RRNodeId& node : rr_graph.nodes()) { - /* Bypass the nodes not in the class */ - if (node_types.end() == std::find(node_types.begin(), node_types.end(), rr_graph.node_type(node))) { - continue; + short counter = 0; + + for (const RRNodeId& node : rr_graph.nodes()) { + /* Bypass the nodes not in the class */ + if (node_types.end() == std::find(node_types.begin(), node_types.end(), rr_graph.node_type(node))) { + continue; + } + counter++; } - counter++; - } - return counter; + return counter; } /************************************************************************ @@ -460,17 +457,17 @@ short find_rr_graph_num_nodes(const RRGraph& rr_graph, ************************************************************************/ short find_rr_graph_max_fan_in(const RRGraph& rr_graph, const std::vector& node_types) { - short max_fan_in = 0; - - for (const RRNodeId& node : rr_graph.nodes()) { - /* Bypass the nodes not in the class */ - if (node_types.end() == std::find(node_types.begin(), node_types.end(), rr_graph.node_type(node))) { - continue; + short max_fan_in = 0; + + for (const RRNodeId& node : rr_graph.nodes()) { + /* Bypass the nodes not in the class */ + if (node_types.end() == std::find(node_types.begin(), node_types.end(), rr_graph.node_type(node))) { + continue; + } + max_fan_in = std::max(rr_graph.node_fan_in(node), max_fan_in); } - max_fan_in = std::max(rr_graph.node_fan_in(node), max_fan_in); - } - return max_fan_in; + return max_fan_in; } /************************************************************************ @@ -479,18 +476,17 @@ short find_rr_graph_max_fan_in(const RRGraph& rr_graph, ************************************************************************/ short find_rr_graph_min_fan_in(const RRGraph& rr_graph, const std::vector& node_types) { - short min_fan_in = 0; - - for (const RRNodeId& node : rr_graph.nodes()) { - /* Bypass the nodes not in the class */ - if (node_types.end() == std::find(node_types.begin(), node_types.end(), rr_graph.node_type(node))) { - continue; + short min_fan_in = 0; + + for (const RRNodeId& node : rr_graph.nodes()) { + /* Bypass the nodes not in the class */ + if (node_types.end() == std::find(node_types.begin(), node_types.end(), rr_graph.node_type(node))) { + continue; + } + min_fan_in = std::min(rr_graph.node_fan_in(node), min_fan_in); } - min_fan_in = std::min(rr_graph.node_fan_in(node), min_fan_in); - } - - return min_fan_in; + return min_fan_in; } /************************************************************************ @@ -499,58 +495,57 @@ short find_rr_graph_min_fan_in(const RRGraph& rr_graph, ************************************************************************/ short find_rr_graph_average_fan_in(const RRGraph& rr_graph, const std::vector& node_types) { - /* Get the maximum SB mux size */ - size_t sum = 0; - size_t counter = 0; - - for (const RRNodeId& node : rr_graph.nodes()) { - /* Bypass the nodes not in the class */ - if (node_types.end() == std::find(node_types.begin(), node_types.end(), rr_graph.node_type(node))) { - continue; + /* Get the maximum SB mux size */ + size_t sum = 0; + size_t counter = 0; + + for (const RRNodeId& node : rr_graph.nodes()) { + /* Bypass the nodes not in the class */ + if (node_types.end() == std::find(node_types.begin(), node_types.end(), rr_graph.node_type(node))) { + continue; + } + + sum += rr_graph.node_fan_in(node); + counter++; } - sum += rr_graph.node_fan_in(node); - counter++; - } - - return sum / counter; + return sum / counter; } /************************************************************************ * Print statistics of multiplexers in a routing resource graph ************************************************************************/ void print_rr_graph_mux_stats(const RRGraph& rr_graph) { - - /* Print MUX size distribution */ - std::vector sb_node_types; - sb_node_types.push_back(CHANX); - sb_node_types.push_back(CHANY); - - /* Print statistics */ - VTR_LOG("------------------------------------------------\n"); - VTR_LOG("Total No. of Switch Block multiplexer size: %d\n", - find_rr_graph_num_nodes(rr_graph, sb_node_types)); - VTR_LOG("Maximum Switch Block multiplexer size: %d\n", - find_rr_graph_max_fan_in(rr_graph, sb_node_types)); - VTR_LOG("Minimum Switch Block multiplexer size: %d\n", - find_rr_graph_min_fan_in(rr_graph, sb_node_types)); - VTR_LOG("Average Switch Block multiplexer size: %lu\n", - find_rr_graph_average_fan_in(rr_graph, sb_node_types)); - VTR_LOG("------------------------------------------------\n"); - - /* Get the maximum CB mux size */ - std::vector cb_node_types(1, IPIN); - - VTR_LOG("------------------------------------------------\n"); - VTR_LOG("Total No. of Connection Block Multiplexer size: %d\n", - find_rr_graph_num_nodes(rr_graph, cb_node_types)); - VTR_LOG("Maximum Connection Block Multiplexer size: %d\n", - find_rr_graph_max_fan_in(rr_graph, cb_node_types)); - VTR_LOG("Minimum Connection Block Multiplexer size: %d\n", - find_rr_graph_min_fan_in(rr_graph, cb_node_types)); - VTR_LOG("Average Connection Block Multiplexer size: %lu\n", - find_rr_graph_average_fan_in(rr_graph, cb_node_types)); - VTR_LOG("------------------------------------------------\n"); + /* Print MUX size distribution */ + std::vector sb_node_types; + sb_node_types.push_back(CHANX); + sb_node_types.push_back(CHANY); + + /* Print statistics */ + VTR_LOG("------------------------------------------------\n"); + VTR_LOG("Total No. of Switch Block multiplexer size: %d\n", + find_rr_graph_num_nodes(rr_graph, sb_node_types)); + VTR_LOG("Maximum Switch Block multiplexer size: %d\n", + find_rr_graph_max_fan_in(rr_graph, sb_node_types)); + VTR_LOG("Minimum Switch Block multiplexer size: %d\n", + find_rr_graph_min_fan_in(rr_graph, sb_node_types)); + VTR_LOG("Average Switch Block multiplexer size: %lu\n", + find_rr_graph_average_fan_in(rr_graph, sb_node_types)); + VTR_LOG("------------------------------------------------\n"); + + /* Get the maximum CB mux size */ + std::vector cb_node_types(1, IPIN); + + VTR_LOG("------------------------------------------------\n"); + VTR_LOG("Total No. of Connection Block Multiplexer size: %d\n", + find_rr_graph_num_nodes(rr_graph, cb_node_types)); + VTR_LOG("Maximum Connection Block Multiplexer size: %d\n", + find_rr_graph_max_fan_in(rr_graph, cb_node_types)); + VTR_LOG("Minimum Connection Block Multiplexer size: %d\n", + find_rr_graph_min_fan_in(rr_graph, cb_node_types)); + VTR_LOG("Average Connection Block Multiplexer size: %lu\n", + find_rr_graph_average_fan_in(rr_graph, cb_node_types)); + VTR_LOG("------------------------------------------------\n"); } } /* end namespace openfpga */ diff --git a/vpr/src/tileable_rr_graph/rr_gsb.cpp b/vpr/src/tileable_rr_graph/rr_gsb.cpp index badaa663bac..68f287e291c 100644 --- a/vpr/src/tileable_rr_graph/rr_gsb.cpp +++ b/vpr/src/tileable_rr_graph/rr_gsb.cpp @@ -18,16 +18,16 @@ namespace openfpga { ***********************************************************************/ /* Constructor for an empty object */ RRGSB::RRGSB() { - /* Set a clean start! */ - coordinate_.set(0, 0); + /* Set a clean start! */ + coordinate_.set(0, 0); - chan_node_.clear(); - chan_node_direction_.clear(); - chan_node_in_edges_.clear(); + chan_node_.clear(); + chan_node_direction_.clear(); + chan_node_in_edges_.clear(); - ipin_node_.clear(); + ipin_node_.clear(); - opin_node_.clear(); + opin_node_.clear(); } /************************************************************************ @@ -35,367 +35,367 @@ RRGSB::RRGSB() { ***********************************************************************/ /* Get the number of sides of this SB */ size_t RRGSB::get_num_sides() const { - VTR_ASSERT (validate_num_sides()); - return chan_node_direction_.size(); + VTR_ASSERT(validate_num_sides()); + return chan_node_direction_.size(); } /* Get the number of routing tracks on a side */ size_t RRGSB::get_chan_width(const e_side& side) const { - SideManager side_manager(side); - VTR_ASSERT(side_manager.validate()); - return chan_node_[side_manager.to_size_t()].get_chan_width(); + SideManager side_manager(side); + VTR_ASSERT(side_manager.validate()); + return chan_node_[side_manager.to_size_t()].get_chan_width(); } /* Get the number of routing tracks on a side */ t_rr_type RRGSB::get_chan_type(const e_side& side) const { - SideManager side_manager(side); - VTR_ASSERT(side_manager.validate()); - return chan_node_[side_manager.to_size_t()].get_type(); + SideManager side_manager(side); + VTR_ASSERT(side_manager.validate()); + return chan_node_[side_manager.to_size_t()].get_type(); } /* Get the maximum number of routing tracks on all sides */ size_t RRGSB::get_max_chan_width() const { - size_t max_chan_width = 0; - for (size_t side = 0; side < get_num_sides(); ++side) { - SideManager side_manager(side); - max_chan_width = std::max(max_chan_width, get_chan_width(side_manager.get_side())); - } - return max_chan_width; -} + size_t max_chan_width = 0; + for (size_t side = 0; side < get_num_sides(); ++side) { + SideManager side_manager(side); + max_chan_width = std::max(max_chan_width, get_chan_width(side_manager.get_side())); + } + return max_chan_width; +} /* Get the number of routing tracks of a X/Y-direction CB */ size_t RRGSB::get_cb_chan_width(const t_rr_type& cb_type) const { - return get_chan_width(get_cb_chan_side(cb_type)); + return get_chan_width(get_cb_chan_side(cb_type)); } /* Get the sides of ipin_nodes belong to the cb */ std::vector RRGSB::get_cb_ipin_sides(const t_rr_type& cb_type) const { - VTR_ASSERT (validate_cb_type(cb_type)); - - std::vector ipin_sides; - - /* Make sure a clean start */ - ipin_sides.clear(); - - switch(cb_type) { - case CHANX: - ipin_sides.push_back(TOP); - ipin_sides.push_back(BOTTOM); - break; - case CHANY: - ipin_sides.push_back(RIGHT); - ipin_sides.push_back(LEFT); - break; - default: - VTR_LOG("Invalid type of connection block!\n"); - exit(1); - } - - return ipin_sides; + VTR_ASSERT(validate_cb_type(cb_type)); + + std::vector ipin_sides; + + /* Make sure a clean start */ + ipin_sides.clear(); + + switch (cb_type) { + case CHANX: + ipin_sides.push_back(TOP); + ipin_sides.push_back(BOTTOM); + break; + case CHANY: + ipin_sides.push_back(RIGHT); + ipin_sides.push_back(LEFT); + break; + default: + VTR_LOG("Invalid type of connection block!\n"); + exit(1); + } + + return ipin_sides; } /* Get the direction of a rr_node at a given side and track_id */ enum PORTS RRGSB::get_chan_node_direction(const e_side& side, const size_t& track_id) const { - SideManager side_manager(side); - VTR_ASSERT(side_manager.validate()); - - /* Ensure the side is valid in the context of this switch block */ - VTR_ASSERT( validate_side(side) ); + SideManager side_manager(side); + VTR_ASSERT(side_manager.validate()); + + /* Ensure the side is valid in the context of this switch block */ + VTR_ASSERT(validate_side(side)); - /* Ensure the track is valid in the context of this switch block at a specific side */ - VTR_ASSERT( validate_track_id(side, track_id) ); - - return chan_node_direction_[side_manager.to_size_t()][track_id]; + /* Ensure the track is valid in the context of this switch block at a specific side */ + VTR_ASSERT(validate_track_id(side, track_id)); + + return chan_node_direction_[side_manager.to_size_t()][track_id]; } /* Get a list of segments used in this routing channel */ std::vector RRGSB::get_chan_segment_ids(const e_side& side) const { - SideManager side_manager(side); - VTR_ASSERT(side_manager.validate()); - - /* Ensure the side is valid in the context of this switch block */ - VTR_ASSERT( validate_side(side) ); + SideManager side_manager(side); + VTR_ASSERT(side_manager.validate()); + + /* Ensure the side is valid in the context of this switch block */ + VTR_ASSERT(validate_side(side)); - return chan_node_[side_manager.to_size_t()].get_segment_ids(); + return chan_node_[side_manager.to_size_t()].get_segment_ids(); } /* Get a list of rr_nodes whose sed_id is specified */ std::vector RRGSB::get_chan_node_ids_by_segment_ids(const e_side& side, - const RRSegmentId& seg_id) const { - return chan_node_[size_t(side)].get_node_ids_by_segment_ids(seg_id); -} + const RRSegmentId& seg_id) const { + return chan_node_[size_t(side)].get_node_ids_by_segment_ids(seg_id); +} /* get a rr_node at a given side and track_id */ RRNodeId RRGSB::get_chan_node(const e_side& side, const size_t& track_id) const { - SideManager side_manager(side); - VTR_ASSERT(side_manager.validate()); - - /* Ensure the side is valid in the context of this switch block */ - VTR_ASSERT( validate_side(side) ); - - /* Ensure the track is valid in the context of this switch block at a specific side */ - VTR_ASSERT( validate_track_id(side, track_id) ); - - return chan_node_[side_manager.to_size_t()].get_node(track_id); -} - -std::vector RRGSB::get_chan_node_in_edges(const RRGraph& rr_graph, + SideManager side_manager(side); + VTR_ASSERT(side_manager.validate()); + + /* Ensure the side is valid in the context of this switch block */ + VTR_ASSERT(validate_side(side)); + + /* Ensure the track is valid in the context of this switch block at a specific side */ + VTR_ASSERT(validate_track_id(side, track_id)); + + return chan_node_[side_manager.to_size_t()].get_node(track_id); +} + +std::vector RRGSB::get_chan_node_in_edges(const RRGraph& rr_graph, const e_side& side, const size_t& track_id) const { - SideManager side_manager(side); - VTR_ASSERT(side_manager.validate()); - - /* Ensure the side is valid in the context of this switch block */ - VTR_ASSERT( validate_side(side) ); + SideManager side_manager(side); + VTR_ASSERT(side_manager.validate()); + + /* Ensure the side is valid in the context of this switch block */ + VTR_ASSERT(validate_side(side)); - /* Ensure the track is valid in the context of this switch block at a specific side */ - VTR_ASSERT( validate_track_id(side, track_id) ); + /* Ensure the track is valid in the context of this switch block at a specific side */ + VTR_ASSERT(validate_track_id(side, track_id)); - /* The chan node must be an output port for the GSB, we allow users to access input edges*/ - VTR_ASSERT(OUT_PORT == get_chan_node_direction(side, track_id)); + /* The chan node must be an output port for the GSB, we allow users to access input edges*/ + VTR_ASSERT(OUT_PORT == get_chan_node_direction(side, track_id)); - /* if sorted, we give sorted edges + /* if sorted, we give sorted edges * if not sorted, we give the empty vector */ - if (0 == chan_node_in_edges_.size()) { - std::vector unsorted_edges; - for (const RREdgeId& edge : rr_graph.node_in_edges(get_chan_node(side, track_id))) { - unsorted_edges.push_back(edge); - } + if (0 == chan_node_in_edges_.size()) { + std::vector unsorted_edges; + for (const RREdgeId& edge : rr_graph.node_in_edges(get_chan_node(side, track_id))) { + unsorted_edges.push_back(edge); + } - return unsorted_edges; - } + return unsorted_edges; + } - return chan_node_in_edges_[side_manager.to_size_t()][track_id]; + return chan_node_in_edges_[side_manager.to_size_t()][track_id]; } /* get the segment id of a channel rr_node */ RRSegmentId RRGSB::get_chan_node_segment(const e_side& side, const size_t& track_id) const { - SideManager side_manager(side); - VTR_ASSERT(side_manager.validate()); - - /* Ensure the side is valid in the context of this switch block */ - VTR_ASSERT( validate_side(side) ); - - /* Ensure the track is valid in the context of this switch block at a specific side */ - VTR_ASSERT( validate_track_id(side, track_id) ); - - return chan_node_[side_manager.to_size_t()].get_node_segment(track_id); -} + SideManager side_manager(side); + VTR_ASSERT(side_manager.validate()); + + /* Ensure the side is valid in the context of this switch block */ + VTR_ASSERT(validate_side(side)); + + /* Ensure the track is valid in the context of this switch block at a specific side */ + VTR_ASSERT(validate_track_id(side, track_id)); + + return chan_node_[side_manager.to_size_t()].get_node_segment(track_id); +} /* Get the number of IPIN rr_nodes on a side */ size_t RRGSB::get_num_ipin_nodes(const e_side& side) const { - SideManager side_manager(side); - VTR_ASSERT(side_manager.validate()); - return ipin_node_[side_manager.to_size_t()].size(); -} + SideManager side_manager(side); + VTR_ASSERT(side_manager.validate()); + return ipin_node_[side_manager.to_size_t()].size(); +} /* get a opin_node at a given side and track_id */ RRNodeId RRGSB::get_ipin_node(const e_side& side, const size_t& node_id) const { - SideManager side_manager(side); - VTR_ASSERT(side_manager.validate()); - - /* Ensure the side is valid in the context of this switch block */ - VTR_ASSERT( validate_side(side) ); - - /* Ensure the track is valid in the context of this switch block at a specific side */ - VTR_ASSERT( validate_ipin_node_id(side, node_id) ); - - return ipin_node_[side_manager.to_size_t()][node_id]; -} + SideManager side_manager(side); + VTR_ASSERT(side_manager.validate()); + + /* Ensure the side is valid in the context of this switch block */ + VTR_ASSERT(validate_side(side)); + + /* Ensure the track is valid in the context of this switch block at a specific side */ + VTR_ASSERT(validate_ipin_node_id(side, node_id)); + + return ipin_node_[side_manager.to_size_t()][node_id]; +} /* Get the number of OPIN rr_nodes on a side */ size_t RRGSB::get_num_opin_nodes(const e_side& side) const { - SideManager side_manager(side); - VTR_ASSERT(side_manager.validate()); - return opin_node_[side_manager.to_size_t()].size(); -} + SideManager side_manager(side); + VTR_ASSERT(side_manager.validate()); + return opin_node_[side_manager.to_size_t()].size(); +} /* get a opin_node at a given side and track_id */ RRNodeId RRGSB::get_opin_node(const e_side& side, const size_t& node_id) const { - SideManager side_manager(side); - VTR_ASSERT(side_manager.validate()); - - /* Ensure the side is valid in the context of this switch block */ - 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) ); - - return opin_node_[side_manager.to_size_t()][node_id]; -} + SideManager side_manager(side); + VTR_ASSERT(side_manager.validate()); + + /* Ensure the side is valid in the context of this switch block */ + 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)); + + return opin_node_[side_manager.to_size_t()][node_id]; +} /* Get the node index of a routing track of a connection block, return -1 if not found */ int RRGSB::get_cb_chan_node_index(const t_rr_type& cb_type, const RRNodeId& node) const { - enum e_side chan_side = get_cb_chan_side(cb_type); - return get_chan_node_index(chan_side, node); + enum e_side chan_side = get_cb_chan_side(cb_type); + return get_chan_node_index(chan_side, node); } /* Get the node index in the array, return -1 if not found */ int RRGSB::get_chan_node_index(const e_side& node_side, const RRNodeId& node) const { - VTR_ASSERT (validate_side(node_side)); - return chan_node_[size_t(node_side)].get_node_track_id(node); + VTR_ASSERT(validate_side(node_side)); + return chan_node_[size_t(node_side)].get_node_track_id(node); } /* Get the node index in the array, return -1 if not found */ int RRGSB::get_node_index(const RRGraph& rr_graph, - const RRNodeId& node, - const e_side& node_side, + const RRNodeId& node, + const e_side& node_side, const PORTS& node_direction) const { - size_t cnt; - int ret; - - cnt = 0; - ret = -1; - - /* Depending on the type of rr_node, we search different arrays */ - switch (rr_graph.node_type(node)) { - case CHANX: - case CHANY: - for (size_t inode = 0; inode < get_chan_width(node_side); ++inode){ - if ((node == chan_node_[size_t(node_side)].get_node(inode)) - /* Check if direction meets specification */ - &&(node_direction == chan_node_direction_[size_t(node_side)][inode])) { - cnt++; - ret = inode; - break; - } - } - break; - case IPIN: - for (size_t inode = 0; inode < get_num_ipin_nodes(node_side); ++inode) { - if (node == ipin_node_[size_t(node_side)][inode]) { - cnt++; - ret = inode; - break; - } + size_t cnt; + int ret; + + cnt = 0; + ret = -1; + + /* Depending on the type of rr_node, we search different arrays */ + switch (rr_graph.node_type(node)) { + case CHANX: + case CHANY: + for (size_t inode = 0; inode < get_chan_width(node_side); ++inode) { + if ((node == chan_node_[size_t(node_side)].get_node(inode)) + /* Check if direction meets specification */ + && (node_direction == chan_node_direction_[size_t(node_side)][inode])) { + cnt++; + ret = inode; + break; + } + } + break; + case IPIN: + for (size_t inode = 0; inode < get_num_ipin_nodes(node_side); ++inode) { + if (node == ipin_node_[size_t(node_side)][inode]) { + cnt++; + ret = inode; + break; + } + } + break; + case OPIN: + for (size_t inode = 0; inode < get_num_opin_nodes(node_side); ++inode) { + if (node == opin_node_[size_t(node_side)][inode]) { + cnt++; + ret = inode; + break; + } + } + break; + default: + VTR_LOG("Invalid cur_rr_node type! Should be [CHANX|CHANY|IPIN|OPIN]\n"); + exit(1); } - break; - case OPIN: - for (size_t inode = 0; inode < get_num_opin_nodes(node_side); ++inode) { - if (node == opin_node_[size_t(node_side)][inode]) { - cnt++; - ret = inode; - break; - } - } - break; - default: - VTR_LOG("Invalid cur_rr_node type! Should be [CHANX|CHANY|IPIN|OPIN]\n"); - exit(1); - } - VTR_ASSERT((0 == cnt)||(1 == cnt)); + VTR_ASSERT((0 == cnt) || (1 == cnt)); - return ret; /* Return an invalid value: nonthing is found*/ + return ret; /* Return an invalid value: nonthing is found*/ } /* Get the side of a node in this SB */ void RRGSB::get_node_side_and_index(const RRGraph& rr_graph, - const RRNodeId& node, + const RRNodeId& node, const PORTS& node_direction, - e_side& node_side, + e_side& node_side, int& node_index) const { - size_t side; - SideManager side_manager; - - /* Count the number of existence of cur_rr_node in cur_sb_info + size_t side; + SideManager side_manager; + + /* Count the number of existence of cur_rr_node in cur_sb_info * It could happen that same cur_rr_node appears on different sides of a SB * For example, a routing track go vertically across the SB. * Then its corresponding rr_node appears on both TOP and BOTTOM sides of this SB. * We need to ensure that the found rr_node has the same direction as user want. * By specifying the direction of rr_node, There should be only one rr_node can satisfy! */ - for (side = 0; side < get_num_sides(); ++side) { - side_manager.set_side(side); - node_index = get_node_index(rr_graph, node, side_manager.get_side(), node_direction); - if (-1 != node_index) { - break; + for (side = 0; side < get_num_sides(); ++side) { + side_manager.set_side(side); + node_index = get_node_index(rr_graph, node, side_manager.get_side(), node_direction); + if (-1 != node_index) { + break; + } } - } - if (side == get_num_sides()) { - /* we find nothing, return NUM_SIDES, and a OPEN node (-1) */ - node_side = NUM_SIDES; - VTR_ASSERT(-1 == node_index); - return; - } + if (side == get_num_sides()) { + /* we find nothing, return NUM_SIDES, and a OPEN node (-1) */ + node_side = NUM_SIDES; + VTR_ASSERT(-1 == node_index); + return; + } - node_side = side_manager.get_side(); - VTR_ASSERT(-1 != node_index); + node_side = side_manager.get_side(); + VTR_ASSERT(-1 != node_index); - return; -} + return; +} /* Check if the node exist in the opposite side of this Switch Block */ bool RRGSB::is_sb_node_exist_opposite_side(const RRGraph& rr_graph, - const RRNodeId& node, + const RRNodeId& node, const e_side& node_side) const { - SideManager side_manager(node_side); - int index; + SideManager side_manager(node_side); + int index; - VTR_ASSERT((CHANX == rr_graph.node_type(node)) || (CHANY == rr_graph.node_type(node))); + VTR_ASSERT((CHANX == rr_graph.node_type(node)) || (CHANY == rr_graph.node_type(node))); - /* See if we can find the same src_rr_node in the opposite chan_side + /* See if we can find the same src_rr_node in the opposite chan_side * if there is one, it means a shorted wire across the SB */ - index = get_node_index(rr_graph, node, side_manager.get_opposite(), IN_PORT); + index = get_node_index(rr_graph, node, side_manager.get_opposite(), IN_PORT); - return (-1 != index); + return (-1 != index); } /* check if the candidate CB is a mirror of the current one */ -bool RRGSB::is_cb_mirror(const RRGraph& rr_graph, const RRGSB& cand, const t_rr_type& cb_type) const { - /* Check if channel width is the same */ - if ( get_cb_chan_width(cb_type) != cand.get_cb_chan_width(cb_type) ) { - return false; - } - - enum e_side chan_side = get_cb_chan_side(cb_type); +bool RRGSB::is_cb_mirror(const RRGraph& rr_graph, const RRGSB& cand, const t_rr_type& cb_type) const { + /* Check if channel width is the same */ + if (get_cb_chan_width(cb_type) != cand.get_cb_chan_width(cb_type)) { + return false; + } - /* check the numbers/directionality of channel rr_nodes */ - if ( false == chan_node_[size_t(chan_side)].is_mirror(rr_graph, cand.chan_node_[size_t(chan_side)]) ) { - return false; - } + enum e_side chan_side = get_cb_chan_side(cb_type); - /* check the equivalence of ipins */ - std::vector ipin_side = get_cb_ipin_sides(cb_type); - for (size_t side = 0; side < ipin_side.size(); ++side) { - /* Ensure we have the same number of IPINs on this side */ - if ( get_num_ipin_nodes(ipin_side[side]) != cand.get_num_ipin_nodes(ipin_side[side]) ) { - return false; - } - for (size_t inode = 0; inode < get_num_ipin_nodes(ipin_side[side]); ++inode) { - if (false == is_cb_node_mirror(rr_graph, cand, cb_type, ipin_side[side], inode)) { + /* check the numbers/directionality of channel rr_nodes */ + if (false == chan_node_[size_t(chan_side)].is_mirror(rr_graph, cand.chan_node_[size_t(chan_side)])) { return false; - } } - } - return true; + /* check the equivalence of ipins */ + std::vector ipin_side = get_cb_ipin_sides(cb_type); + for (size_t side = 0; side < ipin_side.size(); ++side) { + /* Ensure we have the same number of IPINs on this side */ + if (get_num_ipin_nodes(ipin_side[side]) != cand.get_num_ipin_nodes(ipin_side[side])) { + return false; + } + for (size_t inode = 0; inode < get_num_ipin_nodes(ipin_side[side]); ++inode) { + if (false == is_cb_node_mirror(rr_graph, cand, cb_type, ipin_side[side], inode)) { + return false; + } + } + } + + return true; } /* check if the CB exist in this GSB */ bool RRGSB::is_cb_exist(const t_rr_type& cb_type) const { - /* if channel width is zero, there is no CB */ - return (0 != get_cb_chan_width(cb_type)); -} + /* if channel width is zero, there is no CB */ + return (0 != get_cb_chan_width(cb_type)); +} /* check if the SB exist in this GSB */ bool RRGSB::is_sb_exist() const { - /* if all the channel width is zero and number of OPINs are zero, there is no SB */ - for (size_t side = 0; side < get_num_sides(); ++side) { - SideManager side_manager(side); - if (0 != get_chan_width(side_manager.get_side())) { - return true; + /* if all the channel width is zero and number of OPINs are zero, there is no SB */ + for (size_t side = 0; side < get_num_sides(); ++side) { + SideManager side_manager(side); + if (0 != get_chan_width(side_manager.get_side())) { + return true; + } + if (0 != get_num_opin_nodes(side_manager.get_side())) { + return true; + } } - if (0 != get_num_opin_nodes(side_manager.get_side())) { - return true; - } - } - return false; -} + return false; +} /************************************************************************ * Check if the node indicates a passing wire across the Switch Block part of the GSB @@ -407,49 +407,48 @@ bool RRGSB::is_sb_exist() const { * (xhigh, yhigh) should be same as the GSB side coordinate ***********************************************************************/ bool RRGSB::is_sb_node_passing_wire(const RRGraph& rr_graph, - const e_side& node_side, - const size_t& track_id) const { - - /* Get the rr_node */ - RRNodeId track_node = get_chan_node(node_side, track_id); - /* Get the coordinates */ - vtr::Point side_coordinate = get_side_block_coordinate(node_side); - - /* Get the coordinate of where the track starts */ - vtr::Point track_start = get_track_rr_node_start_coordinate(rr_graph, track_node); - - /* INC_DIRECTION start_track: (xlow, ylow) should be same as the GSB side coordinate */ - /* DEC_DIRECTION start_track: (xhigh, yhigh) should be same as the GSB side coordinate */ - if ( (track_start.x() == side_coordinate.x()) - && (track_start.y() == side_coordinate.y()) - && (OUT_PORT == get_chan_node_direction(node_side, track_id)) ) { - /* Double check: start track should be an OUTPUT PORT of the GSB */ - return false; /* This is a starting point */ - } - - /* Get the coordinate of where the track ends */ - vtr::Point track_end = get_track_rr_node_end_coordinate(rr_graph, track_node); - - /* INC_DIRECTION end_track: (xhigh, yhigh) should be same as the GSB side coordinate */ - /* DEC_DIRECTION end_track: (xlow, ylow) should be same as the GSB side coordinate */ - if ( (track_end.x() == side_coordinate.x()) - && (track_end.y() == side_coordinate.y()) - && (IN_PORT == get_chan_node_direction(node_side, track_id)) ) { - /* Double check: end track should be an INPUT PORT of the GSB */ - return false; /* This is an ending point */ - } - - /* Reach here it means that this will be a passing wire, + const e_side& node_side, + const size_t& track_id) const { + /* Get the rr_node */ + RRNodeId track_node = get_chan_node(node_side, track_id); + /* Get the coordinates */ + vtr::Point side_coordinate = get_side_block_coordinate(node_side); + + /* Get the coordinate of where the track starts */ + vtr::Point track_start = get_track_rr_node_start_coordinate(rr_graph, track_node); + + /* INC_DIRECTION start_track: (xlow, ylow) should be same as the GSB side coordinate */ + /* DEC_DIRECTION start_track: (xhigh, yhigh) should be same as the GSB side coordinate */ + if ((track_start.x() == side_coordinate.x()) + && (track_start.y() == side_coordinate.y()) + && (OUT_PORT == get_chan_node_direction(node_side, track_id))) { + /* Double check: start track should be an OUTPUT PORT of the GSB */ + return false; /* This is a starting point */ + } + + /* Get the coordinate of where the track ends */ + vtr::Point track_end = get_track_rr_node_end_coordinate(rr_graph, track_node); + + /* INC_DIRECTION end_track: (xhigh, yhigh) should be same as the GSB side coordinate */ + /* DEC_DIRECTION end_track: (xlow, ylow) should be same as the GSB side coordinate */ + if ((track_end.x() == side_coordinate.x()) + && (track_end.y() == side_coordinate.y()) + && (IN_PORT == get_chan_node_direction(node_side, track_id))) { + /* Double check: end track should be an INPUT PORT of the GSB */ + return false; /* This is an ending point */ + } + + /* Reach here it means that this will be a passing wire, * we should be able to find the node on the opposite side of the GSB! */ - if (true != is_sb_node_exist_opposite_side(rr_graph, track_node, node_side)) { - VTR_LOG("GSB[%lu][%lu] track node[%lu] at %s:\n", - get_x(), get_y(), track_id, SIDE_STRING[node_side]); - rr_graph.print_node(track_node); - } - VTR_ASSERT (true == is_sb_node_exist_opposite_side(rr_graph, track_node, node_side)); + if (true != is_sb_node_exist_opposite_side(rr_graph, track_node, node_side)) { + VTR_LOG("GSB[%lu][%lu] track node[%lu] at %s:\n", + get_x(), get_y(), track_id, SIDE_STRING[node_side]); + rr_graph.print_node(track_node); + } + VTR_ASSERT(true == is_sb_node_exist_opposite_side(rr_graph, track_node, node_side)); - return true; + return true; } /* check if the candidate SB satisfy the basic requirements on being a mirror of the current one */ @@ -459,356 +458,353 @@ bool RRGSB::is_sb_node_passing_wire(const RRGraph& rr_graph, * If all above are satisfied, the two switch blocks may be mirrors ! */ bool RRGSB::is_sb_mirrorable(const RRGraph& rr_graph, const RRGSB& cand) const { - /* check the numbers of sides */ - if (get_num_sides() != cand.get_num_sides()) { - return false; - } - - /* check the numbers/directionality of channel rr_nodes */ - for (size_t side = 0; side < get_num_sides(); ++side) { - SideManager side_manager(side); - - /* Ensure we have the same channel width on this side */ - if (get_chan_width(side_manager.get_side()) != cand.get_chan_width(side_manager.get_side())) { - return false; + /* check the numbers of sides */ + if (get_num_sides() != cand.get_num_sides()) { + return false; } - if ( ((size_t(-1) == get_track_id_first_short_connection(rr_graph, side_manager.get_side())) - && (size_t(-1) != cand.get_track_id_first_short_connection(rr_graph, side_manager.get_side()))) - || ((size_t(-1) != get_track_id_first_short_connection(rr_graph, side_manager.get_side()) ) - && ( size_t(-1) == cand.get_track_id_first_short_connection(rr_graph, side_manager.get_side()))) ) { - return false; + /* check the numbers/directionality of channel rr_nodes */ + for (size_t side = 0; side < get_num_sides(); ++side) { + SideManager side_manager(side); + + /* Ensure we have the same channel width on this side */ + if (get_chan_width(side_manager.get_side()) != cand.get_chan_width(side_manager.get_side())) { + return false; + } + + if (((size_t(-1) == get_track_id_first_short_connection(rr_graph, side_manager.get_side())) + && (size_t(-1) != cand.get_track_id_first_short_connection(rr_graph, side_manager.get_side()))) + || ((size_t(-1) != get_track_id_first_short_connection(rr_graph, side_manager.get_side())) + && (size_t(-1) == cand.get_track_id_first_short_connection(rr_graph, side_manager.get_side())))) { + return false; + } } - } - /* check the numbers of opin_rr_nodes */ - for (size_t side = 0; side < get_num_sides(); ++side) { - SideManager side_manager(side); + /* check the numbers of opin_rr_nodes */ + for (size_t side = 0; side < get_num_sides(); ++side) { + SideManager side_manager(side); - if (get_num_opin_nodes(side_manager.get_side()) != cand.get_num_opin_nodes(side_manager.get_side())) { - return false; + if (get_num_opin_nodes(side_manager.get_side()) != cand.get_num_opin_nodes(side_manager.get_side())) { + return false; + } } - } - return true; + return true; } /* check if all the routing segments of a side of candidate SB is a mirror of the current one */ -bool RRGSB::is_sb_side_segment_mirror(const RRGraph& rr_graph, const RRGSB& cand, - const e_side& side, const RRSegmentId& seg_id) const { - /* Create a side manager */ - SideManager side_manager(side); - - /* Make sure both Switch blocks has this side!!! */ - VTR_ASSERT ( side_manager.to_size_t() < get_num_sides() ); - VTR_ASSERT ( side_manager.to_size_t() < cand.get_num_sides() ); - - /* check the numbers/directionality of channel rr_nodes */ - /* Ensure we have the same channel width on this side */ - if (get_chan_width(side) != cand.get_chan_width(side)) { - return false; - } - for (size_t itrack = 0; itrack < get_chan_width(side); ++itrack) { - /* Bypass unrelated segments */ - if (seg_id != get_chan_node_segment(side, itrack)) { - continue; - } - /* Check the directionality of each node */ - if (get_chan_node_direction(side, itrack) != cand.get_chan_node_direction(side, itrack)) { - return false; +bool RRGSB::is_sb_side_segment_mirror(const RRGraph& rr_graph, const RRGSB& cand, const e_side& side, const RRSegmentId& seg_id) const { + /* Create a side manager */ + SideManager side_manager(side); + + /* Make sure both Switch blocks has this side!!! */ + VTR_ASSERT(side_manager.to_size_t() < get_num_sides()); + VTR_ASSERT(side_manager.to_size_t() < cand.get_num_sides()); + + /* check the numbers/directionality of channel rr_nodes */ + /* Ensure we have the same channel width on this side */ + if (get_chan_width(side) != cand.get_chan_width(side)) { + return false; } - /* Check the track_id of each node + for (size_t itrack = 0; itrack < get_chan_width(side); ++itrack) { + /* Bypass unrelated segments */ + if (seg_id != get_chan_node_segment(side, itrack)) { + continue; + } + /* Check the directionality of each node */ + if (get_chan_node_direction(side, itrack) != cand.get_chan_node_direction(side, itrack)) { + return false; + } + /* Check the track_id of each node * ptc is not necessary, we care the connectivity! */ - /* For OUT_PORT rr_node, we need to check fan-in */ - if (OUT_PORT != get_chan_node_direction(side, itrack)) { - continue; /* skip IN_PORT */ + /* For OUT_PORT rr_node, we need to check fan-in */ + if (OUT_PORT != get_chan_node_direction(side, itrack)) { + continue; /* skip IN_PORT */ + } + + if (false == is_sb_node_mirror(rr_graph, cand, side, itrack)) { + return false; + } } - if (false == is_sb_node_mirror(rr_graph, cand, side, itrack)) { - return false; - } - } - - /* check the numbers of opin_rr_nodes */ - if (get_num_opin_nodes(side) != cand.get_num_opin_nodes(side)) { - return false; - } + /* check the numbers of opin_rr_nodes */ + if (get_num_opin_nodes(side) != cand.get_num_opin_nodes(side)) { + return false; + } - /* check the numbers of ipin_rr_nodes */ - if (get_num_ipin_nodes(side) != cand.get_num_ipin_nodes(side)) { - return false; - } + /* check the numbers of ipin_rr_nodes */ + if (get_num_ipin_nodes(side) != cand.get_num_ipin_nodes(side)) { + return false; + } - return true; -} + return true; +} /* check if a side of candidate SB is a mirror of the current one */ bool RRGSB::is_sb_side_mirror(const RRGraph& rr_graph, const RRGSB& cand, const e_side& side) const { + /* get a list of segments */ + std::vector seg_ids = chan_node_[size_t(side)].get_segment_ids(); - /* get a list of segments */ - std::vector seg_ids = chan_node_[size_t(side)].get_segment_ids(); - - for (size_t iseg = 0; iseg < seg_ids.size(); ++iseg) { - if (false == is_sb_side_segment_mirror(rr_graph, cand, side, seg_ids[iseg])) { - return false; + for (size_t iseg = 0; iseg < seg_ids.size(); ++iseg) { + if (false == is_sb_side_segment_mirror(rr_graph, cand, side, seg_ids[iseg])) { + return false; + } } - } - return true; + return true; } /* check if the candidate SB is a mirror of the current one */ bool RRGSB::is_sb_mirror(const RRGraph& rr_graph, const RRGSB& cand) const { - /* check the numbers of sides */ - if (get_num_sides() != cand.get_num_sides()) { - return false; - } + /* check the numbers of sides */ + if (get_num_sides() != cand.get_num_sides()) { + return false; + } - /* check the numbers/directionality of channel rr_nodes */ - for (size_t side = 0; side < get_num_sides(); ++side) { - SideManager side_manager(side); - if (false == is_sb_side_mirror(rr_graph, cand, side_manager.get_side())) { - return false; - } - } + /* check the numbers/directionality of channel rr_nodes */ + for (size_t side = 0; side < get_num_sides(); ++side) { + SideManager side_manager(side); + if (false == is_sb_side_mirror(rr_graph, cand, side_manager.get_side())) { + return false; + } + } - return true; + return true; } /* Public Accessors: Cooridinator conversion */ /* get the x coordinate of this GSB */ size_t RRGSB::get_x() const { - return coordinate_.x(); -} + return coordinate_.x(); +} /* get the y coordinate of this GSB */ -size_t RRGSB::get_y() const { - return coordinate_.y(); +size_t RRGSB::get_y() const { + return coordinate_.y(); } - /* get the x coordinate of this switch block */ size_t RRGSB::get_sb_x() const { - return coordinate_.x(); -} + return coordinate_.x(); +} /* get the y coordinate of this switch block */ -size_t RRGSB::get_sb_y() const { - return coordinate_.y(); +size_t RRGSB::get_sb_y() const { + return coordinate_.y(); } /* Get the number of sides of this SB */ vtr::Point RRGSB::get_sb_coordinate() const { - return coordinate_; -} + return coordinate_; +} /* get the x coordinate of this X/Y-direction block */ size_t RRGSB::get_cb_x(const t_rr_type& cb_type) const { - VTR_ASSERT (validate_cb_type(cb_type)); - switch(cb_type) { - case CHANX: - return get_side_block_coordinate(LEFT).x(); - case CHANY: - return get_side_block_coordinate(TOP).x(); - default: - VTR_LOG("Invalid type of connection block!\n"); - exit(1); - } -} + VTR_ASSERT(validate_cb_type(cb_type)); + switch (cb_type) { + case CHANX: + return get_side_block_coordinate(LEFT).x(); + case CHANY: + return get_side_block_coordinate(TOP).x(); + default: + VTR_LOG("Invalid type of connection block!\n"); + exit(1); + } +} /* get the y coordinate of this X/Y-direction block */ -size_t RRGSB::get_cb_y(const t_rr_type& cb_type) const { - VTR_ASSERT (validate_cb_type(cb_type)); - switch(cb_type) { - case CHANX: - return get_side_block_coordinate(LEFT).y(); - case CHANY: - return get_side_block_coordinate(TOP).y(); - default: - VTR_LOG("Invalid type of connection block!\n"); - exit(1); - } +size_t RRGSB::get_cb_y(const t_rr_type& cb_type) const { + VTR_ASSERT(validate_cb_type(cb_type)); + switch (cb_type) { + case CHANX: + return get_side_block_coordinate(LEFT).y(); + case CHANY: + return get_side_block_coordinate(TOP).y(); + default: + VTR_LOG("Invalid type of connection block!\n"); + exit(1); + } } /* Get the coordinate of the X/Y-direction CB */ vtr::Point RRGSB::get_cb_coordinate(const t_rr_type& cb_type) const { - VTR_ASSERT (validate_cb_type(cb_type)); - switch(cb_type) { - case CHANX: - return get_side_block_coordinate(LEFT); - case CHANY: - return get_side_block_coordinate(TOP); - default: - VTR_LOG("Invalid type of connection block!\n"); - exit(1); - } -} + VTR_ASSERT(validate_cb_type(cb_type)); + switch (cb_type) { + case CHANX: + return get_side_block_coordinate(LEFT); + case CHANY: + return get_side_block_coordinate(TOP); + default: + VTR_LOG("Invalid type of connection block!\n"); + exit(1); + } +} e_side RRGSB::get_cb_chan_side(const t_rr_type& cb_type) const { - VTR_ASSERT (validate_cb_type(cb_type)); - switch(cb_type) { - case CHANX: - return LEFT; - case CHANY: - return TOP; - default: - VTR_LOG("Invalid type of connection block!\n"); - exit(1); - } + VTR_ASSERT(validate_cb_type(cb_type)); + switch (cb_type) { + case CHANX: + return LEFT; + case CHANY: + return TOP; + default: + VTR_LOG("Invalid type of connection block!\n"); + exit(1); + } } /* Get the side of routing channel in the GSB according to the side of IPIN */ e_side RRGSB::get_cb_chan_side(const e_side& ipin_side) const { - switch(ipin_side) { - case TOP: - return LEFT; - case RIGHT: - return TOP; - case BOTTOM: - return LEFT; - case LEFT: - return TOP; - default: - VTR_LOG("Invalid type of ipin_side!\n"); - exit(1); - } + switch (ipin_side) { + case TOP: + return LEFT; + case RIGHT: + return TOP; + case BOTTOM: + return LEFT; + case LEFT: + return TOP; + default: + VTR_LOG("Invalid type of ipin_side!\n"); + exit(1); + } } vtr::Point RRGSB::get_side_block_coordinate(const e_side& side) const { - SideManager side_manager(side); - VTR_ASSERT(side_manager.validate()); - vtr::Point ret(get_sb_x(), get_sb_y()); - - switch (side_manager.get_side()) { - case TOP: - /* (0 == side) */ - /* 1. Channel Y [x][y+1] inputs */ - ret.set_y(ret.y() + 1); - break; - case RIGHT: - /* 1 == side */ - /* 2. Channel X [x+1][y] inputs */ - ret.set_x(ret.x() + 1); - break; - case BOTTOM: - /* 2 == side */ - /* 3. Channel Y [x][y] inputs */ - break; - case LEFT: - /* 3 == side */ - /* 4. Channel X [x][y] inputs */ - break; - default: - VTR_LOG(" Invalid side!\n"); - exit(1); - } - - return ret; + SideManager side_manager(side); + VTR_ASSERT(side_manager.validate()); + vtr::Point ret(get_sb_x(), get_sb_y()); + + switch (side_manager.get_side()) { + case TOP: + /* (0 == side) */ + /* 1. Channel Y [x][y+1] inputs */ + ret.set_y(ret.y() + 1); + break; + case RIGHT: + /* 1 == side */ + /* 2. Channel X [x+1][y] inputs */ + ret.set_x(ret.x() + 1); + break; + case BOTTOM: + /* 2 == side */ + /* 3. Channel Y [x][y] inputs */ + break; + case LEFT: + /* 3 == side */ + /* 4. Channel X [x][y] inputs */ + break; + default: + VTR_LOG(" Invalid side!\n"); + exit(1); + } + + return ret; } vtr::Point RRGSB::get_grid_coordinate() const { - vtr::Point ret(get_sb_x(), get_sb_y()); - ret.set_y(ret.y() + 1); + vtr::Point ret(get_sb_x(), get_sb_y()); + ret.set_y(ret.y() + 1); - return ret; + return ret; } /************************************************************************ * Public Mutators ***********************************************************************/ /* get a copy from a source */ -void RRGSB::set(const RRGSB& src) { - /* Copy coordinate */ - this->set_coordinate(src.get_sb_coordinate().x(), src.get_sb_coordinate().y()); - - /* Initialize sides */ - this->init_num_sides(src.get_num_sides()); - - /* Copy vectors */ - for (size_t side = 0; side < src.get_num_sides(); ++side) { - SideManager side_manager(side); - /* Copy chan_nodes */ - /* skip if there is no channel width */ - if ( 0 < src.get_chan_width(side_manager.get_side()) ) { - this->chan_node_[side_manager.get_side()].set(src.chan_node_[side_manager.get_side()]); - /* Copy chan_node_direction_*/ - this->chan_node_direction_[side_manager.get_side()].clear(); - for (size_t inode = 0; inode < src.get_chan_width(side_manager.get_side()); ++inode) { - this->chan_node_direction_[side_manager.get_side()].push_back(src.get_chan_node_direction(side_manager.get_side(), inode)); - } - } - - /* Copy opin_node and opin_node_grid_side_ */ - this->opin_node_[side_manager.get_side()].clear(); - for (size_t inode = 0; inode < src.get_num_opin_nodes(side_manager.get_side()); ++inode) { - this->opin_node_[side_manager.get_side()].push_back(src.get_opin_node(side_manager.get_side(), inode)); +void RRGSB::set(const RRGSB& src) { + /* Copy coordinate */ + this->set_coordinate(src.get_sb_coordinate().x(), src.get_sb_coordinate().y()); + + /* Initialize sides */ + this->init_num_sides(src.get_num_sides()); + + /* Copy vectors */ + for (size_t side = 0; side < src.get_num_sides(); ++side) { + SideManager side_manager(side); + /* Copy chan_nodes */ + /* skip if there is no channel width */ + if (0 < src.get_chan_width(side_manager.get_side())) { + this->chan_node_[side_manager.get_side()].set(src.chan_node_[side_manager.get_side()]); + /* Copy chan_node_direction_*/ + this->chan_node_direction_[side_manager.get_side()].clear(); + for (size_t inode = 0; inode < src.get_chan_width(side_manager.get_side()); ++inode) { + this->chan_node_direction_[side_manager.get_side()].push_back(src.get_chan_node_direction(side_manager.get_side(), inode)); + } + } + + /* Copy opin_node and opin_node_grid_side_ */ + this->opin_node_[side_manager.get_side()].clear(); + for (size_t inode = 0; inode < src.get_num_opin_nodes(side_manager.get_side()); ++inode) { + this->opin_node_[side_manager.get_side()].push_back(src.get_opin_node(side_manager.get_side(), inode)); + } + + /* Copy ipin_node and ipin_node_grid_side_ */ + this->ipin_node_[side_manager.get_side()].clear(); + for (size_t inode = 0; inode < src.get_num_ipin_nodes(side_manager.get_side()); ++inode) { + this->ipin_node_[side_manager.get_side()].push_back(src.get_ipin_node(side_manager.get_side(), inode)); + } } - - /* Copy ipin_node and ipin_node_grid_side_ */ - this->ipin_node_[side_manager.get_side()].clear(); - for (size_t inode = 0; inode < src.get_num_ipin_nodes(side_manager.get_side()); ++inode) { - this->ipin_node_[side_manager.get_side()].push_back(src.get_ipin_node(side_manager.get_side(), inode)); - } - } } /* Set the coordinate (x,y) for the switch block */ void RRGSB::set_coordinate(const size_t& x, const size_t& y) { - coordinate_.set(x, y); + coordinate_.set(x, y); } /* Allocate the vectors with the given number of sides */ void RRGSB::init_num_sides(const size_t& num_sides) { - /* Initialize the vectors */ - chan_node_.resize(num_sides); - chan_node_direction_.resize(num_sides); - ipin_node_.resize(num_sides); - opin_node_.resize(num_sides); + /* Initialize the vectors */ + chan_node_.resize(num_sides); + chan_node_direction_.resize(num_sides); + ipin_node_.resize(num_sides); + opin_node_.resize(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, 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)); - - /* fill the dedicated element in the vector */ - chan_node_[size_t(node_side)].set(rr_chan); - chan_node_direction_[size_t(node_side)].resize(rr_chan_dir.size()); - for (size_t inode = 0; inode < rr_chan_dir.size(); ++inode) { - chan_node_direction_[size_t(node_side)][inode] = rr_chan_dir[inode]; - } -} + /* Validate: 1. side is valid, the type of node is valid */ + VTR_ASSERT(validate_side(node_side)); + + /* fill the dedicated element in the vector */ + chan_node_[size_t(node_side)].set(rr_chan); + chan_node_direction_[size_t(node_side)].resize(rr_chan_dir.size()); + for (size_t inode = 0; inode < rr_chan_dir.size(); ++inode) { + chan_node_direction_[size_t(node_side)][inode] = rr_chan_dir[inode]; + } +} /* Add a node to the chan_node_ list and also assign its direction in chan_node_direction_ */ void RRGSB::add_ipin_node(const RRNodeId& node, const e_side& node_side) { - VTR_ASSERT(validate_side(node_side)); - /* push pack the dedicated element in the vector */ - ipin_node_[size_t(node_side)].push_back(node); + VTR_ASSERT(validate_side(node_side)); + /* push pack the dedicated element in the vector */ + ipin_node_[size_t(node_side)].push_back(node); } /* Add a node to the chan_node_ list and also assign its direction in chan_node_direction_ */ void RRGSB::add_opin_node(const RRNodeId& node, const e_side& node_side) { - VTR_ASSERT(validate_side(node_side)); - /* push pack the dedicated element in the vector */ - opin_node_[size_t(node_side)].push_back(node); -} + VTR_ASSERT(validate_side(node_side)); + /* push pack the dedicated element in the vector */ + 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; + 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; + const RRNodeId& chan_node = chan_node_[size_t(chan_side)].get_node(track_id); - /* For each incoming edge, find the node side and index in this GSB. + /* 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() @@ -817,73 +813,73 @@ void RRGSB::sort_chan_node_in_edges(const RRGraph& rr_graph, * 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 */ - if (NUM_SIDES == side) { - VTR_LOG("GSB[%lu][%lu]:\n", get_x(), get_y()); - VTR_LOG("SRC node:\n"); - rr_graph.print_node(src_node); - VTR_LOG("Channel node:\n"); - rr_graph.print_node(chan_node); + 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 */ + if (NUM_SIDES == side) { + VTR_LOG("GSB[%lu][%lu]:\n", get_x(), get_y()); + VTR_LOG("SRC node:\n"); + rr_graph.print_node(src_node); + VTR_LOG("Channel node:\n"); + rr_graph.print_node(chan_node); + } + + 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++; } - 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]); - } + /* 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]); + } + } } - - /* 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()); -} + 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 and bypass passing wires */ - if ( (OUT_PORT == chan_node_direction_[side][track_id]) - && (false == is_sb_node_passing_wire(rr_graph, side_manager.get_side(), track_id)) ) { - sort_chan_node_in_edges(rr_graph, side_manager.get_side(), track_id); - } + /* 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 and bypass passing wires */ + if ((OUT_PORT == chan_node_direction_[side][track_id]) + && (false == is_sb_node_passing_wire(rr_graph, side_manager.get_side(), track_id))) { + sort_chan_node_in_edges(rr_graph, side_manager.get_side(), track_id); + } + } } - } } /************************************************************************ @@ -891,49 +887,49 @@ void RRGSB::sort_chan_node_in_edges(const RRGraph& rr_graph) { ***********************************************************************/ /* Reset the RRGSB to pristine state */ void RRGSB::clear() { - /* Clean all the vectors */ - VTR_ASSERT(validate_num_sides()); - /* Clear the inner vector of each matrix */ - for (size_t side = 0; side < get_num_sides(); ++side) { - chan_node_direction_[side].clear(); - chan_node_[side].clear(); - ipin_node_[side].clear(); - opin_node_[side].clear(); - } - chan_node_direction_.clear(); - chan_node_.clear(); - ipin_node_.clear(); - opin_node_.clear(); + /* Clean all the vectors */ + VTR_ASSERT(validate_num_sides()); + /* Clear the inner vector of each matrix */ + for (size_t side = 0; side < get_num_sides(); ++side) { + chan_node_direction_[side].clear(); + chan_node_[side].clear(); + ipin_node_[side].clear(); + opin_node_[side].clear(); + } + chan_node_direction_.clear(); + chan_node_.clear(); + ipin_node_.clear(); + opin_node_.clear(); } /* Clean the chan_width of a side */ void RRGSB::clear_chan_nodes(const e_side& node_side) { - VTR_ASSERT(validate_side(node_side)); - - chan_node_[size_t(node_side)].clear(); - chan_node_direction_[size_t(node_side)].clear(); -} + VTR_ASSERT(validate_side(node_side)); + + chan_node_[size_t(node_side)].clear(); + chan_node_direction_[size_t(node_side)].clear(); +} /* Clean the number of IPINs of a side */ void RRGSB::clear_ipin_nodes(const e_side& node_side) { - VTR_ASSERT(validate_side(node_side)); - - ipin_node_[size_t(node_side)].clear(); -} + VTR_ASSERT(validate_side(node_side)); + + ipin_node_[size_t(node_side)].clear(); +} /* Clean the number of OPINs of a side */ void RRGSB::clear_opin_nodes(const e_side& node_side) { - VTR_ASSERT(validate_side(node_side)); - - opin_node_[size_t(node_side)].clear(); + VTR_ASSERT(validate_side(node_side)); + + opin_node_[size_t(node_side)].clear(); } /* Clean chan/opin/ipin nodes at one side */ void RRGSB::clear_one_side(const e_side& node_side) { - clear_chan_nodes(node_side); - clear_ipin_nodes(node_side); - clear_opin_nodes(node_side); -} + clear_chan_nodes(node_side); + clear_ipin_nodes(node_side); + clear_opin_nodes(node_side); +} /************************************************************************ * Internal Accessors: identify mirrors @@ -946,62 +942,62 @@ void RRGSB::clear_one_side(const e_side& node_side) { * 3. each drive_rr_switch should be the same */ bool RRGSB::is_sb_node_mirror(const RRGraph& rr_graph, - const RRGSB& cand, - const e_side& node_side, + const RRGSB& cand, + const e_side& node_side, const size_t& track_id) const { - /* Ensure rr_nodes are either the output of short-connection or multiplexer */ - bool is_short_conkt = this->is_sb_node_passing_wire(rr_graph, node_side, track_id); + /* Ensure rr_nodes are either the output of short-connection or multiplexer */ + bool is_short_conkt = this->is_sb_node_passing_wire(rr_graph, node_side, track_id); - if (is_short_conkt != cand.is_sb_node_passing_wire(rr_graph, node_side, track_id)) { - return false; - } + if (is_short_conkt != cand.is_sb_node_passing_wire(rr_graph, node_side, track_id)) { + return false; + } - if (true == is_short_conkt) { - /* Since, both are pass wires, + if (true == is_short_conkt) { + /* Since, both are pass wires, * The two node should be equivalent * we can return here */ - return true; - } + return true; + } - /* Use unsorted/sorted edges */ - std::vector node_in_edges = get_chan_node_in_edges(rr_graph, node_side, track_id); - std::vector cand_node_in_edges = cand.get_chan_node_in_edges(rr_graph, node_side, track_id); + /* Use unsorted/sorted edges */ + std::vector node_in_edges = get_chan_node_in_edges(rr_graph, node_side, track_id); + std::vector cand_node_in_edges = cand.get_chan_node_in_edges(rr_graph, node_side, track_id); - /* For non-passing wires, check driving rr_nodes */ - if (node_in_edges.size() != cand_node_in_edges.size()) { - return false; - } - - VTR_ASSERT(node_in_edges.size() == cand_node_in_edges.size()); - - for (size_t iedge = 0; iedge < node_in_edges.size(); ++iedge) { - RREdgeId src_edge = node_in_edges[iedge]; - RREdgeId src_cand_edge = cand_node_in_edges[iedge]; - RRNodeId src_node = rr_graph.edge_src_node(src_edge); - RRNodeId src_cand_node = rr_graph.edge_src_node(src_cand_edge); - /* node type should be the same */ - if (rr_graph.node_type(src_node) != rr_graph.node_type(src_cand_node)) { - return false; + /* For non-passing wires, check driving rr_nodes */ + if (node_in_edges.size() != cand_node_in_edges.size()) { + return false; } - /* switch type should be the same */ - if (rr_graph.edge_switch(src_edge) != rr_graph.edge_switch(src_cand_edge)) { - return false; + + VTR_ASSERT(node_in_edges.size() == cand_node_in_edges.size()); + + for (size_t iedge = 0; iedge < node_in_edges.size(); ++iedge) { + RREdgeId src_edge = node_in_edges[iedge]; + RREdgeId src_cand_edge = cand_node_in_edges[iedge]; + RRNodeId src_node = rr_graph.edge_src_node(src_edge); + RRNodeId src_cand_node = rr_graph.edge_src_node(src_cand_edge); + /* node type should be the same */ + if (rr_graph.node_type(src_node) != rr_graph.node_type(src_cand_node)) { + return false; + } + /* switch type should be the same */ + if (rr_graph.edge_switch(src_edge) != rr_graph.edge_switch(src_cand_edge)) { + return false; + } + int src_node_id, des_node_id; + enum e_side src_node_side, des_node_side; + this->get_node_side_and_index(rr_graph, src_node, OUT_PORT, src_node_side, src_node_id); + cand.get_node_side_and_index(rr_graph, src_cand_node, OUT_PORT, des_node_side, des_node_id); + if (src_node_id != des_node_id) { + return false; + } + if (src_node_side != des_node_side) { + return false; + } } - int src_node_id, des_node_id; - enum e_side src_node_side, des_node_side; - this->get_node_side_and_index(rr_graph, src_node, OUT_PORT, src_node_side, src_node_id); - cand.get_node_side_and_index(rr_graph, src_cand_node, OUT_PORT, des_node_side, des_node_id); - if (src_node_id != des_node_id) { - return false; - } - if (src_node_side != des_node_side) { - return false; - } - } - - return true; -} + + return true; +} /* check if two ipin_nodes have a similar set of drive_rr_nodes * for each drive_rr_node: @@ -1009,141 +1005,140 @@ bool RRGSB::is_sb_node_mirror(const RRGraph& rr_graph, * 2. each drive_rr_switch should be the same */ bool RRGSB::is_cb_node_mirror(const RRGraph& rr_graph, - const RRGSB& cand, + const RRGSB& cand, const t_rr_type& cb_type, - const e_side& node_side, + const e_side& node_side, const size_t& node_id) const { - /* Ensure rr_nodes are either the output of short-connection or multiplexer */ - RRNodeId node = this->get_ipin_node(node_side, node_id); - RRNodeId cand_node = cand.get_ipin_node(node_side, node_id); + /* Ensure rr_nodes are either the output of short-connection or multiplexer */ + RRNodeId node = this->get_ipin_node(node_side, node_id); + RRNodeId cand_node = cand.get_ipin_node(node_side, node_id); - if ( rr_graph.node_in_edges(node).size() != rr_graph.node_in_edges(cand_node).size() ) { - return false; - } - - std::vector node_in_edges; - for (const RREdgeId& edge : rr_graph.node_in_edges(node)) { - node_in_edges.push_back(edge); - } - - std::vector cand_node_in_edges; - for (const RREdgeId& edge : rr_graph.node_in_edges(cand_node)) { - cand_node_in_edges.push_back(edge); - } - VTR_ASSERT(node_in_edges.size() == cand_node_in_edges.size()); - - for (size_t iedge = 0; iedge < node_in_edges.size(); ++iedge) { - RREdgeId src_edge = node_in_edges[iedge]; - RREdgeId src_cand_edge = cand_node_in_edges[iedge]; - RRNodeId src_node = rr_graph.edge_src_node(src_edge); - RRNodeId src_cand_node = rr_graph.edge_src_node(src_cand_edge); - /* node type should be the same */ - if (rr_graph.node_type(src_node) != rr_graph.node_type(src_cand_node)) { - return false; + if (rr_graph.node_in_edges(node).size() != rr_graph.node_in_edges(cand_node).size()) { + return false; } - /* switch type should be the same */ - if (rr_graph.edge_switch(src_edge)!= rr_graph.edge_switch(src_cand_edge)) { - return false; + + std::vector node_in_edges; + for (const RREdgeId& edge : rr_graph.node_in_edges(node)) { + node_in_edges.push_back(edge); } - int src_node_id, des_node_id; - enum e_side src_node_side, des_node_side; - enum e_side chan_side = get_cb_chan_side(cb_type); - switch (rr_graph.node_type(src_node)) { - case CHANX: - case CHANY: - /* if the drive rr_nodes are routing tracks, find index */ - src_node_id = this->get_chan_node_index(chan_side, src_node); - des_node_id = cand.get_chan_node_index(chan_side, src_cand_node); - break; - case OPIN: - this->get_node_side_and_index(rr_graph, src_node, OUT_PORT, src_node_side, src_node_id); - cand.get_node_side_and_index(rr_graph, src_cand_node, OUT_PORT, des_node_side, des_node_id); - if (src_node_side != des_node_side) { - return false; - } - break; - default: - VTR_LOG("Invalid type of drive_rr_nodes for ipin_node!\n"); - exit(1); + std::vector cand_node_in_edges; + for (const RREdgeId& edge : rr_graph.node_in_edges(cand_node)) { + cand_node_in_edges.push_back(edge); + } + VTR_ASSERT(node_in_edges.size() == cand_node_in_edges.size()); + + for (size_t iedge = 0; iedge < node_in_edges.size(); ++iedge) { + RREdgeId src_edge = node_in_edges[iedge]; + RREdgeId src_cand_edge = cand_node_in_edges[iedge]; + RRNodeId src_node = rr_graph.edge_src_node(src_edge); + RRNodeId src_cand_node = rr_graph.edge_src_node(src_cand_edge); + /* node type should be the same */ + if (rr_graph.node_type(src_node) != rr_graph.node_type(src_cand_node)) { + return false; + } + /* switch type should be the same */ + if (rr_graph.edge_switch(src_edge) != rr_graph.edge_switch(src_cand_edge)) { + return false; + } + + int src_node_id, des_node_id; + enum e_side src_node_side, des_node_side; + enum e_side chan_side = get_cb_chan_side(cb_type); + switch (rr_graph.node_type(src_node)) { + case CHANX: + case CHANY: + /* if the drive rr_nodes are routing tracks, find index */ + src_node_id = this->get_chan_node_index(chan_side, src_node); + des_node_id = cand.get_chan_node_index(chan_side, src_cand_node); + break; + case OPIN: + this->get_node_side_and_index(rr_graph, src_node, OUT_PORT, src_node_side, src_node_id); + cand.get_node_side_and_index(rr_graph, src_cand_node, OUT_PORT, des_node_side, des_node_id); + if (src_node_side != des_node_side) { + return false; + } + break; + default: + VTR_LOG("Invalid type of drive_rr_nodes for ipin_node!\n"); + exit(1); + } + if (src_node_id != des_node_id) { + return false; + } } - if (src_node_id != des_node_id) { - return false; - } - } - return true; -} + return true; +} size_t RRGSB::get_track_id_first_short_connection(const RRGraph& rr_graph, const e_side& node_side) const { - VTR_ASSERT(validate_side(node_side)); + VTR_ASSERT(validate_side(node_side)); - /* Walk through chan_nodes and find the first short connection */ - for (size_t inode = 0; inode < get_chan_width(node_side); ++inode) { - if (true == is_sb_node_passing_wire(rr_graph, node_side, inode)) { - return inode; + /* Walk through chan_nodes and find the first short connection */ + for (size_t inode = 0; inode < get_chan_width(node_side); ++inode) { + if (true == is_sb_node_passing_wire(rr_graph, node_side, inode)) { + return inode; + } } - } - return size_t(-1); + return size_t(-1); } - /************************************************************************ * Internal validators ***********************************************************************/ /* Validate if the number of sides are consistent among internal data arrays ! */ bool RRGSB::validate_num_sides() const { - size_t num_sides = chan_node_direction_.size(); + size_t num_sides = chan_node_direction_.size(); - if ( num_sides != chan_node_.size() ) { - return false; - } + if (num_sides != chan_node_.size()) { + return false; + } - if ( num_sides != ipin_node_.size() ) { - return false; - } + if (num_sides != ipin_node_.size()) { + return false; + } - if ( num_sides != opin_node_.size() ) { - return false; - } + if (num_sides != opin_node_.size()) { + return false; + } - return true; + return true; } /* Check if the side valid in the context: does the switch block have the side? */ bool RRGSB::validate_side(const e_side& side) const { - return (size_t(side) < get_num_sides()); + return (size_t(side) < get_num_sides()); } /* Check the track_id is valid for chan_node_ and chan_node_direction_ */ bool RRGSB::validate_track_id(const e_side& side, const size_t& track_id) const { - if (false == validate_side(side)) { - return false; - } - - return ( ( track_id < chan_node_[size_t(side)].get_chan_width()) - && ( track_id < chan_node_direction_[size_t(side)].size()) ); + if (false == validate_side(side)) { + return false; + } + + return ((track_id < chan_node_[size_t(side)].get_chan_width()) + && (track_id < chan_node_direction_[size_t(side)].size())); } /* Check the opin_node_id is valid for opin_node_ and opin_node_grid_side_ */ bool RRGSB::validate_opin_node_id(const e_side& side, const size_t& node_id) const { - if (false == validate_side(side)) { - return false; - } - return (node_id < opin_node_[size_t(side)].size()); + if (false == validate_side(side)) { + return false; + } + return (node_id < opin_node_[size_t(side)].size()); } /* Check the ipin_node_id is valid for opin_node_ and opin_node_grid_side_ */ bool RRGSB::validate_ipin_node_id(const e_side& side, const size_t& node_id) const { - if (false == validate_side(side)) { - return false; - } - return (node_id < ipin_node_[size_t(side)].size()); + if (false == validate_side(side)) { + return false; + } + return (node_id < ipin_node_[size_t(side)].size()); } bool RRGSB::validate_cb_type(const t_rr_type& cb_type) const { - return ( (CHANX == cb_type) || (CHANY == cb_type) ); + return ((CHANX == cb_type) || (CHANY == cb_type)); } } /* End namespace openfpga*/ diff --git a/vpr/src/tileable_rr_graph/tileable_chan_details_builder.cpp b/vpr/src/tileable_rr_graph/tileable_chan_details_builder.cpp index 2436d170c6d..d2afce3edd7 100644 --- a/vpr/src/tileable_rr_graph/tileable_chan_details_builder.cpp +++ b/vpr/src/tileable_rr_graph/tileable_chan_details_builder.cpp @@ -26,85 +26,85 @@ namespace openfpga { * therefore, we assign tracks one by one until we meet the frequency requirement * In this way, we can assign the number of tracks with repect to frequency ***********************************************************************/ -std::vector get_num_tracks_per_seg_type(const size_t& chan_width, - const std::vector& segment_inf, +std::vector get_num_tracks_per_seg_type(const size_t& chan_width, + const std::vector& segment_inf, const bool& use_full_seg_groups) { - std::vector result; - std::vector demand; - /* Make sure a clean start */ - result.resize(segment_inf.size()); - demand.resize(segment_inf.size()); + std::vector result; + std::vector demand; + /* Make sure a clean start */ + result.resize(segment_inf.size()); + demand.resize(segment_inf.size()); - /* Scale factor so we can divide by any length + /* Scale factor so we can divide by any length * and still use integers */ - /* Get the sum of frequency */ - size_t scale = 1; - size_t freq_sum = 0; - for (size_t iseg = 0; iseg < segment_inf.size(); ++iseg) { - scale *= segment_inf[iseg].length; - freq_sum += segment_inf[iseg].frequency; - } - size_t reduce = scale * freq_sum; - - /* Init assignments to 0 and set the demand values */ - /* Get the fraction of each segment type considering the frequency: + /* Get the sum of frequency */ + size_t scale = 1; + size_t freq_sum = 0; + for (size_t iseg = 0; iseg < segment_inf.size(); ++iseg) { + scale *= segment_inf[iseg].length; + freq_sum += segment_inf[iseg].frequency; + } + size_t reduce = scale * freq_sum; + + /* Init assignments to 0 and set the demand values */ + /* Get the fraction of each segment type considering the frequency: * num_track_per_seg = chan_width * (freq_of_seg / sum_freq) */ - for (size_t iseg = 0; iseg < segment_inf.size(); ++iseg) { - result[iseg] = 0; - demand[iseg] = scale * chan_width * segment_inf[iseg].frequency; - if (true == use_full_seg_groups) { - demand[iseg] /= segment_inf[iseg].length; - } - } - - /* check if the sum of num_tracks, matches the chan_width */ - /* Keep assigning tracks until we use them up */ - size_t assigned = 0; - size_t size = 0; - size_t imax = 0; - while (assigned < chan_width) { - /* Find current maximum demand */ - double max = 0; for (size_t iseg = 0; iseg < segment_inf.size(); ++iseg) { - if (demand[iseg] > max) { - imax = iseg; - } - max = std::max(demand[iseg], max); + result[iseg] = 0; + demand[iseg] = scale * chan_width * segment_inf[iseg].frequency; + if (true == use_full_seg_groups) { + demand[iseg] /= segment_inf[iseg].length; + } } - /* Assign tracks to the type and reduce the types demand */ - size = (use_full_seg_groups ? segment_inf[imax].length : 1); - demand[imax] -= reduce; - result[imax] += size; - assigned += size; - } + /* check if the sum of num_tracks, matches the chan_width */ + /* Keep assigning tracks until we use them up */ + size_t assigned = 0; + size_t size = 0; + size_t imax = 0; + while (assigned < chan_width) { + /* Find current maximum demand */ + double max = 0; + for (size_t iseg = 0; iseg < segment_inf.size(); ++iseg) { + if (demand[iseg] > max) { + imax = iseg; + } + max = std::max(demand[iseg], max); + } + + /* Assign tracks to the type and reduce the types demand */ + size = (use_full_seg_groups ? segment_inf[imax].length : 1); + demand[imax] -= reduce; + result[imax] += size; + assigned += size; + } - /* Undo last assignment if we were closer to goal without it */ - if ((assigned - chan_width) > (size / 2)) { - result[imax] -= size; - } + /* Undo last assignment if we were closer to goal without it */ + if ((assigned - chan_width) > (size / 2)) { + result[imax] -= size; + } - return result; -} + return result; +} /************************************************************************ * Adapt the number of channel width to a tileable routing architecture ***********************************************************************/ -int adapt_to_tileable_route_chan_width(const int& chan_width, +int adapt_to_tileable_route_chan_width(const int& chan_width, const std::vector& segment_infs) { - int tileable_chan_width = 0; - - /* Estimate the number of segments per type by the given ChanW*/ - std::vector num_tracks_per_seg_type = get_num_tracks_per_seg_type(chan_width, - segment_infs, - true); /* Force to use the full segment group */ - /* Sum-up the number of tracks */ - for (size_t iseg = 0; iseg < num_tracks_per_seg_type.size(); ++iseg) { - tileable_chan_width += num_tracks_per_seg_type[iseg]; - } - - return tileable_chan_width; + int tileable_chan_width = 0; + + /* Estimate the number of segments per type by the given ChanW*/ + std::vector num_tracks_per_seg_type = get_num_tracks_per_seg_type(chan_width, + segment_infs, + true); /* Force to use the full segment group */ + /* Sum-up the number of tracks */ + for (size_t iseg = 0; iseg < num_tracks_per_seg_type.size(); ++iseg) { + tileable_chan_width += num_tracks_per_seg_type[iseg]; + } + + return tileable_chan_width; } /************************************************************************ @@ -163,72 +163,72 @@ int adapt_to_tileable_route_chan_width(const int& chan_width, ***********************************************************************/ ChanNodeDetails build_unidir_chan_node_details(const size_t& chan_width, const size_t& max_seg_length, - const bool& force_start, - const bool& force_end, + const bool& force_start, + const bool& force_end, const std::vector& segment_inf) { - ChanNodeDetails chan_node_details; - size_t actual_chan_width = find_unidir_routing_channel_width(chan_width); - VTR_ASSERT(0 == actual_chan_width % 2); - - /* Reserve channel width */ - chan_node_details.reserve(chan_width); - /* Return if zero width is forced */ - if (0 == actual_chan_width) { - return chan_node_details; - } - - /* Find the number of segments required by each group */ - std::vector num_tracks = get_num_tracks_per_seg_type(actual_chan_width / 2, segment_inf, false); - - /* Add node to ChanNodeDetails */ - size_t cur_track = 0; - for (size_t iseg = 0; iseg < segment_inf.size(); ++iseg) { - /* segment length will be set to maxium segment length if this is a longwire */ - size_t seg_len = segment_inf[iseg].length; - if (true == segment_inf[iseg].longline) { - seg_len = max_seg_length; - } - for (size_t itrack = 0; itrack < num_tracks[iseg]; ++itrack) { - bool seg_start = false; - bool seg_end = false; - /* Every first track of a group of Length-N wires, we set a starting point */ - if (0 == itrack % seg_len) { - seg_start = true; - } - /* Every last track of a group of Length-N wires or this is the last track in this group, we set an ending point */ - if ( (seg_len - 1 == itrack % seg_len) - || (itrack == num_tracks[iseg] - 1) ) { - seg_end = true; - } - /* Since this is a unidirectional routing architecture, + ChanNodeDetails chan_node_details; + size_t actual_chan_width = find_unidir_routing_channel_width(chan_width); + VTR_ASSERT(0 == actual_chan_width % 2); + + /* Reserve channel width */ + chan_node_details.reserve(chan_width); + /* Return if zero width is forced */ + if (0 == actual_chan_width) { + return chan_node_details; + } + + /* Find the number of segments required by each group */ + std::vector num_tracks = get_num_tracks_per_seg_type(actual_chan_width / 2, segment_inf, false); + + /* Add node to ChanNodeDetails */ + size_t cur_track = 0; + for (size_t iseg = 0; iseg < segment_inf.size(); ++iseg) { + /* segment length will be set to maxium segment length if this is a longwire */ + size_t seg_len = segment_inf[iseg].length; + if (true == segment_inf[iseg].longline) { + seg_len = max_seg_length; + } + for (size_t itrack = 0; itrack < num_tracks[iseg]; ++itrack) { + bool seg_start = false; + bool seg_end = false; + /* Every first track of a group of Length-N wires, we set a starting point */ + if (0 == itrack % seg_len) { + seg_start = true; + } + /* Every last track of a group of Length-N wires or this is the last track in this group, we set an ending point */ + if ((seg_len - 1 == itrack % seg_len) + || (itrack == num_tracks[iseg] - 1)) { + seg_end = true; + } + /* Since this is a unidirectional routing architecture, * Add a pair of tracks, 1 INC track and 1 DEC track */ - chan_node_details.add_track(cur_track, Direction::INC, iseg, seg_len, seg_start, seg_end); - cur_track++; - chan_node_details.add_track(cur_track, Direction::DEC, iseg, seg_len, seg_start, seg_end); - cur_track++; - } - } - /* Check if all the tracks have been satisified */ - VTR_ASSERT(cur_track == actual_chan_width); - - /* If this is on the border of a device/heterogeneous blocks, segments should start/end */ - if (true == force_start) { - /* INC should all start */ - chan_node_details.set_tracks_start(Direction::INC); - /* DEC should all end */ - chan_node_details.set_tracks_end(Direction::DEC); - } - - /* If this is on the border of a device/heterogeneous blocks, segments should start/end */ - if (true == force_end) { - /* INC should all end */ - chan_node_details.set_tracks_end(Direction::INC); - /* DEC should all start */ - chan_node_details.set_tracks_start(Direction::DEC); - } - - return chan_node_details; + chan_node_details.add_track(cur_track, Direction::INC, iseg, seg_len, seg_start, seg_end); + cur_track++; + chan_node_details.add_track(cur_track, Direction::DEC, iseg, seg_len, seg_start, seg_end); + cur_track++; + } + } + /* Check if all the tracks have been satisified */ + VTR_ASSERT(cur_track == actual_chan_width); + + /* If this is on the border of a device/heterogeneous blocks, segments should start/end */ + if (true == force_start) { + /* INC should all start */ + chan_node_details.set_tracks_start(Direction::INC); + /* DEC should all end */ + chan_node_details.set_tracks_end(Direction::DEC); + } + + /* If this is on the border of a device/heterogeneous blocks, segments should start/end */ + if (true == force_end) { + /* INC should all end */ + chan_node_details.set_tracks_end(Direction::INC); + /* DEC should all start */ + chan_node_details.set_tracks_start(Direction::DEC); + } + + return chan_node_details; } } /* end namespace openfpga */ diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp index 43c41de5416..198c2fc5e1c 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp @@ -72,126 +72,127 @@ namespace openfpga { // external functions: in vpr/src/route/rr_graph.cpp extern std::vector> alloc_and_load_actual_fc(const std::vector& types, - const int max_pins, - const std::vector& segment_inf, - - const int* sets_per_seg_type, - const int max_chan_width, - const e_fc_type fc_type, - const enum e_directionality directionality, - bool* Fc_clipped); -extern t_clb_to_clb_directs* alloc_and_load_clb_to_clb_directs(const t_direct_inf* directs, const int num_directs, int delayless_switch); + const int max_pins, + const std::vector& segment_inf, + + const int* sets_per_seg_type, + const int max_chan_width, + const e_fc_type fc_type, + const enum e_directionality directionality, + bool* Fc_clipped); +extern t_clb_to_clb_directs* alloc_and_load_clb_to_clb_directs(const t_direct_inf* directs, const int num_directs, int delayless_switch); extern void alloc_and_load_rr_switch_inf(const int num_arch_switches, - const float R_minW_nmos, - const float R_minW_pmos, - const int wire_to_arch_ipin_switch, - int* wire_to_rr_ipin_switch); + const float R_minW_nmos, + const float R_minW_pmos, + const int wire_to_arch_ipin_switch, + int* wire_to_rr_ipin_switch); extern void rr_graph_externals(const std::vector& segment_inf, - int wire_to_rr_ipin_switch, - enum e_base_cost_type base_cost_type); + int wire_to_rr_ipin_switch, + enum e_base_cost_type base_cost_type); void build_tileable_unidir_rr_graph(const std::vector& types, const DeviceGrid& grids, const t_chan_width& chan_width, - const e_switch_block_type& sb_type, const int& Fs, - const e_switch_block_type& sb_subtype, const int& subFs, + const e_switch_block_type& sb_type, + const int& Fs, + const e_switch_block_type& sb_subtype, + const int& subFs, const std::vector& segment_inf, const int& delayless_switch, const int& wire_to_arch_ipin_switch, const float R_minW_nmos, const float R_minW_pmos, const enum e_base_cost_type& base_cost_type, - const t_direct_inf *directs, + const t_direct_inf* directs, const int& num_directs, int* wire_to_rr_ipin_switch, const bool& through_channel, const bool& wire_opposite_side, - int *Warnings) { + int* Warnings) { + vtr::ScopedStartFinishTimer timer("Build tileable routing resource graph"); - vtr::ScopedStartFinishTimer timer("Build tileable routing resource graph"); + /* Reset warning flag */ + *Warnings = RR_GRAPH_NO_WARN; - /* Reset warning flag */ - *Warnings = RR_GRAPH_NO_WARN; + /* Create a matrix of grid */ + /* Create a vector of channel width, we support X-direction and Y-direction has different W */ + vtr::Point device_chan_width(chan_width.x_max, chan_width.y_max); - /* Create a matrix of grid */ - /* Create a vector of channel width, we support X-direction and Y-direction has different W */ - vtr::Point device_chan_width(chan_width.x_max, chan_width.y_max); + VTR_LOG("X-direction routing channel width is %lu\n", device_chan_width.x()); + VTR_LOG("Y-direction routing channel width is %lu\n", device_chan_width.y()); - VTR_LOG("X-direction routing channel width is %lu\n", device_chan_width.x()); - VTR_LOG("Y-direction routing channel width is %lu\n", device_chan_width.y()); + /* Get a mutable device ctx so that we have a mutable rr_graph */ + DeviceContext& device_ctx = g_vpr_ctx.mutable_device(); - /* Get a mutable device ctx so that we have a mutable rr_graph */ - DeviceContext& device_ctx = g_vpr_ctx.mutable_device(); - - /* The number of segments are in general small, reserve segments may not bring + /* The number of segments are in general small, reserve segments may not bring * significant memory efficiency */ - device_ctx.rr_graph_builder.reserve_segments(segment_inf.size()); - /* Create the segments */ - for (size_t iseg = 0; iseg < segment_inf.size(); ++iseg) { - device_ctx.rr_graph_builder.add_rr_segment(segment_inf[iseg]); - } + device_ctx.rr_graph_builder.reserve_segments(segment_inf.size()); + /* Create the segments */ + for (size_t iseg = 0; iseg < segment_inf.size(); ++iseg) { + device_ctx.rr_graph_builder.add_rr_segment(segment_inf[iseg]); + } - /* TODO: Load architecture switch to rr_graph switches + /* TODO: Load architecture switch to rr_graph switches * Draft the switches as internal data of RRGraph object * These are temporary switches copied from arch switches * We use them to build the edges * We will reset all the switches in the function * alloc_and_load_rr_switch_inf() */ - /* TODO: Spot the switch id in the architecture switch list */ - RRSwitchId wire_to_ipin_rr_switch = RRSwitchId::INVALID(); - RRSwitchId delayless_rr_switch = RRSwitchId::INVALID(); - - device_ctx.rr_graph_builder.reserve_switches(device_ctx.num_arch_switches); - /* Create the switches */ - for (int iswitch = 0; iswitch < device_ctx.num_arch_switches; ++iswitch) { - const t_rr_switch_inf& temp_rr_switch = create_rr_switch_from_arch_switch(iswitch, R_minW_nmos, R_minW_pmos); - RRSwitchId rr_switch = device_ctx.rr_graph_builder.add_rr_switch(temp_rr_switch); - if (iswitch == wire_to_arch_ipin_switch) { - wire_to_ipin_rr_switch = rr_switch; - } - if (iswitch == delayless_switch) { - delayless_rr_switch = rr_switch; + /* TODO: Spot the switch id in the architecture switch list */ + RRSwitchId wire_to_ipin_rr_switch = RRSwitchId::INVALID(); + RRSwitchId delayless_rr_switch = RRSwitchId::INVALID(); + + device_ctx.rr_graph_builder.reserve_switches(device_ctx.num_arch_switches); + /* Create the switches */ + for (int iswitch = 0; iswitch < device_ctx.num_arch_switches; ++iswitch) { + const t_rr_switch_inf& temp_rr_switch = create_rr_switch_from_arch_switch(iswitch, R_minW_nmos, R_minW_pmos); + RRSwitchId rr_switch = device_ctx.rr_graph_builder.add_rr_switch(temp_rr_switch); + if (iswitch == wire_to_arch_ipin_switch) { + wire_to_ipin_rr_switch = rr_switch; + } + if (iswitch == delayless_switch) { + delayless_rr_switch = rr_switch; + } } - } - // NYI - #if 0 +// NYI +#if 0 /* Validate the special switches */ VTR_ASSERT(true == device_ctx.rr_graph_builder.valid_switch_id(wire_to_ipin_rr_switch)); VTR_ASSERT(true == device_ctx.rr_graph_builder.valid_switch_id(delayless_rr_switch)); - #endif +#endif - /* A temp data about the driver switch ids for each rr_node */ - vtr::vector rr_node_driver_switches; + /* A temp data about the driver switch ids for each rr_node */ + vtr::vector rr_node_driver_switches; - /* A temp data about the track ids for each CHANX and CHANY rr_node */ - std::map> rr_node_track_ids; + /* A temp data about the track ids for each CHANX and CHANY rr_node */ + std::map> rr_node_track_ids; - /************************ + /************************ * Allocate the rr_nodes ************************/ - alloc_tileable_rr_graph_nodes(device_ctx.rr_graph_builder, - rr_node_driver_switches, - grids, - device_chan_width, - segment_inf, - through_channel); - - /************************ + alloc_tileable_rr_graph_nodes(device_ctx.rr_graph_builder, + rr_node_driver_switches, + grids, + device_chan_width, + segment_inf, + through_channel); + + /************************ * Create all the rr_nodes ************************/ - create_tileable_rr_graph_nodes(device_ctx.rr_graph, - device_ctx.rr_graph_builder, - rr_node_driver_switches, - rr_node_track_ids, - grids, - device_chan_width, - segment_inf, - wire_to_ipin_rr_switch, - delayless_rr_switch, - through_channel); - - /************************************************************************ + create_tileable_rr_graph_nodes(device_ctx.rr_graph, + device_ctx.rr_graph_builder, + rr_node_driver_switches, + rr_node_track_ids, + grids, + device_chan_width, + segment_inf, + wire_to_ipin_rr_switch, + delayless_rr_switch, + through_channel); + + /************************************************************************ * Create the connectivity of OPINs * a. Evenly assign connections to OPINs to routing tracks * b. the connection pattern should be same across the fabric @@ -200,52 +201,52 @@ void build_tileable_unidir_rr_graph(const std::vector& typ * a. Evenly assign connections from routing tracks to IPINs * b. the connection pattern should be same across the fabric ***********************************************************************/ - /* Global routing uses a single longwire track */ - int max_chan_width = find_unidir_routing_channel_width(chan_width.max); - VTR_ASSERT(max_chan_width > 0); - - /* get maximum number of pins across all blocks */ - int max_pins = types[0].num_pins; - for (const auto& type : types) { - if (is_empty_type(&type)) { - continue; - } - - if (type.num_pins > max_pins) { - max_pins = type.num_pins; + /* Global routing uses a single longwire track */ + int max_chan_width = find_unidir_routing_channel_width(chan_width.max); + VTR_ASSERT(max_chan_width > 0); + + /* get maximum number of pins across all blocks */ + int max_pins = types[0].num_pins; + for (const auto& type : types) { + if (is_empty_type(&type)) { + continue; + } + + if (type.num_pins > max_pins) { + max_pins = type.num_pins; + } } - } - /* Fc assignment still uses the old function from VPR. + /* Fc assignment still uses the old function from VPR. * Should use tileable version so that we have can have full control */ - std::vector num_tracks = get_num_tracks_per_seg_type(max_chan_width / 2, segment_inf, false); - int* sets_per_seg_type = (int*)vtr::malloc(sizeof(int) * segment_inf.size()); - VTR_ASSERT(num_tracks.size() == segment_inf.size()); - for (size_t iseg = 0; iseg < num_tracks.size(); ++iseg) { - sets_per_seg_type[iseg] = num_tracks[iseg]; - } + std::vector num_tracks = get_num_tracks_per_seg_type(max_chan_width / 2, segment_inf, false); + int* sets_per_seg_type = (int*)vtr::malloc(sizeof(int) * segment_inf.size()); + VTR_ASSERT(num_tracks.size() == segment_inf.size()); + for (size_t iseg = 0; iseg < num_tracks.size(); ++iseg) { + sets_per_seg_type[iseg] = num_tracks[iseg]; + } - bool Fc_clipped = false; - /* [0..num_types-1][0..num_pins-1] */ - std::vector> Fc_in; - Fc_in = alloc_and_load_actual_fc(types, max_pins, segment_inf, sets_per_seg_type, max_chan_width, - e_fc_type::IN, UNI_DIRECTIONAL, &Fc_clipped); - if (Fc_clipped) { - *Warnings |= RR_GRAPH_WARN_FC_CLIPPED; - } + bool Fc_clipped = false; + /* [0..num_types-1][0..num_pins-1] */ + std::vector> Fc_in; + Fc_in = alloc_and_load_actual_fc(types, max_pins, segment_inf, sets_per_seg_type, max_chan_width, + e_fc_type::IN, UNI_DIRECTIONAL, &Fc_clipped); + if (Fc_clipped) { + *Warnings |= RR_GRAPH_WARN_FC_CLIPPED; + } - Fc_clipped = false; - /* [0..num_types-1][0..num_pins-1] */ - std::vector> Fc_out; - Fc_out = alloc_and_load_actual_fc(types, max_pins, segment_inf, sets_per_seg_type, max_chan_width, - e_fc_type::OUT, UNI_DIRECTIONAL, &Fc_clipped); + Fc_clipped = false; + /* [0..num_types-1][0..num_pins-1] */ + std::vector> Fc_out; + Fc_out = alloc_and_load_actual_fc(types, max_pins, segment_inf, sets_per_seg_type, max_chan_width, + e_fc_type::OUT, UNI_DIRECTIONAL, &Fc_clipped); - if (Fc_clipped) { - *Warnings |= RR_GRAPH_WARN_FC_CLIPPED; - } + if (Fc_clipped) { + *Warnings |= RR_GRAPH_WARN_FC_CLIPPED; + } - /************************************************************************ + /************************************************************************ * Build the connections tile by tile: * We classify rr_nodes into a general switch block (GSB) data structure * where we create edges to each rr_nodes in the GSB with respect to @@ -253,34 +254,34 @@ void build_tileable_unidir_rr_graph(const std::vector& typ * In addition, we will also handle direct-connections: * Add edges that bridge OPINs and IPINs to the rr_graph ***********************************************************************/ - /* Create edges for a tileable rr_graph */ - build_rr_graph_edges(device_ctx.rr_graph, - rr_node_driver_switches, - grids, - device_chan_width, - segment_inf, - Fc_in, Fc_out, - sb_type, Fs, sb_subtype, subFs, - wire_opposite_side); - - /************************************************************************ + /* Create edges for a tileable rr_graph */ + build_rr_graph_edges(device_ctx.rr_graph, + rr_node_driver_switches, + grids, + device_chan_width, + segment_inf, + Fc_in, Fc_out, + sb_type, Fs, sb_subtype, subFs, + wire_opposite_side); + + /************************************************************************ * Build direction connection lists * TODO: use tile direct builder ***********************************************************************/ - /* Create data structure of direct-connections */ - t_clb_to_clb_directs* clb_to_clb_directs = NULL; - if (num_directs > 0) { - clb_to_clb_directs = alloc_and_load_clb_to_clb_directs(directs, num_directs, delayless_switch); - } - std::vector arch_directs; - std::vector clb2clb_directs; - for (int idirect = 0; idirect < num_directs; ++idirect) { - arch_directs.push_back(directs[idirect]); - clb2clb_directs.push_back(clb_to_clb_directs[idirect]); - } + /* Create data structure of direct-connections */ + t_clb_to_clb_directs* clb_to_clb_directs = NULL; + if (num_directs > 0) { + clb_to_clb_directs = alloc_and_load_clb_to_clb_directs(directs, num_directs, delayless_switch); + } + std::vector arch_directs; + std::vector clb2clb_directs; + for (int idirect = 0; idirect < num_directs; ++idirect) { + arch_directs.push_back(directs[idirect]); + clb2clb_directs.push_back(clb_to_clb_directs[idirect]); + } - build_rr_graph_direct_connections(device_ctx.rr_graph, grids, delayless_rr_switch, - arch_directs, clb2clb_directs); + build_rr_graph_direct_connections(device_ctx.rr_graph, grids, delayless_rr_switch, + arch_directs, clb2clb_directs); //NYI #if 0 @@ -290,12 +291,12 @@ void build_tileable_unidir_rr_graph(const std::vector& typ device_ctx.rr_graph.rebuild_node_edges(); #endif - /* Allocate and load routing resource switches, which are derived from the switches from the architecture file, + /* Allocate and load routing resource switches, which are derived from the switches from the architecture file, * based on their fanin in the rr graph. This routine also adjusts the rr nodes to point to these new rr switches */ - alloc_and_load_rr_switch_inf(device_ctx.num_arch_switches, R_minW_nmos, R_minW_pmos, wire_to_arch_ipin_switch, wire_to_rr_ipin_switch); + alloc_and_load_rr_switch_inf(device_ctx.num_arch_switches, R_minW_nmos, R_minW_pmos, wire_to_arch_ipin_switch, wire_to_rr_ipin_switch); - /* Save the channel widths for the newly constructed graph */ - device_ctx.chan_width = chan_width; + /* Save the channel widths for the newly constructed graph */ + device_ctx.chan_width = chan_width; //NYI #if 0 @@ -303,49 +304,48 @@ void build_tileable_unidir_rr_graph(const std::vector& typ device_ctx.rr_node_track_ids = rr_node_track_ids; #endif - /************************************************************************ + /************************************************************************ * Allocate external data structures * a. cost_index * b. RC tree ***********************************************************************/ - rr_graph_externals(segment_inf, - *wire_to_rr_ipin_switch, base_cost_type); + rr_graph_externals(segment_inf, + *wire_to_rr_ipin_switch, base_cost_type); - /* Rebuild the link between RRGraph node and segments + /* Rebuild the link between RRGraph node and segments * Should be called only AFTER the function * rr_graph_externals() */ - for (const RRNodeId& inode : device_ctx.rr_graph.nodes()) { - if ( (CHANX != device_ctx.rr_graph.node_type(inode)) - && (CHANY != device_ctx.rr_graph.node_type(inode)) ) { - continue; - } + for (const RRNodeId& inode : device_ctx.rr_graph.nodes()) { + if ((CHANX != device_ctx.rr_graph.node_type(inode)) + && (CHANY != device_ctx.rr_graph.node_type(inode))) { + continue; + } //NYI #if 0 RRIndexedDataId irc_data = device_ctx.rr_graph.node_cost_index(inode); short iseg = device_ctx.rr_indexed_data[irc_data].seg_index; device_ctx.rr_graph_builder.set_node_segment(inode, RRSegmentId(iseg)); // NYI #endif + } - } - - /************************************************************************ + /************************************************************************ * Sanitizer for the rr_graph, check connectivities of rr_nodes ***********************************************************************/ - /* Essential check for rr_graph, build look-up and */ - if (false == device_ctx.rr_graph_builder.validate()) { - /* Error out if built-in validator of rr_graph fails */ - vpr_throw(VPR_ERROR_ROUTE, - __FILE__, - __LINE__, - "Fundamental errors occurred when validating rr_graph object!\n"); - } + /* Essential check for rr_graph, build look-up and */ + if (false == device_ctx.rr_graph_builder.validate()) { + /* Error out if built-in validator of rr_graph fails */ + vpr_throw(VPR_ERROR_ROUTE, + __FILE__, + __LINE__, + "Fundamental errors occurred when validating rr_graph object!\n"); + } - check_rr_graph(GRAPH_UNIDIR, grids, types); + check_rr_graph(GRAPH_UNIDIR, grids, types); - // NYI - // vpr integration: DeviceContext does not provide direct RRGraph access - // we can skip it since check_rr_graph(GRAPH_UNDIR, GRIDS, TYPES) has been called above + // NYI + // vpr integration: DeviceContext does not provide direct RRGraph access + // we can skip it since check_rr_graph(GRAPH_UNDIR, GRIDS, TYPES) has been called above #if 0 /* Error out if advanced checker of rr_graph fails */ if (false == check_rr_graph(device_ctx.rr_graph)) { @@ -357,14 +357,14 @@ void build_tileable_unidir_rr_graph(const std::vector& typ } #endif - /************************************************************************ + /************************************************************************ * Free all temp stucts ***********************************************************************/ - free(sets_per_seg_type); + free(sets_per_seg_type); - if (nullptr != clb_to_clb_directs) { - free(clb_to_clb_directs); - } + if (nullptr != clb_to_clb_directs) { + free(clb_to_clb_directs); + } } } /* end namespace openfpga */ diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp index fd2d4db62d8..3252bd412c9 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp @@ -22,59 +22,57 @@ namespace openfpga { * Build the edges for all the SOURCE and SINKs nodes: * 1. create edges between SOURCE and OPINs ***********************************************************************/ -static -void build_rr_graph_edges_for_source_nodes(RRGraph& rr_graph, - const vtr::vector& rr_node_driver_switches, - const DeviceGrid& grids) { - for (const RRNodeId& node : rr_graph.nodes()) { - /* Bypass all the non OPIN nodes */ - if (OPIN != rr_graph.node_type(node)) { - continue; +static void build_rr_graph_edges_for_source_nodes(RRGraph& rr_graph, + const vtr::vector& rr_node_driver_switches, + const DeviceGrid& grids) { + for (const RRNodeId& node : rr_graph.nodes()) { + /* Bypass all the non OPIN nodes */ + if (OPIN != rr_graph.node_type(node)) { + continue; + } + /* Now, we have an OPIN node, we get the source node index */ + short xlow = rr_graph.node_xlow(node); + short ylow = rr_graph.node_ylow(node); + short src_node_class_num = get_grid_pin_class_index(grids[xlow][ylow], + rr_graph.node_pin_num(node)); + + /* Create edges between SOURCE and OPINs */ + const RRNodeId& src_node = rr_graph.find_node(xlow - grids[xlow][ylow].width_offset, + ylow - grids[xlow][ylow].height_offset, + SOURCE, src_node_class_num); + VTR_ASSERT(true == rr_graph.valid_node_id(src_node)); + + /* add edges to the src_node */ + rr_graph.create_edge(src_node, node, rr_node_driver_switches[node]); } - /* Now, we have an OPIN node, we get the source node index */ - short xlow = rr_graph.node_xlow(node); - short ylow = rr_graph.node_ylow(node); - short src_node_class_num = get_grid_pin_class_index(grids[xlow][ylow], - rr_graph.node_pin_num(node)); - - /* Create edges between SOURCE and OPINs */ - const RRNodeId& src_node = rr_graph.find_node(xlow - grids[xlow][ylow].width_offset, - ylow - grids[xlow][ylow].height_offset, - SOURCE, src_node_class_num); - VTR_ASSERT(true == rr_graph.valid_node_id(src_node)); - - /* add edges to the src_node */ - rr_graph.create_edge(src_node, node, rr_node_driver_switches[node]); - } } /************************************************************************ * Build the edges for all the SINKs nodes: * 1. create edges between IPINs and SINKs ***********************************************************************/ -static -void build_rr_graph_edges_for_sink_nodes(RRGraph& rr_graph, - const vtr::vector& rr_node_driver_switches, - const DeviceGrid& grids) { - for (const RRNodeId& node : rr_graph.nodes()) { - /* Bypass all the non IPIN nodes */ - if (IPIN != rr_graph.node_type(node)) { - continue; +static void build_rr_graph_edges_for_sink_nodes(RRGraph& rr_graph, + const vtr::vector& rr_node_driver_switches, + const DeviceGrid& grids) { + for (const RRNodeId& node : rr_graph.nodes()) { + /* Bypass all the non IPIN nodes */ + if (IPIN != rr_graph.node_type(node)) { + continue; + } + /* Now, we have an OPIN node, we get the source node index */ + short xlow = rr_graph.node_xlow(node); + short ylow = rr_graph.node_ylow(node); + short sink_node_class_num = get_grid_pin_class_index(grids[xlow][ylow], + rr_graph.node_pin_num(node)); + /* 1. create edges between IPINs and SINKs */ + const RRNodeId& sink_node = rr_graph.find_node(xlow - grids[xlow][ylow].width_offset, + ylow - grids[xlow][ylow].height_offset, + SINK, sink_node_class_num); + VTR_ASSERT(true == rr_graph.valid_node_id(sink_node)); + + /* add edges to connect the IPIN node to SINK nodes */ + rr_graph.create_edge(node, sink_node, rr_node_driver_switches[sink_node]); } - /* Now, we have an OPIN node, we get the source node index */ - short xlow = rr_graph.node_xlow(node); - short ylow = rr_graph.node_ylow(node); - short sink_node_class_num = get_grid_pin_class_index(grids[xlow][ylow], - rr_graph.node_pin_num(node)); - /* 1. create edges between IPINs and SINKs */ - const RRNodeId& sink_node = rr_graph.find_node(xlow - grids[xlow][ylow].width_offset, - ylow - grids[xlow][ylow].height_offset, - SINK, sink_node_class_num); - VTR_ASSERT(true == rr_graph.valid_node_id(sink_node)); - - /* add edges to connect the IPIN node to SINK nodes */ - rr_graph.create_edge(node, sink_node, rr_node_driver_switches[sink_node]); - } } /************************************************************************ @@ -87,84 +85,85 @@ void build_rr_graph_edges_for_sink_nodes(RRGraph& rr_graph, * 2. create edges between OPINs, CHANX and CHANY (connections inside switch blocks) * 3. create edges between OPINs and IPINs (direct-connections) ***********************************************************************/ -void build_rr_graph_edges(RRGraph& rr_graph, +void build_rr_graph_edges(RRGraph& rr_graph, const vtr::vector& rr_node_driver_switches, const DeviceGrid& grids, - const vtr::Point& device_chan_width, + const vtr::Point& device_chan_width, const std::vector& segment_inf, const std::vector>& Fc_in, const std::vector>& Fc_out, - const e_switch_block_type& sb_type, const int& Fs, - const e_switch_block_type& sb_subtype, const int& subFs, + const e_switch_block_type& sb_type, + const int& Fs, + const e_switch_block_type& sb_subtype, + const int& subFs, const bool& wire_opposite_side) { - - /* Create edges for SOURCE and SINK nodes for a tileable rr_graph */ - build_rr_graph_edges_for_source_nodes(rr_graph, rr_node_driver_switches, grids); - build_rr_graph_edges_for_sink_nodes(rr_graph, rr_node_driver_switches, grids); - - vtr::Point gsb_range(grids.width() - 2, grids.height() - 2); - - /* Go Switch Block by Switch Block */ - for (size_t ix = 0; ix <= gsb_range.x(); ++ix) { - for (size_t iy = 0; iy <= gsb_range.y(); ++iy) { - //vpr_printf(TIO_MESSAGE_INFO, "Building edges for GSB[%lu][%lu]\n", ix, iy); - - vtr::Point gsb_coord(ix, iy); - /* Create a GSB object */ - const RRGSB& rr_gsb = build_one_tileable_rr_gsb(grids, rr_graph, - device_chan_width, segment_inf, - gsb_coord); - - /* adapt the track_to_ipin_lookup for the GSB nodes */ - t_track2pin_map track2ipin_map; /* [0..track_gsb_side][0..num_tracks][ipin_indices] */ - track2ipin_map = build_gsb_track_to_ipin_map(rr_graph, rr_gsb, grids, segment_inf, Fc_in); - - /* adapt the opin_to_track_map for the GSB nodes */ - t_pin2track_map opin2track_map; /* [0..gsb_side][0..num_opin_node][track_indices] */ - opin2track_map = build_gsb_opin_to_track_map(rr_graph, rr_gsb, grids, segment_inf, Fc_out); - - /* adapt the switch_block_conn for the GSB nodes */ - t_track2track_map sb_conn; /* [0..from_gsb_side][0..chan_width-1][track_indices] */ - sb_conn = build_gsb_track_to_track_map(rr_graph, rr_gsb, - sb_type, Fs, sb_subtype, subFs, wire_opposite_side, - segment_inf); - - /* Build edges for a GSB */ - build_edges_for_one_tileable_rr_gsb(rr_graph, rr_gsb, - track2ipin_map, opin2track_map, - sb_conn, rr_node_driver_switches); - /* Finish this GSB, go to the next*/ + /* Create edges for SOURCE and SINK nodes for a tileable rr_graph */ + build_rr_graph_edges_for_source_nodes(rr_graph, rr_node_driver_switches, grids); + build_rr_graph_edges_for_sink_nodes(rr_graph, rr_node_driver_switches, grids); + + vtr::Point gsb_range(grids.width() - 2, grids.height() - 2); + + /* Go Switch Block by Switch Block */ + for (size_t ix = 0; ix <= gsb_range.x(); ++ix) { + for (size_t iy = 0; iy <= gsb_range.y(); ++iy) { + //vpr_printf(TIO_MESSAGE_INFO, "Building edges for GSB[%lu][%lu]\n", ix, iy); + + vtr::Point gsb_coord(ix, iy); + /* Create a GSB object */ + const RRGSB& rr_gsb = build_one_tileable_rr_gsb(grids, rr_graph, + device_chan_width, segment_inf, + gsb_coord); + + /* adapt the track_to_ipin_lookup for the GSB nodes */ + t_track2pin_map track2ipin_map; /* [0..track_gsb_side][0..num_tracks][ipin_indices] */ + track2ipin_map = build_gsb_track_to_ipin_map(rr_graph, rr_gsb, grids, segment_inf, Fc_in); + + /* adapt the opin_to_track_map for the GSB nodes */ + t_pin2track_map opin2track_map; /* [0..gsb_side][0..num_opin_node][track_indices] */ + opin2track_map = build_gsb_opin_to_track_map(rr_graph, rr_gsb, grids, segment_inf, Fc_out); + + /* adapt the switch_block_conn for the GSB nodes */ + t_track2track_map sb_conn; /* [0..from_gsb_side][0..chan_width-1][track_indices] */ + sb_conn = build_gsb_track_to_track_map(rr_graph, rr_gsb, + sb_type, Fs, sb_subtype, subFs, wire_opposite_side, + segment_inf); + + /* Build edges for a GSB */ + build_edges_for_one_tileable_rr_gsb(rr_graph, rr_gsb, + track2ipin_map, opin2track_map, + sb_conn, rr_node_driver_switches); + /* Finish this GSB, go to the next*/ + } } - } } /************************************************************************ * Build direct edges for Grids * ***********************************************************************/ -void build_rr_graph_direct_connections(RRGraph& rr_graph, - const DeviceGrid& grids, - const RRSwitchId& delayless_switch, - const std::vector& directs, +void build_rr_graph_direct_connections(RRGraph& rr_graph, + const DeviceGrid& grids, + const RRSwitchId& delayless_switch, + const std::vector& directs, const std::vector& clb_to_clb_directs) { - for (size_t ix = 0; ix < grids.width(); ++ix) { - for (size_t iy = 0; iy < grids.height(); ++iy) { - /* Skip EMPTY tiles */ - if (true == is_empty_type(grids[ix][iy].type)) { - continue; - } - /* Skip height > 1 or width > 1 tiles (mostly heterogeneous blocks) */ - if ( (0 < grids[ix][iy].width_offset) - || (0 < grids[ix][iy].height_offset) ) { - continue; - } - vtr::Point from_grid_coordinate(ix, iy); - build_direct_connections_for_one_gsb(rr_graph, - grids, - from_grid_coordinate, - delayless_switch, - directs, clb_to_clb_directs); + for (size_t ix = 0; ix < grids.width(); ++ix) { + for (size_t iy = 0; iy < grids.height(); ++iy) { + /* Skip EMPTY tiles */ + if (true == is_empty_type(grids[ix][iy].type)) { + continue; + } + /* Skip height > 1 or width > 1 tiles (mostly heterogeneous blocks) */ + if ((0 < grids[ix][iy].width_offset) + || (0 < grids[ix][iy].height_offset)) { + continue; + } + vtr::Point from_grid_coordinate(ix, iy); + build_direct_connections_for_one_gsb(rr_graph, + grids, + from_grid_coordinate, + delayless_switch, + directs, clb_to_clb_directs); + } } - } } - + } /* end namespace openfpga */ diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.h b/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.h index a20cef71712..936b9944f50 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.h +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.h @@ -1,6 +1,3 @@ -#ifndef TILEABLE_RR_GRAPH_EDGE_BUILDER_H -#define TILEABLE_RR_GRAPH_EDGE_BUILDER_H - /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ @@ -41,5 +38,3 @@ void build_rr_graph_direct_connections(RRGraphView& rr_graph, const std::vector& clb_to_clb_directs); } /* end namespace openfpga */ - -#endif diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp index 0fc75853dfb..6aab10566ea 100755 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp @@ -35,10 +35,10 @@ typedef std::vector> t_track_group; * track-to-track mapping matrix ***********************************************************************/ enum e_track_status { - TRACK_START, - TRACK_END, - TRACK_PASS, - NUM_TRACK_STATUS /* just a place holder to get the number of status */ + TRACK_START, + TRACK_END, + TRACK_PASS, + NUM_TRACK_STATUS /* just a place holder to get the number of status */ }; /************************************************************************ @@ -48,42 +48,41 @@ enum e_track_status { * Check if a track ends at this GSB or not * (xhigh, yhigh) should be same as the GSB side coordinate ***********************************************************************/ -static -enum e_track_status determine_track_status_of_gsb(const RRGraph& rr_graph, - const RRGSB& rr_gsb, - const enum e_side& gsb_side, - const size_t& track_id) { - enum e_track_status track_status = TRACK_PASS; - /* Get the rr_node */ - RRNodeId track_node = rr_gsb.get_chan_node(gsb_side, track_id); - /* Get the coordinates */ - vtr::Point side_coordinate = rr_gsb.get_side_block_coordinate(gsb_side); - - /* Get the coordinate of where the track starts */ - vtr::Point track_start = get_track_rr_node_start_coordinate(rr_graph, track_node); - - /* INC_DIRECTION start_track: (xlow, ylow) should be same as the GSB side coordinate */ - /* DEC_DIRECTION start_track: (xhigh, yhigh) should be same as the GSB side coordinate */ - if ( (track_start.x() == side_coordinate.x()) - && (track_start.y() == side_coordinate.y()) - && (OUT_PORT == rr_gsb.get_chan_node_direction(gsb_side, track_id)) ) { - /* Double check: start track should be an OUTPUT PORT of the GSB */ - track_status = TRACK_START; - } - - /* Get the coordinate of where the track ends */ - vtr::Point track_end = get_track_rr_node_end_coordinate(rr_graph, track_node); - - /* INC_DIRECTION end_track: (xhigh, yhigh) should be same as the GSB side coordinate */ - /* DEC_DIRECTION end_track: (xlow, ylow) should be same as the GSB side coordinate */ - if ( (track_end.x() == side_coordinate.x()) - && (track_end.y() == side_coordinate.y()) - && (IN_PORT == rr_gsb.get_chan_node_direction(gsb_side, track_id)) ) { - /* Double check: end track should be an INPUT PORT of the GSB */ - track_status = TRACK_END; - } - - return track_status; +static enum e_track_status determine_track_status_of_gsb(const RRGraph& rr_graph, + const RRGSB& rr_gsb, + const enum e_side& gsb_side, + const size_t& track_id) { + enum e_track_status track_status = TRACK_PASS; + /* Get the rr_node */ + RRNodeId track_node = rr_gsb.get_chan_node(gsb_side, track_id); + /* Get the coordinates */ + vtr::Point side_coordinate = rr_gsb.get_side_block_coordinate(gsb_side); + + /* Get the coordinate of where the track starts */ + vtr::Point track_start = get_track_rr_node_start_coordinate(rr_graph, track_node); + + /* INC_DIRECTION start_track: (xlow, ylow) should be same as the GSB side coordinate */ + /* DEC_DIRECTION start_track: (xhigh, yhigh) should be same as the GSB side coordinate */ + if ((track_start.x() == side_coordinate.x()) + && (track_start.y() == side_coordinate.y()) + && (OUT_PORT == rr_gsb.get_chan_node_direction(gsb_side, track_id))) { + /* Double check: start track should be an OUTPUT PORT of the GSB */ + track_status = TRACK_START; + } + + /* Get the coordinate of where the track ends */ + vtr::Point track_end = get_track_rr_node_end_coordinate(rr_graph, track_node); + + /* INC_DIRECTION end_track: (xhigh, yhigh) should be same as the GSB side coordinate */ + /* DEC_DIRECTION end_track: (xlow, ylow) should be same as the GSB side coordinate */ + if ((track_end.x() == side_coordinate.x()) + && (track_end.y() == side_coordinate.y()) + && (IN_PORT == rr_gsb.get_chan_node_direction(gsb_side, track_id))) { + /* Double check: end track should be an INPUT PORT of the GSB */ + track_status = TRACK_END; + } + + return track_status; } /************************************************************************ @@ -98,35 +97,34 @@ enum e_track_status determine_track_status_of_gsb(const RRGraph& rr_graph, * We will find the offset between gsb_side_coordinate and (xlow,ylow) of the track * Use the offset to check if the tracks should engage in this GSB connection ***********************************************************************/ -static -bool is_gsb_in_track_cb_population(const RRGraph& rr_graph, - const RRGSB& rr_gsb, - const e_side& gsb_side, - const int& track_id, - const std::vector& segment_inf) { - /* Get the rr_node */ - RRNodeId track_node = rr_gsb.get_chan_node(gsb_side, track_id); - /* Get the coordinates */ - vtr::Point side_coordinate = rr_gsb.get_side_block_coordinate(gsb_side); - - vtr::Point track_start = get_track_rr_node_start_coordinate(rr_graph, track_node); - - /* Get the offset */ - size_t offset = std::abs((int)side_coordinate.x() - (int)track_start.x()) - + std::abs((int)side_coordinate.y() - (int)track_start.y()); - - /* Get segment id */ - RRSegmentId seg_id = rr_gsb.get_chan_node_segment(gsb_side, track_id); - /* validate offset */ - VTR_ASSERT(offset < segment_inf[size_t(seg_id)].cb.size()); - - /* Get the SB population */ - bool in_cb_population = false; - if (true == segment_inf[size_t(seg_id)].cb[offset]) { - in_cb_population = true; - } - - return in_cb_population; +static bool is_gsb_in_track_cb_population(const RRGraph& rr_graph, + const RRGSB& rr_gsb, + const e_side& gsb_side, + const int& track_id, + const std::vector& segment_inf) { + /* Get the rr_node */ + RRNodeId track_node = rr_gsb.get_chan_node(gsb_side, track_id); + /* Get the coordinates */ + vtr::Point side_coordinate = rr_gsb.get_side_block_coordinate(gsb_side); + + vtr::Point track_start = get_track_rr_node_start_coordinate(rr_graph, track_node); + + /* Get the offset */ + size_t offset = std::abs((int)side_coordinate.x() - (int)track_start.x()) + + std::abs((int)side_coordinate.y() - (int)track_start.y()); + + /* Get segment id */ + RRSegmentId seg_id = rr_gsb.get_chan_node_segment(gsb_side, track_id); + /* validate offset */ + VTR_ASSERT(offset < segment_inf[size_t(seg_id)].cb.size()); + + /* Get the SB population */ + bool in_cb_population = false; + if (true == segment_inf[size_t(seg_id)].cb[offset]) { + in_cb_population = true; + } + + return in_cb_population; } /************************************************************************ @@ -141,35 +139,34 @@ bool is_gsb_in_track_cb_population(const RRGraph& rr_graph, * We will find the offset between gsb_side_coordinate and (xlow,ylow) of the track * Use the offset to check if the tracks should engage in this GSB connection ***********************************************************************/ -static -bool is_gsb_in_track_sb_population(const RRGraph& rr_graph, - const RRGSB& rr_gsb, - const e_side& gsb_side, - const int& track_id, - const std::vector& segment_inf) { - /* Get the rr_node */ - const RRNodeId& track_node = rr_gsb.get_chan_node(gsb_side, track_id); - /* Get the coordinates */ - vtr::Point side_coordinate = rr_gsb.get_side_block_coordinate(gsb_side); - - vtr::Point track_start = get_track_rr_node_start_coordinate(rr_graph, track_node); - - /* Get the offset */ - size_t offset = std::abs((int)side_coordinate.x() - (int)track_start.x()) - + std::abs((int)side_coordinate.y() - (int)track_start.y()); - - /* Get segment id */ - RRSegmentId seg_id = rr_gsb.get_chan_node_segment(gsb_side, track_id); - /* validate offset */ - VTR_ASSERT(offset < segment_inf[size_t(seg_id)].sb.size()); - - /* Get the SB population */ - bool in_sb_population = false; - if (true == segment_inf[size_t(seg_id)].sb[offset]) { - in_sb_population = true; - } - - return in_sb_population; +static bool is_gsb_in_track_sb_population(const RRGraph& rr_graph, + const RRGSB& rr_gsb, + const e_side& gsb_side, + const int& track_id, + const std::vector& segment_inf) { + /* Get the rr_node */ + const RRNodeId& track_node = rr_gsb.get_chan_node(gsb_side, track_id); + /* Get the coordinates */ + vtr::Point side_coordinate = rr_gsb.get_side_block_coordinate(gsb_side); + + vtr::Point track_start = get_track_rr_node_start_coordinate(rr_graph, track_node); + + /* Get the offset */ + size_t offset = std::abs((int)side_coordinate.x() - (int)track_start.x()) + + std::abs((int)side_coordinate.y() - (int)track_start.y()); + + /* Get segment id */ + RRSegmentId seg_id = rr_gsb.get_chan_node_segment(gsb_side, track_id); + /* validate offset */ + VTR_ASSERT(offset < segment_inf[size_t(seg_id)].sb.size()); + + /* Get the SB population */ + bool in_sb_population = false; + if (true == segment_inf[size_t(seg_id)].sb[offset]) { + in_sb_population = true; + } + + return in_sb_population; } /************************************************************************ @@ -177,25 +174,24 @@ bool is_gsb_in_track_sb_population(const RRGraph& rr_graph, * We consider the following list [to_track, to_track + Fs/3 - 1] * if the [to_track + Fs/3 - 1] exceeds the num_to_tracks, we start over from 0! ***********************************************************************/ -static -std::vector get_to_track_list(const int& Fs, const int& to_track, const int& num_to_tracks) { - std::vector to_tracks; +static std::vector get_to_track_list(const int& Fs, const int& to_track, const int& num_to_tracks) { + std::vector to_tracks; - for (int i = 0; i < Fs; i = i + 3) { - /* TODO: currently, for Fs > 3, I always search the next from_track until Fs is satisfied + for (int i = 0; i < Fs; i = i + 3) { + /* TODO: currently, for Fs > 3, I always search the next from_track until Fs is satisfied * The optimal track selection should be done in a more scientific way!!! */ - int to_track_i = to_track + i; - /* make sure the track id is still in range */ - if ( to_track_i > num_to_tracks - 1) { - to_track_i = to_track_i % num_to_tracks; + int to_track_i = to_track + i; + /* make sure the track id is still in range */ + if (to_track_i > num_to_tracks - 1) { + to_track_i = to_track_i % num_to_tracks; + } + /* Ensure we are in the range */ + VTR_ASSERT(to_track_i < num_to_tracks); + /* from track must be connected */ + to_tracks.push_back(to_track_i); } - /* Ensure we are in the range */ - VTR_ASSERT(to_track_i < num_to_tracks); - /* from track must be connected */ - to_tracks.push_back(to_track_i); - } - return to_tracks; + return to_tracks; } /************************************************************************ @@ -204,196 +200,192 @@ std::vector get_to_track_list(const int& Fs, const int& to_track, const * The track_ids to return will depend on different topologies of SB * SUBSET, UNIVERSAL, and WILTON. ***********************************************************************/ -static -std::vector get_switch_block_to_track_id(const e_switch_block_type& switch_block_type, - const int& Fs, - const e_side& from_side, - const int& from_track, - const e_side& to_side, - const int& num_to_tracks) { - - /* This routine returns the track number to which the from_track should +static std::vector get_switch_block_to_track_id(const e_switch_block_type& switch_block_type, + const int& Fs, + const e_side& from_side, + const int& from_track, + const e_side& to_side, + const int& num_to_tracks) { + /* This routine returns the track number to which the from_track should * connect. It supports any Fs % 3 == 0, switch blocks. */ - std::vector to_tracks; + std::vector to_tracks; - /* TODO: currently, for Fs > 3, I always search the next from_track until Fs is satisfied + /* TODO: currently, for Fs > 3, I always search the next from_track until Fs is satisfied * The optimal track selection should be done in a more scientific way!!! */ - VTR_ASSERT(0 == Fs % 3); - - /* Adapt from_track to fit in the range of num_to_tracks */ - size_t actual_from_track = from_track % num_to_tracks; - - switch (switch_block_type) { - case SUBSET: /* NB: Global routing uses SUBSET too */ - to_tracks = get_to_track_list(Fs, actual_from_track, num_to_tracks); - /* Finish, we return */ - return to_tracks; - case UNIVERSAL: - if ( (from_side == LEFT) - || (from_side == RIGHT) ) { - /* For the prev_side, to_track is from_track + VTR_ASSERT(0 == Fs % 3); + + /* Adapt from_track to fit in the range of num_to_tracks */ + size_t actual_from_track = from_track % num_to_tracks; + + switch (switch_block_type) { + case SUBSET: /* NB: Global routing uses SUBSET too */ + to_tracks = get_to_track_list(Fs, actual_from_track, num_to_tracks); + /* Finish, we return */ + return to_tracks; + case UNIVERSAL: + if ((from_side == LEFT) + || (from_side == RIGHT)) { + /* For the prev_side, to_track is from_track * For the next_side, to_track is num_to_tracks - 1 - from_track * For the opposite_side, to_track is always from_track */ - SideManager side_manager(from_side); - if ( (to_side == side_manager.get_opposite()) - || (to_side == side_manager.get_rotate_counterclockwise()) ) { - to_tracks = get_to_track_list(Fs, actual_from_track, num_to_tracks); - } else if (to_side == side_manager.get_rotate_clockwise()) { - to_tracks = get_to_track_list(Fs, num_to_tracks - 1 - actual_from_track, num_to_tracks); - } - } - - if ( (from_side == TOP) - || (from_side == BOTTOM) ) { - /* For the next_side, to_track is from_track + SideManager side_manager(from_side); + if ((to_side == side_manager.get_opposite()) + || (to_side == side_manager.get_rotate_counterclockwise())) { + to_tracks = get_to_track_list(Fs, actual_from_track, num_to_tracks); + } else if (to_side == side_manager.get_rotate_clockwise()) { + to_tracks = get_to_track_list(Fs, num_to_tracks - 1 - actual_from_track, num_to_tracks); + } + } + + if ((from_side == TOP) + || (from_side == BOTTOM)) { + /* For the next_side, to_track is from_track * For the prev_side, to_track is num_to_tracks - 1 - from_track * For the opposite_side, to_track is always from_track */ - SideManager side_manager(from_side); - if ( (to_side == side_manager.get_opposite()) - || (to_side == side_manager.get_rotate_clockwise()) ) { - to_tracks = get_to_track_list(Fs, actual_from_track, num_to_tracks); - } else if (to_side == side_manager.get_rotate_counterclockwise()) { - to_tracks = get_to_track_list(Fs, num_to_tracks - 1 - actual_from_track, num_to_tracks); - } + SideManager side_manager(from_side); + if ((to_side == side_manager.get_opposite()) + || (to_side == side_manager.get_rotate_clockwise())) { + to_tracks = get_to_track_list(Fs, actual_from_track, num_to_tracks); + } else if (to_side == side_manager.get_rotate_counterclockwise()) { + to_tracks = get_to_track_list(Fs, num_to_tracks - 1 - actual_from_track, num_to_tracks); + } + } + /* Finish, we return */ + return to_tracks; + /* End switch_block_type == UNIVERSAL case. */ + case WILTON: + /* See S. Wilton Phd thesis, U of T, 1996 p. 103 for details on following. */ + if (from_side == LEFT) { + if (to_side == RIGHT) { /* CHANX to CHANX */ + to_tracks = get_to_track_list(Fs, actual_from_track, num_to_tracks); + } else if (to_side == TOP) { /* from CHANX to CHANY */ + to_tracks = get_to_track_list(Fs, (num_to_tracks - actual_from_track) % num_to_tracks, num_to_tracks); + } else if (to_side == BOTTOM) { + to_tracks = get_to_track_list(Fs, (num_to_tracks + actual_from_track - 1) % num_to_tracks, num_to_tracks); + } + } else if (from_side == RIGHT) { + if (to_side == LEFT) { /* CHANX to CHANX */ + to_tracks = get_to_track_list(Fs, actual_from_track, num_to_tracks); + } else if (to_side == TOP) { /* from CHANX to CHANY */ + to_tracks = get_to_track_list(Fs, (num_to_tracks + actual_from_track - 1) % num_to_tracks, num_to_tracks); + } else if (to_side == BOTTOM) { + to_tracks = get_to_track_list(Fs, (2 * num_to_tracks - 2 - actual_from_track) % num_to_tracks, num_to_tracks); + } + } else if (from_side == BOTTOM) { + if (to_side == TOP) { /* CHANY to CHANY */ + to_tracks = get_to_track_list(Fs, actual_from_track, num_to_tracks); + } else if (to_side == LEFT) { /* from CHANY to CHANX */ + to_tracks = get_to_track_list(Fs, (actual_from_track + 1) % num_to_tracks, num_to_tracks); + } else if (to_side == RIGHT) { + to_tracks = get_to_track_list(Fs, (2 * num_to_tracks - 2 - actual_from_track) % num_to_tracks, num_to_tracks); + } + } else if (from_side == TOP) { + if (to_side == BOTTOM) { /* CHANY to CHANY */ + to_tracks = get_to_track_list(Fs, from_track, num_to_tracks); + } else if (to_side == LEFT) { /* from CHANY to CHANX */ + to_tracks = get_to_track_list(Fs, (num_to_tracks - actual_from_track) % num_to_tracks, num_to_tracks); + } else if (to_side == RIGHT) { + to_tracks = get_to_track_list(Fs, (actual_from_track + 1) % num_to_tracks, num_to_tracks); + } + } + /* Finish, we return */ + return to_tracks; + /* End switch_block_type == WILTON case. */ + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid switch block pattern !\n"); + exit(1); } - /* Finish, we return */ - return to_tracks; - /* End switch_block_type == UNIVERSAL case. */ - case WILTON: - /* See S. Wilton Phd thesis, U of T, 1996 p. 103 for details on following. */ - if (from_side == LEFT) { - if (to_side == RIGHT) { /* CHANX to CHANX */ - to_tracks = get_to_track_list(Fs, actual_from_track, num_to_tracks); - } else if (to_side == TOP) { /* from CHANX to CHANY */ - to_tracks = get_to_track_list(Fs, (num_to_tracks - actual_from_track ) % num_to_tracks, num_to_tracks); - } else if (to_side == BOTTOM) { - to_tracks = get_to_track_list(Fs, (num_to_tracks + actual_from_track - 1) % num_to_tracks, num_to_tracks); - } - } else if (from_side == RIGHT) { - if (to_side == LEFT) { /* CHANX to CHANX */ - to_tracks = get_to_track_list(Fs, actual_from_track, num_to_tracks); - } else if (to_side == TOP) { /* from CHANX to CHANY */ - to_tracks = get_to_track_list(Fs, (num_to_tracks + actual_from_track - 1) % num_to_tracks, num_to_tracks); - } else if (to_side == BOTTOM) { - to_tracks = get_to_track_list(Fs, (2 * num_to_tracks - 2 - actual_from_track) % num_to_tracks, num_to_tracks); - } - } else if (from_side == BOTTOM) { - if (to_side == TOP) { /* CHANY to CHANY */ - to_tracks = get_to_track_list(Fs, actual_from_track, num_to_tracks); - } else if (to_side == LEFT) { /* from CHANY to CHANX */ - to_tracks = get_to_track_list(Fs, (actual_from_track + 1) % num_to_tracks, num_to_tracks); - } else if (to_side == RIGHT) { - to_tracks = get_to_track_list(Fs, (2 * num_to_tracks - 2 - actual_from_track) % num_to_tracks, num_to_tracks); - } - } else if (from_side == TOP) { - if (to_side == BOTTOM) { /* CHANY to CHANY */ - to_tracks = get_to_track_list(Fs, from_track, num_to_tracks); - } else if (to_side == LEFT) { /* from CHANY to CHANX */ - to_tracks = get_to_track_list(Fs, (num_to_tracks - actual_from_track) % num_to_tracks, num_to_tracks); - } else if (to_side == RIGHT) { - to_tracks = get_to_track_list(Fs, (actual_from_track + 1) % num_to_tracks, num_to_tracks); - } - } - /* Finish, we return */ + return to_tracks; - /* End switch_block_type == WILTON case. */ - default: - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid switch block pattern !\n"); - exit(1); - } - - return to_tracks; } - /************************************************************************ * Build the track_to_track_map[from_side][0..chan_width-1][to_side][track_indices] * For a group of from_track nodes and to_track nodes * For each side of from_tracks, we call a routine to get the list of to_tracks * Then, we fill the track2track_map ***********************************************************************/ -static -void build_gsb_one_group_track_to_track_map(const RRGraph& rr_graph, - const RRGSB& rr_gsb, - const e_switch_block_type& sb_type, - const int& Fs, - const bool& wire_opposite_side, - const t_track_group& from_tracks, /* [0..gsb_side][track_indices] */ - const t_track_group& to_tracks, /* [0..gsb_side][track_indices] */ - t_track2track_map& track2track_map) { - for (size_t side = 0; side < from_tracks.size(); ++side) { - SideManager side_manager(side); - e_side from_side = side_manager.get_side(); - /* Find the other sides where the start tracks will locate */ - std::vector to_track_sides; - /* 0. opposite side */ - to_track_sides.push_back(side_manager.get_opposite()); - /* 1. prev side */ - /* Previous side definition: TOP => LEFT; RIGHT=>TOP; BOTTOM=>RIGHT; LEFT=>BOTTOM */ - to_track_sides.push_back(side_manager.get_rotate_counterclockwise()); - /* 2. next side */ - /* Next side definition: TOP => RIGHT; RIGHT=>BOTTOM; BOTTOM=>LEFT; LEFT=>TOP */ - to_track_sides.push_back(side_manager.get_rotate_clockwise()); - - for (size_t inode = 0; inode < from_tracks[side].size(); ++inode) { - for (size_t to_side_id = 0; to_side_id < to_track_sides.size(); ++to_side_id) { - enum e_side to_side = to_track_sides[to_side_id]; - SideManager to_side_manager(to_side); - size_t to_side_index = to_side_manager.to_size_t(); - /* Bypass those to_sides have no nodes */ - if (0 == to_tracks[to_side_index].size()) { - continue; - } - /* Bypass those from_side is same as to_side */ - if (from_side == to_side) { - continue; - } - /* Bypass those from_side is opposite to to_side if required */ - if ( (true == wire_opposite_side) - && (to_side_manager.get_opposite() == from_side) ) { - continue; +static void build_gsb_one_group_track_to_track_map(const RRGraph& rr_graph, + const RRGSB& rr_gsb, + const e_switch_block_type& sb_type, + const int& Fs, + const bool& wire_opposite_side, + const t_track_group& from_tracks, /* [0..gsb_side][track_indices] */ + const t_track_group& to_tracks, /* [0..gsb_side][track_indices] */ + t_track2track_map& track2track_map) { + for (size_t side = 0; side < from_tracks.size(); ++side) { + SideManager side_manager(side); + e_side from_side = side_manager.get_side(); + /* Find the other sides where the start tracks will locate */ + std::vector to_track_sides; + /* 0. opposite side */ + to_track_sides.push_back(side_manager.get_opposite()); + /* 1. prev side */ + /* Previous side definition: TOP => LEFT; RIGHT=>TOP; BOTTOM=>RIGHT; LEFT=>BOTTOM */ + to_track_sides.push_back(side_manager.get_rotate_counterclockwise()); + /* 2. next side */ + /* Next side definition: TOP => RIGHT; RIGHT=>BOTTOM; BOTTOM=>LEFT; LEFT=>TOP */ + to_track_sides.push_back(side_manager.get_rotate_clockwise()); + + for (size_t inode = 0; inode < from_tracks[side].size(); ++inode) { + for (size_t to_side_id = 0; to_side_id < to_track_sides.size(); ++to_side_id) { + enum e_side to_side = to_track_sides[to_side_id]; + SideManager to_side_manager(to_side); + size_t to_side_index = to_side_manager.to_size_t(); + /* Bypass those to_sides have no nodes */ + if (0 == to_tracks[to_side_index].size()) { + continue; + } + /* Bypass those from_side is same as to_side */ + if (from_side == to_side) { + continue; + } + /* Bypass those from_side is opposite to to_side if required */ + if ((true == wire_opposite_side) + && (to_side_manager.get_opposite() == from_side)) { + continue; + } + /* Get other track_ids depending on the switch block pattern */ + /* Find the track ids that will start at the other sides */ + std::vector to_track_ids = get_switch_block_to_track_id(sb_type, Fs, from_side, inode, + to_side, + to_tracks[to_side_index].size()); + /* Update the track2track_map: */ + for (size_t to_track_id = 0; to_track_id < to_track_ids.size(); ++to_track_id) { + size_t from_side_index = side_manager.to_size_t(); + size_t from_track_index = from_tracks[side][inode]; + /* Check the id is still in the range !*/ + VTR_ASSERT(to_track_ids[to_track_id] < to_tracks[to_side_index].size()); + size_t to_track_index = to_tracks[to_side_index][to_track_ids[to_track_id]]; + //printf("from_track(size=%lu): %lu , to_track_ids[%lu]:%lu, to_track_index: %lu in a group of %lu tracks\n", + // from_tracks[side].size(), inode, to_track_id, to_track_ids[to_track_id], + // to_track_index, to_tracks[to_side_index].size()); + const RRNodeId& to_track_node = rr_gsb.get_chan_node(to_side, to_track_index); + VTR_ASSERT(true == rr_graph.valid_node_id(to_track_node)); + + /* from_track should be IN_PORT */ + VTR_ASSERT(IN_PORT == rr_gsb.get_chan_node_direction(from_side, from_track_index)); + /* to_track should be OUT_PORT */ + VTR_ASSERT(OUT_PORT == rr_gsb.get_chan_node_direction(to_side, to_track_index)); + + /* Check if the to_track_node is already in the list ! */ + std::vector::iterator it = std::find(track2track_map[from_side_index][from_track_index].begin(), + track2track_map[from_side_index][from_track_index].end(), + to_track_node); + if (it != track2track_map[from_side_index][from_track_index].end()) { + continue; /* the node_id is already in the list, go for the next */ + } + /* Clear, we should add to the list */ + track2track_map[from_side_index][from_track_index].push_back(to_track_node); + } + } } - /* Get other track_ids depending on the switch block pattern */ - /* Find the track ids that will start at the other sides */ - std::vector to_track_ids = get_switch_block_to_track_id(sb_type, Fs, from_side, inode, - to_side, - to_tracks[to_side_index].size()); - /* Update the track2track_map: */ - for (size_t to_track_id = 0; to_track_id < to_track_ids.size(); ++to_track_id) { - size_t from_side_index = side_manager.to_size_t(); - size_t from_track_index = from_tracks[side][inode]; - /* Check the id is still in the range !*/ - VTR_ASSERT( to_track_ids[to_track_id] < to_tracks[to_side_index].size() ); - size_t to_track_index = to_tracks[to_side_index][to_track_ids[to_track_id]]; - //printf("from_track(size=%lu): %lu , to_track_ids[%lu]:%lu, to_track_index: %lu in a group of %lu tracks\n", - // from_tracks[side].size(), inode, to_track_id, to_track_ids[to_track_id], - // to_track_index, to_tracks[to_side_index].size()); - const RRNodeId& to_track_node = rr_gsb.get_chan_node(to_side, to_track_index); - VTR_ASSERT(true == rr_graph.valid_node_id(to_track_node)); - - /* from_track should be IN_PORT */ - VTR_ASSERT(IN_PORT == rr_gsb.get_chan_node_direction(from_side, from_track_index)); - /* to_track should be OUT_PORT */ - VTR_ASSERT(OUT_PORT == rr_gsb.get_chan_node_direction(to_side, to_track_index)); - - /* Check if the to_track_node is already in the list ! */ - std::vector::iterator it = std::find(track2track_map[from_side_index][from_track_index].begin(), - track2track_map[from_side_index][from_track_index].end(), - to_track_node); - if (it != track2track_map[from_side_index][from_track_index].end()) { - continue; /* the node_id is already in the list, go for the next */ - } - /* Clear, we should add to the list */ - track2track_map[from_side_index][from_track_index].push_back(to_track_node); - } - } } - } } /************************************************************************ @@ -442,128 +434,127 @@ void build_gsb_one_group_track_to_track_map(const RRGraph& rr_graph, ***********************************************************************/ t_track2track_map build_gsb_track_to_track_map(const RRGraph& rr_graph, const RRGSB& rr_gsb, - const e_switch_block_type& sb_type, + const e_switch_block_type& sb_type, const int& Fs, - const e_switch_block_type& sb_subtype, + const e_switch_block_type& sb_subtype, const int& subFs, const bool& wire_opposite_side, const std::vector& segment_inf) { - t_track2track_map track2track_map; /* [0..gsb_side][0..chan_width][track_indices] */ + t_track2track_map track2track_map; /* [0..gsb_side][0..chan_width][track_indices] */ - /* Categorize tracks into 3 groups: + /* Categorize tracks into 3 groups: * (1) tracks will start here * (2) tracks will end here * (2) tracks will just pass through the SB */ - t_track_group start_tracks; /* [0..gsb_side][track_indices] */ - t_track_group end_tracks; /* [0..gsb_side][track_indices] */ - t_track_group pass_tracks; /* [0..gsb_side][track_indices] */ - - /* resize to the number of sides */ - start_tracks.resize(rr_gsb.get_num_sides()); - end_tracks.resize(rr_gsb.get_num_sides()); - pass_tracks.resize(rr_gsb.get_num_sides()); - - /* Walk through each side */ - for (size_t side = 0; side < rr_gsb.get_num_sides(); ++side) { - SideManager side_manager(side); - e_side gsb_side = side_manager.get_side(); - /* Build a list of tracks that will start from this side */ - for (size_t inode = 0; inode < rr_gsb.get_chan_width(gsb_side); ++inode) { - /* We need to check Switch block population of this track + t_track_group start_tracks; /* [0..gsb_side][track_indices] */ + t_track_group end_tracks; /* [0..gsb_side][track_indices] */ + t_track_group pass_tracks; /* [0..gsb_side][track_indices] */ + + /* resize to the number of sides */ + start_tracks.resize(rr_gsb.get_num_sides()); + end_tracks.resize(rr_gsb.get_num_sides()); + pass_tracks.resize(rr_gsb.get_num_sides()); + + /* Walk through each side */ + for (size_t side = 0; side < rr_gsb.get_num_sides(); ++side) { + SideManager side_manager(side); + e_side gsb_side = side_manager.get_side(); + /* Build a list of tracks that will start from this side */ + for (size_t inode = 0; inode < rr_gsb.get_chan_width(gsb_side); ++inode) { + /* We need to check Switch block population of this track * The track node will not be considered if there supposed to be no SB at this position */ - if (false == is_gsb_in_track_sb_population(rr_graph, rr_gsb, gsb_side, inode, segment_inf)) { - continue; /* skip this node and go to the next */ - } - /* check if this track will start from here */ - enum e_track_status track_status = determine_track_status_of_gsb(rr_graph, rr_gsb, gsb_side, inode); - - switch (track_status) { - case TRACK_START: - /* update starting track list */ - start_tracks[side].push_back(inode); - break; - case TRACK_END: - /* Update end track list */ - end_tracks[side].push_back(inode); - break; - case TRACK_PASS: - /* Update passing track list */ - /* Note that the pass_track should be IN_PORT only !!! */ - if (IN_PORT == rr_gsb.get_chan_node_direction(gsb_side, inode)) { - pass_tracks[side].push_back(inode); + if (false == is_gsb_in_track_sb_population(rr_graph, rr_gsb, gsb_side, inode, segment_inf)) { + continue; /* skip this node and go to the next */ + } + /* check if this track will start from here */ + enum e_track_status track_status = determine_track_status_of_gsb(rr_graph, rr_gsb, gsb_side, inode); + + switch (track_status) { + case TRACK_START: + /* update starting track list */ + start_tracks[side].push_back(inode); + break; + case TRACK_END: + /* Update end track list */ + end_tracks[side].push_back(inode); + break; + case TRACK_PASS: + /* Update passing track list */ + /* Note that the pass_track should be IN_PORT only !!! */ + if (IN_PORT == rr_gsb.get_chan_node_direction(gsb_side, inode)) { + pass_tracks[side].push_back(inode); + } + break; + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid track status!\n"); + exit(1); + } } - break; - default: - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid track status!\n"); - exit(1); - } } - } - - /* Allocate track2track map */ - track2track_map.resize(rr_gsb.get_num_sides()); - for (size_t side = 0; side < rr_gsb.get_num_sides(); ++side) { - SideManager side_manager(side); - enum e_side gsb_side = side_manager.get_side(); - /* allocate track2track_map[gsb_side] */ - track2track_map[side].resize(rr_gsb.get_chan_width(gsb_side)); - for (size_t inode = 0; inode < rr_gsb.get_chan_width(gsb_side); ++inode) { - /* allocate track2track_map[gsb_side][inode] */ - track2track_map[side][inode].clear(); + + /* Allocate track2track map */ + track2track_map.resize(rr_gsb.get_num_sides()); + for (size_t side = 0; side < rr_gsb.get_num_sides(); ++side) { + SideManager side_manager(side); + enum e_side gsb_side = side_manager.get_side(); + /* allocate track2track_map[gsb_side] */ + track2track_map[side].resize(rr_gsb.get_chan_width(gsb_side)); + for (size_t inode = 0; inode < rr_gsb.get_chan_width(gsb_side); ++inode) { + /* allocate track2track_map[gsb_side][inode] */ + track2track_map[side][inode].clear(); + } } - } - /* For Group 1: we build connections between end_tracks and start_tracks*/ - build_gsb_one_group_track_to_track_map(rr_graph, rr_gsb, - sb_type, Fs, - true, /* End tracks should always to wired to start tracks */ - end_tracks, start_tracks, - track2track_map); + /* For Group 1: we build connections between end_tracks and start_tracks*/ + build_gsb_one_group_track_to_track_map(rr_graph, rr_gsb, + sb_type, Fs, + true, /* End tracks should always to wired to start tracks */ + end_tracks, start_tracks, + track2track_map); - /* For Group 2: we build connections between end_tracks and start_tracks*/ - /* Currently, I use the same Switch Block pattern for the passing tracks and end tracks, + /* For Group 2: we build connections between end_tracks and start_tracks*/ + /* Currently, I use the same Switch Block pattern for the passing tracks and end tracks, * TODO: This can be improved with different patterns! */ - build_gsb_one_group_track_to_track_map(rr_graph, rr_gsb, - sb_subtype, subFs, - wire_opposite_side, /* Pass tracks may not be wired to start tracks */ - pass_tracks, start_tracks, - track2track_map); + build_gsb_one_group_track_to_track_map(rr_graph, rr_gsb, + sb_subtype, subFs, + wire_opposite_side, /* Pass tracks may not be wired to start tracks */ + pass_tracks, start_tracks, + track2track_map); - return track2track_map; + return track2track_map; } /* Build a RRChan Object with the given channel type and coorindators */ -static -RRChan build_one_tileable_rr_chan(const vtr::Point& chan_coordinate, - const t_rr_type& chan_type, - const RRGraph& rr_graph, - const ChanNodeDetails& chan_details) { - std::vector chan_rr_nodes; - - /* Create a rr_chan object and check if it is unique in the graph */ - RRChan rr_chan; - - /* Fill the information */ - rr_chan.set_type(chan_type); - - /* Collect rr_nodes for this channel */ - chan_rr_nodes = find_rr_graph_chan_nodes(rr_graph, - chan_coordinate.x(), chan_coordinate.y(), - chan_type); - - /* Reserve */ - /* rr_chan.reserve_node(size_t(chan_width)); */ - - /* Fill the rr_chan */ - for (size_t itrack = 0; itrack < chan_rr_nodes.size(); ++itrack) { - size_t iseg = chan_details.get_track_segment_id(itrack); - rr_chan.add_node(rr_graph, chan_rr_nodes[itrack], RRSegmentId(iseg)); - } - - return rr_chan; +static RRChan build_one_tileable_rr_chan(const vtr::Point& chan_coordinate, + const t_rr_type& chan_type, + const RRGraph& rr_graph, + const ChanNodeDetails& chan_details) { + std::vector chan_rr_nodes; + + /* Create a rr_chan object and check if it is unique in the graph */ + RRChan rr_chan; + + /* Fill the information */ + rr_chan.set_type(chan_type); + + /* Collect rr_nodes for this channel */ + chan_rr_nodes = find_rr_graph_chan_nodes(rr_graph, + chan_coordinate.x(), chan_coordinate.y(), + chan_type); + + /* Reserve */ + /* rr_chan.reserve_node(size_t(chan_width)); */ + + /* Fill the rr_chan */ + for (size_t itrack = 0; itrack < chan_rr_nodes.size(); ++itrack) { + size_t iseg = chan_details.get_track_segment_id(itrack); + rr_chan.add_node(rr_graph, chan_rr_nodes[itrack], RRSegmentId(iseg)); + } + + return rr_chan; } /*********************************************************************** @@ -618,210 +609,210 @@ RRChan build_one_tileable_rr_chan(const vtr::Point& chan_coordinate, * We just need to fill the ipin nodes at LEFT and RIGHT sides * as well as properly fill the ipin_grid_side information ***********************************************************************/ -RRGSB build_one_tileable_rr_gsb(const DeviceGrid& grids, +RRGSB build_one_tileable_rr_gsb(const DeviceGrid& grids, const RRGraph& rr_graph, - const vtr::Point& device_chan_width, + const vtr::Point& device_chan_width, const std::vector& segment_inf, const vtr::Point& gsb_coordinate) { - /* Create an object to return */ - RRGSB rr_gsb; - - /* Check */ - VTR_ASSERT(gsb_coordinate.x() <= grids.width()); - VTR_ASSERT(gsb_coordinate.y() <= grids.height()); - - /* Coordinator initialization */ - rr_gsb.set_coordinate(gsb_coordinate.x(), gsb_coordinate.y()); - - /* Basic information*/ - rr_gsb.init_num_sides(4); /* Fixed number of sides */ - - /* Find all rr_nodes of channels */ - /* SideManager: TOP => 0, RIGHT => 1, BOTTOM => 2, LEFT => 3 */ - for (size_t side = 0; side < rr_gsb.get_num_sides(); ++side) { - /* Local variables inside this for loop */ - SideManager side_manager(side); - vtr::Point coordinate = rr_gsb.get_side_block_coordinate(side_manager.get_side()); - RRChan rr_chan; - std::vector> temp_opin_rr_nodes(2); - enum e_side opin_grid_side[2] = {NUM_SIDES, NUM_SIDES}; - enum PORTS chan_dir_to_port_dir_mapping[2] = {OUT_PORT, IN_PORT}; /* 0: INC_DIRECTION => ?; 1: DEC_DIRECTION => ? */ - - /* Build a segment details, where we need the segment ids for building rr_chan + /* Create an object to return */ + RRGSB rr_gsb; + + /* Check */ + VTR_ASSERT(gsb_coordinate.x() <= grids.width()); + VTR_ASSERT(gsb_coordinate.y() <= grids.height()); + + /* Coordinator initialization */ + rr_gsb.set_coordinate(gsb_coordinate.x(), gsb_coordinate.y()); + + /* Basic information*/ + rr_gsb.init_num_sides(4); /* Fixed number of sides */ + + /* Find all rr_nodes of channels */ + /* SideManager: TOP => 0, RIGHT => 1, BOTTOM => 2, LEFT => 3 */ + for (size_t side = 0; side < rr_gsb.get_num_sides(); ++side) { + /* Local variables inside this for loop */ + SideManager side_manager(side); + vtr::Point coordinate = rr_gsb.get_side_block_coordinate(side_manager.get_side()); + RRChan rr_chan; + std::vector> temp_opin_rr_nodes(2); + enum e_side opin_grid_side[2] = {NUM_SIDES, NUM_SIDES}; + enum PORTS chan_dir_to_port_dir_mapping[2] = {OUT_PORT, IN_PORT}; /* 0: INC_DIRECTION => ?; 1: DEC_DIRECTION => ? */ + + /* Build a segment details, where we need the segment ids for building rr_chan * We do not care starting and ending points here, so set chan_side as NUM_SIDES */ - ChanNodeDetails chanx_details = build_unidir_chan_node_details(device_chan_width.x(), grids.width() - 1, - false, false, segment_inf); - ChanNodeDetails chany_details = build_unidir_chan_node_details(device_chan_width.y(), grids.height() - 1, - false, false, segment_inf); - - switch (side) { - case TOP: /* TOP = 0 */ - /* For the bording, we should take special care */ - if (gsb_coordinate.y() == grids.height() - 1) { - rr_gsb.clear_one_side(side_manager.get_side()); - break; - } - /* Routing channels*/ - /* SideManager: TOP => 0, RIGHT => 1, BOTTOM => 2, LEFT => 3 */ - /* Create a rr_chan object and check if it is unique in the graph */ - rr_chan = build_one_tileable_rr_chan(coordinate, CHANY, rr_graph, chany_details); - chan_dir_to_port_dir_mapping[0] = OUT_PORT; /* INC_DIRECTION => OUT_PORT */ - chan_dir_to_port_dir_mapping[1] = IN_PORT; /* DEC_DIRECTION => IN_PORT */ - - /* Assign grid side of OPIN */ - /* Grid[x][y+1] RIGHT side outputs pins */ - opin_grid_side[0] = RIGHT; - /* Grid[x+1][y+1] left side outputs pins */ - opin_grid_side[1] = LEFT; - - /* Build the Switch block: opin and opin_grid_side */ - /* Include Grid[x][y+1] RIGHT side outputs pins */ - temp_opin_rr_nodes[0] = find_rr_graph_grid_nodes(rr_graph, grids, - gsb_coordinate.x(), gsb_coordinate.y() + 1, - OPIN, opin_grid_side[0]); - /* Include Grid[x+1][y+1] Left side output pins */ - temp_opin_rr_nodes[1] = find_rr_graph_grid_nodes(rr_graph, grids, - gsb_coordinate.x() + 1, gsb_coordinate.y() + 1, - OPIN, opin_grid_side[1]); - - break; - case RIGHT: /* RIGHT = 1 */ - /* For the bording, we should take special care */ - if (gsb_coordinate.x() == grids.width() - 1) { - rr_gsb.clear_one_side(side_manager.get_side()); - break; - } - /* Routing channels*/ - /* SideManager: TOP => 0, RIGHT => 1, BOTTOM => 2, LEFT => 3 */ - /* Collect rr_nodes for Tracks for top: chany[x][y+1] */ - /* Create a rr_chan object and check if it is unique in the graph */ - rr_chan = build_one_tileable_rr_chan(coordinate, CHANX, rr_graph, chanx_details); - chan_dir_to_port_dir_mapping[0] = OUT_PORT; /* INC_DIRECTION => OUT_PORT */ - chan_dir_to_port_dir_mapping[1] = IN_PORT; /* DEC_DIRECTION => IN_PORT */ - - /* Assign grid side of OPIN */ - /* Grid[x+1][y+1] BOTTOM side outputs pins */ - opin_grid_side[0] = BOTTOM; - /* Grid[x+1][y] TOP side outputs pins */ - opin_grid_side[1] = TOP; - - /* Build the Switch block: opin and opin_grid_side */ - /* include Grid[x+1][y+1] Bottom side output pins */ - temp_opin_rr_nodes[0] = find_rr_graph_grid_nodes(rr_graph, grids, - gsb_coordinate.x() + 1, gsb_coordinate.y() + 1, - OPIN, opin_grid_side[0]); - /* include Grid[x+1][y] Top side output pins */ - temp_opin_rr_nodes[1] = find_rr_graph_grid_nodes(rr_graph, grids, - gsb_coordinate.x() + 1, gsb_coordinate.y(), - OPIN, opin_grid_side[1]); - break; - case BOTTOM: /* BOTTOM = 2*/ - /* For the bording, we should take special care */ - if (gsb_coordinate.y() == 0) { - rr_gsb.clear_one_side(side_manager.get_side()); - break; - } - /* Routing channels*/ - /* SideManager: TOP => 0, RIGHT => 1, BOTTOM => 2, LEFT => 3 */ - /* Collect rr_nodes for Tracks for bottom: chany[x][y] */ - /* Create a rr_chan object and check if it is unique in the graph */ - rr_chan = build_one_tileable_rr_chan(coordinate, CHANY, rr_graph, chany_details); - chan_dir_to_port_dir_mapping[0] = IN_PORT; /* INC_DIRECTION => IN_PORT */ - chan_dir_to_port_dir_mapping[1] = OUT_PORT; /* DEC_DIRECTION => OUT_PORT */ - - /* Assign grid side of OPIN */ - /* Grid[x+1][y] LEFT side outputs pins */ - opin_grid_side[0] = LEFT; - /* Grid[x][y] RIGHT side outputs pins */ - opin_grid_side[1] = RIGHT; - - /* Build the Switch block: opin and opin_grid_side */ - /* include Grid[x+1][y] Left side output pins */ - temp_opin_rr_nodes[0] = find_rr_graph_grid_nodes(rr_graph, grids, - gsb_coordinate.x() + 1, gsb_coordinate.y(), - OPIN, opin_grid_side[0]); - /* include Grid[x][y] Right side output pins */ - temp_opin_rr_nodes[1] = find_rr_graph_grid_nodes(rr_graph, grids, - gsb_coordinate.x(), gsb_coordinate.y(), - OPIN, opin_grid_side[1]); - break; - case LEFT: /* LEFT = 3 */ - /* For the bording, we should take special care */ - if (gsb_coordinate.x() == 0) { - rr_gsb.clear_one_side(side_manager.get_side()); - break; - } - /* Routing channels*/ - /* SideManager: TOP => 0, RIGHT => 1, BOTTOM => 2, LEFT => 3 */ - /* Collect rr_nodes for Tracks for left: chanx[x][y] */ - /* Create a rr_chan object and check if it is unique in the graph */ - rr_chan = build_one_tileable_rr_chan(coordinate, CHANX, rr_graph, chanx_details); - chan_dir_to_port_dir_mapping[0] = IN_PORT; /* INC_DIRECTION => IN_PORT */ - chan_dir_to_port_dir_mapping[1] = OUT_PORT; /* DEC_DIRECTION => OUT_PORT */ - - /* Grid[x][y+1] BOTTOM side outputs pins */ - opin_grid_side[0] = BOTTOM; - /* Grid[x][y] TOP side outputs pins */ - opin_grid_side[1] = TOP; - - /* Build the Switch block: opin and opin_grid_side */ - /* include Grid[x][y+1] Bottom side outputs pins */ - temp_opin_rr_nodes[0] = find_rr_graph_grid_nodes(rr_graph, grids, - gsb_coordinate.x(), gsb_coordinate.y() + 1, - OPIN, opin_grid_side[0]); - /* include Grid[x][y] Top side output pins */ - temp_opin_rr_nodes[1] = find_rr_graph_grid_nodes(rr_graph, grids, - gsb_coordinate.x(), gsb_coordinate.y(), - OPIN, opin_grid_side[1]); - - break; - default: - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid side index!\n"); - exit(1); - } + ChanNodeDetails chanx_details = build_unidir_chan_node_details(device_chan_width.x(), grids.width() - 1, + false, false, segment_inf); + ChanNodeDetails chany_details = build_unidir_chan_node_details(device_chan_width.y(), grids.height() - 1, + false, false, segment_inf); + + switch (side) { + case TOP: /* TOP = 0 */ + /* For the bording, we should take special care */ + if (gsb_coordinate.y() == grids.height() - 1) { + rr_gsb.clear_one_side(side_manager.get_side()); + break; + } + /* Routing channels*/ + /* SideManager: TOP => 0, RIGHT => 1, BOTTOM => 2, LEFT => 3 */ + /* Create a rr_chan object and check if it is unique in the graph */ + rr_chan = build_one_tileable_rr_chan(coordinate, CHANY, rr_graph, chany_details); + chan_dir_to_port_dir_mapping[0] = OUT_PORT; /* INC_DIRECTION => OUT_PORT */ + chan_dir_to_port_dir_mapping[1] = IN_PORT; /* DEC_DIRECTION => IN_PORT */ + + /* Assign grid side of OPIN */ + /* Grid[x][y+1] RIGHT side outputs pins */ + opin_grid_side[0] = RIGHT; + /* Grid[x+1][y+1] left side outputs pins */ + opin_grid_side[1] = LEFT; + + /* Build the Switch block: opin and opin_grid_side */ + /* Include Grid[x][y+1] RIGHT side outputs pins */ + temp_opin_rr_nodes[0] = find_rr_graph_grid_nodes(rr_graph, grids, + gsb_coordinate.x(), gsb_coordinate.y() + 1, + OPIN, opin_grid_side[0]); + /* Include Grid[x+1][y+1] Left side output pins */ + temp_opin_rr_nodes[1] = find_rr_graph_grid_nodes(rr_graph, grids, + gsb_coordinate.x() + 1, gsb_coordinate.y() + 1, + OPIN, opin_grid_side[1]); + + break; + case RIGHT: /* RIGHT = 1 */ + /* For the bording, we should take special care */ + if (gsb_coordinate.x() == grids.width() - 1) { + rr_gsb.clear_one_side(side_manager.get_side()); + break; + } + /* Routing channels*/ + /* SideManager: TOP => 0, RIGHT => 1, BOTTOM => 2, LEFT => 3 */ + /* Collect rr_nodes for Tracks for top: chany[x][y+1] */ + /* Create a rr_chan object and check if it is unique in the graph */ + rr_chan = build_one_tileable_rr_chan(coordinate, CHANX, rr_graph, chanx_details); + chan_dir_to_port_dir_mapping[0] = OUT_PORT; /* INC_DIRECTION => OUT_PORT */ + chan_dir_to_port_dir_mapping[1] = IN_PORT; /* DEC_DIRECTION => IN_PORT */ + + /* Assign grid side of OPIN */ + /* Grid[x+1][y+1] BOTTOM side outputs pins */ + opin_grid_side[0] = BOTTOM; + /* Grid[x+1][y] TOP side outputs pins */ + opin_grid_side[1] = TOP; + + /* Build the Switch block: opin and opin_grid_side */ + /* include Grid[x+1][y+1] Bottom side output pins */ + temp_opin_rr_nodes[0] = find_rr_graph_grid_nodes(rr_graph, grids, + gsb_coordinate.x() + 1, gsb_coordinate.y() + 1, + OPIN, opin_grid_side[0]); + /* include Grid[x+1][y] Top side output pins */ + temp_opin_rr_nodes[1] = find_rr_graph_grid_nodes(rr_graph, grids, + gsb_coordinate.x() + 1, gsb_coordinate.y(), + OPIN, opin_grid_side[1]); + break; + case BOTTOM: /* BOTTOM = 2*/ + /* For the bording, we should take special care */ + if (gsb_coordinate.y() == 0) { + rr_gsb.clear_one_side(side_manager.get_side()); + break; + } + /* Routing channels*/ + /* SideManager: TOP => 0, RIGHT => 1, BOTTOM => 2, LEFT => 3 */ + /* Collect rr_nodes for Tracks for bottom: chany[x][y] */ + /* Create a rr_chan object and check if it is unique in the graph */ + rr_chan = build_one_tileable_rr_chan(coordinate, CHANY, rr_graph, chany_details); + chan_dir_to_port_dir_mapping[0] = IN_PORT; /* INC_DIRECTION => IN_PORT */ + chan_dir_to_port_dir_mapping[1] = OUT_PORT; /* DEC_DIRECTION => OUT_PORT */ + + /* Assign grid side of OPIN */ + /* Grid[x+1][y] LEFT side outputs pins */ + opin_grid_side[0] = LEFT; + /* Grid[x][y] RIGHT side outputs pins */ + opin_grid_side[1] = RIGHT; + + /* Build the Switch block: opin and opin_grid_side */ + /* include Grid[x+1][y] Left side output pins */ + temp_opin_rr_nodes[0] = find_rr_graph_grid_nodes(rr_graph, grids, + gsb_coordinate.x() + 1, gsb_coordinate.y(), + OPIN, opin_grid_side[0]); + /* include Grid[x][y] Right side output pins */ + temp_opin_rr_nodes[1] = find_rr_graph_grid_nodes(rr_graph, grids, + gsb_coordinate.x(), gsb_coordinate.y(), + OPIN, opin_grid_side[1]); + break; + case LEFT: /* LEFT = 3 */ + /* For the bording, we should take special care */ + if (gsb_coordinate.x() == 0) { + rr_gsb.clear_one_side(side_manager.get_side()); + break; + } + /* Routing channels*/ + /* SideManager: TOP => 0, RIGHT => 1, BOTTOM => 2, LEFT => 3 */ + /* Collect rr_nodes for Tracks for left: chanx[x][y] */ + /* Create a rr_chan object and check if it is unique in the graph */ + rr_chan = build_one_tileable_rr_chan(coordinate, CHANX, rr_graph, chanx_details); + chan_dir_to_port_dir_mapping[0] = IN_PORT; /* INC_DIRECTION => IN_PORT */ + chan_dir_to_port_dir_mapping[1] = OUT_PORT; /* DEC_DIRECTION => OUT_PORT */ + + /* Grid[x][y+1] BOTTOM side outputs pins */ + opin_grid_side[0] = BOTTOM; + /* Grid[x][y] TOP side outputs pins */ + opin_grid_side[1] = TOP; + + /* Build the Switch block: opin and opin_grid_side */ + /* include Grid[x][y+1] Bottom side outputs pins */ + temp_opin_rr_nodes[0] = find_rr_graph_grid_nodes(rr_graph, grids, + gsb_coordinate.x(), gsb_coordinate.y() + 1, + OPIN, opin_grid_side[0]); + /* include Grid[x][y] Top side output pins */ + temp_opin_rr_nodes[1] = find_rr_graph_grid_nodes(rr_graph, grids, + gsb_coordinate.x(), gsb_coordinate.y(), + OPIN, opin_grid_side[1]); + + break; + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid side index!\n"); + exit(1); + } - /* Organize a vector of port direction */ - if (0 < rr_chan.get_chan_width()) { - std::vector rr_chan_dir; - rr_chan_dir.resize(rr_chan.get_chan_width()); - for (size_t itrack = 0; itrack < rr_chan.get_chan_width(); ++itrack) { - /* Identify the directionality, record it in rr_node_direction */ - if (Direction::INC == rr_graph.node_direction(rr_chan.get_node(itrack))) { - rr_chan_dir[itrack] = chan_dir_to_port_dir_mapping[0]; - } else { - VTR_ASSERT(Direction::DEC == rr_graph.node_direction(rr_chan.get_node(itrack))); - rr_chan_dir[itrack] = chan_dir_to_port_dir_mapping[1]; + /* Organize a vector of port direction */ + if (0 < rr_chan.get_chan_width()) { + std::vector rr_chan_dir; + rr_chan_dir.resize(rr_chan.get_chan_width()); + for (size_t itrack = 0; itrack < rr_chan.get_chan_width(); ++itrack) { + /* Identify the directionality, record it in rr_node_direction */ + if (Direction::INC == rr_graph.node_direction(rr_chan.get_node(itrack))) { + rr_chan_dir[itrack] = chan_dir_to_port_dir_mapping[0]; + } else { + VTR_ASSERT(Direction::DEC == rr_graph.node_direction(rr_chan.get_node(itrack))); + rr_chan_dir[itrack] = chan_dir_to_port_dir_mapping[1]; + } + } + /* Fill chan_rr_nodes */ + rr_gsb.add_chan_node(side_manager.get_side(), rr_chan, rr_chan_dir); } - } - /* Fill chan_rr_nodes */ - rr_gsb.add_chan_node(side_manager.get_side(), rr_chan, rr_chan_dir); - } - /* Fill opin_rr_nodes */ - /* Copy from temp_opin_rr_node to opin_rr_node */ - for (const RRNodeId& inode : temp_opin_rr_nodes[0]) { - /* Grid[x+1][y+1] Bottom side outputs pins */ - rr_gsb.add_opin_node(inode, side_manager.get_side()); - } - for (const RRNodeId& inode : temp_opin_rr_nodes[1]) { - /* Grid[x+1][y] TOP side outputs pins */ - rr_gsb.add_opin_node(inode, side_manager.get_side()); - } + /* Fill opin_rr_nodes */ + /* Copy from temp_opin_rr_node to opin_rr_node */ + for (const RRNodeId& inode : temp_opin_rr_nodes[0]) { + /* Grid[x+1][y+1] Bottom side outputs pins */ + rr_gsb.add_opin_node(inode, side_manager.get_side()); + } + for (const RRNodeId& inode : temp_opin_rr_nodes[1]) { + /* Grid[x+1][y] TOP side outputs pins */ + rr_gsb.add_opin_node(inode, side_manager.get_side()); + } - /* Clean ipin_rr_nodes */ - /* We do not have any IPIN for a Switch Block */ - rr_gsb.clear_ipin_nodes(side_manager.get_side()); + /* Clean ipin_rr_nodes */ + /* We do not have any IPIN for a Switch Block */ + rr_gsb.clear_ipin_nodes(side_manager.get_side()); - /* Clear the temp data */ - temp_opin_rr_nodes[0].clear(); - temp_opin_rr_nodes[1].clear(); - opin_grid_side[0] = NUM_SIDES; - opin_grid_side[1] = NUM_SIDES; - } + /* Clear the temp data */ + temp_opin_rr_nodes[0].clear(); + temp_opin_rr_nodes[1].clear(); + opin_grid_side[0] = NUM_SIDES; + opin_grid_side[1] = NUM_SIDES; + } - /* Add IPIN nodes from adjacent grids: the 4 grids sitting on the 4 corners of the Switch Block + /* Add IPIN nodes from adjacent grids: the 4 grids sitting on the 4 corners of the Switch Block * * - The concept of top/bottom side of connection block in GSB domain: * @@ -849,69 +840,69 @@ RRGSB build_one_tileable_rr_gsb(const DeviceGrid& grids, * --------------+ +---------------------- ... ---------------------+ +---------------- * */ - for (size_t side = 0; side < rr_gsb.get_num_sides(); ++side) { - SideManager side_manager(side); - size_t ix; - size_t iy; - enum e_side chan_side; - std::vector temp_ipin_rr_nodes; - enum e_side ipin_rr_node_grid_side; - - switch (side) { - case TOP: - /* Consider the routing channel that is connected to the left side of the switch block */ - chan_side = LEFT; - /* The input pins of the routing channel come from the bottom side of Grid[x][y+1] */ - ix = rr_gsb.get_sb_x(); - iy = rr_gsb.get_sb_y() + 1; - ipin_rr_node_grid_side = BOTTOM; - break; - case RIGHT: - /* Consider the routing channel that is connected to the top side of the switch block */ - chan_side = TOP; - /* The input pins of the routing channel come from the left side of Grid[x+1][y+1] */ - ix = rr_gsb.get_sb_x() + 1; - iy = rr_gsb.get_sb_y() + 1; - ipin_rr_node_grid_side = LEFT; - break; - case BOTTOM: - /* Consider the routing channel that is connected to the left side of the switch block */ - chan_side = LEFT; - /* The input pins of the routing channel come from the top side of Grid[x][y] */ - ix = rr_gsb.get_sb_x(); - iy = rr_gsb.get_sb_y(); - ipin_rr_node_grid_side = TOP; - break; - case LEFT: - /* Consider the routing channel that is connected to the top side of the switch block */ - chan_side = TOP; - /* The input pins of the routing channel come from the right side of Grid[x][y+1] */ - ix = rr_gsb.get_sb_x(); - iy = rr_gsb.get_sb_y() + 1; - ipin_rr_node_grid_side = RIGHT; - break; - default: - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid side index!\n"); - exit(1); - } - - /* If there is no channel at this side, we skip ipin_node annotation */ - if (0 == rr_gsb.get_chan_width(chan_side)) { - continue; - } - /* Collect IPIN rr_nodes*/ - temp_ipin_rr_nodes = find_rr_graph_grid_nodes(rr_graph, grids, - ix, iy, IPIN, ipin_rr_node_grid_side); - /* Fill the ipin nodes of RRGSB */ - for (const RRNodeId& inode : temp_ipin_rr_nodes) { - rr_gsb.add_ipin_node(inode, side_manager.get_side()); + for (size_t side = 0; side < rr_gsb.get_num_sides(); ++side) { + SideManager side_manager(side); + size_t ix; + size_t iy; + enum e_side chan_side; + std::vector temp_ipin_rr_nodes; + enum e_side ipin_rr_node_grid_side; + + switch (side) { + case TOP: + /* Consider the routing channel that is connected to the left side of the switch block */ + chan_side = LEFT; + /* The input pins of the routing channel come from the bottom side of Grid[x][y+1] */ + ix = rr_gsb.get_sb_x(); + iy = rr_gsb.get_sb_y() + 1; + ipin_rr_node_grid_side = BOTTOM; + break; + case RIGHT: + /* Consider the routing channel that is connected to the top side of the switch block */ + chan_side = TOP; + /* The input pins of the routing channel come from the left side of Grid[x+1][y+1] */ + ix = rr_gsb.get_sb_x() + 1; + iy = rr_gsb.get_sb_y() + 1; + ipin_rr_node_grid_side = LEFT; + break; + case BOTTOM: + /* Consider the routing channel that is connected to the left side of the switch block */ + chan_side = LEFT; + /* The input pins of the routing channel come from the top side of Grid[x][y] */ + ix = rr_gsb.get_sb_x(); + iy = rr_gsb.get_sb_y(); + ipin_rr_node_grid_side = TOP; + break; + case LEFT: + /* Consider the routing channel that is connected to the top side of the switch block */ + chan_side = TOP; + /* The input pins of the routing channel come from the right side of Grid[x][y+1] */ + ix = rr_gsb.get_sb_x(); + iy = rr_gsb.get_sb_y() + 1; + ipin_rr_node_grid_side = RIGHT; + break; + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid side index!\n"); + exit(1); + } + + /* If there is no channel at this side, we skip ipin_node annotation */ + if (0 == rr_gsb.get_chan_width(chan_side)) { + continue; + } + /* Collect IPIN rr_nodes*/ + temp_ipin_rr_nodes = find_rr_graph_grid_nodes(rr_graph, grids, + ix, iy, IPIN, ipin_rr_node_grid_side); + /* Fill the ipin nodes of RRGSB */ + for (const RRNodeId& inode : temp_ipin_rr_nodes) { + rr_gsb.add_ipin_node(inode, side_manager.get_side()); + } + /* Clear the temp data */ + temp_ipin_rr_nodes.clear(); } - /* Clear the temp data */ - temp_ipin_rr_nodes.clear(); - } - return rr_gsb; + return rr_gsb; } /************************************************************************ @@ -920,52 +911,51 @@ RRGSB build_one_tileable_rr_gsb(const DeviceGrid& grids, * 2. create edges between OPINs, CHANX and CHANY (connections inside switch blocks) * 3. create edges between OPINs and IPINs (direct-connections) ***********************************************************************/ -void build_edges_for_one_tileable_rr_gsb(RRGraph& rr_graph, +void build_edges_for_one_tileable_rr_gsb(RRGraph& rr_graph, const RRGSB& rr_gsb, const t_track2pin_map& track2ipin_map, const t_pin2track_map& opin2track_map, const t_track2track_map& track2track_map, const vtr::vector& rr_node_driver_switches) { - - /* Walk through each sides */ - for (size_t side = 0; side < rr_gsb.get_num_sides(); ++side) { - SideManager side_manager(side); - enum e_side gsb_side = side_manager.get_side(); - - /* Find OPINs */ - for (size_t inode = 0; inode < rr_gsb.get_num_opin_nodes(gsb_side); ++inode) { - const RRNodeId& opin_node = rr_gsb.get_opin_node(gsb_side, inode); - - /* 1. create edges between OPINs and CHANX|CHANY, using opin2track_map */ - /* add edges to the opin_node */ - for (const RRNodeId& track_node : opin2track_map[gsb_side][inode]) { - rr_graph.create_edge(opin_node, track_node, rr_node_driver_switches[track_node]); - } - } + /* Walk through each sides */ + for (size_t side = 0; side < rr_gsb.get_num_sides(); ++side) { + SideManager side_manager(side); + enum e_side gsb_side = side_manager.get_side(); + + /* Find OPINs */ + for (size_t inode = 0; inode < rr_gsb.get_num_opin_nodes(gsb_side); ++inode) { + const RRNodeId& opin_node = rr_gsb.get_opin_node(gsb_side, inode); + + /* 1. create edges between OPINs and CHANX|CHANY, using opin2track_map */ + /* add edges to the opin_node */ + for (const RRNodeId& track_node : opin2track_map[gsb_side][inode]) { + rr_graph.create_edge(opin_node, track_node, rr_node_driver_switches[track_node]); + } + } - /* Find CHANX or CHANY */ - /* For TRACKs to IPINs, we only care LEFT and TOP sides + /* Find CHANX or CHANY */ + /* For TRACKs to IPINs, we only care LEFT and TOP sides * Skip RIGHT and BOTTOM for the ipin2track_map since they should be handled in other GSBs */ - if ( (side_manager.get_side() == rr_gsb.get_cb_chan_side(CHANX)) - || (side_manager.get_side() == rr_gsb.get_cb_chan_side(CHANY)) ) { - /* 2. create edges between CHANX|CHANY and IPINs, using ipin2track_map */ - for (size_t inode = 0; inode < rr_gsb.get_chan_width(gsb_side); ++inode) { - const RRNodeId& chan_node = rr_gsb.get_chan_node(gsb_side, inode); - for (const RRNodeId& ipin_node : track2ipin_map[gsb_side][inode]) { - rr_graph.create_edge(chan_node, ipin_node, rr_node_driver_switches[ipin_node]); + if ((side_manager.get_side() == rr_gsb.get_cb_chan_side(CHANX)) + || (side_manager.get_side() == rr_gsb.get_cb_chan_side(CHANY))) { + /* 2. create edges between CHANX|CHANY and IPINs, using ipin2track_map */ + for (size_t inode = 0; inode < rr_gsb.get_chan_width(gsb_side); ++inode) { + const RRNodeId& chan_node = rr_gsb.get_chan_node(gsb_side, inode); + for (const RRNodeId& ipin_node : track2ipin_map[gsb_side][inode]) { + rr_graph.create_edge(chan_node, ipin_node, rr_node_driver_switches[ipin_node]); + } + } } - } - } - /* 3. create edges between CHANX|CHANY and CHANX|CHANY, using track2track_map */ - for (size_t inode = 0; inode < rr_gsb.get_chan_width(gsb_side); ++inode) { - const RRNodeId& chan_node = rr_gsb.get_chan_node(gsb_side, inode); - for (const RRNodeId& track_node : track2track_map[gsb_side][inode]) { - rr_graph.create_edge(chan_node, track_node, rr_node_driver_switches[track_node]); - } + /* 3. create edges between CHANX|CHANY and CHANX|CHANY, using track2track_map */ + for (size_t inode = 0; inode < rr_gsb.get_chan_width(gsb_side); ++inode) { + const RRNodeId& chan_node = rr_gsb.get_chan_node(gsb_side, inode); + for (const RRNodeId& track_node : track2track_map[gsb_side][inode]) { + rr_graph.create_edge(chan_node, track_node, rr_node_driver_switches[track_node]); + } + } } - } } /************************************************************************ @@ -979,87 +969,86 @@ void build_edges_for_one_tileable_rr_gsb(RRGraph& rr_graph, * 3. Scale the Fc of each pin to the actual number of routing tracks * actual_Fc = (int) Fc * num_tracks / chan_width ***********************************************************************/ -static -void build_gsb_one_ipin_track2pin_map(const RRGraph& rr_graph, - const RRGSB& rr_gsb, - const enum e_side& ipin_side, - const size_t& ipin_node_id, - const std::vector& Fc, - const size_t& offset, - const std::vector& segment_inf, - t_track2pin_map& track2ipin_map) { - /* Get a list of segment_ids*/ - enum e_side chan_side = rr_gsb.get_cb_chan_side(ipin_side); - SideManager chan_side_manager(chan_side); - std::vector seg_list = rr_gsb.get_chan_segment_ids(chan_side); - size_t chan_width = rr_gsb.get_chan_width(chan_side); - SideManager ipin_side_manager(ipin_side); - const RRNodeId& ipin_node = rr_gsb.get_ipin_node(ipin_side, ipin_node_id); - - for (size_t iseg = 0; iseg < seg_list.size(); ++iseg) { - /* Get a list of node that have the segment id */ - std::vector track_list = rr_gsb.get_chan_node_ids_by_segment_ids(chan_side, seg_list[iseg]); - /* Refine the track_list: keep those will have connection blocks in the GSB */ - std::vector actual_track_list; - for (size_t inode = 0; inode < track_list.size(); ++inode) { - /* Check if tracks allow connection blocks in the GSB*/ - if (false == is_gsb_in_track_cb_population(rr_graph, rr_gsb, chan_side, track_list[inode], segment_inf)) { - continue; /* Bypass condition */ - } - /* Push the node to actual_track_list */ - actual_track_list.push_back(track_list[inode]); - } - /* Check the actual track list */ - VTR_ASSERT(0 == actual_track_list.size() % 2); - - /* Scale Fc */ - int actual_Fc = std::ceil((float)Fc[iseg] * (float)actual_track_list.size() / (float)chan_width); - /* Minimum Fc should be 2 : ensure we will connect to a pair of routing tracks */ - actual_Fc = std::max(1, actual_Fc); - /* Compute the step between two connection from this IPIN to tracks: +static void build_gsb_one_ipin_track2pin_map(const RRGraph& rr_graph, + const RRGSB& rr_gsb, + const enum e_side& ipin_side, + const size_t& ipin_node_id, + const std::vector& Fc, + const size_t& offset, + const std::vector& segment_inf, + t_track2pin_map& track2ipin_map) { + /* Get a list of segment_ids*/ + enum e_side chan_side = rr_gsb.get_cb_chan_side(ipin_side); + SideManager chan_side_manager(chan_side); + std::vector seg_list = rr_gsb.get_chan_segment_ids(chan_side); + size_t chan_width = rr_gsb.get_chan_width(chan_side); + SideManager ipin_side_manager(ipin_side); + const RRNodeId& ipin_node = rr_gsb.get_ipin_node(ipin_side, ipin_node_id); + + for (size_t iseg = 0; iseg < seg_list.size(); ++iseg) { + /* Get a list of node that have the segment id */ + std::vector track_list = rr_gsb.get_chan_node_ids_by_segment_ids(chan_side, seg_list[iseg]); + /* Refine the track_list: keep those will have connection blocks in the GSB */ + std::vector actual_track_list; + for (size_t inode = 0; inode < track_list.size(); ++inode) { + /* Check if tracks allow connection blocks in the GSB*/ + if (false == is_gsb_in_track_cb_population(rr_graph, rr_gsb, chan_side, track_list[inode], segment_inf)) { + continue; /* Bypass condition */ + } + /* Push the node to actual_track_list */ + actual_track_list.push_back(track_list[inode]); + } + /* Check the actual track list */ + VTR_ASSERT(0 == actual_track_list.size() % 2); + + /* Scale Fc */ + int actual_Fc = std::ceil((float)Fc[iseg] * (float)actual_track_list.size() / (float)chan_width); + /* Minimum Fc should be 2 : ensure we will connect to a pair of routing tracks */ + actual_Fc = std::max(1, actual_Fc); + /* Compute the step between two connection from this IPIN to tracks: * step = W' / Fc', W' and Fc' are the adapted W and Fc from actual_track_list and Fc_in */ - size_t track_step = std::floor((float)actual_track_list.size() / (float)actual_Fc); - /* Make sure step should be at least 2 */ - track_step = std::max(1, (int)track_step); - /* Adapt offset to the range of actual_track_list */ - size_t actual_offset = offset % actual_track_list.size(); - /* rotate the track list by an offset */ - if (0 < actual_offset) { - std::rotate(actual_track_list.begin(), actual_track_list.begin() + actual_offset, actual_track_list.end()); - } + size_t track_step = std::floor((float)actual_track_list.size() / (float)actual_Fc); + /* Make sure step should be at least 2 */ + track_step = std::max(1, (int)track_step); + /* Adapt offset to the range of actual_track_list */ + size_t actual_offset = offset % actual_track_list.size(); + /* rotate the track list by an offset */ + if (0 < actual_offset) { + std::rotate(actual_track_list.begin(), actual_track_list.begin() + actual_offset, actual_track_list.end()); + } - /* Assign tracks: since we assign 2 track per round, we increment itrack by 2* step */ - int track_cnt = 0; - /* Keep assigning until we meet the Fc requirement */ - for (size_t itrack = 0; itrack < actual_track_list.size(); itrack = itrack + 2 * track_step) { - /* Update pin2track map */ - size_t chan_side_index = chan_side_manager.to_size_t(); - /* itrack may exceed the size of actual_track_list, adapt it */ - size_t actual_itrack = itrack % actual_track_list.size(); - /* track_index may exceed the chan_width(), adapt it */ - size_t track_index = actual_track_list[actual_itrack] % chan_width; + /* Assign tracks: since we assign 2 track per round, we increment itrack by 2* step */ + int track_cnt = 0; + /* Keep assigning until we meet the Fc requirement */ + for (size_t itrack = 0; itrack < actual_track_list.size(); itrack = itrack + 2 * track_step) { + /* Update pin2track map */ + size_t chan_side_index = chan_side_manager.to_size_t(); + /* itrack may exceed the size of actual_track_list, adapt it */ + size_t actual_itrack = itrack % actual_track_list.size(); + /* track_index may exceed the chan_width(), adapt it */ + size_t track_index = actual_track_list[actual_itrack] % chan_width; - track2ipin_map[chan_side_index][track_index].push_back(ipin_node); + track2ipin_map[chan_side_index][track_index].push_back(ipin_node); - /* track_index may exceed the chan_width(), adapt it */ - track_index = (actual_track_list[actual_itrack] + 1) % chan_width; + /* track_index may exceed the chan_width(), adapt it */ + track_index = (actual_track_list[actual_itrack] + 1) % chan_width; - track2ipin_map[chan_side_index][track_index].push_back(ipin_node); + track2ipin_map[chan_side_index][track_index].push_back(ipin_node); - track_cnt += 2; - } + track_cnt += 2; + } - /* Ensure the number of tracks is similar to Fc */ - /* Give a warning if Fc is < track_cnt */ - /* + /* Ensure the number of tracks is similar to Fc */ + /* Give a warning if Fc is < track_cnt */ + /* if (actual_Fc != track_cnt) { vpr_printf(TIO_MESSAGE_INFO, "IPIN Node(%lu) will have a different Fc(=%lu) than specified(=%lu)!\n", ipin_node - rr_graph->rr_node, track_cnt, actual_Fc); } */ - } + } } /************************************************************************ @@ -1073,98 +1062,95 @@ void build_gsb_one_ipin_track2pin_map(const RRGraph& rr_graph, * 3. Scale the Fc of each pin to the actual number of routing tracks * actual_Fc = (int) Fc * num_tracks / chan_width ***********************************************************************/ -static -void build_gsb_one_opin_pin2track_map(const RRGraph& rr_graph, - const RRGSB& rr_gsb, - const enum e_side& opin_side, - const size_t& opin_node_id, - const std::vector& Fc, - const size_t& offset, - const std::vector& segment_inf, - t_pin2track_map& opin2track_map) { - /* Get a list of segment_ids*/ - std::vector seg_list = rr_gsb.get_chan_segment_ids(opin_side); - enum e_side chan_side = opin_side; - size_t chan_width = rr_gsb.get_chan_width(chan_side); - SideManager opin_side_manager(opin_side); - - for (size_t iseg = 0; iseg < seg_list.size(); ++iseg) { - /* Get a list of node that have the segment id */ - std::vector track_list = rr_gsb.get_chan_node_ids_by_segment_ids(chan_side, seg_list[iseg]); - /* Refine the track_list: keep those will have connection blocks in the GSB */ - std::vector actual_track_list; - for (size_t inode = 0; inode < track_list.size(); ++inode) { - /* Check if tracks allow connection blocks in the GSB*/ - if (false == is_gsb_in_track_sb_population(rr_graph, rr_gsb, chan_side, - track_list[inode], segment_inf)) { - continue; /* Bypass condition */ - } - if (TRACK_START != determine_track_status_of_gsb(rr_graph, rr_gsb, chan_side, track_list[inode])) { - continue; /* Bypass condition */ - } - /* Push the node to actual_track_list */ - actual_track_list.push_back(track_list[inode]); - } +static void build_gsb_one_opin_pin2track_map(const RRGraph& rr_graph, + const RRGSB& rr_gsb, + const enum e_side& opin_side, + const size_t& opin_node_id, + const std::vector& Fc, + const size_t& offset, + const std::vector& segment_inf, + t_pin2track_map& opin2track_map) { + /* Get a list of segment_ids*/ + std::vector seg_list = rr_gsb.get_chan_segment_ids(opin_side); + enum e_side chan_side = opin_side; + size_t chan_width = rr_gsb.get_chan_width(chan_side); + SideManager opin_side_manager(opin_side); + + for (size_t iseg = 0; iseg < seg_list.size(); ++iseg) { + /* Get a list of node that have the segment id */ + std::vector track_list = rr_gsb.get_chan_node_ids_by_segment_ids(chan_side, seg_list[iseg]); + /* Refine the track_list: keep those will have connection blocks in the GSB */ + std::vector actual_track_list; + for (size_t inode = 0; inode < track_list.size(); ++inode) { + /* Check if tracks allow connection blocks in the GSB*/ + if (false == is_gsb_in_track_sb_population(rr_graph, rr_gsb, chan_side, track_list[inode], segment_inf)) { + continue; /* Bypass condition */ + } + if (TRACK_START != determine_track_status_of_gsb(rr_graph, rr_gsb, chan_side, track_list[inode])) { + continue; /* Bypass condition */ + } + /* Push the node to actual_track_list */ + actual_track_list.push_back(track_list[inode]); + } - /* Go the next segment if offset is zero or actual_track_list is empty */ - if (0 == actual_track_list.size()) { - continue; - } - - /* Scale Fc */ - int actual_Fc = std::ceil((float)Fc[iseg] * (float)actual_track_list.size() / (float)chan_width); - /* Minimum Fc should be 1 : ensure we will drive 1 routing track */ - actual_Fc = std::max(1, actual_Fc); - /* Compute the step between two connection from this IPIN to tracks: + /* Go the next segment if offset is zero or actual_track_list is empty */ + if (0 == actual_track_list.size()) { + continue; + } + + /* Scale Fc */ + int actual_Fc = std::ceil((float)Fc[iseg] * (float)actual_track_list.size() / (float)chan_width); + /* Minimum Fc should be 1 : ensure we will drive 1 routing track */ + actual_Fc = std::max(1, actual_Fc); + /* Compute the step between two connection from this IPIN to tracks: * step = W' / Fc', W' and Fc' are the adapted W and Fc from actual_track_list and Fc_in */ - size_t track_step = std::floor((float)actual_track_list.size() / (float)actual_Fc); - /* Track step mush be a multiple of 2!!!*/ - /* Make sure step should be at least 1 */ - track_step = std::max(1, (int)track_step); - /* Adapt offset to the range of actual_track_list */ - size_t actual_offset = offset % actual_track_list.size(); - - /* No need to rotate if offset is zero */ - if (0 < actual_offset) { - /* rotate the track list by an offset */ - std::rotate(actual_track_list.begin(), actual_track_list.begin() + actual_offset, actual_track_list.end()); - } + size_t track_step = std::floor((float)actual_track_list.size() / (float)actual_Fc); + /* Track step mush be a multiple of 2!!!*/ + /* Make sure step should be at least 1 */ + track_step = std::max(1, (int)track_step); + /* Adapt offset to the range of actual_track_list */ + size_t actual_offset = offset % actual_track_list.size(); + + /* No need to rotate if offset is zero */ + if (0 < actual_offset) { + /* rotate the track list by an offset */ + std::rotate(actual_track_list.begin(), actual_track_list.begin() + actual_offset, actual_track_list.end()); + } - /* Assign tracks */ - int track_cnt = 0; - /* Keep assigning until we meet the Fc requirement */ - for (size_t itrack = 0; itrack < actual_track_list.size(); itrack = itrack + track_step) { - /* Update pin2track map */ - size_t opin_side_index = opin_side_manager.to_size_t(); - /* itrack may exceed the size of actual_track_list, adapt it */ - size_t actual_itrack = itrack % actual_track_list.size(); - size_t track_index = actual_track_list[actual_itrack]; - const RRNodeId& track_rr_node_index = rr_gsb.get_chan_node(chan_side, track_index); - opin2track_map[opin_side_index][opin_node_id].push_back(track_rr_node_index); - /* update track counter */ - track_cnt++; - /* Stop when we have enough Fc: this may lead to some tracks have zero drivers. + /* Assign tracks */ + int track_cnt = 0; + /* Keep assigning until we meet the Fc requirement */ + for (size_t itrack = 0; itrack < actual_track_list.size(); itrack = itrack + track_step) { + /* Update pin2track map */ + size_t opin_side_index = opin_side_manager.to_size_t(); + /* itrack may exceed the size of actual_track_list, adapt it */ + size_t actual_itrack = itrack % actual_track_list.size(); + size_t track_index = actual_track_list[actual_itrack]; + const RRNodeId& track_rr_node_index = rr_gsb.get_chan_node(chan_side, track_index); + opin2track_map[opin_side_index][opin_node_id].push_back(track_rr_node_index); + /* update track counter */ + track_cnt++; + /* Stop when we have enough Fc: this may lead to some tracks have zero drivers. * So I comment it. And we just make sure its track_cnt >= actual_Fc if (actual_Fc == track_cnt) { break; } */ - } + } - /* Ensure the number of tracks is similar to Fc */ - /* Give a warning if Fc is < track_cnt */ - /* + /* Ensure the number of tracks is similar to Fc */ + /* Give a warning if Fc is < track_cnt */ + /* if (actual_Fc != track_cnt) { vpr_printf(TIO_MESSAGE_INFO, "OPIN Node(%lu) will have a different Fc(=%lu) than specified(=%lu)!\n", opin_node_id, track_cnt, actual_Fc); } */ - } + } } - /************************************************************************ * Build the track_to_ipin_map[gsb_side][0..chan_width-1][ipin_indices] * based on the existing routing resources in the General Switch Block (GSB) @@ -1176,81 +1162,81 @@ void build_gsb_one_opin_pin2track_map(const RRGraph& rr_graph, * 2. Convert the ipin_to_track_map to track_to_ipin_map ***********************************************************************/ t_track2pin_map build_gsb_track_to_ipin_map(const RRGraph& rr_graph, - const RRGSB& rr_gsb, - const DeviceGrid& grids, - const std::vector& segment_inf, + const RRGSB& rr_gsb, + const DeviceGrid& grids, + const std::vector& segment_inf, const std::vector>& Fc_in) { - t_track2pin_map track2ipin_map; - /* Resize the matrix */ - track2ipin_map.resize(rr_gsb.get_num_sides()); - - /* offset counter: it aims to balance the track-to-IPIN for each connection block */ - size_t offset_size = 0; - std::vector offset; - for (size_t side = 0; side < rr_gsb.get_num_sides(); ++side) { - SideManager side_manager(side); - enum e_side ipin_side = side_manager.get_side(); - /* Get the chan_side */ - enum e_side chan_side = rr_gsb.get_cb_chan_side(ipin_side); - SideManager chan_side_manager(chan_side); - /* resize offset to the maximum chan_side*/ - offset_size = std::max(offset_size, chan_side_manager.to_size_t() + 1); - } - /* Initial offset */ - offset.resize(offset_size); - offset.assign(offset.size(), 0); - - /* Walk through each side */ - for (size_t side = 0; side < rr_gsb.get_num_sides(); ++side) { - SideManager side_manager(side); - enum e_side ipin_side = side_manager.get_side(); - /* Get the chan_side */ - enum e_side chan_side = rr_gsb.get_cb_chan_side(ipin_side); - SideManager chan_side_manager(chan_side); - /* This track2pin mapping is for Connection Blocks, so we only care two sides! */ - /* Get channel width and resize the matrix */ - size_t chan_width = rr_gsb.get_chan_width(chan_side); - track2ipin_map[chan_side_manager.to_size_t()].resize(chan_width); - /* Find the ipin/opin nodes */ - for (size_t inode = 0; inode < rr_gsb.get_num_ipin_nodes(ipin_side); ++inode) { - const RRNodeId& ipin_node = rr_gsb.get_ipin_node(ipin_side, inode); - /* Skip EMPTY type */ - if (true == is_empty_type(grids[rr_graph.node_xlow(ipin_node)][rr_graph.node_ylow(ipin_node)].type)) { - continue; - } - - int grid_type_index = grids[rr_graph.node_xlow(ipin_node)][rr_graph.node_ylow(ipin_node)].type->index; - /* Get Fc of the ipin */ - /* skip Fc = 0 or unintialized, those pins are in the */ - bool skip_conn2track = true; - std::vector ipin_Fc_out; - for (size_t iseg = 0; iseg < segment_inf.size(); ++iseg) { - int ipin_Fc = Fc_in[grid_type_index][rr_graph.node_pin_num(ipin_node)][iseg]; - ipin_Fc_out.push_back(ipin_Fc); - if (0 != ipin_Fc) { - skip_conn2track = false; - continue; + t_track2pin_map track2ipin_map; + /* Resize the matrix */ + track2ipin_map.resize(rr_gsb.get_num_sides()); + + /* offset counter: it aims to balance the track-to-IPIN for each connection block */ + size_t offset_size = 0; + std::vector offset; + for (size_t side = 0; side < rr_gsb.get_num_sides(); ++side) { + SideManager side_manager(side); + enum e_side ipin_side = side_manager.get_side(); + /* Get the chan_side */ + enum e_side chan_side = rr_gsb.get_cb_chan_side(ipin_side); + SideManager chan_side_manager(chan_side); + /* resize offset to the maximum chan_side*/ + offset_size = std::max(offset_size, chan_side_manager.to_size_t() + 1); + } + /* Initial offset */ + offset.resize(offset_size); + offset.assign(offset.size(), 0); + + /* Walk through each side */ + for (size_t side = 0; side < rr_gsb.get_num_sides(); ++side) { + SideManager side_manager(side); + enum e_side ipin_side = side_manager.get_side(); + /* Get the chan_side */ + enum e_side chan_side = rr_gsb.get_cb_chan_side(ipin_side); + SideManager chan_side_manager(chan_side); + /* This track2pin mapping is for Connection Blocks, so we only care two sides! */ + /* Get channel width and resize the matrix */ + size_t chan_width = rr_gsb.get_chan_width(chan_side); + track2ipin_map[chan_side_manager.to_size_t()].resize(chan_width); + /* Find the ipin/opin nodes */ + for (size_t inode = 0; inode < rr_gsb.get_num_ipin_nodes(ipin_side); ++inode) { + const RRNodeId& ipin_node = rr_gsb.get_ipin_node(ipin_side, inode); + /* Skip EMPTY type */ + if (true == is_empty_type(grids[rr_graph.node_xlow(ipin_node)][rr_graph.node_ylow(ipin_node)].type)) { + continue; + } + + int grid_type_index = grids[rr_graph.node_xlow(ipin_node)][rr_graph.node_ylow(ipin_node)].type->index; + /* Get Fc of the ipin */ + /* skip Fc = 0 or unintialized, those pins are in the */ + bool skip_conn2track = true; + std::vector ipin_Fc_out; + for (size_t iseg = 0; iseg < segment_inf.size(); ++iseg) { + int ipin_Fc = Fc_in[grid_type_index][rr_graph.node_pin_num(ipin_node)][iseg]; + ipin_Fc_out.push_back(ipin_Fc); + if (0 != ipin_Fc) { + skip_conn2track = false; + continue; + } + } + + if (true == skip_conn2track) { + continue; + } + + VTR_ASSERT(ipin_Fc_out.size() == segment_inf.size()); + + /* Build track2ipin_map for this IPIN */ + build_gsb_one_ipin_track2pin_map(rr_graph, rr_gsb, ipin_side, inode, ipin_Fc_out, + /* Give an offset for the first track that this ipin will connect to */ + offset[chan_side_manager.to_size_t()], + segment_inf, track2ipin_map); + /* update offset */ + offset[chan_side_manager.to_size_t()] += 2; + //printf("offset[%lu]=%lu\n", chan_side_manager.to_size_t(), offset[chan_side_manager.to_size_t()]); } - } - - if (true == skip_conn2track) { - continue; - } - - VTR_ASSERT(ipin_Fc_out.size() == segment_inf.size()); - - /* Build track2ipin_map for this IPIN */ - build_gsb_one_ipin_track2pin_map(rr_graph, rr_gsb, ipin_side, inode, ipin_Fc_out, - /* Give an offset for the first track that this ipin will connect to */ - offset[chan_side_manager.to_size_t()], - segment_inf, track2ipin_map); - /* update offset */ - offset[chan_side_manager.to_size_t()] += 2; - //printf("offset[%lu]=%lu\n", chan_side_manager.to_size_t(), offset[chan_side_manager.to_size_t()]); } - } - return track2ipin_map; + return track2ipin_map; } /************************************************************************ @@ -1266,72 +1252,72 @@ t_track2pin_map build_gsb_track_to_ipin_map(const RRGraph& rr_graph, * actual_Fc = (int) Fc * num_tracks / chan_width ***********************************************************************/ t_pin2track_map build_gsb_opin_to_track_map(const RRGraph& rr_graph, - const RRGSB& rr_gsb, - const DeviceGrid& grids, - const std::vector& segment_inf, + const RRGSB& rr_gsb, + const DeviceGrid& grids, + const std::vector& segment_inf, const std::vector>& Fc_out) { - t_pin2track_map opin2track_map; - /* Resize the matrix */ - opin2track_map.resize(rr_gsb.get_num_sides()); - - /* offset counter: it aims to balance the OPIN-to-track for each switch block */ - std::vector offset; - /* Get the chan_side: which is the same as the opin side */ - offset.resize(rr_gsb.get_num_sides()); - /* Initial offset */ - offset.assign(offset.size(), 0); - - /* Walk through each side */ - for (size_t side = 0; side < rr_gsb.get_num_sides(); ++side) { - SideManager side_manager(side); - enum e_side opin_side = side_manager.get_side(); - /* Get the chan_side */ - /* This track2pin mapping is for Connection Blocks, so we only care two sides! */ - /* Get channel width and resize the matrix */ - size_t num_opin_nodes = rr_gsb.get_num_opin_nodes(opin_side); - opin2track_map[side].resize(num_opin_nodes); - /* Find the ipin/opin nodes */ - for (size_t inode = 0; inode < num_opin_nodes; ++inode) { - const RRNodeId& opin_node = rr_gsb.get_opin_node(opin_side, inode); - /* Skip EMPTY type */ - if (true == is_empty_type(grids[rr_graph.node_xlow(opin_node)][rr_graph.node_ylow(opin_node)].type)) { - continue; - } - int grid_type_index = grids[rr_graph.node_xlow(opin_node)][rr_graph.node_ylow(opin_node)].type->index; - - /* Get Fc of the ipin */ - /* skip Fc = 0 or unintialized, those pins are in the */ - bool skip_conn2track = true; - std::vector opin_Fc_out; - for (size_t iseg = 0; iseg < segment_inf.size(); ++iseg) { - int opin_Fc = Fc_out[grid_type_index][rr_graph.node_pin_num(opin_node)][iseg]; - opin_Fc_out.push_back(opin_Fc); - if (0 != opin_Fc) { - skip_conn2track = false; - continue; + t_pin2track_map opin2track_map; + /* Resize the matrix */ + opin2track_map.resize(rr_gsb.get_num_sides()); + + /* offset counter: it aims to balance the OPIN-to-track for each switch block */ + std::vector offset; + /* Get the chan_side: which is the same as the opin side */ + offset.resize(rr_gsb.get_num_sides()); + /* Initial offset */ + offset.assign(offset.size(), 0); + + /* Walk through each side */ + for (size_t side = 0; side < rr_gsb.get_num_sides(); ++side) { + SideManager side_manager(side); + enum e_side opin_side = side_manager.get_side(); + /* Get the chan_side */ + /* This track2pin mapping is for Connection Blocks, so we only care two sides! */ + /* Get channel width and resize the matrix */ + size_t num_opin_nodes = rr_gsb.get_num_opin_nodes(opin_side); + opin2track_map[side].resize(num_opin_nodes); + /* Find the ipin/opin nodes */ + for (size_t inode = 0; inode < num_opin_nodes; ++inode) { + const RRNodeId& opin_node = rr_gsb.get_opin_node(opin_side, inode); + /* Skip EMPTY type */ + if (true == is_empty_type(grids[rr_graph.node_xlow(opin_node)][rr_graph.node_ylow(opin_node)].type)) { + continue; + } + int grid_type_index = grids[rr_graph.node_xlow(opin_node)][rr_graph.node_ylow(opin_node)].type->index; + + /* Get Fc of the ipin */ + /* skip Fc = 0 or unintialized, those pins are in the */ + bool skip_conn2track = true; + std::vector opin_Fc_out; + for (size_t iseg = 0; iseg < segment_inf.size(); ++iseg) { + int opin_Fc = Fc_out[grid_type_index][rr_graph.node_pin_num(opin_node)][iseg]; + opin_Fc_out.push_back(opin_Fc); + if (0 != opin_Fc) { + skip_conn2track = false; + continue; + } + } + + if (true == skip_conn2track) { + continue; + } + VTR_ASSERT(opin_Fc_out.size() == segment_inf.size()); + + /* Build track2ipin_map for this IPIN */ + build_gsb_one_opin_pin2track_map(rr_graph, rr_gsb, opin_side, inode, opin_Fc_out, + /* Give an offset for the first track that this ipin will connect to */ + offset[side_manager.to_size_t()], + segment_inf, opin2track_map); + /* update offset: aim to rotate starting tracks by 1*/ + offset[side_manager.to_size_t()] += 1; } - } - - if (true == skip_conn2track) { - continue; - } - VTR_ASSERT(opin_Fc_out.size() == segment_inf.size()); - - /* Build track2ipin_map for this IPIN */ - build_gsb_one_opin_pin2track_map(rr_graph, rr_gsb, opin_side, inode, opin_Fc_out, - /* Give an offset for the first track that this ipin will connect to */ - offset[side_manager.to_size_t()], - segment_inf, opin2track_map); - /* update offset: aim to rotate starting tracks by 1*/ - offset[side_manager.to_size_t()] += 1; - } - /* Check: + /* Check: * 1. We want to ensure that each OPIN will drive at least one track * 2. We want to ensure that each track will be driven by at least 1 OPIN */ - } + } - return opin2track_map; + return opin2track_map; } /************************************************************************ @@ -1340,92 +1326,92 @@ t_pin2track_map build_gsb_opin_to_track_map(const RRGraph& rr_graph, void build_direct_connections_for_one_gsb(RRGraph& rr_graph, const DeviceGrid& grids, const vtr::Point& from_grid_coordinate, - const RRSwitchId& delayless_switch, - const std::vector& directs, + const RRSwitchId& delayless_switch, + const std::vector& directs, const std::vector& clb_to_clb_directs) { - VTR_ASSERT(directs.size() == clb_to_clb_directs.size()); + VTR_ASSERT(directs.size() == clb_to_clb_directs.size()); - const t_grid_tile& from_grid = grids[from_grid_coordinate.x()][from_grid_coordinate.y()]; - t_physical_tile_type_ptr grid_type = from_grid.type; + const t_grid_tile& from_grid = grids[from_grid_coordinate.x()][from_grid_coordinate.y()]; + t_physical_tile_type_ptr grid_type = from_grid.type; - /* Iterate through all direct connections */ - for (size_t i = 0; i < directs.size(); ++i) { - /* Bypass unmatched direct clb-to-clb connections */ - if (grid_type != clb_to_clb_directs[i].from_clb_type) { - continue; - } + /* Iterate through all direct connections */ + for (size_t i = 0; i < directs.size(); ++i) { + /* Bypass unmatched direct clb-to-clb connections */ + if (grid_type != clb_to_clb_directs[i].from_clb_type) { + continue; + } - /* This opin is specified to connect directly to an ipin, + /* This opin is specified to connect directly to an ipin, * now compute which ipin to connect to */ - vtr::Point to_grid_coordinate(from_grid_coordinate.x() + directs[i].x_offset, - from_grid_coordinate.y() + directs[i].y_offset); - - /* Bypass unmatched direct clb-to-clb connections */ - t_physical_tile_type_ptr to_grid_type = grids[to_grid_coordinate.x()][to_grid_coordinate.y()].type; - /* Check if to_grid if the same grid */ - if (to_grid_type != clb_to_clb_directs[i].to_clb_type) { - continue; - } - - bool swap; - int max_index, min_index; - /* Compute index of opin with regards to given pins */ - if ( clb_to_clb_directs[i].from_clb_pin_start_index - > clb_to_clb_directs[i].from_clb_pin_end_index) { - swap = true; - max_index = clb_to_clb_directs[i].from_clb_pin_start_index; - min_index = clb_to_clb_directs[i].from_clb_pin_end_index; - } else { - swap = false; - min_index = clb_to_clb_directs[i].from_clb_pin_start_index; - max_index = clb_to_clb_directs[i].from_clb_pin_end_index; - } + vtr::Point to_grid_coordinate(from_grid_coordinate.x() + directs[i].x_offset, + from_grid_coordinate.y() + directs[i].y_offset); + + /* Bypass unmatched direct clb-to-clb connections */ + t_physical_tile_type_ptr to_grid_type = grids[to_grid_coordinate.x()][to_grid_coordinate.y()].type; + /* Check if to_grid if the same grid */ + if (to_grid_type != clb_to_clb_directs[i].to_clb_type) { + continue; + } - /* get every opin in the range */ - for (int opin = min_index; opin <= max_index; ++opin) { - int offset = opin - min_index; - - if ( (to_grid_coordinate.x() < grids.width() - 1) - && (to_grid_coordinate.y() < grids.height() - 1) ) { - int ipin = OPEN; - if ( clb_to_clb_directs[i].to_clb_pin_start_index - > clb_to_clb_directs[i].to_clb_pin_end_index) { - if (true == swap) { - ipin = clb_to_clb_directs[i].to_clb_pin_end_index + offset; - } else { - ipin = clb_to_clb_directs[i].to_clb_pin_start_index - offset; - } + bool swap; + int max_index, min_index; + /* Compute index of opin with regards to given pins */ + if (clb_to_clb_directs[i].from_clb_pin_start_index + > clb_to_clb_directs[i].from_clb_pin_end_index) { + swap = true; + max_index = clb_to_clb_directs[i].from_clb_pin_start_index; + min_index = clb_to_clb_directs[i].from_clb_pin_end_index; } else { - if(true == swap) { - ipin = clb_to_clb_directs[i].to_clb_pin_end_index - offset; - } else { - ipin = clb_to_clb_directs[i].to_clb_pin_start_index + offset; - } + swap = false; + min_index = clb_to_clb_directs[i].from_clb_pin_start_index; + max_index = clb_to_clb_directs[i].from_clb_pin_end_index; } - /* Get the pin index in the rr_graph */ - int from_grid_width_ofs = from_grid.width_offset; - int from_grid_height_ofs = from_grid.height_offset; - int to_grid_width_ofs = grids[to_grid_coordinate.x()][to_grid_coordinate.y()].width_offset; - int to_grid_height_ofs = grids[to_grid_coordinate.x()][to_grid_coordinate.y()].height_offset; - - /* Find the side of grid pins, the pin location should be unique! + /* get every opin in the range */ + for (int opin = min_index; opin <= max_index; ++opin) { + int offset = opin - min_index; + + if ((to_grid_coordinate.x() < grids.width() - 1) + && (to_grid_coordinate.y() < grids.height() - 1)) { + int ipin = OPEN; + if (clb_to_clb_directs[i].to_clb_pin_start_index + > clb_to_clb_directs[i].to_clb_pin_end_index) { + if (true == swap) { + ipin = clb_to_clb_directs[i].to_clb_pin_end_index + offset; + } else { + ipin = clb_to_clb_directs[i].to_clb_pin_start_index - offset; + } + } else { + if (true == swap) { + ipin = clb_to_clb_directs[i].to_clb_pin_end_index - offset; + } else { + ipin = clb_to_clb_directs[i].to_clb_pin_start_index + offset; + } + } + + /* Get the pin index in the rr_graph */ + int from_grid_width_ofs = from_grid.width_offset; + int from_grid_height_ofs = from_grid.height_offset; + int to_grid_width_ofs = grids[to_grid_coordinate.x()][to_grid_coordinate.y()].width_offset; + int to_grid_height_ofs = grids[to_grid_coordinate.x()][to_grid_coordinate.y()].height_offset; + + /* Find the side of grid pins, the pin location should be unique! * Pin location is required by searching a node in rr_graph */ - std::vector opin_grid_side = find_grid_pin_sides(from_grid, opin); - VTR_ASSERT(1 == opin_grid_side.size()); - - std::vector ipin_grid_side = find_grid_pin_sides(grids[to_grid_coordinate.x()][to_grid_coordinate.y()], ipin); - VTR_ASSERT(1 == ipin_grid_side.size()); - - const RRNodeId& opin_node_id = rr_graph.find_node(from_grid_coordinate.x() - from_grid_width_ofs, - from_grid_coordinate.y() - from_grid_height_ofs, - OPIN, opin, opin_grid_side[0]); - const RRNodeId& ipin_node_id = rr_graph.find_node(to_grid_coordinate.x() - to_grid_width_ofs, - to_grid_coordinate.y() - to_grid_height_ofs, - IPIN, ipin, ipin_grid_side[0]); - /* + std::vector opin_grid_side = find_grid_pin_sides(from_grid, opin); + VTR_ASSERT(1 == opin_grid_side.size()); + + std::vector ipin_grid_side = find_grid_pin_sides(grids[to_grid_coordinate.x()][to_grid_coordinate.y()], ipin); + VTR_ASSERT(1 == ipin_grid_side.size()); + + const RRNodeId& opin_node_id = rr_graph.find_node(from_grid_coordinate.x() - from_grid_width_ofs, + from_grid_coordinate.y() - from_grid_height_ofs, + OPIN, opin, opin_grid_side[0]); + const RRNodeId& ipin_node_id = rr_graph.find_node(to_grid_coordinate.x() - to_grid_width_ofs, + to_grid_coordinate.y() - to_grid_height_ofs, + IPIN, ipin, ipin_grid_side[0]); + /* VTR_LOG("Direct connection: from grid[%lu][%lu].pin[%lu] at side %s to grid[%lu][%lu].pin[%lu] at side %s\n", from_grid_coordinate.x() - from_grid_width_ofs, from_grid_coordinate.y() - from_grid_height_ofs, @@ -1434,14 +1420,13 @@ void build_direct_connections_for_one_gsb(RRGraph& rr_graph, to_grid_coordinate.y() - to_grid_height_ofs, ipin, SIDE_STRING[ipin_grid_side[0]]); */ - - /* add edges to the opin_node */ - rr_graph.create_edge(opin_node_id, ipin_node_id, - delayless_switch); - } + + /* add edges to the opin_node */ + rr_graph.create_edge(opin_node_id, ipin_node_id, + delayless_switch); + } + } } - } } - } /* end namespace openfpga */ diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp index 89a0e264904..3d4627576bd 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp @@ -27,60 +27,58 @@ namespace openfpga { /************************************************************************ * Find the number output pins by considering all the grid ***********************************************************************/ -static -size_t estimate_num_grid_rr_nodes_by_type(const DeviceGrid& grids, - const t_rr_type& node_type) { - size_t num_grid_rr_nodes = 0; +static size_t estimate_num_grid_rr_nodes_by_type(const DeviceGrid& grids, + const t_rr_type& node_type) { + size_t num_grid_rr_nodes = 0; - for (size_t ix = 0; ix < grids.width(); ++ix) { - for (size_t iy = 0; iy < grids.height(); ++iy) { - - /* Skip EMPTY tiles */ - if (true == is_empty_type(grids[ix][iy].type)) { - continue; - } - - /* Skip height > 1 or width > 1 tiles (mostly heterogeneous blocks) */ - if ( (0 < grids[ix][iy].width_offset) - || (0 < grids[ix][iy].height_offset) ) { - continue; - } - - enum e_side io_side = NUM_SIDES; - - /* If this is the block on borders, we consider IO side */ - if (true == is_io_type(grids[ix][iy].type)) { - vtr::Point io_device_size(grids.width() - 1, grids.height() - 1); - vtr::Point grid_coordinate(ix, iy); - io_side = determine_io_grid_pin_side(io_device_size, grid_coordinate); - } - - switch (node_type) { - case OPIN: - /* get the number of OPINs */ - num_grid_rr_nodes += get_grid_num_pins(grids[ix][iy], DRIVER, io_side); - break; - case IPIN: - /* get the number of IPINs */ - num_grid_rr_nodes += get_grid_num_pins(grids[ix][iy], RECEIVER, io_side); - break; - case SOURCE: - /* SOURCE: number of classes whose type is DRIVER */ - num_grid_rr_nodes += get_grid_num_classes(grids[ix][iy], DRIVER); - break; - case SINK: - /* SINK: number of classes whose type is RECEIVER */ - num_grid_rr_nodes += get_grid_num_classes(grids[ix][iy], RECEIVER); - break; - default: - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid routing resource node!\n"); - exit(1); - } + for (size_t ix = 0; ix < grids.width(); ++ix) { + for (size_t iy = 0; iy < grids.height(); ++iy) { + /* Skip EMPTY tiles */ + if (true == is_empty_type(grids[ix][iy].type)) { + continue; + } + + /* Skip height > 1 or width > 1 tiles (mostly heterogeneous blocks) */ + if ((0 < grids[ix][iy].width_offset) + || (0 < grids[ix][iy].height_offset)) { + continue; + } + + enum e_side io_side = NUM_SIDES; + + /* If this is the block on borders, we consider IO side */ + if (true == is_io_type(grids[ix][iy].type)) { + vtr::Point io_device_size(grids.width() - 1, grids.height() - 1); + vtr::Point grid_coordinate(ix, iy); + io_side = determine_io_grid_pin_side(io_device_size, grid_coordinate); + } + + switch (node_type) { + case OPIN: + /* get the number of OPINs */ + num_grid_rr_nodes += get_grid_num_pins(grids[ix][iy], DRIVER, io_side); + break; + case IPIN: + /* get the number of IPINs */ + num_grid_rr_nodes += get_grid_num_pins(grids[ix][iy], RECEIVER, io_side); + break; + case SOURCE: + /* SOURCE: number of classes whose type is DRIVER */ + num_grid_rr_nodes += get_grid_num_classes(grids[ix][iy], DRIVER); + break; + case SINK: + /* SINK: number of classes whose type is RECEIVER */ + num_grid_rr_nodes += get_grid_num_classes(grids[ix][iy], RECEIVER); + break; + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid routing resource node!\n"); + exit(1); + } + } } - } - return num_grid_rr_nodes; + return num_grid_rr_nodes; } /************************************************************************ @@ -176,52 +174,51 @@ size_t estimate_num_grid_rr_nodes_by_type(const DeviceGrid& grids, * * ***********************************************************************/ -static -size_t estimate_num_chanx_rr_nodes(const DeviceGrid& grids, - const size_t& chan_width, - const std::vector& segment_infs, - const bool& through_channel) { - size_t num_chanx_rr_nodes = 0; +static size_t estimate_num_chanx_rr_nodes(const DeviceGrid& grids, + const size_t& chan_width, + const std::vector& segment_infs, + const bool& through_channel) { + size_t num_chanx_rr_nodes = 0; - for (size_t iy = 0; iy < grids.height() - 1; ++iy) { - for (size_t ix = 1; ix < grids.width() - 1; ++ix) { - vtr::Point chanx_coord(ix, iy); + for (size_t iy = 0; iy < grids.height() - 1; ++iy) { + for (size_t ix = 1; ix < grids.width() - 1; ++ix) { + vtr::Point chanx_coord(ix, iy); - /* Bypass if the routing channel does not exist when through channels are not allowed */ - if ( (false == through_channel) - && (false == is_chanx_exist(grids, chanx_coord))) { - continue; - } + /* Bypass if the routing channel does not exist when through channels are not allowed */ + if ((false == through_channel) + && (false == is_chanx_exist(grids, chanx_coord))) { + continue; + } - bool force_start = false; - bool force_end = false; + bool force_start = false; + bool force_end = false; - /* All the tracks have to start when + /* All the tracks have to start when * - the routing channel touch the RIGHT side a heterogeneous block * - the routing channel touch the LEFT side of FPGA */ - if (true == is_chanx_right_to_multi_height_grid(grids, chanx_coord, through_channel)) { - force_start = true; - } + if (true == is_chanx_right_to_multi_height_grid(grids, chanx_coord, through_channel)) { + force_start = true; + } - /* All the tracks have to end when + /* All the tracks have to end when * - the routing channel touch the LEFT side a heterogeneous block * - the routing channel touch the RIGHT side of FPGA */ - if (true == is_chanx_left_to_multi_height_grid(grids, chanx_coord, through_channel)) { - force_end = true; - } - - /* Evaluate if the routing channel locates in the middle of a grid */ - ChanNodeDetails chanx_details = build_unidir_chan_node_details(chan_width, grids.width() - 2, force_start, force_end, segment_infs); - /* When an INC_DIRECTION CHANX starts, we need a new rr_node */ - num_chanx_rr_nodes += chanx_details.get_num_starting_tracks(Direction::INC); - /* When an DEC_DIRECTION CHANX ends, we need a new rr_node */ - num_chanx_rr_nodes += chanx_details.get_num_ending_tracks(Direction::DEC); + if (true == is_chanx_left_to_multi_height_grid(grids, chanx_coord, through_channel)) { + force_end = true; + } + + /* Evaluate if the routing channel locates in the middle of a grid */ + ChanNodeDetails chanx_details = build_unidir_chan_node_details(chan_width, grids.width() - 2, force_start, force_end, segment_infs); + /* When an INC_DIRECTION CHANX starts, we need a new rr_node */ + num_chanx_rr_nodes += chanx_details.get_num_starting_tracks(Direction::INC); + /* When an DEC_DIRECTION CHANX ends, we need a new rr_node */ + num_chanx_rr_nodes += chanx_details.get_num_ending_tracks(Direction::DEC); + } } - } - return num_chanx_rr_nodes; + return num_chanx_rr_nodes; } /************************************************************************ @@ -229,75 +226,71 @@ size_t estimate_num_chanx_rr_nodes(const DeviceGrid& grids, * The technical rationale is very similar to the X-direction routing channel * Refer to the detailed explanation there ***********************************************************************/ -static -size_t estimate_num_chany_rr_nodes(const DeviceGrid& grids, - const size_t& chan_width, - const std::vector& segment_infs, - const bool& through_channel) { - size_t num_chany_rr_nodes = 0; - - for (size_t ix = 0; ix < grids.width() - 1; ++ix) { - for (size_t iy = 1; iy < grids.height() - 1; ++iy) { - vtr::Point chany_coord(ix, iy); +static size_t estimate_num_chany_rr_nodes(const DeviceGrid& grids, + const size_t& chan_width, + const std::vector& segment_infs, + const bool& through_channel) { + size_t num_chany_rr_nodes = 0; - /* Bypass if the routing channel does not exist when through channel are not allowed */ - if ( (false == through_channel) - && (false == is_chany_exist(grids, chany_coord))) { - continue; - } + for (size_t ix = 0; ix < grids.width() - 1; ++ix) { + for (size_t iy = 1; iy < grids.height() - 1; ++iy) { + vtr::Point chany_coord(ix, iy); + /* Bypass if the routing channel does not exist when through channel are not allowed */ + if ((false == through_channel) + && (false == is_chany_exist(grids, chany_coord))) { + continue; + } - bool force_start = false; - bool force_end = false; + bool force_start = false; + bool force_end = false; - /* All the tracks have to start when + /* All the tracks have to start when * - the routing channel touch the TOP side a heterogeneous block * - the routing channel touch the BOTTOM side of FPGA */ - if (true == is_chany_top_to_multi_width_grid(grids, chany_coord, through_channel)) { - force_start = true; - } + if (true == is_chany_top_to_multi_width_grid(grids, chany_coord, through_channel)) { + force_start = true; + } - /* All the tracks have to end when + /* All the tracks have to end when * - the routing channel touch the BOTTOM side a heterogeneous block * - the routing channel touch the TOP side of FPGA */ - if (true == is_chany_bottom_to_multi_width_grid(grids, chany_coord, through_channel)) { - force_end = true; - } - - ChanNodeDetails chany_details = build_unidir_chan_node_details(chan_width, grids.height() - 2, force_start, force_end, segment_infs); - /* When an INC_DIRECTION CHANX starts, we need a new rr_node */ - num_chany_rr_nodes += chany_details.get_num_starting_tracks(Direction::INC); - /* When an DEC_DIRECTION CHANX ends, we need a new rr_node */ - num_chany_rr_nodes += chany_details.get_num_ending_tracks(Direction::DEC); + if (true == is_chany_bottom_to_multi_width_grid(grids, chany_coord, through_channel)) { + force_end = true; + } + + ChanNodeDetails chany_details = build_unidir_chan_node_details(chan_width, grids.height() - 2, force_start, force_end, segment_infs); + /* When an INC_DIRECTION CHANX starts, we need a new rr_node */ + num_chany_rr_nodes += chany_details.get_num_starting_tracks(Direction::INC); + /* When an DEC_DIRECTION CHANX ends, we need a new rr_node */ + num_chany_rr_nodes += chany_details.get_num_ending_tracks(Direction::DEC); + } } - } - return num_chany_rr_nodes; + return num_chany_rr_nodes; } /************************************************************************ * Estimate the number of nodes by each type in a routing resource graph ***********************************************************************/ -static -std::vector estimate_num_rr_nodes(const DeviceGrid& grids, - const vtr::Point& chan_width, - const std::vector& segment_infs, - const bool& through_channel) { - - /* Reset the OPIN, IPIN, SOURCE, SINK counter to be zero */ - std::vector num_rr_nodes_per_type(NUM_RR_TYPES, 0); - - /** +static std::vector estimate_num_rr_nodes(const DeviceGrid& grids, + const vtr::Point& chan_width, + const std::vector& segment_infs, + const bool& through_channel) { + /* Reset the OPIN, IPIN, SOURCE, SINK counter to be zero */ + std::vector num_rr_nodes_per_type(NUM_RR_TYPES, 0); + + /** * 1 Find number of rr nodes related to grids */ - num_rr_nodes_per_type[OPIN] = estimate_num_grid_rr_nodes_by_type(grids, OPIN); - num_rr_nodes_per_type[IPIN] = estimate_num_grid_rr_nodes_by_type(grids, IPIN); - num_rr_nodes_per_type[SOURCE] = estimate_num_grid_rr_nodes_by_type(grids, SOURCE); - num_rr_nodes_per_type[SINK] = estimate_num_grid_rr_nodes_by_type(grids, SINK); + num_rr_nodes_per_type[OPIN] = estimate_num_grid_rr_nodes_by_type(grids, OPIN); + num_rr_nodes_per_type[IPIN] = estimate_num_grid_rr_nodes_by_type(grids, IPIN); + num_rr_nodes_per_type[SOURCE] = estimate_num_grid_rr_nodes_by_type(grids, SOURCE); + num_rr_nodes_per_type[SINK] = estimate_num_grid_rr_nodes_by_type(grids, SINK); - /** + /** * 2. Assign the segments for each routing channel, * To be specific, for each routing track, we assign a routing segment. * The assignment is subject to users' specifications, such as @@ -312,16 +305,16 @@ std::vector estimate_num_rr_nodes(const DeviceGrid& grids, * in X-direction and Y-direction channels!!! * So we will load segment details for different channels */ - num_rr_nodes_per_type[CHANX] = estimate_num_chanx_rr_nodes(grids, - chan_width.x(), - segment_infs, - through_channel); - num_rr_nodes_per_type[CHANY] = estimate_num_chany_rr_nodes(grids, - chan_width.y(), - segment_infs, - through_channel); - - return num_rr_nodes_per_type; + num_rr_nodes_per_type[CHANX] = estimate_num_chanx_rr_nodes(grids, + chan_width.x(), + segment_infs, + through_channel); + num_rr_nodes_per_type[CHANY] = estimate_num_chany_rr_nodes(grids, + chan_width.y(), + segment_infs, + through_channel); + + return num_rr_nodes_per_type; } /************************************************************************ @@ -337,22 +330,22 @@ void alloc_tileable_rr_graph_nodes(RRGraphBuilder& rr_graph_builder, const vtr::Point& chan_width, const std::vector& segment_infs, const bool& through_channel) { - VTR_ASSERT(0 == rr_graph_builder.rr_nodes().size()); + VTR_ASSERT(0 == rr_graph_builder.rr_nodes().size()); - std::vector num_rr_nodes_per_type = estimate_num_rr_nodes(grids, - chan_width, - segment_infs, - through_channel); + std::vector num_rr_nodes_per_type = estimate_num_rr_nodes(grids, + chan_width, + segment_infs, + through_channel); - /* Reserve the number of node to be memory efficient */ - size_t num_nodes = 0; - for (const size_t& num_node_per_type : num_rr_nodes_per_type) { - num_nodes += num_node_per_type; - } + /* Reserve the number of node to be memory efficient */ + size_t num_nodes = 0; + for (const size_t& num_node_per_type : num_rr_nodes_per_type) { + num_nodes += num_node_per_type; + } - rr_graph_builder.reserve_nodes(num_nodes); + rr_graph_builder.reserve_nodes(num_nodes); - rr_node_driver_switches.reserve(num_nodes); + rr_node_driver_switches.reserve(num_nodes); } /************************************************************************ @@ -362,61 +355,59 @@ void alloc_tileable_rr_graph_nodes(RRGraphBuilder& rr_graph_builder, * * Note: this function should be applied ONLY to grid with 0 width offset and 0 height offset!!! ***********************************************************************/ -static -void load_one_grid_opin_nodes_basic_info(RRGraphBuilder& rr_graph_builder, - vtr::vector& rr_node_driver_switches, - const vtr::Point& grid_coordinate, - const t_grid_tile& cur_grid, - const e_side& io_side, - const RRSwitchId& delayless_switch) { - SideManager io_side_manager(io_side); - - /* Walk through the width height of each grid, +static void load_one_grid_opin_nodes_basic_info(RRGraphBuilder& rr_graph_builder, + vtr::vector& rr_node_driver_switches, + const vtr::Point& grid_coordinate, + const t_grid_tile& cur_grid, + const e_side& io_side, + const RRSwitchId& delayless_switch) { + SideManager io_side_manager(io_side); + + /* Walk through the width height of each grid, * get pins and configure the rr_nodes */ - for (int width = 0; width < cur_grid.type->width; ++width) { - for (int height = 0; height < cur_grid.type->height; ++height) { - /* Walk through sides */ - for (e_side side : SIDES) { - SideManager side_manager(side); - /* skip unwanted sides */ - if ( (true == is_io_type(cur_grid.type)) - && (side != io_side_manager.to_size_t()) && (NUM_SIDES != io_side) ) { - continue; - } - /* Find OPINs */ - /* Configure pins by pins */ - std::vector opin_list = get_grid_side_pins(cur_grid, DRIVER, side_manager.get_side(), - width, height); - for (const int& pin_num : opin_list) { - /* Create a new node and fill information */ - const RRNodeId& node = rr_graph_builder.node_lookup().find_node(width, height, OPIN, pin_num, side); - - /* node bounding box */ - rr_graph_builder.set_node_coordinates(node, grid_coordinate.x() + width, - grid_coordinate.y() + height, - grid_coordinate.x() + width, - grid_coordinate.y() + height); - rr_graph_builder.add_node_side(node, side_manager.get_side()); - rr_graph_builder.set_node_pin_num(node, pin_num); - - rr_graph_builder.set_node_capacity(node, 1); - - /* cost index is a FIXED value for OPIN */ - rr_graph_builder.set_node_cost_index(node, RRIndexedDataId(OPIN_COST_INDEX)); - - /* Switch info */ - VTR_ASSERT(size_t(node) == rr_node_driver_switches.size()); - rr_node_driver_switches.push_back(delayless_switch); - - /* RC data */ - rr_graph_builder.set_node_rc_index(node, NodeRCIndex(find_create_rr_rc_data(0., 0.))); - - } /* End of loading OPIN rr_nodes */ - } /* End of side enumeration */ - } /* End of height enumeration */ - } /* End of width enumeration */ - + for (int width = 0; width < cur_grid.type->width; ++width) { + for (int height = 0; height < cur_grid.type->height; ++height) { + /* Walk through sides */ + for (e_side side : SIDES) { + SideManager side_manager(side); + /* skip unwanted sides */ + if ((true == is_io_type(cur_grid.type)) + && (side != io_side_manager.to_size_t()) && (NUM_SIDES != io_side)) { + continue; + } + /* Find OPINs */ + /* Configure pins by pins */ + std::vector opin_list = get_grid_side_pins(cur_grid, DRIVER, side_manager.get_side(), + width, height); + for (const int& pin_num : opin_list) { + /* Create a new node and fill information */ + const RRNodeId& node = rr_graph_builder.node_lookup().find_node(width, height, OPIN, pin_num, side); + + /* node bounding box */ + rr_graph_builder.set_node_coordinates(node, grid_coordinate.x() + width, + grid_coordinate.y() + height, + grid_coordinate.x() + width, + grid_coordinate.y() + height); + rr_graph_builder.add_node_side(node, side_manager.get_side()); + rr_graph_builder.set_node_pin_num(node, pin_num); + + rr_graph_builder.set_node_capacity(node, 1); + + /* cost index is a FIXED value for OPIN */ + rr_graph_builder.set_node_cost_index(node, RRIndexedDataId(OPIN_COST_INDEX)); + + /* Switch info */ + VTR_ASSERT(size_t(node) == rr_node_driver_switches.size()); + rr_node_driver_switches.push_back(delayless_switch); + + /* RC data */ + rr_graph_builder.set_node_rc_index(node, NodeRCIndex(find_create_rr_rc_data(0., 0.))); + + } /* End of loading OPIN rr_nodes */ + } /* End of side enumeration */ + } /* End of height enumeration */ + } /* End of width enumeration */ } /************************************************************************ @@ -426,60 +417,59 @@ void load_one_grid_opin_nodes_basic_info(RRGraphBuilder& rr_graph_builder, * * Note: this function should be applied ONLY to grid with 0 width offset and 0 height offset!!! ***********************************************************************/ -static -void load_one_grid_ipin_nodes_basic_info(RRGraphBuilder& rr_graph_builder, - vtr::vector& rr_node_driver_switches, - const vtr::Point& grid_coordinate, - const t_grid_tile& cur_grid, - const e_side& io_side, - const RRSwitchId& wire_to_ipin_switch) { - SideManager io_side_manager(io_side); - - /* Walk through the width and height of each grid, +static void load_one_grid_ipin_nodes_basic_info(RRGraphBuilder& rr_graph_builder, + vtr::vector& rr_node_driver_switches, + const vtr::Point& grid_coordinate, + const t_grid_tile& cur_grid, + const e_side& io_side, + const RRSwitchId& wire_to_ipin_switch) { + SideManager io_side_manager(io_side); + + /* Walk through the width and height of each grid, * get pins and configure the rr_nodes */ - for (int width = 0; width < cur_grid.type->width; ++width) { - for (int height = 0; height < cur_grid.type->height; ++height) { - /* Walk through sides */ - for (e_side side : SIDES) { - SideManager side_manager(side); - /* skip unwanted sides */ - if ( (true == is_io_type(cur_grid.type)) - && (side != io_side_manager.to_size_t()) && (NUM_SIDES != io_side) ) { - continue; - } - - /* Find IPINs */ - /* Configure pins by pins */ - std::vector ipin_list = get_grid_side_pins(cur_grid, RECEIVER, side_manager.get_side(), width, height); - for (const int& pin_num : ipin_list) { - /* Create a new node and fill information */ - const RRNodeId& node = rr_graph_builder.node_lookup().find_node(width, height, IPIN, pin_num, side); - - /* node bounding box */ - rr_graph_builder.set_node_coordinates(node, grid_coordinate.x() + width, - grid_coordinate.y() + height, - grid_coordinate.x() + width, - grid_coordinate.y() + height); - rr_graph_builder.add_node_side(node, side_manager.get_side()); - rr_graph_builder.set_node_pin_num(node, pin_num); - - rr_graph_builder.set_node_capacity(node, 1); - - /* cost index is a FIXED value for OPIN */ - rr_graph_builder.set_node_cost_index(node, RRIndexedDataId(IPIN_COST_INDEX)); - - /* Switch info */ - VTR_ASSERT(size_t(node) == rr_node_driver_switches.size()); - rr_node_driver_switches.push_back(wire_to_ipin_switch); - - /* RC data */ - rr_graph_builder.set_node_rc_index(node, NodeRCIndex(find_create_rr_rc_data(0., 0.))); - - } /* End of loading IPIN rr_nodes */ - } /* End of side enumeration */ - } /* End of height enumeration */ - } /* End of width enumeration */ + for (int width = 0; width < cur_grid.type->width; ++width) { + for (int height = 0; height < cur_grid.type->height; ++height) { + /* Walk through sides */ + for (e_side side : SIDES) { + SideManager side_manager(side); + /* skip unwanted sides */ + if ((true == is_io_type(cur_grid.type)) + && (side != io_side_manager.to_size_t()) && (NUM_SIDES != io_side)) { + continue; + } + + /* Find IPINs */ + /* Configure pins by pins */ + std::vector ipin_list = get_grid_side_pins(cur_grid, RECEIVER, side_manager.get_side(), width, height); + for (const int& pin_num : ipin_list) { + /* Create a new node and fill information */ + const RRNodeId& node = rr_graph_builder.node_lookup().find_node(width, height, IPIN, pin_num, side); + + /* node bounding box */ + rr_graph_builder.set_node_coordinates(node, grid_coordinate.x() + width, + grid_coordinate.y() + height, + grid_coordinate.x() + width, + grid_coordinate.y() + height); + rr_graph_builder.add_node_side(node, side_manager.get_side()); + rr_graph_builder.set_node_pin_num(node, pin_num); + + rr_graph_builder.set_node_capacity(node, 1); + + /* cost index is a FIXED value for OPIN */ + rr_graph_builder.set_node_cost_index(node, RRIndexedDataId(IPIN_COST_INDEX)); + + /* Switch info */ + VTR_ASSERT(size_t(node) == rr_node_driver_switches.size()); + rr_node_driver_switches.push_back(wire_to_ipin_switch); + + /* RC data */ + rr_graph_builder.set_node_rc_index(node, NodeRCIndex(find_create_rr_rc_data(0., 0.))); + + } /* End of loading IPIN rr_nodes */ + } /* End of side enumeration */ + } /* End of height enumeration */ + } /* End of width enumeration */ } /************************************************************************ @@ -489,48 +479,47 @@ void load_one_grid_ipin_nodes_basic_info(RRGraphBuilder& rr_graph_builder, * * Note: this function should be applied ONLY to grid with 0 width offset and 0 height offset!!! ***********************************************************************/ -static -void load_one_grid_source_nodes_basic_info(RRGraphBuilder& rr_graph_builder, - vtr::vector& rr_node_driver_switches, - const vtr::Point& grid_coordinate, - const t_grid_tile& cur_grid, - const e_side& io_side, - const RRSwitchId& delayless_switch) { - SideManager io_side_manager(io_side); - - /* Set a SOURCE rr_node for each DRIVER class */ - for (int iclass = 0; iclass < cur_grid.type->num_class; ++iclass) { - /* Set a SINK rr_node for the OPIN */ - if (DRIVER != cur_grid.type->class_inf[iclass].type) { - continue; - } +static void load_one_grid_source_nodes_basic_info(RRGraphBuilder& rr_graph_builder, + vtr::vector& rr_node_driver_switches, + const vtr::Point& grid_coordinate, + const t_grid_tile& cur_grid, + const e_side& io_side, + const RRSwitchId& delayless_switch) { + SideManager io_side_manager(io_side); + + /* Set a SOURCE rr_node for each DRIVER class */ + for (int iclass = 0; iclass < cur_grid.type->num_class; ++iclass) { + /* Set a SINK rr_node for the OPIN */ + if (DRIVER != cur_grid.type->class_inf[iclass].type) { + continue; + } - /* Create a new node and fill information */ - const RRNodeId& node = rr_graph_builder.node_lookup().find_node(grid_coordinate.x(), grid_coordinate.y(), SOURCE, iclass); + /* Create a new node and fill information */ + const RRNodeId& node = rr_graph_builder.node_lookup().find_node(grid_coordinate.x(), grid_coordinate.y(), SOURCE, iclass); - /* node bounding box */ - rr_graph_builder.set_node_coordinates(node, grid_coordinate.x(), - grid_coordinate.y(), - grid_coordinate.x() + cur_grid.type->width - 1, - grid_coordinate.y() + cur_grid.type->height - 1); - rr_graph_builder.set_node_class_num(node, iclass); + /* node bounding box */ + rr_graph_builder.set_node_coordinates(node, grid_coordinate.x(), + grid_coordinate.y(), + grid_coordinate.x() + cur_grid.type->width - 1, + grid_coordinate.y() + cur_grid.type->height - 1); + rr_graph_builder.set_node_class_num(node, iclass); - rr_graph_builder.set_node_capacity(node, 1); + rr_graph_builder.set_node_capacity(node, 1); - /* The capacity should be the number of pins in this class*/ - rr_graph_builder.set_node_capacity(node, cur_grid.type->class_inf[iclass].num_pins); + /* The capacity should be the number of pins in this class*/ + rr_graph_builder.set_node_capacity(node, cur_grid.type->class_inf[iclass].num_pins); - /* cost index is a FIXED value for SOURCE */ - rr_graph_builder.set_node_cost_index(node, RRIndexedDataId(SOURCE_COST_INDEX)); + /* cost index is a FIXED value for SOURCE */ + rr_graph_builder.set_node_cost_index(node, RRIndexedDataId(SOURCE_COST_INDEX)); - /* Switch info */ - VTR_ASSERT(size_t(node) == rr_node_driver_switches.size()); - rr_node_driver_switches.push_back(delayless_switch); + /* Switch info */ + VTR_ASSERT(size_t(node) == rr_node_driver_switches.size()); + rr_node_driver_switches.push_back(delayless_switch); - /* RC data */ - rr_graph_builder.set_node_rc_index(node, NodeRCIndex(find_create_rr_rc_data(0., 0.))); + /* RC data */ + rr_graph_builder.set_node_rc_index(node, NodeRCIndex(find_create_rr_rc_data(0., 0.))); - } /* End of class enumeration */ + } /* End of class enumeration */ } /************************************************************************ @@ -540,116 +529,112 @@ void load_one_grid_source_nodes_basic_info(RRGraphBuilder& rr_graph_builder, * * Note: this function should be applied ONLY to grid with 0 width offset and 0 height offset!!! ***********************************************************************/ -static -void load_one_grid_sink_nodes_basic_info(RRGraphBuilder& rr_graph_builder, - vtr::vector& rr_node_driver_switches, - const vtr::Point& grid_coordinate, - const t_grid_tile& cur_grid, - const e_side& io_side, - const RRSwitchId& delayless_switch) { - SideManager io_side_manager(io_side); - - /* Set a SINK rr_node for each RECEIVER class */ - for (int iclass = 0; iclass < cur_grid.type->num_class; ++iclass) { - /* Set a SINK rr_node for the OPIN */ - if (RECEIVER != cur_grid.type->class_inf[iclass].type) { - continue; - } +static void load_one_grid_sink_nodes_basic_info(RRGraphBuilder& rr_graph_builder, + vtr::vector& rr_node_driver_switches, + const vtr::Point& grid_coordinate, + const t_grid_tile& cur_grid, + const e_side& io_side, + const RRSwitchId& delayless_switch) { + SideManager io_side_manager(io_side); + + /* Set a SINK rr_node for each RECEIVER class */ + for (int iclass = 0; iclass < cur_grid.type->num_class; ++iclass) { + /* Set a SINK rr_node for the OPIN */ + if (RECEIVER != cur_grid.type->class_inf[iclass].type) { + continue; + } - /* Create a new node and fill information */ - const RRNodeId& node = rr_graph_builder.node_lookup().find_node(grid_coordinate.x(), grid_coordinate.y(), SINK, iclass); + /* Create a new node and fill information */ + const RRNodeId& node = rr_graph_builder.node_lookup().find_node(grid_coordinate.x(), grid_coordinate.y(), SINK, iclass); - /* node bounding box */ - rr_graph_builder.set_node_coordinates(node, grid_coordinate.x(), - grid_coordinate.y(), - grid_coordinate.x() + cur_grid.type->width - 1, - grid_coordinate.y() + cur_grid.type->height - 1); - rr_graph_builder.set_node_class_num(node, iclass); + /* node bounding box */ + rr_graph_builder.set_node_coordinates(node, grid_coordinate.x(), + grid_coordinate.y(), + grid_coordinate.x() + cur_grid.type->width - 1, + grid_coordinate.y() + cur_grid.type->height - 1); + rr_graph_builder.set_node_class_num(node, iclass); - rr_graph_builder.set_node_capacity(node, 1); + rr_graph_builder.set_node_capacity(node, 1); - /* The capacity should be the number of pins in this class*/ - rr_graph_builder.set_node_capacity(node, cur_grid.type->class_inf[iclass].num_pins); + /* The capacity should be the number of pins in this class*/ + rr_graph_builder.set_node_capacity(node, cur_grid.type->class_inf[iclass].num_pins); - /* cost index is a FIXED value for SINK */ - rr_graph_builder.set_node_cost_index(node, RRIndexedDataId(SINK_COST_INDEX)); + /* cost index is a FIXED value for SINK */ + rr_graph_builder.set_node_cost_index(node, RRIndexedDataId(SINK_COST_INDEX)); - /* Switch info */ - VTR_ASSERT(size_t(node) == rr_node_driver_switches.size()); - rr_node_driver_switches.push_back(delayless_switch); + /* Switch info */ + VTR_ASSERT(size_t(node) == rr_node_driver_switches.size()); + rr_node_driver_switches.push_back(delayless_switch); - /* RC data */ - rr_graph_builder.set_node_rc_index(node, NodeRCIndex(find_create_rr_rc_data(0., 0.))); + /* RC data */ + rr_graph_builder.set_node_rc_index(node, NodeRCIndex(find_create_rr_rc_data(0., 0.))); - } /* End of class enumeration */ + } /* End of class enumeration */ } /************************************************************************ * Create all the rr_nodes for grids ***********************************************************************/ -static -void load_grid_nodes_basic_info(RRGraphBuilder& rr_graph_builder, - vtr::vector& rr_node_driver_switches, - const DeviceGrid& grids, - const RRSwitchId& wire_to_ipin_switch, - const RRSwitchId& delayless_switch) { - - for (size_t iy = 0; iy < grids.height(); ++iy) { - for (size_t ix = 0; ix < grids.width(); ++ix) { - /* Skip EMPTY tiles */ - if (true == is_empty_type(grids[ix][iy].type)) { - continue; - } - - /* We only build rr_nodes for grids with width_offset = 0 and height_offset = 0 */ - if ( (0 < grids[ix][iy].width_offset) - || (0 < grids[ix][iy].height_offset) ) { - continue; - } - - vtr::Point grid_coordinate(ix, iy); - enum e_side io_side = NUM_SIDES; - - /* If this is the block on borders, we consider IO side */ - if (true == is_io_type(grids[ix][iy].type)) { - vtr::Point io_device_size(grids.width() - 1, grids.height() - 1); - io_side = determine_io_grid_pin_side(io_device_size, grid_coordinate); - } - - /* Configure source rr_nodes for this grid */ - load_one_grid_source_nodes_basic_info(rr_graph_builder, - rr_node_driver_switches, - grid_coordinate, - grids[ix][iy], - io_side, - delayless_switch); - - /* Configure sink rr_nodes for this grid */ - load_one_grid_sink_nodes_basic_info(rr_graph_builder, - rr_node_driver_switches, - grid_coordinate, - grids[ix][iy], - io_side, - delayless_switch); - - /* Configure opin rr_nodes for this grid */ - load_one_grid_opin_nodes_basic_info(rr_graph_builder, - rr_node_driver_switches, - grid_coordinate, - grids[ix][iy], - io_side, - delayless_switch); - - /* Configure ipin rr_nodes for this grid */ - load_one_grid_ipin_nodes_basic_info(rr_graph_builder, - rr_node_driver_switches, - grid_coordinate, - grids[ix][iy], - io_side, - wire_to_ipin_switch); - +static void load_grid_nodes_basic_info(RRGraphBuilder& rr_graph_builder, + vtr::vector& rr_node_driver_switches, + const DeviceGrid& grids, + const RRSwitchId& wire_to_ipin_switch, + const RRSwitchId& delayless_switch) { + for (size_t iy = 0; iy < grids.height(); ++iy) { + for (size_t ix = 0; ix < grids.width(); ++ix) { + /* Skip EMPTY tiles */ + if (true == is_empty_type(grids[ix][iy].type)) { + continue; + } + + /* We only build rr_nodes for grids with width_offset = 0 and height_offset = 0 */ + if ((0 < grids[ix][iy].width_offset) + || (0 < grids[ix][iy].height_offset)) { + continue; + } + + vtr::Point grid_coordinate(ix, iy); + enum e_side io_side = NUM_SIDES; + + /* If this is the block on borders, we consider IO side */ + if (true == is_io_type(grids[ix][iy].type)) { + vtr::Point io_device_size(grids.width() - 1, grids.height() - 1); + io_side = determine_io_grid_pin_side(io_device_size, grid_coordinate); + } + + /* Configure source rr_nodes for this grid */ + load_one_grid_source_nodes_basic_info(rr_graph_builder, + rr_node_driver_switches, + grid_coordinate, + grids[ix][iy], + io_side, + delayless_switch); + + /* Configure sink rr_nodes for this grid */ + load_one_grid_sink_nodes_basic_info(rr_graph_builder, + rr_node_driver_switches, + grid_coordinate, + grids[ix][iy], + io_side, + delayless_switch); + + /* Configure opin rr_nodes for this grid */ + load_one_grid_opin_nodes_basic_info(rr_graph_builder, + rr_node_driver_switches, + grid_coordinate, + grids[ix][iy], + io_side, + delayless_switch); + + /* Configure ipin rr_nodes for this grid */ + load_one_grid_ipin_nodes_basic_info(rr_graph_builder, + rr_node_driver_switches, + grid_coordinate, + grids[ix][iy], + io_side, + wire_to_ipin_switch); + } } - } } /************************************************************************ @@ -657,114 +642,110 @@ void load_grid_nodes_basic_info(RRGraphBuilder& rr_graph_builder, * coordinates: xlow, ylow, xhigh, yhigh, * features: capacity, track_ids, ptc_num, direction ***********************************************************************/ -static -void load_one_chan_rr_nodes_basic_info(RRGraphView& rr_graph, - RRGraphBuilder& rr_graph_builder, - vtr::vector& rr_node_driver_switches, - std::map>& rr_node_track_ids, - const vtr::Point& chan_coordinate, - const t_rr_type& chan_type, - ChanNodeDetails& chan_details, - const std::vector& segment_infs, - const int& cost_index_offset) { - /* Check each node_id(potential ptc_num) in the channel : +static void load_one_chan_rr_nodes_basic_info(RRGraphView& rr_graph, + RRGraphBuilder& rr_graph_builder, + vtr::vector& rr_node_driver_switches, + std::map>& rr_node_track_ids, + const vtr::Point& chan_coordinate, + const t_rr_type& chan_type, + ChanNodeDetails& chan_details, + const std::vector& segment_infs, + const int& cost_index_offset) { + /* Check each node_id(potential ptc_num) in the channel : * If this is a starting point, we set a new rr_node with xlow/ylow, ptc_num * If this is a ending point, we set xhigh/yhigh and track_ids * For other nodes, we set changes in track_ids */ - for (size_t itrack = 0; itrack < chan_details.get_chan_width(); ++itrack) { - /* For INC direction, a starting point requires a new chan rr_node */ - if ( ( (true == chan_details.is_track_start(itrack)) - && (Direction::INC == chan_details.get_track_direction(itrack)) ) - /* For DEC direction, an ending point requires a new chan rr_node */ - || - ( (true == chan_details.is_track_end(itrack)) - && (Direction::DEC == chan_details.get_track_direction(itrack)) ) ) { - - /* Create a new chan rr_node */ - const RRNodeId& node = rr_graph_builder.node_lookup().find_node(chan_coordinate.x(), chan_coordinate.y(), chan_type, itrack); - - rr_graph_builder.set_node_direction(node, chan_details.get_track_direction(itrack)); - rr_graph_builder.set_node_track_num(node, itrack); - rr_node_track_ids[node].push_back(itrack); - - rr_graph_builder.set_node_capacity(node, 1); - - /* assign switch id */ - size_t seg_id = chan_details.get_track_segment_id(itrack); - VTR_ASSERT(size_t(node) == rr_node_driver_switches.size()); - rr_node_driver_switches.push_back(RRSwitchId(segment_infs[seg_id].arch_opin_switch)); - - /* Update chan_details with node_id */ - chan_details.set_track_node_id(itrack, size_t(node)); - - /* cost index depends on the segment index */ - rr_graph_builder.set_node_cost_index(node, RRIndexedDataId(cost_index_offset + seg_id)); - /* Finish here, go to next */ - } + for (size_t itrack = 0; itrack < chan_details.get_chan_width(); ++itrack) { + /* For INC direction, a starting point requires a new chan rr_node */ + if (((true == chan_details.is_track_start(itrack)) + && (Direction::INC == chan_details.get_track_direction(itrack))) + /* For DEC direction, an ending point requires a new chan rr_node */ + || ((true == chan_details.is_track_end(itrack)) + && (Direction::DEC == chan_details.get_track_direction(itrack)))) { + /* Create a new chan rr_node */ + const RRNodeId& node = rr_graph_builder.node_lookup().find_node(chan_coordinate.x(), chan_coordinate.y(), chan_type, itrack); + + rr_graph_builder.set_node_direction(node, chan_details.get_track_direction(itrack)); + rr_graph_builder.set_node_track_num(node, itrack); + rr_node_track_ids[node].push_back(itrack); + + rr_graph_builder.set_node_capacity(node, 1); + + /* assign switch id */ + size_t seg_id = chan_details.get_track_segment_id(itrack); + VTR_ASSERT(size_t(node) == rr_node_driver_switches.size()); + rr_node_driver_switches.push_back(RRSwitchId(segment_infs[seg_id].arch_opin_switch)); + + /* Update chan_details with node_id */ + chan_details.set_track_node_id(itrack, size_t(node)); + + /* cost index depends on the segment index */ + rr_graph_builder.set_node_cost_index(node, RRIndexedDataId(cost_index_offset + seg_id)); + /* Finish here, go to next */ + } - /* For INC direction, an ending point requires an update on xhigh and yhigh */ - if ( ( (true == chan_details.is_track_end(itrack)) - && (Direction::INC == chan_details.get_track_direction(itrack)) ) - || - /* For DEC direction, an starting point requires an update on xlow and ylow */ - ( (true == chan_details.is_track_start(itrack)) - && (Direction::DEC == chan_details.get_track_direction(itrack)) ) ) { - - /* Get the node_id */ - const RRNodeId& rr_node_id = RRNodeId(chan_details.get_track_node_id(itrack)); - - /* Do a quick check, make sure we do not mistakenly modify other nodes */ - VTR_ASSERT(chan_type == rr_graph.node_type(rr_node_id)); - VTR_ASSERT(chan_details.get_track_direction(itrack) == rr_graph.node_direction(rr_node_id)); - - /* set xhigh/yhigh and push changes to track_ids */ - rr_graph_builder.set_node_coordinates(rr_node_id, rr_graph.node_xlow(rr_node_id), - rr_graph.node_ylow(rr_node_id), - chan_coordinate.x(), - chan_coordinate.y()); - - /* Do not update track_ids for length-1 wires, they should have only 1 track_id */ - if ( (rr_graph.node_xhigh(rr_node_id) > rr_graph.node_xlow(rr_node_id)) - || (rr_graph.node_yhigh(rr_node_id) > rr_graph.node_ylow(rr_node_id)) ) { - rr_node_track_ids[rr_node_id].push_back(itrack); - rr_graph_builder.set_node_track_num(rr_node_id, itrack); - } - /* Finish here, go to next */ - } + /* For INC direction, an ending point requires an update on xhigh and yhigh */ + if (((true == chan_details.is_track_end(itrack)) + && (Direction::INC == chan_details.get_track_direction(itrack))) + || + /* For DEC direction, an starting point requires an update on xlow and ylow */ + ((true == chan_details.is_track_start(itrack)) + && (Direction::DEC == chan_details.get_track_direction(itrack)))) { + /* Get the node_id */ + const RRNodeId& rr_node_id = RRNodeId(chan_details.get_track_node_id(itrack)); + + /* Do a quick check, make sure we do not mistakenly modify other nodes */ + VTR_ASSERT(chan_type == rr_graph.node_type(rr_node_id)); + VTR_ASSERT(chan_details.get_track_direction(itrack) == rr_graph.node_direction(rr_node_id)); + + /* set xhigh/yhigh and push changes to track_ids */ + rr_graph_builder.set_node_coordinates(rr_node_id, rr_graph.node_xlow(rr_node_id), + rr_graph.node_ylow(rr_node_id), + chan_coordinate.x(), + chan_coordinate.y()); + + /* Do not update track_ids for length-1 wires, they should have only 1 track_id */ + if ((rr_graph.node_xhigh(rr_node_id) > rr_graph.node_xlow(rr_node_id)) + || (rr_graph.node_yhigh(rr_node_id) > rr_graph.node_ylow(rr_node_id))) { + rr_node_track_ids[rr_node_id].push_back(itrack); + rr_graph_builder.set_node_track_num(rr_node_id, itrack); + } + /* Finish here, go to next */ + } - /* Finish processing starting and ending tracks */ - if ( (true == chan_details.is_track_start(itrack)) - || (true == chan_details.is_track_end(itrack)) ) { - /* Finish here, go to next */ - continue; - } + /* Finish processing starting and ending tracks */ + if ((true == chan_details.is_track_start(itrack)) + || (true == chan_details.is_track_end(itrack))) { + /* Finish here, go to next */ + continue; + } - /* For other nodes, we get the node_id and just update track_ids */ - /* Ensure those nodes are neither starting nor ending points */ - VTR_ASSERT( (false == chan_details.is_track_start(itrack)) - && (false == chan_details.is_track_end(itrack)) ); + /* For other nodes, we get the node_id and just update track_ids */ + /* Ensure those nodes are neither starting nor ending points */ + VTR_ASSERT((false == chan_details.is_track_start(itrack)) + && (false == chan_details.is_track_end(itrack))); - /* Get the node_id */ - const RRNodeId& rr_node_id = RRNodeId(chan_details.get_track_node_id(itrack)); + /* Get the node_id */ + const RRNodeId& rr_node_id = RRNodeId(chan_details.get_track_node_id(itrack)); - /* Do a quick check, make sure we do not mistakenly modify other nodes */ - VTR_ASSERT(chan_type == rr_graph.node_type(rr_node_id)); - VTR_ASSERT(chan_details.get_track_direction(itrack) == rr_graph.node_direction(rr_node_id)); + /* Do a quick check, make sure we do not mistakenly modify other nodes */ + VTR_ASSERT(chan_type == rr_graph.node_type(rr_node_id)); + VTR_ASSERT(chan_details.get_track_direction(itrack) == rr_graph.node_direction(rr_node_id)); - /* Deposit xhigh and yhigh using the current chan_coordinate + /* Deposit xhigh and yhigh using the current chan_coordinate * We will update when this track ends */ - rr_graph_builder.set_node_coordinates(rr_node_id, rr_graph.node_xlow(rr_node_id), - rr_graph.node_ylow(rr_node_id), - chan_coordinate.x(), - chan_coordinate.y()); - - /* Update track_ids */ - rr_node_track_ids[rr_node_id].push_back(itrack); - rr_graph_builder.set_node_track_num(rr_node_id, itrack); - /* Finish here, go to next */ - } + rr_graph_builder.set_node_coordinates(rr_node_id, rr_graph.node_xlow(rr_node_id), + rr_graph.node_ylow(rr_node_id), + chan_coordinate.x(), + chan_coordinate.y()); + + /* Update track_ids */ + rr_node_track_ids[rr_node_id].push_back(itrack); + rr_graph_builder.set_node_track_num(rr_node_id, itrack); + /* Finish here, go to next */ + } } /************************************************************************ @@ -773,62 +754,60 @@ void load_one_chan_rr_nodes_basic_info(RRGraphView& rr_graph, * features: capacity, track_ids, ptc_num, direction * grid_info : pb_graph_pin ***********************************************************************/ -static -void load_chanx_rr_nodes_basic_info(RRGraphView& rr_graph, - RRGraphBuilder& rr_graph_builder, - vtr::vector& rr_node_driver_switches, - std::map>& rr_node_track_ids, - const DeviceGrid& grids, - const size_t& chan_width, - const std::vector& segment_infs, - const bool& through_channel) { - - /* For X-direction Channel: CHANX */ - for (size_t iy = 0; iy < grids.height() - 1; ++iy) { - /* Keep a vector of node_ids for the channels, because we will rotate them when walking through ix */ - std::vector track_node_ids; - - for (size_t ix = 1; ix < grids.width() - 1; ++ix) { - vtr::Point chanx_coord(ix, iy); - - /* Bypass if the routing channel does not exist when through channels are not allowed */ - if ( (false == through_channel) - && (false == is_chanx_exist(grids, chanx_coord))) { - continue; - } - - bool force_start = false; - bool force_end = false; - - /* All the tracks have to start when +static void load_chanx_rr_nodes_basic_info(RRGraphView& rr_graph, + RRGraphBuilder& rr_graph_builder, + vtr::vector& rr_node_driver_switches, + std::map>& rr_node_track_ids, + const DeviceGrid& grids, + const size_t& chan_width, + const std::vector& segment_infs, + const bool& through_channel) { + /* For X-direction Channel: CHANX */ + for (size_t iy = 0; iy < grids.height() - 1; ++iy) { + /* Keep a vector of node_ids for the channels, because we will rotate them when walking through ix */ + std::vector track_node_ids; + + for (size_t ix = 1; ix < grids.width() - 1; ++ix) { + vtr::Point chanx_coord(ix, iy); + + /* Bypass if the routing channel does not exist when through channels are not allowed */ + if ((false == through_channel) + && (false == is_chanx_exist(grids, chanx_coord))) { + continue; + } + + bool force_start = false; + bool force_end = false; + + /* All the tracks have to start when * - the routing channel touch the RIGHT side a heterogeneous block * - the routing channel touch the LEFT side of FPGA */ - if (true == is_chanx_right_to_multi_height_grid(grids, chanx_coord, through_channel)) { - force_start = true; - } + if (true == is_chanx_right_to_multi_height_grid(grids, chanx_coord, through_channel)) { + force_start = true; + } - /* All the tracks have to end when + /* All the tracks have to end when * - the routing channel touch the LEFT side a heterogeneous block * - the routing channel touch the RIGHT side of FPGA */ - if (true == is_chanx_left_to_multi_height_grid(grids, chanx_coord, through_channel)) { - force_end = true; - } - - ChanNodeDetails chanx_details = build_unidir_chan_node_details(chan_width, grids.width() - 2, - force_start, force_end, segment_infs); - /* Force node_ids from the previous chanx */ - if (0 < track_node_ids.size()) { - /* Rotate should be done based on a typical case of routing tracks. + if (true == is_chanx_left_to_multi_height_grid(grids, chanx_coord, through_channel)) { + force_end = true; + } + + ChanNodeDetails chanx_details = build_unidir_chan_node_details(chan_width, grids.width() - 2, + force_start, force_end, segment_infs); + /* Force node_ids from the previous chanx */ + if (0 < track_node_ids.size()) { + /* Rotate should be done based on a typical case of routing tracks. * Tracks on the borders are not regularly started and ended, * which causes the node_rotation malfunction */ - ChanNodeDetails chanx_details_tt = build_unidir_chan_node_details(chan_width, grids.width() - 2, - false, false, segment_infs); - chanx_details_tt.set_track_node_ids(track_node_ids); + ChanNodeDetails chanx_details_tt = build_unidir_chan_node_details(chan_width, grids.width() - 2, + false, false, segment_infs); + chanx_details_tt.set_track_node_ids(track_node_ids); - /* TODO: + /* TODO: * Do NOT rotate the tracks when the routing channel * locates inside a multi-height and multi-width grid * Let the routing channel passing through the grid (if through channel is allowed!) @@ -840,41 +819,41 @@ void load_chanx_rr_nodes_basic_info(RRGraphView& rr_graph, * track0 ----->+-----------------------------+----> track0 * | | */ - if (true == is_chanx_exist(grids, chanx_coord, through_channel)) { - /* Rotate the chanx_details by an offset of ix - 1, the distance to the most left channel */ - /* For INC_DIRECTION, we use clockwise rotation + if (true == is_chanx_exist(grids, chanx_coord, through_channel)) { + /* Rotate the chanx_details by an offset of ix - 1, the distance to the most left channel */ + /* For INC_DIRECTION, we use clockwise rotation * node_id A ----> -----> node_id D * node_id B ----> / ----> node_id A * node_id C ----> / ----> node_id B * node_id D ----> ----> node_id C */ - chanx_details_tt.rotate_track_node_id(1, Direction::INC, true); - /* For DEC_DIRECTION, we use clockwise rotation + chanx_details_tt.rotate_track_node_id(1, Direction::INC, true); + /* For DEC_DIRECTION, we use clockwise rotation * node_id A <----- <----- node_id B * node_id B <----- \ <----- node_id C * node_id C <----- \ <----- node_id D * node_id D <----- <----- node_id A */ - chanx_details_tt.rotate_track_node_id(1, Direction::DEC, false); + chanx_details_tt.rotate_track_node_id(1, Direction::DEC, false); + } + + track_node_ids = chanx_details_tt.get_track_node_ids(); + chanx_details.set_track_node_ids(track_node_ids); + } + + /* Configure CHANX in this channel */ + load_one_chan_rr_nodes_basic_info(rr_graph, + rr_graph_builder, + rr_node_driver_switches, + rr_node_track_ids, + chanx_coord, CHANX, + chanx_details, + segment_infs, + CHANX_COST_INDEX_START); + /* Get a copy of node_ids */ + track_node_ids = chanx_details.get_track_node_ids(); } - - track_node_ids = chanx_details_tt.get_track_node_ids(); - chanx_details.set_track_node_ids(track_node_ids); - } - - /* Configure CHANX in this channel */ - load_one_chan_rr_nodes_basic_info(rr_graph, - rr_graph_builder, - rr_node_driver_switches, - rr_node_track_ids, - chanx_coord, CHANX, - chanx_details, - segment_infs, - CHANX_COST_INDEX_START); - /* Get a copy of node_ids */ - track_node_ids = chanx_details.get_track_node_ids(); } - } } /************************************************************************ @@ -882,65 +861,63 @@ void load_chanx_rr_nodes_basic_info(RRGraphView& rr_graph, * coordinates: xlow, ylow, xhigh, yhigh, * features: capacity, track_ids, ptc_num, direction ***********************************************************************/ -static -void load_chany_rr_nodes_basic_info(RRGraphView& rr_graph, - RRGraphBuilder& rr_graph_builder, - vtr::vector& rr_node_driver_switches, - std::map>& rr_node_track_ids, - const DeviceGrid& grids, - const size_t& chan_width, - const std::vector& segment_infs, - const bool& through_channel) { - - /* For Y-direction Channel: CHANY */ - for (size_t ix = 0; ix < grids.width() - 1; ++ix) { - /* Keep a vector of node_ids for the channels, because we will rotate them when walking through ix */ - std::vector track_node_ids; - - for (size_t iy = 1; iy < grids.height() - 1; ++iy) { - vtr::Point chany_coord(ix, iy); - - /* Bypass if the routing channel does not exist when through channel are not allowed */ - if ( (false == through_channel) - && (false == is_chany_exist(grids, chany_coord))) { - continue; - } - - bool force_start = false; - bool force_end = false; - - /* All the tracks have to start when +static void load_chany_rr_nodes_basic_info(RRGraphView& rr_graph, + RRGraphBuilder& rr_graph_builder, + vtr::vector& rr_node_driver_switches, + std::map>& rr_node_track_ids, + const DeviceGrid& grids, + const size_t& chan_width, + const std::vector& segment_infs, + const bool& through_channel) { + /* For Y-direction Channel: CHANY */ + for (size_t ix = 0; ix < grids.width() - 1; ++ix) { + /* Keep a vector of node_ids for the channels, because we will rotate them when walking through ix */ + std::vector track_node_ids; + + for (size_t iy = 1; iy < grids.height() - 1; ++iy) { + vtr::Point chany_coord(ix, iy); + + /* Bypass if the routing channel does not exist when through channel are not allowed */ + if ((false == through_channel) + && (false == is_chany_exist(grids, chany_coord))) { + continue; + } + + bool force_start = false; + bool force_end = false; + + /* All the tracks have to start when * - the routing channel touch the TOP side a heterogeneous block * - the routing channel touch the BOTTOM side of FPGA */ - if (true == is_chany_top_to_multi_width_grid(grids, chany_coord, through_channel)) { - force_start = true; - } + if (true == is_chany_top_to_multi_width_grid(grids, chany_coord, through_channel)) { + force_start = true; + } - /* All the tracks have to end when + /* All the tracks have to end when * - the routing channel touch the BOTTOM side a heterogeneous block * - the routing channel touch the TOP side of FPGA */ - if (true == is_chany_bottom_to_multi_width_grid(grids, chany_coord, through_channel)) { - force_end = true; - } + if (true == is_chany_bottom_to_multi_width_grid(grids, chany_coord, through_channel)) { + force_end = true; + } - ChanNodeDetails chany_details = build_unidir_chan_node_details(chan_width, grids.height() - 2, - force_start, force_end, segment_infs); - /* Force node_ids from the previous chany + ChanNodeDetails chany_details = build_unidir_chan_node_details(chan_width, grids.height() - 2, + force_start, force_end, segment_infs); + /* Force node_ids from the previous chany * This will not be applied when the routing channel is cut off (force to start) */ - if (0 < track_node_ids.size()) { - /* Rotate should be done based on a typical case of routing tracks. + if (0 < track_node_ids.size()) { + /* Rotate should be done based on a typical case of routing tracks. * Tracks on the borders are not regularly started and ended, * which causes the node_rotation malfunction */ - ChanNodeDetails chany_details_tt = build_unidir_chan_node_details(chan_width, grids.height() - 2, - false, false, segment_infs); + ChanNodeDetails chany_details_tt = build_unidir_chan_node_details(chan_width, grids.height() - 2, + false, false, segment_infs); - chany_details_tt.set_track_node_ids(track_node_ids); + chany_details_tt.set_track_node_ids(track_node_ids); - /* TODO: + /* TODO: * Do NOT rotate the tracks when the routing channel * locates inside a multi-height and multi-width grid * Let the routing channel passing through the grid (if through channel is allowed!) @@ -953,40 +930,40 @@ void load_chany_rr_nodes_basic_info(RRGraphView& rr_graph, * | | * we should rotate only once at the bottom side of a grid */ - if (true == is_chany_exist(grids, chany_coord, through_channel)) { - /* Rotate the chany_details by an offset of 1*/ - /* For INC_DIRECTION, we use clockwise rotation + if (true == is_chany_exist(grids, chany_coord, through_channel)) { + /* Rotate the chany_details by an offset of 1*/ + /* For INC_DIRECTION, we use clockwise rotation * node_id A ----> -----> node_id D * node_id B ----> / ----> node_id A * node_id C ----> / ----> node_id B * node_id D ----> ----> node_id C */ - chany_details_tt.rotate_track_node_id(1, Direction::INC, true); - /* For DEC_DIRECTION, we use clockwise rotation + chany_details_tt.rotate_track_node_id(1, Direction::INC, true); + /* For DEC_DIRECTION, we use clockwise rotation * node_id A <----- <----- node_id B * node_id B <----- \ <----- node_id C * node_id C <----- \ <----- node_id D * node_id D <----- <----- node_id A */ - chany_details_tt.rotate_track_node_id(1, Direction::DEC, false); + chany_details_tt.rotate_track_node_id(1, Direction::DEC, false); + } + + track_node_ids = chany_details_tt.get_track_node_ids(); + chany_details.set_track_node_ids(track_node_ids); + } + /* Configure CHANX in this channel */ + load_one_chan_rr_nodes_basic_info(rr_graph, + rr_graph_builder, + rr_node_driver_switches, + rr_node_track_ids, + chany_coord, CHANY, + chany_details, + segment_infs, + CHANX_COST_INDEX_START + segment_infs.size()); + /* Get a copy of node_ids */ + track_node_ids = chany_details.get_track_node_ids(); } - - track_node_ids = chany_details_tt.get_track_node_ids(); - chany_details.set_track_node_ids(track_node_ids); - } - /* Configure CHANX in this channel */ - load_one_chan_rr_nodes_basic_info(rr_graph, - rr_graph_builder, - rr_node_driver_switches, - rr_node_track_ids, - chany_coord, CHANY, - chany_details, - segment_infs, - CHANX_COST_INDEX_START + segment_infs.size()); - /* Get a copy of node_ids */ - track_node_ids = chany_details.get_track_node_ids(); } - } } /************************************************************************ @@ -996,24 +973,23 @@ void load_chany_rr_nodes_basic_info(RRGraphView& rr_graph, * However, DEC direction routing tracks should have a reversed sequence in * track ids ***********************************************************************/ -static -void reverse_dec_chan_rr_node_track_ids(const RRGraphView& rr_graph, - std::map>& rr_node_track_ids) { +static void reverse_dec_chan_rr_node_track_ids(const RRGraphView& rr_graph, + std::map>& rr_node_track_ids) { // this should call rr_graph_view to do the job -for (auto& node : rr_graph.nodes()) { - /* Bypass condition: only focus on CHANX and CHANY in DEC_DIRECTION */ - if ( (CHANX != rr_graph.node_type(node)) - && (CHANY != rr_graph.node_type(node)) ) { - continue; - } - /* Reach here, we must have a node of CHANX or CHANY */ - if (Direction::DEC != rr_graph.node_direction(node)) { - continue; + for (auto& node : rr_graph.nodes()) { + /* Bypass condition: only focus on CHANX and CHANY in DEC_DIRECTION */ + if ((CHANX != rr_graph.node_type(node)) + && (CHANY != rr_graph.node_type(node))) { + continue; + } + /* Reach here, we must have a node of CHANX or CHANY */ + if (Direction::DEC != rr_graph.node_direction(node)) { + continue; + } + std::reverse(rr_node_track_ids[node].begin(), + rr_node_track_ids[node].end()); } - std::reverse(rr_node_track_ids[node].begin(), - rr_node_track_ids[node].end() ); - } } /************************************************************************ @@ -1029,33 +1005,32 @@ void create_tileable_rr_graph_nodes(RRGraphView& rr_graph, const RRSwitchId& wire_to_ipin_switch, const RRSwitchId& delayless_switch, const bool& through_channel) { - load_grid_nodes_basic_info(rr_graph_builder, - rr_node_driver_switches, - grids, - wire_to_ipin_switch, - delayless_switch); - - load_chanx_rr_nodes_basic_info(rr_graph, - rr_graph_builder, - rr_node_driver_switches, - rr_node_track_ids, - grids, - chan_width.x(), - segment_infs, - through_channel); - - load_chany_rr_nodes_basic_info(rr_graph, - rr_graph_builder, - rr_node_driver_switches, - rr_node_track_ids, - grids, - chan_width.y(), - segment_infs, - through_channel); - - reverse_dec_chan_rr_node_track_ids(rr_graph, - rr_node_track_ids); - + load_grid_nodes_basic_info(rr_graph_builder, + rr_node_driver_switches, + grids, + wire_to_ipin_switch, + delayless_switch); + + load_chanx_rr_nodes_basic_info(rr_graph, + rr_graph_builder, + rr_node_driver_switches, + rr_node_track_ids, + grids, + chan_width.x(), + segment_infs, + through_channel); + + load_chany_rr_nodes_basic_info(rr_graph, + rr_graph_builder, + rr_node_driver_switches, + rr_node_track_ids, + grids, + chan_width.y(), + segment_infs, + through_channel); + + reverse_dec_chan_rr_node_track_ids(rr_graph, + rr_node_track_ids); } } /* end namespace openfpga */ diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.h b/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.h index 1e90fc2feda..48bfe54bd46 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.h +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.h @@ -1,6 +1,3 @@ -#ifndef TILEABLE_RR_GRAPH_NODE_BUILDER_H -#define TILEABLE_RR_GRAPH_NODE_BUILDER_H - /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ @@ -24,7 +21,7 @@ namespace openfpga { void alloc_tileable_rr_graph_nodes(RRGraphBuilder& rr_graph_builder, - vtr::vector& driver_switches, + vtr::vector& driver_switches, const DeviceGrid& grids, const vtr::Point& chan_width, const std::vector& segment_infs, @@ -32,10 +29,10 @@ void alloc_tileable_rr_graph_nodes(RRGraphBuilder& rr_graph_builder, void create_tileable_rr_graph_nodes(RRGraphView& rr_graph, RRGraphBuilder& rr_graph_builder, - vtr::vector& rr_node_driver_switches, + vtr::vector& rr_node_driver_switches, std::map>& rr_node_track_ids, - const DeviceGrid& grids, - const vtr::Point& chan_width, + const DeviceGrid& grids, + const vtr::Point& chan_width, const std::vector& segment_infs, const RRSwitchId& wire_to_ipin_switch, const RRSwitchId& delayless_switch, @@ -43,5 +40,3 @@ void create_tileable_rr_graph_nodes(RRGraphView& rr_graph, } /* end namespace openfpga */ - -#endif From b749ce139e9d65d62f38dd3bc6fe671b50c88b02 Mon Sep 17 00:00:00 2001 From: taoli4rs Date: Wed, 27 Jul 2022 23:36:42 -0700 Subject: [PATCH 004/147] Enable tileable rr graph builder for unidir graph arch; code cleanup. --- vpr/src/base/SetupVPR.cpp | 9 ++ vpr/src/base/ShowSetup.cpp | 2 + vpr/src/base/vpr_api.cpp | 3 + vpr/src/base/vpr_types.h | 60 ++++++---- vpr/src/route/rr_graph.cpp | 110 ++++++++---------- vpr/src/route/rr_graph.h | 30 +++++ .../tileable_rr_graph/chan_node_details.cpp | 5 - vpr/src/tileable_rr_graph/chan_node_details.h | 5 - vpr/src/tileable_rr_graph/clb2clb_directs.h | 16 --- vpr/src/tileable_rr_graph/openfpga_port.h | 5 - .../openfpga_rr_graph_utils.cpp | 5 - .../openfpga_rr_graph_utils.h | 5 - .../tileable_rr_graph/openfpga_side_manager.h | 5 - vpr/src/tileable_rr_graph/rr_chan.cpp | 5 - vpr/src/tileable_rr_graph/rr_chan.h | 7 -- .../rr_graph_builder_utils.cpp | 5 - .../rr_graph_builder_utils.h | 5 - vpr/src/tileable_rr_graph/rr_graph_types.h | 4 +- vpr/src/tileable_rr_graph/rr_gsb.cpp | 5 - vpr/src/tileable_rr_graph/rr_gsb.h | 5 - .../tileable_chan_details_builder.cpp | 5 - .../tileable_chan_details_builder.h | 5 - .../tileable_rr_graph_builder.cpp | 64 +++++----- .../tileable_rr_graph_builder.h | 5 - .../tileable_rr_graph_edge_builder.cpp | 12 +- .../tileable_rr_graph_edge_builder.h | 25 ++-- .../tileable_rr_graph_gsb.cpp | 5 - .../tileable_rr_graph/tileable_rr_graph_gsb.h | 38 +++--- .../tileable_rr_graph_node_builder.cpp | 5 - .../tileable_rr_graph_node_builder.h | 7 +- 30 files changed, 200 insertions(+), 267 deletions(-) delete mode 100644 vpr/src/tileable_rr_graph/clb2clb_directs.h mode change 100755 => 100644 vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp mode change 100755 => 100644 vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.h diff --git a/vpr/src/base/SetupVPR.cpp b/vpr/src/base/SetupVPR.cpp index f75745facae..123bbb2d423 100644 --- a/vpr/src/base/SetupVPR.cpp +++ b/vpr/src/base/SetupVPR.cpp @@ -351,6 +351,10 @@ static void SetupRoutingArch(const t_arch& Arch, /* copy over the switch block information */ RoutingArch->switchblocks = Arch.switchblocks; + + /* Copy the tileable routing setting */ + RoutingArch->tileable = Arch.tileable; + RoutingArch->through_channel = Arch.through_channel; } static void SetupRouterOpts(const t_options& Options, t_router_opts* RouterOpts) { @@ -378,6 +382,11 @@ static void SetupRouterOpts(const t_options& Options, t_router_opts* RouterOpts) RouterOpts->router_algorithm = Options.RouterAlgorithm; RouterOpts->fixed_channel_width = Options.RouteChanWidth; RouterOpts->min_channel_width_hint = Options.min_route_chan_width_hint; + + //TODO document these? + RouterOpts->trim_empty_channels = false; /* DEFAULT */ + RouterOpts->trim_obs_channels = false; /* DEFAULT */ + RouterOpts->read_rr_edge_metadata = Options.read_rr_edge_metadata; RouterOpts->reorder_rr_graph_nodes_algorithm = Options.reorder_rr_graph_nodes_algorithm; RouterOpts->reorder_rr_graph_nodes_threshold = Options.reorder_rr_graph_nodes_threshold; diff --git a/vpr/src/base/ShowSetup.cpp b/vpr/src/base/ShowSetup.cpp index 782038c4a31..a3188fe5eb1 100644 --- a/vpr/src/base/ShowSetup.cpp +++ b/vpr/src/base/ShowSetup.cpp @@ -302,6 +302,8 @@ static void ShowRouterOpts(const t_router_opts& RouterOpts) { VPR_FATAL_ERROR(VPR_ERROR_UNKNOWN, "Unknown check_route value\n"); } + VTR_LOG("RouterOpts.trim_empty_chan: %s\n", (RouterOpts.trim_empty_channels ? "true" : "false")); + VTR_LOG("RouterOpts.trim_obs_chan: %s\n", (RouterOpts.trim_obs_channels ? "true" : "false")); VTR_LOG("RouterOpts.acc_fac: %f\n", RouterOpts.acc_fac); VTR_LOG("RouterOpts.bb_factor: %d\n", RouterOpts.bb_factor); VTR_LOG("RouterOpts.bend_cost: %f\n", RouterOpts.bend_cost); diff --git a/vpr/src/base/vpr_api.cpp b/vpr/src/base/vpr_api.cpp index d2b55121543..2f6fc3017f9 100644 --- a/vpr/src/base/vpr_api.cpp +++ b/vpr/src/base/vpr_api.cpp @@ -901,6 +901,9 @@ void vpr_create_rr_graph(t_vpr_setup& vpr_setup, const t_arch& arch, int chan_wi } else { graph_type = (det_routing_arch->directionality == BI_DIRECTIONAL ? GRAPH_BIDIR : GRAPH_UNIDIR); graph_directionality = (det_routing_arch->directionality == BI_DIRECTIONAL ? GRAPH_BIDIR : GRAPH_UNIDIR); + if ((UNI_DIRECTIONAL == det_routing_arch->directionality) && (true == det_routing_arch->tileable)) { + graph_type = GRAPH_UNIDIR_TILEABLE; + } } t_chan_width chan_width = init_chan(chan_width_fac, arch.Chans, graph_directionality); diff --git a/vpr/src/base/vpr_types.h b/vpr/src/base/vpr_types.h index 584762da50c..0075939d570 100644 --- a/vpr/src/base/vpr_types.h +++ b/vpr/src/base/vpr_types.h @@ -1200,6 +1200,8 @@ struct t_router_opts { enum e_route_type route_type; int fixed_channel_width; int min_channel_width_hint; /// switchblocks; + /* Xifan Tang: subtype of switch blocks. + * Sub type and Fs are applied to pass tracks + */ + int subFs; + enum e_switch_block_type switch_block_subtype; + + /* Xifan Tang: tileable routing */ + bool tileable; + bool through_channel; + short global_route_switch; short delayless_switch; int wire_to_arch_ipin_switch; @@ -1347,17 +1359,17 @@ struct t_det_routing_arch { * Note that this index will store the index of the segment * relative to its **parallel** segment types, not all segments * as stored in device_ctx. Look in rr_graph.cpp: build_rr_graph - * for details but here is an example: say our segment_inf_vec in + * for details but here is an example: say our segment_inf_vec in * device_ctx is as follows: [seg_a_x, seg_b_x, seg_a_y, seg_b_y] - * when building the rr_graph, static segment_inf_vectors will be - * created for each direction, thus you will have the following - * 2 vectors: X_vec =[seg_a_x,seg_b_x] and Y_vec = [seg_a_y,seg_b_y]. - * As a result, e.g. seg_b_y::index == 1 (index in Y_vec) + * when building the rr_graph, static segment_inf_vectors will be + * created for each direction, thus you will have the following + * 2 vectors: X_vec =[seg_a_x,seg_b_x] and Y_vec = [seg_a_y,seg_b_y]. + * As a result, e.g. seg_b_y::index == 1 (index in Y_vec) * and != 3 (index in device_ctx segment_inf_vec). - * @param abs_index index is relative to the segment_inf vec as stored in device_ctx. - * Note that the above vector is **unifies** both x-parallel and - * y-parallel segments and is loaded up originally in read_xml_arch_file.cpp - * + * @param abs_index index is relative to the segment_inf vec as stored in device_ctx. + * Note that the above vector is **unifies** both x-parallel and + * y-parallel segments and is loaded up originally in read_xml_arch_file.cpp + * * @param type_name_ptr pointer to name of the segment type this track belongs * to. points to the appropriate name in s_segment_inf */ @@ -1441,7 +1453,7 @@ class t_chan_seg_details { const t_seg_details* seg_detail_ = nullptr; }; -/* Defines a 3-D array of t_chan_seg_details data structures (one per-each horizontal and vertical channel) +/* Defines a 3-D array of t_chan_seg_details data structures (one per-each horizontal and vertical channel) * once allocated in rr_graph2.cpp, is can be accessed like: [0..grid.width()][0..grid.height()][0..num_tracks-1] */ typedef vtr::NdMatrix t_chan_details; @@ -1464,14 +1476,14 @@ constexpr bool is_src_sink(e_rr_type type) { return (type == SOURCE || type == S * @brief Basic element used to store the traceback (routing) of each net. * * @param index Array index (ID) of this routing resource node. - * @param net_pin_index: Net pin index associated with the node. This value - * ranges from 1 to fanout [1..num_pins-1]. For cases when - * different speed paths are taken to the same SINK for - * different pins, node index cannot uniquely identify - * each SINK, so the net pin index guarantees an unique - * identification for each SINK node. For non-SINK nodes - * and for SINK nodes with no associated net pin index - * (i.e. special SINKs like the source of a clock tree + * @param net_pin_index: Net pin index associated with the node. This value + * ranges from 1 to fanout [1..num_pins-1]. For cases when + * different speed paths are taken to the same SINK for + * different pins, node index cannot uniquely identify + * each SINK, so the net pin index guarantees an unique + * identification for each SINK node. For non-SINK nodes + * and for SINK nodes with no associated net pin index + * (i.e. special SINKs like the source of a clock tree * which do not correspond to an actual netlist connection), * the value for this member should be set to OPEN (-1). * @param iswitch Index of the switch type used to go from this rr_node to @@ -1604,12 +1616,12 @@ struct t_power_opts { }; /** @brief Channel width data - * @param max= Maximum channel width between x_max and y_max. - * @param x_min= Minimum channel width of horizontal channels. Initialized when init_chan() is invoked in rr_graph2.cpp - * @param y_min= Same as above but for vertical channels. - * @param x_max= Maximum channel width of horiozntal channels. Initialized when init_chan() is invoked in rr_graph2.cpp - * @param y_max= Same as above but for vertical channels. - * @param x_list= Stores the channel width of all horizontal channels and thus goes from [0..grid.height()] + * @param max= Maximum channel width between x_max and y_max. + * @param x_min= Minimum channel width of horizontal channels. Initialized when init_chan() is invoked in rr_graph2.cpp + * @param y_min= Same as above but for vertical channels. + * @param x_max= Maximum channel width of horiozntal channels. Initialized when init_chan() is invoked in rr_graph2.cpp + * @param y_max= Same as above but for vertical channels. + * @param x_list= Stores the channel width of all horizontal channels and thus goes from [0..grid.height()] * (imagine a 2D Cartesian grid with horizontal lines starting at every grid point on a line parallel to the y-axis) * @param y_list= Stores the channel width of all verical channels and thus goes from [0..grid.width()] * (imagine a 2D Cartesian grid with vertical lines starting at every grid point on a line parallel to the x-axis) diff --git a/vpr/src/route/rr_graph.cpp b/vpr/src/route/rr_graph.cpp index 711187fbce8..23ed4a8ce40 100644 --- a/vpr/src/route/rr_graph.cpp +++ b/vpr/src/route/rr_graph.cpp @@ -35,6 +35,7 @@ #include "rr_graph_clock.h" #include "edge_groups.h" #include "rr_graph_builder.h" +#include "tileable_rr_graph_builder.h" #include "rr_types.h" @@ -53,16 +54,6 @@ struct t_mux_size_distribution { t_mux_size_distribution* next; }; -struct t_clb_to_clb_directs { - t_physical_tile_type_ptr from_clb_type; - int from_clb_pin_start_index; - int from_clb_pin_end_index; - t_physical_tile_type_ptr to_clb_type; - int to_clb_pin_start_index; - int to_clb_pin_end_index; - int switch_index; //The switch type used by this direct connection -}; - struct t_pin_loc { int pin_index; int width_offset; @@ -244,11 +235,7 @@ void uniquify_edges(t_rr_edge_info_set& rr_edges_to_create); void alloc_and_load_edges(RRGraphBuilder& rr_graph_builder, const t_rr_edge_info_set& rr_edges_to_create); -static void alloc_and_load_rr_switch_inf(const int num_arch_switches, - const float R_minW_nmos, - const float R_minW_pmos, - const int wire_to_arch_ipin_switch, - int* wire_to_rr_ipin_switch); + static void remap_rr_node_switch_indices(const t_arch_switch_fanin& switch_fanin); @@ -256,26 +243,9 @@ static void load_rr_switch_inf(const int num_arch_switches, const float R_minW_n static void alloc_rr_switch_inf(t_arch_switch_fanin& switch_fanin); -static void rr_graph_externals(const std::vector& segment_inf, - const std::vector& segment_inf_x, - const std::vector& segment_inf_y, - int wire_to_rr_ipin_switch, - enum e_base_cost_type base_cost_type); - -static t_clb_to_clb_directs* alloc_and_load_clb_to_clb_directs(const t_direct_inf* directs, const int num_directs, const int delayless_switch); - static t_seg_details* alloc_and_load_global_route_seg_details(const int global_route_switch, int* num_seg_details = nullptr); -static std::vector> alloc_and_load_actual_fc(const std::vector& types, - const int max_pins, - const std::vector& segment_inf, - const int* sets_per_seg_type, - const t_chan_width* nodes_per_chan, - const e_fc_type fc_type, - const enum e_directionality directionality, - bool* Fc_clipped); - static RRNodeId pick_best_direct_connect_target_rr_node(const RRGraphView& rr_graph, RRNodeId from_rr, const std::vector& candidate_rr_nodes); @@ -344,29 +314,51 @@ void create_rr_graph(const t_graph_type graph_type, } free_rr_graph(); - build_rr_graph(graph_type, - block_types, - grid, - nodes_per_chan, - det_routing_arch->switch_block_type, - det_routing_arch->Fs, - det_routing_arch->switchblocks, - num_arch_switches, - segment_inf, - det_routing_arch->global_route_switch, - det_routing_arch->wire_to_arch_ipin_switch, - det_routing_arch->delayless_switch, - det_routing_arch->R_minW_nmos, - det_routing_arch->R_minW_pmos, - router_opts.base_cost_type, - router_opts.clock_modeling, - directs, num_directs, - &det_routing_arch->wire_to_rr_ipin_switch, - Warnings); - if (router_opts.reorder_rr_graph_nodes_algorithm != DONT_REORDER) { - mutable_device_ctx.rr_graph_builder.reorder_nodes(router_opts.reorder_rr_graph_nodes_algorithm, - router_opts.reorder_rr_graph_nodes_threshold, - router_opts.reorder_rr_graph_nodes_seed); + if (GRAPH_UNIDIR_TILEABLE != graph_type) { + build_rr_graph(graph_type, + block_types, + grid, + nodes_per_chan, + det_routing_arch->switch_block_type, + det_routing_arch->Fs, + det_routing_arch->switchblocks, + num_arch_switches, + segment_inf, + det_routing_arch->global_route_switch, + det_routing_arch->wire_to_arch_ipin_switch, + det_routing_arch->delayless_switch, + det_routing_arch->R_minW_nmos, + det_routing_arch->R_minW_pmos, + router_opts.base_cost_type, + router_opts.clock_modeling, + directs, num_directs, + &det_routing_arch->wire_to_rr_ipin_switch, + Warnings); + if (router_opts.reorder_rr_graph_nodes_algorithm != DONT_REORDER) { + mutable_device_ctx.rr_graph_builder.reorder_nodes(router_opts.reorder_rr_graph_nodes_algorithm, + router_opts.reorder_rr_graph_nodes_threshold, + router_opts.reorder_rr_graph_nodes_seed); + } + } else { + /* We do not support dedicated network for clocks in tileable rr_graph generation */ + build_tileable_unidir_rr_graph(block_types, + grid, + nodes_per_chan, + det_routing_arch->switch_block_type, + det_routing_arch->Fs, + det_routing_arch->switch_block_subtype, + det_routing_arch->subFs, + segment_inf, + det_routing_arch->delayless_switch, + det_routing_arch->wire_to_arch_ipin_switch, + det_routing_arch->R_minW_nmos, + det_routing_arch->R_minW_pmos, + router_opts.base_cost_type, + directs, num_directs, + &det_routing_arch->wire_to_rr_ipin_switch, + router_opts.trim_obs_channels || det_routing_arch->through_channel, /* Allow/Prohibit through tracks across multi-height and multi-width grids */ + false, /* Do not allow passing tracks to be wired to the same routing channels */ + Warnings); } } @@ -872,7 +864,7 @@ static void build_rr_graph(const t_graph_type graph_type, * and count how many different fan-ins exist for each arch switch. * Then we create these rr switches and update the switch indices * of rr_nodes to index into the rr_switch_inf array. */ -static void alloc_and_load_rr_switch_inf(const int num_arch_switches, const float R_minW_nmos, const float R_minW_pmos, const int wire_to_arch_ipin_switch, int* wire_to_rr_ipin_switch) { +void alloc_and_load_rr_switch_inf(const int num_arch_switches, const float R_minW_nmos, const float R_minW_pmos, const int wire_to_arch_ipin_switch, int* wire_to_rr_ipin_switch) { /* we will potentially be creating a couple of versions of each arch switch where * each version corresponds to a different fan-in. We will need to fill device_ctx.rr_switch_inf * with this expanded list of switches. @@ -1033,7 +1025,7 @@ static void remap_rr_node_switch_indices(const t_arch_switch_fanin& switch_fanin device_ctx.rr_graph_builder.remap_rr_node_switch_indices(switch_fanin); } -static void rr_graph_externals(const std::vector& segment_inf, +void rr_graph_externals(const std::vector& segment_inf, const std::vector& segment_inf_x, const std::vector& segment_inf_y, int wire_to_rr_ipin_switch, @@ -1130,7 +1122,7 @@ static t_seg_details* alloc_and_load_global_route_seg_details(const int global_r } /* Calculates the number of track connections from each block pin to each segment type */ -static std::vector> alloc_and_load_actual_fc(const std::vector& types, +std::vector> alloc_and_load_actual_fc(const std::vector& types, const int max_pins, const std::vector& segment_inf, const int* sets_per_seg_type, @@ -2774,7 +2766,7 @@ static void build_unidir_rr_opins(RRGraphBuilder& rr_graph_builder, * This data structure supplements the the info in the "directs" data structure * TODO: The function that does this parsing in placement is poorly done because it lacks generality on heterogeniety, should replace with this one */ -static t_clb_to_clb_directs* alloc_and_load_clb_to_clb_directs(const t_direct_inf* directs, const int num_directs, int delayless_switch) { +t_clb_to_clb_directs* alloc_and_load_clb_to_clb_directs(const t_direct_inf* directs, const int num_directs, int delayless_switch) { int i; t_clb_to_clb_directs* clb_to_clb_directs; char *tile_name, *port_name; diff --git a/vpr/src/route/rr_graph.h b/vpr/src/route/rr_graph.h index e4f29959207..2d230f92fb8 100644 --- a/vpr/src/route/rr_graph.h +++ b/vpr/src/route/rr_graph.h @@ -9,6 +9,16 @@ #include "device_grid.h" #include "vpr_types.h" +struct t_clb_to_clb_directs { + t_physical_tile_type_ptr from_clb_type; + int from_clb_pin_start_index; + int from_clb_pin_end_index; + t_physical_tile_type_ptr to_clb_type; + int to_clb_pin_start_index; + int to_clb_pin_end_index; + int switch_index; //The switch type used by this direct connection +}; + enum e_graph_type { GRAPH_GLOBAL, /* One node per channel with wire capacity > 1 and full connectivity */ GRAPH_BIDIR, /* Detailed bidirectional graph */ @@ -56,4 +66,24 @@ void load_rr_switch_from_arch_switch(int arch_switch_idx, t_non_configurable_rr_sets identify_non_configurable_rr_sets(); +void rr_graph_externals(const std::vector& segment_inf, + const std::vector& segment_inf_x, + const std::vector& segment_inf_y, + int wire_to_rr_ipin_switch, + enum e_base_cost_type base_cost_type); + +std::vector> alloc_and_load_actual_fc(const std::vector& types, + const int max_pins, + const std::vector& segment_inf, + const int* sets_per_seg_type, + const t_chan_width* nodes_per_chan, + const e_fc_type fc_type, + const enum e_directionality directionality, + bool* Fc_clipped); +t_clb_to_clb_directs* alloc_and_load_clb_to_clb_directs(const t_direct_inf* directs, const int num_directs, const int delayless_switch); +void alloc_and_load_rr_switch_inf(const int num_arch_switches, + const float R_minW_nmos, + const float R_minW_pmos, + const int wire_to_arch_ipin_switch, + int* wire_to_rr_ipin_switch); #endif diff --git a/vpr/src/tileable_rr_graph/chan_node_details.cpp b/vpr/src/tileable_rr_graph/chan_node_details.cpp index 3da5f2f29de..3109039b1a7 100644 --- a/vpr/src/tileable_rr_graph/chan_node_details.cpp +++ b/vpr/src/tileable_rr_graph/chan_node_details.cpp @@ -8,9 +8,6 @@ #include "chan_node_details.h" -/* begin namespace openfpga */ -namespace openfpga { - /************************************************************************ * Constructors ***********************************************************************/ @@ -292,5 +289,3 @@ bool ChanNodeDetails::validate_track_id(const size_t& track_id) const { } return false; } - -} /* end namespace openfpga */ diff --git a/vpr/src/tileable_rr_graph/chan_node_details.h b/vpr/src/tileable_rr_graph/chan_node_details.h index b2426ae56a1..4b50d7b2405 100644 --- a/vpr/src/tileable_rr_graph/chan_node_details.h +++ b/vpr/src/tileable_rr_graph/chan_node_details.h @@ -18,9 +18,6 @@ * 4. potentail track_id(ptc_num) of each segment ***********************************************************************/ -/* begin namespace openfpga */ -namespace openfpga { - /************************************************************************ * ChanNodeDetails records segment length, directionality and starting of routing tracks * +---------------------------------+ @@ -72,6 +69,4 @@ class ChanNodeDetails { std::vector track_end_; /* flag to identify if this is the ending point of the track */ }; -} /* end namespace openfpga */ - #endif diff --git a/vpr/src/tileable_rr_graph/clb2clb_directs.h b/vpr/src/tileable_rr_graph/clb2clb_directs.h deleted file mode 100644 index 7cc54bb8813..00000000000 --- a/vpr/src/tileable_rr_graph/clb2clb_directs.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef CLB2CLB_DIRECTS_H -#define CLB2CLB_DIRECTS_H - -#include "physical_types.h" - -struct t_clb_to_clb_directs { - t_physical_tile_type_ptr from_clb_type; - int from_clb_pin_start_index; - int from_clb_pin_end_index; - t_physical_tile_type_ptr to_clb_type; - int to_clb_pin_start_index; - int to_clb_pin_end_index; - int switch_index; //The switch type used by this direct connection -}; - -#endif diff --git a/vpr/src/tileable_rr_graph/openfpga_port.h b/vpr/src/tileable_rr_graph/openfpga_port.h index 3df6d0efa40..2975405ebe5 100644 --- a/vpr/src/tileable_rr_graph/openfpga_port.h +++ b/vpr/src/tileable_rr_graph/openfpga_port.h @@ -7,9 +7,6 @@ #include #include -/* namespace openfpga begins */ -namespace openfpga { - /* A basic port */ class BasicPort { public: /* Constructors */ @@ -90,7 +87,5 @@ class ConfPorts { /* TODO: create a class for BL and WL ports */ -} /* namespace openfpga ends */ - #endif diff --git a/vpr/src/tileable_rr_graph/openfpga_rr_graph_utils.cpp b/vpr/src/tileable_rr_graph/openfpga_rr_graph_utils.cpp index 231781a69b2..c532b888b9b 100644 --- a/vpr/src/tileable_rr_graph/openfpga_rr_graph_utils.cpp +++ b/vpr/src/tileable_rr_graph/openfpga_rr_graph_utils.cpp @@ -11,9 +11,6 @@ #include "openfpga_rr_graph_utils.h" #include "rr_graph_types.h" -/* begin namespace openfpga */ -namespace openfpga { - /************************************************************************ * Get the coordinator of a starting point of a routing track * For routing tracks in INC_DIRECTION @@ -180,5 +177,3 @@ bool is_ipin_direct_connected_opin(const RRGraph& rr_graph, return true; } - -} /* end namespace openfpga */ diff --git a/vpr/src/tileable_rr_graph/openfpga_rr_graph_utils.h b/vpr/src/tileable_rr_graph/openfpga_rr_graph_utils.h index ebf741f8d97..1a1801379ec 100644 --- a/vpr/src/tileable_rr_graph/openfpga_rr_graph_utils.h +++ b/vpr/src/tileable_rr_graph/openfpga_rr_graph_utils.h @@ -14,9 +14,6 @@ * Function declaration *******************************************************************/ -/* begin namespace openfpga */ -namespace openfpga { - vtr::Point get_track_rr_node_start_coordinate(const RRGraph& rr_graph, const RRNodeId& track_rr_node); @@ -41,6 +38,4 @@ bool is_opin_direct_connected_ipin(const RRGraph& rr_graph, bool is_ipin_direct_connected_opin(const RRGraph& rr_graph, const RRNodeId& node); -} /* end namespace openfpga */ - #endif diff --git a/vpr/src/tileable_rr_graph/openfpga_side_manager.h b/vpr/src/tileable_rr_graph/openfpga_side_manager.h index 4903f7b4bba..a6eb01d9197 100644 --- a/vpr/src/tileable_rr_graph/openfpga_side_manager.h +++ b/vpr/src/tileable_rr_graph/openfpga_side_manager.h @@ -10,9 +10,6 @@ /* Header files form archfpga library */ #include "physical_types.h" -/* namespace openfpga begins */ -namespace openfpga { - /******************************************************************** * Define a class for the sides of a physical block in FPGA architecture * Basically, each block has four sides : @@ -44,6 +41,4 @@ class SideManager { enum e_side side_; }; -} /* namespace openfpga ends */ - #endif diff --git a/vpr/src/tileable_rr_graph/rr_chan.cpp b/vpr/src/tileable_rr_graph/rr_chan.cpp index 556f1893a74..13ba606cefd 100644 --- a/vpr/src/tileable_rr_graph/rr_chan.cpp +++ b/vpr/src/tileable_rr_graph/rr_chan.cpp @@ -5,9 +5,6 @@ #include "vtr_assert.h" #include "rr_chan.h" -/* namespace openfpga begins */ -namespace openfpga { - /************************************************************************ * Constructors ***********************************************************************/ @@ -221,5 +218,3 @@ bool RRChan::valid_node_id(const size_t& node_id) const { return false; } - -} /* End namespace openfpga*/ diff --git a/vpr/src/tileable_rr_graph/rr_chan.h b/vpr/src/tileable_rr_graph/rr_chan.h index d06d894caa8..e6dacde42f8 100644 --- a/vpr/src/tileable_rr_graph/rr_chan.h +++ b/vpr/src/tileable_rr_graph/rr_chan.h @@ -15,9 +15,6 @@ /* Headers from vpr library */ #include "rr_graph_obj.h" -/* Begin namespace openfpga */ -namespace openfpga { - /******************************************************************** * RRChan object aim to describe a routing channel in a routing resource graph * - What are the nodes in the RRGraph object, for each routing track @@ -87,8 +84,4 @@ class RRChan { std::vector node_segments_; /* segment of each track */ }; - - -} /* End namespace openfpga*/ - #endif diff --git a/vpr/src/tileable_rr_graph/rr_graph_builder_utils.cpp b/vpr/src/tileable_rr_graph/rr_graph_builder_utils.cpp index c3653ac3b73..47660c0bd26 100644 --- a/vpr/src/tileable_rr_graph/rr_graph_builder_utils.cpp +++ b/vpr/src/tileable_rr_graph/rr_graph_builder_utils.cpp @@ -12,9 +12,6 @@ #include "rr_graph_builder_utils.h" -/* begin namespace openfpga */ -namespace openfpga { - /************************************************************************ * Correct number of routing channel width to be compatible to * uni-directional routing architecture @@ -547,5 +544,3 @@ void print_rr_graph_mux_stats(const RRGraph& rr_graph) { find_rr_graph_average_fan_in(rr_graph, cb_node_types)); VTR_LOG("------------------------------------------------\n"); } - -} /* end namespace openfpga */ diff --git a/vpr/src/tileable_rr_graph/rr_graph_builder_utils.h b/vpr/src/tileable_rr_graph/rr_graph_builder_utils.h index 6ff78412f06..05628fac18e 100644 --- a/vpr/src/tileable_rr_graph/rr_graph_builder_utils.h +++ b/vpr/src/tileable_rr_graph/rr_graph_builder_utils.h @@ -12,9 +12,6 @@ * Function declaration *******************************************************************/ -/* begin namespace openfpga */ -namespace openfpga { - size_t find_unidir_routing_channel_width(const size_t& chan_width); int get_grid_pin_class_index(const t_grid_tile& cur_grid, @@ -92,7 +89,5 @@ short find_rr_graph_average_fan_in(const RRGraph& rr_graph, void print_rr_graph_mux_stats(const RRGraph& rr_graph); -} /* end namespace openfpga */ - #endif diff --git a/vpr/src/tileable_rr_graph/rr_graph_types.h b/vpr/src/tileable_rr_graph/rr_graph_types.h index 6cf7e1b56eb..5f7297a49c4 100644 --- a/vpr/src/tileable_rr_graph/rr_graph_types.h +++ b/vpr/src/tileable_rr_graph/rr_graph_types.h @@ -1,5 +1,5 @@ -#ifndef RR_GRAPH_TYPES -#define RR_GRAPH_TYPES +#ifndef RR_GRAPH_TYPES_H +#define RR_GRAPH_TYPES_H /******************************************************************** * Data types required by routing resource graph (RRGraph) definition diff --git a/vpr/src/tileable_rr_graph/rr_gsb.cpp b/vpr/src/tileable_rr_graph/rr_gsb.cpp index 68f287e291c..2a467d61ff5 100644 --- a/vpr/src/tileable_rr_graph/rr_gsb.cpp +++ b/vpr/src/tileable_rr_graph/rr_gsb.cpp @@ -10,9 +10,6 @@ #include "rr_gsb.h" -/* namespace openfpga begins */ -namespace openfpga { - /************************************************************************ * Constructors ***********************************************************************/ @@ -1140,5 +1137,3 @@ bool RRGSB::validate_ipin_node_id(const e_side& side, const size_t& node_id) con bool RRGSB::validate_cb_type(const t_rr_type& cb_type) const { return ((CHANX == cb_type) || (CHANY == cb_type)); } - -} /* End namespace openfpga*/ diff --git a/vpr/src/tileable_rr_graph/rr_gsb.h b/vpr/src/tileable_rr_graph/rr_gsb.h index 279f206f9da..e533007d57a 100644 --- a/vpr/src/tileable_rr_graph/rr_gsb.h +++ b/vpr/src/tileable_rr_graph/rr_gsb.h @@ -9,9 +9,6 @@ #include "rr_chan.h" -/* Begin namespace openfpga */ -namespace openfpga { - /******************************************************************** * Object Generic Switch Block * This block contains @@ -284,6 +281,4 @@ class RRGSB { std::vector> opin_node_; }; -} /* End namespace openfpga*/ - #endif diff --git a/vpr/src/tileable_rr_graph/tileable_chan_details_builder.cpp b/vpr/src/tileable_rr_graph/tileable_chan_details_builder.cpp index d2afce3edd7..4c185ecd347 100644 --- a/vpr/src/tileable_rr_graph/tileable_chan_details_builder.cpp +++ b/vpr/src/tileable_rr_graph/tileable_chan_details_builder.cpp @@ -14,9 +14,6 @@ #include "rr_graph_builder_utils.h" #include "tileable_chan_details_builder.h" -/* begin namespace openfpga */ -namespace openfpga { - /************************************************************************ * Generate the number of tracks for each types of routing segments * w.r.t. the frequency of each of segments and channel width @@ -230,5 +227,3 @@ ChanNodeDetails build_unidir_chan_node_details(const size_t& chan_width, return chan_node_details; } - -} /* end namespace openfpga */ diff --git a/vpr/src/tileable_rr_graph/tileable_chan_details_builder.h b/vpr/src/tileable_rr_graph/tileable_chan_details_builder.h index e6adb71621b..34a476d80e4 100644 --- a/vpr/src/tileable_rr_graph/tileable_chan_details_builder.h +++ b/vpr/src/tileable_rr_graph/tileable_chan_details_builder.h @@ -12,9 +12,6 @@ * Function declaration *******************************************************************/ -/* begin namespace openfpga */ -namespace openfpga { - std::vector get_num_tracks_per_seg_type(const size_t& chan_width, const std::vector& segment_inf, const bool& use_full_seg_groups); @@ -27,6 +24,4 @@ ChanNodeDetails build_unidir_chan_node_details(const size_t& chan_width, const bool& force_end, const std::vector& segment_inf); -} /* end namespace openfpga */ - #endif diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp index 198c2fc5e1c..1aa8766a73c 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp @@ -27,9 +27,6 @@ #include "globals.h" -/* begin namespace openfpga */ -namespace openfpga { - /************************************************************************ * Main function of this file * Builder for a detailed uni-directional tileable rr_graph @@ -70,26 +67,6 @@ namespace openfpga { * b. RC tree ***********************************************************************/ -// external functions: in vpr/src/route/rr_graph.cpp -extern std::vector> alloc_and_load_actual_fc(const std::vector& types, - const int max_pins, - const std::vector& segment_inf, - - const int* sets_per_seg_type, - const int max_chan_width, - const e_fc_type fc_type, - const enum e_directionality directionality, - bool* Fc_clipped); -extern t_clb_to_clb_directs* alloc_and_load_clb_to_clb_directs(const t_direct_inf* directs, const int num_directs, int delayless_switch); -extern void alloc_and_load_rr_switch_inf(const int num_arch_switches, - const float R_minW_nmos, - const float R_minW_pmos, - const int wire_to_arch_ipin_switch, - int* wire_to_rr_ipin_switch); -extern void rr_graph_externals(const std::vector& segment_inf, - int wire_to_rr_ipin_switch, - enum e_base_cost_type base_cost_type); - void build_tileable_unidir_rr_graph(const std::vector& types, const DeviceGrid& grids, const t_chan_width& chan_width, @@ -157,9 +134,9 @@ void build_tileable_unidir_rr_graph(const std::vector& typ } // NYI #if 0 - /* Validate the special switches */ - VTR_ASSERT(true == device_ctx.rr_graph_builder.valid_switch_id(wire_to_ipin_rr_switch)); - VTR_ASSERT(true == device_ctx.rr_graph_builder.valid_switch_id(delayless_rr_switch)); + /* Validate the special switches */ + VTR_ASSERT(true == device_ctx.rr_graph.validate_node(wire_to_ipin_rr_switch)); + VTR_ASSERT(true == device_ctx.rr_graph.validate_node(delayless_rr_switch)); #endif /* A temp data about the driver switch ids for each rr_node */ @@ -230,7 +207,7 @@ void build_tileable_unidir_rr_graph(const std::vector& typ bool Fc_clipped = false; /* [0..num_types-1][0..num_pins-1] */ std::vector> Fc_in; - Fc_in = alloc_and_load_actual_fc(types, max_pins, segment_inf, sets_per_seg_type, max_chan_width, + Fc_in = alloc_and_load_actual_fc(types, max_pins, segment_inf, sets_per_seg_type, (const t_chan_width*) &chan_width, e_fc_type::IN, UNI_DIRECTIONAL, &Fc_clipped); if (Fc_clipped) { *Warnings |= RR_GRAPH_WARN_FC_CLIPPED; @@ -239,7 +216,7 @@ void build_tileable_unidir_rr_graph(const std::vector& typ Fc_clipped = false; /* [0..num_types-1][0..num_pins-1] */ std::vector> Fc_out; - Fc_out = alloc_and_load_actual_fc(types, max_pins, segment_inf, sets_per_seg_type, max_chan_width, + Fc_out = alloc_and_load_actual_fc(types, max_pins, segment_inf, sets_per_seg_type, (const t_chan_width*) &chan_width, e_fc_type::OUT, UNI_DIRECTIONAL, &Fc_clipped); if (Fc_clipped) { @@ -255,6 +232,9 @@ void build_tileable_unidir_rr_graph(const std::vector& typ * Add edges that bridge OPINs and IPINs to the rr_graph ***********************************************************************/ /* Create edges for a tileable rr_graph */ + +// Link error: undefined reference to `build_rr_graph_edges` +#if 0 build_rr_graph_edges(device_ctx.rr_graph, rr_node_driver_switches, grids, @@ -263,6 +243,7 @@ void build_tileable_unidir_rr_graph(const std::vector& typ Fc_in, Fc_out, sb_type, Fs, sb_subtype, subFs, wire_opposite_side); +#endif /************************************************************************ * Build direction connection lists @@ -280,8 +261,11 @@ void build_tileable_unidir_rr_graph(const std::vector& typ clb2clb_directs.push_back(clb_to_clb_directs[idirect]); } +// Link error: undefined reference to `build_rr_graph_direct_connections` +#if 0 build_rr_graph_direct_connections(device_ctx.rr_graph, grids, delayless_rr_switch, arch_directs, clb2clb_directs); +#endif //NYI #if 0 @@ -309,7 +293,10 @@ void build_tileable_unidir_rr_graph(const std::vector& typ * a. cost_index * b. RC tree ***********************************************************************/ - rr_graph_externals(segment_inf, + t_unified_to_parallel_seg_index segment_index_map; + std::vector segment_inf_x = get_parallel_segs(segment_inf, segment_index_map, X_AXIS); + std::vector segment_inf_y = get_parallel_segs(segment_inf, segment_index_map, Y_AXIS); + rr_graph_externals(segment_inf, segment_inf_x, segment_inf_y, *wire_to_rr_ipin_switch, base_cost_type); /* Rebuild the link between RRGraph node and segments @@ -321,12 +308,14 @@ void build_tileable_unidir_rr_graph(const std::vector& typ && (CHANY != device_ctx.rr_graph.node_type(inode))) { continue; } -//NYI -#if 0 - RRIndexedDataId irc_data = device_ctx.rr_graph.node_cost_index(inode); - short iseg = device_ctx.rr_indexed_data[irc_data].seg_index; - device_ctx.rr_graph_builder.set_node_segment(inode, RRSegmentId(iseg)); // NYI -#endif + // NYI + #if 0 + RRIndexedDataId irc_data = device_ctx.rr_graph.node_cost_index(inode); + short iseg = device_ctx.rr_indexed_data[irc_data].seg_index; + // device_ctx.rr_graph_builder.set_node_segment(inode, RRSegmentId(iseg)); // NYI + vtr::vector rr_segments = device_ctx.rr_graph_builder.rr_segments(); + rr_segments[(RRSegmentId)iseg] = segment_inf; + #endif } /************************************************************************ @@ -345,7 +334,8 @@ void build_tileable_unidir_rr_graph(const std::vector& typ // NYI // vpr integration: DeviceContext does not provide direct RRGraph access - // we can skip it since check_rr_graph(GRAPH_UNDIR, GRIDS, TYPES) has been called above + // for advanced rr graph checker in check_rr_graph_obj.h, needs rr graph object + // rr graph view won't work here #if 0 /* Error out if advanced checker of rr_graph fails */ if (false == check_rr_graph(device_ctx.rr_graph)) { @@ -366,5 +356,3 @@ void build_tileable_unidir_rr_graph(const std::vector& typ free(clb_to_clb_directs); } } - -} /* end namespace openfpga */ diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.h b/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.h index 46be3817d76..e2372d4d196 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.h +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.h @@ -13,9 +13,6 @@ * Function declaration *******************************************************************/ -/* begin namespace openfpga */ -namespace openfpga { - void build_tileable_unidir_rr_graph(const std::vector& types, const DeviceGrid& grids, const t_chan_width& chan_width, @@ -34,6 +31,4 @@ void build_tileable_unidir_rr_graph(const std::vector& typ const bool& wire_opposite_side, int *Warnings); -} /* end namespace openfpga */ - #endif diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp index 3252bd412c9..3a2ea544605 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp @@ -15,14 +15,11 @@ #include "tileable_rr_graph_gsb.h" #include "tileable_rr_graph_edge_builder.h" -/* begin namespace openfpga */ -namespace openfpga { - /************************************************************************ * Build the edges for all the SOURCE and SINKs nodes: * 1. create edges between SOURCE and OPINs ***********************************************************************/ -static void build_rr_graph_edges_for_source_nodes(RRGraph& rr_graph, +void build_rr_graph_edges_for_source_nodes(RRGraph& rr_graph, const vtr::vector& rr_node_driver_switches, const DeviceGrid& grids) { for (const RRNodeId& node : rr_graph.nodes()) { @@ -51,7 +48,7 @@ static void build_rr_graph_edges_for_source_nodes(RRGraph& rr_graph, * Build the edges for all the SINKs nodes: * 1. create edges between IPINs and SINKs ***********************************************************************/ -static void build_rr_graph_edges_for_sink_nodes(RRGraph& rr_graph, +void build_rr_graph_edges_for_sink_nodes(RRGraph& rr_graph, const vtr::vector& rr_node_driver_switches, const DeviceGrid& grids) { for (const RRNodeId& node : rr_graph.nodes()) { @@ -79,8 +76,8 @@ static void build_rr_graph_edges_for_sink_nodes(RRGraph& rr_graph, * Build the edges of each rr_node tile by tile: * We classify rr_nodes into a general switch block (GSB) data structure * where we create edges to each rr_nodes in the GSB with respect to - * Fc_in and Fc_out, switch block patterns - * For each GSB: + * Fc_in and Fc_out, switch block patterns + * For each GSB: * 1. create edges between CHANX | CHANY and IPINs (connections inside connection blocks) * 2. create edges between OPINs, CHANX and CHANY (connections inside switch blocks) * 3. create edges between OPINs and IPINs (direct-connections) @@ -166,4 +163,3 @@ void build_rr_graph_direct_connections(RRGraph& rr_graph, } } -} /* end namespace openfpga */ diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.h b/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.h index 936b9944f50..1d92f4fc7c0 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.h +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.h @@ -1,3 +1,6 @@ +#ifndef BILEABLE_RR_GRAPH_EDGE_BUILDER_H +#define BILEABLE_RR_GRAPH_EDGE_BUILDER_H + /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ @@ -10,16 +13,13 @@ #include "physical_types.h" #include "device_grid.h" #include "rr_graph_obj.h" -#include "clb2clb_directs.h" #include "rr_graph_view.h" +#include "rr_graph.h" /******************************************************************** * Function declaration *******************************************************************/ -/* begin namespace openfpga */ -namespace openfpga { - void build_rr_graph_edges(RRGraphView& rr_graph, const vtr::vector& rr_node_driver_switches, const DeviceGrid& grids, @@ -27,8 +27,10 @@ void build_rr_graph_edges(RRGraphView& rr_graph, const std::vector& segment_inf, const std::vector>& Fc_in, const std::vector>& Fc_out, - const e_switch_block_type& sb_type, const int& Fs, - const e_switch_block_type& sb_subtype, const int& subFs, + const e_switch_block_type& sb_type, + const int& Fs, + const e_switch_block_type& sb_subtype, + const int& subFs, const bool& wire_opposite_side); void build_rr_graph_direct_connections(RRGraphView& rr_graph, @@ -37,4 +39,13 @@ void build_rr_graph_direct_connections(RRGraphView& rr_graph, const std::vector& directs, const std::vector& clb_to_clb_directs); -} /* end namespace openfpga */ +void build_rr_graph_edges_for_source_nodes(RRGraph& rr_graph, + const vtr::vector& rr_node_driver_switches, + const DeviceGrid& grids); + +void build_rr_graph_edges_for_sink_nodes(RRGraph& rr_graph, + const vtr::vector& rr_node_driver_switches, + const DeviceGrid& grids); + +#endif + diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp old mode 100755 new mode 100644 index 6aab10566ea..4d23c3b723c --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp @@ -20,9 +20,6 @@ #include "tileable_chan_details_builder.h" #include "tileable_rr_graph_gsb.h" -/* begin namespace openfpga */ -namespace openfpga { - /************************************************************************ * Internal data structures ***********************************************************************/ @@ -1428,5 +1425,3 @@ void build_direct_connections_for_one_gsb(RRGraph& rr_graph, } } } - -} /* end namespace openfpga */ diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.h b/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.h old mode 100755 new mode 100644 index adf6118fbbe..fbe3a90f89a --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.h +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.h @@ -1,6 +1,5 @@ #ifndef TILEABLE_RR_GRAPH_GSB_H #define TILEABLE_RR_GRAPH_GSB_H - /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ @@ -14,41 +13,38 @@ #include "rr_gsb.h" #include "rr_graph_obj.h" -#include "clb2clb_directs.h" +#include "rr_graph.h" /******************************************************************** * Function declaration *******************************************************************/ -/* begin namespace openfpga */ -namespace openfpga { - /************************************************************************ - * Data stuctures related to the functions + * Data stuctures related to the functions ***********************************************************************/ typedef std::vector>> t_track2track_map; typedef std::vector>> t_track2pin_map; typedef std::vector>> t_pin2track_map; /************************************************************************ - * Functions + * Functions ***********************************************************************/ t_track2track_map build_gsb_track_to_track_map(const RRGraph& rr_graph, const RRGSB& rr_gsb, - const e_switch_block_type& sb_type, + const e_switch_block_type& sb_type, const int& Fs, - const e_switch_block_type& sb_subtype, + const e_switch_block_type& sb_subtype, const int& subFs, const bool& wire_opposite_side, const std::vector& segment_inf); -RRGSB build_one_tileable_rr_gsb(const DeviceGrid& grids, +RRGSB build_one_tileable_rr_gsb(const DeviceGrid& grids, const RRGraph& rr_graph, - const vtr::Point& device_chan_width, + const vtr::Point& device_chan_width, const std::vector& segment_inf, const vtr::Point& gsb_coordinate); -void build_edges_for_one_tileable_rr_gsb(RRGraph& rr_graph, +void build_edges_for_one_tileable_rr_gsb(RRGraph& rr_graph, const RRGSB& rr_gsb, const t_track2pin_map& track2ipin_map, const t_pin2track_map& opin2track_map, @@ -56,25 +52,23 @@ void build_edges_for_one_tileable_rr_gsb(RRGraph& rr_graph, const vtr::vector& rr_node_driver_switches); t_track2pin_map build_gsb_track_to_ipin_map(const RRGraph& rr_graph, - const RRGSB& rr_gsb, - const DeviceGrid& grids, - const std::vector& segment_inf, + const RRGSB& rr_gsb, + const DeviceGrid& grids, + const std::vector& segment_inf, const std::vector>& Fc_in); t_pin2track_map build_gsb_opin_to_track_map(const RRGraph& rr_graph, - const RRGSB& rr_gsb, - const DeviceGrid& grids, - const std::vector& segment_inf, + const RRGSB& rr_gsb, + const DeviceGrid& grids, + const std::vector& segment_inf, const std::vector>& Fc_out); void build_direct_connections_for_one_gsb(RRGraph& rr_graph, const DeviceGrid& grids, const vtr::Point& from_grid_coordinate, - const RRSwitchId& delayless_switch, - const std::vector& directs, + const RRSwitchId& delayless_switch, + const std::vector& directs, const std::vector& clb_to_clb_directs); -} /* end namespace openfpga */ - #endif diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp index 3d4627576bd..20727607473 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp @@ -21,9 +21,6 @@ #include "tileable_rr_graph_node_builder.h" #include "rr_rc_data.h" -/* begin namespace openfpga */ -namespace openfpga { - /************************************************************************ * Find the number output pins by considering all the grid ***********************************************************************/ @@ -1032,5 +1029,3 @@ void create_tileable_rr_graph_nodes(RRGraphView& rr_graph, reverse_dec_chan_rr_node_track_ids(rr_graph, rr_node_track_ids); } - -} /* end namespace openfpga */ diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.h b/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.h index 48bfe54bd46..c555c19a178 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.h +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.h @@ -1,3 +1,5 @@ +#ifndef TILEABLE_RR_GRAPH_NODE_BUILDER_H +#define TILEABLE_RR_GRAPH_NODE_BUILDER_H /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ @@ -17,9 +19,6 @@ * Function declaration *******************************************************************/ -/* begin namespace openfpga */ -namespace openfpga { - void alloc_tileable_rr_graph_nodes(RRGraphBuilder& rr_graph_builder, vtr::vector& driver_switches, const DeviceGrid& grids, @@ -38,5 +37,5 @@ void create_tileable_rr_graph_nodes(RRGraphView& rr_graph, const RRSwitchId& delayless_switch, const bool& through_channel); +#endif -} /* end namespace openfpga */ From 3932e1d1192bc219261e098655fafafe8c40e231 Mon Sep 17 00:00:00 2001 From: taoli4rs Date: Thu, 28 Jul 2022 16:24:07 -0700 Subject: [PATCH 005/147] Fix typo. --- vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.h b/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.h index 1d92f4fc7c0..0d5c31af691 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.h +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.h @@ -1,5 +1,5 @@ -#ifndef BILEABLE_RR_GRAPH_EDGE_BUILDER_H -#define BILEABLE_RR_GRAPH_EDGE_BUILDER_H +#ifndef TILEABLE_RR_GRAPH_EDGE_BUILDER_H +#define TILEABLE_RR_GRAPH_EDGE_BUILDER_H /******************************************************************** * Include header files that are required by function declaration From aecd504a283a1e04112e34f386b9ce3afa049f70 Mon Sep 17 00:00:00 2001 From: taoli4rs Date: Fri, 29 Jul 2022 22:58:08 -0700 Subject: [PATCH 006/147] Add missing tileable rr graph functions and support class to make it compileable. --- libs/libvtrutil/src/vtr_geometry.tpp | 5 + vpr/src/tileable_rr_graph/openfpga_port.cpp | 439 +++++ .../openfpga_rr_graph_utils.cpp | 61 +- .../openfpga_rr_graph_utils.h | 17 +- .../openfpga_side_manager.cpp | 171 ++ vpr/src/tileable_rr_graph/rr_chan.cpp | 6 +- vpr/src/tileable_rr_graph/rr_chan.h | 8 +- .../tileable_rr_graph/rr_graph_obj_util.cpp | 161 ++ vpr/src/tileable_rr_graph/rr_graph_obj_util.h | 9 +- vpr/src/tileable_rr_graph/rr_gsb.cpp | 61 +- vpr/src/tileable_rr_graph/rr_gsb.h | 31 +- .../tileable_rr_graph_builder.cpp | 10 +- .../tileable_rr_graph_edge_builder.cpp | 41 +- .../tileable_rr_graph_edge_builder.h | 12 +- .../tileable_rr_graph_gsb.cpp | 67 +- .../tileable_rr_graph/tileable_rr_graph_gsb.h | 15 +- .../tileable_rr_graph_node_builder.cpp | 1430 +++++++++-------- .../tileable_rr_graph_node_builder.h | 12 +- 18 files changed, 1748 insertions(+), 808 deletions(-) create mode 100644 vpr/src/tileable_rr_graph/openfpga_port.cpp create mode 100644 vpr/src/tileable_rr_graph/openfpga_side_manager.cpp create mode 100644 vpr/src/tileable_rr_graph/rr_graph_obj_util.cpp diff --git a/libs/libvtrutil/src/vtr_geometry.tpp b/libs/libvtrutil/src/vtr_geometry.tpp index 2010700fc50..c3e25dcf8a9 100644 --- a/libs/libvtrutil/src/vtr_geometry.tpp +++ b/libs/libvtrutil/src/vtr_geometry.tpp @@ -3,6 +3,11 @@ namespace vtr { * Point */ +template +Point::Point() { + //pass +} + template Point::Point(T x_val, T y_val) noexcept : x_(x_val) diff --git a/vpr/src/tileable_rr_graph/openfpga_port.cpp b/vpr/src/tileable_rr_graph/openfpga_port.cpp new file mode 100644 index 00000000000..7cfd03b20f5 --- /dev/null +++ b/vpr/src/tileable_rr_graph/openfpga_port.cpp @@ -0,0 +1,439 @@ +#include +#include +#include + +/* Headers from vtrutil library */ +#include "vtr_assert.h" + +#include "openfpga_port.h" + +/************************************************************************ + * Member functions for BasicPort class + ***********************************************************************/ + +/************************************************************************ + * Constructors + ***********************************************************************/ +/* Default constructor */ +BasicPort::BasicPort() { + /* By default we set an invalid port, which size is 0 */ + lsb_ = 1; + msb_ = 0; + + origin_port_width_ = -1; +} + +/* Quick constructor */ +BasicPort::BasicPort(const char* name, const size_t& lsb, const size_t& msb) { + set_name(std::string(name)); + set_width(lsb, msb); + set_origin_port_width(-1); +} + +BasicPort::BasicPort(const std::string& name, const size_t& lsb, const size_t& msb) { + set_name(name); + set_width(lsb, msb); + set_origin_port_width(-1); +} + +BasicPort::BasicPort(const char* name, const size_t& width) { + set_name(std::string(name)); + set_width(width); + set_origin_port_width(-1); +} + +BasicPort::BasicPort(const std::string& name, const size_t& width) { + set_name(name); + set_width(width); + set_origin_port_width(-1); +} + +/************************************************************************ + * Accessors + ***********************************************************************/ +/* get the port width */ +size_t BasicPort::get_width() const { + if (true == is_valid()) { + return msb_ - lsb_ + 1; + } + return 0; /* invalid port has a zero width */ +} + +/* get the LSB */ +size_t BasicPort::get_msb() const { + return msb_; +} + +/* get the LSB */ +size_t BasicPort::get_lsb() const { + return lsb_; +} + +/* get the name */ +std::string BasicPort::get_name() const { + return name_; +} + +/* Make a range of the pin indices */ +std::vector BasicPort::pins() const { + std::vector pin_indices; + + /* Return if the port is invalid */ + if (false == is_valid()) { + return pin_indices; /* Return an empty vector */ + } + /* For valid ports, create a vector whose length is the port width */ + pin_indices.resize(get_width()); + /* Fill in an incremental sequence */ + std::iota(pin_indices.begin(), pin_indices.end(), get_lsb()); + /* Ensure the last one is MSB */ + VTR_ASSERT(get_msb() == pin_indices.back()); + + return pin_indices; +} + +/* Check if a port can be merged with this port: their name should be the same */ +bool BasicPort::mergeable(const BasicPort& portA) const { + return (0 == this->get_name().compare(portA.get_name())); +} + +/* Check if a port is contained by this port: + * this function will check if the (LSB, MSB) of portA + * is contained by the (LSB, MSB) of this port + */ +bool BasicPort::contained(const BasicPort& portA) const { + return ( lsb_ <= portA.get_lsb() && portA.get_msb() <= msb_ ); +} + +/* Set original port width */ +size_t BasicPort::get_origin_port_width() const { + return origin_port_width_; +} + +/************************************************************************ + * Overloaded operators + ***********************************************************************/ +/* Two ports are the same only when: + * 1. port names are the same + * 2. LSBs are the same + * 3. MSBs are the same + */ +bool BasicPort::operator== (const BasicPort& portA) const { + if ( (0 == this->get_name().compare(portA.get_name())) + && (this->get_lsb() == portA.get_lsb()) + && (this->get_msb() == portA.get_msb()) ) { + return true; + } + return false; +} + +bool BasicPort::operator< (const BasicPort& portA) const { + if ( (0 == this->get_name().compare(portA.get_name())) + && (this->get_lsb() < portA.get_lsb()) + && (this->get_msb() < portA.get_msb()) ) { + return true; + } + return false; +} + + +/************************************************************************ + * Mutators + ***********************************************************************/ +/* copy */ +void BasicPort::set(const BasicPort& basic_port) { + name_ = basic_port.get_name(); + lsb_ = basic_port.get_lsb(); + msb_ = basic_port.get_msb(); + origin_port_width_ = basic_port.get_origin_port_width(); + + return; +} + +/* set the port LSB and MSB */ +void BasicPort::set_name(const std::string& name) { + name_ = name; + return; +} + +/* set the port LSB and MSB */ +void BasicPort::set_width(const size_t& width) { + if (0 == width) { + make_invalid(); + return; + } + lsb_ = 0; + msb_ = width - 1; + return; +} + +/* set the port LSB and MSB */ +void BasicPort::set_width(const size_t& lsb, const size_t& msb) { + /* If lsb and msb is invalid, we make a default port */ + if (lsb > msb) { + make_invalid(); + return; + } + set_lsb(lsb); + set_msb(msb); + return; +} + +void BasicPort::set_lsb(const size_t& lsb) { + lsb_ = lsb; + return; +} + +void BasicPort::set_msb(const size_t& msb) { + msb_ = msb; + return; +} + +void BasicPort::set_origin_port_width(const size_t& origin_port_width) { + origin_port_width_ = origin_port_width; + return; +} + +/* Increase the port width */ +void BasicPort::expand(const size_t& width) { + if (0 == width) { + return; /* ignore zero-width port */ + } + /* If current port is invalid, we do not combine */ + if (0 == get_width()) { + lsb_ = 0; + msb_ = width; + return; + } + /* Increase MSB */ + msb_ += width; + return; +} + +/* Swap lsb and msb */ +void BasicPort::revert() { + std::swap(lsb_, msb_); + return; +} + +/* rotate: increase both lsb and msb by an offset */ +bool BasicPort::rotate(const size_t& offset) { + /* If offset is 0, we do nothing */ + if (0 == offset) { + return true; + } + + /* If current width is 0, we set a width using the offset! */ + if (0 == get_width()) { + set_width(offset); + return true; + } + /* check if leads to overflow: + * if limits - msb is larger than offset + */ + if ( (std::numeric_limits::max() - msb_ < offset) ) { + return false; + } + /* Increase LSB and MSB */ + lsb_ += offset; + msb_ += offset; + return true; +} + +/* rotate: decrease both lsb and msb by an offset */ +bool BasicPort::counter_rotate(const size_t& offset) { + /* If current port is invalid or offset is 0, + * we do nothing + */ + if ((0 == offset) || (0 == get_width())) { + return true; + } + /* check if leads to overflow: + * if limits is larger than offset + */ + if ( (std::numeric_limits::min() + lsb_ < offset) ) { + return false; + } + /* decrease LSB and MSB */ + lsb_ -= offset; + msb_ -= offset; + return true; +} + +/* Reset to initial port */ +void BasicPort::reset() { + make_invalid(); + return; +} + +/* Combine two ports */ +void BasicPort::combine(const BasicPort& port) { + /* LSB follows the current LSB */ + /* MSB increases */ + VTR_ASSERT(0 < port.get_width() ); /* Make sure port is valid */ + /* If current port is invalid, we do not combine */ + if (0 == get_width()) { + return; + } + /* Increase MSB */ + msb_ += port.get_width(); + return; +} + +/* A restricted combine function for two ports, + * Following conditions will be applied: + * 1. the two ports have the same name + * Note: you must run mergable() function first + * to make sure this assumption is valid + * 2. the new MSB will be the maximum MSB of the two ports + * 3. the new LSB will be the minimum LSB of the two ports + * 4. both ports should be valid!!! + */ +void BasicPort::merge(const BasicPort& portA) { + VTR_ASSERT(true == this->mergeable(portA)); + VTR_ASSERT(true == this->is_valid() && true == portA.is_valid()); + /* We skip merging if the portA is already contained by this port */ + if (true == this->contained(portA)) { + return; + } + /* LSB follows the minium LSB of the two ports */ + lsb_ = std::min((int)lsb_, (int)portA.get_lsb()); + /* MSB follows the minium MSB of the two ports */ + msb_ = std::max((int)msb_, (int)portA.get_msb()); + /* Origin port width follows the maximum of the two ports */ + msb_ = std::max((int)origin_port_width_, (int)portA.get_origin_port_width()); + return; +} + +/* Internal functions */ +/* Make a port to be invalid: msb < lsb */ +void BasicPort::make_invalid() { + /* set a default invalid port */ + lsb_ = 1; + msb_ = 0; + return; +} + +/* check if port size is valid > 0 */ +bool BasicPort::is_valid() const { + /* msb should be equal or greater than lsb, if this is a valid port */ + if ( msb_ < lsb_ ) { + return false; + } + return true; +} + +/************************************************************************ + * ConfPorts member functions + ***********************************************************************/ + +/************************************************************************ + * Constructor + ***********************************************************************/ +/* Default constructor */ +ConfPorts::ConfPorts() { + /* default port */ + reserved_.reset(); + regular_.reset(); +} + +/* copy */ +ConfPorts::ConfPorts(const ConfPorts& conf_ports) { + set(conf_ports); +} + +/************************************************************************ + * Accessors + ***********************************************************************/ +size_t ConfPorts::get_reserved_port_width() const { + return reserved_.get_width(); +} + +size_t ConfPorts::get_reserved_port_lsb() const { + return reserved_.get_lsb(); +} + +size_t ConfPorts::get_reserved_port_msb() const { + return reserved_.get_msb(); +} + +size_t ConfPorts::get_regular_port_width() const { + return regular_.get_width(); +} + +size_t ConfPorts::get_regular_port_lsb() const { + return regular_.get_lsb(); +} + +size_t ConfPorts::get_regular_port_msb() const { + return regular_.get_msb(); +} + +/************************************************************************ + * Mutators + ***********************************************************************/ +void ConfPorts::set(const ConfPorts& conf_ports) { + set_reserved_port(conf_ports.get_reserved_port_width()); + set_regular_port(conf_ports.get_regular_port_lsb(), conf_ports.get_regular_port_msb()); + return; +} + +void ConfPorts::set_reserved_port(size_t width) { + reserved_.set_width(width); + return; +} + +void ConfPorts::set_regular_port(size_t width) { + regular_.set_width(width); + return; +} + +void ConfPorts::set_regular_port(size_t lsb, size_t msb) { + regular_.set_width(lsb, msb); + return; +} + +void ConfPorts::set_regular_port_lsb(size_t lsb) { + regular_.set_lsb(lsb); + return; +} + +void ConfPorts::set_regular_port_msb(size_t msb) { + regular_.set_msb(msb); + return; +} + +/* Increase the port width of reserved port */ +void ConfPorts::expand_reserved_port(size_t width) { + reserved_.expand(width); + return; +} + +/* Increase the port width of regular port */ +void ConfPorts::expand_regular_port(size_t width) { + regular_.expand(width); + return; +} + +/* Increase the port width of both ports */ +void ConfPorts::expand(size_t width) { + expand_reserved_port(width); + expand_regular_port(width); +} + +/* rotate */ +bool ConfPorts::rotate_regular_port(size_t offset) { + return regular_.rotate(offset); +} + +/* counter rotate */ +bool ConfPorts::counter_rotate_regular_port(size_t offset) { + return regular_.counter_rotate(offset); +} + +/* Reset to initial port */ +void ConfPorts::reset() { + reserved_.reset(); + regular_.reset(); + return; +} diff --git a/vpr/src/tileable_rr_graph/openfpga_rr_graph_utils.cpp b/vpr/src/tileable_rr_graph/openfpga_rr_graph_utils.cpp index c532b888b9b..b237e104443 100644 --- a/vpr/src/tileable_rr_graph/openfpga_rr_graph_utils.cpp +++ b/vpr/src/tileable_rr_graph/openfpga_rr_graph_utils.cpp @@ -10,6 +10,8 @@ #include "openfpga_rr_graph_utils.h" #include "rr_graph_types.h" +#include "rr_graph_view.h" +#include "vtr_geometry.h" /************************************************************************ * Get the coordinator of a starting point of a routing track @@ -19,7 +21,7 @@ * For routing tracks in DEC_DIRECTION * (xhigh, yhigh) should be the starting point ***********************************************************************/ -vtr::Point get_track_rr_node_start_coordinate(const RRGraph& rr_graph, +vtr::Point get_track_rr_node_start_coordinate(const RRGraphView& rr_graph, const RRNodeId& track_rr_node) { /* Make sure we have CHANX or CHANY */ VTR_ASSERT((CHANX == rr_graph.node_type(track_rr_node)) @@ -45,7 +47,7 @@ vtr::Point get_track_rr_node_start_coordinate(const RRGraph& rr_graph, * For routing tracks in DEC_DIRECTION * (xlow, ylow) should be the starting point ***********************************************************************/ -vtr::Point get_track_rr_node_end_coordinate(const RRGraph& rr_graph, +vtr::Point get_track_rr_node_end_coordinate(const RRGraphView& rr_graph, const RRNodeId& track_rr_node) { /* Make sure we have CHANX or CHANY */ VTR_ASSERT((CHANX == rr_graph.node_type(track_rr_node)) @@ -67,14 +69,22 @@ vtr::Point get_track_rr_node_end_coordinate(const RRGraph& rr_graph, * Find the driver switches for a node in the rr_graph * This function only return unique driver switches ***********************************************************************/ -std::vector get_rr_graph_driver_switches(const RRGraph& rr_graph, +std::vector get_rr_graph_driver_switches(const RRGraphView& rr_graph, const RRNodeId& node) { + std::vector driver_switches; + +// NYI +// unused argements + (void)(rr_graph); + (void)(node); +#if 0 for (const RREdgeId& edge : rr_graph.node_in_edges(node)) { if (driver_switches.end() == std::find(driver_switches.begin(), driver_switches.end(), rr_graph.edge_switch(edge))) { driver_switches.push_back(rr_graph.edge_switch(edge)); } } +#endif return driver_switches; } @@ -82,12 +92,19 @@ std::vector get_rr_graph_driver_switches(const RRGraph& rr_graph, /************************************************************************ * Find the driver nodes for a node in the rr_graph ***********************************************************************/ -std::vector get_rr_graph_driver_nodes(const RRGraph& rr_graph, +std::vector get_rr_graph_driver_nodes(const RRGraphView& rr_graph, const RRNodeId& node) { std::vector driver_nodes; + +// NYI +// unused argements + (void)(rr_graph); + (void)(node); +#if 0 for (const RREdgeId& edge : rr_graph.node_in_edges(node)) { driver_nodes.push_back(rr_graph.edge_src_node(edge)); } +#endif return driver_nodes; } @@ -95,9 +112,17 @@ std::vector get_rr_graph_driver_nodes(const RRGraph& rr_graph, /************************************************************************ * Find the configurable driver nodes for a node in the rr_graph ***********************************************************************/ -std::vector get_rr_graph_configurable_driver_nodes(const RRGraph& rr_graph, +std::vector get_rr_graph_configurable_driver_nodes(const RRGraphView& rr_graph, const RRNodeId& node) { std::vector driver_nodes; + +// NYI +// unused argements + (void)(rr_graph); + (void)(node); +#if 0 + (void)(rr_graph); + (void)(node); for (const RREdgeId& edge : rr_graph.node_in_edges(node)) { /* Bypass non-configurable edges */ if (false == rr_graph.edge_is_configurable(edge)) { @@ -105,6 +130,7 @@ std::vector get_rr_graph_configurable_driver_nodes(const RRGraph& rr_g } driver_nodes.push_back(rr_graph.edge_src_node(edge)); } +#endif return driver_nodes; } @@ -112,9 +138,15 @@ std::vector get_rr_graph_configurable_driver_nodes(const RRGraph& rr_g /************************************************************************ * Find the configurable driver nodes for a node in the rr_graph ***********************************************************************/ -std::vector get_rr_graph_non_configurable_driver_nodes(const RRGraph& rr_graph, +std::vector get_rr_graph_non_configurable_driver_nodes(const RRGraphView& rr_graph, const RRNodeId& node) { std::vector driver_nodes; + +// NYI +// unused argements + (void)(rr_graph); + (void)(node); +#if 0 for (const RREdgeId& edge : rr_graph.node_in_edges(node)) { /* Bypass configurable edges */ if (true == rr_graph.edge_is_configurable(edge)) { @@ -122,6 +154,7 @@ std::vector get_rr_graph_non_configurable_driver_nodes(const RRGraph& } driver_nodes.push_back(rr_graph.edge_src_node(edge)); } +#endif return driver_nodes; } @@ -132,11 +165,16 @@ std::vector get_rr_graph_non_configurable_driver_nodes(const RRGraph& * - Have only 1 fan-out * - The only fan-out is an IPIN ***********************************************************************/ -bool is_opin_direct_connected_ipin(const RRGraph& rr_graph, +bool is_opin_direct_connected_ipin(const RRGraphView& rr_graph, const RRNodeId& node) { /* We only accept OPIN */ VTR_ASSERT(OPIN == rr_graph.node_type(node)); +// NYI +// unused argements + (void)(rr_graph); + (void)(node); +#if 0 if (1 != rr_graph.node_out_edges(node).size()) { return false; } @@ -148,6 +186,7 @@ bool is_opin_direct_connected_ipin(const RRGraph& rr_graph, return false; } } +#endif return true; } @@ -158,11 +197,16 @@ bool is_opin_direct_connected_ipin(const RRGraph& rr_graph, * - Have only 1 fan-in * - The only fan-in is an OPIN ***********************************************************************/ -bool is_ipin_direct_connected_opin(const RRGraph& rr_graph, +bool is_ipin_direct_connected_opin(const RRGraphView& rr_graph, const RRNodeId& node) { /* We only accept IPIN */ VTR_ASSERT(IPIN == rr_graph.node_type(node)); +// NYI +// unused argements + (void)(rr_graph); + (void)(node); +#if 0 if (1 != rr_graph.node_in_edges(node).size()) { return false; } @@ -174,6 +218,7 @@ bool is_ipin_direct_connected_opin(const RRGraph& rr_graph, return false; } } +#endif return true; } diff --git a/vpr/src/tileable_rr_graph/openfpga_rr_graph_utils.h b/vpr/src/tileable_rr_graph/openfpga_rr_graph_utils.h index 1a1801379ec..69668d762c7 100644 --- a/vpr/src/tileable_rr_graph/openfpga_rr_graph_utils.h +++ b/vpr/src/tileable_rr_graph/openfpga_rr_graph_utils.h @@ -9,33 +9,34 @@ /* Headers from vpr library */ #include "rr_graph_obj.h" +#include "rr_graph_view.h" /******************************************************************** * Function declaration *******************************************************************/ -vtr::Point get_track_rr_node_start_coordinate(const RRGraph& rr_graph, +vtr::Point get_track_rr_node_start_coordinate(const RRGraphView& rr_graph, const RRNodeId& track_rr_node); -vtr::Point get_track_rr_node_end_coordinate(const RRGraph& rr_graph, +vtr::Point get_track_rr_node_end_coordinate(const RRGraphView& rr_graph, const RRNodeId& track_rr_node); -std::vector get_rr_graph_driver_switches(const RRGraph& rr_graph, +std::vector get_rr_graph_driver_switches(const RRGraphView& rr_graph, const RRNodeId& node); -std::vector get_rr_graph_driver_nodes(const RRGraph& rr_graph, +std::vector get_rr_graph_driver_nodes(const RRGraphView& rr_graph, const RRNodeId& node); -std::vector get_rr_graph_configurable_driver_nodes(const RRGraph& rr_graph, +std::vector get_rr_graph_configurable_driver_nodes(const RRGraphView& rr_graph, const RRNodeId& node); -std::vector get_rr_graph_non_configurable_driver_nodes(const RRGraph& rr_graph, +std::vector get_rr_graph_non_configurable_driver_nodes(const RRGraphView& rr_graph, const RRNodeId& node); -bool is_opin_direct_connected_ipin(const RRGraph& rr_graph, +bool is_opin_direct_connected_ipin(const RRGraphView& rr_graph, const RRNodeId& node); -bool is_ipin_direct_connected_opin(const RRGraph& rr_graph, +bool is_ipin_direct_connected_opin(const RRGraphView& rr_graph, const RRNodeId& node); #endif diff --git a/vpr/src/tileable_rr_graph/openfpga_side_manager.cpp b/vpr/src/tileable_rr_graph/openfpga_side_manager.cpp new file mode 100644 index 00000000000..ceb93882d23 --- /dev/null +++ b/vpr/src/tileable_rr_graph/openfpga_side_manager.cpp @@ -0,0 +1,171 @@ +/******************************************************************** + * Memeber function for class SideManagerManager + *******************************************************************/ +#include "openfpga_side_manager.h" + +/* Constructors */ +SideManager::SideManager(enum e_side side) { + side_ = side; +} + +SideManager::SideManager() { + side_ = NUM_SIDES; +} + +SideManager::SideManager(size_t side) { + set_side(side); +} + +/* Public Accessors */ +enum e_side SideManager::get_side() const { + return side_; +} + +enum e_side SideManager::get_opposite() const { + switch (side_) { + case TOP: + return BOTTOM; + case RIGHT: + return LEFT; + case BOTTOM: + return TOP; + case LEFT: + return RIGHT; + default: + return NUM_SIDES; + } +} + +enum e_side SideManager::get_rotate_clockwise() const { + switch (side_) { + case TOP: + return RIGHT; + case RIGHT: + return BOTTOM; + case BOTTOM: + return LEFT; + case LEFT: + return TOP; + default: + return NUM_SIDES; + } +} + +enum e_side SideManager::get_rotate_counterclockwise() const { + switch (side_) { + case TOP: + return LEFT; + case RIGHT: + return TOP; + case BOTTOM: + return RIGHT; + case LEFT: + return BOTTOM; + default: + return NUM_SIDES; + } +} + +bool SideManager::validate() const { + if (NUM_SIDES == side_) { + return false; + } + return true; +} + +size_t SideManager::to_size_t() const { + switch (side_) { + case TOP: + return 0; + case RIGHT: + return 1; + case BOTTOM: + return 2; + case LEFT: + return 3; + default: + return 4; + } +} + +/* Convert to char* */ +const char* SideManager::c_str() const { + switch (side_) { + case TOP: + return "top"; + case RIGHT: + return "right"; + case BOTTOM: + return "bottom"; + case LEFT: + return "left"; + default: + return "invalid_side"; + } +} + +/* Convert to char* */ +std::string SideManager::to_string() const { + std::string ret; + switch (side_) { + case TOP: + ret.assign("top"); + break; + case RIGHT: + ret.assign("right"); + break; + case BOTTOM: + ret.assign("bottom"); + break; + case LEFT: + ret.assign("left"); + break; + default: + ret.assign("invalid_side"); + break; + } + + return ret; +} + +/* Public Mutators */ +void SideManager::set_side(size_t side) { + switch (side) { + case 0: + side_ = TOP; + return; + case 1: + side_ = RIGHT; + return; + case 2: + side_ = BOTTOM; + return; + case 3: + side_ = LEFT; + return; + default: + side_ = NUM_SIDES; + return; + } +} + +void SideManager::set_side(enum e_side side) { + side_ = side; + return; +} + +void SideManager::set_opposite() { + side_ = get_opposite(); + return; +} + +void SideManager::rotate_clockwise() { + side_ = get_rotate_clockwise(); + return; +} + +void SideManager::rotate_counterclockwise() { + side_ = get_rotate_counterclockwise(); + return; +} + diff --git a/vpr/src/tileable_rr_graph/rr_chan.cpp b/vpr/src/tileable_rr_graph/rr_chan.cpp index 13ba606cefd..2f69bd659b1 100644 --- a/vpr/src/tileable_rr_graph/rr_chan.cpp +++ b/vpr/src/tileable_rr_graph/rr_chan.cpp @@ -67,7 +67,7 @@ RRSegmentId RRChan::get_node_segment(const size_t& track_num) const { } /* evaluate if two RRChan is mirror to each other */ -bool RRChan::is_mirror(const RRGraph& rr_graph, const RRChan& cand) const { +bool RRChan::is_mirror(const RRGraphView& rr_graph, const RRChan& cand) const { /* If any following element does not match, it is not mirror */ /* 1. type */ if (this->get_type() != cand.get_type()) { @@ -166,7 +166,7 @@ void RRChan::reserve_node(const size_t& node_size) { } /* add a node to the array */ -void RRChan::add_node(const RRGraph& rr_graph, const RRNodeId& node, const RRSegmentId& node_segment) { +void RRChan::add_node(const RRGraphView& rr_graph, const RRNodeId& node, const RRSegmentId& node_segment) { /* fill the dedicated element in the vector */ nodes_.push_back(node); node_segments_.push_back(node_segment); @@ -198,7 +198,7 @@ bool RRChan::valid_type(const t_rr_type& type) const { } /* Check each node, see if the node type is consistent with the type */ -bool RRChan::valid_node_type(const RRGraph& rr_graph, const RRNodeId& node) const { +bool RRChan::valid_node_type(const RRGraphView& rr_graph, const RRNodeId& node) const { valid_type(rr_graph.node_type(node)); if (NUM_RR_TYPES == type_) { return true; diff --git a/vpr/src/tileable_rr_graph/rr_chan.h b/vpr/src/tileable_rr_graph/rr_chan.h index e6dacde42f8..effa69273f7 100644 --- a/vpr/src/tileable_rr_graph/rr_chan.h +++ b/vpr/src/tileable_rr_graph/rr_chan.h @@ -15,6 +15,8 @@ /* Headers from vpr library */ #include "rr_graph_obj.h" +#include "rr_graph_view.h" + /******************************************************************** * RRChan object aim to describe a routing channel in a routing resource graph * - What are the nodes in the RRGraph object, for each routing track @@ -48,7 +50,7 @@ class RRChan { RRNodeId get_node(const size_t& track_num) const; /* get the rr_node with the track_id */ RRSegmentId get_node_segment(const RRNodeId& node) const; RRSegmentId get_node_segment(const size_t& track_num) const; - bool is_mirror(const RRGraph& rr_graph, const RRChan& cand) const; /* evaluate if two RR_chan is mirror to each other */ + bool is_mirror(const RRGraphView& rr_graph, const RRChan& cand) const; /* evaluate if two RR_chan is mirror to each other */ std::vector get_segment_ids() const; /* Get a list of segments used in this routing channel */ std::vector get_node_ids_by_segment_ids(const RRSegmentId& seg_id) const; /* Get a list of segments used in this routing channel */ public: /* Mutators */ @@ -62,7 +64,7 @@ class RRChan { void reserve_node(const size_t& node_size); /* add a node to the routing channel */ - void add_node(const RRGraph& rr_graph, const RRNodeId& node, const RRSegmentId& node_segment); + void add_node(const RRGraphView& rr_graph, const RRNodeId& node, const RRSegmentId& node_segment); /* clear the content */ void clear(); @@ -73,7 +75,7 @@ class RRChan { bool valid_type(const t_rr_type& type) const; /* Check each node, see if the node type is consistent with the type of routing channel */ - bool valid_node_type(const RRGraph& rr_graph, const RRNodeId& node) const; + bool valid_node_type(const RRGraphView& rr_graph, const RRNodeId& node) const; /* Validate if the track number in the range */ bool valid_node_id(const size_t& node_id) const; diff --git a/vpr/src/tileable_rr_graph/rr_graph_obj_util.cpp b/vpr/src/tileable_rr_graph/rr_graph_obj_util.cpp new file mode 100644 index 00000000000..bef1c745557 --- /dev/null +++ b/vpr/src/tileable_rr_graph/rr_graph_obj_util.cpp @@ -0,0 +1,161 @@ +/**************************************************************************** + * This file include most-utilized functions that manipulate on the + * RRGraph object + ***************************************************************************/ +#include "rr_graph_obj.h" +#include "rr_graph_obj_util.h" + +/**************************************************************************** + * Find the switches interconnecting two nodes + * Return a vector of switch ids + ***************************************************************************/ +std::vector find_rr_graph_switches(const RRGraphView& rr_graph, + const RRNodeId& from_node, + const RRNodeId& to_node) { + + std::vector switches; + + // NYI + // unused parameters + (void)(rr_graph); + (void)(from_node); + (void)(to_node); + #if 0 + std::vector edges = rr_graph.find_edges(from_node, to_node); + if (true == edges.empty()) { + /* edge is open, we return an empty vector of switches */ + return switches; + } + + /* Reach here, edge list is not empty, find switch id one by one + * and update the switch list + */ + for (auto edge : edges) { + switches.push_back(rr_graph.edge_switch(edge)); + } + #endif + + return switches; +} + +/********************************************************************* + * Like the RRGraph.find_node() but returns all matching nodes, + * rather than just the first. This is particularly useful for getting all instances + * of a specific IPIN/OPIN at a specific grid tile (x,y) location. + **********************************************************************/ +std::vector find_rr_graph_nodes(const RRGraphView& rr_graph, + const int& x, + const int& y, + const t_rr_type& rr_type, + const int& ptc) { + std::vector indices; + + // NYI + // unused parameters + (void)(rr_graph); + (void)(x); + (void)(y); + (void)(rr_type); + (void)(ptc); + #if 0 + if (rr_type == IPIN || rr_type == OPIN) { + //For pins we need to look at all the sides of the current grid tile + + for (e_side side : SIDES) { + RRNodeId rr_node_index = rr_graph.find_node(x, y, rr_type, ptc, side); + + if (rr_node_index != RRNodeId::INVALID()) { + indices.push_back(rr_node_index); + } + } + } else { + //Sides do not effect non-pins so there should only be one per ptc + RRNodeId rr_node_index = rr_graph.find_node(x, y, rr_type, ptc); + + if (rr_node_index != RRNodeId::INVALID()) { + indices.push_back(rr_node_index); + } + } + #endif + + return indices; +} + +/********************************************************************* + * Find a list of rr nodes in a routing channel at (x,y) + **********************************************************************/ +std::vector find_rr_graph_chan_nodes(const RRGraphView& rr_graph, + const int& x, + const int& y, + const t_rr_type& rr_type) { + std::vector indices; + + VTR_ASSERT(rr_type == CHANX || rr_type == CHANY); + + // NYI + // unused parameters + (void)(rr_graph); + (void)(x); + (void)(y); + #if 0 + for (short track = 0; track < rr_graph.chan_num_tracks(x, y, rr_type); ++track) { + RRNodeId rr_node_index = rr_graph.find_node(x, y, rr_type, track); + + if (rr_node_index != RRNodeId::INVALID()) { + indices.push_back(rr_node_index); + } + } + #endif + + return indices; +} + +/********************************************************************* + * Find a list of rr_nodes that locate at a side of a grid + **********************************************************************/ +std::vector find_rr_graph_grid_nodes(const RRGraphView& rr_graph, + const DeviceGrid& device_grid, + const int& x, + const int& y, + const t_rr_type& rr_type, + const e_side& side) { + std::vector indices; + + VTR_ASSERT(rr_type == IPIN || rr_type == OPIN); + + /* Ensure that (x, y) is a valid location in grids */ + VTR_ASSERT(size_t(x) <= device_grid.width() && size_t(y) <= device_grid.height()); + + /* Ensure we have a valid side */ + VTR_ASSERT(side != NUM_SIDES); + + /* Find all the pins on the side of the grid */ + int width_offset = device_grid[x][y].width_offset; + int height_offset = device_grid[x][y].height_offset; + for (int pin = 0; pin < device_grid[x][y].type->num_pins; ++pin) { + /* Skip those pins have been ignored during rr_graph build-up */ + if (true == device_grid[x][y].type->is_ignored_pin[pin]) { + continue; + } + if (false == device_grid[x][y].type->pinloc[width_offset][height_offset][side][pin]) { + /* Not the pin on this side, we skip */ + continue; + } + + // NYI + // unused parameter + (void)(rr_graph); + #if 0 + /* Try to find the rr node */ + RRNodeId rr_node_index = rr_graph.find_node(x, y, rr_type, pin, side); + if (rr_node_index != RRNodeId::INVALID()) { + indices.push_back(rr_node_index); + } + #endif + + } + + + return indices; +} + diff --git a/vpr/src/tileable_rr_graph/rr_graph_obj_util.h b/vpr/src/tileable_rr_graph/rr_graph_obj_util.h index 01f753ddcf6..c413386c5dc 100644 --- a/vpr/src/tileable_rr_graph/rr_graph_obj_util.h +++ b/vpr/src/tileable_rr_graph/rr_graph_obj_util.h @@ -7,24 +7,25 @@ #include #include "rr_graph_obj.h" #include "device_grid.h" +#include "rr_graph_view.h" /* Get node-to-node switches in a RRGraph */ -std::vector find_rr_graph_switches(const RRGraph& rr_graph, +std::vector find_rr_graph_switches(const RRGraphView& rr_graph, const RRNodeId& from_node, const RRNodeId& to_node); -std::vector find_rr_graph_nodes(const RRGraph& rr_graph, +std::vector find_rr_graph_nodes(const RRGraphView& rr_graph, const int& x, const int& y, const t_rr_type& rr_type, const int& ptc); -std::vector find_rr_graph_chan_nodes(const RRGraph& rr_graph, +std::vector find_rr_graph_chan_nodes(const RRGraphView& rr_graph, const int& x, const int& y, const t_rr_type& rr_type); -std::vector find_rr_graph_grid_nodes(const RRGraph& rr_graph, +std::vector find_rr_graph_grid_nodes(const RRGraphView& rr_graph, const DeviceGrid& device_grid, const int& x, const int& y, diff --git a/vpr/src/tileable_rr_graph/rr_gsb.cpp b/vpr/src/tileable_rr_graph/rr_gsb.cpp index 2a467d61ff5..59436c84c1d 100644 --- a/vpr/src/tileable_rr_graph/rr_gsb.cpp +++ b/vpr/src/tileable_rr_graph/rr_gsb.cpp @@ -9,6 +9,7 @@ #include "openfpga_side_manager.h" #include "rr_gsb.h" +#include "vtr_geometry.h" /************************************************************************ * Constructors @@ -136,7 +137,7 @@ RRNodeId RRGSB::get_chan_node(const e_side& side, const size_t& track_id) const return chan_node_[side_manager.to_size_t()].get_node(track_id); } -std::vector RRGSB::get_chan_node_in_edges(const RRGraph& rr_graph, +std::vector RRGSB::get_chan_node_in_edges(const RRGraphView& rr_graph, const e_side& side, const size_t& track_id) const { SideManager side_manager(side); @@ -156,9 +157,15 @@ std::vector RRGSB::get_chan_node_in_edges(const RRGraph& rr_graph, */ if (0 == chan_node_in_edges_.size()) { std::vector unsorted_edges; + + // NYI + // unused parameter + (void)(rr_graph); + #if 0 for (const RREdgeId& edge : rr_graph.node_in_edges(get_chan_node(side, track_id))) { unsorted_edges.push_back(edge); } + #endif return unsorted_edges; } @@ -235,7 +242,7 @@ int RRGSB::get_chan_node_index(const e_side& node_side, const RRNodeId& node) co } /* Get the node index in the array, return -1 if not found */ -int RRGSB::get_node_index(const RRGraph& rr_graph, +int RRGSB::get_node_index(const RRGraphView& rr_graph, const RRNodeId& node, const e_side& node_side, const PORTS& node_direction) const { @@ -288,7 +295,7 @@ int RRGSB::get_node_index(const RRGraph& rr_graph, } /* Get the side of a node in this SB */ -void RRGSB::get_node_side_and_index(const RRGraph& rr_graph, +void RRGSB::get_node_side_and_index(const RRGraphView& rr_graph, const RRNodeId& node, const PORTS& node_direction, e_side& node_side, @@ -325,7 +332,7 @@ void RRGSB::get_node_side_and_index(const RRGraph& rr_graph, } /* Check if the node exist in the opposite side of this Switch Block */ -bool RRGSB::is_sb_node_exist_opposite_side(const RRGraph& rr_graph, +bool RRGSB::is_sb_node_exist_opposite_side(const RRGraphView& rr_graph, const RRNodeId& node, const e_side& node_side) const { SideManager side_manager(node_side); @@ -342,7 +349,7 @@ bool RRGSB::is_sb_node_exist_opposite_side(const RRGraph& rr_graph, } /* check if the candidate CB is a mirror of the current one */ -bool RRGSB::is_cb_mirror(const RRGraph& rr_graph, const RRGSB& cand, const t_rr_type& cb_type) const { +bool RRGSB::is_cb_mirror(const RRGraphView& rr_graph, const RRGSB& cand, const t_rr_type& cb_type) const { /* Check if channel width is the same */ if (get_cb_chan_width(cb_type) != cand.get_cb_chan_width(cb_type)) { return false; @@ -403,7 +410,7 @@ bool RRGSB::is_sb_exist() const { * For DEC_DIRECTION * (xhigh, yhigh) should be same as the GSB side coordinate ***********************************************************************/ -bool RRGSB::is_sb_node_passing_wire(const RRGraph& rr_graph, +bool RRGSB::is_sb_node_passing_wire(const RRGraphView& rr_graph, const e_side& node_side, const size_t& track_id) const { /* Get the rr_node */ @@ -441,7 +448,11 @@ bool RRGSB::is_sb_node_passing_wire(const RRGraph& rr_graph, if (true != is_sb_node_exist_opposite_side(rr_graph, track_node, node_side)) { VTR_LOG("GSB[%lu][%lu] track node[%lu] at %s:\n", get_x(), get_y(), track_id, SIDE_STRING[node_side]); + + // NYI + #if 0 rr_graph.print_node(track_node); + #endif } VTR_ASSERT(true == is_sb_node_exist_opposite_side(rr_graph, track_node, node_side)); @@ -454,7 +465,7 @@ bool RRGSB::is_sb_node_passing_wire(const RRGraph& rr_graph, * Number of channel/opin/ipin rr_nodes are same * If all above are satisfied, the two switch blocks may be mirrors ! */ -bool RRGSB::is_sb_mirrorable(const RRGraph& rr_graph, const RRGSB& cand) const { +bool RRGSB::is_sb_mirrorable(const RRGraphView& rr_graph, const RRGSB& cand) const { /* check the numbers of sides */ if (get_num_sides() != cand.get_num_sides()) { return false; @@ -490,7 +501,7 @@ bool RRGSB::is_sb_mirrorable(const RRGraph& rr_graph, const RRGSB& cand) const { } /* check if all the routing segments of a side of candidate SB is a mirror of the current one */ -bool RRGSB::is_sb_side_segment_mirror(const RRGraph& rr_graph, const RRGSB& cand, const e_side& side, const RRSegmentId& seg_id) const { +bool RRGSB::is_sb_side_segment_mirror(const RRGraphView& rr_graph, const RRGSB& cand, const e_side& side, const RRSegmentId& seg_id) const { /* Create a side manager */ SideManager side_manager(side); @@ -539,7 +550,7 @@ bool RRGSB::is_sb_side_segment_mirror(const RRGraph& rr_graph, const RRGSB& cand } /* check if a side of candidate SB is a mirror of the current one */ -bool RRGSB::is_sb_side_mirror(const RRGraph& rr_graph, const RRGSB& cand, const e_side& side) const { +bool RRGSB::is_sb_side_mirror(const RRGraphView& rr_graph, const RRGSB& cand, const e_side& side) const { /* get a list of segments */ std::vector seg_ids = chan_node_[size_t(side)].get_segment_ids(); @@ -553,7 +564,7 @@ bool RRGSB::is_sb_side_mirror(const RRGraph& rr_graph, const RRGSB& cand, const } /* check if the candidate SB is a mirror of the current one */ -bool RRGSB::is_sb_mirror(const RRGraph& rr_graph, const RRGSB& cand) const { +bool RRGSB::is_sb_mirror(const RRGraphView& rr_graph, const RRGSB& cand) const { /* check the numbers of sides */ if (get_num_sides() != cand.get_num_sides()) { return false; @@ -790,7 +801,7 @@ 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, +void RRGSB::sort_chan_node_in_edges(const RRGraphView& rr_graph, const e_side& chan_side, const size_t& track_id) { std::map> from_grid_edge_map; @@ -810,6 +821,13 @@ void RRGSB::sort_chan_node_in_edges(const RRGraph& rr_graph, * For each side, the edge from grid pins will be the 1st part * while the edge from routing tracks will be the 2nd part */ + + // NYI + // unused parameter + (void)(rr_graph); + // unused variable + (void)(chan_node); + #if 0 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); @@ -839,6 +857,7 @@ void RRGSB::sort_chan_node_in_edges(const RRGraph& rr_graph, edge_counter++; } + #endif /* Store the sorted edge */ for (size_t side = 0; side < get_num_sides(); ++side) { @@ -862,7 +881,7 @@ void RRGSB::sort_chan_node_in_edges(const RRGraph& rr_graph, 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) { +void RRGSB::sort_chan_node_in_edges(const RRGraphView& rr_graph) { /* Allocate here, as sort edge is optional, we do not allocate when adding nodes */ chan_node_in_edges_.resize(get_num_sides()); @@ -938,7 +957,7 @@ void RRGSB::clear_one_side(const e_side& node_side) { * 2. OPIN or IPIN: should have the same side and index * 3. each drive_rr_switch should be the same */ -bool RRGSB::is_sb_node_mirror(const RRGraph& rr_graph, +bool RRGSB::is_sb_node_mirror(const RRGraphView& rr_graph, const RRGSB& cand, const e_side& node_side, const size_t& track_id) const { @@ -968,6 +987,8 @@ bool RRGSB::is_sb_node_mirror(const RRGraph& rr_graph, VTR_ASSERT(node_in_edges.size() == cand_node_in_edges.size()); + // NYI + #if 0 for (size_t iedge = 0; iedge < node_in_edges.size(); ++iedge) { RREdgeId src_edge = node_in_edges[iedge]; RREdgeId src_cand_edge = cand_node_in_edges[iedge]; @@ -992,6 +1013,7 @@ bool RRGSB::is_sb_node_mirror(const RRGraph& rr_graph, return false; } } + #endif return true; } @@ -1001,7 +1023,7 @@ bool RRGSB::is_sb_node_mirror(const RRGraph& rr_graph, * 1. CHANX or CHANY: should have the same side and index * 2. each drive_rr_switch should be the same */ -bool RRGSB::is_cb_node_mirror(const RRGraph& rr_graph, +bool RRGSB::is_cb_node_mirror(const RRGraphView& rr_graph, const RRGSB& cand, const t_rr_type& cb_type, const e_side& node_side, @@ -1010,6 +1032,14 @@ bool RRGSB::is_cb_node_mirror(const RRGraph& rr_graph, RRNodeId node = this->get_ipin_node(node_side, node_id); RRNodeId cand_node = cand.get_ipin_node(node_side, node_id); + // NYI + // unused parameter + (void)(rr_graph); + (void)(cb_type); + // unused variables + (void)(node); + (void)(cand_node); + #if 0 if (rr_graph.node_in_edges(node).size() != rr_graph.node_in_edges(cand_node).size()) { return false; } @@ -1064,11 +1094,12 @@ bool RRGSB::is_cb_node_mirror(const RRGraph& rr_graph, return false; } } + #endif return true; } -size_t RRGSB::get_track_id_first_short_connection(const RRGraph& rr_graph, const e_side& node_side) const { +size_t RRGSB::get_track_id_first_short_connection(const RRGraphView& rr_graph, const e_side& node_side) const { VTR_ASSERT(validate_side(node_side)); /* Walk through chan_nodes and find the first short connection */ diff --git a/vpr/src/tileable_rr_graph/rr_gsb.h b/vpr/src/tileable_rr_graph/rr_gsb.h index e533007d57a..a2106325c62 100644 --- a/vpr/src/tileable_rr_graph/rr_gsb.h +++ b/vpr/src/tileable_rr_graph/rr_gsb.h @@ -8,6 +8,7 @@ #include "vtr_geometry.h" #include "rr_chan.h" +#include "rr_graph_view.h" /******************************************************************** * Object Generic Switch Block @@ -83,7 +84,7 @@ class RRGSB { RRNodeId get_chan_node(const e_side& side, const size_t& track_id) const; /* get all the sorted incoming edges for a rr_node at a given side and track_id */ - std::vector get_chan_node_in_edges(const RRGraph& rr_graph, + std::vector get_chan_node_in_edges(const RRGraphView& rr_graph, const e_side& side, const size_t& track_id) const; @@ -107,16 +108,16 @@ class RRGSB { int get_chan_node_index(const e_side& node_side, const RRNodeId& node) const; /* Get the node index in the array, return -1 if not found */ - int get_node_index(const RRGraph& rr_graph, const RRNodeId& node, const e_side& node_side, const PORTS& node_direction) const; + int get_node_index(const RRGraphView& rr_graph, const RRNodeId& node, const e_side& node_side, const PORTS& node_direction) const; /* Given a rr_node, try to find its side and index in the Switch block */ - void get_node_side_and_index(const RRGraph& rr_graph, const RRNodeId& node, const PORTS& node_direction, e_side& node_side, int& node_index) const; + void get_node_side_and_index(const RRGraphView& rr_graph, const RRNodeId& node, const PORTS& node_direction, e_side& node_side, int& node_index) const; /* Check if the node exist in the opposite side of this Switch Block */ - bool is_sb_node_exist_opposite_side(const RRGraph& rr_graph, const RRNodeId& node, const e_side& node_side) const; + bool is_sb_node_exist_opposite_side(const RRGraphView& rr_graph, const RRNodeId& node, const e_side& node_side) const; public: /* Accessors: to identify mirrors */ /* check if the candidate SB is a mirror of the current one */ - bool is_cb_mirror(const RRGraph& rr_graph, const RRGSB& cand, const t_rr_type& cb_type) const; + bool is_cb_mirror(const RRGraphView& rr_graph, const RRGSB& cand, const t_rr_type& cb_type) const; /* check if the connect block exists in the GSB */ bool is_cb_exist(const t_rr_type& cb_type) const; @@ -125,15 +126,15 @@ class RRGSB { bool is_sb_exist() const; /* Check if the node imply a short connection inside the SB, which happens to long wires across a FPGA fabric */ - bool is_sb_node_passing_wire(const RRGraph& rr_graph, const e_side& node_side, const size_t& track_id) const; + bool is_sb_node_passing_wire(const RRGraphView& rr_graph, const e_side& node_side, const size_t& track_id) const; /* check if the candidate SB satisfy the basic requirements * on being a mirror of the current one */ - bool is_sb_mirrorable(const RRGraph& rr_graph, const RRGSB& cand) const; + bool is_sb_mirrorable(const RRGraphView& rr_graph, const RRGSB& cand) const; /* check if all the routing segments of a side of candidate SB is a mirror of the current one */ - bool is_sb_side_segment_mirror(const RRGraph& rr_graph, const RRGSB& cand, + bool is_sb_side_segment_mirror(const RRGraphView& rr_graph, const RRGSB& cand, const e_side& side, const RRSegmentId& seg_id) const; /* check if a side of candidate SB is a mirror of the current one @@ -147,7 +148,7 @@ class RRGSB { * 5. check if pin class id and pin id are same * If all above are satisfied, the side of the two switch blocks are mirrors! */ - bool is_sb_side_mirror(const RRGraph& rr_graph, const RRGSB& cand, const e_side& side) const; + bool is_sb_side_mirror(const RRGraphView& rr_graph, const RRGSB& cand, const e_side& side) const; /* check if the candidate SB is a mirror of the current one * Idenify mirror Switch blocks @@ -161,7 +162,7 @@ class RRGSB { * 5. check if pin class id and pin id are same * If all above are satisfied, the two switch blocks are mirrors! */ - bool is_sb_mirror(const RRGraph& rr_graph, const RRGSB& cand) const; + bool is_sb_mirror(const RRGraphView& rr_graph, const RRGSB& cand) const; public: /* Cooridinator conversion and output */ size_t get_x() const; /* get the x coordinate of this switch block */ @@ -204,7 +205,7 @@ class RRGSB { 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); + void sort_chan_node_in_edges(const RRGraphView& rr_graph); public: /* Mutators: cleaners */ void clear(); @@ -223,23 +224,23 @@ class RRGSB { 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, + void sort_chan_node_in_edges(const RRGraphView& rr_graph, const e_side& chan_side, const size_t& track_id); private: /* internal functions */ - bool is_sb_node_mirror(const RRGraph& rr_graph, + bool is_sb_node_mirror(const RRGraphView& rr_graph, const RRGSB& cand, const e_side& node_side, const size_t& track_id) const; - bool is_cb_node_mirror(const RRGraph& rr_graph, + bool is_cb_node_mirror(const RRGraphView& rr_graph, const RRGSB& cand, const t_rr_type& cb_type, const e_side& node_side, const size_t& node_id) const; - size_t get_track_id_first_short_connection(const RRGraph& rr_graph, const e_side& node_side) const; + size_t get_track_id_first_short_connection(const RRGraphView& rr_graph, const e_side& node_side) const; private: /* internal validators */ bool validate_num_sides() const; diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp index 1aa8766a73c..c4814f5b78e 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp @@ -233,9 +233,8 @@ void build_tileable_unidir_rr_graph(const std::vector& typ ***********************************************************************/ /* Create edges for a tileable rr_graph */ -// Link error: undefined reference to `build_rr_graph_edges` -#if 0 build_rr_graph_edges(device_ctx.rr_graph, + device_ctx.rr_graph_builder, rr_node_driver_switches, grids, device_chan_width, @@ -243,7 +242,6 @@ void build_tileable_unidir_rr_graph(const std::vector& typ Fc_in, Fc_out, sb_type, Fs, sb_subtype, subFs, wire_opposite_side); -#endif /************************************************************************ * Build direction connection lists @@ -261,13 +259,11 @@ void build_tileable_unidir_rr_graph(const std::vector& typ clb2clb_directs.push_back(clb_to_clb_directs[idirect]); } -// Link error: undefined reference to `build_rr_graph_direct_connections` -#if 0 - build_rr_graph_direct_connections(device_ctx.rr_graph, grids, delayless_rr_switch, + build_rr_graph_direct_connections(device_ctx.rr_graph, device_ctx.rr_graph_builder, device_ctx.grid, delayless_rr_switch, arch_directs, clb2clb_directs); -#endif //NYI +// We may not need to rebuild it again #if 0 /* First time to build edges so that we can remap the architecture switch to rr_switch * This is a must-do before function alloc_and_load_rr_switch_inf() diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp index 3a2ea544605..f46e1fc48da 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp @@ -19,7 +19,8 @@ * Build the edges for all the SOURCE and SINKs nodes: * 1. create edges between SOURCE and OPINs ***********************************************************************/ -void build_rr_graph_edges_for_source_nodes(RRGraph& rr_graph, +void build_rr_graph_edges_for_source_nodes(const RRGraphView& rr_graph, + RRGraphBuilder& rr_graph_builder, const vtr::vector& rr_node_driver_switches, const DeviceGrid& grids) { for (const RRNodeId& node : rr_graph.nodes()) { @@ -34,13 +35,17 @@ void build_rr_graph_edges_for_source_nodes(RRGraph& rr_graph, rr_graph.node_pin_num(node)); /* Create edges between SOURCE and OPINs */ - const RRNodeId& src_node = rr_graph.find_node(xlow - grids[xlow][ylow].width_offset, + const RRNodeId& src_node = rr_graph_builder.node_lookup().find_node(xlow - grids[xlow][ylow].width_offset, ylow - grids[xlow][ylow].height_offset, SOURCE, src_node_class_num); - VTR_ASSERT(true == rr_graph.valid_node_id(src_node)); + VTR_ASSERT(true == rr_graph.validate_node(src_node)); + // NYI + (void)(rr_node_driver_switches); + #if 0 /* add edges to the src_node */ - rr_graph.create_edge(src_node, node, rr_node_driver_switches[node]); + rr_graph_builder.create_edge(src_node, node, rr_node_driver_switches[node]); + #endif } } @@ -48,7 +53,8 @@ void build_rr_graph_edges_for_source_nodes(RRGraph& rr_graph, * Build the edges for all the SINKs nodes: * 1. create edges between IPINs and SINKs ***********************************************************************/ -void build_rr_graph_edges_for_sink_nodes(RRGraph& rr_graph, +void build_rr_graph_edges_for_sink_nodes(const RRGraphView& rr_graph, + RRGraphBuilder& rr_graph_builder, const vtr::vector& rr_node_driver_switches, const DeviceGrid& grids) { for (const RRNodeId& node : rr_graph.nodes()) { @@ -62,13 +68,23 @@ void build_rr_graph_edges_for_sink_nodes(RRGraph& rr_graph, short sink_node_class_num = get_grid_pin_class_index(grids[xlow][ylow], rr_graph.node_pin_num(node)); /* 1. create edges between IPINs and SINKs */ + // NYI + (void)(sink_node_class_num); + #if 0 const RRNodeId& sink_node = rr_graph.find_node(xlow - grids[xlow][ylow].width_offset, ylow - grids[xlow][ylow].height_offset, SINK, sink_node_class_num); VTR_ASSERT(true == rr_graph.valid_node_id(sink_node)); + #endif + // NYI + (void)(rr_node_driver_switches); + (void)(rr_graph_builder); + #if 0 /* add edges to connect the IPIN node to SINK nodes */ - rr_graph.create_edge(node, sink_node, rr_node_driver_switches[sink_node]); + rr_graph_builder.create_edge(node, sink_node, rr_node_driver_switches[sink_node]); + #endif + } } @@ -82,7 +98,8 @@ void build_rr_graph_edges_for_sink_nodes(RRGraph& rr_graph, * 2. create edges between OPINs, CHANX and CHANY (connections inside switch blocks) * 3. create edges between OPINs and IPINs (direct-connections) ***********************************************************************/ -void build_rr_graph_edges(RRGraph& rr_graph, +void build_rr_graph_edges(const RRGraphView& rr_graph, + RRGraphBuilder& rr_graph_builder, const vtr::vector& rr_node_driver_switches, const DeviceGrid& grids, const vtr::Point& device_chan_width, @@ -95,8 +112,8 @@ void build_rr_graph_edges(RRGraph& rr_graph, const int& subFs, const bool& wire_opposite_side) { /* Create edges for SOURCE and SINK nodes for a tileable rr_graph */ - build_rr_graph_edges_for_source_nodes(rr_graph, rr_node_driver_switches, grids); - build_rr_graph_edges_for_sink_nodes(rr_graph, rr_node_driver_switches, grids); + build_rr_graph_edges_for_source_nodes(rr_graph, rr_graph_builder, rr_node_driver_switches, grids); + build_rr_graph_edges_for_sink_nodes(rr_graph, rr_graph_builder, rr_node_driver_switches, grids); vtr::Point gsb_range(grids.width() - 2, grids.height() - 2); @@ -126,7 +143,7 @@ void build_rr_graph_edges(RRGraph& rr_graph, segment_inf); /* Build edges for a GSB */ - build_edges_for_one_tileable_rr_gsb(rr_graph, rr_gsb, + build_edges_for_one_tileable_rr_gsb(rr_graph_builder, rr_gsb, track2ipin_map, opin2track_map, sb_conn, rr_node_driver_switches); /* Finish this GSB, go to the next*/ @@ -137,7 +154,8 @@ void build_rr_graph_edges(RRGraph& rr_graph, /************************************************************************ * Build direct edges for Grids * ***********************************************************************/ -void build_rr_graph_direct_connections(RRGraph& rr_graph, +void build_rr_graph_direct_connections(const RRGraphView& rr_graph, + RRGraphBuilder& rr_graph_builder, const DeviceGrid& grids, const RRSwitchId& delayless_switch, const std::vector& directs, @@ -155,6 +173,7 @@ void build_rr_graph_direct_connections(RRGraph& rr_graph, } vtr::Point from_grid_coordinate(ix, iy); build_direct_connections_for_one_gsb(rr_graph, + rr_graph_builder, grids, from_grid_coordinate, delayless_switch, diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.h b/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.h index 0d5c31af691..cb43d80f8fb 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.h +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.h @@ -20,7 +20,8 @@ * Function declaration *******************************************************************/ -void build_rr_graph_edges(RRGraphView& rr_graph, +void build_rr_graph_edges(const RRGraphView& rr_graph, + RRGraphBuilder& rr_graph_builder, const vtr::vector& rr_node_driver_switches, const DeviceGrid& grids, const vtr::Point& device_chan_width, @@ -33,17 +34,20 @@ void build_rr_graph_edges(RRGraphView& rr_graph, const int& subFs, const bool& wire_opposite_side); -void build_rr_graph_direct_connections(RRGraphView& rr_graph, +void build_rr_graph_direct_connections(const RRGraphView& rr_graph, + RRGraphBuilder& rr_graph_builder, const DeviceGrid& grids, const RRSwitchId& delayless_switch, const std::vector& directs, const std::vector& clb_to_clb_directs); -void build_rr_graph_edges_for_source_nodes(RRGraph& rr_graph, +void build_rr_graph_edges_for_source_nodes(const RRGraphView& rr_graph, + RRGraphBuilder& rr_graph_builder, const vtr::vector& rr_node_driver_switches, const DeviceGrid& grids); -void build_rr_graph_edges_for_sink_nodes(RRGraph& rr_graph, +void build_rr_graph_edges_for_sink_nodes(const RRGraphView& rr_graph, + RRGraphBuilder& rr_graph_builder, const vtr::vector& rr_node_driver_switches, const DeviceGrid& grids); diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp index 4d23c3b723c..e8c019724da 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp @@ -19,6 +19,9 @@ #include "rr_graph_builder_utils.h" #include "tileable_chan_details_builder.h" #include "tileable_rr_graph_gsb.h" +#include "rr_graph_view.h" +#include "rr_graph_builder.h" +#include "vtr_geometry.h" /************************************************************************ * Internal data structures @@ -45,7 +48,7 @@ enum e_track_status { * Check if a track ends at this GSB or not * (xhigh, yhigh) should be same as the GSB side coordinate ***********************************************************************/ -static enum e_track_status determine_track_status_of_gsb(const RRGraph& rr_graph, +static enum e_track_status determine_track_status_of_gsb(const RRGraphView& rr_graph, const RRGSB& rr_gsb, const enum e_side& gsb_side, const size_t& track_id) { @@ -94,7 +97,7 @@ static enum e_track_status determine_track_status_of_gsb(const RRGraph& rr_graph * We will find the offset between gsb_side_coordinate and (xlow,ylow) of the track * Use the offset to check if the tracks should engage in this GSB connection ***********************************************************************/ -static bool is_gsb_in_track_cb_population(const RRGraph& rr_graph, +static bool is_gsb_in_track_cb_population(const RRGraphView& rr_graph, const RRGSB& rr_gsb, const e_side& gsb_side, const int& track_id, @@ -136,7 +139,7 @@ static bool is_gsb_in_track_cb_population(const RRGraph& rr_graph, * We will find the offset between gsb_side_coordinate and (xlow,ylow) of the track * Use the offset to check if the tracks should engage in this GSB connection ***********************************************************************/ -static bool is_gsb_in_track_sb_population(const RRGraph& rr_graph, +static bool is_gsb_in_track_sb_population(const RRGraphView& rr_graph, const RRGSB& rr_gsb, const e_side& gsb_side, const int& track_id, @@ -307,7 +310,7 @@ static std::vector get_switch_block_to_track_id(const e_switch_block_typ * For each side of from_tracks, we call a routine to get the list of to_tracks * Then, we fill the track2track_map ***********************************************************************/ -static void build_gsb_one_group_track_to_track_map(const RRGraph& rr_graph, +static void build_gsb_one_group_track_to_track_map(const RRGraphView& rr_graph, const RRGSB& rr_gsb, const e_switch_block_type& sb_type, const int& Fs, @@ -363,7 +366,7 @@ static void build_gsb_one_group_track_to_track_map(const RRGraph& rr_graph, // from_tracks[side].size(), inode, to_track_id, to_track_ids[to_track_id], // to_track_index, to_tracks[to_side_index].size()); const RRNodeId& to_track_node = rr_gsb.get_chan_node(to_side, to_track_index); - VTR_ASSERT(true == rr_graph.valid_node_id(to_track_node)); + VTR_ASSERT(true == rr_graph.validate_node(to_track_node)); /* from_track should be IN_PORT */ VTR_ASSERT(IN_PORT == rr_gsb.get_chan_node_direction(from_side, from_track_index)); @@ -429,7 +432,7 @@ static void build_gsb_one_group_track_to_track_map(const RRGraph& rr_graph, * b. tracks that will bypass at the BOTTOM side * 5. Apply switch block patterns to Group 2 (SUBSET, UNIVERSAL, WILTON) ***********************************************************************/ -t_track2track_map build_gsb_track_to_track_map(const RRGraph& rr_graph, +t_track2track_map build_gsb_track_to_track_map(const RRGraphView& rr_graph, const RRGSB& rr_gsb, const e_switch_block_type& sb_type, const int& Fs, @@ -527,7 +530,7 @@ t_track2track_map build_gsb_track_to_track_map(const RRGraph& rr_graph, /* Build a RRChan Object with the given channel type and coorindators */ static RRChan build_one_tileable_rr_chan(const vtr::Point& chan_coordinate, const t_rr_type& chan_type, - const RRGraph& rr_graph, + const RRGraphView& rr_graph, const ChanNodeDetails& chan_details) { std::vector chan_rr_nodes; @@ -607,7 +610,7 @@ static RRChan build_one_tileable_rr_chan(const vtr::Point& chan_coordina * as well as properly fill the ipin_grid_side information ***********************************************************************/ RRGSB build_one_tileable_rr_gsb(const DeviceGrid& grids, - const RRGraph& rr_graph, + const RRGraphView& rr_graph, const vtr::Point& device_chan_width, const std::vector& segment_inf, const vtr::Point& gsb_coordinate) { @@ -908,12 +911,22 @@ RRGSB build_one_tileable_rr_gsb(const DeviceGrid& grids, * 2. create edges between OPINs, CHANX and CHANY (connections inside switch blocks) * 3. create edges between OPINs and IPINs (direct-connections) ***********************************************************************/ -void build_edges_for_one_tileable_rr_gsb(RRGraph& rr_graph, +void build_edges_for_one_tileable_rr_gsb(RRGraphBuilder& rr_graph_builder, const RRGSB& rr_gsb, const t_track2pin_map& track2ipin_map, const t_pin2track_map& opin2track_map, const t_track2track_map& track2track_map, const vtr::vector& rr_node_driver_switches) { + + // NYI + // unused parameters + (void) (rr_graph_builder); + (void) (rr_gsb); + (void) (track2ipin_map); + (void) (opin2track_map); + (void) (track2track_map); + (void) (rr_node_driver_switches); + #if 0 /* Walk through each sides */ for (size_t side = 0; side < rr_gsb.get_num_sides(); ++side) { SideManager side_manager(side); @@ -926,7 +939,7 @@ void build_edges_for_one_tileable_rr_gsb(RRGraph& rr_graph, /* 1. create edges between OPINs and CHANX|CHANY, using opin2track_map */ /* add edges to the opin_node */ for (const RRNodeId& track_node : opin2track_map[gsb_side][inode]) { - rr_graph.create_edge(opin_node, track_node, rr_node_driver_switches[track_node]); + rr_graph_builder.create_edge(opin_node, track_node, rr_node_driver_switches[track_node]); } } @@ -940,7 +953,7 @@ void build_edges_for_one_tileable_rr_gsb(RRGraph& rr_graph, for (size_t inode = 0; inode < rr_gsb.get_chan_width(gsb_side); ++inode) { const RRNodeId& chan_node = rr_gsb.get_chan_node(gsb_side, inode); for (const RRNodeId& ipin_node : track2ipin_map[gsb_side][inode]) { - rr_graph.create_edge(chan_node, ipin_node, rr_node_driver_switches[ipin_node]); + rr_graph_builder.create_edge(chan_node, ipin_node, rr_node_driver_switches[ipin_node]); } } } @@ -953,6 +966,7 @@ void build_edges_for_one_tileable_rr_gsb(RRGraph& rr_graph, } } } + #endif } /************************************************************************ @@ -966,7 +980,7 @@ void build_edges_for_one_tileable_rr_gsb(RRGraph& rr_graph, * 3. Scale the Fc of each pin to the actual number of routing tracks * actual_Fc = (int) Fc * num_tracks / chan_width ***********************************************************************/ -static void build_gsb_one_ipin_track2pin_map(const RRGraph& rr_graph, +static void build_gsb_one_ipin_track2pin_map(const RRGraphView& rr_graph, const RRGSB& rr_gsb, const enum e_side& ipin_side, const size_t& ipin_node_id, @@ -1059,7 +1073,7 @@ static void build_gsb_one_ipin_track2pin_map(const RRGraph& rr_graph, * 3. Scale the Fc of each pin to the actual number of routing tracks * actual_Fc = (int) Fc * num_tracks / chan_width ***********************************************************************/ -static void build_gsb_one_opin_pin2track_map(const RRGraph& rr_graph, +static void build_gsb_one_opin_pin2track_map(const RRGraphView& rr_graph, const RRGSB& rr_gsb, const enum e_side& opin_side, const size_t& opin_node_id, @@ -1158,7 +1172,7 @@ static void build_gsb_one_opin_pin2track_map(const RRGraph& rr_graph, * Then, we assign IPINs to tracks evenly while satisfying the actual_Fc * 2. Convert the ipin_to_track_map to track_to_ipin_map ***********************************************************************/ -t_track2pin_map build_gsb_track_to_ipin_map(const RRGraph& rr_graph, +t_track2pin_map build_gsb_track_to_ipin_map(const RRGraphView& rr_graph, const RRGSB& rr_gsb, const DeviceGrid& grids, const std::vector& segment_inf, @@ -1248,7 +1262,7 @@ t_track2pin_map build_gsb_track_to_ipin_map(const RRGraph& rr_graph, * 3. Scale the Fc of each pin to the actual number of routing tracks * actual_Fc = (int) Fc * num_tracks / chan_width ***********************************************************************/ -t_pin2track_map build_gsb_opin_to_track_map(const RRGraph& rr_graph, +t_pin2track_map build_gsb_opin_to_track_map(const RRGraphView& rr_graph, const RRGSB& rr_gsb, const DeviceGrid& grids, const std::vector& segment_inf, @@ -1320,7 +1334,8 @@ t_pin2track_map build_gsb_opin_to_track_map(const RRGraph& rr_graph, /************************************************************************ * Add all direct clb-pin-to-clb-pin edges to given opin ***********************************************************************/ -void build_direct_connections_for_one_gsb(RRGraph& rr_graph, +void build_direct_connections_for_one_gsb(const RRGraphView& rr_graph, + RRGraphBuilder& rr_graph_builder, const DeviceGrid& grids, const vtr::Point& from_grid_coordinate, const RRSwitchId& delayless_switch, @@ -1402,12 +1417,23 @@ void build_direct_connections_for_one_gsb(RRGraph& rr_graph, std::vector ipin_grid_side = find_grid_pin_sides(grids[to_grid_coordinate.x()][to_grid_coordinate.y()], ipin); VTR_ASSERT(1 == ipin_grid_side.size()); + // NYI + // unused parameters + (void)(rr_graph); + (void)(rr_graph_builder); + // unused variables + (void)(from_grid_width_ofs); + (void)(from_grid_height_ofs); + (void)(to_grid_width_ofs); + (void)(to_grid_height_ofs); + #if 0 const RRNodeId& opin_node_id = rr_graph.find_node(from_grid_coordinate.x() - from_grid_width_ofs, from_grid_coordinate.y() - from_grid_height_ofs, OPIN, opin, opin_grid_side[0]); const RRNodeId& ipin_node_id = rr_graph.find_node(to_grid_coordinate.x() - to_grid_width_ofs, to_grid_coordinate.y() - to_grid_height_ofs, IPIN, ipin, ipin_grid_side[0]); + #endif /* VTR_LOG("Direct connection: from grid[%lu][%lu].pin[%lu] at side %s to grid[%lu][%lu].pin[%lu] at side %s\n", from_grid_coordinate.x() - from_grid_width_ofs, @@ -1419,8 +1445,15 @@ void build_direct_connections_for_one_gsb(RRGraph& rr_graph, */ /* add edges to the opin_node */ - rr_graph.create_edge(opin_node_id, ipin_node_id, + + // NYI + // unused parameters + (void)(delayless_switch); + #if 0 + rr_graph_builder.create_edge(opin_node_id, ipin_node_id, delayless_switch); + #endif + } } } diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.h b/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.h index fbe3a90f89a..992a446706a 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.h +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.h @@ -14,6 +14,8 @@ #include "rr_gsb.h" #include "rr_graph_obj.h" #include "rr_graph.h" +#include "rr_graph_view.h" +#include "rr_graph_builder.h" /******************************************************************** * Function declaration @@ -29,7 +31,7 @@ typedef std::vector>> t_pin2track_map; /************************************************************************ * Functions ***********************************************************************/ -t_track2track_map build_gsb_track_to_track_map(const RRGraph& rr_graph, +t_track2track_map build_gsb_track_to_track_map(const RRGraphView& rr_graph, const RRGSB& rr_gsb, const e_switch_block_type& sb_type, const int& Fs, @@ -39,31 +41,32 @@ t_track2track_map build_gsb_track_to_track_map(const RRGraph& rr_graph, const std::vector& segment_inf); RRGSB build_one_tileable_rr_gsb(const DeviceGrid& grids, - const RRGraph& rr_graph, + const RRGraphView& rr_graph, const vtr::Point& device_chan_width, const std::vector& segment_inf, const vtr::Point& gsb_coordinate); -void build_edges_for_one_tileable_rr_gsb(RRGraph& rr_graph, +void build_edges_for_one_tileable_rr_gsb(RRGraphBuilder& rr_graph_builder, const RRGSB& rr_gsb, const t_track2pin_map& track2ipin_map, const t_pin2track_map& opin2track_map, const t_track2track_map& track2track_map, const vtr::vector& rr_node_driver_switches); -t_track2pin_map build_gsb_track_to_ipin_map(const RRGraph& rr_graph, +t_track2pin_map build_gsb_track_to_ipin_map(const RRGraphView& rr_graph, const RRGSB& rr_gsb, const DeviceGrid& grids, const std::vector& segment_inf, const std::vector>& Fc_in); -t_pin2track_map build_gsb_opin_to_track_map(const RRGraph& rr_graph, +t_pin2track_map build_gsb_opin_to_track_map(const RRGraphView& rr_graph, const RRGSB& rr_gsb, const DeviceGrid& grids, const std::vector& segment_inf, const std::vector>& Fc_out); -void build_direct_connections_for_one_gsb(RRGraph& rr_graph, +void build_direct_connections_for_one_gsb(const RRGraphView& rr_graph, + RRGraphBuilder& rr_graph_builder, const DeviceGrid& grids, const vtr::Point& from_grid_coordinate, const RRSwitchId& delayless_switch, diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp index 20727607473..a1a6fc1ffd5 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp @@ -1,5 +1,5 @@ /************************************************************************ - * This file contains functions that are used to allocate nodes + * This file contains functions that are used to allocate nodes * for the tileable routing resource graph builder ***********************************************************************/ /* Headers from vtrutil library */ @@ -24,58 +24,60 @@ /************************************************************************ * Find the number output pins by considering all the grid ***********************************************************************/ -static size_t estimate_num_grid_rr_nodes_by_type(const DeviceGrid& grids, - const t_rr_type& node_type) { - size_t num_grid_rr_nodes = 0; - - for (size_t ix = 0; ix < grids.width(); ++ix) { - for (size_t iy = 0; iy < grids.height(); ++iy) { - /* Skip EMPTY tiles */ - if (true == is_empty_type(grids[ix][iy].type)) { - continue; - } - - /* Skip height > 1 or width > 1 tiles (mostly heterogeneous blocks) */ - if ((0 < grids[ix][iy].width_offset) - || (0 < grids[ix][iy].height_offset)) { - continue; - } - - enum e_side io_side = NUM_SIDES; - - /* If this is the block on borders, we consider IO side */ - if (true == is_io_type(grids[ix][iy].type)) { - vtr::Point io_device_size(grids.width() - 1, grids.height() - 1); - vtr::Point grid_coordinate(ix, iy); - io_side = determine_io_grid_pin_side(io_device_size, grid_coordinate); - } - - switch (node_type) { - case OPIN: - /* get the number of OPINs */ - num_grid_rr_nodes += get_grid_num_pins(grids[ix][iy], DRIVER, io_side); - break; - case IPIN: - /* get the number of IPINs */ - num_grid_rr_nodes += get_grid_num_pins(grids[ix][iy], RECEIVER, io_side); - break; - case SOURCE: - /* SOURCE: number of classes whose type is DRIVER */ - num_grid_rr_nodes += get_grid_num_classes(grids[ix][iy], DRIVER); - break; - case SINK: - /* SINK: number of classes whose type is RECEIVER */ - num_grid_rr_nodes += get_grid_num_classes(grids[ix][iy], RECEIVER); - break; - default: - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid routing resource node!\n"); - exit(1); - } - } +static +size_t estimate_num_grid_rr_nodes_by_type(const DeviceGrid& grids, + const t_rr_type& node_type) { + size_t num_grid_rr_nodes = 0; + + for (size_t ix = 0; ix < grids.width(); ++ix) { + for (size_t iy = 0; iy < grids.height(); ++iy) { + + /* Skip EMPTY tiles */ + if (true == is_empty_type(grids[ix][iy].type)) { + continue; + } + + /* Skip height > 1 or width > 1 tiles (mostly heterogeneous blocks) */ + if ( (0 < grids[ix][iy].width_offset) + || (0 < grids[ix][iy].height_offset) ) { + continue; + } + + enum e_side io_side = NUM_SIDES; + + /* If this is the block on borders, we consider IO side */ + if (true == is_io_type(grids[ix][iy].type)) { + vtr::Point io_device_size(grids.width() - 1, grids.height() - 1); + vtr::Point grid_coordinate(ix, iy); + io_side = determine_io_grid_pin_side(io_device_size, grid_coordinate); + } + + switch (node_type) { + case OPIN: + /* get the number of OPINs */ + num_grid_rr_nodes += get_grid_num_pins(grids[ix][iy], DRIVER, io_side); + break; + case IPIN: + /* get the number of IPINs */ + num_grid_rr_nodes += get_grid_num_pins(grids[ix][iy], RECEIVER, io_side); + break; + case SOURCE: + /* SOURCE: number of classes whose type is DRIVER */ + num_grid_rr_nodes += get_grid_num_classes(grids[ix][iy], DRIVER); + break; + case SINK: + /* SINK: number of classes whose type is RECEIVER */ + num_grid_rr_nodes += get_grid_num_classes(grids[ix][iy], RECEIVER); + break; + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid routing resource node!\n"); + exit(1); + } } + } - return num_grid_rr_nodes; + return num_grid_rr_nodes; } /************************************************************************ @@ -85,10 +87,10 @@ static size_t estimate_num_grid_rr_nodes_by_type(const DeviceGrid& grids, * * As such, the range of CHANX coordinate starts from x = 1, y = 0 * which is the grid (I/O) at the left bottom of the fabric - * + * * As such, the range of CHANX coordinate ends to x = width - 2, y = height - 2 * which is the grid at the top right of the core fabric - * Note that the I/O ring is + * Note that the I/O ring is * * TOP SIDE OF FPGA * @@ -106,16 +108,16 @@ static size_t estimate_num_grid_rr_nodes_by_type(const DeviceGrid& grids, * | Grid | | Grid | ... | Grid | * | [1][0] | | [2][0] | | [width-2][height-2] | * +-------------+ +-------------+ +---------------------+ - * + * * ... ... ... - * + * * +-------------+ +-------------+ +--------------+ * | X-Channel | | X-Channel | ... | X-Channel | * | [1][1] | | [2][1] | | [width-2][1] | * +-------------+ +-------------+ +--------------+ * * LEFT +-------------+ +-------------+ +--------------+ RIGHT - * SIDE | Grid | | Grid | ... | Grid | SIDE + * SIDE | Grid | | Grid | ... | Grid | SIDE * GRID | [1][1] | | [2][1] | | [width-2][1] | GRID * +-------------+ +-------------+ +--------------+ * @@ -131,9 +133,9 @@ static size_t estimate_num_grid_rr_nodes_by_type(const DeviceGrid& grids, * * BOTTOM SIDE OF FPGA * - * The figure above describe how the X-direction routing channels are - * organized in a homogeneous FPGA fabric - * Note that we talk about general-purpose uni-directional routing architecture here + * The figure above describe how the X-direction routing channels are + * organized in a homogeneous FPGA fabric + * Note that we talk about general-purpose uni-directional routing architecture here * It means that a routing track may span across multiple grids * However, the hard limits are as follows * All the routing tracks will start at the most LEFT routing channel @@ -143,7 +145,7 @@ static size_t estimate_num_grid_rr_nodes_by_type(const DeviceGrid& grids, * in the context of heterogeneous FPGAs * We may have a grid which span multiple column and rows, as exemplified in the figure below * In such case, - * all the routing tracks [x-1][y] at the left side of the grid [x][y] are forced to end + * all the routing tracks [x-1][y] at the left side of the grid [x][y] are forced to end * all the routing tracks [x+2][y] at the right side of the grid [x][y] are forced to start * And there are no routing tracks inside the grid[x][y] * It means that X-channel [x][y] & [x+1][y] will no exist @@ -171,51 +173,52 @@ static size_t estimate_num_grid_rr_nodes_by_type(const DeviceGrid& grids, * * ***********************************************************************/ -static size_t estimate_num_chanx_rr_nodes(const DeviceGrid& grids, - const size_t& chan_width, - const std::vector& segment_infs, - const bool& through_channel) { - size_t num_chanx_rr_nodes = 0; - - for (size_t iy = 0; iy < grids.height() - 1; ++iy) { - for (size_t ix = 1; ix < grids.width() - 1; ++ix) { - vtr::Point chanx_coord(ix, iy); - - /* Bypass if the routing channel does not exist when through channels are not allowed */ - if ((false == through_channel) - && (false == is_chanx_exist(grids, chanx_coord))) { - continue; - } - - bool force_start = false; - bool force_end = false; - - /* All the tracks have to start when +static +size_t estimate_num_chanx_rr_nodes(const DeviceGrid& grids, + const size_t& chan_width, + const std::vector& segment_infs, + const bool& through_channel) { + size_t num_chanx_rr_nodes = 0; + + for (size_t iy = 0; iy < grids.height() - 1; ++iy) { + for (size_t ix = 1; ix < grids.width() - 1; ++ix) { + vtr::Point chanx_coord(ix, iy); + + /* Bypass if the routing channel does not exist when through channels are not allowed */ + if ( (false == through_channel) + && (false == is_chanx_exist(grids, chanx_coord))) { + continue; + } + + bool force_start = false; + bool force_end = false; + + /* All the tracks have to start when * - the routing channel touch the RIGHT side a heterogeneous block * - the routing channel touch the LEFT side of FPGA */ - if (true == is_chanx_right_to_multi_height_grid(grids, chanx_coord, through_channel)) { - force_start = true; - } + if (true == is_chanx_right_to_multi_height_grid(grids, chanx_coord, through_channel)) { + force_start = true; + } - /* All the tracks have to end when + /* All the tracks have to end when * - the routing channel touch the LEFT side a heterogeneous block * - the routing channel touch the RIGHT side of FPGA */ - if (true == is_chanx_left_to_multi_height_grid(grids, chanx_coord, through_channel)) { - force_end = true; - } - - /* Evaluate if the routing channel locates in the middle of a grid */ - ChanNodeDetails chanx_details = build_unidir_chan_node_details(chan_width, grids.width() - 2, force_start, force_end, segment_infs); - /* When an INC_DIRECTION CHANX starts, we need a new rr_node */ - num_chanx_rr_nodes += chanx_details.get_num_starting_tracks(Direction::INC); - /* When an DEC_DIRECTION CHANX ends, we need a new rr_node */ - num_chanx_rr_nodes += chanx_details.get_num_ending_tracks(Direction::DEC); - } + if (true == is_chanx_left_to_multi_height_grid(grids, chanx_coord, through_channel)) { + force_end = true; + } + + /* Evaluate if the routing channel locates in the middle of a grid */ + ChanNodeDetails chanx_details = build_unidir_chan_node_details(chan_width, grids.width() - 2, force_start, force_end, segment_infs); + /* When an INC_DIRECTION CHANX starts, we need a new rr_node */ + num_chanx_rr_nodes += chanx_details.get_num_starting_tracks(Direction::INC); + /* When an DEC_DIRECTION CHANX ends, we need a new rr_node */ + num_chanx_rr_nodes += chanx_details.get_num_ending_tracks(Direction::DEC); } + } - return num_chanx_rr_nodes; + return num_chanx_rr_nodes; } /************************************************************************ @@ -223,74 +226,78 @@ static size_t estimate_num_chanx_rr_nodes(const DeviceGrid& grids, * The technical rationale is very similar to the X-direction routing channel * Refer to the detailed explanation there ***********************************************************************/ -static size_t estimate_num_chany_rr_nodes(const DeviceGrid& grids, - const size_t& chan_width, - const std::vector& segment_infs, - const bool& through_channel) { - size_t num_chany_rr_nodes = 0; +static +size_t estimate_num_chany_rr_nodes(const DeviceGrid& grids, + const size_t& chan_width, + const std::vector& segment_infs, + const bool& through_channel) { + size_t num_chany_rr_nodes = 0; - for (size_t ix = 0; ix < grids.width() - 1; ++ix) { - for (size_t iy = 1; iy < grids.height() - 1; ++iy) { - vtr::Point chany_coord(ix, iy); + for (size_t ix = 0; ix < grids.width() - 1; ++ix) { + for (size_t iy = 1; iy < grids.height() - 1; ++iy) { + vtr::Point chany_coord(ix, iy); - /* Bypass if the routing channel does not exist when through channel are not allowed */ - if ((false == through_channel) - && (false == is_chany_exist(grids, chany_coord))) { - continue; - } + /* Bypass if the routing channel does not exist when through channel are not allowed */ + if ( (false == through_channel) + && (false == is_chany_exist(grids, chany_coord))) { + continue; + } - bool force_start = false; - bool force_end = false; - /* All the tracks have to start when + bool force_start = false; + bool force_end = false; + + /* All the tracks have to start when * - the routing channel touch the TOP side a heterogeneous block * - the routing channel touch the BOTTOM side of FPGA */ - if (true == is_chany_top_to_multi_width_grid(grids, chany_coord, through_channel)) { - force_start = true; - } + if (true == is_chany_top_to_multi_width_grid(grids, chany_coord, through_channel)) { + force_start = true; + } - /* All the tracks have to end when + /* All the tracks have to end when * - the routing channel touch the BOTTOM side a heterogeneous block * - the routing channel touch the TOP side of FPGA */ - if (true == is_chany_bottom_to_multi_width_grid(grids, chany_coord, through_channel)) { - force_end = true; - } - - ChanNodeDetails chany_details = build_unidir_chan_node_details(chan_width, grids.height() - 2, force_start, force_end, segment_infs); - /* When an INC_DIRECTION CHANX starts, we need a new rr_node */ - num_chany_rr_nodes += chany_details.get_num_starting_tracks(Direction::INC); - /* When an DEC_DIRECTION CHANX ends, we need a new rr_node */ - num_chany_rr_nodes += chany_details.get_num_ending_tracks(Direction::DEC); - } + if (true == is_chany_bottom_to_multi_width_grid(grids, chany_coord, through_channel)) { + force_end = true; + } + + ChanNodeDetails chany_details = build_unidir_chan_node_details(chan_width, grids.height() - 2, force_start, force_end, segment_infs); + /* When an INC_DIRECTION CHANX starts, we need a new rr_node */ + num_chany_rr_nodes += chany_details.get_num_starting_tracks(Direction::INC); + /* When an DEC_DIRECTION CHANX ends, we need a new rr_node */ + num_chany_rr_nodes += chany_details.get_num_ending_tracks(Direction::DEC); } + } - return num_chany_rr_nodes; + return num_chany_rr_nodes; } /************************************************************************ * Estimate the number of nodes by each type in a routing resource graph ***********************************************************************/ -static std::vector estimate_num_rr_nodes(const DeviceGrid& grids, - const vtr::Point& chan_width, - const std::vector& segment_infs, - const bool& through_channel) { - /* Reset the OPIN, IPIN, SOURCE, SINK counter to be zero */ - std::vector num_rr_nodes_per_type(NUM_RR_TYPES, 0); - - /** +static +std::vector estimate_num_rr_nodes(const DeviceGrid& grids, + const vtr::Point& chan_width, + const std::vector& segment_infs, + const bool& through_channel) { + + /* Reset the OPIN, IPIN, SOURCE, SINK counter to be zero */ + std::vector num_rr_nodes_per_type(NUM_RR_TYPES, 0); + + /** * 1 Find number of rr nodes related to grids */ - num_rr_nodes_per_type[OPIN] = estimate_num_grid_rr_nodes_by_type(grids, OPIN); - num_rr_nodes_per_type[IPIN] = estimate_num_grid_rr_nodes_by_type(grids, IPIN); - num_rr_nodes_per_type[SOURCE] = estimate_num_grid_rr_nodes_by_type(grids, SOURCE); - num_rr_nodes_per_type[SINK] = estimate_num_grid_rr_nodes_by_type(grids, SINK); + num_rr_nodes_per_type[OPIN] = estimate_num_grid_rr_nodes_by_type(grids, OPIN); + num_rr_nodes_per_type[IPIN] = estimate_num_grid_rr_nodes_by_type(grids, IPIN); + num_rr_nodes_per_type[SOURCE] = estimate_num_grid_rr_nodes_by_type(grids, SOURCE); + num_rr_nodes_per_type[SINK] = estimate_num_grid_rr_nodes_by_type(grids, SINK); - /** + /** * 2. Assign the segments for each routing channel, * To be specific, for each routing track, we assign a routing segment. - * The assignment is subject to users' specifications, such as + * The assignment is subject to users' specifications, such as * a. length of each type of segment * b. frequency of each type of segment. * c. routing channel width @@ -298,695 +305,713 @@ static std::vector estimate_num_rr_nodes(const DeviceGrid& grids, * SPECIAL for fringes: * All segments will start and ends with no exception * - * IMPORTANT: we should be aware that channel width maybe different + * IMPORTANT: we should be aware that channel width maybe different * in X-direction and Y-direction channels!!! - * So we will load segment details for different channels + * So we will load segment details for different channels */ - num_rr_nodes_per_type[CHANX] = estimate_num_chanx_rr_nodes(grids, - chan_width.x(), - segment_infs, - through_channel); - num_rr_nodes_per_type[CHANY] = estimate_num_chany_rr_nodes(grids, - chan_width.y(), - segment_infs, - through_channel); - - return num_rr_nodes_per_type; + num_rr_nodes_per_type[CHANX] = estimate_num_chanx_rr_nodes(grids, + chan_width.x(), + segment_infs, + through_channel); + num_rr_nodes_per_type[CHANY] = estimate_num_chany_rr_nodes(grids, + chan_width.y(), + segment_infs, + through_channel); + + return num_rr_nodes_per_type; } /************************************************************************ - * Allocate rr_nodes to a rr_graph object + * Allocate rr_nodes to a rr_graph object * This function just allocate the memory and ensure its efficiency * It will NOT fill detailed information for each node!!! * * Note: ensure that there are NO nodes in the rr_graph ***********************************************************************/ void alloc_tileable_rr_graph_nodes(RRGraphBuilder& rr_graph_builder, - vtr::vector& rr_node_driver_switches, + vtr::vector& rr_node_driver_switches, const DeviceGrid& grids, const vtr::Point& chan_width, const std::vector& segment_infs, const bool& through_channel) { - VTR_ASSERT(0 == rr_graph_builder.rr_nodes().size()); + VTR_ASSERT(0 == rr_graph_builder.rr_nodes().size()); - std::vector num_rr_nodes_per_type = estimate_num_rr_nodes(grids, - chan_width, - segment_infs, - through_channel); + std::vector num_rr_nodes_per_type = estimate_num_rr_nodes(grids, + chan_width, + segment_infs, + through_channel); - /* Reserve the number of node to be memory efficient */ - size_t num_nodes = 0; - for (const size_t& num_node_per_type : num_rr_nodes_per_type) { - num_nodes += num_node_per_type; - } + /* Reserve the number of node to be memory efficient */ + size_t num_nodes = 0; + for (const size_t& num_node_per_type : num_rr_nodes_per_type) { + num_nodes += num_node_per_type; + } - rr_graph_builder.reserve_nodes(num_nodes); + rr_graph_builder.reserve_nodes(num_nodes); - rr_node_driver_switches.reserve(num_nodes); + rr_node_driver_switches.reserve(num_nodes); } /************************************************************************ - * Configure OPIN rr_nodes for this grid - * coordinates: xlow, ylow, xhigh, yhigh, + * Configure OPIN rr_nodes for this grid + * coordinates: xlow, ylow, xhigh, yhigh, * features: capacity, ptc_num (pin_num), * * Note: this function should be applied ONLY to grid with 0 width offset and 0 height offset!!! ***********************************************************************/ -static void load_one_grid_opin_nodes_basic_info(RRGraphBuilder& rr_graph_builder, - vtr::vector& rr_node_driver_switches, - const vtr::Point& grid_coordinate, - const t_grid_tile& cur_grid, - const e_side& io_side, - const RRSwitchId& delayless_switch) { - SideManager io_side_manager(io_side); - - /* Walk through the width height of each grid, +static +void load_one_grid_opin_nodes_basic_info(RRGraphBuilder& rr_graph_builder, + vtr::vector& rr_node_driver_switches, + const vtr::Point& grid_coordinate, + const t_grid_tile& cur_grid, + const e_side& io_side, + const RRSwitchId& delayless_switch) { + SideManager io_side_manager(io_side); + + /* Walk through the width height of each grid, * get pins and configure the rr_nodes */ - for (int width = 0; width < cur_grid.type->width; ++width) { - for (int height = 0; height < cur_grid.type->height; ++height) { - /* Walk through sides */ - for (e_side side : SIDES) { - SideManager side_manager(side); - /* skip unwanted sides */ - if ((true == is_io_type(cur_grid.type)) - && (side != io_side_manager.to_size_t()) && (NUM_SIDES != io_side)) { - continue; - } - /* Find OPINs */ - /* Configure pins by pins */ - std::vector opin_list = get_grid_side_pins(cur_grid, DRIVER, side_manager.get_side(), - width, height); - for (const int& pin_num : opin_list) { - /* Create a new node and fill information */ - const RRNodeId& node = rr_graph_builder.node_lookup().find_node(width, height, OPIN, pin_num, side); - - /* node bounding box */ - rr_graph_builder.set_node_coordinates(node, grid_coordinate.x() + width, - grid_coordinate.y() + height, - grid_coordinate.x() + width, - grid_coordinate.y() + height); - rr_graph_builder.add_node_side(node, side_manager.get_side()); - rr_graph_builder.set_node_pin_num(node, pin_num); - - rr_graph_builder.set_node_capacity(node, 1); - - /* cost index is a FIXED value for OPIN */ - rr_graph_builder.set_node_cost_index(node, RRIndexedDataId(OPIN_COST_INDEX)); - - /* Switch info */ - VTR_ASSERT(size_t(node) == rr_node_driver_switches.size()); - rr_node_driver_switches.push_back(delayless_switch); - - /* RC data */ - rr_graph_builder.set_node_rc_index(node, NodeRCIndex(find_create_rr_rc_data(0., 0.))); - - } /* End of loading OPIN rr_nodes */ - } /* End of side enumeration */ - } /* End of height enumeration */ - } /* End of width enumeration */ + for (int width = 0; width < cur_grid.type->width; ++width) { + for (int height = 0; height < cur_grid.type->height; ++height) { + /* Walk through sides */ + for (e_side side : SIDES) { + SideManager side_manager(side); + /* skip unwanted sides */ + if ( (true == is_io_type(cur_grid.type)) + && (side != io_side_manager.to_size_t()) && (NUM_SIDES != io_side) ) { + continue; + } + /* Find OPINs */ + /* Configure pins by pins */ + std::vector opin_list = get_grid_side_pins(cur_grid, DRIVER, side_manager.get_side(), + width, height); + for (const int& pin_num : opin_list) { + /* Create a new node and fill information */ + const RRNodeId& node = rr_graph_builder.node_lookup().find_node(width, height, OPIN, pin_num, side); + + /* node bounding box */ + rr_graph_builder.set_node_coordinates(node, grid_coordinate.x() + width, + grid_coordinate.y() + height, + grid_coordinate.x() + width, + grid_coordinate.y() + height); + rr_graph_builder.add_node_side(node, side_manager.get_side()); + rr_graph_builder.set_node_pin_num(node, pin_num); + + rr_graph_builder.set_node_capacity(node, 1); + + /* cost index is a FIXED value for OPIN */ + rr_graph_builder.set_node_cost_index(node, RRIndexedDataId(OPIN_COST_INDEX)); + + /* Switch info */ + VTR_ASSERT(size_t(node) == rr_node_driver_switches.size()); + rr_node_driver_switches.push_back(delayless_switch); + + /* RC data */ + rr_graph_builder.set_node_rc_index(node, NodeRCIndex(find_create_rr_rc_data(0., 0.))); + + } /* End of loading OPIN rr_nodes */ + } /* End of side enumeration */ + } /* End of height enumeration */ + } /* End of width enumeration */ + } /************************************************************************ - * Configure IPIN rr_nodes for this grid - * coordinates: xlow, ylow, xhigh, yhigh, + * Configure IPIN rr_nodes for this grid + * coordinates: xlow, ylow, xhigh, yhigh, * features: capacity, ptc_num (pin_num), * * Note: this function should be applied ONLY to grid with 0 width offset and 0 height offset!!! ***********************************************************************/ -static void load_one_grid_ipin_nodes_basic_info(RRGraphBuilder& rr_graph_builder, - vtr::vector& rr_node_driver_switches, - const vtr::Point& grid_coordinate, - const t_grid_tile& cur_grid, - const e_side& io_side, - const RRSwitchId& wire_to_ipin_switch) { - SideManager io_side_manager(io_side); - - /* Walk through the width and height of each grid, +static +void load_one_grid_ipin_nodes_basic_info(RRGraphBuilder& rr_graph_builder, + vtr::vector& rr_node_driver_switches, + const vtr::Point& grid_coordinate, + const t_grid_tile& cur_grid, + const e_side& io_side, + const RRSwitchId& wire_to_ipin_switch) { + SideManager io_side_manager(io_side); + + /* Walk through the width and height of each grid, * get pins and configure the rr_nodes */ - for (int width = 0; width < cur_grid.type->width; ++width) { - for (int height = 0; height < cur_grid.type->height; ++height) { - /* Walk through sides */ - for (e_side side : SIDES) { - SideManager side_manager(side); - /* skip unwanted sides */ - if ((true == is_io_type(cur_grid.type)) - && (side != io_side_manager.to_size_t()) && (NUM_SIDES != io_side)) { - continue; - } - - /* Find IPINs */ - /* Configure pins by pins */ - std::vector ipin_list = get_grid_side_pins(cur_grid, RECEIVER, side_manager.get_side(), width, height); - for (const int& pin_num : ipin_list) { - /* Create a new node and fill information */ - const RRNodeId& node = rr_graph_builder.node_lookup().find_node(width, height, IPIN, pin_num, side); - - /* node bounding box */ - rr_graph_builder.set_node_coordinates(node, grid_coordinate.x() + width, - grid_coordinate.y() + height, - grid_coordinate.x() + width, - grid_coordinate.y() + height); - rr_graph_builder.add_node_side(node, side_manager.get_side()); - rr_graph_builder.set_node_pin_num(node, pin_num); - - rr_graph_builder.set_node_capacity(node, 1); - - /* cost index is a FIXED value for OPIN */ - rr_graph_builder.set_node_cost_index(node, RRIndexedDataId(IPIN_COST_INDEX)); - - /* Switch info */ - VTR_ASSERT(size_t(node) == rr_node_driver_switches.size()); - rr_node_driver_switches.push_back(wire_to_ipin_switch); - - /* RC data */ - rr_graph_builder.set_node_rc_index(node, NodeRCIndex(find_create_rr_rc_data(0., 0.))); - - } /* End of loading IPIN rr_nodes */ - } /* End of side enumeration */ - } /* End of height enumeration */ - } /* End of width enumeration */ + for (int width = 0; width < cur_grid.type->width; ++width) { + for (int height = 0; height < cur_grid.type->height; ++height) { + /* Walk through sides */ + for (e_side side : SIDES) { + SideManager side_manager(side); + /* skip unwanted sides */ + if ( (true == is_io_type(cur_grid.type)) + && (side != io_side_manager.to_size_t()) && (NUM_SIDES != io_side) ) { + continue; + } + + /* Find IPINs */ + /* Configure pins by pins */ + std::vector ipin_list = get_grid_side_pins(cur_grid, RECEIVER, side_manager.get_side(), width, height); + for (const int& pin_num : ipin_list) { + /* Create a new node and fill information */ + const RRNodeId& node = rr_graph_builder.node_lookup().find_node(width, height, IPIN, pin_num, side); + + /* node bounding box */ + rr_graph_builder.set_node_coordinates(node, grid_coordinate.x() + width, + grid_coordinate.y() + height, + grid_coordinate.x() + width, + grid_coordinate.y() + height); + rr_graph_builder.add_node_side(node, side_manager.get_side()); + rr_graph_builder.set_node_pin_num(node, pin_num); + + rr_graph_builder.set_node_capacity(node, 1); + + /* cost index is a FIXED value for OPIN */ + rr_graph_builder.set_node_cost_index(node, RRIndexedDataId(IPIN_COST_INDEX)); + + /* Switch info */ + VTR_ASSERT(size_t(node) == rr_node_driver_switches.size()); + rr_node_driver_switches.push_back(wire_to_ipin_switch); + + /* RC data */ + rr_graph_builder.set_node_rc_index(node, NodeRCIndex(find_create_rr_rc_data(0., 0.))); + + } /* End of loading IPIN rr_nodes */ + } /* End of side enumeration */ + } /* End of height enumeration */ + } /* End of width enumeration */ } /************************************************************************ - * Configure SOURCE rr_nodes for this grid - * coordinates: xlow, ylow, xhigh, yhigh, + * Configure SOURCE rr_nodes for this grid + * coordinates: xlow, ylow, xhigh, yhigh, * features: capacity, ptc_num (pin_num), * * Note: this function should be applied ONLY to grid with 0 width offset and 0 height offset!!! ***********************************************************************/ -static void load_one_grid_source_nodes_basic_info(RRGraphBuilder& rr_graph_builder, - vtr::vector& rr_node_driver_switches, - const vtr::Point& grid_coordinate, - const t_grid_tile& cur_grid, - const e_side& io_side, - const RRSwitchId& delayless_switch) { - SideManager io_side_manager(io_side); - - /* Set a SOURCE rr_node for each DRIVER class */ - for (int iclass = 0; iclass < cur_grid.type->num_class; ++iclass) { - /* Set a SINK rr_node for the OPIN */ - if (DRIVER != cur_grid.type->class_inf[iclass].type) { - continue; - } - - /* Create a new node and fill information */ - const RRNodeId& node = rr_graph_builder.node_lookup().find_node(grid_coordinate.x(), grid_coordinate.y(), SOURCE, iclass); - - /* node bounding box */ - rr_graph_builder.set_node_coordinates(node, grid_coordinate.x(), - grid_coordinate.y(), - grid_coordinate.x() + cur_grid.type->width - 1, - grid_coordinate.y() + cur_grid.type->height - 1); - rr_graph_builder.set_node_class_num(node, iclass); - - rr_graph_builder.set_node_capacity(node, 1); - - /* The capacity should be the number of pins in this class*/ - rr_graph_builder.set_node_capacity(node, cur_grid.type->class_inf[iclass].num_pins); - - /* cost index is a FIXED value for SOURCE */ - rr_graph_builder.set_node_cost_index(node, RRIndexedDataId(SOURCE_COST_INDEX)); - - /* Switch info */ - VTR_ASSERT(size_t(node) == rr_node_driver_switches.size()); - rr_node_driver_switches.push_back(delayless_switch); - - /* RC data */ - rr_graph_builder.set_node_rc_index(node, NodeRCIndex(find_create_rr_rc_data(0., 0.))); - - } /* End of class enumeration */ +static +void load_one_grid_source_nodes_basic_info(RRGraphBuilder& rr_graph_builder, + vtr::vector& rr_node_driver_switches, + const vtr::Point& grid_coordinate, + const t_grid_tile& cur_grid, + const e_side& io_side, + const RRSwitchId& delayless_switch) { + SideManager io_side_manager(io_side); + + /* Set a SOURCE rr_node for each DRIVER class */ + for (int iclass = 0; iclass < cur_grid.type->num_class; ++iclass) { + /* Set a SINK rr_node for the OPIN */ + if (DRIVER != cur_grid.type->class_inf[iclass].type) { + continue; + } + + /* Create a new node and fill information */ + const RRNodeId& node = rr_graph_builder.node_lookup().find_node(grid_coordinate.x(), grid_coordinate.y(), SOURCE, iclass); + + /* node bounding box */ + rr_graph_builder.set_node_coordinates(node, grid_coordinate.x(), + grid_coordinate.y(), + grid_coordinate.x() + cur_grid.type->width - 1, + grid_coordinate.y() + cur_grid.type->height - 1); + rr_graph_builder.set_node_class_num(node, iclass); + + rr_graph_builder.set_node_capacity(node, 1); + + /* The capacity should be the number of pins in this class*/ + rr_graph_builder.set_node_capacity(node, cur_grid.type->class_inf[iclass].num_pins); + + /* cost index is a FIXED value for SOURCE */ + rr_graph_builder.set_node_cost_index(node, RRIndexedDataId(SOURCE_COST_INDEX)); + + /* Switch info */ + VTR_ASSERT(size_t(node) == rr_node_driver_switches.size()); + rr_node_driver_switches.push_back(delayless_switch); + + /* RC data */ + rr_graph_builder.set_node_rc_index(node, NodeRCIndex(find_create_rr_rc_data(0., 0.))); + + } /* End of class enumeration */ } /************************************************************************ - * Configure SINK rr_nodes for this grid - * coordinates: xlow, ylow, xhigh, yhigh, + * Configure SINK rr_nodes for this grid + * coordinates: xlow, ylow, xhigh, yhigh, * features: capacity, ptc_num (pin_num), * * Note: this function should be applied ONLY to grid with 0 width offset and 0 height offset!!! ***********************************************************************/ -static void load_one_grid_sink_nodes_basic_info(RRGraphBuilder& rr_graph_builder, - vtr::vector& rr_node_driver_switches, - const vtr::Point& grid_coordinate, - const t_grid_tile& cur_grid, - const e_side& io_side, - const RRSwitchId& delayless_switch) { - SideManager io_side_manager(io_side); - - /* Set a SINK rr_node for each RECEIVER class */ - for (int iclass = 0; iclass < cur_grid.type->num_class; ++iclass) { - /* Set a SINK rr_node for the OPIN */ - if (RECEIVER != cur_grid.type->class_inf[iclass].type) { - continue; - } +static +void load_one_grid_sink_nodes_basic_info(RRGraphBuilder& rr_graph_builder, + vtr::vector& rr_node_driver_switches, + const vtr::Point& grid_coordinate, + const t_grid_tile& cur_grid, + const e_side& io_side, + const RRSwitchId& delayless_switch) { + SideManager io_side_manager(io_side); + + /* Set a SINK rr_node for each RECEIVER class */ + for (int iclass = 0; iclass < cur_grid.type->num_class; ++iclass) { + /* Set a SINK rr_node for the OPIN */ + if (RECEIVER != cur_grid.type->class_inf[iclass].type) { + continue; + } - /* Create a new node and fill information */ - const RRNodeId& node = rr_graph_builder.node_lookup().find_node(grid_coordinate.x(), grid_coordinate.y(), SINK, iclass); + /* Create a new node and fill information */ + const RRNodeId& node = rr_graph_builder.node_lookup().find_node(grid_coordinate.x(), grid_coordinate.y(), SINK, iclass); - /* node bounding box */ - rr_graph_builder.set_node_coordinates(node, grid_coordinate.x(), - grid_coordinate.y(), - grid_coordinate.x() + cur_grid.type->width - 1, - grid_coordinate.y() + cur_grid.type->height - 1); - rr_graph_builder.set_node_class_num(node, iclass); + /* node bounding box */ + rr_graph_builder.set_node_coordinates(node, grid_coordinate.x(), + grid_coordinate.y(), + grid_coordinate.x() + cur_grid.type->width - 1, + grid_coordinate.y() + cur_grid.type->height - 1); + rr_graph_builder.set_node_class_num(node, iclass); - rr_graph_builder.set_node_capacity(node, 1); + rr_graph_builder.set_node_capacity(node, 1); - /* The capacity should be the number of pins in this class*/ - rr_graph_builder.set_node_capacity(node, cur_grid.type->class_inf[iclass].num_pins); + /* The capacity should be the number of pins in this class*/ + rr_graph_builder.set_node_capacity(node, cur_grid.type->class_inf[iclass].num_pins); - /* cost index is a FIXED value for SINK */ - rr_graph_builder.set_node_cost_index(node, RRIndexedDataId(SINK_COST_INDEX)); + /* cost index is a FIXED value for SINK */ + rr_graph_builder.set_node_cost_index(node, RRIndexedDataId(SINK_COST_INDEX)); - /* Switch info */ - VTR_ASSERT(size_t(node) == rr_node_driver_switches.size()); - rr_node_driver_switches.push_back(delayless_switch); + /* Switch info */ + VTR_ASSERT(size_t(node) == rr_node_driver_switches.size()); + rr_node_driver_switches.push_back(delayless_switch); - /* RC data */ - rr_graph_builder.set_node_rc_index(node, NodeRCIndex(find_create_rr_rc_data(0., 0.))); + /* RC data */ + rr_graph_builder.set_node_rc_index(node, NodeRCIndex(find_create_rr_rc_data(0., 0.))); - } /* End of class enumeration */ + } /* End of class enumeration */ } /************************************************************************ * Create all the rr_nodes for grids ***********************************************************************/ -static void load_grid_nodes_basic_info(RRGraphBuilder& rr_graph_builder, - vtr::vector& rr_node_driver_switches, - const DeviceGrid& grids, - const RRSwitchId& wire_to_ipin_switch, - const RRSwitchId& delayless_switch) { - for (size_t iy = 0; iy < grids.height(); ++iy) { - for (size_t ix = 0; ix < grids.width(); ++ix) { - /* Skip EMPTY tiles */ - if (true == is_empty_type(grids[ix][iy].type)) { - continue; - } - - /* We only build rr_nodes for grids with width_offset = 0 and height_offset = 0 */ - if ((0 < grids[ix][iy].width_offset) - || (0 < grids[ix][iy].height_offset)) { - continue; - } - - vtr::Point grid_coordinate(ix, iy); - enum e_side io_side = NUM_SIDES; - - /* If this is the block on borders, we consider IO side */ - if (true == is_io_type(grids[ix][iy].type)) { - vtr::Point io_device_size(grids.width() - 1, grids.height() - 1); - io_side = determine_io_grid_pin_side(io_device_size, grid_coordinate); - } - - /* Configure source rr_nodes for this grid */ - load_one_grid_source_nodes_basic_info(rr_graph_builder, - rr_node_driver_switches, - grid_coordinate, - grids[ix][iy], - io_side, - delayless_switch); - - /* Configure sink rr_nodes for this grid */ - load_one_grid_sink_nodes_basic_info(rr_graph_builder, - rr_node_driver_switches, - grid_coordinate, - grids[ix][iy], - io_side, - delayless_switch); - - /* Configure opin rr_nodes for this grid */ - load_one_grid_opin_nodes_basic_info(rr_graph_builder, - rr_node_driver_switches, - grid_coordinate, - grids[ix][iy], - io_side, - delayless_switch); - - /* Configure ipin rr_nodes for this grid */ - load_one_grid_ipin_nodes_basic_info(rr_graph_builder, - rr_node_driver_switches, - grid_coordinate, - grids[ix][iy], - io_side, - wire_to_ipin_switch); - } +static +void load_grid_nodes_basic_info(RRGraphBuilder& rr_graph_builder, + vtr::vector& rr_node_driver_switches, + const DeviceGrid& grids, + const RRSwitchId& wire_to_ipin_switch, + const RRSwitchId& delayless_switch) { + + for (size_t iy = 0; iy < grids.height(); ++iy) { + for (size_t ix = 0; ix < grids.width(); ++ix) { + /* Skip EMPTY tiles */ + if (true == is_empty_type(grids[ix][iy].type)) { + continue; + } + + /* We only build rr_nodes for grids with width_offset = 0 and height_offset = 0 */ + if ( (0 < grids[ix][iy].width_offset) + || (0 < grids[ix][iy].height_offset) ) { + continue; + } + + vtr::Point grid_coordinate(ix, iy); + enum e_side io_side = NUM_SIDES; + + /* If this is the block on borders, we consider IO side */ + if (true == is_io_type(grids[ix][iy].type)) { + vtr::Point io_device_size(grids.width() - 1, grids.height() - 1); + io_side = determine_io_grid_pin_side(io_device_size, grid_coordinate); + } + + /* Configure source rr_nodes for this grid */ + load_one_grid_source_nodes_basic_info(rr_graph_builder, + rr_node_driver_switches, + grid_coordinate, + grids[ix][iy], + io_side, + delayless_switch); + + /* Configure sink rr_nodes for this grid */ + load_one_grid_sink_nodes_basic_info(rr_graph_builder, + rr_node_driver_switches, + grid_coordinate, + grids[ix][iy], + io_side, + delayless_switch); + + /* Configure opin rr_nodes for this grid */ + load_one_grid_opin_nodes_basic_info(rr_graph_builder, + rr_node_driver_switches, + grid_coordinate, + grids[ix][iy], + io_side, + delayless_switch); + + /* Configure ipin rr_nodes for this grid */ + load_one_grid_ipin_nodes_basic_info(rr_graph_builder, + rr_node_driver_switches, + grid_coordinate, + grids[ix][iy], + io_side, + wire_to_ipin_switch); + } + } } /************************************************************************ * Initialize the basic information of routing track rr_nodes - * coordinates: xlow, ylow, xhigh, yhigh, - * features: capacity, track_ids, ptc_num, direction + * coordinates: xlow, ylow, xhigh, yhigh, + * features: capacity, track_ids, ptc_num, direction ***********************************************************************/ -static void load_one_chan_rr_nodes_basic_info(RRGraphView& rr_graph, - RRGraphBuilder& rr_graph_builder, - vtr::vector& rr_node_driver_switches, - std::map>& rr_node_track_ids, - const vtr::Point& chan_coordinate, - const t_rr_type& chan_type, - ChanNodeDetails& chan_details, - const std::vector& segment_infs, - const int& cost_index_offset) { - /* Check each node_id(potential ptc_num) in the channel : +static +void load_one_chan_rr_nodes_basic_info(RRGraphView& rr_graph, + RRGraphBuilder& rr_graph_builder, + vtr::vector& rr_node_driver_switches, + std::map>& rr_node_track_ids, + const vtr::Point& chan_coordinate, + const t_rr_type& chan_type, + ChanNodeDetails& chan_details, + const std::vector& segment_infs, + const int& cost_index_offset) { + /* Check each node_id(potential ptc_num) in the channel : * If this is a starting point, we set a new rr_node with xlow/ylow, ptc_num * If this is a ending point, we set xhigh/yhigh and track_ids * For other nodes, we set changes in track_ids */ - for (size_t itrack = 0; itrack < chan_details.get_chan_width(); ++itrack) { - /* For INC direction, a starting point requires a new chan rr_node */ - if (((true == chan_details.is_track_start(itrack)) - && (Direction::INC == chan_details.get_track_direction(itrack))) - /* For DEC direction, an ending point requires a new chan rr_node */ - || ((true == chan_details.is_track_end(itrack)) - && (Direction::DEC == chan_details.get_track_direction(itrack)))) { - /* Create a new chan rr_node */ - const RRNodeId& node = rr_graph_builder.node_lookup().find_node(chan_coordinate.x(), chan_coordinate.y(), chan_type, itrack); - - rr_graph_builder.set_node_direction(node, chan_details.get_track_direction(itrack)); - rr_graph_builder.set_node_track_num(node, itrack); - rr_node_track_ids[node].push_back(itrack); - - rr_graph_builder.set_node_capacity(node, 1); - - /* assign switch id */ - size_t seg_id = chan_details.get_track_segment_id(itrack); - VTR_ASSERT(size_t(node) == rr_node_driver_switches.size()); - rr_node_driver_switches.push_back(RRSwitchId(segment_infs[seg_id].arch_opin_switch)); - - /* Update chan_details with node_id */ - chan_details.set_track_node_id(itrack, size_t(node)); - - /* cost index depends on the segment index */ - rr_graph_builder.set_node_cost_index(node, RRIndexedDataId(cost_index_offset + seg_id)); - /* Finish here, go to next */ - } + for (size_t itrack = 0; itrack < chan_details.get_chan_width(); ++itrack) { + /* For INC direction, a starting point requires a new chan rr_node */ + if ( ( (true == chan_details.is_track_start(itrack)) + && (Direction::INC == chan_details.get_track_direction(itrack)) ) + /* For DEC direction, an ending point requires a new chan rr_node */ + || + ( (true == chan_details.is_track_end(itrack)) + && (Direction::DEC == chan_details.get_track_direction(itrack)) ) ) { + + /* Create a new chan rr_node */ + const RRNodeId& node = rr_graph_builder.node_lookup().find_node(chan_coordinate.x(), chan_coordinate.y(), chan_type, itrack); + + rr_graph_builder.set_node_direction(node, chan_details.get_track_direction(itrack)); + rr_graph_builder.set_node_track_num(node, itrack); + rr_node_track_ids[node].push_back(itrack); + + rr_graph_builder.set_node_capacity(node, 1); + + /* assign switch id */ + size_t seg_id = chan_details.get_track_segment_id(itrack); + VTR_ASSERT(size_t(node) == rr_node_driver_switches.size()); + rr_node_driver_switches.push_back(RRSwitchId(segment_infs[seg_id].arch_opin_switch)); + + /* Update chan_details with node_id */ + chan_details.set_track_node_id(itrack, size_t(node)); + + /* cost index depends on the segment index */ + rr_graph_builder.set_node_cost_index(node, RRIndexedDataId(cost_index_offset + seg_id)); + /* Finish here, go to next */ + } - /* For INC direction, an ending point requires an update on xhigh and yhigh */ - if (((true == chan_details.is_track_end(itrack)) - && (Direction::INC == chan_details.get_track_direction(itrack))) - || - /* For DEC direction, an starting point requires an update on xlow and ylow */ - ((true == chan_details.is_track_start(itrack)) - && (Direction::DEC == chan_details.get_track_direction(itrack)))) { - /* Get the node_id */ - const RRNodeId& rr_node_id = RRNodeId(chan_details.get_track_node_id(itrack)); - - /* Do a quick check, make sure we do not mistakenly modify other nodes */ - VTR_ASSERT(chan_type == rr_graph.node_type(rr_node_id)); - VTR_ASSERT(chan_details.get_track_direction(itrack) == rr_graph.node_direction(rr_node_id)); - - /* set xhigh/yhigh and push changes to track_ids */ - rr_graph_builder.set_node_coordinates(rr_node_id, rr_graph.node_xlow(rr_node_id), - rr_graph.node_ylow(rr_node_id), - chan_coordinate.x(), - chan_coordinate.y()); - - /* Do not update track_ids for length-1 wires, they should have only 1 track_id */ - if ((rr_graph.node_xhigh(rr_node_id) > rr_graph.node_xlow(rr_node_id)) - || (rr_graph.node_yhigh(rr_node_id) > rr_graph.node_ylow(rr_node_id))) { - rr_node_track_ids[rr_node_id].push_back(itrack); - rr_graph_builder.set_node_track_num(rr_node_id, itrack); - } - /* Finish here, go to next */ - } + /* For INC direction, an ending point requires an update on xhigh and yhigh */ + if ( ( (true == chan_details.is_track_end(itrack)) + && (Direction::INC == chan_details.get_track_direction(itrack)) ) + || + /* For DEC direction, an starting point requires an update on xlow and ylow */ + ( (true == chan_details.is_track_start(itrack)) + && (Direction::DEC == chan_details.get_track_direction(itrack)) ) ) { + + /* Get the node_id */ + const RRNodeId& rr_node_id = RRNodeId(chan_details.get_track_node_id(itrack)); + + /* Do a quick check, make sure we do not mistakenly modify other nodes */ + VTR_ASSERT(chan_type == rr_graph.node_type(rr_node_id)); + VTR_ASSERT(chan_details.get_track_direction(itrack) == rr_graph.node_direction(rr_node_id)); + + /* set xhigh/yhigh and push changes to track_ids */ + rr_graph_builder.set_node_coordinates(rr_node_id, rr_graph.node_xlow(rr_node_id), + rr_graph.node_ylow(rr_node_id), + chan_coordinate.x(), + chan_coordinate.y()); + + /* Do not update track_ids for length-1 wires, they should have only 1 track_id */ + if ( (rr_graph.node_xhigh(rr_node_id) > rr_graph.node_xlow(rr_node_id)) + || (rr_graph.node_yhigh(rr_node_id) > rr_graph.node_ylow(rr_node_id)) ) { + rr_node_track_ids[rr_node_id].push_back(itrack); + rr_graph_builder.set_node_track_num(rr_node_id, itrack); + } + /* Finish here, go to next */ + } - /* Finish processing starting and ending tracks */ - if ((true == chan_details.is_track_start(itrack)) - || (true == chan_details.is_track_end(itrack))) { - /* Finish here, go to next */ - continue; - } + /* Finish processing starting and ending tracks */ + if ( (true == chan_details.is_track_start(itrack)) + || (true == chan_details.is_track_end(itrack)) ) { + /* Finish here, go to next */ + continue; + } - /* For other nodes, we get the node_id and just update track_ids */ - /* Ensure those nodes are neither starting nor ending points */ - VTR_ASSERT((false == chan_details.is_track_start(itrack)) - && (false == chan_details.is_track_end(itrack))); + /* For other nodes, we get the node_id and just update track_ids */ + /* Ensure those nodes are neither starting nor ending points */ + VTR_ASSERT( (false == chan_details.is_track_start(itrack)) + && (false == chan_details.is_track_end(itrack)) ); - /* Get the node_id */ - const RRNodeId& rr_node_id = RRNodeId(chan_details.get_track_node_id(itrack)); + /* Get the node_id */ + const RRNodeId& rr_node_id = RRNodeId(chan_details.get_track_node_id(itrack)); - /* Do a quick check, make sure we do not mistakenly modify other nodes */ - VTR_ASSERT(chan_type == rr_graph.node_type(rr_node_id)); - VTR_ASSERT(chan_details.get_track_direction(itrack) == rr_graph.node_direction(rr_node_id)); + /* Do a quick check, make sure we do not mistakenly modify other nodes */ + VTR_ASSERT(chan_type == rr_graph.node_type(rr_node_id)); + VTR_ASSERT(chan_details.get_track_direction(itrack) == rr_graph.node_direction(rr_node_id)); - /* Deposit xhigh and yhigh using the current chan_coordinate + /* Deposit xhigh and yhigh using the current chan_coordinate * We will update when this track ends */ - rr_graph_builder.set_node_coordinates(rr_node_id, rr_graph.node_xlow(rr_node_id), - rr_graph.node_ylow(rr_node_id), - chan_coordinate.x(), - chan_coordinate.y()); - - /* Update track_ids */ - rr_node_track_ids[rr_node_id].push_back(itrack); - rr_graph_builder.set_node_track_num(rr_node_id, itrack); - /* Finish here, go to next */ - } -} + rr_graph_builder.set_node_coordinates(rr_node_id, rr_graph.node_xlow(rr_node_id), + rr_graph.node_ylow(rr_node_id), + chan_coordinate.x(), + chan_coordinate.y()); + + /* Update track_ids */ + rr_node_track_ids[rr_node_id].push_back(itrack); + rr_graph_builder.set_node_track_num(rr_node_id, itrack); + /* Finish here, go to next */ + } +} /************************************************************************ * Initialize the basic information of X-channel rr_nodes: - * coordinates: xlow, ylow, xhigh, yhigh, - * features: capacity, track_ids, ptc_num, direction + * coordinates: xlow, ylow, xhigh, yhigh, + * features: capacity, track_ids, ptc_num, direction * grid_info : pb_graph_pin ***********************************************************************/ -static void load_chanx_rr_nodes_basic_info(RRGraphView& rr_graph, - RRGraphBuilder& rr_graph_builder, - vtr::vector& rr_node_driver_switches, - std::map>& rr_node_track_ids, - const DeviceGrid& grids, - const size_t& chan_width, - const std::vector& segment_infs, - const bool& through_channel) { - /* For X-direction Channel: CHANX */ - for (size_t iy = 0; iy < grids.height() - 1; ++iy) { - /* Keep a vector of node_ids for the channels, because we will rotate them when walking through ix */ - std::vector track_node_ids; - - for (size_t ix = 1; ix < grids.width() - 1; ++ix) { - vtr::Point chanx_coord(ix, iy); - - /* Bypass if the routing channel does not exist when through channels are not allowed */ - if ((false == through_channel) - && (false == is_chanx_exist(grids, chanx_coord))) { - continue; - } - - bool force_start = false; - bool force_end = false; - - /* All the tracks have to start when +static +void load_chanx_rr_nodes_basic_info(RRGraphView& rr_graph, + RRGraphBuilder& rr_graph_builder, + vtr::vector& rr_node_driver_switches, + std::map>& rr_node_track_ids, + const DeviceGrid& grids, + const size_t& chan_width, + const std::vector& segment_infs, + const bool& through_channel) { + + /* For X-direction Channel: CHANX */ + for (size_t iy = 0; iy < grids.height() - 1; ++iy) { + /* Keep a vector of node_ids for the channels, because we will rotate them when walking through ix */ + std::vector track_node_ids; + + for (size_t ix = 1; ix < grids.width() - 1; ++ix) { + vtr::Point chanx_coord(ix, iy); + + /* Bypass if the routing channel does not exist when through channels are not allowed */ + if ( (false == through_channel) + && (false == is_chanx_exist(grids, chanx_coord))) { + continue; + } + + bool force_start = false; + bool force_end = false; + + /* All the tracks have to start when * - the routing channel touch the RIGHT side a heterogeneous block * - the routing channel touch the LEFT side of FPGA */ - if (true == is_chanx_right_to_multi_height_grid(grids, chanx_coord, through_channel)) { - force_start = true; - } + if (true == is_chanx_right_to_multi_height_grid(grids, chanx_coord, through_channel)) { + force_start = true; + } - /* All the tracks have to end when + /* All the tracks have to end when * - the routing channel touch the LEFT side a heterogeneous block * - the routing channel touch the RIGHT side of FPGA */ - if (true == is_chanx_left_to_multi_height_grid(grids, chanx_coord, through_channel)) { - force_end = true; - } - - ChanNodeDetails chanx_details = build_unidir_chan_node_details(chan_width, grids.width() - 2, - force_start, force_end, segment_infs); - /* Force node_ids from the previous chanx */ - if (0 < track_node_ids.size()) { - /* Rotate should be done based on a typical case of routing tracks. - * Tracks on the borders are not regularly started and ended, - * which causes the node_rotation malfunction + if (true == is_chanx_left_to_multi_height_grid(grids, chanx_coord, through_channel)) { + force_end = true; + } + + ChanNodeDetails chanx_details = build_unidir_chan_node_details(chan_width, grids.width() - 2, + force_start, force_end, segment_infs); + /* Force node_ids from the previous chanx */ + if (0 < track_node_ids.size()) { + /* Rotate should be done based on a typical case of routing tracks. + * Tracks on the borders are not regularly started and ended, + * which causes the node_rotation malfunction */ - ChanNodeDetails chanx_details_tt = build_unidir_chan_node_details(chan_width, grids.width() - 2, - false, false, segment_infs); - chanx_details_tt.set_track_node_ids(track_node_ids); + ChanNodeDetails chanx_details_tt = build_unidir_chan_node_details(chan_width, grids.width() - 2, + false, false, segment_infs); + chanx_details_tt.set_track_node_ids(track_node_ids); - /* TODO: - * Do NOT rotate the tracks when the routing channel + /* TODO: + * Do NOT rotate the tracks when the routing channel * locates inside a multi-height and multi-width grid - * Let the routing channel passing through the grid (if through channel is allowed!) + * Let the routing channel passing through the grid (if through channel is allowed!) * An example: - * + * * +------------------------------ * | | * | Grid | * track0 ----->+-----------------------------+----> track0 * | | */ - if (true == is_chanx_exist(grids, chanx_coord, through_channel)) { - /* Rotate the chanx_details by an offset of ix - 1, the distance to the most left channel */ - /* For INC_DIRECTION, we use clockwise rotation + if (true == is_chanx_exist(grids, chanx_coord, through_channel)) { + /* Rotate the chanx_details by an offset of ix - 1, the distance to the most left channel */ + /* For INC_DIRECTION, we use clockwise rotation * node_id A ----> -----> node_id D * node_id B ----> / ----> node_id A * node_id C ----> / ----> node_id B - * node_id D ----> ----> node_id C + * node_id D ----> ----> node_id C */ - chanx_details_tt.rotate_track_node_id(1, Direction::INC, true); - /* For DEC_DIRECTION, we use clockwise rotation + chanx_details_tt.rotate_track_node_id(1, Direction::INC, true); + /* For DEC_DIRECTION, we use clockwise rotation * node_id A <----- <----- node_id B * node_id B <----- \ <----- node_id C * node_id C <----- \ <----- node_id D - * node_id D <----- <----- node_id A + * node_id D <----- <----- node_id A */ - chanx_details_tt.rotate_track_node_id(1, Direction::DEC, false); - } - - track_node_ids = chanx_details_tt.get_track_node_ids(); - chanx_details.set_track_node_ids(track_node_ids); - } - - /* Configure CHANX in this channel */ - load_one_chan_rr_nodes_basic_info(rr_graph, - rr_graph_builder, - rr_node_driver_switches, - rr_node_track_ids, - chanx_coord, CHANX, - chanx_details, - segment_infs, - CHANX_COST_INDEX_START); - /* Get a copy of node_ids */ - track_node_ids = chanx_details.get_track_node_ids(); - } + chanx_details_tt.rotate_track_node_id(1, Direction::DEC, false); + } + + track_node_ids = chanx_details_tt.get_track_node_ids(); + chanx_details.set_track_node_ids(track_node_ids); + } + + /* Configure CHANX in this channel */ + load_one_chan_rr_nodes_basic_info(rr_graph, + rr_graph_builder, + rr_node_driver_switches, + rr_node_track_ids, + chanx_coord, CHANX, + chanx_details, + segment_infs, + CHANX_COST_INDEX_START); + /* Get a copy of node_ids */ + track_node_ids = chanx_details.get_track_node_ids(); } + } } /************************************************************************ * Initialize the basic information of Y-channel rr_nodes: - * coordinates: xlow, ylow, xhigh, yhigh, - * features: capacity, track_ids, ptc_num, direction + * coordinates: xlow, ylow, xhigh, yhigh, + * features: capacity, track_ids, ptc_num, direction ***********************************************************************/ -static void load_chany_rr_nodes_basic_info(RRGraphView& rr_graph, - RRGraphBuilder& rr_graph_builder, - vtr::vector& rr_node_driver_switches, - std::map>& rr_node_track_ids, - const DeviceGrid& grids, - const size_t& chan_width, - const std::vector& segment_infs, - const bool& through_channel) { - /* For Y-direction Channel: CHANY */ - for (size_t ix = 0; ix < grids.width() - 1; ++ix) { - /* Keep a vector of node_ids for the channels, because we will rotate them when walking through ix */ - std::vector track_node_ids; - - for (size_t iy = 1; iy < grids.height() - 1; ++iy) { - vtr::Point chany_coord(ix, iy); - - /* Bypass if the routing channel does not exist when through channel are not allowed */ - if ((false == through_channel) - && (false == is_chany_exist(grids, chany_coord))) { - continue; - } - - bool force_start = false; - bool force_end = false; - - /* All the tracks have to start when +static +void load_chany_rr_nodes_basic_info(RRGraphView& rr_graph, + RRGraphBuilder& rr_graph_builder, + vtr::vector& rr_node_driver_switches, + std::map>& rr_node_track_ids, + const DeviceGrid& grids, + const size_t& chan_width, + const std::vector& segment_infs, + const bool& through_channel) { + + /* For Y-direction Channel: CHANY */ + for (size_t ix = 0; ix < grids.width() - 1; ++ix) { + /* Keep a vector of node_ids for the channels, because we will rotate them when walking through ix */ + std::vector track_node_ids; + + for (size_t iy = 1; iy < grids.height() - 1; ++iy) { + vtr::Point chany_coord(ix, iy); + + /* Bypass if the routing channel does not exist when through channel are not allowed */ + if ( (false == through_channel) + && (false == is_chany_exist(grids, chany_coord))) { + continue; + } + + bool force_start = false; + bool force_end = false; + + /* All the tracks have to start when * - the routing channel touch the TOP side a heterogeneous block * - the routing channel touch the BOTTOM side of FPGA */ - if (true == is_chany_top_to_multi_width_grid(grids, chany_coord, through_channel)) { - force_start = true; - } + if (true == is_chany_top_to_multi_width_grid(grids, chany_coord, through_channel)) { + force_start = true; + } - /* All the tracks have to end when + /* All the tracks have to end when * - the routing channel touch the BOTTOM side a heterogeneous block * - the routing channel touch the TOP side of FPGA */ - if (true == is_chany_bottom_to_multi_width_grid(grids, chany_coord, through_channel)) { - force_end = true; - } + if (true == is_chany_bottom_to_multi_width_grid(grids, chany_coord, through_channel)) { + force_end = true; + } - ChanNodeDetails chany_details = build_unidir_chan_node_details(chan_width, grids.height() - 2, - force_start, force_end, segment_infs); - /* Force node_ids from the previous chany + ChanNodeDetails chany_details = build_unidir_chan_node_details(chan_width, grids.height() - 2, + force_start, force_end, segment_infs); + /* Force node_ids from the previous chany * This will not be applied when the routing channel is cut off (force to start) */ - if (0 < track_node_ids.size()) { - /* Rotate should be done based on a typical case of routing tracks. - * Tracks on the borders are not regularly started and ended, - * which causes the node_rotation malfunction + if (0 < track_node_ids.size()) { + /* Rotate should be done based on a typical case of routing tracks. + * Tracks on the borders are not regularly started and ended, + * which causes the node_rotation malfunction */ - ChanNodeDetails chany_details_tt = build_unidir_chan_node_details(chan_width, grids.height() - 2, - false, false, segment_infs); + ChanNodeDetails chany_details_tt = build_unidir_chan_node_details(chan_width, grids.height() - 2, + false, false, segment_infs); - chany_details_tt.set_track_node_ids(track_node_ids); + chany_details_tt.set_track_node_ids(track_node_ids); - /* TODO: - * Do NOT rotate the tracks when the routing channel + /* TODO: + * Do NOT rotate the tracks when the routing channel * locates inside a multi-height and multi-width grid - * Let the routing channel passing through the grid (if through channel is allowed!) + * Let the routing channel passing through the grid (if through channel is allowed!) * An example: - * + * * +------------------------------ * | | * | Grid | * track0 ----->+-----------------------------+----> track0 * | | - * we should rotate only once at the bottom side of a grid + * we should rotate only once at the bottom side of a grid */ - if (true == is_chany_exist(grids, chany_coord, through_channel)) { - /* Rotate the chany_details by an offset of 1*/ - /* For INC_DIRECTION, we use clockwise rotation + if (true == is_chany_exist(grids, chany_coord, through_channel)) { + /* Rotate the chany_details by an offset of 1*/ + /* For INC_DIRECTION, we use clockwise rotation * node_id A ----> -----> node_id D * node_id B ----> / ----> node_id A * node_id C ----> / ----> node_id B - * node_id D ----> ----> node_id C + * node_id D ----> ----> node_id C */ - chany_details_tt.rotate_track_node_id(1, Direction::INC, true); - /* For DEC_DIRECTION, we use clockwise rotation + chany_details_tt.rotate_track_node_id(1, Direction::INC, true); + /* For DEC_DIRECTION, we use clockwise rotation * node_id A <----- <----- node_id B * node_id B <----- \ <----- node_id C * node_id C <----- \ <----- node_id D - * node_id D <----- <----- node_id A + * node_id D <----- <----- node_id A */ - chany_details_tt.rotate_track_node_id(1, Direction::DEC, false); - } - - track_node_ids = chany_details_tt.get_track_node_ids(); - chany_details.set_track_node_ids(track_node_ids); - } - /* Configure CHANX in this channel */ - load_one_chan_rr_nodes_basic_info(rr_graph, - rr_graph_builder, - rr_node_driver_switches, - rr_node_track_ids, - chany_coord, CHANY, - chany_details, - segment_infs, - CHANX_COST_INDEX_START + segment_infs.size()); - /* Get a copy of node_ids */ - track_node_ids = chany_details.get_track_node_ids(); + chany_details_tt.rotate_track_node_id(1, Direction::DEC, false); } + + track_node_ids = chany_details_tt.get_track_node_ids(); + chany_details.set_track_node_ids(track_node_ids); + } + /* Configure CHANX in this channel */ + load_one_chan_rr_nodes_basic_info(rr_graph, + rr_graph_builder, + rr_node_driver_switches, + rr_node_track_ids, + chany_coord, CHANY, + chany_details, + segment_infs, + CHANX_COST_INDEX_START + segment_infs.size()); + /* Get a copy of node_ids */ + track_node_ids = chany_details.get_track_node_ids(); } + } } /************************************************************************ * Reverse the track_ids of CHANX and CHANY nodes in DEC_DIRECTION * This is required as the track ids are allocated in the sequence * of incrementing x and y - * However, DEC direction routing tracks should have a reversed sequence in - * track ids + * However, DEC direction routing tracks should have a reversed sequence in + * track ids ***********************************************************************/ -static void reverse_dec_chan_rr_node_track_ids(const RRGraphView& rr_graph, - std::map>& rr_node_track_ids) { - // this should call rr_graph_view to do the job - - for (auto& node : rr_graph.nodes()) { - /* Bypass condition: only focus on CHANX and CHANY in DEC_DIRECTION */ - if ((CHANX != rr_graph.node_type(node)) - && (CHANY != rr_graph.node_type(node))) { - continue; - } - /* Reach here, we must have a node of CHANX or CHANY */ - if (Direction::DEC != rr_graph.node_direction(node)) { - continue; - } - std::reverse(rr_node_track_ids[node].begin(), - rr_node_track_ids[node].end()); +static +void reverse_dec_chan_rr_node_track_ids(const RRGraphBuilder& rr_graph_builder, + std::map>& rr_node_track_ids) { +#if 0 + // this should call rr_graph_builder to do the job + for (const RRNodeId& node : rr_graph_builder.nodes()) { + /* Bypass condition: only focus on CHANX and CHANY in DEC_DIRECTION */ + if ( (CHANX != rr_graph_builder.node_type(node)) + && (CHANY != rr_graph_builder.node_type(node)) ) { + continue; + } + /* Reach here, we must have a node of CHANX or CHANY */ + if (Direction::DEC != rr_graph_builder.node_direction(node)) { + continue; } + std::reverse(rr_node_track_ids[node].begin(), + rr_node_track_ids[node].end() ); + } +#endif } /************************************************************************ @@ -994,38 +1019,39 @@ static void reverse_dec_chan_rr_node_track_ids(const RRGraphView& rr_graph, ***********************************************************************/ void create_tileable_rr_graph_nodes(RRGraphView& rr_graph, RRGraphBuilder& rr_graph_builder, - vtr::vector& rr_node_driver_switches, + vtr::vector& rr_node_driver_switches, std::map>& rr_node_track_ids, - const DeviceGrid& grids, - const vtr::Point& chan_width, + const DeviceGrid& grids, + const vtr::Point& chan_width, const std::vector& segment_infs, const RRSwitchId& wire_to_ipin_switch, const RRSwitchId& delayless_switch, const bool& through_channel) { - load_grid_nodes_basic_info(rr_graph_builder, - rr_node_driver_switches, - grids, - wire_to_ipin_switch, - delayless_switch); - - load_chanx_rr_nodes_basic_info(rr_graph, - rr_graph_builder, - rr_node_driver_switches, - rr_node_track_ids, - grids, - chan_width.x(), - segment_infs, - through_channel); - - load_chany_rr_nodes_basic_info(rr_graph, - rr_graph_builder, - rr_node_driver_switches, - rr_node_track_ids, - grids, - chan_width.y(), - segment_infs, - through_channel); - - reverse_dec_chan_rr_node_track_ids(rr_graph, - rr_node_track_ids); + load_grid_nodes_basic_info(rr_graph_builder, + rr_node_driver_switches, + grids, + wire_to_ipin_switch, + delayless_switch); + + load_chanx_rr_nodes_basic_info(rr_graph, + rr_graph_builder, + rr_node_driver_switches, + rr_node_track_ids, + grids, + chan_width.x(), + segment_infs, + through_channel); + + load_chany_rr_nodes_basic_info(rr_graph, + rr_graph_builder, + rr_node_driver_switches, + rr_node_track_ids, + grids, + chan_width.y(), + segment_infs, + through_channel); + + reverse_dec_chan_rr_node_track_ids(rr_graph_builder, + rr_node_track_ids); + } diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.h b/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.h index c555c19a178..8317c10169b 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.h +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.h @@ -1,5 +1,6 @@ #ifndef TILEABLE_RR_GRAPH_NODE_BUILDER_H #define TILEABLE_RR_GRAPH_NODE_BUILDER_H + /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ @@ -20,7 +21,7 @@ *******************************************************************/ void alloc_tileable_rr_graph_nodes(RRGraphBuilder& rr_graph_builder, - vtr::vector& driver_switches, + vtr::vector& driver_switches, const DeviceGrid& grids, const vtr::Point& chan_width, const std::vector& segment_infs, @@ -28,14 +29,15 @@ void alloc_tileable_rr_graph_nodes(RRGraphBuilder& rr_graph_builder, void create_tileable_rr_graph_nodes(RRGraphView& rr_graph, RRGraphBuilder& rr_graph_builder, - vtr::vector& rr_node_driver_switches, + vtr::vector& rr_node_driver_switches, std::map>& rr_node_track_ids, - const DeviceGrid& grids, - const vtr::Point& chan_width, + const DeviceGrid& grids, + const vtr::Point& chan_width, const std::vector& segment_infs, const RRSwitchId& wire_to_ipin_switch, const RRSwitchId& delayless_switch, const bool& through_channel); -#endif + +#endif From 17626dd80e3cea905766b00a7c50ddf7509439ba Mon Sep 17 00:00:00 2001 From: taoli4rs Date: Tue, 2 Aug 2022 18:05:38 -0700 Subject: [PATCH 007/147] Code cleanup: fix warnings and format code by complying to vtr format. --- vpr/src/tileable_rr_graph/chan_node_details.h | 29 +- vpr/src/tileable_rr_graph/openfpga_port.cpp | 417 +++-- vpr/src/tileable_rr_graph/openfpga_port.h | 72 +- .../openfpga_rr_graph_utils.cpp | 25 +- .../openfpga_rr_graph_utils.h | 2 +- .../openfpga_side_manager.cpp | 227 ++- .../tileable_rr_graph/openfpga_side_manager.h | 5 +- vpr/src/tileable_rr_graph/rr_chan.h | 34 +- .../rr_graph_builder_utils.h | 21 +- .../tileable_rr_graph/rr_graph_obj_util.cpp | 30 +- vpr/src/tileable_rr_graph/rr_graph_obj_util.h | 1 - vpr/src/tileable_rr_graph/rr_graph_types.h | 1 - vpr/src/tileable_rr_graph/rr_gsb.cpp | 24 +- vpr/src/tileable_rr_graph/rr_gsb.h | 40 +- .../tileable_chan_details_builder.h | 12 +- .../tileable_rr_graph_builder.cpp | 12 +- .../tileable_rr_graph_builder.h | 14 +- .../tileable_rr_graph_edge_builder.cpp | 30 +- .../tileable_rr_graph_edge_builder.h | 13 +- .../tileable_rr_graph_gsb.cpp | 26 +- .../tileable_rr_graph/tileable_rr_graph_gsb.h | 1 - .../tileable_rr_graph_node_builder.cpp | 1405 ++++++++--------- .../tileable_rr_graph_node_builder.h | 10 +- 23 files changed, 1212 insertions(+), 1239 deletions(-) diff --git a/vpr/src/tileable_rr_graph/chan_node_details.h b/vpr/src/tileable_rr_graph/chan_node_details.h index 4b50d7b2405..e322b5c6d73 100644 --- a/vpr/src/tileable_rr_graph/chan_node_details.h +++ b/vpr/src/tileable_rr_graph/chan_node_details.h @@ -28,10 +28,10 @@ ***********************************************************************/ class ChanNodeDetails { - public : /* Constructor */ + public: /* Constructor */ ChanNodeDetails(const ChanNodeDetails&); /* Duplication */ - ChanNodeDetails(); /* Initilization */ - public: /* Accessors */ + ChanNodeDetails(); /* Initilization */ + public: /* Accessors */ size_t get_chan_width() const; size_t get_track_node_id(const size_t& track_id) const; std::vector get_track_node_ids() const; @@ -44,11 +44,10 @@ class ChanNodeDetails { std::vector get_seg_group_node_id(const std::vector& seg_group) const; size_t get_num_starting_tracks(const Direction& track_direction) const; size_t get_num_ending_tracks(const Direction& track_direction) const; - public: /* Mutators */ + + public: /* Mutators */ void reserve(const size_t& chan_width); /* Reserve the capacitcy of vectors */ - void add_track(const size_t& track_node_id, const Direction& track_direction, - const size_t& seg_id, const size_t& seg_length, - const size_t& is_start, const size_t& is_end); + void add_track(const size_t& track_node_id, const Direction& track_direction, const size_t& seg_id, const size_t& seg_length, const size_t& is_start, const size_t& is_end); void set_track_node_id(const size_t& track_index, const size_t& track_node_id); void set_track_node_ids(const std::vector& track_node_ids); void set_tracks_start(const Direction& track_direction); @@ -57,16 +56,18 @@ class ChanNodeDetails { const Direction& track_direction, const bool& counter_rotate); /* rotate the track_node_id by an offset */ void clear(); + private: /* validators */ bool validate_chan_width() const; bool validate_track_id(const size_t& track_id) const; - private: /* Internal data */ - std::vector track_node_ids_; /* indices of each track */ + + private: /* Internal data */ + std::vector track_node_ids_; /* indices of each track */ std::vector track_direction_; /* direction of each track */ - std::vector seg_ids_; /* id of segment of each track */ - std::vector seg_length_; /* Length of each segment */ - std::vector track_start_; /* flag to identify if this is the starting point of the track */ - std::vector track_end_; /* flag to identify if this is the ending point of the track */ + std::vector seg_ids_; /* id of segment of each track */ + std::vector seg_length_; /* Length of each segment */ + std::vector track_start_; /* flag to identify if this is the starting point of the track */ + std::vector track_end_; /* flag to identify if this is the ending point of the track */ }; -#endif +#endif diff --git a/vpr/src/tileable_rr_graph/openfpga_port.cpp b/vpr/src/tileable_rr_graph/openfpga_port.cpp index 7cfd03b20f5..3d4d59348f6 100644 --- a/vpr/src/tileable_rr_graph/openfpga_port.cpp +++ b/vpr/src/tileable_rr_graph/openfpga_port.cpp @@ -16,36 +16,36 @@ ***********************************************************************/ /* Default constructor */ BasicPort::BasicPort() { - /* By default we set an invalid port, which size is 0 */ - lsb_ = 1; - msb_ = 0; + /* By default we set an invalid port, which size is 0 */ + lsb_ = 1; + msb_ = 0; - origin_port_width_ = -1; + origin_port_width_ = -1; } /* Quick constructor */ BasicPort::BasicPort(const char* name, const size_t& lsb, const size_t& msb) { - set_name(std::string(name)); - set_width(lsb, msb); - set_origin_port_width(-1); + set_name(std::string(name)); + set_width(lsb, msb); + set_origin_port_width(-1); } BasicPort::BasicPort(const std::string& name, const size_t& lsb, const size_t& msb) { - set_name(name); - set_width(lsb, msb); - set_origin_port_width(-1); + set_name(name); + set_width(lsb, msb); + set_origin_port_width(-1); } BasicPort::BasicPort(const char* name, const size_t& width) { - set_name(std::string(name)); - set_width(width); - set_origin_port_width(-1); + set_name(std::string(name)); + set_width(width); + set_origin_port_width(-1); } BasicPort::BasicPort(const std::string& name, const size_t& width) { - set_name(name); - set_width(width); - set_origin_port_width(-1); + set_name(name); + set_width(width); + set_origin_port_width(-1); } /************************************************************************ @@ -53,62 +53,62 @@ BasicPort::BasicPort(const std::string& name, const size_t& width) { ***********************************************************************/ /* get the port width */ size_t BasicPort::get_width() const { - if (true == is_valid()) { - return msb_ - lsb_ + 1; - } - return 0; /* invalid port has a zero width */ + if (true == is_valid()) { + return msb_ - lsb_ + 1; + } + return 0; /* invalid port has a zero width */ } - + /* get the LSB */ size_t BasicPort::get_msb() const { - return msb_; + return msb_; } /* get the LSB */ size_t BasicPort::get_lsb() const { - return lsb_; + return lsb_; } /* get the name */ std::string BasicPort::get_name() const { - return name_; -} + return name_; +} /* Make a range of the pin indices */ std::vector BasicPort::pins() const { - std::vector pin_indices; + std::vector pin_indices; - /* Return if the port is invalid */ - if (false == is_valid()) { - return pin_indices; /* Return an empty vector */ - } - /* For valid ports, create a vector whose length is the port width */ - pin_indices.resize(get_width()); - /* Fill in an incremental sequence */ - std::iota(pin_indices.begin(), pin_indices.end(), get_lsb()); - /* Ensure the last one is MSB */ - VTR_ASSERT(get_msb() == pin_indices.back()); + /* Return if the port is invalid */ + if (false == is_valid()) { + return pin_indices; /* Return an empty vector */ + } + /* For valid ports, create a vector whose length is the port width */ + pin_indices.resize(get_width()); + /* Fill in an incremental sequence */ + std::iota(pin_indices.begin(), pin_indices.end(), get_lsb()); + /* Ensure the last one is MSB */ + VTR_ASSERT(get_msb() == pin_indices.back()); - return pin_indices; + return pin_indices; } /* Check if a port can be merged with this port: their name should be the same */ bool BasicPort::mergeable(const BasicPort& portA) const { - return (0 == this->get_name().compare(portA.get_name())); -} + return (0 == this->get_name().compare(portA.get_name())); +} /* Check if a port is contained by this port: * this function will check if the (LSB, MSB) of portA * is contained by the (LSB, MSB) of this port */ bool BasicPort::contained(const BasicPort& portA) const { - return ( lsb_ <= portA.get_lsb() && portA.get_msb() <= msb_ ); + return (lsb_ <= portA.get_lsb() && portA.get_msb() <= msb_); } /* Set original port width */ size_t BasicPort::get_origin_port_width() const { - return origin_port_width_; -} + return origin_port_width_; +} /************************************************************************ * Overloaded operators @@ -118,167 +118,166 @@ size_t BasicPort::get_origin_port_width() const { * 2. LSBs are the same * 3. MSBs are the same */ -bool BasicPort::operator== (const BasicPort& portA) const { - if ( (0 == this->get_name().compare(portA.get_name())) - && (this->get_lsb() == portA.get_lsb()) - && (this->get_msb() == portA.get_msb()) ) { - return true; - } - return false; +bool BasicPort::operator==(const BasicPort& portA) const { + if ((0 == this->get_name().compare(portA.get_name())) + && (this->get_lsb() == portA.get_lsb()) + && (this->get_msb() == portA.get_msb())) { + return true; + } + return false; } -bool BasicPort::operator< (const BasicPort& portA) const { - if ( (0 == this->get_name().compare(portA.get_name())) - && (this->get_lsb() < portA.get_lsb()) - && (this->get_msb() < portA.get_msb()) ) { - return true; - } - return false; +bool BasicPort::operator<(const BasicPort& portA) const { + if ((0 == this->get_name().compare(portA.get_name())) + && (this->get_lsb() < portA.get_lsb()) + && (this->get_msb() < portA.get_msb())) { + return true; + } + return false; } - /************************************************************************ * Mutators ***********************************************************************/ /* copy */ void BasicPort::set(const BasicPort& basic_port) { - name_ = basic_port.get_name(); - lsb_ = basic_port.get_lsb(); - msb_ = basic_port.get_msb(); - origin_port_width_ = basic_port.get_origin_port_width(); + name_ = basic_port.get_name(); + lsb_ = basic_port.get_lsb(); + msb_ = basic_port.get_msb(); + origin_port_width_ = basic_port.get_origin_port_width(); - return; + return; } /* set the port LSB and MSB */ -void BasicPort::set_name(const std::string& name) { - name_ = name; - return; +void BasicPort::set_name(const std::string& name) { + name_ = name; + return; } - + /* set the port LSB and MSB */ void BasicPort::set_width(const size_t& width) { - if (0 == width) { - make_invalid(); + if (0 == width) { + make_invalid(); + return; + } + lsb_ = 0; + msb_ = width - 1; return; - } - lsb_ = 0; - msb_ = width - 1; - return; } - + /* set the port LSB and MSB */ void BasicPort::set_width(const size_t& lsb, const size_t& msb) { - /* If lsb and msb is invalid, we make a default port */ - if (lsb > msb) { - make_invalid(); + /* If lsb and msb is invalid, we make a default port */ + if (lsb > msb) { + make_invalid(); + return; + } + set_lsb(lsb); + set_msb(msb); return; - } - set_lsb(lsb); - set_msb(msb); - return; } - + void BasicPort::set_lsb(const size_t& lsb) { - lsb_ = lsb; - return; + lsb_ = lsb; + return; } void BasicPort::set_msb(const size_t& msb) { - msb_ = msb; - return; + msb_ = msb; + return; } void BasicPort::set_origin_port_width(const size_t& origin_port_width) { - origin_port_width_ = origin_port_width; - return; + origin_port_width_ = origin_port_width; + return; } /* Increase the port width */ -void BasicPort::expand(const size_t& width) { - if (0 == width) { - return; /* ignore zero-width port */ - } - /* If current port is invalid, we do not combine */ - if (0 == get_width()) { - lsb_ = 0; - msb_ = width; +void BasicPort::expand(const size_t& width) { + if (0 == width) { + return; /* ignore zero-width port */ + } + /* If current port is invalid, we do not combine */ + if (0 == get_width()) { + lsb_ = 0; + msb_ = width; + return; + } + /* Increase MSB */ + msb_ += width; return; - } - /* Increase MSB */ - msb_ += width; - return; } /* Swap lsb and msb */ void BasicPort::revert() { - std::swap(lsb_, msb_); - return; + std::swap(lsb_, msb_); + return; } - + /* rotate: increase both lsb and msb by an offset */ bool BasicPort::rotate(const size_t& offset) { - /* If offset is 0, we do nothing */ - if (0 == offset) { - return true; - } - - /* If current width is 0, we set a width using the offset! */ - if (0 == get_width()) { - set_width(offset); - return true; - } - /* check if leads to overflow: + /* If offset is 0, we do nothing */ + if (0 == offset) { + return true; + } + + /* If current width is 0, we set a width using the offset! */ + if (0 == get_width()) { + set_width(offset); + return true; + } + /* check if leads to overflow: * if limits - msb is larger than offset */ - if ( (std::numeric_limits::max() - msb_ < offset) ) { - return false; - } - /* Increase LSB and MSB */ - lsb_ += offset; - msb_ += offset; - return true; + if ((std::numeric_limits::max() - msb_ < offset)) { + return false; + } + /* Increase LSB and MSB */ + lsb_ += offset; + msb_ += offset; + return true; } /* rotate: decrease both lsb and msb by an offset */ bool BasicPort::counter_rotate(const size_t& offset) { - /* If current port is invalid or offset is 0, + /* If current port is invalid or offset is 0, * we do nothing */ - if ((0 == offset) || (0 == get_width())) { - return true; - } - /* check if leads to overflow: + if ((0 == offset) || (0 == get_width())) { + return true; + } + /* check if leads to overflow: * if limits is larger than offset */ - if ( (std::numeric_limits::min() + lsb_ < offset) ) { - return false; - } - /* decrease LSB and MSB */ - lsb_ -= offset; - msb_ -= offset; - return true; + if ((std::numeric_limits::min() + lsb_ < offset)) { + return false; + } + /* decrease LSB and MSB */ + lsb_ -= offset; + msb_ -= offset; + return true; } - + /* Reset to initial port */ void BasicPort::reset() { - make_invalid(); - return; -} + make_invalid(); + return; +} /* Combine two ports */ void BasicPort::combine(const BasicPort& port) { - /* LSB follows the current LSB */ - /* MSB increases */ - VTR_ASSERT(0 < port.get_width() ); /* Make sure port is valid */ - /* If current port is invalid, we do not combine */ - if (0 == get_width()) { + /* LSB follows the current LSB */ + /* MSB increases */ + VTR_ASSERT(0 < port.get_width()); /* Make sure port is valid */ + /* If current port is invalid, we do not combine */ + if (0 == get_width()) { + return; + } + /* Increase MSB */ + msb_ += port.get_width(); return; - } - /* Increase MSB */ - msb_ += port.get_width(); - return; -} +} /* A restricted combine function for two ports, * Following conditions will be applied: @@ -290,38 +289,38 @@ void BasicPort::combine(const BasicPort& port) { * 4. both ports should be valid!!! */ void BasicPort::merge(const BasicPort& portA) { - VTR_ASSERT(true == this->mergeable(portA)); - VTR_ASSERT(true == this->is_valid() && true == portA.is_valid()); - /* We skip merging if the portA is already contained by this port */ - if (true == this->contained(portA)) { + VTR_ASSERT(true == this->mergeable(portA)); + VTR_ASSERT(true == this->is_valid() && true == portA.is_valid()); + /* We skip merging if the portA is already contained by this port */ + if (true == this->contained(portA)) { + return; + } + /* LSB follows the minium LSB of the two ports */ + lsb_ = std::min((int)lsb_, (int)portA.get_lsb()); + /* MSB follows the minium MSB of the two ports */ + msb_ = std::max((int)msb_, (int)portA.get_msb()); + /* Origin port width follows the maximum of the two ports */ + msb_ = std::max((int)origin_port_width_, (int)portA.get_origin_port_width()); return; - } - /* LSB follows the minium LSB of the two ports */ - lsb_ = std::min((int)lsb_, (int)portA.get_lsb()); - /* MSB follows the minium MSB of the two ports */ - msb_ = std::max((int)msb_, (int)portA.get_msb()); - /* Origin port width follows the maximum of the two ports */ - msb_ = std::max((int)origin_port_width_, (int)portA.get_origin_port_width()); - return; } /* Internal functions */ /* Make a port to be invalid: msb < lsb */ void BasicPort::make_invalid() { - /* set a default invalid port */ - lsb_ = 1; - msb_ = 0; - return; + /* set a default invalid port */ + lsb_ = 1; + msb_ = 0; + return; } /* check if port size is valid > 0 */ bool BasicPort::is_valid() const { - /* msb should be equal or greater than lsb, if this is a valid port */ - if ( msb_ < lsb_ ) { - return false; - } - return true; -} + /* msb should be equal or greater than lsb, if this is a valid port */ + if (msb_ < lsb_) { + return false; + } + return true; +} /************************************************************************ * ConfPorts member functions @@ -331,109 +330,109 @@ bool BasicPort::is_valid() const { * Constructor ***********************************************************************/ /* Default constructor */ -ConfPorts::ConfPorts() { - /* default port */ - reserved_.reset(); - regular_.reset(); +ConfPorts::ConfPorts() { + /* default port */ + reserved_.reset(); + regular_.reset(); } /* copy */ -ConfPorts::ConfPorts(const ConfPorts& conf_ports) { - set(conf_ports); +ConfPorts::ConfPorts(const ConfPorts& conf_ports) { + set(conf_ports); } /************************************************************************ * Accessors ***********************************************************************/ size_t ConfPorts::get_reserved_port_width() const { - return reserved_.get_width(); + return reserved_.get_width(); } size_t ConfPorts::get_reserved_port_lsb() const { - return reserved_.get_lsb(); + return reserved_.get_lsb(); } size_t ConfPorts::get_reserved_port_msb() const { - return reserved_.get_msb(); + return reserved_.get_msb(); } size_t ConfPorts::get_regular_port_width() const { - return regular_.get_width(); + return regular_.get_width(); } size_t ConfPorts::get_regular_port_lsb() const { - return regular_.get_lsb(); + return regular_.get_lsb(); } size_t ConfPorts::get_regular_port_msb() const { - return regular_.get_msb(); + return regular_.get_msb(); } /************************************************************************ * Mutators ***********************************************************************/ void ConfPorts::set(const ConfPorts& conf_ports) { - set_reserved_port(conf_ports.get_reserved_port_width()); - set_regular_port(conf_ports.get_regular_port_lsb(), conf_ports.get_regular_port_msb()); - return; + set_reserved_port(conf_ports.get_reserved_port_width()); + set_regular_port(conf_ports.get_regular_port_lsb(), conf_ports.get_regular_port_msb()); + return; } void ConfPorts::set_reserved_port(size_t width) { - reserved_.set_width(width); - return; + reserved_.set_width(width); + return; } void ConfPorts::set_regular_port(size_t width) { - regular_.set_width(width); - return; + regular_.set_width(width); + return; } void ConfPorts::set_regular_port(size_t lsb, size_t msb) { - regular_.set_width(lsb, msb); - return; + regular_.set_width(lsb, msb); + return; } void ConfPorts::set_regular_port_lsb(size_t lsb) { - regular_.set_lsb(lsb); - return; + regular_.set_lsb(lsb); + return; } void ConfPorts::set_regular_port_msb(size_t msb) { - regular_.set_msb(msb); - return; + regular_.set_msb(msb); + return; } /* Increase the port width of reserved port */ void ConfPorts::expand_reserved_port(size_t width) { - reserved_.expand(width); - return; + reserved_.expand(width); + return; } - + /* Increase the port width of regular port */ -void ConfPorts::expand_regular_port(size_t width) { - regular_.expand(width); - return; +void ConfPorts::expand_regular_port(size_t width) { + regular_.expand(width); + return; } /* Increase the port width of both ports */ -void ConfPorts::expand(size_t width) { - expand_reserved_port(width); - expand_regular_port(width); +void ConfPorts::expand(size_t width) { + expand_reserved_port(width); + expand_regular_port(width); } /* rotate */ bool ConfPorts::rotate_regular_port(size_t offset) { - return regular_.rotate(offset); -} + return regular_.rotate(offset); +} /* counter rotate */ bool ConfPorts::counter_rotate_regular_port(size_t offset) { - return regular_.counter_rotate(offset); + return regular_.counter_rotate(offset); } /* Reset to initial port */ void ConfPorts::reset() { - reserved_.reset(); - regular_.reset(); - return; -} + reserved_.reset(); + regular_.reset(); + return; +} diff --git a/vpr/src/tileable_rr_graph/openfpga_port.h b/vpr/src/tileable_rr_graph/openfpga_port.h index 2975405ebe5..5d9a8ef910c 100644 --- a/vpr/src/tileable_rr_graph/openfpga_port.h +++ b/vpr/src/tileable_rr_graph/openfpga_port.h @@ -15,40 +15,44 @@ class BasicPort { BasicPort(const char* name, const size_t& width); BasicPort(const std::string& name, const size_t& lsb, const size_t& msb); BasicPort(const std::string& name, const size_t& width); + public: /* Overloaded operators */ - bool operator== (const BasicPort& portA) const; - bool operator< (const BasicPort& portA) const; - public: /* Accessors */ - size_t get_width() const; /* get the port width */ - size_t get_msb() const; /* get the LSB */ - size_t get_lsb() const; /* get the LSB */ - std::string get_name() const; /* get the name */ - bool is_valid() const; /* check if port size is valid > 0 */ - std::vector pins() const; /* Make a range of the pin indices */ + bool operator==(const BasicPort& portA) const; + bool operator<(const BasicPort& portA) const; + + public: /* Accessors */ + size_t get_width() const; /* get the port width */ + size_t get_msb() const; /* get the LSB */ + size_t get_lsb() const; /* get the LSB */ + std::string get_name() const; /* get the name */ + bool is_valid() const; /* check if port size is valid > 0 */ + std::vector pins() const; /* Make a range of the pin indices */ bool mergeable(const BasicPort& portA) const; /* Check if a port can be merged with this port */ bool contained(const BasicPort& portA) const; /* Check if a port is contained by this port */ size_t get_origin_port_width() const; - public: /* Mutators */ - void set(const BasicPort& basic_port); /* copy */ - void set_name(const std::string& name); /* set the port LSB and MSB */ - void set_width(const size_t& width); /* set the port LSB and MSB */ + + public: /* Mutators */ + void set(const BasicPort& basic_port); /* copy */ + void set_name(const std::string& name); /* set the port LSB and MSB */ + void set_width(const size_t& width); /* set the port LSB and MSB */ void set_width(const size_t& lsb, const size_t& msb); /* set the port LSB and MSB */ void set_lsb(const size_t& lsb); void set_msb(const size_t& msb); - void expand(const size_t& width); /* Increase the port width */ - void revert(); /* Swap lsb and msb */ - bool rotate(const size_t& offset); /* rotate */ + void expand(const size_t& width); /* Increase the port width */ + void revert(); /* Swap lsb and msb */ + bool rotate(const size_t& offset); /* rotate */ bool counter_rotate(const size_t& offset); /* counter rotate */ - void reset(); /* Reset to initial port */ - void combine(const BasicPort& port); /* Combine two ports */ + void reset(); /* Reset to initial port */ + void combine(const BasicPort& port); /* Combine two ports */ void merge(const BasicPort& portA); void set_origin_port_width(const size_t& origin_port_width); - private: /* internal functions */ - void make_invalid(); /* Make a port invalid */ - private: /* Internal Data */ - std::string name_; /* Name of this port */ - size_t msb_; /* Most Significant Bit of this port */ - size_t lsb_; /* Least Significant Bit of this port */ + + private: /* internal functions */ + void make_invalid(); /* Make a port invalid */ + private: /* Internal Data */ + std::string name_; /* Name of this port */ + size_t msb_; /* Most Significant Bit of this port */ + size_t lsb_; /* Least Significant Bit of this port */ size_t origin_port_width_; /* Original port width of a port, used by traceback port conversion history */ }; @@ -57,16 +61,17 @@ class BasicPort { * 2. regular configuration port, which is used by any FPGA architecture */ class ConfPorts { - public: /* Constructors */ - ConfPorts(); /* default port */ + public: /* Constructors */ + ConfPorts(); /* default port */ ConfPorts(const ConfPorts& conf_ports); /* copy */ - public: /* Accessors */ + public: /* Accessors */ size_t get_reserved_port_width() const; size_t get_reserved_port_lsb() const; size_t get_reserved_port_msb() const; size_t get_regular_port_width() const; size_t get_regular_port_lsb() const; size_t get_regular_port_msb() const; + public: /* Mutators */ void set(const ConfPorts& conf_ports); void set_reserved_port(size_t width); @@ -74,13 +79,13 @@ class ConfPorts { void set_regular_port(size_t lsb, size_t msb); void set_regular_port_lsb(size_t lsb); void set_regular_port_msb(size_t msb); - void expand_reserved_port(size_t width); /* Increase the port width of reserved port */ - void expand_regular_port(size_t width); /* Increase the port width of regular port */ - void expand(size_t width); /* Increase the port width of both ports */ - bool rotate_regular_port(size_t offset); /* rotate */ + void expand_reserved_port(size_t width); /* Increase the port width of reserved port */ + void expand_regular_port(size_t width); /* Increase the port width of regular port */ + void expand(size_t width); /* Increase the port width of both ports */ + bool rotate_regular_port(size_t offset); /* rotate */ bool counter_rotate_regular_port(size_t offset); /* counter rotate */ - void reset(); /* Reset to initial port */ - private: /* Internal Data */ + void reset(); /* Reset to initial port */ + private: /* Internal Data */ BasicPort reserved_; BasicPort regular_; }; @@ -88,4 +93,3 @@ class ConfPorts { /* TODO: create a class for BL and WL ports */ #endif - diff --git a/vpr/src/tileable_rr_graph/openfpga_rr_graph_utils.cpp b/vpr/src/tileable_rr_graph/openfpga_rr_graph_utils.cpp index b237e104443..47809f9da8f 100644 --- a/vpr/src/tileable_rr_graph/openfpga_rr_graph_utils.cpp +++ b/vpr/src/tileable_rr_graph/openfpga_rr_graph_utils.cpp @@ -71,11 +71,10 @@ vtr::Point get_track_rr_node_end_coordinate(const RRGraphView& rr_graph, ***********************************************************************/ std::vector get_rr_graph_driver_switches(const RRGraphView& rr_graph, const RRNodeId& node) { - std::vector driver_switches; -// NYI -// unused argements + // NYI + // unused argements (void)(rr_graph); (void)(node); #if 0 @@ -96,8 +95,8 @@ std::vector get_rr_graph_driver_nodes(const RRGraphView& rr_graph, const RRNodeId& node) { std::vector driver_nodes; -// NYI -// unused argements + // NYI + // unused argements (void)(rr_graph); (void)(node); #if 0 @@ -116,8 +115,8 @@ std::vector get_rr_graph_configurable_driver_nodes(const RRGraphView& const RRNodeId& node) { std::vector driver_nodes; -// NYI -// unused argements + // NYI + // unused argements (void)(rr_graph); (void)(node); #if 0 @@ -142,8 +141,8 @@ std::vector get_rr_graph_non_configurable_driver_nodes(const RRGraphVi const RRNodeId& node) { std::vector driver_nodes; -// NYI -// unused argements + // NYI + // unused argements (void)(rr_graph); (void)(node); #if 0 @@ -170,8 +169,8 @@ bool is_opin_direct_connected_ipin(const RRGraphView& rr_graph, /* We only accept OPIN */ VTR_ASSERT(OPIN == rr_graph.node_type(node)); -// NYI -// unused argements + // NYI + // unused argements (void)(rr_graph); (void)(node); #if 0 @@ -202,8 +201,8 @@ bool is_ipin_direct_connected_opin(const RRGraphView& rr_graph, /* We only accept IPIN */ VTR_ASSERT(IPIN == rr_graph.node_type(node)); -// NYI -// unused argements + // NYI + // unused argements (void)(rr_graph); (void)(node); #if 0 diff --git a/vpr/src/tileable_rr_graph/openfpga_rr_graph_utils.h b/vpr/src/tileable_rr_graph/openfpga_rr_graph_utils.h index 69668d762c7..f3d3f65abe8 100644 --- a/vpr/src/tileable_rr_graph/openfpga_rr_graph_utils.h +++ b/vpr/src/tileable_rr_graph/openfpga_rr_graph_utils.h @@ -15,7 +15,7 @@ * Function declaration *******************************************************************/ -vtr::Point get_track_rr_node_start_coordinate(const RRGraphView& rr_graph, +vtr::Point get_track_rr_node_start_coordinate(const RRGraphView& rr_graph, const RRNodeId& track_rr_node); vtr::Point get_track_rr_node_end_coordinate(const RRGraphView& rr_graph, diff --git a/vpr/src/tileable_rr_graph/openfpga_side_manager.cpp b/vpr/src/tileable_rr_graph/openfpga_side_manager.cpp index ceb93882d23..3b1ee1ec404 100644 --- a/vpr/src/tileable_rr_graph/openfpga_side_manager.cpp +++ b/vpr/src/tileable_rr_graph/openfpga_side_manager.cpp @@ -5,167 +5,166 @@ /* Constructors */ SideManager::SideManager(enum e_side side) { - side_ = side; + side_ = side; } SideManager::SideManager() { - side_ = NUM_SIDES; + side_ = NUM_SIDES; } SideManager::SideManager(size_t side) { - set_side(side); + set_side(side); } /* Public Accessors */ enum e_side SideManager::get_side() const { - return side_; + return side_; } enum e_side SideManager::get_opposite() const { - switch (side_) { - case TOP: - return BOTTOM; - case RIGHT: - return LEFT; - case BOTTOM: - return TOP; - case LEFT: - return RIGHT; - default: - return NUM_SIDES; - } + switch (side_) { + case TOP: + return BOTTOM; + case RIGHT: + return LEFT; + case BOTTOM: + return TOP; + case LEFT: + return RIGHT; + default: + return NUM_SIDES; + } } enum e_side SideManager::get_rotate_clockwise() const { - switch (side_) { - case TOP: - return RIGHT; - case RIGHT: - return BOTTOM; - case BOTTOM: - return LEFT; - case LEFT: - return TOP; - default: - return NUM_SIDES; - } + switch (side_) { + case TOP: + return RIGHT; + case RIGHT: + return BOTTOM; + case BOTTOM: + return LEFT; + case LEFT: + return TOP; + default: + return NUM_SIDES; + } } enum e_side SideManager::get_rotate_counterclockwise() const { - switch (side_) { - case TOP: - return LEFT; - case RIGHT: - return TOP; - case BOTTOM: - return RIGHT; - case LEFT: - return BOTTOM; - default: - return NUM_SIDES; - } + switch (side_) { + case TOP: + return LEFT; + case RIGHT: + return TOP; + case BOTTOM: + return RIGHT; + case LEFT: + return BOTTOM; + default: + return NUM_SIDES; + } } bool SideManager::validate() const { - if (NUM_SIDES == side_) { - return false; - } - return true; + if (NUM_SIDES == side_) { + return false; + } + return true; } size_t SideManager::to_size_t() const { - switch (side_) { - case TOP: - return 0; - case RIGHT: - return 1; - case BOTTOM: - return 2; - case LEFT: - return 3; - default: - return 4; - } + switch (side_) { + case TOP: + return 0; + case RIGHT: + return 1; + case BOTTOM: + return 2; + case LEFT: + return 3; + default: + return 4; + } } /* Convert to char* */ const char* SideManager::c_str() const { - switch (side_) { - case TOP: - return "top"; - case RIGHT: - return "right"; - case BOTTOM: - return "bottom"; - case LEFT: - return "left"; - default: - return "invalid_side"; - } + switch (side_) { + case TOP: + return "top"; + case RIGHT: + return "right"; + case BOTTOM: + return "bottom"; + case LEFT: + return "left"; + default: + return "invalid_side"; + } } /* Convert to char* */ std::string SideManager::to_string() const { - std::string ret; - switch (side_) { - case TOP: - ret.assign("top"); - break; - case RIGHT: - ret.assign("right"); - break; - case BOTTOM: - ret.assign("bottom"); - break; - case LEFT: - ret.assign("left"); - break; - default: - ret.assign("invalid_side"); - break; - } - - return ret; + std::string ret; + switch (side_) { + case TOP: + ret.assign("top"); + break; + case RIGHT: + ret.assign("right"); + break; + case BOTTOM: + ret.assign("bottom"); + break; + case LEFT: + ret.assign("left"); + break; + default: + ret.assign("invalid_side"); + break; + } + + return ret; } /* Public Mutators */ void SideManager::set_side(size_t side) { - switch (side) { - case 0: - side_ = TOP; - return; - case 1: - side_ = RIGHT; - return; - case 2: - side_ = BOTTOM; - return; - case 3: - side_ = LEFT; - return; - default: - side_ = NUM_SIDES; - return; - } + switch (side) { + case 0: + side_ = TOP; + return; + case 1: + side_ = RIGHT; + return; + case 2: + side_ = BOTTOM; + return; + case 3: + side_ = LEFT; + return; + default: + side_ = NUM_SIDES; + return; + } } void SideManager::set_side(enum e_side side) { - side_ = side; - return; + side_ = side; + return; } void SideManager::set_opposite() { - side_ = get_opposite(); - return; + side_ = get_opposite(); + return; } void SideManager::rotate_clockwise() { - side_ = get_rotate_clockwise(); - return; + side_ = get_rotate_clockwise(); + return; } void SideManager::rotate_counterclockwise() { - side_ = get_rotate_counterclockwise(); - return; + side_ = get_rotate_counterclockwise(); + return; } - diff --git a/vpr/src/tileable_rr_graph/openfpga_side_manager.h b/vpr/src/tileable_rr_graph/openfpga_side_manager.h index a6eb01d9197..a6eb265cd64 100644 --- a/vpr/src/tileable_rr_graph/openfpga_side_manager.h +++ b/vpr/src/tileable_rr_graph/openfpga_side_manager.h @@ -22,6 +22,7 @@ class SideManager { SideManager(enum e_side side); SideManager(); SideManager(size_t side); + public: /* Accessors */ enum e_side get_side() const; enum e_side get_opposite() const; @@ -31,14 +32,16 @@ class SideManager { size_t to_size_t() const; const char* c_str() const; std::string to_string() const; + public: /* Mutators */ void set_side(size_t side); void set_side(enum e_side side); void set_opposite(); void rotate_clockwise(); void rotate_counterclockwise(); + private: /* internal data */ - enum e_side side_; + enum e_side side_; }; #endif diff --git a/vpr/src/tileable_rr_graph/rr_chan.h b/vpr/src/tileable_rr_graph/rr_chan.h index effa69273f7..11c40595bd3 100644 --- a/vpr/src/tileable_rr_graph/rr_chan.h +++ b/vpr/src/tileable_rr_graph/rr_chan.h @@ -43,46 +43,46 @@ class RRChan { public: /* Constructors */ RRChan(); + public: /* Accessors */ t_rr_type get_type() const; - size_t get_chan_width() const; /* get the number of tracks in this channel */ + size_t get_chan_width() const; /* get the number of tracks in this channel */ int get_node_track_id(const RRNodeId& node) const; /* get the track_id of a node */ - RRNodeId get_node(const size_t& track_num) const; /* get the rr_node with the track_id */ + RRNodeId get_node(const size_t& track_num) const; /* get the rr_node with the track_id */ RRSegmentId get_node_segment(const RRNodeId& node) const; RRSegmentId get_node_segment(const size_t& track_num) const; - bool is_mirror(const RRGraphView& rr_graph, const RRChan& cand) const; /* evaluate if two RR_chan is mirror to each other */ - std::vector get_segment_ids() const; /* Get a list of segments used in this routing channel */ + bool is_mirror(const RRGraphView& rr_graph, const RRChan& cand) const; /* evaluate if two RR_chan is mirror to each other */ + std::vector get_segment_ids() const; /* Get a list of segments used in this routing channel */ std::vector get_node_ids_by_segment_ids(const RRSegmentId& seg_id) const; /* Get a list of segments used in this routing channel */ - public: /* Mutators */ + public: /* Mutators */ /* copy */ - void set(const RRChan&); + void set(const RRChan&); /* modify the type of routing channel */ - void set_type(const t_rr_type& type); + void set_type(const t_rr_type& type); /* reseve a number of nodes to the array */ - void reserve_node(const size_t& node_size); + void reserve_node(const size_t& node_size); /* add a node to the routing channel */ - void add_node(const RRGraphView& rr_graph, const RRNodeId& node, const RRSegmentId& node_segment); + void add_node(const RRGraphView& rr_graph, const RRNodeId& node, const RRSegmentId& node_segment); /* clear the content */ - void clear(); + void clear(); private: /* internal functions */ - /* For the type of a routing channel, only valid type is CHANX and CHANY */ - bool valid_type(const t_rr_type& type) const; + bool valid_type(const t_rr_type& type) const; /* Check each node, see if the node type is consistent with the type of routing channel */ - bool valid_node_type(const RRGraphView& rr_graph, const RRNodeId& node) const; + bool valid_node_type(const RRGraphView& rr_graph, const RRNodeId& node) const; /* Validate if the track number in the range */ - bool valid_node_id(const size_t& node_id) const; + bool valid_node_id(const size_t& node_id) const; - private: /* Internal Data */ - t_rr_type type_; /* channel type: CHANX or CHANY */ - std::vector nodes_; /* rr nodes of each track in the channel */ + private: /* Internal Data */ + t_rr_type type_; /* channel type: CHANX or CHANY */ + std::vector nodes_; /* rr nodes of each track in the channel */ std::vector node_segments_; /* segment of each track */ }; diff --git a/vpr/src/tileable_rr_graph/rr_graph_builder_utils.h b/vpr/src/tileable_rr_graph/rr_graph_builder_utils.h index 05628fac18e..ff0cc9ab782 100644 --- a/vpr/src/tileable_rr_graph/rr_graph_builder_utils.h +++ b/vpr/src/tileable_rr_graph/rr_graph_builder_utils.h @@ -17,32 +17,32 @@ size_t find_unidir_routing_channel_width(const size_t& chan_width); int get_grid_pin_class_index(const t_grid_tile& cur_grid, const int pin_index); -std::vector find_grid_pin_sides(const t_grid_tile& grid, +std::vector find_grid_pin_sides(const t_grid_tile& grid, const size_t& pin_id); -e_side determine_io_grid_pin_side(const vtr::Point& device_size, +e_side determine_io_grid_pin_side(const vtr::Point& device_size, const vtr::Point& grid_coordinate); -std::vector get_grid_side_pins(const t_grid_tile& cur_grid, - const e_pin_type& pin_type, - const e_side& pin_side, +std::vector get_grid_side_pins(const t_grid_tile& cur_grid, + const e_pin_type& pin_type, + const e_side& pin_side, const int& pin_width, const int& pin_height); -size_t get_grid_num_pins(const t_grid_tile& cur_grid, - const e_pin_type& pin_type, +size_t get_grid_num_pins(const t_grid_tile& cur_grid, + const e_pin_type& pin_type, const e_side& io_side); -size_t get_grid_num_classes(const t_grid_tile& cur_grid, +size_t get_grid_num_classes(const t_grid_tile& cur_grid, const e_pin_type& pin_type); bool is_chanx_exist(const DeviceGrid& grids, const vtr::Point& chanx_coord, - const bool& through_channel=false); + const bool& through_channel = false); bool is_chany_exist(const DeviceGrid& grids, const vtr::Point& chany_coord, - const bool& through_channel=false); + const bool& through_channel = false); bool is_chanx_right_to_multi_height_grid(const DeviceGrid& grids, const vtr::Point& chanx_coord, @@ -90,4 +90,3 @@ short find_rr_graph_average_fan_in(const RRGraph& rr_graph, void print_rr_graph_mux_stats(const RRGraph& rr_graph); #endif - diff --git a/vpr/src/tileable_rr_graph/rr_graph_obj_util.cpp b/vpr/src/tileable_rr_graph/rr_graph_obj_util.cpp index bef1c745557..d389ab757e4 100644 --- a/vpr/src/tileable_rr_graph/rr_graph_obj_util.cpp +++ b/vpr/src/tileable_rr_graph/rr_graph_obj_util.cpp @@ -12,15 +12,14 @@ std::vector find_rr_graph_switches(const RRGraphView& rr_graph, const RRNodeId& from_node, const RRNodeId& to_node) { - std::vector switches; - + // NYI // unused parameters (void)(rr_graph); (void)(from_node); (void)(to_node); - #if 0 +#if 0 std::vector edges = rr_graph.find_edges(from_node, to_node); if (true == edges.empty()) { /* edge is open, we return an empty vector of switches */ @@ -33,7 +32,7 @@ std::vector find_rr_graph_switches(const RRGraphView& rr_graph, for (auto edge : edges) { switches.push_back(rr_graph.edge_switch(edge)); } - #endif +#endif return switches; } @@ -57,7 +56,7 @@ std::vector find_rr_graph_nodes(const RRGraphView& rr_graph, (void)(y); (void)(rr_type); (void)(ptc); - #if 0 +#if 0 if (rr_type == IPIN || rr_type == OPIN) { //For pins we need to look at all the sides of the current grid tile @@ -76,7 +75,7 @@ std::vector find_rr_graph_nodes(const RRGraphView& rr_graph, indices.push_back(rr_node_index); } } - #endif +#endif return indices; } @@ -97,7 +96,7 @@ std::vector find_rr_graph_chan_nodes(const RRGraphView& rr_graph, (void)(rr_graph); (void)(x); (void)(y); - #if 0 +#if 0 for (short track = 0; track < rr_graph.chan_num_tracks(x, y, rr_type); ++track) { RRNodeId rr_node_index = rr_graph.find_node(x, y, rr_type, track); @@ -105,7 +104,7 @@ std::vector find_rr_graph_chan_nodes(const RRGraphView& rr_graph, indices.push_back(rr_node_index); } } - #endif +#endif return indices; } @@ -122,14 +121,14 @@ std::vector find_rr_graph_grid_nodes(const RRGraphView& rr_graph, std::vector indices; VTR_ASSERT(rr_type == IPIN || rr_type == OPIN); - - /* Ensure that (x, y) is a valid location in grids */ + + /* Ensure that (x, y) is a valid location in grids */ VTR_ASSERT(size_t(x) <= device_grid.width() && size_t(y) <= device_grid.height()); /* Ensure we have a valid side */ VTR_ASSERT(side != NUM_SIDES); - - /* Find all the pins on the side of the grid */ + + /* Find all the pins on the side of the grid */ int width_offset = device_grid[x][y].width_offset; int height_offset = device_grid[x][y].height_offset; for (int pin = 0; pin < device_grid[x][y].type->num_pins; ++pin) { @@ -145,17 +144,14 @@ std::vector find_rr_graph_grid_nodes(const RRGraphView& rr_graph, // NYI // unused parameter (void)(rr_graph); - #if 0 +#if 0 /* Try to find the rr node */ RRNodeId rr_node_index = rr_graph.find_node(x, y, rr_type, pin, side); if (rr_node_index != RRNodeId::INVALID()) { indices.push_back(rr_node_index); } - #endif - +#endif } - return indices; } - diff --git a/vpr/src/tileable_rr_graph/rr_graph_obj_util.h b/vpr/src/tileable_rr_graph/rr_graph_obj_util.h index c413386c5dc..f32957e43c2 100644 --- a/vpr/src/tileable_rr_graph/rr_graph_obj_util.h +++ b/vpr/src/tileable_rr_graph/rr_graph_obj_util.h @@ -32,5 +32,4 @@ std::vector find_rr_graph_grid_nodes(const RRGraphView& rr_graph, const t_rr_type& rr_type, const e_side& side); - #endif diff --git a/vpr/src/tileable_rr_graph/rr_graph_types.h b/vpr/src/tileable_rr_graph/rr_graph_types.h index 5f7297a49c4..ca97d7d38a9 100644 --- a/vpr/src/tileable_rr_graph/rr_graph_types.h +++ b/vpr/src/tileable_rr_graph/rr_graph_types.h @@ -42,5 +42,4 @@ typedef enum e_rr_type : unsigned char { // constexpr std::array RR_TYPES = {{SOURCE, SINK, IPIN, OPIN, CHANX, CHANY}}; // constexpr std::array rr_node_typename{{"SOURCE", "SINK", "IPIN", "OPIN", "CHANX", "CHANY"}}; - #endif diff --git a/vpr/src/tileable_rr_graph/rr_gsb.cpp b/vpr/src/tileable_rr_graph/rr_gsb.cpp index 59436c84c1d..d1b6e2b4e1e 100644 --- a/vpr/src/tileable_rr_graph/rr_gsb.cpp +++ b/vpr/src/tileable_rr_graph/rr_gsb.cpp @@ -161,11 +161,11 @@ std::vector RRGSB::get_chan_node_in_edges(const RRGraphView& rr_graph, // NYI // unused parameter (void)(rr_graph); - #if 0 +#if 0 for (const RREdgeId& edge : rr_graph.node_in_edges(get_chan_node(side, track_id))) { unsorted_edges.push_back(edge); } - #endif +#endif return unsorted_edges; } @@ -449,10 +449,10 @@ bool RRGSB::is_sb_node_passing_wire(const RRGraphView& rr_graph, VTR_LOG("GSB[%lu][%lu] track node[%lu] at %s:\n", get_x(), get_y(), track_id, SIDE_STRING[node_side]); - // NYI - #if 0 +// NYI +#if 0 rr_graph.print_node(track_node); - #endif +#endif } VTR_ASSERT(true == is_sb_node_exist_opposite_side(rr_graph, track_node, node_side)); @@ -827,7 +827,7 @@ void RRGSB::sort_chan_node_in_edges(const RRGraphView& rr_graph, (void)(rr_graph); // unused variable (void)(chan_node); - #if 0 +#if 0 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); @@ -857,7 +857,7 @@ void RRGSB::sort_chan_node_in_edges(const RRGraphView& rr_graph, edge_counter++; } - #endif +#endif /* Store the sorted edge */ for (size_t side = 0; side < get_num_sides(); ++side) { @@ -987,8 +987,8 @@ bool RRGSB::is_sb_node_mirror(const RRGraphView& rr_graph, VTR_ASSERT(node_in_edges.size() == cand_node_in_edges.size()); - // NYI - #if 0 +// NYI +#if 0 for (size_t iedge = 0; iedge < node_in_edges.size(); ++iedge) { RREdgeId src_edge = node_in_edges[iedge]; RREdgeId src_cand_edge = cand_node_in_edges[iedge]; @@ -1013,7 +1013,7 @@ bool RRGSB::is_sb_node_mirror(const RRGraphView& rr_graph, return false; } } - #endif +#endif return true; } @@ -1039,7 +1039,7 @@ bool RRGSB::is_cb_node_mirror(const RRGraphView& rr_graph, // unused variables (void)(node); (void)(cand_node); - #if 0 +#if 0 if (rr_graph.node_in_edges(node).size() != rr_graph.node_in_edges(cand_node).size()) { return false; } @@ -1094,7 +1094,7 @@ bool RRGSB::is_cb_node_mirror(const RRGraphView& rr_graph, return false; } } - #endif +#endif return true; } diff --git a/vpr/src/tileable_rr_graph/rr_gsb.h b/vpr/src/tileable_rr_graph/rr_gsb.h index a2106325c62..00caa876d29 100644 --- a/vpr/src/tileable_rr_graph/rr_gsb.h +++ b/vpr/src/tileable_rr_graph/rr_gsb.h @@ -49,9 +49,9 @@ * num_conf_bits: number of configuration bits this switch block requires *******************************************************************/ class RRGSB { - public: /* Contructors */ - RRGSB();/* Default constructor */ - public: /* Accessors */ + public: /* Contructors */ + RRGSB(); /* Default constructor */ + public: /* Accessors */ /* Get the number of sides of this SB */ size_t get_num_sides() const; @@ -115,6 +115,7 @@ class RRGSB { /* Check if the node exist in the opposite side of this Switch Block */ bool is_sb_node_exist_opposite_side(const RRGraphView& rr_graph, const RRNodeId& node, const e_side& node_side) const; + public: /* Accessors: to identify mirrors */ /* check if the candidate SB is a mirror of the current one */ bool is_cb_mirror(const RRGraphView& rr_graph, const RRGSB& cand, const t_rr_type& cb_type) const; @@ -134,8 +135,7 @@ class RRGSB { bool is_sb_mirrorable(const RRGraphView& rr_graph, const RRGSB& cand) const; /* check if all the routing segments of a side of candidate SB is a mirror of the current one */ - bool is_sb_side_segment_mirror(const RRGraphView& rr_graph, const RRGSB& cand, - const e_side& side, const RRSegmentId& seg_id) const; + bool is_sb_side_segment_mirror(const RRGraphView& rr_graph, const RRGSB& cand, const e_side& side, const RRSegmentId& seg_id) const; /* check if a side of candidate SB is a mirror of the current one * Check the specified side of two switch blocks: @@ -164,19 +164,20 @@ class RRGSB { */ bool is_sb_mirror(const RRGraphView& rr_graph, const RRGSB& cand) const; - public: /* Cooridinator conversion and output */ - size_t get_x() const; /* get the x coordinate of this switch block */ - size_t get_y() const; /* get the y coordinate of this switch block */ - size_t get_sb_x() const; /* get the x coordinate of this switch block */ - size_t get_sb_y() const; /* get the y coordinate of this switch block */ - vtr::Point get_sb_coordinate() const; /* Get the coordinate of the SB */ - size_t get_cb_x(const t_rr_type& cb_type) const; /* get the x coordinate of this X/Y-direction block */ - size_t get_cb_y(const t_rr_type& cb_type) const; /* get the y coordinate of this X/Y-direction block */ + public: /* Cooridinator conversion and output */ + size_t get_x() const; /* get the x coordinate of this switch block */ + size_t get_y() const; /* get the y coordinate of this switch block */ + size_t get_sb_x() const; /* get the x coordinate of this switch block */ + size_t get_sb_y() const; /* get the y coordinate of this switch block */ + vtr::Point get_sb_coordinate() const; /* Get the coordinate of the SB */ + size_t get_cb_x(const t_rr_type& cb_type) const; /* get the x coordinate of this X/Y-direction block */ + size_t get_cb_y(const t_rr_type& cb_type) const; /* get the y coordinate of this X/Y-direction block */ vtr::Point get_cb_coordinate(const t_rr_type& cb_type) const; /* Get the coordinate of the X/Y-direction CB */ - e_side get_cb_chan_side(const t_rr_type& cb_type) const; /* get the side of a Connection block */ - e_side get_cb_chan_side(const e_side& ipin_side) const; /* get the side of a Connection block */ + e_side get_cb_chan_side(const t_rr_type& cb_type) const; /* get the side of a Connection block */ + e_side get_cb_chan_side(const e_side& ipin_side) const; /* get the side of a Connection block */ vtr::Point get_side_block_coordinate(const e_side& side) const; vtr::Point get_grid_coordinate() const; + public: /* Mutators */ /* get a copy from a source */ void set(const RRGSB& src); @@ -249,6 +250,7 @@ class RRGSB { bool validate_opin_node_id(const e_side& side, const size_t& node_id) const; bool validate_ipin_node_id(const e_side& side, const size_t& node_id) const; bool validate_cb_type(const t_rr_type& cb_type) const; + private: /* Internal Data */ /* Coordinator */ vtr::Point coordinate_; @@ -257,10 +259,10 @@ class RRGSB { * Each GSB may have four sides of routing track nodes */ /* Node id in rr_graph denoting each routing track */ - std::vector chan_node_; + std::vector chan_node_; /* Direction of a port when the channel node appear in the GSB module */ - std::vector> chan_node_direction_; + 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 @@ -276,10 +278,10 @@ class RRGSB { std::vector>> chan_node_in_edges_; /* Logic Block Inputs data */ - std::vector> ipin_node_; + std::vector> ipin_node_; /* Logic Block Outputs data */ - std::vector> opin_node_; + std::vector> opin_node_; }; #endif diff --git a/vpr/src/tileable_rr_graph/tileable_chan_details_builder.h b/vpr/src/tileable_rr_graph/tileable_chan_details_builder.h index 34a476d80e4..5ce79b61221 100644 --- a/vpr/src/tileable_rr_graph/tileable_chan_details_builder.h +++ b/vpr/src/tileable_rr_graph/tileable_chan_details_builder.h @@ -1,5 +1,5 @@ -#ifndef TILEABLE_CHAN_DETAILS_BUILDER_H -#define TILEABLE_CHAN_DETAILS_BUILDER_H +#ifndef TILEABLE_CHAN_DETAILS_BUILDER_H +#define TILEABLE_CHAN_DETAILS_BUILDER_H /******************************************************************** * Include header files that are required by function declaration @@ -12,16 +12,16 @@ * Function declaration *******************************************************************/ -std::vector get_num_tracks_per_seg_type(const size_t& chan_width, - const std::vector& segment_inf, +std::vector get_num_tracks_per_seg_type(const size_t& chan_width, + const std::vector& segment_inf, const bool& use_full_seg_groups); int adapt_to_tileable_route_chan_width(const int& chan_width, const std::vector& segment_inf); ChanNodeDetails build_unidir_chan_node_details(const size_t& chan_width, const size_t& max_seg_length, - const bool& force_start, - const bool& force_end, + const bool& force_start, + const bool& force_end, const std::vector& segment_inf); #endif diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp index c4814f5b78e..8aa3b8485ef 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp @@ -207,7 +207,7 @@ void build_tileable_unidir_rr_graph(const std::vector& typ bool Fc_clipped = false; /* [0..num_types-1][0..num_pins-1] */ std::vector> Fc_in; - Fc_in = alloc_and_load_actual_fc(types, max_pins, segment_inf, sets_per_seg_type, (const t_chan_width*) &chan_width, + Fc_in = alloc_and_load_actual_fc(types, max_pins, segment_inf, sets_per_seg_type, (const t_chan_width*)&chan_width, e_fc_type::IN, UNI_DIRECTIONAL, &Fc_clipped); if (Fc_clipped) { *Warnings |= RR_GRAPH_WARN_FC_CLIPPED; @@ -216,7 +216,7 @@ void build_tileable_unidir_rr_graph(const std::vector& typ Fc_clipped = false; /* [0..num_types-1][0..num_pins-1] */ std::vector> Fc_out; - Fc_out = alloc_and_load_actual_fc(types, max_pins, segment_inf, sets_per_seg_type, (const t_chan_width*) &chan_width, + Fc_out = alloc_and_load_actual_fc(types, max_pins, segment_inf, sets_per_seg_type, (const t_chan_width*)&chan_width, e_fc_type::OUT, UNI_DIRECTIONAL, &Fc_clipped); if (Fc_clipped) { @@ -263,7 +263,7 @@ void build_tileable_unidir_rr_graph(const std::vector& typ arch_directs, clb2clb_directs); //NYI -// We may not need to rebuild it again +// We may not need to rebuild it again #if 0 /* First time to build edges so that we can remap the architecture switch to rr_switch * This is a must-do before function alloc_and_load_rr_switch_inf() @@ -304,14 +304,14 @@ void build_tileable_unidir_rr_graph(const std::vector& typ && (CHANY != device_ctx.rr_graph.node_type(inode))) { continue; } - // NYI - #if 0 +// NYI +#if 0 RRIndexedDataId irc_data = device_ctx.rr_graph.node_cost_index(inode); short iseg = device_ctx.rr_indexed_data[irc_data].seg_index; // device_ctx.rr_graph_builder.set_node_segment(inode, RRSegmentId(iseg)); // NYI vtr::vector rr_segments = device_ctx.rr_graph_builder.rr_segments(); rr_segments[(RRSegmentId)iseg] = segment_inf; - #endif +#endif } /************************************************************************ diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.h b/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.h index e2372d4d196..c5275e1d0a7 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.h +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.h @@ -16,19 +16,21 @@ void build_tileable_unidir_rr_graph(const std::vector& types, const DeviceGrid& grids, const t_chan_width& chan_width, - const e_switch_block_type& sb_type, const int& Fs, - const e_switch_block_type& sb_subtype, const int& subFs, + const e_switch_block_type& sb_type, + const int& Fs, + const e_switch_block_type& sb_subtype, + const int& subFs, const std::vector& segment_inf, - const int& delayless_switch, + const int& delayless_switch, const int& wire_to_arch_ipin_switch, const float R_minW_nmos, const float R_minW_pmos, - const enum e_base_cost_type& base_cost_type, - const t_direct_inf *directs, + const enum e_base_cost_type& base_cost_type, + const t_direct_inf* directs, const int& num_directs, int* wire_to_rr_ipin_switch, const bool& through_channel, const bool& wire_opposite_side, - int *Warnings); + int* Warnings); #endif diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp index f46e1fc48da..c261af8f655 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp @@ -20,9 +20,9 @@ * 1. create edges between SOURCE and OPINs ***********************************************************************/ void build_rr_graph_edges_for_source_nodes(const RRGraphView& rr_graph, - RRGraphBuilder& rr_graph_builder, - const vtr::vector& rr_node_driver_switches, - const DeviceGrid& grids) { + RRGraphBuilder& rr_graph_builder, + const vtr::vector& rr_node_driver_switches, + const DeviceGrid& grids) { for (const RRNodeId& node : rr_graph.nodes()) { /* Bypass all the non OPIN nodes */ if (OPIN != rr_graph.node_type(node)) { @@ -36,16 +36,16 @@ void build_rr_graph_edges_for_source_nodes(const RRGraphView& rr_graph, /* Create edges between SOURCE and OPINs */ const RRNodeId& src_node = rr_graph_builder.node_lookup().find_node(xlow - grids[xlow][ylow].width_offset, - ylow - grids[xlow][ylow].height_offset, - SOURCE, src_node_class_num); + ylow - grids[xlow][ylow].height_offset, + SOURCE, src_node_class_num); VTR_ASSERT(true == rr_graph.validate_node(src_node)); // NYI (void)(rr_node_driver_switches); - #if 0 +#if 0 /* add edges to the src_node */ rr_graph_builder.create_edge(src_node, node, rr_node_driver_switches[node]); - #endif +#endif } } @@ -54,9 +54,9 @@ void build_rr_graph_edges_for_source_nodes(const RRGraphView& rr_graph, * 1. create edges between IPINs and SINKs ***********************************************************************/ void build_rr_graph_edges_for_sink_nodes(const RRGraphView& rr_graph, - RRGraphBuilder& rr_graph_builder, - const vtr::vector& rr_node_driver_switches, - const DeviceGrid& grids) { + RRGraphBuilder& rr_graph_builder, + const vtr::vector& rr_node_driver_switches, + const DeviceGrid& grids) { for (const RRNodeId& node : rr_graph.nodes()) { /* Bypass all the non IPIN nodes */ if (IPIN != rr_graph.node_type(node)) { @@ -70,21 +70,20 @@ void build_rr_graph_edges_for_sink_nodes(const RRGraphView& rr_graph, /* 1. create edges between IPINs and SINKs */ // NYI (void)(sink_node_class_num); - #if 0 +#if 0 const RRNodeId& sink_node = rr_graph.find_node(xlow - grids[xlow][ylow].width_offset, ylow - grids[xlow][ylow].height_offset, SINK, sink_node_class_num); VTR_ASSERT(true == rr_graph.valid_node_id(sink_node)); - #endif +#endif // NYI (void)(rr_node_driver_switches); (void)(rr_graph_builder); - #if 0 +#if 0 /* add edges to connect the IPIN node to SINK nodes */ rr_graph_builder.create_edge(node, sink_node, rr_node_driver_switches[sink_node]); - #endif - +#endif } } @@ -181,4 +180,3 @@ void build_rr_graph_direct_connections(const RRGraphView& rr_graph, } } } - diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.h b/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.h index cb43d80f8fb..8e780521da3 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.h +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.h @@ -42,14 +42,13 @@ void build_rr_graph_direct_connections(const RRGraphView& rr_graph, const std::vector& clb_to_clb_directs); void build_rr_graph_edges_for_source_nodes(const RRGraphView& rr_graph, - RRGraphBuilder& rr_graph_builder, - const vtr::vector& rr_node_driver_switches, - const DeviceGrid& grids); + RRGraphBuilder& rr_graph_builder, + const vtr::vector& rr_node_driver_switches, + const DeviceGrid& grids); void build_rr_graph_edges_for_sink_nodes(const RRGraphView& rr_graph, - RRGraphBuilder& rr_graph_builder, - const vtr::vector& rr_node_driver_switches, - const DeviceGrid& grids); + RRGraphBuilder& rr_graph_builder, + const vtr::vector& rr_node_driver_switches, + const DeviceGrid& grids); #endif - diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp index e8c019724da..549a50c4d98 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp @@ -917,16 +917,15 @@ void build_edges_for_one_tileable_rr_gsb(RRGraphBuilder& rr_graph_builder, const t_pin2track_map& opin2track_map, const t_track2track_map& track2track_map, const vtr::vector& rr_node_driver_switches) { - // NYI // unused parameters - (void) (rr_graph_builder); - (void) (rr_gsb); - (void) (track2ipin_map); - (void) (opin2track_map); - (void) (track2track_map); - (void) (rr_node_driver_switches); - #if 0 + (void)(rr_graph_builder); + (void)(rr_gsb); + (void)(track2ipin_map); + (void)(opin2track_map); + (void)(track2track_map); + (void)(rr_node_driver_switches); +#if 0 /* Walk through each sides */ for (size_t side = 0; side < rr_gsb.get_num_sides(); ++side) { SideManager side_manager(side); @@ -966,7 +965,7 @@ void build_edges_for_one_tileable_rr_gsb(RRGraphBuilder& rr_graph_builder, } } } - #endif +#endif } /************************************************************************ @@ -1426,14 +1425,14 @@ void build_direct_connections_for_one_gsb(const RRGraphView& rr_graph, (void)(from_grid_height_ofs); (void)(to_grid_width_ofs); (void)(to_grid_height_ofs); - #if 0 +#if 0 const RRNodeId& opin_node_id = rr_graph.find_node(from_grid_coordinate.x() - from_grid_width_ofs, from_grid_coordinate.y() - from_grid_height_ofs, OPIN, opin, opin_grid_side[0]); const RRNodeId& ipin_node_id = rr_graph.find_node(to_grid_coordinate.x() - to_grid_width_ofs, to_grid_coordinate.y() - to_grid_height_ofs, IPIN, ipin, ipin_grid_side[0]); - #endif +#endif /* VTR_LOG("Direct connection: from grid[%lu][%lu].pin[%lu] at side %s to grid[%lu][%lu].pin[%lu] at side %s\n", from_grid_coordinate.x() - from_grid_width_ofs, @@ -1449,11 +1448,10 @@ void build_direct_connections_for_one_gsb(const RRGraphView& rr_graph, // NYI // unused parameters (void)(delayless_switch); - #if 0 +#if 0 rr_graph_builder.create_edge(opin_node_id, ipin_node_id, delayless_switch); - #endif - +#endif } } } diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.h b/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.h index 992a446706a..43224fbdbc7 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.h +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.h @@ -74,4 +74,3 @@ void build_direct_connections_for_one_gsb(const RRGraphView& rr_graph, const std::vector& clb_to_clb_directs); #endif - diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp index a1a6fc1ffd5..5c9f583658b 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp @@ -1,5 +1,5 @@ /************************************************************************ - * This file contains functions that are used to allocate nodes + * This file contains functions that are used to allocate nodes * for the tileable routing resource graph builder ***********************************************************************/ /* Headers from vtrutil library */ @@ -24,60 +24,58 @@ /************************************************************************ * Find the number output pins by considering all the grid ***********************************************************************/ -static -size_t estimate_num_grid_rr_nodes_by_type(const DeviceGrid& grids, - const t_rr_type& node_type) { - size_t num_grid_rr_nodes = 0; - - for (size_t ix = 0; ix < grids.width(); ++ix) { - for (size_t iy = 0; iy < grids.height(); ++iy) { - - /* Skip EMPTY tiles */ - if (true == is_empty_type(grids[ix][iy].type)) { - continue; - } - - /* Skip height > 1 or width > 1 tiles (mostly heterogeneous blocks) */ - if ( (0 < grids[ix][iy].width_offset) - || (0 < grids[ix][iy].height_offset) ) { - continue; - } - - enum e_side io_side = NUM_SIDES; - - /* If this is the block on borders, we consider IO side */ - if (true == is_io_type(grids[ix][iy].type)) { - vtr::Point io_device_size(grids.width() - 1, grids.height() - 1); - vtr::Point grid_coordinate(ix, iy); - io_side = determine_io_grid_pin_side(io_device_size, grid_coordinate); - } - - switch (node_type) { - case OPIN: - /* get the number of OPINs */ - num_grid_rr_nodes += get_grid_num_pins(grids[ix][iy], DRIVER, io_side); - break; - case IPIN: - /* get the number of IPINs */ - num_grid_rr_nodes += get_grid_num_pins(grids[ix][iy], RECEIVER, io_side); - break; - case SOURCE: - /* SOURCE: number of classes whose type is DRIVER */ - num_grid_rr_nodes += get_grid_num_classes(grids[ix][iy], DRIVER); - break; - case SINK: - /* SINK: number of classes whose type is RECEIVER */ - num_grid_rr_nodes += get_grid_num_classes(grids[ix][iy], RECEIVER); - break; - default: - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid routing resource node!\n"); - exit(1); - } +static size_t estimate_num_grid_rr_nodes_by_type(const DeviceGrid& grids, + const t_rr_type& node_type) { + size_t num_grid_rr_nodes = 0; + + for (size_t ix = 0; ix < grids.width(); ++ix) { + for (size_t iy = 0; iy < grids.height(); ++iy) { + /* Skip EMPTY tiles */ + if (true == is_empty_type(grids[ix][iy].type)) { + continue; + } + + /* Skip height > 1 or width > 1 tiles (mostly heterogeneous blocks) */ + if ((0 < grids[ix][iy].width_offset) + || (0 < grids[ix][iy].height_offset)) { + continue; + } + + enum e_side io_side = NUM_SIDES; + + /* If this is the block on borders, we consider IO side */ + if (true == is_io_type(grids[ix][iy].type)) { + vtr::Point io_device_size(grids.width() - 1, grids.height() - 1); + vtr::Point grid_coordinate(ix, iy); + io_side = determine_io_grid_pin_side(io_device_size, grid_coordinate); + } + + switch (node_type) { + case OPIN: + /* get the number of OPINs */ + num_grid_rr_nodes += get_grid_num_pins(grids[ix][iy], DRIVER, io_side); + break; + case IPIN: + /* get the number of IPINs */ + num_grid_rr_nodes += get_grid_num_pins(grids[ix][iy], RECEIVER, io_side); + break; + case SOURCE: + /* SOURCE: number of classes whose type is DRIVER */ + num_grid_rr_nodes += get_grid_num_classes(grids[ix][iy], DRIVER); + break; + case SINK: + /* SINK: number of classes whose type is RECEIVER */ + num_grid_rr_nodes += get_grid_num_classes(grids[ix][iy], RECEIVER); + break; + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid routing resource node!\n"); + exit(1); + } + } } - } - return num_grid_rr_nodes; + return num_grid_rr_nodes; } /************************************************************************ @@ -87,10 +85,10 @@ size_t estimate_num_grid_rr_nodes_by_type(const DeviceGrid& grids, * * As such, the range of CHANX coordinate starts from x = 1, y = 0 * which is the grid (I/O) at the left bottom of the fabric - * + * * As such, the range of CHANX coordinate ends to x = width - 2, y = height - 2 * which is the grid at the top right of the core fabric - * Note that the I/O ring is + * Note that the I/O ring is * * TOP SIDE OF FPGA * @@ -108,16 +106,16 @@ size_t estimate_num_grid_rr_nodes_by_type(const DeviceGrid& grids, * | Grid | | Grid | ... | Grid | * | [1][0] | | [2][0] | | [width-2][height-2] | * +-------------+ +-------------+ +---------------------+ - * + * * ... ... ... - * + * * +-------------+ +-------------+ +--------------+ * | X-Channel | | X-Channel | ... | X-Channel | * | [1][1] | | [2][1] | | [width-2][1] | * +-------------+ +-------------+ +--------------+ * * LEFT +-------------+ +-------------+ +--------------+ RIGHT - * SIDE | Grid | | Grid | ... | Grid | SIDE + * SIDE | Grid | | Grid | ... | Grid | SIDE * GRID | [1][1] | | [2][1] | | [width-2][1] | GRID * +-------------+ +-------------+ +--------------+ * @@ -133,9 +131,9 @@ size_t estimate_num_grid_rr_nodes_by_type(const DeviceGrid& grids, * * BOTTOM SIDE OF FPGA * - * The figure above describe how the X-direction routing channels are - * organized in a homogeneous FPGA fabric - * Note that we talk about general-purpose uni-directional routing architecture here + * The figure above describe how the X-direction routing channels are + * organized in a homogeneous FPGA fabric + * Note that we talk about general-purpose uni-directional routing architecture here * It means that a routing track may span across multiple grids * However, the hard limits are as follows * All the routing tracks will start at the most LEFT routing channel @@ -145,7 +143,7 @@ size_t estimate_num_grid_rr_nodes_by_type(const DeviceGrid& grids, * in the context of heterogeneous FPGAs * We may have a grid which span multiple column and rows, as exemplified in the figure below * In such case, - * all the routing tracks [x-1][y] at the left side of the grid [x][y] are forced to end + * all the routing tracks [x-1][y] at the left side of the grid [x][y] are forced to end * all the routing tracks [x+2][y] at the right side of the grid [x][y] are forced to start * And there are no routing tracks inside the grid[x][y] * It means that X-channel [x][y] & [x+1][y] will no exist @@ -173,52 +171,51 @@ size_t estimate_num_grid_rr_nodes_by_type(const DeviceGrid& grids, * * ***********************************************************************/ -static -size_t estimate_num_chanx_rr_nodes(const DeviceGrid& grids, - const size_t& chan_width, - const std::vector& segment_infs, - const bool& through_channel) { - size_t num_chanx_rr_nodes = 0; - - for (size_t iy = 0; iy < grids.height() - 1; ++iy) { - for (size_t ix = 1; ix < grids.width() - 1; ++ix) { - vtr::Point chanx_coord(ix, iy); - - /* Bypass if the routing channel does not exist when through channels are not allowed */ - if ( (false == through_channel) - && (false == is_chanx_exist(grids, chanx_coord))) { - continue; - } - - bool force_start = false; - bool force_end = false; - - /* All the tracks have to start when +static size_t estimate_num_chanx_rr_nodes(const DeviceGrid& grids, + const size_t& chan_width, + const std::vector& segment_infs, + const bool& through_channel) { + size_t num_chanx_rr_nodes = 0; + + for (size_t iy = 0; iy < grids.height() - 1; ++iy) { + for (size_t ix = 1; ix < grids.width() - 1; ++ix) { + vtr::Point chanx_coord(ix, iy); + + /* Bypass if the routing channel does not exist when through channels are not allowed */ + if ((false == through_channel) + && (false == is_chanx_exist(grids, chanx_coord))) { + continue; + } + + bool force_start = false; + bool force_end = false; + + /* All the tracks have to start when * - the routing channel touch the RIGHT side a heterogeneous block * - the routing channel touch the LEFT side of FPGA */ - if (true == is_chanx_right_to_multi_height_grid(grids, chanx_coord, through_channel)) { - force_start = true; - } + if (true == is_chanx_right_to_multi_height_grid(grids, chanx_coord, through_channel)) { + force_start = true; + } - /* All the tracks have to end when + /* All the tracks have to end when * - the routing channel touch the LEFT side a heterogeneous block * - the routing channel touch the RIGHT side of FPGA */ - if (true == is_chanx_left_to_multi_height_grid(grids, chanx_coord, through_channel)) { - force_end = true; - } - - /* Evaluate if the routing channel locates in the middle of a grid */ - ChanNodeDetails chanx_details = build_unidir_chan_node_details(chan_width, grids.width() - 2, force_start, force_end, segment_infs); - /* When an INC_DIRECTION CHANX starts, we need a new rr_node */ - num_chanx_rr_nodes += chanx_details.get_num_starting_tracks(Direction::INC); - /* When an DEC_DIRECTION CHANX ends, we need a new rr_node */ - num_chanx_rr_nodes += chanx_details.get_num_ending_tracks(Direction::DEC); + if (true == is_chanx_left_to_multi_height_grid(grids, chanx_coord, through_channel)) { + force_end = true; + } + + /* Evaluate if the routing channel locates in the middle of a grid */ + ChanNodeDetails chanx_details = build_unidir_chan_node_details(chan_width, grids.width() - 2, force_start, force_end, segment_infs); + /* When an INC_DIRECTION CHANX starts, we need a new rr_node */ + num_chanx_rr_nodes += chanx_details.get_num_starting_tracks(Direction::INC); + /* When an DEC_DIRECTION CHANX ends, we need a new rr_node */ + num_chanx_rr_nodes += chanx_details.get_num_ending_tracks(Direction::DEC); + } } - } - return num_chanx_rr_nodes; + return num_chanx_rr_nodes; } /************************************************************************ @@ -226,78 +223,74 @@ size_t estimate_num_chanx_rr_nodes(const DeviceGrid& grids, * The technical rationale is very similar to the X-direction routing channel * Refer to the detailed explanation there ***********************************************************************/ -static -size_t estimate_num_chany_rr_nodes(const DeviceGrid& grids, - const size_t& chan_width, - const std::vector& segment_infs, - const bool& through_channel) { - size_t num_chany_rr_nodes = 0; - - for (size_t ix = 0; ix < grids.width() - 1; ++ix) { - for (size_t iy = 1; iy < grids.height() - 1; ++iy) { - vtr::Point chany_coord(ix, iy); +static size_t estimate_num_chany_rr_nodes(const DeviceGrid& grids, + const size_t& chan_width, + const std::vector& segment_infs, + const bool& through_channel) { + size_t num_chany_rr_nodes = 0; - /* Bypass if the routing channel does not exist when through channel are not allowed */ - if ( (false == through_channel) - && (false == is_chany_exist(grids, chany_coord))) { - continue; - } + for (size_t ix = 0; ix < grids.width() - 1; ++ix) { + for (size_t iy = 1; iy < grids.height() - 1; ++iy) { + vtr::Point chany_coord(ix, iy); + /* Bypass if the routing channel does not exist when through channel are not allowed */ + if ((false == through_channel) + && (false == is_chany_exist(grids, chany_coord))) { + continue; + } - bool force_start = false; - bool force_end = false; + bool force_start = false; + bool force_end = false; - /* All the tracks have to start when + /* All the tracks have to start when * - the routing channel touch the TOP side a heterogeneous block * - the routing channel touch the BOTTOM side of FPGA */ - if (true == is_chany_top_to_multi_width_grid(grids, chany_coord, through_channel)) { - force_start = true; - } + if (true == is_chany_top_to_multi_width_grid(grids, chany_coord, through_channel)) { + force_start = true; + } - /* All the tracks have to end when + /* All the tracks have to end when * - the routing channel touch the BOTTOM side a heterogeneous block * - the routing channel touch the TOP side of FPGA */ - if (true == is_chany_bottom_to_multi_width_grid(grids, chany_coord, through_channel)) { - force_end = true; - } - - ChanNodeDetails chany_details = build_unidir_chan_node_details(chan_width, grids.height() - 2, force_start, force_end, segment_infs); - /* When an INC_DIRECTION CHANX starts, we need a new rr_node */ - num_chany_rr_nodes += chany_details.get_num_starting_tracks(Direction::INC); - /* When an DEC_DIRECTION CHANX ends, we need a new rr_node */ - num_chany_rr_nodes += chany_details.get_num_ending_tracks(Direction::DEC); + if (true == is_chany_bottom_to_multi_width_grid(grids, chany_coord, through_channel)) { + force_end = true; + } + + ChanNodeDetails chany_details = build_unidir_chan_node_details(chan_width, grids.height() - 2, force_start, force_end, segment_infs); + /* When an INC_DIRECTION CHANX starts, we need a new rr_node */ + num_chany_rr_nodes += chany_details.get_num_starting_tracks(Direction::INC); + /* When an DEC_DIRECTION CHANX ends, we need a new rr_node */ + num_chany_rr_nodes += chany_details.get_num_ending_tracks(Direction::DEC); + } } - } - return num_chany_rr_nodes; + return num_chany_rr_nodes; } /************************************************************************ * Estimate the number of nodes by each type in a routing resource graph ***********************************************************************/ -static -std::vector estimate_num_rr_nodes(const DeviceGrid& grids, - const vtr::Point& chan_width, - const std::vector& segment_infs, - const bool& through_channel) { - - /* Reset the OPIN, IPIN, SOURCE, SINK counter to be zero */ - std::vector num_rr_nodes_per_type(NUM_RR_TYPES, 0); - - /** +static std::vector estimate_num_rr_nodes(const DeviceGrid& grids, + const vtr::Point& chan_width, + const std::vector& segment_infs, + const bool& through_channel) { + /* Reset the OPIN, IPIN, SOURCE, SINK counter to be zero */ + std::vector num_rr_nodes_per_type(NUM_RR_TYPES, 0); + + /** * 1 Find number of rr nodes related to grids */ - num_rr_nodes_per_type[OPIN] = estimate_num_grid_rr_nodes_by_type(grids, OPIN); - num_rr_nodes_per_type[IPIN] = estimate_num_grid_rr_nodes_by_type(grids, IPIN); - num_rr_nodes_per_type[SOURCE] = estimate_num_grid_rr_nodes_by_type(grids, SOURCE); - num_rr_nodes_per_type[SINK] = estimate_num_grid_rr_nodes_by_type(grids, SINK); + num_rr_nodes_per_type[OPIN] = estimate_num_grid_rr_nodes_by_type(grids, OPIN); + num_rr_nodes_per_type[IPIN] = estimate_num_grid_rr_nodes_by_type(grids, IPIN); + num_rr_nodes_per_type[SOURCE] = estimate_num_grid_rr_nodes_by_type(grids, SOURCE); + num_rr_nodes_per_type[SINK] = estimate_num_grid_rr_nodes_by_type(grids, SINK); - /** + /** * 2. Assign the segments for each routing channel, * To be specific, for each routing track, we assign a routing segment. - * The assignment is subject to users' specifications, such as + * The assignment is subject to users' specifications, such as * a. length of each type of segment * b. frequency of each type of segment. * c. routing channel width @@ -305,697 +298,684 @@ std::vector estimate_num_rr_nodes(const DeviceGrid& grids, * SPECIAL for fringes: * All segments will start and ends with no exception * - * IMPORTANT: we should be aware that channel width maybe different + * IMPORTANT: we should be aware that channel width maybe different * in X-direction and Y-direction channels!!! - * So we will load segment details for different channels + * So we will load segment details for different channels */ - num_rr_nodes_per_type[CHANX] = estimate_num_chanx_rr_nodes(grids, - chan_width.x(), - segment_infs, - through_channel); - num_rr_nodes_per_type[CHANY] = estimate_num_chany_rr_nodes(grids, - chan_width.y(), - segment_infs, - through_channel); - - return num_rr_nodes_per_type; + num_rr_nodes_per_type[CHANX] = estimate_num_chanx_rr_nodes(grids, + chan_width.x(), + segment_infs, + through_channel); + num_rr_nodes_per_type[CHANY] = estimate_num_chany_rr_nodes(grids, + chan_width.y(), + segment_infs, + through_channel); + + return num_rr_nodes_per_type; } /************************************************************************ - * Allocate rr_nodes to a rr_graph object + * Allocate rr_nodes to a rr_graph object * This function just allocate the memory and ensure its efficiency * It will NOT fill detailed information for each node!!! * * Note: ensure that there are NO nodes in the rr_graph ***********************************************************************/ void alloc_tileable_rr_graph_nodes(RRGraphBuilder& rr_graph_builder, - vtr::vector& rr_node_driver_switches, + vtr::vector& rr_node_driver_switches, const DeviceGrid& grids, const vtr::Point& chan_width, const std::vector& segment_infs, const bool& through_channel) { - VTR_ASSERT(0 == rr_graph_builder.rr_nodes().size()); + VTR_ASSERT(0 == rr_graph_builder.rr_nodes().size()); - std::vector num_rr_nodes_per_type = estimate_num_rr_nodes(grids, - chan_width, - segment_infs, - through_channel); + std::vector num_rr_nodes_per_type = estimate_num_rr_nodes(grids, + chan_width, + segment_infs, + through_channel); - /* Reserve the number of node to be memory efficient */ - size_t num_nodes = 0; - for (const size_t& num_node_per_type : num_rr_nodes_per_type) { - num_nodes += num_node_per_type; - } + /* Reserve the number of node to be memory efficient */ + size_t num_nodes = 0; + for (const size_t& num_node_per_type : num_rr_nodes_per_type) { + num_nodes += num_node_per_type; + } - rr_graph_builder.reserve_nodes(num_nodes); + rr_graph_builder.reserve_nodes(num_nodes); - rr_node_driver_switches.reserve(num_nodes); + rr_node_driver_switches.reserve(num_nodes); } /************************************************************************ - * Configure OPIN rr_nodes for this grid - * coordinates: xlow, ylow, xhigh, yhigh, + * Configure OPIN rr_nodes for this grid + * coordinates: xlow, ylow, xhigh, yhigh, * features: capacity, ptc_num (pin_num), * * Note: this function should be applied ONLY to grid with 0 width offset and 0 height offset!!! ***********************************************************************/ -static -void load_one_grid_opin_nodes_basic_info(RRGraphBuilder& rr_graph_builder, - vtr::vector& rr_node_driver_switches, - const vtr::Point& grid_coordinate, - const t_grid_tile& cur_grid, - const e_side& io_side, - const RRSwitchId& delayless_switch) { - SideManager io_side_manager(io_side); - - /* Walk through the width height of each grid, +static void load_one_grid_opin_nodes_basic_info(RRGraphBuilder& rr_graph_builder, + vtr::vector& rr_node_driver_switches, + const vtr::Point& grid_coordinate, + const t_grid_tile& cur_grid, + const e_side& io_side, + const RRSwitchId& delayless_switch) { + SideManager io_side_manager(io_side); + + /* Walk through the width height of each grid, * get pins and configure the rr_nodes */ - for (int width = 0; width < cur_grid.type->width; ++width) { - for (int height = 0; height < cur_grid.type->height; ++height) { - /* Walk through sides */ - for (e_side side : SIDES) { - SideManager side_manager(side); - /* skip unwanted sides */ - if ( (true == is_io_type(cur_grid.type)) - && (side != io_side_manager.to_size_t()) && (NUM_SIDES != io_side) ) { - continue; - } - /* Find OPINs */ - /* Configure pins by pins */ - std::vector opin_list = get_grid_side_pins(cur_grid, DRIVER, side_manager.get_side(), - width, height); - for (const int& pin_num : opin_list) { - /* Create a new node and fill information */ - const RRNodeId& node = rr_graph_builder.node_lookup().find_node(width, height, OPIN, pin_num, side); - - /* node bounding box */ - rr_graph_builder.set_node_coordinates(node, grid_coordinate.x() + width, - grid_coordinate.y() + height, - grid_coordinate.x() + width, - grid_coordinate.y() + height); - rr_graph_builder.add_node_side(node, side_manager.get_side()); - rr_graph_builder.set_node_pin_num(node, pin_num); - - rr_graph_builder.set_node_capacity(node, 1); - - /* cost index is a FIXED value for OPIN */ - rr_graph_builder.set_node_cost_index(node, RRIndexedDataId(OPIN_COST_INDEX)); - - /* Switch info */ - VTR_ASSERT(size_t(node) == rr_node_driver_switches.size()); - rr_node_driver_switches.push_back(delayless_switch); - - /* RC data */ - rr_graph_builder.set_node_rc_index(node, NodeRCIndex(find_create_rr_rc_data(0., 0.))); - - } /* End of loading OPIN rr_nodes */ - } /* End of side enumeration */ - } /* End of height enumeration */ - } /* End of width enumeration */ - + for (int width = 0; width < cur_grid.type->width; ++width) { + for (int height = 0; height < cur_grid.type->height; ++height) { + /* Walk through sides */ + for (e_side side : SIDES) { + SideManager side_manager(side); + /* skip unwanted sides */ + if ((true == is_io_type(cur_grid.type)) + && (side != io_side_manager.to_size_t()) && (NUM_SIDES != io_side)) { + continue; + } + /* Find OPINs */ + /* Configure pins by pins */ + std::vector opin_list = get_grid_side_pins(cur_grid, DRIVER, side_manager.get_side(), + width, height); + for (const int& pin_num : opin_list) { + /* Create a new node and fill information */ + const RRNodeId& node = rr_graph_builder.node_lookup().find_node(width, height, OPIN, pin_num, side); + + /* node bounding box */ + rr_graph_builder.set_node_coordinates(node, grid_coordinate.x() + width, + grid_coordinate.y() + height, + grid_coordinate.x() + width, + grid_coordinate.y() + height); + rr_graph_builder.add_node_side(node, side_manager.get_side()); + rr_graph_builder.set_node_pin_num(node, pin_num); + + rr_graph_builder.set_node_capacity(node, 1); + + /* cost index is a FIXED value for OPIN */ + rr_graph_builder.set_node_cost_index(node, RRIndexedDataId(OPIN_COST_INDEX)); + + /* Switch info */ + VTR_ASSERT(size_t(node) == rr_node_driver_switches.size()); + rr_node_driver_switches.push_back(delayless_switch); + + /* RC data */ + rr_graph_builder.set_node_rc_index(node, NodeRCIndex(find_create_rr_rc_data(0., 0.))); + + } /* End of loading OPIN rr_nodes */ + } /* End of side enumeration */ + } /* End of height enumeration */ + } /* End of width enumeration */ } /************************************************************************ - * Configure IPIN rr_nodes for this grid - * coordinates: xlow, ylow, xhigh, yhigh, + * Configure IPIN rr_nodes for this grid + * coordinates: xlow, ylow, xhigh, yhigh, * features: capacity, ptc_num (pin_num), * * Note: this function should be applied ONLY to grid with 0 width offset and 0 height offset!!! ***********************************************************************/ -static -void load_one_grid_ipin_nodes_basic_info(RRGraphBuilder& rr_graph_builder, - vtr::vector& rr_node_driver_switches, - const vtr::Point& grid_coordinate, - const t_grid_tile& cur_grid, - const e_side& io_side, - const RRSwitchId& wire_to_ipin_switch) { - SideManager io_side_manager(io_side); - - /* Walk through the width and height of each grid, +static void load_one_grid_ipin_nodes_basic_info(RRGraphBuilder& rr_graph_builder, + vtr::vector& rr_node_driver_switches, + const vtr::Point& grid_coordinate, + const t_grid_tile& cur_grid, + const e_side& io_side, + const RRSwitchId& wire_to_ipin_switch) { + SideManager io_side_manager(io_side); + + /* Walk through the width and height of each grid, * get pins and configure the rr_nodes */ - for (int width = 0; width < cur_grid.type->width; ++width) { - for (int height = 0; height < cur_grid.type->height; ++height) { - /* Walk through sides */ - for (e_side side : SIDES) { - SideManager side_manager(side); - /* skip unwanted sides */ - if ( (true == is_io_type(cur_grid.type)) - && (side != io_side_manager.to_size_t()) && (NUM_SIDES != io_side) ) { - continue; - } - - /* Find IPINs */ - /* Configure pins by pins */ - std::vector ipin_list = get_grid_side_pins(cur_grid, RECEIVER, side_manager.get_side(), width, height); - for (const int& pin_num : ipin_list) { - /* Create a new node and fill information */ - const RRNodeId& node = rr_graph_builder.node_lookup().find_node(width, height, IPIN, pin_num, side); - - /* node bounding box */ - rr_graph_builder.set_node_coordinates(node, grid_coordinate.x() + width, - grid_coordinate.y() + height, - grid_coordinate.x() + width, - grid_coordinate.y() + height); - rr_graph_builder.add_node_side(node, side_manager.get_side()); - rr_graph_builder.set_node_pin_num(node, pin_num); - - rr_graph_builder.set_node_capacity(node, 1); - - /* cost index is a FIXED value for OPIN */ - rr_graph_builder.set_node_cost_index(node, RRIndexedDataId(IPIN_COST_INDEX)); - - /* Switch info */ - VTR_ASSERT(size_t(node) == rr_node_driver_switches.size()); - rr_node_driver_switches.push_back(wire_to_ipin_switch); - - /* RC data */ - rr_graph_builder.set_node_rc_index(node, NodeRCIndex(find_create_rr_rc_data(0., 0.))); - - } /* End of loading IPIN rr_nodes */ - } /* End of side enumeration */ - } /* End of height enumeration */ - } /* End of width enumeration */ + for (int width = 0; width < cur_grid.type->width; ++width) { + for (int height = 0; height < cur_grid.type->height; ++height) { + /* Walk through sides */ + for (e_side side : SIDES) { + SideManager side_manager(side); + /* skip unwanted sides */ + if ((true == is_io_type(cur_grid.type)) + && (side != io_side_manager.to_size_t()) && (NUM_SIDES != io_side)) { + continue; + } + + /* Find IPINs */ + /* Configure pins by pins */ + std::vector ipin_list = get_grid_side_pins(cur_grid, RECEIVER, side_manager.get_side(), width, height); + for (const int& pin_num : ipin_list) { + /* Create a new node and fill information */ + const RRNodeId& node = rr_graph_builder.node_lookup().find_node(width, height, IPIN, pin_num, side); + + /* node bounding box */ + rr_graph_builder.set_node_coordinates(node, grid_coordinate.x() + width, + grid_coordinate.y() + height, + grid_coordinate.x() + width, + grid_coordinate.y() + height); + rr_graph_builder.add_node_side(node, side_manager.get_side()); + rr_graph_builder.set_node_pin_num(node, pin_num); + + rr_graph_builder.set_node_capacity(node, 1); + + /* cost index is a FIXED value for OPIN */ + rr_graph_builder.set_node_cost_index(node, RRIndexedDataId(IPIN_COST_INDEX)); + + /* Switch info */ + VTR_ASSERT(size_t(node) == rr_node_driver_switches.size()); + rr_node_driver_switches.push_back(wire_to_ipin_switch); + + /* RC data */ + rr_graph_builder.set_node_rc_index(node, NodeRCIndex(find_create_rr_rc_data(0., 0.))); + + } /* End of loading IPIN rr_nodes */ + } /* End of side enumeration */ + } /* End of height enumeration */ + } /* End of width enumeration */ } /************************************************************************ - * Configure SOURCE rr_nodes for this grid - * coordinates: xlow, ylow, xhigh, yhigh, + * Configure SOURCE rr_nodes for this grid + * coordinates: xlow, ylow, xhigh, yhigh, * features: capacity, ptc_num (pin_num), * * Note: this function should be applied ONLY to grid with 0 width offset and 0 height offset!!! ***********************************************************************/ -static -void load_one_grid_source_nodes_basic_info(RRGraphBuilder& rr_graph_builder, - vtr::vector& rr_node_driver_switches, - const vtr::Point& grid_coordinate, - const t_grid_tile& cur_grid, - const e_side& io_side, - const RRSwitchId& delayless_switch) { - SideManager io_side_manager(io_side); - - /* Set a SOURCE rr_node for each DRIVER class */ - for (int iclass = 0; iclass < cur_grid.type->num_class; ++iclass) { - /* Set a SINK rr_node for the OPIN */ - if (DRIVER != cur_grid.type->class_inf[iclass].type) { - continue; - } - - /* Create a new node and fill information */ - const RRNodeId& node = rr_graph_builder.node_lookup().find_node(grid_coordinate.x(), grid_coordinate.y(), SOURCE, iclass); - - /* node bounding box */ - rr_graph_builder.set_node_coordinates(node, grid_coordinate.x(), - grid_coordinate.y(), - grid_coordinate.x() + cur_grid.type->width - 1, - grid_coordinate.y() + cur_grid.type->height - 1); - rr_graph_builder.set_node_class_num(node, iclass); - - rr_graph_builder.set_node_capacity(node, 1); - - /* The capacity should be the number of pins in this class*/ - rr_graph_builder.set_node_capacity(node, cur_grid.type->class_inf[iclass].num_pins); - - /* cost index is a FIXED value for SOURCE */ - rr_graph_builder.set_node_cost_index(node, RRIndexedDataId(SOURCE_COST_INDEX)); - - /* Switch info */ - VTR_ASSERT(size_t(node) == rr_node_driver_switches.size()); - rr_node_driver_switches.push_back(delayless_switch); - - /* RC data */ - rr_graph_builder.set_node_rc_index(node, NodeRCIndex(find_create_rr_rc_data(0., 0.))); - - } /* End of class enumeration */ +static void load_one_grid_source_nodes_basic_info(RRGraphBuilder& rr_graph_builder, + vtr::vector& rr_node_driver_switches, + const vtr::Point& grid_coordinate, + const t_grid_tile& cur_grid, + const e_side& io_side, + const RRSwitchId& delayless_switch) { + SideManager io_side_manager(io_side); + + /* Set a SOURCE rr_node for each DRIVER class */ + for (int iclass = 0; iclass < cur_grid.type->num_class; ++iclass) { + /* Set a SINK rr_node for the OPIN */ + if (DRIVER != cur_grid.type->class_inf[iclass].type) { + continue; + } + + /* Create a new node and fill information */ + const RRNodeId& node = rr_graph_builder.node_lookup().find_node(grid_coordinate.x(), grid_coordinate.y(), SOURCE, iclass); + + /* node bounding box */ + rr_graph_builder.set_node_coordinates(node, grid_coordinate.x(), + grid_coordinate.y(), + grid_coordinate.x() + cur_grid.type->width - 1, + grid_coordinate.y() + cur_grid.type->height - 1); + rr_graph_builder.set_node_class_num(node, iclass); + + rr_graph_builder.set_node_capacity(node, 1); + + /* The capacity should be the number of pins in this class*/ + rr_graph_builder.set_node_capacity(node, cur_grid.type->class_inf[iclass].num_pins); + + /* cost index is a FIXED value for SOURCE */ + rr_graph_builder.set_node_cost_index(node, RRIndexedDataId(SOURCE_COST_INDEX)); + + /* Switch info */ + VTR_ASSERT(size_t(node) == rr_node_driver_switches.size()); + rr_node_driver_switches.push_back(delayless_switch); + + /* RC data */ + rr_graph_builder.set_node_rc_index(node, NodeRCIndex(find_create_rr_rc_data(0., 0.))); + + } /* End of class enumeration */ } /************************************************************************ - * Configure SINK rr_nodes for this grid - * coordinates: xlow, ylow, xhigh, yhigh, + * Configure SINK rr_nodes for this grid + * coordinates: xlow, ylow, xhigh, yhigh, * features: capacity, ptc_num (pin_num), * * Note: this function should be applied ONLY to grid with 0 width offset and 0 height offset!!! ***********************************************************************/ -static -void load_one_grid_sink_nodes_basic_info(RRGraphBuilder& rr_graph_builder, - vtr::vector& rr_node_driver_switches, - const vtr::Point& grid_coordinate, - const t_grid_tile& cur_grid, - const e_side& io_side, - const RRSwitchId& delayless_switch) { - SideManager io_side_manager(io_side); - - /* Set a SINK rr_node for each RECEIVER class */ - for (int iclass = 0; iclass < cur_grid.type->num_class; ++iclass) { - /* Set a SINK rr_node for the OPIN */ - if (RECEIVER != cur_grid.type->class_inf[iclass].type) { - continue; - } +static void load_one_grid_sink_nodes_basic_info(RRGraphBuilder& rr_graph_builder, + vtr::vector& rr_node_driver_switches, + const vtr::Point& grid_coordinate, + const t_grid_tile& cur_grid, + const e_side& io_side, + const RRSwitchId& delayless_switch) { + SideManager io_side_manager(io_side); + + /* Set a SINK rr_node for each RECEIVER class */ + for (int iclass = 0; iclass < cur_grid.type->num_class; ++iclass) { + /* Set a SINK rr_node for the OPIN */ + if (RECEIVER != cur_grid.type->class_inf[iclass].type) { + continue; + } - /* Create a new node and fill information */ - const RRNodeId& node = rr_graph_builder.node_lookup().find_node(grid_coordinate.x(), grid_coordinate.y(), SINK, iclass); + /* Create a new node and fill information */ + const RRNodeId& node = rr_graph_builder.node_lookup().find_node(grid_coordinate.x(), grid_coordinate.y(), SINK, iclass); - /* node bounding box */ - rr_graph_builder.set_node_coordinates(node, grid_coordinate.x(), - grid_coordinate.y(), - grid_coordinate.x() + cur_grid.type->width - 1, - grid_coordinate.y() + cur_grid.type->height - 1); - rr_graph_builder.set_node_class_num(node, iclass); + /* node bounding box */ + rr_graph_builder.set_node_coordinates(node, grid_coordinate.x(), + grid_coordinate.y(), + grid_coordinate.x() + cur_grid.type->width - 1, + grid_coordinate.y() + cur_grid.type->height - 1); + rr_graph_builder.set_node_class_num(node, iclass); - rr_graph_builder.set_node_capacity(node, 1); + rr_graph_builder.set_node_capacity(node, 1); - /* The capacity should be the number of pins in this class*/ - rr_graph_builder.set_node_capacity(node, cur_grid.type->class_inf[iclass].num_pins); + /* The capacity should be the number of pins in this class*/ + rr_graph_builder.set_node_capacity(node, cur_grid.type->class_inf[iclass].num_pins); - /* cost index is a FIXED value for SINK */ - rr_graph_builder.set_node_cost_index(node, RRIndexedDataId(SINK_COST_INDEX)); + /* cost index is a FIXED value for SINK */ + rr_graph_builder.set_node_cost_index(node, RRIndexedDataId(SINK_COST_INDEX)); - /* Switch info */ - VTR_ASSERT(size_t(node) == rr_node_driver_switches.size()); - rr_node_driver_switches.push_back(delayless_switch); + /* Switch info */ + VTR_ASSERT(size_t(node) == rr_node_driver_switches.size()); + rr_node_driver_switches.push_back(delayless_switch); - /* RC data */ - rr_graph_builder.set_node_rc_index(node, NodeRCIndex(find_create_rr_rc_data(0., 0.))); + /* RC data */ + rr_graph_builder.set_node_rc_index(node, NodeRCIndex(find_create_rr_rc_data(0., 0.))); - } /* End of class enumeration */ + } /* End of class enumeration */ } /************************************************************************ * Create all the rr_nodes for grids ***********************************************************************/ -static -void load_grid_nodes_basic_info(RRGraphBuilder& rr_graph_builder, - vtr::vector& rr_node_driver_switches, - const DeviceGrid& grids, - const RRSwitchId& wire_to_ipin_switch, - const RRSwitchId& delayless_switch) { - - for (size_t iy = 0; iy < grids.height(); ++iy) { - for (size_t ix = 0; ix < grids.width(); ++ix) { - /* Skip EMPTY tiles */ - if (true == is_empty_type(grids[ix][iy].type)) { - continue; - } - - /* We only build rr_nodes for grids with width_offset = 0 and height_offset = 0 */ - if ( (0 < grids[ix][iy].width_offset) - || (0 < grids[ix][iy].height_offset) ) { - continue; - } - - vtr::Point grid_coordinate(ix, iy); - enum e_side io_side = NUM_SIDES; - - /* If this is the block on borders, we consider IO side */ - if (true == is_io_type(grids[ix][iy].type)) { - vtr::Point io_device_size(grids.width() - 1, grids.height() - 1); - io_side = determine_io_grid_pin_side(io_device_size, grid_coordinate); - } - - /* Configure source rr_nodes for this grid */ - load_one_grid_source_nodes_basic_info(rr_graph_builder, - rr_node_driver_switches, - grid_coordinate, - grids[ix][iy], - io_side, - delayless_switch); - - /* Configure sink rr_nodes for this grid */ - load_one_grid_sink_nodes_basic_info(rr_graph_builder, - rr_node_driver_switches, - grid_coordinate, - grids[ix][iy], - io_side, - delayless_switch); - - /* Configure opin rr_nodes for this grid */ - load_one_grid_opin_nodes_basic_info(rr_graph_builder, - rr_node_driver_switches, - grid_coordinate, - grids[ix][iy], - io_side, - delayless_switch); - - /* Configure ipin rr_nodes for this grid */ - load_one_grid_ipin_nodes_basic_info(rr_graph_builder, - rr_node_driver_switches, - grid_coordinate, - grids[ix][iy], - io_side, - wire_to_ipin_switch); - +static void load_grid_nodes_basic_info(RRGraphBuilder& rr_graph_builder, + vtr::vector& rr_node_driver_switches, + const DeviceGrid& grids, + const RRSwitchId& wire_to_ipin_switch, + const RRSwitchId& delayless_switch) { + for (size_t iy = 0; iy < grids.height(); ++iy) { + for (size_t ix = 0; ix < grids.width(); ++ix) { + /* Skip EMPTY tiles */ + if (true == is_empty_type(grids[ix][iy].type)) { + continue; + } + + /* We only build rr_nodes for grids with width_offset = 0 and height_offset = 0 */ + if ((0 < grids[ix][iy].width_offset) + || (0 < grids[ix][iy].height_offset)) { + continue; + } + + vtr::Point grid_coordinate(ix, iy); + enum e_side io_side = NUM_SIDES; + + /* If this is the block on borders, we consider IO side */ + if (true == is_io_type(grids[ix][iy].type)) { + vtr::Point io_device_size(grids.width() - 1, grids.height() - 1); + io_side = determine_io_grid_pin_side(io_device_size, grid_coordinate); + } + + /* Configure source rr_nodes for this grid */ + load_one_grid_source_nodes_basic_info(rr_graph_builder, + rr_node_driver_switches, + grid_coordinate, + grids[ix][iy], + io_side, + delayless_switch); + + /* Configure sink rr_nodes for this grid */ + load_one_grid_sink_nodes_basic_info(rr_graph_builder, + rr_node_driver_switches, + grid_coordinate, + grids[ix][iy], + io_side, + delayless_switch); + + /* Configure opin rr_nodes for this grid */ + load_one_grid_opin_nodes_basic_info(rr_graph_builder, + rr_node_driver_switches, + grid_coordinate, + grids[ix][iy], + io_side, + delayless_switch); + + /* Configure ipin rr_nodes for this grid */ + load_one_grid_ipin_nodes_basic_info(rr_graph_builder, + rr_node_driver_switches, + grid_coordinate, + grids[ix][iy], + io_side, + wire_to_ipin_switch); + } } - } } /************************************************************************ * Initialize the basic information of routing track rr_nodes - * coordinates: xlow, ylow, xhigh, yhigh, - * features: capacity, track_ids, ptc_num, direction + * coordinates: xlow, ylow, xhigh, yhigh, + * features: capacity, track_ids, ptc_num, direction ***********************************************************************/ -static -void load_one_chan_rr_nodes_basic_info(RRGraphView& rr_graph, - RRGraphBuilder& rr_graph_builder, - vtr::vector& rr_node_driver_switches, - std::map>& rr_node_track_ids, - const vtr::Point& chan_coordinate, - const t_rr_type& chan_type, - ChanNodeDetails& chan_details, - const std::vector& segment_infs, - const int& cost_index_offset) { - /* Check each node_id(potential ptc_num) in the channel : +static void load_one_chan_rr_nodes_basic_info(RRGraphView& rr_graph, + RRGraphBuilder& rr_graph_builder, + vtr::vector& rr_node_driver_switches, + std::map>& rr_node_track_ids, + const vtr::Point& chan_coordinate, + const t_rr_type& chan_type, + ChanNodeDetails& chan_details, + const std::vector& segment_infs, + const int& cost_index_offset) { + /* Check each node_id(potential ptc_num) in the channel : * If this is a starting point, we set a new rr_node with xlow/ylow, ptc_num * If this is a ending point, we set xhigh/yhigh and track_ids * For other nodes, we set changes in track_ids */ - for (size_t itrack = 0; itrack < chan_details.get_chan_width(); ++itrack) { - /* For INC direction, a starting point requires a new chan rr_node */ - if ( ( (true == chan_details.is_track_start(itrack)) - && (Direction::INC == chan_details.get_track_direction(itrack)) ) - /* For DEC direction, an ending point requires a new chan rr_node */ - || - ( (true == chan_details.is_track_end(itrack)) - && (Direction::DEC == chan_details.get_track_direction(itrack)) ) ) { - - /* Create a new chan rr_node */ - const RRNodeId& node = rr_graph_builder.node_lookup().find_node(chan_coordinate.x(), chan_coordinate.y(), chan_type, itrack); - - rr_graph_builder.set_node_direction(node, chan_details.get_track_direction(itrack)); - rr_graph_builder.set_node_track_num(node, itrack); - rr_node_track_ids[node].push_back(itrack); - - rr_graph_builder.set_node_capacity(node, 1); - - /* assign switch id */ - size_t seg_id = chan_details.get_track_segment_id(itrack); - VTR_ASSERT(size_t(node) == rr_node_driver_switches.size()); - rr_node_driver_switches.push_back(RRSwitchId(segment_infs[seg_id].arch_opin_switch)); - - /* Update chan_details with node_id */ - chan_details.set_track_node_id(itrack, size_t(node)); - - /* cost index depends on the segment index */ - rr_graph_builder.set_node_cost_index(node, RRIndexedDataId(cost_index_offset + seg_id)); - /* Finish here, go to next */ - } + for (size_t itrack = 0; itrack < chan_details.get_chan_width(); ++itrack) { + /* For INC direction, a starting point requires a new chan rr_node */ + if (((true == chan_details.is_track_start(itrack)) + && (Direction::INC == chan_details.get_track_direction(itrack))) + /* For DEC direction, an ending point requires a new chan rr_node */ + || ((true == chan_details.is_track_end(itrack)) + && (Direction::DEC == chan_details.get_track_direction(itrack)))) { + /* Create a new chan rr_node */ + const RRNodeId& node = rr_graph_builder.node_lookup().find_node(chan_coordinate.x(), chan_coordinate.y(), chan_type, itrack); + + rr_graph_builder.set_node_direction(node, chan_details.get_track_direction(itrack)); + rr_graph_builder.set_node_track_num(node, itrack); + rr_node_track_ids[node].push_back(itrack); + + rr_graph_builder.set_node_capacity(node, 1); + + /* assign switch id */ + size_t seg_id = chan_details.get_track_segment_id(itrack); + VTR_ASSERT(size_t(node) == rr_node_driver_switches.size()); + rr_node_driver_switches.push_back(RRSwitchId(segment_infs[seg_id].arch_opin_switch)); + + /* Update chan_details with node_id */ + chan_details.set_track_node_id(itrack, size_t(node)); + + /* cost index depends on the segment index */ + rr_graph_builder.set_node_cost_index(node, RRIndexedDataId(cost_index_offset + seg_id)); + /* Finish here, go to next */ + } - /* For INC direction, an ending point requires an update on xhigh and yhigh */ - if ( ( (true == chan_details.is_track_end(itrack)) - && (Direction::INC == chan_details.get_track_direction(itrack)) ) - || - /* For DEC direction, an starting point requires an update on xlow and ylow */ - ( (true == chan_details.is_track_start(itrack)) - && (Direction::DEC == chan_details.get_track_direction(itrack)) ) ) { - - /* Get the node_id */ - const RRNodeId& rr_node_id = RRNodeId(chan_details.get_track_node_id(itrack)); - - /* Do a quick check, make sure we do not mistakenly modify other nodes */ - VTR_ASSERT(chan_type == rr_graph.node_type(rr_node_id)); - VTR_ASSERT(chan_details.get_track_direction(itrack) == rr_graph.node_direction(rr_node_id)); - - /* set xhigh/yhigh and push changes to track_ids */ - rr_graph_builder.set_node_coordinates(rr_node_id, rr_graph.node_xlow(rr_node_id), - rr_graph.node_ylow(rr_node_id), - chan_coordinate.x(), - chan_coordinate.y()); - - /* Do not update track_ids for length-1 wires, they should have only 1 track_id */ - if ( (rr_graph.node_xhigh(rr_node_id) > rr_graph.node_xlow(rr_node_id)) - || (rr_graph.node_yhigh(rr_node_id) > rr_graph.node_ylow(rr_node_id)) ) { - rr_node_track_ids[rr_node_id].push_back(itrack); - rr_graph_builder.set_node_track_num(rr_node_id, itrack); - } - /* Finish here, go to next */ - } + /* For INC direction, an ending point requires an update on xhigh and yhigh */ + if (((true == chan_details.is_track_end(itrack)) + && (Direction::INC == chan_details.get_track_direction(itrack))) + || + /* For DEC direction, an starting point requires an update on xlow and ylow */ + ((true == chan_details.is_track_start(itrack)) + && (Direction::DEC == chan_details.get_track_direction(itrack)))) { + /* Get the node_id */ + const RRNodeId& rr_node_id = RRNodeId(chan_details.get_track_node_id(itrack)); + + /* Do a quick check, make sure we do not mistakenly modify other nodes */ + VTR_ASSERT(chan_type == rr_graph.node_type(rr_node_id)); + VTR_ASSERT(chan_details.get_track_direction(itrack) == rr_graph.node_direction(rr_node_id)); + + /* set xhigh/yhigh and push changes to track_ids */ + rr_graph_builder.set_node_coordinates(rr_node_id, rr_graph.node_xlow(rr_node_id), + rr_graph.node_ylow(rr_node_id), + chan_coordinate.x(), + chan_coordinate.y()); + + /* Do not update track_ids for length-1 wires, they should have only 1 track_id */ + if ((rr_graph.node_xhigh(rr_node_id) > rr_graph.node_xlow(rr_node_id)) + || (rr_graph.node_yhigh(rr_node_id) > rr_graph.node_ylow(rr_node_id))) { + rr_node_track_ids[rr_node_id].push_back(itrack); + rr_graph_builder.set_node_track_num(rr_node_id, itrack); + } + /* Finish here, go to next */ + } - /* Finish processing starting and ending tracks */ - if ( (true == chan_details.is_track_start(itrack)) - || (true == chan_details.is_track_end(itrack)) ) { - /* Finish here, go to next */ - continue; - } + /* Finish processing starting and ending tracks */ + if ((true == chan_details.is_track_start(itrack)) + || (true == chan_details.is_track_end(itrack))) { + /* Finish here, go to next */ + continue; + } - /* For other nodes, we get the node_id and just update track_ids */ - /* Ensure those nodes are neither starting nor ending points */ - VTR_ASSERT( (false == chan_details.is_track_start(itrack)) - && (false == chan_details.is_track_end(itrack)) ); + /* For other nodes, we get the node_id and just update track_ids */ + /* Ensure those nodes are neither starting nor ending points */ + VTR_ASSERT((false == chan_details.is_track_start(itrack)) + && (false == chan_details.is_track_end(itrack))); - /* Get the node_id */ - const RRNodeId& rr_node_id = RRNodeId(chan_details.get_track_node_id(itrack)); + /* Get the node_id */ + const RRNodeId& rr_node_id = RRNodeId(chan_details.get_track_node_id(itrack)); - /* Do a quick check, make sure we do not mistakenly modify other nodes */ - VTR_ASSERT(chan_type == rr_graph.node_type(rr_node_id)); - VTR_ASSERT(chan_details.get_track_direction(itrack) == rr_graph.node_direction(rr_node_id)); + /* Do a quick check, make sure we do not mistakenly modify other nodes */ + VTR_ASSERT(chan_type == rr_graph.node_type(rr_node_id)); + VTR_ASSERT(chan_details.get_track_direction(itrack) == rr_graph.node_direction(rr_node_id)); - /* Deposit xhigh and yhigh using the current chan_coordinate + /* Deposit xhigh and yhigh using the current chan_coordinate * We will update when this track ends */ - rr_graph_builder.set_node_coordinates(rr_node_id, rr_graph.node_xlow(rr_node_id), - rr_graph.node_ylow(rr_node_id), - chan_coordinate.x(), - chan_coordinate.y()); - - /* Update track_ids */ - rr_node_track_ids[rr_node_id].push_back(itrack); - rr_graph_builder.set_node_track_num(rr_node_id, itrack); - /* Finish here, go to next */ - } -} + rr_graph_builder.set_node_coordinates(rr_node_id, rr_graph.node_xlow(rr_node_id), + rr_graph.node_ylow(rr_node_id), + chan_coordinate.x(), + chan_coordinate.y()); + + /* Update track_ids */ + rr_node_track_ids[rr_node_id].push_back(itrack); + rr_graph_builder.set_node_track_num(rr_node_id, itrack); + /* Finish here, go to next */ + } +} /************************************************************************ * Initialize the basic information of X-channel rr_nodes: - * coordinates: xlow, ylow, xhigh, yhigh, - * features: capacity, track_ids, ptc_num, direction + * coordinates: xlow, ylow, xhigh, yhigh, + * features: capacity, track_ids, ptc_num, direction * grid_info : pb_graph_pin ***********************************************************************/ -static -void load_chanx_rr_nodes_basic_info(RRGraphView& rr_graph, - RRGraphBuilder& rr_graph_builder, - vtr::vector& rr_node_driver_switches, - std::map>& rr_node_track_ids, - const DeviceGrid& grids, - const size_t& chan_width, - const std::vector& segment_infs, - const bool& through_channel) { - - /* For X-direction Channel: CHANX */ - for (size_t iy = 0; iy < grids.height() - 1; ++iy) { - /* Keep a vector of node_ids for the channels, because we will rotate them when walking through ix */ - std::vector track_node_ids; - - for (size_t ix = 1; ix < grids.width() - 1; ++ix) { - vtr::Point chanx_coord(ix, iy); - - /* Bypass if the routing channel does not exist when through channels are not allowed */ - if ( (false == through_channel) - && (false == is_chanx_exist(grids, chanx_coord))) { - continue; - } - - bool force_start = false; - bool force_end = false; - - /* All the tracks have to start when +static void load_chanx_rr_nodes_basic_info(RRGraphView& rr_graph, + RRGraphBuilder& rr_graph_builder, + vtr::vector& rr_node_driver_switches, + std::map>& rr_node_track_ids, + const DeviceGrid& grids, + const size_t& chan_width, + const std::vector& segment_infs, + const bool& through_channel) { + /* For X-direction Channel: CHANX */ + for (size_t iy = 0; iy < grids.height() - 1; ++iy) { + /* Keep a vector of node_ids for the channels, because we will rotate them when walking through ix */ + std::vector track_node_ids; + + for (size_t ix = 1; ix < grids.width() - 1; ++ix) { + vtr::Point chanx_coord(ix, iy); + + /* Bypass if the routing channel does not exist when through channels are not allowed */ + if ((false == through_channel) + && (false == is_chanx_exist(grids, chanx_coord))) { + continue; + } + + bool force_start = false; + bool force_end = false; + + /* All the tracks have to start when * - the routing channel touch the RIGHT side a heterogeneous block * - the routing channel touch the LEFT side of FPGA */ - if (true == is_chanx_right_to_multi_height_grid(grids, chanx_coord, through_channel)) { - force_start = true; - } + if (true == is_chanx_right_to_multi_height_grid(grids, chanx_coord, through_channel)) { + force_start = true; + } - /* All the tracks have to end when + /* All the tracks have to end when * - the routing channel touch the LEFT side a heterogeneous block * - the routing channel touch the RIGHT side of FPGA */ - if (true == is_chanx_left_to_multi_height_grid(grids, chanx_coord, through_channel)) { - force_end = true; - } - - ChanNodeDetails chanx_details = build_unidir_chan_node_details(chan_width, grids.width() - 2, - force_start, force_end, segment_infs); - /* Force node_ids from the previous chanx */ - if (0 < track_node_ids.size()) { - /* Rotate should be done based on a typical case of routing tracks. - * Tracks on the borders are not regularly started and ended, - * which causes the node_rotation malfunction + if (true == is_chanx_left_to_multi_height_grid(grids, chanx_coord, through_channel)) { + force_end = true; + } + + ChanNodeDetails chanx_details = build_unidir_chan_node_details(chan_width, grids.width() - 2, + force_start, force_end, segment_infs); + /* Force node_ids from the previous chanx */ + if (0 < track_node_ids.size()) { + /* Rotate should be done based on a typical case of routing tracks. + * Tracks on the borders are not regularly started and ended, + * which causes the node_rotation malfunction */ - ChanNodeDetails chanx_details_tt = build_unidir_chan_node_details(chan_width, grids.width() - 2, - false, false, segment_infs); - chanx_details_tt.set_track_node_ids(track_node_ids); + ChanNodeDetails chanx_details_tt = build_unidir_chan_node_details(chan_width, grids.width() - 2, + false, false, segment_infs); + chanx_details_tt.set_track_node_ids(track_node_ids); - /* TODO: - * Do NOT rotate the tracks when the routing channel + /* TODO: + * Do NOT rotate the tracks when the routing channel * locates inside a multi-height and multi-width grid - * Let the routing channel passing through the grid (if through channel is allowed!) + * Let the routing channel passing through the grid (if through channel is allowed!) * An example: - * + * * +------------------------------ * | | * | Grid | * track0 ----->+-----------------------------+----> track0 * | | */ - if (true == is_chanx_exist(grids, chanx_coord, through_channel)) { - /* Rotate the chanx_details by an offset of ix - 1, the distance to the most left channel */ - /* For INC_DIRECTION, we use clockwise rotation + if (true == is_chanx_exist(grids, chanx_coord, through_channel)) { + /* Rotate the chanx_details by an offset of ix - 1, the distance to the most left channel */ + /* For INC_DIRECTION, we use clockwise rotation * node_id A ----> -----> node_id D * node_id B ----> / ----> node_id A * node_id C ----> / ----> node_id B - * node_id D ----> ----> node_id C + * node_id D ----> ----> node_id C */ - chanx_details_tt.rotate_track_node_id(1, Direction::INC, true); - /* For DEC_DIRECTION, we use clockwise rotation + chanx_details_tt.rotate_track_node_id(1, Direction::INC, true); + /* For DEC_DIRECTION, we use clockwise rotation * node_id A <----- <----- node_id B * node_id B <----- \ <----- node_id C * node_id C <----- \ <----- node_id D - * node_id D <----- <----- node_id A + * node_id D <----- <----- node_id A */ - chanx_details_tt.rotate_track_node_id(1, Direction::DEC, false); - } - - track_node_ids = chanx_details_tt.get_track_node_ids(); - chanx_details.set_track_node_ids(track_node_ids); - } - - /* Configure CHANX in this channel */ - load_one_chan_rr_nodes_basic_info(rr_graph, - rr_graph_builder, - rr_node_driver_switches, - rr_node_track_ids, - chanx_coord, CHANX, - chanx_details, - segment_infs, - CHANX_COST_INDEX_START); - /* Get a copy of node_ids */ - track_node_ids = chanx_details.get_track_node_ids(); + chanx_details_tt.rotate_track_node_id(1, Direction::DEC, false); + } + + track_node_ids = chanx_details_tt.get_track_node_ids(); + chanx_details.set_track_node_ids(track_node_ids); + } + + /* Configure CHANX in this channel */ + load_one_chan_rr_nodes_basic_info(rr_graph, + rr_graph_builder, + rr_node_driver_switches, + rr_node_track_ids, + chanx_coord, CHANX, + chanx_details, + segment_infs, + CHANX_COST_INDEX_START); + /* Get a copy of node_ids */ + track_node_ids = chanx_details.get_track_node_ids(); + } } - } } /************************************************************************ * Initialize the basic information of Y-channel rr_nodes: - * coordinates: xlow, ylow, xhigh, yhigh, - * features: capacity, track_ids, ptc_num, direction + * coordinates: xlow, ylow, xhigh, yhigh, + * features: capacity, track_ids, ptc_num, direction ***********************************************************************/ -static -void load_chany_rr_nodes_basic_info(RRGraphView& rr_graph, - RRGraphBuilder& rr_graph_builder, - vtr::vector& rr_node_driver_switches, - std::map>& rr_node_track_ids, - const DeviceGrid& grids, - const size_t& chan_width, - const std::vector& segment_infs, - const bool& through_channel) { - - /* For Y-direction Channel: CHANY */ - for (size_t ix = 0; ix < grids.width() - 1; ++ix) { - /* Keep a vector of node_ids for the channels, because we will rotate them when walking through ix */ - std::vector track_node_ids; - - for (size_t iy = 1; iy < grids.height() - 1; ++iy) { - vtr::Point chany_coord(ix, iy); - - /* Bypass if the routing channel does not exist when through channel are not allowed */ - if ( (false == through_channel) - && (false == is_chany_exist(grids, chany_coord))) { - continue; - } - - bool force_start = false; - bool force_end = false; - - /* All the tracks have to start when +static void load_chany_rr_nodes_basic_info(RRGraphView& rr_graph, + RRGraphBuilder& rr_graph_builder, + vtr::vector& rr_node_driver_switches, + std::map>& rr_node_track_ids, + const DeviceGrid& grids, + const size_t& chan_width, + const std::vector& segment_infs, + const bool& through_channel) { + /* For Y-direction Channel: CHANY */ + for (size_t ix = 0; ix < grids.width() - 1; ++ix) { + /* Keep a vector of node_ids for the channels, because we will rotate them when walking through ix */ + std::vector track_node_ids; + + for (size_t iy = 1; iy < grids.height() - 1; ++iy) { + vtr::Point chany_coord(ix, iy); + + /* Bypass if the routing channel does not exist when through channel are not allowed */ + if ((false == through_channel) + && (false == is_chany_exist(grids, chany_coord))) { + continue; + } + + bool force_start = false; + bool force_end = false; + + /* All the tracks have to start when * - the routing channel touch the TOP side a heterogeneous block * - the routing channel touch the BOTTOM side of FPGA */ - if (true == is_chany_top_to_multi_width_grid(grids, chany_coord, through_channel)) { - force_start = true; - } + if (true == is_chany_top_to_multi_width_grid(grids, chany_coord, through_channel)) { + force_start = true; + } - /* All the tracks have to end when + /* All the tracks have to end when * - the routing channel touch the BOTTOM side a heterogeneous block * - the routing channel touch the TOP side of FPGA */ - if (true == is_chany_bottom_to_multi_width_grid(grids, chany_coord, through_channel)) { - force_end = true; - } + if (true == is_chany_bottom_to_multi_width_grid(grids, chany_coord, through_channel)) { + force_end = true; + } - ChanNodeDetails chany_details = build_unidir_chan_node_details(chan_width, grids.height() - 2, - force_start, force_end, segment_infs); - /* Force node_ids from the previous chany + ChanNodeDetails chany_details = build_unidir_chan_node_details(chan_width, grids.height() - 2, + force_start, force_end, segment_infs); + /* Force node_ids from the previous chany * This will not be applied when the routing channel is cut off (force to start) */ - if (0 < track_node_ids.size()) { - /* Rotate should be done based on a typical case of routing tracks. - * Tracks on the borders are not regularly started and ended, - * which causes the node_rotation malfunction + if (0 < track_node_ids.size()) { + /* Rotate should be done based on a typical case of routing tracks. + * Tracks on the borders are not regularly started and ended, + * which causes the node_rotation malfunction */ - ChanNodeDetails chany_details_tt = build_unidir_chan_node_details(chan_width, grids.height() - 2, - false, false, segment_infs); + ChanNodeDetails chany_details_tt = build_unidir_chan_node_details(chan_width, grids.height() - 2, + false, false, segment_infs); - chany_details_tt.set_track_node_ids(track_node_ids); + chany_details_tt.set_track_node_ids(track_node_ids); - /* TODO: - * Do NOT rotate the tracks when the routing channel + /* TODO: + * Do NOT rotate the tracks when the routing channel * locates inside a multi-height and multi-width grid - * Let the routing channel passing through the grid (if through channel is allowed!) + * Let the routing channel passing through the grid (if through channel is allowed!) * An example: - * + * * +------------------------------ * | | * | Grid | * track0 ----->+-----------------------------+----> track0 * | | - * we should rotate only once at the bottom side of a grid + * we should rotate only once at the bottom side of a grid */ - if (true == is_chany_exist(grids, chany_coord, through_channel)) { - /* Rotate the chany_details by an offset of 1*/ - /* For INC_DIRECTION, we use clockwise rotation + if (true == is_chany_exist(grids, chany_coord, through_channel)) { + /* Rotate the chany_details by an offset of 1*/ + /* For INC_DIRECTION, we use clockwise rotation * node_id A ----> -----> node_id D * node_id B ----> / ----> node_id A * node_id C ----> / ----> node_id B - * node_id D ----> ----> node_id C + * node_id D ----> ----> node_id C */ - chany_details_tt.rotate_track_node_id(1, Direction::INC, true); - /* For DEC_DIRECTION, we use clockwise rotation + chany_details_tt.rotate_track_node_id(1, Direction::INC, true); + /* For DEC_DIRECTION, we use clockwise rotation * node_id A <----- <----- node_id B * node_id B <----- \ <----- node_id C * node_id C <----- \ <----- node_id D - * node_id D <----- <----- node_id A + * node_id D <----- <----- node_id A */ - chany_details_tt.rotate_track_node_id(1, Direction::DEC, false); + chany_details_tt.rotate_track_node_id(1, Direction::DEC, false); + } + + track_node_ids = chany_details_tt.get_track_node_ids(); + chany_details.set_track_node_ids(track_node_ids); + } + /* Configure CHANX in this channel */ + load_one_chan_rr_nodes_basic_info(rr_graph, + rr_graph_builder, + rr_node_driver_switches, + rr_node_track_ids, + chany_coord, CHANY, + chany_details, + segment_infs, + CHANX_COST_INDEX_START + segment_infs.size()); + /* Get a copy of node_ids */ + track_node_ids = chany_details.get_track_node_ids(); } - - track_node_ids = chany_details_tt.get_track_node_ids(); - chany_details.set_track_node_ids(track_node_ids); - } - /* Configure CHANX in this channel */ - load_one_chan_rr_nodes_basic_info(rr_graph, - rr_graph_builder, - rr_node_driver_switches, - rr_node_track_ids, - chany_coord, CHANY, - chany_details, - segment_infs, - CHANX_COST_INDEX_START + segment_infs.size()); - /* Get a copy of node_ids */ - track_node_ids = chany_details.get_track_node_ids(); } - } } /************************************************************************ * Reverse the track_ids of CHANX and CHANY nodes in DEC_DIRECTION * This is required as the track ids are allocated in the sequence * of incrementing x and y - * However, DEC direction routing tracks should have a reversed sequence in - * track ids + * However, DEC direction routing tracks should have a reversed sequence in + * track ids ***********************************************************************/ -static -void reverse_dec_chan_rr_node_track_ids(const RRGraphBuilder& rr_graph_builder, - std::map>& rr_node_track_ids) { +static void reverse_dec_chan_rr_node_track_ids(const RRGraphBuilder& rr_graph_builder, + std::map>& rr_node_track_ids) { + // NYI + // unused parameters + (void)(rr_graph_builder); + (void)(rr_node_track_ids); #if 0 // this should call rr_graph_builder to do the job for (const RRNodeId& node : rr_graph_builder.nodes()) { @@ -1019,39 +999,38 @@ void reverse_dec_chan_rr_node_track_ids(const RRGraphBuilder& rr_graph_builder, ***********************************************************************/ void create_tileable_rr_graph_nodes(RRGraphView& rr_graph, RRGraphBuilder& rr_graph_builder, - vtr::vector& rr_node_driver_switches, + vtr::vector& rr_node_driver_switches, std::map>& rr_node_track_ids, - const DeviceGrid& grids, - const vtr::Point& chan_width, + const DeviceGrid& grids, + const vtr::Point& chan_width, const std::vector& segment_infs, const RRSwitchId& wire_to_ipin_switch, const RRSwitchId& delayless_switch, const bool& through_channel) { - load_grid_nodes_basic_info(rr_graph_builder, - rr_node_driver_switches, - grids, - wire_to_ipin_switch, - delayless_switch); - - load_chanx_rr_nodes_basic_info(rr_graph, - rr_graph_builder, - rr_node_driver_switches, - rr_node_track_ids, - grids, - chan_width.x(), - segment_infs, - through_channel); - - load_chany_rr_nodes_basic_info(rr_graph, - rr_graph_builder, - rr_node_driver_switches, - rr_node_track_ids, - grids, - chan_width.y(), - segment_infs, - through_channel); - - reverse_dec_chan_rr_node_track_ids(rr_graph_builder, - rr_node_track_ids); - + load_grid_nodes_basic_info(rr_graph_builder, + rr_node_driver_switches, + grids, + wire_to_ipin_switch, + delayless_switch); + + load_chanx_rr_nodes_basic_info(rr_graph, + rr_graph_builder, + rr_node_driver_switches, + rr_node_track_ids, + grids, + chan_width.x(), + segment_infs, + through_channel); + + load_chany_rr_nodes_basic_info(rr_graph, + rr_graph_builder, + rr_node_driver_switches, + rr_node_track_ids, + grids, + chan_width.y(), + segment_infs, + through_channel); + + reverse_dec_chan_rr_node_track_ids(rr_graph_builder, + rr_node_track_ids); } diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.h b/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.h index 8317c10169b..cb8839018a7 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.h +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.h @@ -21,7 +21,7 @@ *******************************************************************/ void alloc_tileable_rr_graph_nodes(RRGraphBuilder& rr_graph_builder, - vtr::vector& driver_switches, + vtr::vector& driver_switches, const DeviceGrid& grids, const vtr::Point& chan_width, const std::vector& segment_infs, @@ -29,15 +29,13 @@ void alloc_tileable_rr_graph_nodes(RRGraphBuilder& rr_graph_builder, void create_tileable_rr_graph_nodes(RRGraphView& rr_graph, RRGraphBuilder& rr_graph_builder, - vtr::vector& rr_node_driver_switches, + vtr::vector& rr_node_driver_switches, std::map>& rr_node_track_ids, - const DeviceGrid& grids, - const vtr::Point& chan_width, + const DeviceGrid& grids, + const vtr::Point& chan_width, const std::vector& segment_infs, const RRSwitchId& wire_to_ipin_switch, const RRSwitchId& delayless_switch, const bool& through_channel); - - #endif From f3a6875e19b5a4785964638ef6bde8c3342b7147 Mon Sep 17 00:00:00 2001 From: taoli4rs Date: Wed, 3 Aug 2022 10:42:15 -0700 Subject: [PATCH 008/147] Code cleanup: change comments format by complying to vtr clang format. --- vpr/src/base/SetupVPR.cpp | 2 +- vpr/src/route/rr_graph.cpp | 24 +- vpr/src/route/rr_graph.h | 10 +- .../tileable_rr_graph/chan_node_details.cpp | 12 +- vpr/src/tileable_rr_graph/openfpga_port.cpp | 42 +-- .../rr_graph_builder_utils.cpp | 12 +- vpr/src/tileable_rr_graph/rr_gsb.cpp | 80 ++--- .../tileable_chan_details_builder.cpp | 32 +- .../tileable_rr_graph_builder.cpp | 86 +++--- .../tileable_rr_graph_gsb.cpp | 284 +++++++++--------- .../tileable_rr_graph_node_builder.cpp | 202 ++++++------- 11 files changed, 393 insertions(+), 393 deletions(-) diff --git a/vpr/src/base/SetupVPR.cpp b/vpr/src/base/SetupVPR.cpp index 123bbb2d423..14bb78b40be 100644 --- a/vpr/src/base/SetupVPR.cpp +++ b/vpr/src/base/SetupVPR.cpp @@ -351,7 +351,7 @@ static void SetupRoutingArch(const t_arch& Arch, /* copy over the switch block information */ RoutingArch->switchblocks = Arch.switchblocks; - + /* Copy the tileable routing setting */ RoutingArch->tileable = Arch.tileable; RoutingArch->through_channel = Arch.through_channel; diff --git a/vpr/src/route/rr_graph.cpp b/vpr/src/route/rr_graph.cpp index 23ed4a8ce40..8c1b44dffad 100644 --- a/vpr/src/route/rr_graph.cpp +++ b/vpr/src/route/rr_graph.cpp @@ -235,8 +235,6 @@ void uniquify_edges(t_rr_edge_info_set& rr_edges_to_create); void alloc_and_load_edges(RRGraphBuilder& rr_graph_builder, const t_rr_edge_info_set& rr_edges_to_create); - - static void remap_rr_node_switch_indices(const t_arch_switch_fanin& switch_fanin); static void load_rr_switch_inf(const int num_arch_switches, const float R_minW_nmos, const float R_minW_pmos, const t_arch_switch_fanin& switch_fanin); @@ -1026,10 +1024,10 @@ static void remap_rr_node_switch_indices(const t_arch_switch_fanin& switch_fanin } void rr_graph_externals(const std::vector& segment_inf, - const std::vector& segment_inf_x, - const std::vector& segment_inf_y, - int wire_to_rr_ipin_switch, - enum e_base_cost_type base_cost_type) { + const std::vector& segment_inf_x, + const std::vector& segment_inf_y, + int wire_to_rr_ipin_switch, + enum e_base_cost_type base_cost_type) { auto& device_ctx = g_vpr_ctx.device(); const auto& rr_graph = device_ctx.rr_graph; add_rr_graph_C_from_switches(rr_graph.rr_switch_inf(RRSwitchId(wire_to_rr_ipin_switch)).Cin); @@ -1123,13 +1121,13 @@ static t_seg_details* alloc_and_load_global_route_seg_details(const int global_r /* Calculates the number of track connections from each block pin to each segment type */ std::vector> alloc_and_load_actual_fc(const std::vector& types, - const int max_pins, - const std::vector& segment_inf, - const int* sets_per_seg_type, - const t_chan_width* nodes_per_chan, - const e_fc_type fc_type, - const enum e_directionality directionality, - bool* Fc_clipped) { + const int max_pins, + const std::vector& segment_inf, + const int* sets_per_seg_type, + const t_chan_width* nodes_per_chan, + const e_fc_type fc_type, + const enum e_directionality directionality, + bool* Fc_clipped) { //Initialize Fc of all blocks to zero auto zeros = vtr::Matrix({size_t(max_pins), segment_inf.size()}, 0); std::vector> Fc(types.size(), zeros); diff --git a/vpr/src/route/rr_graph.h b/vpr/src/route/rr_graph.h index 2d230f92fb8..2a6bcd8a367 100644 --- a/vpr/src/route/rr_graph.h +++ b/vpr/src/route/rr_graph.h @@ -80,10 +80,12 @@ std::vector> alloc_and_load_actual_fc(const std::vector ChanNodeDetails::get_seg_group(const size_t& track_id) const { VTR_ASSERT(validate_chan_width()); @@ -222,8 +222,8 @@ void ChanNodeDetails::rotate_track_node_id(const size_t& offset, const Direction } /* Rotate the node_ids by groups - * A group begins from a track_start and ends before another track_start - */ + * A group begins from a track_start and ends before another track_start + */ VTR_ASSERT(validate_chan_width()); for (size_t itrack = 0; itrack < get_chan_width(); ++itrack) { /* Bypass non-start segment */ @@ -264,7 +264,7 @@ void ChanNodeDetails::clear() { } /************************************************************************ - * Validators + * Validators ***********************************************************************/ bool ChanNodeDetails::validate_chan_width() const { size_t chan_width = track_node_ids_.size(); diff --git a/vpr/src/tileable_rr_graph/openfpga_port.cpp b/vpr/src/tileable_rr_graph/openfpga_port.cpp index 3d4d59348f6..63542cd7d5a 100644 --- a/vpr/src/tileable_rr_graph/openfpga_port.cpp +++ b/vpr/src/tileable_rr_graph/openfpga_port.cpp @@ -8,7 +8,7 @@ #include "openfpga_port.h" /************************************************************************ - * Member functions for BasicPort class + * Member functions for BasicPort class ***********************************************************************/ /************************************************************************ @@ -49,7 +49,7 @@ BasicPort::BasicPort(const std::string& name, const size_t& width) { } /************************************************************************ - * Accessors + * Accessors ***********************************************************************/ /* get the port width */ size_t BasicPort::get_width() const { @@ -98,8 +98,8 @@ bool BasicPort::mergeable(const BasicPort& portA) const { } /* Check if a port is contained by this port: - * this function will check if the (LSB, MSB) of portA - * is contained by the (LSB, MSB) of this port + * this function will check if the (LSB, MSB) of portA + * is contained by the (LSB, MSB) of this port */ bool BasicPort::contained(const BasicPort& portA) const { return (lsb_ <= portA.get_lsb() && portA.get_msb() <= msb_); @@ -111,12 +111,12 @@ size_t BasicPort::get_origin_port_width() const { } /************************************************************************ - * Overloaded operators + * Overloaded operators ***********************************************************************/ -/* Two ports are the same only when: +/* Two ports are the same only when: * 1. port names are the same * 2. LSBs are the same - * 3. MSBs are the same + * 3. MSBs are the same */ bool BasicPort::operator==(const BasicPort& portA) const { if ((0 == this->get_name().compare(portA.get_name())) @@ -137,7 +137,7 @@ bool BasicPort::operator<(const BasicPort& portA) const { } /************************************************************************ - * Mutators + * Mutators ***********************************************************************/ /* copy */ void BasicPort::set(const BasicPort& basic_port) { @@ -227,9 +227,9 @@ bool BasicPort::rotate(const size_t& offset) { set_width(offset); return true; } - /* check if leads to overflow: - * if limits - msb is larger than offset - */ + /* check if leads to overflow: + * if limits - msb is larger than offset + */ if ((std::numeric_limits::max() - msb_ < offset)) { return false; } @@ -241,15 +241,15 @@ bool BasicPort::rotate(const size_t& offset) { /* rotate: decrease both lsb and msb by an offset */ bool BasicPort::counter_rotate(const size_t& offset) { - /* If current port is invalid or offset is 0, - * we do nothing - */ + /* If current port is invalid or offset is 0, + * we do nothing + */ if ((0 == offset) || (0 == get_width())) { return true; } - /* check if leads to overflow: - * if limits is larger than offset - */ + /* check if leads to overflow: + * if limits is larger than offset + */ if ((std::numeric_limits::min() + lsb_ < offset)) { return false; } @@ -282,7 +282,7 @@ void BasicPort::combine(const BasicPort& port) { /* A restricted combine function for two ports, * Following conditions will be applied: * 1. the two ports have the same name - * Note: you must run mergable() function first + * Note: you must run mergable() function first * to make sure this assumption is valid * 2. the new MSB will be the maximum MSB of the two ports * 3. the new LSB will be the minimum LSB of the two ports @@ -323,11 +323,11 @@ bool BasicPort::is_valid() const { } /************************************************************************ - * ConfPorts member functions + * ConfPorts member functions ***********************************************************************/ /************************************************************************ - * Constructor + * Constructor ***********************************************************************/ /* Default constructor */ ConfPorts::ConfPorts() { @@ -369,7 +369,7 @@ size_t ConfPorts::get_regular_port_msb() const { } /************************************************************************ - * Mutators + * Mutators ***********************************************************************/ void ConfPorts::set(const ConfPorts& conf_ports) { set_reserved_port(conf_ports.get_reserved_port_width()); diff --git a/vpr/src/tileable_rr_graph/rr_graph_builder_utils.cpp b/vpr/src/tileable_rr_graph/rr_graph_builder_utils.cpp index 47660c0bd26..cb8afb1db9a 100644 --- a/vpr/src/tileable_rr_graph/rr_graph_builder_utils.cpp +++ b/vpr/src/tileable_rr_graph/rr_graph_builder_utils.cpp @@ -247,8 +247,8 @@ bool is_chanx_right_to_multi_height_grid(const DeviceGrid& grids, VTR_ASSERT(0 < chanx_coord.x()); if (1 == chanx_coord.x()) { /* This is already the LEFT side of FPGA fabric, - * it is the same results as chanx is right to a multi-height grid - */ + * it is the same results as chanx is right to a multi-height grid + */ return true; } @@ -322,8 +322,8 @@ bool is_chany_top_to_multi_width_grid(const DeviceGrid& grids, VTR_ASSERT(0 < chany_coord.y()); if (1 == chany_coord.y()) { /* This is already the BOTTOM side of FPGA fabric, - * it is the same results as chany is at the top of a multi-width grid - */ + * it is the same results as chany is at the top of a multi-width grid + */ return true; } @@ -362,8 +362,8 @@ bool is_chany_bottom_to_multi_width_grid(const DeviceGrid& grids, VTR_ASSERT(chany_coord.y() < grids.height() - 1); if (grids.height() - 2 == chany_coord.y()) { /* This is already the TOP side of FPGA fabric, - * it is the same results as chany is at the bottom of a multi-width grid - */ + * it is the same results as chany is at the bottom of a multi-width grid + */ return true; } diff --git a/vpr/src/tileable_rr_graph/rr_gsb.cpp b/vpr/src/tileable_rr_graph/rr_gsb.cpp index d1b6e2b4e1e..d1b6f7e4a18 100644 --- a/vpr/src/tileable_rr_graph/rr_gsb.cpp +++ b/vpr/src/tileable_rr_graph/rr_gsb.cpp @@ -153,8 +153,8 @@ std::vector RRGSB::get_chan_node_in_edges(const RRGraphView& rr_graph, VTR_ASSERT(OUT_PORT == get_chan_node_direction(side, track_id)); /* if sorted, we give sorted edges - * if not sorted, we give the empty vector - */ + * if not sorted, we give the empty vector + */ if (0 == chan_node_in_edges_.size()) { std::vector unsorted_edges; @@ -304,12 +304,12 @@ void RRGSB::get_node_side_and_index(const RRGraphView& rr_graph, SideManager side_manager; /* Count the number of existence of cur_rr_node in cur_sb_info - * It could happen that same cur_rr_node appears on different sides of a SB - * For example, a routing track go vertically across the SB. - * Then its corresponding rr_node appears on both TOP and BOTTOM sides of this SB. - * We need to ensure that the found rr_node has the same direction as user want. - * By specifying the direction of rr_node, There should be only one rr_node can satisfy! - */ + * It could happen that same cur_rr_node appears on different sides of a SB + * For example, a routing track go vertically across the SB. + * Then its corresponding rr_node appears on both TOP and BOTTOM sides of this SB. + * We need to ensure that the found rr_node has the same direction as user want. + * By specifying the direction of rr_node, There should be only one rr_node can satisfy! + */ for (side = 0; side < get_num_sides(); ++side) { side_manager.set_side(side); node_index = get_node_index(rr_graph, node, side_manager.get_side(), node_direction); @@ -340,9 +340,9 @@ bool RRGSB::is_sb_node_exist_opposite_side(const RRGraphView& rr_graph, VTR_ASSERT((CHANX == rr_graph.node_type(node)) || (CHANY == rr_graph.node_type(node))); - /* See if we can find the same src_rr_node in the opposite chan_side - * if there is one, it means a shorted wire across the SB - */ + /* See if we can find the same src_rr_node in the opposite chan_side + * if there is one, it means a shorted wire across the SB + */ index = get_node_index(rr_graph, node, side_manager.get_opposite(), IN_PORT); return (-1 != index); @@ -402,13 +402,13 @@ bool RRGSB::is_sb_exist() const { } /************************************************************************ - * Check if the node indicates a passing wire across the Switch Block part of the GSB - * Therefore, we actually do the following check - * Check if a track starts from this GSB or not + * Check if the node indicates a passing wire across the Switch Block part of the GSB + * Therefore, we actually do the following check + * Check if a track starts from this GSB or not * For INC_DIRECTION - * (xlow, ylow) should be same as the GSB side coordinate + * (xlow, ylow) should be same as the GSB side coordinate * For DEC_DIRECTION - * (xhigh, yhigh) should be same as the GSB side coordinate + * (xhigh, yhigh) should be same as the GSB side coordinate ***********************************************************************/ bool RRGSB::is_sb_node_passing_wire(const RRGraphView& rr_graph, const e_side& node_side, @@ -442,9 +442,9 @@ bool RRGSB::is_sb_node_passing_wire(const RRGraphView& rr_graph, return false; /* This is an ending point */ } - /* Reach here it means that this will be a passing wire, - * we should be able to find the node on the opposite side of the GSB! - */ + /* Reach here it means that this will be a passing wire, + * we should be able to find the node on the opposite side of the GSB! + */ if (true != is_sb_node_exist_opposite_side(rr_graph, track_node, node_side)) { VTR_LOG("GSB[%lu][%lu] track node[%lu] at %s:\n", get_x(), get_y(), track_id, SIDE_STRING[node_side]); @@ -460,9 +460,9 @@ bool RRGSB::is_sb_node_passing_wire(const RRGraphView& rr_graph, } /* check if the candidate SB satisfy the basic requirements on being a mirror of the current one */ -/* Idenify mirror Switch blocks - * Check each two switch blocks: - * Number of channel/opin/ipin rr_nodes are same +/* Idenify mirror Switch blocks + * Check each two switch blocks: + * Number of channel/opin/ipin rr_nodes are same * If all above are satisfied, the two switch blocks may be mirrors ! */ bool RRGSB::is_sb_mirrorable(const RRGraphView& rr_graph, const RRGSB& cand) const { @@ -524,8 +524,8 @@ bool RRGSB::is_sb_side_segment_mirror(const RRGraphView& rr_graph, const RRGSB& return false; } /* Check the track_id of each node - * ptc is not necessary, we care the connectivity! - */ + * ptc is not necessary, we care the connectivity! + */ /* For OUT_PORT rr_node, we need to check fan-in */ if (OUT_PORT != get_chan_node_direction(side, itrack)) { continue; /* skip IN_PORT */ @@ -813,14 +813,14 @@ void RRGSB::sort_chan_node_in_edges(const RRGraphView& rr_graph, 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 - */ + * 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 + */ // NYI // unused parameter @@ -951,11 +951,11 @@ void RRGSB::clear_one_side(const e_side& node_side) { * Internal Accessors: identify mirrors ***********************************************************************/ -/* check if two rr_nodes have a similar set of drive_rr_nodes +/* check if two rr_nodes have a similar set of drive_rr_nodes * for each drive_rr_node: * 1. CHANX or CHANY: should have the same side and index * 2. OPIN or IPIN: should have the same side and index - * 3. each drive_rr_switch should be the same + * 3. each drive_rr_switch should be the same */ bool RRGSB::is_sb_node_mirror(const RRGraphView& rr_graph, const RRGSB& cand, @@ -969,10 +969,10 @@ bool RRGSB::is_sb_node_mirror(const RRGraphView& rr_graph, } if (true == is_short_conkt) { - /* Since, both are pass wires, - * The two node should be equivalent - * we can return here - */ + /* Since, both are pass wires, + * The two node should be equivalent + * we can return here + */ return true; } @@ -1018,10 +1018,10 @@ bool RRGSB::is_sb_node_mirror(const RRGraphView& rr_graph, return true; } -/* check if two ipin_nodes have a similar set of drive_rr_nodes +/* check if two ipin_nodes have a similar set of drive_rr_nodes * for each drive_rr_node: * 1. CHANX or CHANY: should have the same side and index - * 2. each drive_rr_switch should be the same + * 2. each drive_rr_switch should be the same */ bool RRGSB::is_cb_node_mirror(const RRGraphView& rr_graph, const RRGSB& cand, diff --git a/vpr/src/tileable_rr_graph/tileable_chan_details_builder.cpp b/vpr/src/tileable_rr_graph/tileable_chan_details_builder.cpp index 4c185ecd347..1dbdb7a3917 100644 --- a/vpr/src/tileable_rr_graph/tileable_chan_details_builder.cpp +++ b/vpr/src/tileable_rr_graph/tileable_chan_details_builder.cpp @@ -1,7 +1,7 @@ /************************************************************************ - * This file contains a builder for the ChanNodeDetails data structure - * Different from VPR rr_graph builders, this builder aims to create a - * highly regular routing channel. Thus, it is called tileable, + * This file contains a builder for the ChanNodeDetails data structure + * Different from VPR rr_graph builders, this builder aims to create a + * highly regular routing channel. Thus, it is called tileable, * which brings significant advantage in producing large FPGA fabrics. ***********************************************************************/ #include @@ -18,10 +18,10 @@ * Generate the number of tracks for each types of routing segments * w.r.t. the frequency of each of segments and channel width * Note that if we dertermine the number of tracks per type using - * chan_width * segment_frequency / total_freq may cause - * The total track num may not match the chan_width, + * chan_width * segment_frequency / total_freq may cause + * The total track num may not match the chan_width, * therefore, we assign tracks one by one until we meet the frequency requirement - * In this way, we can assign the number of tracks with repect to frequency + * In this way, we can assign the number of tracks with repect to frequency ***********************************************************************/ std::vector get_num_tracks_per_seg_type(const size_t& chan_width, const std::vector& segment_inf, @@ -33,7 +33,7 @@ std::vector get_num_tracks_per_seg_type(const size_t& chan_width, demand.resize(segment_inf.size()); /* Scale factor so we can divide by any length - * and still use integers */ + * and still use integers */ /* Get the sum of frequency */ size_t scale = 1; size_t freq_sum = 0; @@ -45,8 +45,8 @@ std::vector get_num_tracks_per_seg_type(const size_t& chan_width, /* Init assignments to 0 and set the demand values */ /* Get the fraction of each segment type considering the frequency: - * num_track_per_seg = chan_width * (freq_of_seg / sum_freq) - */ + * num_track_per_seg = chan_width * (freq_of_seg / sum_freq) + */ for (size_t iseg = 0; iseg < segment_inf.size(); ++iseg) { result[iseg] = 0; demand[iseg] = scale * chan_width * segment_inf[iseg].frequency; @@ -105,11 +105,11 @@ int adapt_to_tileable_route_chan_width(const int& chan_width, } /************************************************************************ - * Build details of routing tracks in a channel - * The function will + * Build details of routing tracks in a channel + * The function will * 1. Assign the segments for each routing channel, * To be specific, for each routing track, we assign a routing segment. - * The assignment is subject to users' specifications, such as + * The assignment is subject to users' specifications, such as * a. length of each type of segment * b. frequency of each type of segment. * c. routing channel width @@ -154,9 +154,9 @@ int adapt_to_tileable_route_chan_width(const int& chan_width, * if device_side is NUM_SIDES, we assume this channel does not locate on borders * All segments will start and ends with no exception * - * 4. IMPORTANT: we should be aware that channel width maybe different + * 4. IMPORTANT: we should be aware that channel width maybe different * in X-direction and Y-direction channels!!! - * So we will load segment details for different channels + * So we will load segment details for different channels ***********************************************************************/ ChanNodeDetails build_unidir_chan_node_details(const size_t& chan_width, const size_t& max_seg_length, @@ -198,8 +198,8 @@ ChanNodeDetails build_unidir_chan_node_details(const size_t& chan_width, seg_end = true; } /* Since this is a unidirectional routing architecture, - * Add a pair of tracks, 1 INC track and 1 DEC track - */ + * Add a pair of tracks, 1 INC track and 1 DEC track + */ chan_node_details.add_track(cur_track, Direction::INC, iseg, seg_len, seg_start, seg_end); cur_track++; chan_node_details.add_track(cur_track, Direction::DEC, iseg, seg_len, seg_start, seg_end); diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp index 8aa3b8485ef..ab759e8a219 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp @@ -102,7 +102,7 @@ void build_tileable_unidir_rr_graph(const std::vector& typ DeviceContext& device_ctx = g_vpr_ctx.mutable_device(); /* The number of segments are in general small, reserve segments may not bring - * significant memory efficiency */ + * significant memory efficiency */ device_ctx.rr_graph_builder.reserve_segments(segment_inf.size()); /* Create the segments */ for (size_t iseg = 0; iseg < segment_inf.size(); ++iseg) { @@ -110,12 +110,12 @@ void build_tileable_unidir_rr_graph(const std::vector& typ } /* TODO: Load architecture switch to rr_graph switches - * Draft the switches as internal data of RRGraph object - * These are temporary switches copied from arch switches - * We use them to build the edges - * We will reset all the switches in the function - * alloc_and_load_rr_switch_inf() - */ + * Draft the switches as internal data of RRGraph object + * These are temporary switches copied from arch switches + * We use them to build the edges + * We will reset all the switches in the function + * alloc_and_load_rr_switch_inf() + */ /* TODO: Spot the switch id in the architecture switch list */ RRSwitchId wire_to_ipin_rr_switch = RRSwitchId::INVALID(); RRSwitchId delayless_rr_switch = RRSwitchId::INVALID(); @@ -146,8 +146,8 @@ void build_tileable_unidir_rr_graph(const std::vector& typ std::map> rr_node_track_ids; /************************ - * Allocate the rr_nodes - ************************/ + * Allocate the rr_nodes + ************************/ alloc_tileable_rr_graph_nodes(device_ctx.rr_graph_builder, rr_node_driver_switches, grids, @@ -156,8 +156,8 @@ void build_tileable_unidir_rr_graph(const std::vector& typ through_channel); /************************ - * Create all the rr_nodes - ************************/ + * Create all the rr_nodes + ************************/ create_tileable_rr_graph_nodes(device_ctx.rr_graph, device_ctx.rr_graph_builder, rr_node_driver_switches, @@ -170,14 +170,14 @@ void build_tileable_unidir_rr_graph(const std::vector& typ through_channel); /************************************************************************ - * Create the connectivity of OPINs - * a. Evenly assign connections to OPINs to routing tracks - * b. the connection pattern should be same across the fabric - * - * Create the connectivity of IPINs - * a. Evenly assign connections from routing tracks to IPINs - * b. the connection pattern should be same across the fabric - ***********************************************************************/ + * Create the connectivity of OPINs + * a. Evenly assign connections to OPINs to routing tracks + * b. the connection pattern should be same across the fabric + * + * Create the connectivity of IPINs + * a. Evenly assign connections from routing tracks to IPINs + * b. the connection pattern should be same across the fabric + ***********************************************************************/ /* Global routing uses a single longwire track */ int max_chan_width = find_unidir_routing_channel_width(chan_width.max); VTR_ASSERT(max_chan_width > 0); @@ -195,8 +195,8 @@ void build_tileable_unidir_rr_graph(const std::vector& typ } /* Fc assignment still uses the old function from VPR. - * Should use tileable version so that we have can have full control - */ + * Should use tileable version so that we have can have full control + */ std::vector num_tracks = get_num_tracks_per_seg_type(max_chan_width / 2, segment_inf, false); int* sets_per_seg_type = (int*)vtr::malloc(sizeof(int) * segment_inf.size()); VTR_ASSERT(num_tracks.size() == segment_inf.size()); @@ -224,13 +224,13 @@ void build_tileable_unidir_rr_graph(const std::vector& typ } /************************************************************************ - * Build the connections tile by tile: - * We classify rr_nodes into a general switch block (GSB) data structure - * where we create edges to each rr_nodes in the GSB with respect to - * Fc_in and Fc_out, switch block patterns - * In addition, we will also handle direct-connections: - * Add edges that bridge OPINs and IPINs to the rr_graph - ***********************************************************************/ + * Build the connections tile by tile: + * We classify rr_nodes into a general switch block (GSB) data structure + * where we create edges to each rr_nodes in the GSB with respect to + * Fc_in and Fc_out, switch block patterns + * In addition, we will also handle direct-connections: + * Add edges that bridge OPINs and IPINs to the rr_graph + ***********************************************************************/ /* Create edges for a tileable rr_graph */ build_rr_graph_edges(device_ctx.rr_graph, @@ -244,9 +244,9 @@ void build_tileable_unidir_rr_graph(const std::vector& typ wire_opposite_side); /************************************************************************ - * Build direction connection lists - * TODO: use tile direct builder - ***********************************************************************/ + * Build direction connection lists + * TODO: use tile direct builder + ***********************************************************************/ /* Create data structure of direct-connections */ t_clb_to_clb_directs* clb_to_clb_directs = NULL; if (num_directs > 0) { @@ -272,7 +272,7 @@ void build_tileable_unidir_rr_graph(const std::vector& typ #endif /* Allocate and load routing resource switches, which are derived from the switches from the architecture file, - * based on their fanin in the rr graph. This routine also adjusts the rr nodes to point to these new rr switches */ + * based on their fanin in the rr graph. This routine also adjusts the rr nodes to point to these new rr switches */ alloc_and_load_rr_switch_inf(device_ctx.num_arch_switches, R_minW_nmos, R_minW_pmos, wire_to_arch_ipin_switch, wire_to_rr_ipin_switch); /* Save the channel widths for the newly constructed graph */ @@ -285,10 +285,10 @@ void build_tileable_unidir_rr_graph(const std::vector& typ #endif /************************************************************************ - * Allocate external data structures - * a. cost_index - * b. RC tree - ***********************************************************************/ + * Allocate external data structures + * a. cost_index + * b. RC tree + ***********************************************************************/ t_unified_to_parallel_seg_index segment_index_map; std::vector segment_inf_x = get_parallel_segs(segment_inf, segment_index_map, X_AXIS); std::vector segment_inf_y = get_parallel_segs(segment_inf, segment_index_map, Y_AXIS); @@ -296,9 +296,9 @@ void build_tileable_unidir_rr_graph(const std::vector& typ *wire_to_rr_ipin_switch, base_cost_type); /* Rebuild the link between RRGraph node and segments - * Should be called only AFTER the function - * rr_graph_externals() - */ + * Should be called only AFTER the function + * rr_graph_externals() + */ for (const RRNodeId& inode : device_ctx.rr_graph.nodes()) { if ((CHANX != device_ctx.rr_graph.node_type(inode)) && (CHANY != device_ctx.rr_graph.node_type(inode))) { @@ -315,8 +315,8 @@ void build_tileable_unidir_rr_graph(const std::vector& typ } /************************************************************************ - * Sanitizer for the rr_graph, check connectivities of rr_nodes - ***********************************************************************/ + * Sanitizer for the rr_graph, check connectivities of rr_nodes + ***********************************************************************/ /* Essential check for rr_graph, build look-up and */ if (false == device_ctx.rr_graph_builder.validate()) { /* Error out if built-in validator of rr_graph fails */ @@ -344,8 +344,8 @@ void build_tileable_unidir_rr_graph(const std::vector& typ #endif /************************************************************************ - * Free all temp stucts - ***********************************************************************/ + * Free all temp stucts + ***********************************************************************/ free(sets_per_seg_type); if (nullptr != clb_to_clb_directs) { diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp index 549a50c4d98..978341a7399 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp @@ -1,5 +1,5 @@ /************************************************************************ - * This file contains a builder for track-to-track connections inside a + * This file contains a builder for track-to-track connections inside a * tileable General Switch Block (GSB). ***********************************************************************/ #include @@ -42,11 +42,11 @@ enum e_track_status { }; /************************************************************************ - * Check if a track starts from this GSB or not - * (xlow, ylow) should be same as the GSB side coordinate + * Check if a track starts from this GSB or not + * (xlow, ylow) should be same as the GSB side coordinate * - * Check if a track ends at this GSB or not - * (xhigh, yhigh) should be same as the GSB side coordinate + * Check if a track ends at this GSB or not + * (xhigh, yhigh) should be same as the GSB side coordinate ***********************************************************************/ static enum e_track_status determine_track_status_of_gsb(const RRGraphView& rr_graph, const RRGSB& rr_gsb, @@ -173,14 +173,14 @@ static bool is_gsb_in_track_sb_population(const RRGraphView& rr_graph, * Create a list of track_id based on the to_track and num_to_tracks * We consider the following list [to_track, to_track + Fs/3 - 1] * if the [to_track + Fs/3 - 1] exceeds the num_to_tracks, we start over from 0! -***********************************************************************/ + ***********************************************************************/ static std::vector get_to_track_list(const int& Fs, const int& to_track, const int& num_to_tracks) { std::vector to_tracks; for (int i = 0; i < Fs; i = i + 3) { - /* TODO: currently, for Fs > 3, I always search the next from_track until Fs is satisfied - * The optimal track selection should be done in a more scientific way!!! - */ + /* TODO: currently, for Fs > 3, I always search the next from_track until Fs is satisfied + * The optimal track selection should be done in a more scientific way!!! + */ int to_track_i = to_track + i; /* make sure the track id is still in range */ if (to_track_i > num_to_tracks - 1) { @@ -196,9 +196,9 @@ static std::vector get_to_track_list(const int& Fs, const int& to_track, /************************************************************************ * This function aims to return the track indices that drive the from_track - * in a Switch Block + * in a Switch Block * The track_ids to return will depend on different topologies of SB - * SUBSET, UNIVERSAL, and WILTON. + * SUBSET, UNIVERSAL, and WILTON. ***********************************************************************/ static std::vector get_switch_block_to_track_id(const e_switch_block_type& switch_block_type, const int& Fs, @@ -206,14 +206,14 @@ static std::vector get_switch_block_to_track_id(const e_switch_block_typ const int& from_track, const e_side& to_side, const int& num_to_tracks) { - /* This routine returns the track number to which the from_track should - * connect. It supports any Fs % 3 == 0, switch blocks. - */ + /* This routine returns the track number to which the from_track should + * connect. It supports any Fs % 3 == 0, switch blocks. + */ std::vector to_tracks; - /* TODO: currently, for Fs > 3, I always search the next from_track until Fs is satisfied - * The optimal track selection should be done in a more scientific way!!! - */ + /* TODO: currently, for Fs > 3, I always search the next from_track until Fs is satisfied + * The optimal track selection should be done in a more scientific way!!! + */ VTR_ASSERT(0 == Fs % 3); /* Adapt from_track to fit in the range of num_to_tracks */ @@ -227,10 +227,10 @@ static std::vector get_switch_block_to_track_id(const e_switch_block_typ case UNIVERSAL: if ((from_side == LEFT) || (from_side == RIGHT)) { - /* For the prev_side, to_track is from_track - * For the next_side, to_track is num_to_tracks - 1 - from_track - * For the opposite_side, to_track is always from_track - */ + /* For the prev_side, to_track is from_track + * For the next_side, to_track is num_to_tracks - 1 - from_track + * For the opposite_side, to_track is always from_track + */ SideManager side_manager(from_side); if ((to_side == side_manager.get_opposite()) || (to_side == side_manager.get_rotate_counterclockwise())) { @@ -242,10 +242,10 @@ static std::vector get_switch_block_to_track_id(const e_switch_block_typ if ((from_side == TOP) || (from_side == BOTTOM)) { - /* For the next_side, to_track is from_track - * For the prev_side, to_track is num_to_tracks - 1 - from_track - * For the opposite_side, to_track is always from_track - */ + /* For the next_side, to_track is from_track + * For the prev_side, to_track is num_to_tracks - 1 - from_track + * For the opposite_side, to_track is always from_track + */ SideManager side_manager(from_side); if ((to_side == side_manager.get_opposite()) || (to_side == side_manager.get_rotate_clockwise())) { @@ -305,7 +305,7 @@ static std::vector get_switch_block_to_track_id(const e_switch_block_typ } /************************************************************************ - * Build the track_to_track_map[from_side][0..chan_width-1][to_side][track_indices] + * Build the track_to_track_map[from_side][0..chan_width-1][to_side][track_indices] * For a group of from_track nodes and to_track nodes * For each side of from_tracks, we call a routine to get the list of to_tracks * Then, we fill the track2track_map @@ -389,21 +389,21 @@ static void build_gsb_one_group_track_to_track_map(const RRGraphView& rr_graph, } /************************************************************************ - * Build the track_to_track_map[from_side][0..chan_width-1][to_side][track_indices] + * Build the track_to_track_map[from_side][0..chan_width-1][to_side][track_indices] * based on the existing routing resources in the General Switch Block (GSB) - * The track_indices is the indices of tracks that the node at from_side and [0..chan_width-1] will drive + * The track_indices is the indices of tracks that the node at from_side and [0..chan_width-1] will drive * IMPORTANT: the track_indices are the indicies in the GSB context, but not the rr_graph!!! * We separate the connections into two groups: - * Group 1: the routing tracks start from this GSB - * We will apply switch block patterns (SUBSET, UNIVERSAL, WILTON) + * Group 1: the routing tracks start from this GSB + * We will apply switch block patterns (SUBSET, UNIVERSAL, WILTON) * Group 2: the routing tracks do not start from this GSB (bypassing wires) - * We will apply switch block patterns (SUBSET, UNIVERSAL, WILTON) - * but we will check the Switch Block (SB) population of these + * We will apply switch block patterns (SUBSET, UNIVERSAL, WILTON) + * but we will check the Switch Block (SB) population of these * routing segments, and determine which requires connections - * + * * CHANY CHANY CHANY CHANY * [0] [1] [2] [3] - * start yes no yes no + * start yes no yes no * end +-------------------------+ start Group 1 Group 2 * no CHANX[0] | TOP | CHANX[0] yes TOP/BOTTOM TOP/BOTTOM * | | CHANY[0,2] CHANY[1,3] @@ -412,25 +412,25 @@ static void build_gsb_one_group_track_to_track_map(const RRGraphView& rr_graph, * no CHANX[2] | | CHANX[2] yes * | | * yes CHANX[3] | BOTTOM | CHANX[3] no - * +-------------------------+ + * +-------------------------+ * CHANY CHANY CHANY CHANY * [0] [1] [2] [3] - * start yes no yes no - * + * start yes no yes no + * * The mapping is done in the following steps: (For each side of the GSB) * 1. Build a list of tracks that will start from this side * if a track starts, its xlow/ylow is the same as the x,y of this gsb * 2. Build a list of tracks on the other sides belonging to Group 1. - * Take the example of RIGHT side, we will collect - * a. tracks that will end at the LEFT side + * Take the example of RIGHT side, we will collect + * a. tracks that will end at the LEFT side * b. tracks that will start at the TOP side * c. tracks that will start at the BOTTOM side - * 3. Apply switch block patterns to Group 1 (SUBSET, UNIVERSAL, WILTON) + * 3. Apply switch block patterns to Group 1 (SUBSET, UNIVERSAL, WILTON) * 4. Build a list of tracks on the other sides belonging to Group 1. - * Take the example of RIGHT side, we will collect + * Take the example of RIGHT side, we will collect * a. tracks that will bypass at the TOP side * b. tracks that will bypass at the BOTTOM side - * 5. Apply switch block patterns to Group 2 (SUBSET, UNIVERSAL, WILTON) + * 5. Apply switch block patterns to Group 2 (SUBSET, UNIVERSAL, WILTON) ***********************************************************************/ t_track2track_map build_gsb_track_to_track_map(const RRGraphView& rr_graph, const RRGSB& rr_gsb, @@ -442,10 +442,10 @@ t_track2track_map build_gsb_track_to_track_map(const RRGraphView& rr_graph, const std::vector& segment_inf) { t_track2track_map track2track_map; /* [0..gsb_side][0..chan_width][track_indices] */ - /* Categorize tracks into 3 groups: - * (1) tracks will start here - * (2) tracks will end here - * (2) tracks will just pass through the SB */ + /* Categorize tracks into 3 groups: + * (1) tracks will start here + * (2) tracks will end here + * (2) tracks will just pass through the SB */ t_track_group start_tracks; /* [0..gsb_side][track_indices] */ t_track_group end_tracks; /* [0..gsb_side][track_indices] */ t_track_group pass_tracks; /* [0..gsb_side][track_indices] */ @@ -461,9 +461,9 @@ t_track2track_map build_gsb_track_to_track_map(const RRGraphView& rr_graph, e_side gsb_side = side_manager.get_side(); /* Build a list of tracks that will start from this side */ for (size_t inode = 0; inode < rr_gsb.get_chan_width(gsb_side); ++inode) { - /* We need to check Switch block population of this track - * The track node will not be considered if there supposed to be no SB at this position - */ + /* We need to check Switch block population of this track + * The track node will not be considered if there supposed to be no SB at this position + */ if (false == is_gsb_in_track_sb_population(rr_graph, rr_gsb, gsb_side, inode, segment_inf)) { continue; /* skip this node and go to the next */ } @@ -516,8 +516,8 @@ t_track2track_map build_gsb_track_to_track_map(const RRGraphView& rr_graph, /* For Group 2: we build connections between end_tracks and start_tracks*/ /* Currently, I use the same Switch Block pattern for the passing tracks and end tracks, - * TODO: This can be improved with different patterns! - */ + * TODO: This can be improved with different patterns! + */ build_gsb_one_group_track_to_track_map(rr_graph, rr_gsb, sb_subtype, subFs, wire_opposite_side, /* Pass tracks may not be wired to start tracks */ @@ -558,10 +558,10 @@ static RRChan build_one_tileable_rr_chan(const vtr::Point& chan_coordina } /*********************************************************************** - * Build a General Switch Block (GSB) + * Build a General Switch Block (GSB) * which includes: * [I] A Switch Box subckt consists of following ports: - * 1. Channel Y [x][y] inputs + * 1. Channel Y [x][y] inputs * 2. Channel X [x+1][y] inputs * 3. Channel Y [x][y-1] outputs * 4. Channel X [x][y] outputs @@ -581,7 +581,7 @@ static RRChan build_one_tileable_rr_chan(const vtr::Point& chan_coordina * | | | | * -------------- -------------- * ---------- - * ChanX & CBX | Switch | ChanX + * ChanX & CBX | Switch | ChanX * [x][y] | Box | [x+1][y] * | [x][y] | * ---------- @@ -602,11 +602,11 @@ static RRChan build_one_tileable_rr_chan(const vtr::Point& chan_coordina * * [II] A X-direction Connection Block [x][y] * The connection block shares the same routing channel[x][y] with the Switch Block - * We just need to fill the ipin nodes at TOP and BOTTOM sides + * We just need to fill the ipin nodes at TOP and BOTTOM sides * as well as properly fill the ipin_grid_side information * [III] A Y-direction Connection Block [x][y+1] * The connection block shares the same routing channel[x][y+1] with the Switch Block - * We just need to fill the ipin nodes at LEFT and RIGHT sides + * We just need to fill the ipin nodes at LEFT and RIGHT sides * as well as properly fill the ipin_grid_side information ***********************************************************************/ RRGSB build_one_tileable_rr_gsb(const DeviceGrid& grids, @@ -638,9 +638,9 @@ RRGSB build_one_tileable_rr_gsb(const DeviceGrid& grids, enum e_side opin_grid_side[2] = {NUM_SIDES, NUM_SIDES}; enum PORTS chan_dir_to_port_dir_mapping[2] = {OUT_PORT, IN_PORT}; /* 0: INC_DIRECTION => ?; 1: DEC_DIRECTION => ? */ - /* Build a segment details, where we need the segment ids for building rr_chan - * We do not care starting and ending points here, so set chan_side as NUM_SIDES - */ + /* Build a segment details, where we need the segment ids for building rr_chan + * We do not care starting and ending points here, so set chan_side as NUM_SIDES + */ ChanNodeDetails chanx_details = build_unidir_chan_node_details(device_chan_width.x(), grids.width() - 1, false, false, segment_inf); ChanNodeDetails chany_details = build_unidir_chan_node_details(device_chan_width.y(), grids.height() - 1, @@ -812,34 +812,34 @@ RRGSB build_one_tileable_rr_gsb(const DeviceGrid& grids, opin_grid_side[1] = NUM_SIDES; } - /* Add IPIN nodes from adjacent grids: the 4 grids sitting on the 4 corners of the Switch Block - * - * - The concept of top/bottom side of connection block in GSB domain: - * - * | Grid[x][y+1] | - * | BOTTOM side | - * +-----------------------+ - * | - * v - * +-----------------------+ - * | TOP side | - * | X- Connection Block | - * | BOTTOM side | - * +-----------------------+ - * ^ - * | - * +-----------------------+ - * | TOP side | - * | Grid[x][y] | - * - * - The concept of top/bottom side of connection block in GSB domain: - * - * ---------------+ +---------------------- ... ---------------------+ +---------------- - * Grid[x][y+1] |->| Y- Connection Block Y- Connection Block |<-| Grid[x+1][y+1] - * RIGHT side | | LEFT side ... RIGHT side | | LEFT side - * --------------+ +---------------------- ... ---------------------+ +---------------- - * - */ + /* Add IPIN nodes from adjacent grids: the 4 grids sitting on the 4 corners of the Switch Block + * + * - The concept of top/bottom side of connection block in GSB domain: + * + * | Grid[x][y+1] | + * | BOTTOM side | + * +-----------------------+ + * | + * v + * +-----------------------+ + * | TOP side | + * | X- Connection Block | + * | BOTTOM side | + * +-----------------------+ + * ^ + * | + * +-----------------------+ + * | TOP side | + * | Grid[x][y] | + * + * - The concept of top/bottom side of connection block in GSB domain: + * + * ---------------+ +---------------------- ... ---------------------+ +---------------- + * Grid[x][y+1] |->| Y- Connection Block Y- Connection Block |<-| Grid[x+1][y+1] + * RIGHT side | | LEFT side ... RIGHT side | | LEFT side + * --------------+ +---------------------- ... ---------------------+ +---------------- + * + */ for (size_t side = 0; side < rr_gsb.get_num_sides(); ++side) { SideManager side_manager(side); size_t ix; @@ -907,9 +907,9 @@ RRGSB build_one_tileable_rr_gsb(const DeviceGrid& grids, /************************************************************************ * Create edges for each rr_node of a General Switch Blocks (GSB): - * 1. create edges between CHANX | CHANY and IPINs (connections inside connection blocks) - * 2. create edges between OPINs, CHANX and CHANY (connections inside switch blocks) - * 3. create edges between OPINs and IPINs (direct-connections) + * 1. create edges between CHANX | CHANY and IPINs (connections inside connection blocks) + * 2. create edges between OPINs, CHANX and CHANY (connections inside switch blocks) + * 3. create edges between OPINs and IPINs (direct-connections) ***********************************************************************/ void build_edges_for_one_tileable_rr_gsb(RRGraphBuilder& rr_graph_builder, const RRGSB& rr_gsb, @@ -943,9 +943,9 @@ void build_edges_for_one_tileable_rr_gsb(RRGraphBuilder& rr_graph_builder, } /* Find CHANX or CHANY */ - /* For TRACKs to IPINs, we only care LEFT and TOP sides - * Skip RIGHT and BOTTOM for the ipin2track_map since they should be handled in other GSBs - */ + /* For TRACKs to IPINs, we only care LEFT and TOP sides + * Skip RIGHT and BOTTOM for the ipin2track_map since they should be handled in other GSBs + */ if ((side_manager.get_side() == rr_gsb.get_cb_chan_side(CHANX)) || (side_manager.get_side() == rr_gsb.get_cb_chan_side(CHANY))) { /* 2. create edges between CHANX|CHANY and IPINs, using ipin2track_map */ @@ -969,9 +969,9 @@ void build_edges_for_one_tileable_rr_gsb(RRGraphBuilder& rr_graph_builder, } /************************************************************************ - * Build track2ipin_map for an IPIN + * Build track2ipin_map for an IPIN * 1. build a list of routing tracks which are allowed for connections - * We will check the Connection Block (CB) population of each routing track. + * We will check the Connection Block (CB) population of each routing track. * By comparing current chan_y - ylow, we can determine if a CB connection * is required for each routing track * 2. Divide the routing tracks by segment types, so that we can balance @@ -1015,9 +1015,9 @@ static void build_gsb_one_ipin_track2pin_map(const RRGraphView& rr_graph, int actual_Fc = std::ceil((float)Fc[iseg] * (float)actual_track_list.size() / (float)chan_width); /* Minimum Fc should be 2 : ensure we will connect to a pair of routing tracks */ actual_Fc = std::max(1, actual_Fc); - /* Compute the step between two connection from this IPIN to tracks: - * step = W' / Fc', W' and Fc' are the adapted W and Fc from actual_track_list and Fc_in - */ + /* Compute the step between two connection from this IPIN to tracks: + * step = W' / Fc', W' and Fc' are the adapted W and Fc from actual_track_list and Fc_in + */ size_t track_step = std::floor((float)actual_track_list.size() / (float)actual_Fc); /* Make sure step should be at least 2 */ track_step = std::max(1, (int)track_step); @@ -1052,19 +1052,19 @@ static void build_gsb_one_ipin_track2pin_map(const RRGraphView& rr_graph, /* Ensure the number of tracks is similar to Fc */ /* Give a warning if Fc is < track_cnt */ /* - if (actual_Fc != track_cnt) { - vpr_printf(TIO_MESSAGE_INFO, - "IPIN Node(%lu) will have a different Fc(=%lu) than specified(=%lu)!\n", - ipin_node - rr_graph->rr_node, track_cnt, actual_Fc); - } - */ + * if (actual_Fc != track_cnt) { + * vpr_printf(TIO_MESSAGE_INFO, + * "IPIN Node(%lu) will have a different Fc(=%lu) than specified(=%lu)!\n", + * ipin_node - rr_graph->rr_node, track_cnt, actual_Fc); + * } + */ } } /************************************************************************ - * Build opin2track_map for an OPIN + * Build opin2track_map for an OPIN * 1. build a list of routing tracks which are allowed for connections - * We will check the Switch Block (SB) population of each routing track. + * We will check the Switch Block (SB) population of each routing track. * By comparing current chan_y - ylow, we can determine if a SB connection * is required for each routing track * 2. Divide the routing tracks by segment types, so that we can balance @@ -1112,9 +1112,9 @@ static void build_gsb_one_opin_pin2track_map(const RRGraphView& rr_graph, int actual_Fc = std::ceil((float)Fc[iseg] * (float)actual_track_list.size() / (float)chan_width); /* Minimum Fc should be 1 : ensure we will drive 1 routing track */ actual_Fc = std::max(1, actual_Fc); - /* Compute the step between two connection from this IPIN to tracks: - * step = W' / Fc', W' and Fc' are the adapted W and Fc from actual_track_list and Fc_in - */ + /* Compute the step between two connection from this IPIN to tracks: + * step = W' / Fc', W' and Fc' are the adapted W and Fc from actual_track_list and Fc_in + */ size_t track_step = std::floor((float)actual_track_list.size() / (float)actual_Fc); /* Track step mush be a multiple of 2!!!*/ /* Make sure step should be at least 1 */ @@ -1141,34 +1141,34 @@ static void build_gsb_one_opin_pin2track_map(const RRGraphView& rr_graph, opin2track_map[opin_side_index][opin_node_id].push_back(track_rr_node_index); /* update track counter */ track_cnt++; - /* Stop when we have enough Fc: this may lead to some tracks have zero drivers. - * So I comment it. And we just make sure its track_cnt >= actual_Fc - if (actual_Fc == track_cnt) { - break; - } - */ + /* Stop when we have enough Fc: this may lead to some tracks have zero drivers. + * So I comment it. And we just make sure its track_cnt >= actual_Fc + * if (actual_Fc == track_cnt) { + * break; + * } + */ } /* Ensure the number of tracks is similar to Fc */ /* Give a warning if Fc is < track_cnt */ /* - if (actual_Fc != track_cnt) { - vpr_printf(TIO_MESSAGE_INFO, - "OPIN Node(%lu) will have a different Fc(=%lu) than specified(=%lu)!\n", - opin_node_id, track_cnt, actual_Fc); - } - */ + * if (actual_Fc != track_cnt) { + * vpr_printf(TIO_MESSAGE_INFO, + * "OPIN Node(%lu) will have a different Fc(=%lu) than specified(=%lu)!\n", + * opin_node_id, track_cnt, actual_Fc); + * } + */ } } /************************************************************************ - * Build the track_to_ipin_map[gsb_side][0..chan_width-1][ipin_indices] + * Build the track_to_ipin_map[gsb_side][0..chan_width-1][ipin_indices] * based on the existing routing resources in the General Switch Block (GSB) - * This function supports both X-directional and Y-directional tracks + * This function supports both X-directional and Y-directional tracks * The mapping is done in the following steps: * 1. Build ipin_to_track_map[gsb_side][0..num_ipin_nodes-1][track_indices] * For each IPIN, we ensure at least one connection to the tracks. - * Then, we assign IPINs to tracks evenly while satisfying the actual_Fc + * Then, we assign IPINs to tracks evenly while satisfying the actual_Fc * 2. Convert the ipin_to_track_map to track_to_ipin_map ***********************************************************************/ t_track2pin_map build_gsb_track_to_ipin_map(const RRGraphView& rr_graph, @@ -1250,9 +1250,9 @@ t_track2pin_map build_gsb_track_to_ipin_map(const RRGraphView& rr_graph, } /************************************************************************ - * Build the opin_to_track_map[gsb_side][0..num_opin_nodes-1][track_indices] + * Build the opin_to_track_map[gsb_side][0..num_opin_nodes-1][track_indices] * based on the existing routing resources in the General Switch Block (GSB) - * This function supports both X-directional and Y-directional tracks + * This function supports both X-directional and Y-directional tracks * The mapping is done in the following steps: * 1. Build a list of routing tracks whose starting points locate at this GSB * (xlow - gsb_x == 0) @@ -1323,15 +1323,15 @@ t_pin2track_map build_gsb_opin_to_track_map(const RRGraphView& rr_graph, } /* Check: - * 1. We want to ensure that each OPIN will drive at least one track - * 2. We want to ensure that each track will be driven by at least 1 OPIN */ + * 1. We want to ensure that each OPIN will drive at least one track + * 2. We want to ensure that each track will be driven by at least 1 OPIN */ } return opin2track_map; } /************************************************************************ - * Add all direct clb-pin-to-clb-pin edges to given opin + * Add all direct clb-pin-to-clb-pin edges to given opin ***********************************************************************/ void build_direct_connections_for_one_gsb(const RRGraphView& rr_graph, RRGraphBuilder& rr_graph_builder, @@ -1352,9 +1352,9 @@ void build_direct_connections_for_one_gsb(const RRGraphView& rr_graph, continue; } - /* This opin is specified to connect directly to an ipin, - * now compute which ipin to connect to - */ + /* This opin is specified to connect directly to an ipin, + * now compute which ipin to connect to + */ vtr::Point to_grid_coordinate(from_grid_coordinate.x() + directs[i].x_offset, from_grid_coordinate.y() + directs[i].y_offset); @@ -1408,8 +1408,8 @@ void build_direct_connections_for_one_gsb(const RRGraphView& rr_graph, int to_grid_height_ofs = grids[to_grid_coordinate.x()][to_grid_coordinate.y()].height_offset; /* Find the side of grid pins, the pin location should be unique! - * Pin location is required by searching a node in rr_graph - */ + * Pin location is required by searching a node in rr_graph + */ std::vector opin_grid_side = find_grid_pin_sides(from_grid, opin); VTR_ASSERT(1 == opin_grid_side.size()); @@ -1434,14 +1434,14 @@ void build_direct_connections_for_one_gsb(const RRGraphView& rr_graph, IPIN, ipin, ipin_grid_side[0]); #endif /* - VTR_LOG("Direct connection: from grid[%lu][%lu].pin[%lu] at side %s to grid[%lu][%lu].pin[%lu] at side %s\n", - from_grid_coordinate.x() - from_grid_width_ofs, - from_grid_coordinate.y() - from_grid_height_ofs, - opin, SIDE_STRING[opin_grid_side[0]], - to_grid_coordinate.x() - to_grid_width_ofs, - to_grid_coordinate.y() - to_grid_height_ofs, - ipin, SIDE_STRING[ipin_grid_side[0]]); - */ + * VTR_LOG("Direct connection: from grid[%lu][%lu].pin[%lu] at side %s to grid[%lu][%lu].pin[%lu] at side %s\n", + * from_grid_coordinate.x() - from_grid_width_ofs, + * from_grid_coordinate.y() - from_grid_height_ofs, + * opin, SIDE_STRING[opin_grid_side[0]], + * to_grid_coordinate.x() - to_grid_width_ofs, + * to_grid_coordinate.y() - to_grid_height_ofs, + * ipin, SIDE_STRING[ipin_grid_side[0]]); + */ /* add edges to the opin_node */ diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp index 5c9f583658b..f64bde1340a 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp @@ -191,17 +191,17 @@ static size_t estimate_num_chanx_rr_nodes(const DeviceGrid& grids, bool force_end = false; /* All the tracks have to start when - * - the routing channel touch the RIGHT side a heterogeneous block - * - the routing channel touch the LEFT side of FPGA - */ + * - the routing channel touch the RIGHT side a heterogeneous block + * - the routing channel touch the LEFT side of FPGA + */ if (true == is_chanx_right_to_multi_height_grid(grids, chanx_coord, through_channel)) { force_start = true; } /* All the tracks have to end when - * - the routing channel touch the LEFT side a heterogeneous block - * - the routing channel touch the RIGHT side of FPGA - */ + * - the routing channel touch the LEFT side a heterogeneous block + * - the routing channel touch the RIGHT side of FPGA + */ if (true == is_chanx_left_to_multi_height_grid(grids, chanx_coord, through_channel)) { force_end = true; } @@ -243,17 +243,17 @@ static size_t estimate_num_chany_rr_nodes(const DeviceGrid& grids, bool force_end = false; /* All the tracks have to start when - * - the routing channel touch the TOP side a heterogeneous block - * - the routing channel touch the BOTTOM side of FPGA - */ + * - the routing channel touch the TOP side a heterogeneous block + * - the routing channel touch the BOTTOM side of FPGA + */ if (true == is_chany_top_to_multi_width_grid(grids, chany_coord, through_channel)) { force_start = true; } /* All the tracks have to end when - * - the routing channel touch the BOTTOM side a heterogeneous block - * - the routing channel touch the TOP side of FPGA - */ + * - the routing channel touch the BOTTOM side a heterogeneous block + * - the routing channel touch the TOP side of FPGA + */ if (true == is_chany_bottom_to_multi_width_grid(grids, chany_coord, through_channel)) { force_end = true; } @@ -280,28 +280,28 @@ static std::vector estimate_num_rr_nodes(const DeviceGrid& grids, std::vector num_rr_nodes_per_type(NUM_RR_TYPES, 0); /** - * 1 Find number of rr nodes related to grids - */ + * 1 Find number of rr nodes related to grids + */ num_rr_nodes_per_type[OPIN] = estimate_num_grid_rr_nodes_by_type(grids, OPIN); num_rr_nodes_per_type[IPIN] = estimate_num_grid_rr_nodes_by_type(grids, IPIN); num_rr_nodes_per_type[SOURCE] = estimate_num_grid_rr_nodes_by_type(grids, SOURCE); num_rr_nodes_per_type[SINK] = estimate_num_grid_rr_nodes_by_type(grids, SINK); /** - * 2. Assign the segments for each routing channel, - * To be specific, for each routing track, we assign a routing segment. - * The assignment is subject to users' specifications, such as - * a. length of each type of segment - * b. frequency of each type of segment. - * c. routing channel width - * - * SPECIAL for fringes: - * All segments will start and ends with no exception - * - * IMPORTANT: we should be aware that channel width maybe different - * in X-direction and Y-direction channels!!! - * So we will load segment details for different channels - */ + * 2. Assign the segments for each routing channel, + * To be specific, for each routing track, we assign a routing segment. + * The assignment is subject to users' specifications, such as + * a. length of each type of segment + * b. frequency of each type of segment. + * c. routing channel width + * + * SPECIAL for fringes: + * All segments will start and ends with no exception + * + * IMPORTANT: we should be aware that channel width maybe different + * in X-direction and Y-direction channels!!! + * So we will load segment details for different channels + */ num_rr_nodes_per_type[CHANX] = estimate_num_chanx_rr_nodes(grids, chan_width.x(), segment_infs, @@ -361,8 +361,8 @@ static void load_one_grid_opin_nodes_basic_info(RRGraphBuilder& rr_graph_builder SideManager io_side_manager(io_side); /* Walk through the width height of each grid, - * get pins and configure the rr_nodes - */ + * get pins and configure the rr_nodes + */ for (int width = 0; width < cur_grid.type->width; ++width) { for (int height = 0; height < cur_grid.type->height; ++height) { /* Walk through sides */ @@ -423,8 +423,8 @@ static void load_one_grid_ipin_nodes_basic_info(RRGraphBuilder& rr_graph_builder SideManager io_side_manager(io_side); /* Walk through the width and height of each grid, - * get pins and configure the rr_nodes - */ + * get pins and configure the rr_nodes + */ for (int width = 0; width < cur_grid.type->width; ++width) { for (int height = 0; height < cur_grid.type->height; ++height) { /* Walk through sides */ @@ -649,10 +649,10 @@ static void load_one_chan_rr_nodes_basic_info(RRGraphView& rr_graph, const std::vector& segment_infs, const int& cost_index_offset) { /* Check each node_id(potential ptc_num) in the channel : - * If this is a starting point, we set a new rr_node with xlow/ylow, ptc_num - * If this is a ending point, we set xhigh/yhigh and track_ids - * For other nodes, we set changes in track_ids - */ + * If this is a starting point, we set a new rr_node with xlow/ylow, ptc_num + * If this is a ending point, we set xhigh/yhigh and track_ids + * For other nodes, we set changes in track_ids + */ for (size_t itrack = 0; itrack < chan_details.get_chan_width(); ++itrack) { /* For INC direction, a starting point requires a new chan rr_node */ if (((true == chan_details.is_track_start(itrack)) @@ -731,8 +731,8 @@ static void load_one_chan_rr_nodes_basic_info(RRGraphView& rr_graph, VTR_ASSERT(chan_details.get_track_direction(itrack) == rr_graph.node_direction(rr_node_id)); /* Deposit xhigh and yhigh using the current chan_coordinate - * We will update when this track ends - */ + * We will update when this track ends + */ rr_graph_builder.set_node_coordinates(rr_node_id, rr_graph.node_xlow(rr_node_id), rr_graph.node_ylow(rr_node_id), chan_coordinate.x(), @@ -777,17 +777,17 @@ static void load_chanx_rr_nodes_basic_info(RRGraphView& rr_graph, bool force_end = false; /* All the tracks have to start when - * - the routing channel touch the RIGHT side a heterogeneous block - * - the routing channel touch the LEFT side of FPGA - */ + * - the routing channel touch the RIGHT side a heterogeneous block + * - the routing channel touch the LEFT side of FPGA + */ if (true == is_chanx_right_to_multi_height_grid(grids, chanx_coord, through_channel)) { force_start = true; } /* All the tracks have to end when - * - the routing channel touch the LEFT side a heterogeneous block - * - the routing channel touch the RIGHT side of FPGA - */ + * - the routing channel touch the LEFT side a heterogeneous block + * - the routing channel touch the RIGHT side of FPGA + */ if (true == is_chanx_left_to_multi_height_grid(grids, chanx_coord, through_channel)) { force_end = true; } @@ -797,40 +797,40 @@ static void load_chanx_rr_nodes_basic_info(RRGraphView& rr_graph, /* Force node_ids from the previous chanx */ if (0 < track_node_ids.size()) { /* Rotate should be done based on a typical case of routing tracks. - * Tracks on the borders are not regularly started and ended, - * which causes the node_rotation malfunction - */ + * Tracks on the borders are not regularly started and ended, + * which causes the node_rotation malfunction + */ ChanNodeDetails chanx_details_tt = build_unidir_chan_node_details(chan_width, grids.width() - 2, false, false, segment_infs); chanx_details_tt.set_track_node_ids(track_node_ids); /* TODO: - * Do NOT rotate the tracks when the routing channel - * locates inside a multi-height and multi-width grid - * Let the routing channel passing through the grid (if through channel is allowed!) - * An example: - * - * +------------------------------ - * | | - * | Grid | - * track0 ----->+-----------------------------+----> track0 - * | | - */ + * Do NOT rotate the tracks when the routing channel + * locates inside a multi-height and multi-width grid + * Let the routing channel passing through the grid (if through channel is allowed!) + * An example: + * + * +------------------------------ + * | | + * | Grid | + * track0 ----->+-----------------------------+----> track0 + * | | + */ if (true == is_chanx_exist(grids, chanx_coord, through_channel)) { /* Rotate the chanx_details by an offset of ix - 1, the distance to the most left channel */ /* For INC_DIRECTION, we use clockwise rotation - * node_id A ----> -----> node_id D - * node_id B ----> / ----> node_id A - * node_id C ----> / ----> node_id B - * node_id D ----> ----> node_id C - */ + * node_id A ----> -----> node_id D + * node_id B ----> / ----> node_id A + * node_id C ----> / ----> node_id B + * node_id D ----> ----> node_id C + */ chanx_details_tt.rotate_track_node_id(1, Direction::INC, true); /* For DEC_DIRECTION, we use clockwise rotation - * node_id A <----- <----- node_id B - * node_id B <----- \ <----- node_id C - * node_id C <----- \ <----- node_id D - * node_id D <----- <----- node_id A - */ + * node_id A <----- <----- node_id B + * node_id B <----- \ <----- node_id C + * node_id C <----- \ <----- node_id D + * node_id D <----- <----- node_id A + */ chanx_details_tt.rotate_track_node_id(1, Direction::DEC, false); } @@ -884,17 +884,17 @@ static void load_chany_rr_nodes_basic_info(RRGraphView& rr_graph, bool force_end = false; /* All the tracks have to start when - * - the routing channel touch the TOP side a heterogeneous block - * - the routing channel touch the BOTTOM side of FPGA - */ + * - the routing channel touch the TOP side a heterogeneous block + * - the routing channel touch the BOTTOM side of FPGA + */ if (true == is_chany_top_to_multi_width_grid(grids, chany_coord, through_channel)) { force_start = true; } /* All the tracks have to end when - * - the routing channel touch the BOTTOM side a heterogeneous block - * - the routing channel touch the TOP side of FPGA - */ + * - the routing channel touch the BOTTOM side a heterogeneous block + * - the routing channel touch the TOP side of FPGA + */ if (true == is_chany_bottom_to_multi_width_grid(grids, chany_coord, through_channel)) { force_end = true; } @@ -902,46 +902,46 @@ static void load_chany_rr_nodes_basic_info(RRGraphView& rr_graph, ChanNodeDetails chany_details = build_unidir_chan_node_details(chan_width, grids.height() - 2, force_start, force_end, segment_infs); /* Force node_ids from the previous chany - * This will not be applied when the routing channel is cut off (force to start) - */ + * This will not be applied when the routing channel is cut off (force to start) + */ if (0 < track_node_ids.size()) { /* Rotate should be done based on a typical case of routing tracks. - * Tracks on the borders are not regularly started and ended, - * which causes the node_rotation malfunction - */ + * Tracks on the borders are not regularly started and ended, + * which causes the node_rotation malfunction + */ ChanNodeDetails chany_details_tt = build_unidir_chan_node_details(chan_width, grids.height() - 2, false, false, segment_infs); chany_details_tt.set_track_node_ids(track_node_ids); /* TODO: - * Do NOT rotate the tracks when the routing channel - * locates inside a multi-height and multi-width grid - * Let the routing channel passing through the grid (if through channel is allowed!) - * An example: - * - * +------------------------------ - * | | - * | Grid | - * track0 ----->+-----------------------------+----> track0 - * | | - * we should rotate only once at the bottom side of a grid - */ + * Do NOT rotate the tracks when the routing channel + * locates inside a multi-height and multi-width grid + * Let the routing channel passing through the grid (if through channel is allowed!) + * An example: + * + * +------------------------------ + * | | + * | Grid | + * track0 ----->+-----------------------------+----> track0 + * | | + * we should rotate only once at the bottom side of a grid + */ if (true == is_chany_exist(grids, chany_coord, through_channel)) { /* Rotate the chany_details by an offset of 1*/ /* For INC_DIRECTION, we use clockwise rotation - * node_id A ----> -----> node_id D - * node_id B ----> / ----> node_id A - * node_id C ----> / ----> node_id B - * node_id D ----> ----> node_id C - */ + * node_id A ----> -----> node_id D + * node_id B ----> / ----> node_id A + * node_id C ----> / ----> node_id B + * node_id D ----> ----> node_id C + */ chany_details_tt.rotate_track_node_id(1, Direction::INC, true); /* For DEC_DIRECTION, we use clockwise rotation - * node_id A <----- <----- node_id B - * node_id B <----- \ <----- node_id C - * node_id C <----- \ <----- node_id D - * node_id D <----- <----- node_id A - */ + * node_id A <----- <----- node_id B + * node_id B <----- \ <----- node_id C + * node_id C <----- \ <----- node_id D + * node_id D <----- <----- node_id A + */ chany_details_tt.rotate_track_node_id(1, Direction::DEC, false); } From 3f4a404fe4ee3eebb830aacad2ad417b91f82ca9 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 13 Aug 2022 14:11:53 -0700 Subject: [PATCH 009/147] [vpr] add missing files --- vpr/src/tileable_rr_graph/clb2clb_directs.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 vpr/src/tileable_rr_graph/clb2clb_directs.h diff --git a/vpr/src/tileable_rr_graph/clb2clb_directs.h b/vpr/src/tileable_rr_graph/clb2clb_directs.h new file mode 100644 index 00000000000..7cc54bb8813 --- /dev/null +++ b/vpr/src/tileable_rr_graph/clb2clb_directs.h @@ -0,0 +1,16 @@ +#ifndef CLB2CLB_DIRECTS_H +#define CLB2CLB_DIRECTS_H + +#include "physical_types.h" + +struct t_clb_to_clb_directs { + t_physical_tile_type_ptr from_clb_type; + int from_clb_pin_start_index; + int from_clb_pin_end_index; + t_physical_tile_type_ptr to_clb_type; + int to_clb_pin_start_index; + int to_clb_pin_end_index; + int switch_index; //The switch type used by this direct connection +}; + +#endif From 6e2166330b70dc1edca9193b009f807326c905ab Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 13 Aug 2022 14:20:33 -0700 Subject: [PATCH 010/147] [vpr] add the declaration of common rr_graph building function to header file --- vpr/src/route/rr_graph.h | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/vpr/src/route/rr_graph.h b/vpr/src/route/rr_graph.h index c1a7a20f25b..0373c3efbd8 100644 --- a/vpr/src/route/rr_graph.h +++ b/vpr/src/route/rr_graph.h @@ -10,6 +10,7 @@ #include "vpr_types.h" #include "rr_graph_type.h" #include "describe_rr_node.h" +#include "clb2clb_directs.h" /* Warnings about the routing graph that can be returned. * This is to avoid output messages during a value sweep */ @@ -37,6 +38,26 @@ void free_rr_graph(); t_rr_switch_inf create_rr_switch_from_arch_switch(int arch_switch_idx, const float R_minW_nmos, const float R_minW_pmos); + +void alloc_and_load_rr_switch_inf(const int num_arch_switches, const float R_minW_nmos, const float R_minW_pmos, const int wire_to_arch_ipin_switch, int* wire_to_rr_ipin_switch); + +void rr_graph_externals(const std::vector& segment_inf, + const std::vector& segment_inf_x, + const std::vector& segment_inf_y, + int wire_to_rr_ipin_switch, + enum e_base_cost_type base_cost_type); + +t_clb_to_clb_directs* alloc_and_load_clb_to_clb_directs(const t_direct_inf* directs, const int num_directs, int delayless_switch); + +std::vector> alloc_and_load_actual_fc(const std::vector& types, + const int max_pins, + const std::vector& segment_inf, + const int* sets_per_seg_type, + const t_chan_width* nodes_per_chan, + const e_fc_type fc_type, + const enum e_directionality directionality, + bool* Fc_clipped); + // Sets the spec for the rr_switch based on the arch switch void load_rr_switch_from_arch_switch(int arch_switch_idx, int rr_switch_idx, From ac554b1ed9d6dbd2afc1310de5e9a4cb471905e1 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 13 Aug 2022 16:13:22 -0700 Subject: [PATCH 011/147] [vpr] cleaning up compilation errors --- vpr/src/base/vpr_context.h | 6 ++ .../tileable_rr_graph_builder.cpp | 62 +++---------------- .../tileable_rr_graph_node_builder.cpp | 19 ++++-- .../tileable_rr_graph_node_builder.h | 3 +- 4 files changed, 31 insertions(+), 59 deletions(-) diff --git a/vpr/src/base/vpr_context.h b/vpr/src/base/vpr_context.h index 17d0f55a3d5..8e3cb7effc0 100644 --- a/vpr/src/base/vpr_context.h +++ b/vpr/src/base/vpr_context.h @@ -192,6 +192,12 @@ struct DeviceContext : public Context { * for client functions: GUI, placer, router, timing analyzer etc. */ RRGraphView rr_graph{rr_graph_builder.rr_nodes(), rr_graph_builder.node_lookup(), rr_graph_builder.rr_node_metadata(), rr_graph_builder.rr_edge_metadata(), rr_indexed_data, rr_rc_data, rr_graph_builder.rr_segments(), rr_graph_builder.rr_switch()}; + + /* Track ids for each rr_node in the rr_graph. + * This is used by drawer for tileable routing resource graph + */ + std::map> rr_node_track_ids; + int num_arch_switches; t_arch_switch_inf* arch_switch_inf; // [0..(num_arch_switches-1)] diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp index ab759e8a219..2d34082c464 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp @@ -132,12 +132,10 @@ void build_tileable_unidir_rr_graph(const std::vector& typ delayless_rr_switch = rr_switch; } } -// NYI -#if 0 + /* Validate the special switches */ - VTR_ASSERT(true == device_ctx.rr_graph.validate_node(wire_to_ipin_rr_switch)); - VTR_ASSERT(true == device_ctx.rr_graph.validate_node(delayless_rr_switch)); -#endif + VTR_ASSERT(true == device_ctx.rr_graph.rr_nodes().validate_node(wire_to_ipin_rr_switch)); + VTR_ASSERT(true == device_ctx.rr_graph.rr_nodes().validate_node(delayless_rr_switch)); /* A temp data about the driver switch ids for each rr_node */ vtr::vector rr_node_driver_switches; @@ -162,6 +160,7 @@ void build_tileable_unidir_rr_graph(const std::vector& typ device_ctx.rr_graph_builder, rr_node_driver_switches, rr_node_track_ids, + device_ctx.rr_rc_data, grids, device_chan_width, segment_inf, @@ -262,15 +261,6 @@ void build_tileable_unidir_rr_graph(const std::vector& typ build_rr_graph_direct_connections(device_ctx.rr_graph, device_ctx.rr_graph_builder, device_ctx.grid, delayless_rr_switch, arch_directs, clb2clb_directs); -//NYI -// We may not need to rebuild it again -#if 0 - /* First time to build edges so that we can remap the architecture switch to rr_switch - * This is a must-do before function alloc_and_load_rr_switch_inf() - */ - device_ctx.rr_graph.rebuild_node_edges(); -#endif - /* Allocate and load routing resource switches, which are derived from the switches from the architecture file, * based on their fanin in the rr graph. This routine also adjusts the rr nodes to point to these new rr switches */ alloc_and_load_rr_switch_inf(device_ctx.num_arch_switches, R_minW_nmos, R_minW_pmos, wire_to_arch_ipin_switch, wire_to_rr_ipin_switch); @@ -278,11 +268,8 @@ void build_tileable_unidir_rr_graph(const std::vector& typ /* Save the channel widths for the newly constructed graph */ device_ctx.chan_width = chan_width; -//NYI -#if 0 - /* Save the track ids for tileable routing resource graph */ - device_ctx.rr_node_track_ids = rr_node_track_ids; -#endif + /* Save the track ids for tileable routing resource graph */ + device_ctx.rr_node_track_ids = rr_node_track_ids; /************************************************************************ * Allocate external data structures @@ -295,25 +282,6 @@ void build_tileable_unidir_rr_graph(const std::vector& typ rr_graph_externals(segment_inf, segment_inf_x, segment_inf_y, *wire_to_rr_ipin_switch, base_cost_type); - /* Rebuild the link between RRGraph node and segments - * Should be called only AFTER the function - * rr_graph_externals() - */ - for (const RRNodeId& inode : device_ctx.rr_graph.nodes()) { - if ((CHANX != device_ctx.rr_graph.node_type(inode)) - && (CHANY != device_ctx.rr_graph.node_type(inode))) { - continue; - } -// NYI -#if 0 - RRIndexedDataId irc_data = device_ctx.rr_graph.node_cost_index(inode); - short iseg = device_ctx.rr_indexed_data[irc_data].seg_index; - // device_ctx.rr_graph_builder.set_node_segment(inode, RRSegmentId(iseg)); // NYI - vtr::vector rr_segments = device_ctx.rr_graph_builder.rr_segments(); - rr_segments[(RRSegmentId)iseg] = segment_inf; -#endif - } - /************************************************************************ * Sanitizer for the rr_graph, check connectivities of rr_nodes ***********************************************************************/ @@ -326,22 +294,8 @@ void build_tileable_unidir_rr_graph(const std::vector& typ "Fundamental errors occurred when validating rr_graph object!\n"); } - check_rr_graph(GRAPH_UNIDIR, grids, types); - - // NYI - // vpr integration: DeviceContext does not provide direct RRGraph access - // for advanced rr graph checker in check_rr_graph_obj.h, needs rr graph object - // rr graph view won't work here -#if 0 - /* Error out if advanced checker of rr_graph fails */ - if (false == check_rr_graph(device_ctx.rr_graph)) { - vpr_throw(VPR_ERROR_ROUTE, - __FILE__, - __LINE__, - "Advanced checking rr_graph object fails! Routing may still work " - "but not smooth\n"); - } -#endif + /* No clock network support yet */ + check_rr_graph(device_ctx.rr_graph, types, device_ctx.rr_indexed_data, grids, device_ctx.chan_width, GRAPH_UNIDIR, OPEN); /************************************************************************ * Free all temp stucts diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp index f64bde1340a..17054fc5d28 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp @@ -354,6 +354,7 @@ void alloc_tileable_rr_graph_nodes(RRGraphBuilder& rr_graph_builder, ***********************************************************************/ static void load_one_grid_opin_nodes_basic_info(RRGraphBuilder& rr_graph_builder, vtr::vector& rr_node_driver_switches, + std::vector& rr_rc_data, const vtr::Point& grid_coordinate, const t_grid_tile& cur_grid, const e_side& io_side, @@ -399,7 +400,7 @@ static void load_one_grid_opin_nodes_basic_info(RRGraphBuilder& rr_graph_builder rr_node_driver_switches.push_back(delayless_switch); /* RC data */ - rr_graph_builder.set_node_rc_index(node, NodeRCIndex(find_create_rr_rc_data(0., 0.))); + rr_graph_builder.set_node_rc_index(node, NodeRCIndex(find_create_rr_rc_data(0., 0., rr_rc_data))); } /* End of loading OPIN rr_nodes */ } /* End of side enumeration */ @@ -416,6 +417,7 @@ static void load_one_grid_opin_nodes_basic_info(RRGraphBuilder& rr_graph_builder ***********************************************************************/ static void load_one_grid_ipin_nodes_basic_info(RRGraphBuilder& rr_graph_builder, vtr::vector& rr_node_driver_switches, + std::vector& rr_rc_data, const vtr::Point& grid_coordinate, const t_grid_tile& cur_grid, const e_side& io_side, @@ -461,7 +463,7 @@ static void load_one_grid_ipin_nodes_basic_info(RRGraphBuilder& rr_graph_builder rr_node_driver_switches.push_back(wire_to_ipin_switch); /* RC data */ - rr_graph_builder.set_node_rc_index(node, NodeRCIndex(find_create_rr_rc_data(0., 0.))); + rr_graph_builder.set_node_rc_index(node, NodeRCIndex(find_create_rr_rc_data(0., 0., rr_rc_data))); } /* End of loading IPIN rr_nodes */ } /* End of side enumeration */ @@ -478,6 +480,7 @@ static void load_one_grid_ipin_nodes_basic_info(RRGraphBuilder& rr_graph_builder ***********************************************************************/ static void load_one_grid_source_nodes_basic_info(RRGraphBuilder& rr_graph_builder, vtr::vector& rr_node_driver_switches, + std::vector& rr_rc_data, const vtr::Point& grid_coordinate, const t_grid_tile& cur_grid, const e_side& io_side, @@ -514,7 +517,7 @@ static void load_one_grid_source_nodes_basic_info(RRGraphBuilder& rr_graph_build rr_node_driver_switches.push_back(delayless_switch); /* RC data */ - rr_graph_builder.set_node_rc_index(node, NodeRCIndex(find_create_rr_rc_data(0., 0.))); + rr_graph_builder.set_node_rc_index(node, NodeRCIndex(find_create_rr_rc_data(0., 0., rr_rc_data))); } /* End of class enumeration */ } @@ -528,6 +531,7 @@ static void load_one_grid_source_nodes_basic_info(RRGraphBuilder& rr_graph_build ***********************************************************************/ static void load_one_grid_sink_nodes_basic_info(RRGraphBuilder& rr_graph_builder, vtr::vector& rr_node_driver_switches, + std::vector& rr_rc_data, const vtr::Point& grid_coordinate, const t_grid_tile& cur_grid, const e_side& io_side, @@ -564,7 +568,7 @@ static void load_one_grid_sink_nodes_basic_info(RRGraphBuilder& rr_graph_builder rr_node_driver_switches.push_back(delayless_switch); /* RC data */ - rr_graph_builder.set_node_rc_index(node, NodeRCIndex(find_create_rr_rc_data(0., 0.))); + rr_graph_builder.set_node_rc_index(node, NodeRCIndex(find_create_rr_rc_data(0., 0., rr_rc_data))); } /* End of class enumeration */ } @@ -574,6 +578,7 @@ static void load_one_grid_sink_nodes_basic_info(RRGraphBuilder& rr_graph_builder ***********************************************************************/ static void load_grid_nodes_basic_info(RRGraphBuilder& rr_graph_builder, vtr::vector& rr_node_driver_switches, + std::vector& rr_rc_data, const DeviceGrid& grids, const RRSwitchId& wire_to_ipin_switch, const RRSwitchId& delayless_switch) { @@ -602,6 +607,7 @@ static void load_grid_nodes_basic_info(RRGraphBuilder& rr_graph_builder, /* Configure source rr_nodes for this grid */ load_one_grid_source_nodes_basic_info(rr_graph_builder, rr_node_driver_switches, + rr_rc_data, grid_coordinate, grids[ix][iy], io_side, @@ -610,6 +616,7 @@ static void load_grid_nodes_basic_info(RRGraphBuilder& rr_graph_builder, /* Configure sink rr_nodes for this grid */ load_one_grid_sink_nodes_basic_info(rr_graph_builder, rr_node_driver_switches, + rr_rc_data, grid_coordinate, grids[ix][iy], io_side, @@ -618,6 +625,7 @@ static void load_grid_nodes_basic_info(RRGraphBuilder& rr_graph_builder, /* Configure opin rr_nodes for this grid */ load_one_grid_opin_nodes_basic_info(rr_graph_builder, rr_node_driver_switches, + rr_rc_data, grid_coordinate, grids[ix][iy], io_side, @@ -626,6 +634,7 @@ static void load_grid_nodes_basic_info(RRGraphBuilder& rr_graph_builder, /* Configure ipin rr_nodes for this grid */ load_one_grid_ipin_nodes_basic_info(rr_graph_builder, rr_node_driver_switches, + rr_rc_data, grid_coordinate, grids[ix][iy], io_side, @@ -1001,6 +1010,7 @@ void create_tileable_rr_graph_nodes(RRGraphView& rr_graph, RRGraphBuilder& rr_graph_builder, vtr::vector& rr_node_driver_switches, std::map>& rr_node_track_ids, + std::vector& rr_rc_data, const DeviceGrid& grids, const vtr::Point& chan_width, const std::vector& segment_infs, @@ -1009,6 +1019,7 @@ void create_tileable_rr_graph_nodes(RRGraphView& rr_graph, const bool& through_channel) { load_grid_nodes_basic_info(rr_graph_builder, rr_node_driver_switches, + rr_rc_data, grids, wire_to_ipin_switch, delayless_switch); diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.h b/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.h index cb8839018a7..116f51e3a89 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.h +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.h @@ -11,8 +11,8 @@ #include "physical_types.h" /* Headers from vpr library */ -#include "rr_graph_obj.h" #include "device_grid.h" +#include "rr_node_types.h" #include "rr_graph_view.h" #include "rr_graph_builder.h" @@ -31,6 +31,7 @@ void create_tileable_rr_graph_nodes(RRGraphView& rr_graph, RRGraphBuilder& rr_graph_builder, vtr::vector& rr_node_driver_switches, std::map>& rr_node_track_ids, + std::vector& rr_rc_data, const DeviceGrid& grids, const vtr::Point& chan_width, const std::vector& segment_infs, From 7490a21bc70ae43d826cc66f19468415a51b451b Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 13 Aug 2022 17:24:02 -0700 Subject: [PATCH 012/147] [vpr] adapting API in tileable rr_graph builder --- libs/librrgraph/src/base/rr_graph_view.h | 7 +++- .../tileable_rr_graph_builder.cpp | 4 +-- .../tileable_rr_graph_node_builder.cpp | 34 ++++++++----------- 3 files changed, 22 insertions(+), 23 deletions(-) diff --git a/libs/librrgraph/src/base/rr_graph_view.h b/libs/librrgraph/src/base/rr_graph_view.h index 6d0c995864b..ffea6084e18 100644 --- a/libs/librrgraph/src/base/rr_graph_view.h +++ b/libs/librrgraph/src/base/rr_graph_view.h @@ -462,7 +462,7 @@ class RRGraphView { } public: /* Validators */ - /** brief Validate that edge data is partitioned correctly + /** @brief Validate that edge data is partitioned correctly * @note This function is used to validate the correctness of the routing resource graph in terms * of graph attributes. Strongly recommend to call it when you finish the building a routing resource * graph. If you need more advance checks, which are related to architecture features, you should @@ -471,6 +471,11 @@ class RRGraphView { return node_storage_.validate_node(node_id, rr_switch_inf_); } + /** @brief Check if the switch is a valid one in storage */ + inline bool valid_switch(RRSwitchId switch_id) const { + return (size_t(switch_id) < rr_switch_inf_.size()); + } + /* -- Internal data storage -- */ /* Note: only read-only object or data structures are allowed!!! */ private: diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp index 2d34082c464..cd8c5aa2f83 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp @@ -134,8 +134,8 @@ void build_tileable_unidir_rr_graph(const std::vector& typ } /* Validate the special switches */ - VTR_ASSERT(true == device_ctx.rr_graph.rr_nodes().validate_node(wire_to_ipin_rr_switch)); - VTR_ASSERT(true == device_ctx.rr_graph.rr_nodes().validate_node(delayless_rr_switch)); + VTR_ASSERT(true == device_ctx.rr_graph.valid_switch(wire_to_ipin_rr_switch)); + VTR_ASSERT(true == device_ctx.rr_graph.valid_switch(delayless_rr_switch)); /* A temp data about the driver switch ids for each rr_node */ vtr::vector rr_node_driver_switches; diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp index 17054fc5d28..9662cb52bcd 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp @@ -979,28 +979,22 @@ static void load_chany_rr_nodes_basic_info(RRGraphView& rr_graph, * However, DEC direction routing tracks should have a reversed sequence in * track ids ***********************************************************************/ -static void reverse_dec_chan_rr_node_track_ids(const RRGraphBuilder& rr_graph_builder, +static void reverse_dec_chan_rr_node_track_ids(const RRGraphView& rr_graph, std::map>& rr_node_track_ids) { - // NYI - // unused parameters - (void)(rr_graph_builder); - (void)(rr_node_track_ids); -#if 0 // this should call rr_graph_builder to do the job - for (const RRNodeId& node : rr_graph_builder.nodes()) { - /* Bypass condition: only focus on CHANX and CHANY in DEC_DIRECTION */ - if ( (CHANX != rr_graph_builder.node_type(node)) - && (CHANY != rr_graph_builder.node_type(node)) ) { - continue; - } - /* Reach here, we must have a node of CHANX or CHANY */ - if (Direction::DEC != rr_graph_builder.node_direction(node)) { - continue; + for (const RRNodeId& node : rr_graph.nodes()) { + /* Bypass condition: only focus on CHANX and CHANY in DEC_DIRECTION */ + if ( (CHANX != rr_graph.node_type(node)) + && (CHANY != rr_graph.node_type(node)) ) { + continue; + } + /* Reach here, we must have a node of CHANX or CHANY */ + if (Direction::DEC != rr_graph.node_direction(node)) { + continue; + } + std::reverse(rr_node_track_ids[node].begin(), + rr_node_track_ids[node].end() ); } - std::reverse(rr_node_track_ids[node].begin(), - rr_node_track_ids[node].end() ); - } -#endif } /************************************************************************ @@ -1042,6 +1036,6 @@ void create_tileable_rr_graph_nodes(RRGraphView& rr_graph, segment_infs, through_channel); - reverse_dec_chan_rr_node_track_ids(rr_graph_builder, + reverse_dec_chan_rr_node_track_ids(rr_graph, rr_node_track_ids); } From e4fa74700ff37747ff27eaec7b4812a30d3cd950 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 13 Aug 2022 17:53:18 -0700 Subject: [PATCH 013/147] [vpr] adapting apis in tileable rr_graph builder --- .../tileable_rr_graph_edge_builder.cpp | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp index c261af8f655..ea031c0467e 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp @@ -68,14 +68,10 @@ void build_rr_graph_edges_for_sink_nodes(const RRGraphView& rr_graph, short sink_node_class_num = get_grid_pin_class_index(grids[xlow][ylow], rr_graph.node_pin_num(node)); /* 1. create edges between IPINs and SINKs */ - // NYI - (void)(sink_node_class_num); -#if 0 - const RRNodeId& sink_node = rr_graph.find_node(xlow - grids[xlow][ylow].width_offset, - ylow - grids[xlow][ylow].height_offset, - SINK, sink_node_class_num); - VTR_ASSERT(true == rr_graph.valid_node_id(sink_node)); -#endif + const RRNodeId& sink_node = rr_graph.node_lookup().find_node(xlow - grids[xlow][ylow].width_offset, + ylow - grids[xlow][ylow].height_offset, + SINK, sink_node_class_num); + VTR_ASSERT(true == rr_graph.validate_node(sink_node)); // NYI (void)(rr_node_driver_switches); From 11015885c2060dcd02cc2b22f07fedf5e6fbee75 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 13 Aug 2022 20:02:47 -0700 Subject: [PATCH 014/147] [vpr] enrich error message in rr_gsb --- vpr/src/tileable_rr_graph/rr_gsb.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/vpr/src/tileable_rr_graph/rr_gsb.cpp b/vpr/src/tileable_rr_graph/rr_gsb.cpp index d1b6f7e4a18..f02d2ef4be5 100644 --- a/vpr/src/tileable_rr_graph/rr_gsb.cpp +++ b/vpr/src/tileable_rr_graph/rr_gsb.cpp @@ -446,13 +446,11 @@ bool RRGSB::is_sb_node_passing_wire(const RRGraphView& rr_graph, * we should be able to find the node on the opposite side of the GSB! */ if (true != is_sb_node_exist_opposite_side(rr_graph, track_node, node_side)) { - VTR_LOG("GSB[%lu][%lu] track node[%lu] at %s:\n", + VTR_LOG("Cannot find a node on the opposite side to GSB[%lu][%lu] track node[%lu] at %s!\nDetailed node information:\n", get_x(), get_y(), track_id, SIDE_STRING[node_side]); - -// NYI -#if 0 - rr_graph.print_node(track_node); -#endif + VTR_LOG("Node type: %s\n", rr_graph.node_type_string(track_node)); + VTR_LOG("Node coordinate: %d\n", rr_graph.node_coordinate_to_string(track_node).c_str()); + VTR_LOG("Node ptc: %d\n", rr_graph.node_ptc_num(track_node)); } VTR_ASSERT(true == is_sb_node_exist_opposite_side(rr_graph, track_node, node_side)); From 2bbb7f2417ba22780aaa781fa7b0086e8e125b96 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sun, 14 Aug 2022 10:49:06 -0700 Subject: [PATCH 015/147] [vpr] integrating edge builder to rrgraph builder --- libs/librrgraph/src/base/rr_graph_builder.cpp | 12 ++++++ libs/librrgraph/src/base/rr_graph_builder.h | 22 +++++++++- .../tileable_rr_graph_edge_builder.cpp | 14 +++---- .../tileable_rr_graph_gsb.cpp | 41 ++++--------------- 4 files changed, 44 insertions(+), 45 deletions(-) diff --git a/libs/librrgraph/src/base/rr_graph_builder.cpp b/libs/librrgraph/src/base/rr_graph_builder.cpp index 535e027ca9f..88ed3e042e4 100644 --- a/libs/librrgraph/src/base/rr_graph_builder.cpp +++ b/libs/librrgraph/src/base/rr_graph_builder.cpp @@ -66,6 +66,7 @@ void RRGraphBuilder::clear() { rr_edge_metadata_.clear(); rr_segments_.clear(); rr_switch_inf_.clear(); + edges_to_build_.clear(); } void RRGraphBuilder::reorder_nodes(e_rr_node_reorder_algorithm reorder_rr_graph_nodes_algorithm, @@ -137,3 +138,14 @@ void RRGraphBuilder::reorder_nodes(e_rr_node_reorder_algorithm reorder_rr_graph_ std::get<2>(edge)); }); } + +void RRGraphBuilder::create_edge(RRNodeId src, RRNodeId dest, RRSwitchId edge_switch) { + edges_to_build_.emplace_back(src, dest, size_t(edge_switch)); +} + +void RRGraphBuilder::build_edges() { + std::sort(edges_to_build_.begin(), edges_to_build_.end()); + edges_to_build_.erase(std::unique(edges_to_build_.begin(), edges_to_build_.end()), edges_to_build_.end()); + alloc_and_load_edges(&edges_to_build_); + edges_to_build_.clear(); +} diff --git a/libs/librrgraph/src/base/rr_graph_builder.h b/libs/librrgraph/src/base/rr_graph_builder.h index df3018e928a..000ee750fbd 100644 --- a/libs/librrgraph/src/base/rr_graph_builder.h +++ b/libs/librrgraph/src/base/rr_graph_builder.h @@ -16,6 +16,7 @@ #include "rr_graph_storage.h" #include "rr_spatial_lookup.h" #include "metadata_storage.h" +#include "rr_edge.h" class RRGraphBuilder { /* -- Constructors -- */ @@ -200,6 +201,15 @@ class RRGraphBuilder { node_storage_.set_node_direction(id, new_direction); } + /** @brief Add a new edge to the cache of edges to be built + * .. note:: This will not add an edge to storage! You need to call build_edges() after all the edges are cached! */ + void create_edge(RRNodeId src, RRNodeId dest, RRSwitchId edge_switch); + + /** @brief Allocate and build actual edges in storage. + * Once called, the cached edges will be uniquified and added to routing resource nodes, + * while the cache will be empty once build-up is accomplished */ + void build_edges(); + /** @brief Reserve the lists of edges to be memory efficient. * This function is mainly used to reserve memory space inside RRGraph, * when adding a large number of edges in order to avoid memory fragements */ @@ -285,13 +295,13 @@ class RRGraphBuilder { rr_switch_inf_.resize(size); } - /** @brief Validate that edge data is partitioned correctly + /** @brief Validate that edge data is partitioned correctly. Also there are no edges left to be built! * @note This function is used to validate the correctness of the routing resource graph in terms * of graph attributes. Strongly recommend to call it when you finish the building a routing resource * graph. If you need more advance checks, which are related to architecture features, you should * consider to use the check_rr_graph() function or build your own check_rr_graph() function. */ inline bool validate() const { - return node_storage_.validate(rr_switch_inf_); + return node_storage_.validate(rr_switch_inf_) && edges_to_build_.empty(); } /** @brief Sorts edge data such that configurable edges appears before @@ -325,6 +335,14 @@ class RRGraphBuilder { /* Fast look-up for rr nodes */ RRSpatialLookup node_lookup_; + /* A cache for edge-related information, required to build edges for routing resource nodes. + * It is used when building a routing resource graph by considering memory efficiency. + * It will be clear up after calling build_edges(). + * + * .. warning:: This is a temporary data which is used to collect edges to be built for nodes + */ + t_rr_edge_info_set edges_to_build_; + /** Wire segment types in RR graph * - Each rr_segment contains the detailed information of a routing track, which is denoted by a node in CHANX or CHANY type. * - We use a fly-weight data structure here, in the same philosophy as the rr_indexed_data. See detailed explanation in the t_segment_inf data structure diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp index ea031c0467e..317cafca793 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp @@ -40,13 +40,11 @@ void build_rr_graph_edges_for_source_nodes(const RRGraphView& rr_graph, SOURCE, src_node_class_num); VTR_ASSERT(true == rr_graph.validate_node(src_node)); - // NYI - (void)(rr_node_driver_switches); -#if 0 /* add edges to the src_node */ rr_graph_builder.create_edge(src_node, node, rr_node_driver_switches[node]); -#endif } + /* Allocate edges for all the source nodes */ + rr_graph_builder.build_edges(); } /************************************************************************ @@ -73,14 +71,11 @@ void build_rr_graph_edges_for_sink_nodes(const RRGraphView& rr_graph, SINK, sink_node_class_num); VTR_ASSERT(true == rr_graph.validate_node(sink_node)); - // NYI - (void)(rr_node_driver_switches); - (void)(rr_graph_builder); -#if 0 /* add edges to connect the IPIN node to SINK nodes */ rr_graph_builder.create_edge(node, sink_node, rr_node_driver_switches[sink_node]); -#endif } + /* Allocate edges for all the source nodes */ + rr_graph_builder.build_edges(); } /************************************************************************ @@ -142,6 +137,7 @@ void build_rr_graph_edges(const RRGraphView& rr_graph, track2ipin_map, opin2track_map, sb_conn, rr_node_driver_switches); /* Finish this GSB, go to the next*/ + rr_graph_builder.build_edges(); } } } diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp index 978341a7399..cad2574d51a 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp @@ -917,15 +917,6 @@ void build_edges_for_one_tileable_rr_gsb(RRGraphBuilder& rr_graph_builder, const t_pin2track_map& opin2track_map, const t_track2track_map& track2track_map, const vtr::vector& rr_node_driver_switches) { - // NYI - // unused parameters - (void)(rr_graph_builder); - (void)(rr_gsb); - (void)(track2ipin_map); - (void)(opin2track_map); - (void)(track2track_map); - (void)(rr_node_driver_switches); -#if 0 /* Walk through each sides */ for (size_t side = 0; side < rr_gsb.get_num_sides(); ++side) { SideManager side_manager(side); @@ -965,7 +956,6 @@ void build_edges_for_one_tileable_rr_gsb(RRGraphBuilder& rr_graph_builder, } } } -#endif } /************************************************************************ @@ -1416,23 +1406,12 @@ void build_direct_connections_for_one_gsb(const RRGraphView& rr_graph, std::vector ipin_grid_side = find_grid_pin_sides(grids[to_grid_coordinate.x()][to_grid_coordinate.y()], ipin); VTR_ASSERT(1 == ipin_grid_side.size()); - // NYI - // unused parameters - (void)(rr_graph); - (void)(rr_graph_builder); - // unused variables - (void)(from_grid_width_ofs); - (void)(from_grid_height_ofs); - (void)(to_grid_width_ofs); - (void)(to_grid_height_ofs); -#if 0 - const RRNodeId& opin_node_id = rr_graph.find_node(from_grid_coordinate.x() - from_grid_width_ofs, - from_grid_coordinate.y() - from_grid_height_ofs, - OPIN, opin, opin_grid_side[0]); - const RRNodeId& ipin_node_id = rr_graph.find_node(to_grid_coordinate.x() - to_grid_width_ofs, - to_grid_coordinate.y() - to_grid_height_ofs, - IPIN, ipin, ipin_grid_side[0]); -#endif + const RRNodeId& opin_node_id = rr_graph.node_lookup().find_node(from_grid_coordinate.x() - from_grid_width_ofs, + from_grid_coordinate.y() - from_grid_height_ofs, + OPIN, opin, opin_grid_side[0]); + const RRNodeId& ipin_node_id = rr_graph.node_lookup().find_node(to_grid_coordinate.x() - to_grid_width_ofs, + to_grid_coordinate.y() - to_grid_height_ofs, + IPIN, ipin, ipin_grid_side[0]); /* * VTR_LOG("Direct connection: from grid[%lu][%lu].pin[%lu] at side %s to grid[%lu][%lu].pin[%lu] at side %s\n", * from_grid_coordinate.x() - from_grid_width_ofs, @@ -1445,13 +1424,7 @@ void build_direct_connections_for_one_gsb(const RRGraphView& rr_graph, /* add edges to the opin_node */ - // NYI - // unused parameters - (void)(delayless_switch); -#if 0 - rr_graph_builder.create_edge(opin_node_id, ipin_node_id, - delayless_switch); -#endif + rr_graph_builder.create_edge(opin_node_id, ipin_node_id, delayless_switch); } } } From 4d46b4761ee727d43ff3805cdf47b1b134f5cd85 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sun, 14 Aug 2022 12:34:28 -0700 Subject: [PATCH 016/147] [vpr] syntax error --- vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp index cad2574d51a..52c9ab56d2c 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp @@ -952,7 +952,7 @@ void build_edges_for_one_tileable_rr_gsb(RRGraphBuilder& rr_graph_builder, for (size_t inode = 0; inode < rr_gsb.get_chan_width(gsb_side); ++inode) { const RRNodeId& chan_node = rr_gsb.get_chan_node(gsb_side, inode); for (const RRNodeId& track_node : track2track_map[gsb_side][inode]) { - rr_graph.create_edge(chan_node, track_node, rr_node_driver_switches[track_node]); + rr_graph_builder.create_edge(chan_node, track_node, rr_node_driver_switches[track_node]); } } } From 3ecee3e522d21b97f713c9a97ef15d00271ebe05 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sun, 14 Aug 2022 13:08:14 -0700 Subject: [PATCH 017/147] [vpr] rename header file --- .../{rr_graph_obj_util.cpp => rr_graph_view_util.cpp} | 3 +-- .../{rr_graph_obj_util.h => rr_graph_view_util.h} | 5 ++--- vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp | 2 +- 3 files changed, 4 insertions(+), 6 deletions(-) rename vpr/src/tileable_rr_graph/{rr_graph_obj_util.cpp => rr_graph_view_util.cpp} (98%) rename vpr/src/tileable_rr_graph/{rr_graph_obj_util.h => rr_graph_view_util.h} (94%) diff --git a/vpr/src/tileable_rr_graph/rr_graph_obj_util.cpp b/vpr/src/tileable_rr_graph/rr_graph_view_util.cpp similarity index 98% rename from vpr/src/tileable_rr_graph/rr_graph_obj_util.cpp rename to vpr/src/tileable_rr_graph/rr_graph_view_util.cpp index d389ab757e4..637c926872e 100644 --- a/vpr/src/tileable_rr_graph/rr_graph_obj_util.cpp +++ b/vpr/src/tileable_rr_graph/rr_graph_view_util.cpp @@ -2,8 +2,7 @@ * This file include most-utilized functions that manipulate on the * RRGraph object ***************************************************************************/ -#include "rr_graph_obj.h" -#include "rr_graph_obj_util.h" +#include "rr_graph_view_util.h" /**************************************************************************** * Find the switches interconnecting two nodes diff --git a/vpr/src/tileable_rr_graph/rr_graph_obj_util.h b/vpr/src/tileable_rr_graph/rr_graph_view_util.h similarity index 94% rename from vpr/src/tileable_rr_graph/rr_graph_obj_util.h rename to vpr/src/tileable_rr_graph/rr_graph_view_util.h index f32957e43c2..0834f34ef22 100644 --- a/vpr/src/tileable_rr_graph/rr_graph_obj_util.h +++ b/vpr/src/tileable_rr_graph/rr_graph_view_util.h @@ -1,11 +1,10 @@ -#ifndef RR_GRAPH_OBJ_UTIL_H -#define RR_GRAPH_OBJ_UTIL_H +#ifndef RR_GRAPH_VIEW_UTIL_H +#define RR_GRAPH_VIEW_UTIL_H /* Include header files which include data structures used by * the function declaration */ #include -#include "rr_graph_obj.h" #include "device_grid.h" #include "rr_graph_view.h" diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp index 52c9ab56d2c..2df3a759286 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp @@ -14,7 +14,7 @@ #include "openfpga_side_manager.h" #include "vpr_utils.h" -#include "rr_graph_obj_util.h" +#include "rr_graph_view_util.h" #include "openfpga_rr_graph_utils.h" #include "rr_graph_builder_utils.h" #include "tileable_chan_details_builder.h" From 2b71a2cb1cd5d423ed5ed227e836c90079e4257c Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sun, 14 Aug 2022 14:33:16 -0700 Subject: [PATCH 018/147] [vpr] add api for node_in_edges --- libs/librrgraph/src/base/rr_graph_builder.cpp | 36 ++++++++++++++++++- libs/librrgraph/src/base/rr_graph_builder.h | 18 ++++++++++ 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/libs/librrgraph/src/base/rr_graph_builder.cpp b/libs/librrgraph/src/base/rr_graph_builder.cpp index 88ed3e042e4..baf353322bf 100644 --- a/libs/librrgraph/src/base/rr_graph_builder.cpp +++ b/libs/librrgraph/src/base/rr_graph_builder.cpp @@ -7,7 +7,10 @@ //#include "globals.h" -RRGraphBuilder::RRGraphBuilder() {} +RRGraphBuilder::RRGraphBuilder() { + is_edge_dirty_ = true; + is_incoming_edge_dirty_ = true; +} t_rr_graph_storage& RRGraphBuilder::rr_nodes() { return node_storage_; @@ -67,6 +70,8 @@ void RRGraphBuilder::clear() { rr_segments_.clear(); rr_switch_inf_.clear(); edges_to_build_.clear(); + is_edge_dirty_ = true; + is_incoming_edge_dirty_ = true; } void RRGraphBuilder::reorder_nodes(e_rr_node_reorder_algorithm reorder_rr_graph_nodes_algorithm, @@ -141,6 +146,8 @@ void RRGraphBuilder::reorder_nodes(e_rr_node_reorder_algorithm reorder_rr_graph_ void RRGraphBuilder::create_edge(RRNodeId src, RRNodeId dest, RRSwitchId edge_switch) { edges_to_build_.emplace_back(src, dest, size_t(edge_switch)); + is_edge_dirty_ = true; /* Adding a new edge revokes the flag */ + is_incoming_edge_dirty_ = true; } void RRGraphBuilder::build_edges() { @@ -148,4 +155,31 @@ void RRGraphBuilder::build_edges() { edges_to_build_.erase(std::unique(edges_to_build_.begin(), edges_to_build_.end()), edges_to_build_.end()); alloc_and_load_edges(&edges_to_build_); edges_to_build_.clear(); + is_edge_dirty_ = false; +} + +void RRGraphBuilder::build_in_edges() { + VTR_ASSERT(validate()); + node_in_edges_.clear(); + node_in_edges_.resize(node_storage_.size()); + + for (const RRNodeId& src_node: vtr::StrongIdRange(RRNodeId(0), RRNodeId(node_storage_.size()))) { + for (size_t iedge = size_t(node_storage_.first_edge(src_node)); iedge < size_t(node_storage_.last_edge(src_node)); iedge++) { + RRNodeId des_node = node_storage_.edge_sink_node(RREdgeId(iedge)); + node_in_edges_[des_node].push_back(RREdgeId(iedge)); + } + } + is_incoming_edge_dirty_ = false; +} + +std::vector RRGraphBuilder::node_in_edges(RRNodeId node) { + VTR_ASSERT(size_t(node) < node_storage_.size()); + if (is_incoming_edge_dirty_) { + VTR_LOG_ERROR("Incoming edges are built yet in routing resource graph. Please call build_in_edges()."); + return std::vector(); + } + if (node_in_edges_.empty()) { + return std::vector(); + } + return node_in_edges_[node]; } diff --git a/libs/librrgraph/src/base/rr_graph_builder.h b/libs/librrgraph/src/base/rr_graph_builder.h index 000ee750fbd..3c3b845cabb 100644 --- a/libs/librrgraph/src/base/rr_graph_builder.h +++ b/libs/librrgraph/src/base/rr_graph_builder.h @@ -210,6 +210,15 @@ class RRGraphBuilder { * while the cache will be empty once build-up is accomplished */ void build_edges(); + /** @brief Allocate and build incoming edges for each node. + * By default, no incoming edges are kept in storage, to be memory efficient */ + void build_in_edges(); + + /** @brief Return incoming edges for a given routing resource node + * Require build_in_edges() to be called first + */ + std::vector node_in_edges(RRNodeId node); + /** @brief Reserve the lists of edges to be memory efficient. * This function is mainly used to reserve memory space inside RRGraph, * when adding a large number of edges in order to avoid memory fragements */ @@ -357,6 +366,10 @@ class RRGraphBuilder { /* Detailed information about the switches, which are used in the RRGraph */ vtr::vector rr_switch_inf_; + /** A list of incoming edges for each routing resource node. This can be built optionally, as required by applications. + * By default, it is empty! Call build_in_edges() to construct it!!! */ + vtr::vector> node_in_edges_; + /** .. warning:: The Metadata should stay as an independent data structure than rest of the internal data, * e.g., node_lookup! */ /* Metadata is an extra data on rr-nodes and edges, respectively, that is not used by vpr @@ -381,6 +394,11 @@ class RRGraphBuilder { * value: map of */ MetadataStorage> rr_edge_metadata_; + + /** @brief a flag to mark the status of edge storage + * dirty means that the edge storage is not complete, should call related APIs to build */ + bool is_edge_dirty_; + bool is_incoming_edge_dirty_; }; #endif From bef7983cd3f9047f0075053c61fa520d9f658c7f Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sun, 14 Aug 2022 15:30:06 -0700 Subject: [PATCH 019/147] [vpr] added APIs for node_in_edges and adapt tileable rr graph generator --- libs/librrgraph/src/base/rr_graph_builder.cpp | 6 ++- libs/librrgraph/src/base/rr_graph_builder.h | 4 +- libs/librrgraph/src/base/rr_graph_storage.cpp | 5 +++ libs/librrgraph/src/base/rr_graph_storage.h | 1 + libs/librrgraph/src/base/rr_graph_view.cpp | 14 ++++++- libs/librrgraph/src/base/rr_graph_view.h | 31 +++++++++++++- vpr/src/base/vpr_context.h | 2 +- .../openfpga_rr_graph_utils.cpp | 42 +------------------ .../tileable_rr_graph/rr_graph_view_util.cpp | 20 ++------- vpr/src/tileable_rr_graph/rr_gsb.cpp | 33 +++------------ 10 files changed, 68 insertions(+), 90 deletions(-) diff --git a/libs/librrgraph/src/base/rr_graph_builder.cpp b/libs/librrgraph/src/base/rr_graph_builder.cpp index baf353322bf..9523000dc83 100644 --- a/libs/librrgraph/src/base/rr_graph_builder.cpp +++ b/libs/librrgraph/src/base/rr_graph_builder.cpp @@ -28,6 +28,10 @@ MetadataStorage>& RRGraphBuilder::rr_edge_metadata() return rr_edge_metadata_; } +vtr::vector> RRGraphBuilder::node_in_edge_storage() { + return node_in_edges_; +} + void RRGraphBuilder::add_node_to_all_locs(RRNodeId node) { t_rr_type node_type = node_storage_.node_type(node); short node_ptc_num = node_storage_.node_ptc_num(node); @@ -172,7 +176,7 @@ void RRGraphBuilder::build_in_edges() { is_incoming_edge_dirty_ = false; } -std::vector RRGraphBuilder::node_in_edges(RRNodeId node) { +std::vector RRGraphBuilder::node_in_edges(RRNodeId node) const { VTR_ASSERT(size_t(node) < node_storage_.size()); if (is_incoming_edge_dirty_) { VTR_LOG_ERROR("Incoming edges are built yet in routing resource graph. Please call build_in_edges()."); diff --git a/libs/librrgraph/src/base/rr_graph_builder.h b/libs/librrgraph/src/base/rr_graph_builder.h index 3c3b845cabb..a036fea7866 100644 --- a/libs/librrgraph/src/base/rr_graph_builder.h +++ b/libs/librrgraph/src/base/rr_graph_builder.h @@ -45,6 +45,8 @@ class RRGraphBuilder { MetadataStorage& rr_node_metadata(); /** @brief Return a writable object for the meta data on the edge */ MetadataStorage>& rr_edge_metadata(); + /** @brief Return a writable object fo the incoming edge storage */ + vtr::vector> node_in_edge_storage(); /** @brief Return the size for rr_node_metadata */ inline size_t rr_node_metadata_size() const { @@ -217,7 +219,7 @@ class RRGraphBuilder { /** @brief Return incoming edges for a given routing resource node * Require build_in_edges() to be called first */ - std::vector node_in_edges(RRNodeId node); + std::vector node_in_edges(RRNodeId node) const; /** @brief Reserve the lists of edges to be memory efficient. * This function is mainly used to reserve memory space inside RRGraph, diff --git a/libs/librrgraph/src/base/rr_graph_storage.cpp b/libs/librrgraph/src/base/rr_graph_storage.cpp index dbf6fdb2e2a..5e85557499d 100644 --- a/libs/librrgraph/src/base/rr_graph_storage.cpp +++ b/libs/librrgraph/src/base/rr_graph_storage.cpp @@ -531,6 +531,11 @@ t_edge_size t_rr_graph_storage::num_non_configurable_edges(RRNodeId node, const return num_edges(node) - num_configurable_edges(node, rr_switches); } +bool t_rr_graph_storage::edge_is_configurable(RREdgeId edge, const vtr::vector& rr_switches) const { + auto iswitch = edge_switch(edge); + return rr_switches[RRSwitchId(iswitch)].configurable(); +} + bool t_rr_graph_storage::edge_is_configurable(RRNodeId id, t_edge_size iedge, const vtr::vector& rr_switches) const { auto iswitch = edge_switch(id, iedge); return rr_switches[RRSwitchId(iswitch)].configurable(); diff --git a/libs/librrgraph/src/base/rr_graph_storage.h b/libs/librrgraph/src/base/rr_graph_storage.h index a23ce92c67d..20d791c9596 100644 --- a/libs/librrgraph/src/base/rr_graph_storage.h +++ b/libs/librrgraph/src/base/rr_graph_storage.h @@ -270,6 +270,7 @@ class t_rr_graph_storage { t_edge_size num_edges(const RRNodeId& id) const { return size_t(last_edge(id)) - size_t(first_edge(id)); } + bool edge_is_configurable(RREdgeId edge, const vtr::vector& rr_switches) const; bool edge_is_configurable(RRNodeId id, t_edge_size iedge, const vtr::vector& rr_switches) const; t_edge_size num_configurable_edges(RRNodeId node, const vtr::vector& rr_switches) const; t_edge_size num_non_configurable_edges(RRNodeId node, const vtr::vector& rr_switches) const; diff --git a/libs/librrgraph/src/base/rr_graph_view.cpp b/libs/librrgraph/src/base/rr_graph_view.cpp index 0ddc5445d42..eccac8b7f05 100644 --- a/libs/librrgraph/src/base/rr_graph_view.cpp +++ b/libs/librrgraph/src/base/rr_graph_view.cpp @@ -9,7 +9,8 @@ RRGraphView::RRGraphView(const t_rr_graph_storage& node_storage, const vtr::vector& rr_indexed_data, const std::vector& rr_rc_data, const vtr::vector& rr_segments, - const vtr::vector& rr_switch_inf) + const vtr::vector& rr_switch_inf, + const vtr::vector>& node_in_edges) : node_storage_(node_storage) , node_lookup_(node_lookup) , rr_node_metadata_(rr_node_metadata) @@ -17,5 +18,14 @@ RRGraphView::RRGraphView(const t_rr_graph_storage& node_storage, , rr_indexed_data_(rr_indexed_data) , rr_rc_data_(rr_rc_data) , rr_segments_(rr_segments) - , rr_switch_inf_(rr_switch_inf) { + , rr_switch_inf_(rr_switch_inf) + , node_in_edges_(node_in_edges) { +} + +std::vector RRGraphView::node_in_edges(RRNodeId node) const { + VTR_ASSERT(size_t(node) < node_storage_.size()); + if (node_in_edges_.empty()) { + return std::vector(); + } + return node_in_edges_[node]; } diff --git a/libs/librrgraph/src/base/rr_graph_view.h b/libs/librrgraph/src/base/rr_graph_view.h index ffea6084e18..1719751da08 100644 --- a/libs/librrgraph/src/base/rr_graph_view.h +++ b/libs/librrgraph/src/base/rr_graph_view.h @@ -42,7 +42,8 @@ class RRGraphView { const vtr::vector& rr_indexed_data, const std::vector& rr_rc_data, const vtr::vector& rr_segments, - const vtr::vector& rr_switch_inf); + const vtr::vector& rr_switch_inf, + const vtr::vector>& node_in_edges); /* Disable copy constructors and copy assignment operator * This is to avoid accidental copy because it could be an expensive operation considering that the @@ -300,12 +301,24 @@ class RRGraphView { inline short edge_switch(RRNodeId id, t_edge_size iedge) const { return node_storage_.edge_switch(id, iedge); } + inline RRSwitchId edge_switch(RREdgeId edge) const { + return RRSwitchId(node_storage_.edge_switch(edge)); + } + /** @brief Get the source node for the iedge'th edge from specified RRNodeId. + * This method should generally not be used, and instead first_edge and + * last_edge should be used.*/ + inline RRNodeId edge_src_node(RREdgeId edge) const { + return node_storage_.edge_source_node(edge); + } /** @brief Get the destination node for the iedge'th edge from specified RRNodeId. * This method should generally not be used, and instead first_edge and * last_edge should be used.*/ inline RRNodeId edge_sink_node(RRNodeId id, t_edge_size iedge) const { return node_storage_.edge_sink_node(id, iedge); } + inline RRNodeId edge_sink_node(RREdgeId edge) const { + return node_storage_.edge_sink_node(edge); + } /** @brief Get the source node for the iedge'th edge from specified RRNodeId. * This method should generally not be used, and instead first_edge and @@ -318,6 +331,9 @@ class RRGraphView { inline bool edge_is_configurable(RRNodeId id, t_edge_size iedge) const { return node_storage_.edge_is_configurable(id, iedge, rr_switch_inf_); } + inline bool edge_is_configurable(RREdgeId edge) const { + return node_storage_.edge_is_configurable(edge, rr_switch_inf_); + } /** @brief Get the number of configurable edges. This function is inlined for runtime optimization. */ inline t_edge_size num_configurable_edges(RRNodeId node) const { @@ -358,6 +374,9 @@ class RRGraphView { inline edge_idx_range edges(const RRNodeId& id) const { return vtr::make_range(edge_idx_iterator(0), edge_idx_iterator(num_edges(id))); } + inline edge_idx_range node_out_edges(const RRNodeId& id) const { + return vtr::make_range(edge_idx_iterator(0), edge_idx_iterator(num_edges(id))); + } /** @brief Get the number of edges. This function is inlined for runtime optimization. */ inline t_edge_size num_edges(RRNodeId node) const { @@ -399,6 +418,12 @@ class RRGraphView { RRIndexedDataId node_cost_index(RRNodeId node) const { return node_storage_.node_cost_index(node); } + + /** @brief Return incoming edges for a given routing resource node + * Require build_in_edges() to be called first + */ + std::vector node_in_edges(RRNodeId node) const; + /** @brief Return detailed routing segment information with a given id* @note The routing segments here may not be exactly same as those defined in architecture file. They have been * adapted to fit the context of routing resource graphs. */ @@ -517,6 +542,10 @@ class RRGraphView { const vtr::vector& rr_segments_; /* switch info for rr nodes */ const vtr::vector& rr_switch_inf_; + + /** A list of incoming edges for each routing resource node. This can be built optionally, as required by applications. + * By default, it is empty! Call build_in_edges() to construct it!!! */ + const vtr::vector>& node_in_edges_; }; #endif diff --git a/vpr/src/base/vpr_context.h b/vpr/src/base/vpr_context.h index 8e3cb7effc0..25dc0687fcb 100644 --- a/vpr/src/base/vpr_context.h +++ b/vpr/src/base/vpr_context.h @@ -191,7 +191,7 @@ struct DeviceContext : public Context { /* A read-only view of routing resource graph to be the ONLY database * for client functions: GUI, placer, router, timing analyzer etc. */ - RRGraphView rr_graph{rr_graph_builder.rr_nodes(), rr_graph_builder.node_lookup(), rr_graph_builder.rr_node_metadata(), rr_graph_builder.rr_edge_metadata(), rr_indexed_data, rr_rc_data, rr_graph_builder.rr_segments(), rr_graph_builder.rr_switch()}; + RRGraphView rr_graph{rr_graph_builder.rr_nodes(), rr_graph_builder.node_lookup(), rr_graph_builder.rr_node_metadata(), rr_graph_builder.rr_edge_metadata(), rr_indexed_data, rr_rc_data, rr_graph_builder.rr_segments(), rr_graph_builder.rr_switch(), rr_graph_builder.node_in_edge_storage()}; /* Track ids for each rr_node in the rr_graph. * This is used by drawer for tileable routing resource graph diff --git a/vpr/src/tileable_rr_graph/openfpga_rr_graph_utils.cpp b/vpr/src/tileable_rr_graph/openfpga_rr_graph_utils.cpp index 47809f9da8f..0855c082691 100644 --- a/vpr/src/tileable_rr_graph/openfpga_rr_graph_utils.cpp +++ b/vpr/src/tileable_rr_graph/openfpga_rr_graph_utils.cpp @@ -73,17 +73,11 @@ std::vector get_rr_graph_driver_switches(const RRGraphView& rr_graph const RRNodeId& node) { std::vector driver_switches; - // NYI - // unused argements - (void)(rr_graph); - (void)(node); -#if 0 for (const RREdgeId& edge : rr_graph.node_in_edges(node)) { if (driver_switches.end() == std::find(driver_switches.begin(), driver_switches.end(), rr_graph.edge_switch(edge))) { driver_switches.push_back(rr_graph.edge_switch(edge)); } } -#endif return driver_switches; } @@ -95,15 +89,9 @@ std::vector get_rr_graph_driver_nodes(const RRGraphView& rr_graph, const RRNodeId& node) { std::vector driver_nodes; - // NYI - // unused argements - (void)(rr_graph); - (void)(node); -#if 0 for (const RREdgeId& edge : rr_graph.node_in_edges(node)) { driver_nodes.push_back(rr_graph.edge_src_node(edge)); } -#endif return driver_nodes; } @@ -115,13 +103,6 @@ std::vector get_rr_graph_configurable_driver_nodes(const RRGraphView& const RRNodeId& node) { std::vector driver_nodes; - // NYI - // unused argements - (void)(rr_graph); - (void)(node); -#if 0 - (void)(rr_graph); - (void)(node); for (const RREdgeId& edge : rr_graph.node_in_edges(node)) { /* Bypass non-configurable edges */ if (false == rr_graph.edge_is_configurable(edge)) { @@ -129,7 +110,6 @@ std::vector get_rr_graph_configurable_driver_nodes(const RRGraphView& } driver_nodes.push_back(rr_graph.edge_src_node(edge)); } -#endif return driver_nodes; } @@ -141,11 +121,6 @@ std::vector get_rr_graph_non_configurable_driver_nodes(const RRGraphVi const RRNodeId& node) { std::vector driver_nodes; - // NYI - // unused argements - (void)(rr_graph); - (void)(node); -#if 0 for (const RREdgeId& edge : rr_graph.node_in_edges(node)) { /* Bypass configurable edges */ if (true == rr_graph.edge_is_configurable(edge)) { @@ -153,7 +128,6 @@ std::vector get_rr_graph_non_configurable_driver_nodes(const RRGraphVi } driver_nodes.push_back(rr_graph.edge_src_node(edge)); } -#endif return driver_nodes; } @@ -169,23 +143,17 @@ bool is_opin_direct_connected_ipin(const RRGraphView& rr_graph, /* We only accept OPIN */ VTR_ASSERT(OPIN == rr_graph.node_type(node)); - // NYI - // unused argements - (void)(rr_graph); - (void)(node); -#if 0 if (1 != rr_graph.node_out_edges(node).size()) { return false; } VTR_ASSERT(1 == rr_graph.node_out_edges(node).size()); - for (const RREdgeId& edge : rr_graph.node_out_edges(node)) { - const RRNodeId& sink_node = rr_graph.edge_sink_node(edge); + for (auto edge : rr_graph.node_out_edges(node)) { + const RRNodeId& sink_node = rr_graph.edge_sink_node(RREdgeId(edge)); if (IPIN != rr_graph.node_type(sink_node)) { return false; } } -#endif return true; } @@ -201,11 +169,6 @@ bool is_ipin_direct_connected_opin(const RRGraphView& rr_graph, /* We only accept IPIN */ VTR_ASSERT(IPIN == rr_graph.node_type(node)); - // NYI - // unused argements - (void)(rr_graph); - (void)(node); -#if 0 if (1 != rr_graph.node_in_edges(node).size()) { return false; } @@ -217,7 +180,6 @@ bool is_ipin_direct_connected_opin(const RRGraphView& rr_graph, return false; } } -#endif return true; } diff --git a/vpr/src/tileable_rr_graph/rr_graph_view_util.cpp b/vpr/src/tileable_rr_graph/rr_graph_view_util.cpp index 637c926872e..4c3a55144ef 100644 --- a/vpr/src/tileable_rr_graph/rr_graph_view_util.cpp +++ b/vpr/src/tileable_rr_graph/rr_graph_view_util.cpp @@ -48,19 +48,11 @@ std::vector find_rr_graph_nodes(const RRGraphView& rr_graph, const int& ptc) { std::vector indices; - // NYI - // unused parameters - (void)(rr_graph); - (void)(x); - (void)(y); - (void)(rr_type); - (void)(ptc); -#if 0 if (rr_type == IPIN || rr_type == OPIN) { //For pins we need to look at all the sides of the current grid tile for (e_side side : SIDES) { - RRNodeId rr_node_index = rr_graph.find_node(x, y, rr_type, ptc, side); + RRNodeId rr_node_index = rr_graph.node_lookup().find_node(x, y, rr_type, ptc, side); if (rr_node_index != RRNodeId::INVALID()) { indices.push_back(rr_node_index); @@ -68,13 +60,12 @@ std::vector find_rr_graph_nodes(const RRGraphView& rr_graph, } } else { //Sides do not effect non-pins so there should only be one per ptc - RRNodeId rr_node_index = rr_graph.find_node(x, y, rr_type, ptc); + RRNodeId rr_node_index = rr_graph.node_lookup().find_node(x, y, rr_type, ptc); if (rr_node_index != RRNodeId::INVALID()) { indices.push_back(rr_node_index); } } -#endif return indices; } @@ -140,16 +131,11 @@ std::vector find_rr_graph_grid_nodes(const RRGraphView& rr_graph, continue; } - // NYI - // unused parameter - (void)(rr_graph); -#if 0 /* Try to find the rr node */ - RRNodeId rr_node_index = rr_graph.find_node(x, y, rr_type, pin, side); + RRNodeId rr_node_index = rr_graph.node_lookup().find_node(x, y, rr_type, pin, side); if (rr_node_index != RRNodeId::INVALID()) { indices.push_back(rr_node_index); } -#endif } return indices; diff --git a/vpr/src/tileable_rr_graph/rr_gsb.cpp b/vpr/src/tileable_rr_graph/rr_gsb.cpp index f02d2ef4be5..4aa7b8e4352 100644 --- a/vpr/src/tileable_rr_graph/rr_gsb.cpp +++ b/vpr/src/tileable_rr_graph/rr_gsb.cpp @@ -158,14 +158,9 @@ std::vector RRGSB::get_chan_node_in_edges(const RRGraphView& rr_graph, if (0 == chan_node_in_edges_.size()) { std::vector unsorted_edges; - // NYI - // unused parameter - (void)(rr_graph); -#if 0 for (const RREdgeId& edge : rr_graph.node_in_edges(get_chan_node(side, track_id))) { unsorted_edges.push_back(edge); } -#endif return unsorted_edges; } @@ -819,13 +814,6 @@ void RRGSB::sort_chan_node_in_edges(const RRGraphView& rr_graph, * For each side, the edge from grid pins will be the 1st part * while the edge from routing tracks will be the 2nd part */ - - // NYI - // unused parameter - (void)(rr_graph); - // unused variable - (void)(chan_node); -#if 0 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); @@ -837,9 +825,13 @@ void RRGSB::sort_chan_node_in_edges(const RRGraphView& rr_graph, if (NUM_SIDES == side) { VTR_LOG("GSB[%lu][%lu]:\n", get_x(), get_y()); VTR_LOG("SRC node:\n"); - rr_graph.print_node(src_node); + VTR_LOG("Node type: %s\n", rr_graph.node_type_string(src_node)); + VTR_LOG("Node coordinate: %d\n", rr_graph.node_coordinate_to_string(src_node).c_str()); + VTR_LOG("Node ptc: %d\n", rr_graph.node_ptc_num(src_node)); VTR_LOG("Channel node:\n"); - rr_graph.print_node(chan_node); + VTR_LOG("Node type: %s\n", rr_graph.node_type_string(chan_node)); + VTR_LOG("Node coordinate: %d\n", rr_graph.node_coordinate_to_string(chan_node).c_str()); + VTR_LOG("Node ptc: %d\n", rr_graph.node_ptc_num(chan_node)); } VTR_ASSERT(NUM_SIDES != side); @@ -855,7 +847,6 @@ void RRGSB::sort_chan_node_in_edges(const RRGraphView& rr_graph, edge_counter++; } -#endif /* Store the sorted edge */ for (size_t side = 0; side < get_num_sides(); ++side) { @@ -985,8 +976,6 @@ bool RRGSB::is_sb_node_mirror(const RRGraphView& rr_graph, VTR_ASSERT(node_in_edges.size() == cand_node_in_edges.size()); -// NYI -#if 0 for (size_t iedge = 0; iedge < node_in_edges.size(); ++iedge) { RREdgeId src_edge = node_in_edges[iedge]; RREdgeId src_cand_edge = cand_node_in_edges[iedge]; @@ -1011,7 +1000,6 @@ bool RRGSB::is_sb_node_mirror(const RRGraphView& rr_graph, return false; } } -#endif return true; } @@ -1030,14 +1018,6 @@ bool RRGSB::is_cb_node_mirror(const RRGraphView& rr_graph, RRNodeId node = this->get_ipin_node(node_side, node_id); RRNodeId cand_node = cand.get_ipin_node(node_side, node_id); - // NYI - // unused parameter - (void)(rr_graph); - (void)(cb_type); - // unused variables - (void)(node); - (void)(cand_node); -#if 0 if (rr_graph.node_in_edges(node).size() != rr_graph.node_in_edges(cand_node).size()) { return false; } @@ -1092,7 +1072,6 @@ bool RRGSB::is_cb_node_mirror(const RRGraphView& rr_graph, return false; } } -#endif return true; } From 38a8569de47d644c1f0ac5bdb6166cb627a945f4 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sun, 14 Aug 2022 15:45:14 -0700 Subject: [PATCH 020/147] [vpr] add missing API find_edges() for tileable rr_graph builder --- libs/librrgraph/src/base/rr_graph_view.cpp | 20 ++++++++++++++----- libs/librrgraph/src/base/rr_graph_view.h | 3 +++ .../tileable_rr_graph/rr_graph_view_util.cpp | 7 ------- 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/libs/librrgraph/src/base/rr_graph_view.cpp b/libs/librrgraph/src/base/rr_graph_view.cpp index eccac8b7f05..5ae0d7a430e 100644 --- a/libs/librrgraph/src/base/rr_graph_view.cpp +++ b/libs/librrgraph/src/base/rr_graph_view.cpp @@ -23,9 +23,19 @@ RRGraphView::RRGraphView(const t_rr_graph_storage& node_storage, } std::vector RRGraphView::node_in_edges(RRNodeId node) const { - VTR_ASSERT(size_t(node) < node_storage_.size()); - if (node_in_edges_.empty()) { - return std::vector(); - } - return node_in_edges_[node]; + VTR_ASSERT(size_t(node) < node_storage_.size()); + if (node_in_edges_.empty()) { + return std::vector(); + } + return node_in_edges_[node]; +} + +std::vector RRGraphView::find_edges(const RRNodeId& src_node, const RRNodeId& des_node) const { + std::vector edge_list; + for (auto iedge : node_out_edges(src_node)) { + if (edge_sink_node(RREdgeId(iedge)) == des_node) { + edge_list.push_back(RREdgeId(iedge)); + } + } + return edge_list; } diff --git a/libs/librrgraph/src/base/rr_graph_view.h b/libs/librrgraph/src/base/rr_graph_view.h index 1719751da08..b2695e67e62 100644 --- a/libs/librrgraph/src/base/rr_graph_view.h +++ b/libs/librrgraph/src/base/rr_graph_view.h @@ -378,6 +378,9 @@ class RRGraphView { return vtr::make_range(edge_idx_iterator(0), edge_idx_iterator(num_edges(id))); } + /** @brief find the edges between two nodes */ + std::vector find_edges(const RRNodeId& src_node, const RRNodeId& des_node) const; + /** @brief Get the number of edges. This function is inlined for runtime optimization. */ inline t_edge_size num_edges(RRNodeId node) const { return node_storage_.num_edges(node); diff --git a/vpr/src/tileable_rr_graph/rr_graph_view_util.cpp b/vpr/src/tileable_rr_graph/rr_graph_view_util.cpp index 4c3a55144ef..292cade3111 100644 --- a/vpr/src/tileable_rr_graph/rr_graph_view_util.cpp +++ b/vpr/src/tileable_rr_graph/rr_graph_view_util.cpp @@ -13,12 +13,6 @@ std::vector find_rr_graph_switches(const RRGraphView& rr_graph, const RRNodeId& to_node) { std::vector switches; - // NYI - // unused parameters - (void)(rr_graph); - (void)(from_node); - (void)(to_node); -#if 0 std::vector edges = rr_graph.find_edges(from_node, to_node); if (true == edges.empty()) { /* edge is open, we return an empty vector of switches */ @@ -31,7 +25,6 @@ std::vector find_rr_graph_switches(const RRGraphView& rr_graph, for (auto edge : edges) { switches.push_back(rr_graph.edge_switch(edge)); } -#endif return switches; } From 0af16341a4e5c0266be2f7fe0872e708bfacde40 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sun, 14 Aug 2022 15:52:22 -0700 Subject: [PATCH 021/147] [vpr] using updated api in tileable rrgraph builder when finding channel nodes --- vpr/src/tileable_rr_graph/rr_graph_view_util.cpp | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/vpr/src/tileable_rr_graph/rr_graph_view_util.cpp b/vpr/src/tileable_rr_graph/rr_graph_view_util.cpp index 292cade3111..90dadea3964 100644 --- a/vpr/src/tileable_rr_graph/rr_graph_view_util.cpp +++ b/vpr/src/tileable_rr_graph/rr_graph_view_util.cpp @@ -74,20 +74,11 @@ std::vector find_rr_graph_chan_nodes(const RRGraphView& rr_graph, VTR_ASSERT(rr_type == CHANX || rr_type == CHANY); - // NYI - // unused parameters - (void)(rr_graph); - (void)(x); - (void)(y); -#if 0 - for (short track = 0; track < rr_graph.chan_num_tracks(x, y, rr_type); ++track) { - RRNodeId rr_node_index = rr_graph.find_node(x, y, rr_type, track); - + for (const RRNodeId& rr_node_index : rr_graph.node_lookup().find_channel_nodes(x, y, rr_type)) { if (rr_node_index != RRNodeId::INVALID()) { indices.push_back(rr_node_index); } } -#endif return indices; } From aba2572f053eb7712a9ffedc000e7c79470a0c82 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 15 Aug 2022 09:07:08 -0700 Subject: [PATCH 022/147] [vpr] now enable build edges and incoming edges --- vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp | 3 +++ vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp index cd8c5aa2f83..b2bc9135c39 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp @@ -271,6 +271,9 @@ void build_tileable_unidir_rr_graph(const std::vector& typ /* Save the track ids for tileable routing resource graph */ device_ctx.rr_node_track_ids = rr_node_track_ids; + /* Build incoming edges */ + device_ctx.rr_graph_builder.build_incoming_edges(); + /************************************************************************ * Allocate external data structures * a. cost_index diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp index 2df3a759286..1f0c886ae9d 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp @@ -1423,9 +1423,10 @@ void build_direct_connections_for_one_gsb(const RRGraphView& rr_graph, */ /* add edges to the opin_node */ - rr_graph_builder.create_edge(opin_node_id, ipin_node_id, delayless_switch); } } } + /* Build actual edges */ + rr_graph_builder.build_edges(); } From b06c5bad536ef0063f4b2070f8e13dce0fc43084 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 15 Aug 2022 09:10:17 -0700 Subject: [PATCH 023/147] [vpr] syntax --- vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp index b2bc9135c39..031deebd58a 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp @@ -272,7 +272,7 @@ void build_tileable_unidir_rr_graph(const std::vector& typ device_ctx.rr_node_track_ids = rr_node_track_ids; /* Build incoming edges */ - device_ctx.rr_graph_builder.build_incoming_edges(); + device_ctx.rr_graph_builder.build_in_edges(); /************************************************************************ * Allocate external data structures From 314d22a0900cf5a17e6360e1868f48c673c0bec2 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 15 Aug 2022 09:28:48 -0700 Subject: [PATCH 024/147] [vpr] enable tileable rr_graph in create_rr_graph() --- vpr/src/route/rr_graph.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/vpr/src/route/rr_graph.cpp b/vpr/src/route/rr_graph.cpp index 3cb077b2d48..f992602a6ca 100644 --- a/vpr/src/route/rr_graph.cpp +++ b/vpr/src/route/rr_graph.cpp @@ -348,13 +348,9 @@ void create_rr_graph(const t_graph_type graph_type, directs, num_directs, &det_routing_arch->wire_to_rr_ipin_switch, Warnings); - if (router_opts.reorder_rr_graph_nodes_algorithm != DONT_REORDER) { - mutable_device_ctx.rr_graph_builder.reorder_nodes(router_opts.reorder_rr_graph_nodes_algorithm, - router_opts.reorder_rr_graph_nodes_threshold, - router_opts.reorder_rr_graph_nodes_seed); - } } else { /* We do not support dedicated network for clocks in tileable rr_graph generation */ + VTR_LOG_WARN("Tileable routing resource graph does not support clock modeling yet! Related options are ignored..."); build_tileable_unidir_rr_graph(block_types, grid, nodes_per_chan, @@ -374,6 +370,12 @@ void create_rr_graph(const t_graph_type graph_type, false, /* Do not allow passing tracks to be wired to the same routing channels */ Warnings); } + /* Reorder nodes upon needs in algorithms and router options */ + if (router_opts.reorder_rr_graph_nodes_algorithm != DONT_REORDER) { + mutable_device_ctx.rr_graph_builder.reorder_nodes(router_opts.reorder_rr_graph_nodes_algorithm, + router_opts.reorder_rr_graph_nodes_threshold, + router_opts.reorder_rr_graph_nodes_seed); + } } process_non_config_sets(); From 4f19f8e0573a4844fe66a334bfaa20abe48913df Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 15 Aug 2022 09:32:21 -0700 Subject: [PATCH 025/147] [test] add a quick test for tileable rr_graph --- vtr_flow/arch/timing/k4_N4_tileable_90nm.xml | 194 ++++++++++++++++++ .../config/config.txt | 29 +++ .../config/golden_results.txt | 4 + 3 files changed, 227 insertions(+) create mode 100644 vtr_flow/arch/timing/k4_N4_tileable_90nm.xml create mode 100755 vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_tileable_rr_graph/config/config.txt create mode 100644 vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_tileable_rr_graph/config/golden_results.txt diff --git a/vtr_flow/arch/timing/k4_N4_tileable_90nm.xml b/vtr_flow/arch/timing/k4_N4_tileable_90nm.xml new file mode 100644 index 00000000000..5193264205e --- /dev/null +++ b/vtr_flow/arch/timing/k4_N4_tileable_90nm.xml @@ -0,0 +1,194 @@ + + + + + + + + + + + + + + + + + io.outpad io.inpad io.clock + io.outpad io.inpad io.clock + io.outpad io.inpad io.clock + io.outpad io.inpad io.clock + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2.253000e-10 + 2.253000e-10 + 2.253000e-10 + 2.253000e-10 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_tileable_rr_graph/config/config.txt b/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_tileable_rr_graph/config/config.txt new file mode 100755 index 00000000000..fbf3358dd11 --- /dev/null +++ b/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_tileable_rr_graph/config/config.txt @@ -0,0 +1,29 @@ +############################################ +# Configuration file for running experiments +############################################## + +# Path to directory of circuits to use +circuits_dir=benchmarks/blif/4 + +# Path to directory of architectures to use +archs_dir=arch/timing + +# Add circuits to list to sweep +circuit_list_add=diffeq.blif +circuit_list_add=ex5p.blif +circuit_list_add=s298.blif + +# Add architectures to list to sweep +arch_list_add=k4_N4_tileable_90nm.xml + +# Parse info and how to parse +parse_file=vpr_standard.txt + +# How to parse QoR info +qor_parse_file=qor_standard.txt + +# Pass requirements +pass_requirements_file=pass_requirements.txt + +script_params=-starting_stage vpr -track_memory_usage + diff --git a/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_tileable_rr_graph/config/golden_results.txt b/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_tileable_rr_graph/config/golden_results.txt new file mode 100644 index 00000000000..7abe3a1a1c3 --- /dev/null +++ b/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_tileable_rr_graph/config/golden_results.txt @@ -0,0 +1,4 @@ + arch circuit script_params vtr_flow_elapsed_time error odin_synth_time max_odin_mem abc_depth abc_synth_time abc_cec_time abc_sec_time max_abc_mem ace_time max_ace_mem num_clb num_io num_memories num_mult vpr_status vpr_revision vpr_build_info vpr_compiler vpr_compiled hostname rundir max_vpr_mem num_primary_inputs num_primary_outputs num_pre_packed_nets num_pre_packed_blocks num_netlist_clocks num_post_packed_nets num_post_packed_blocks device_width device_height device_grid_tiles device_limiting_resources device_name pack_time placed_wirelength_est place_time place_quench_time placed_CPD_est placed_setup_TNS_est placed_setup_WNS_est placed_geomean_nonvirtual_intradomain_critical_path_delay_est place_delay_matrix_lookup_time place_quench_timing_analysis_time place_quench_sta_time place_total_timing_analysis_time place_total_sta_time min_chan_width routed_wirelength min_chan_width_route_success_iteration logic_block_area_total logic_block_area_used min_chan_width_routing_area_total min_chan_width_routing_area_per_tile min_chan_width_route_time min_chan_width_total_timing_analysis_time min_chan_width_total_sta_time crit_path_routed_wirelength crit_path_route_success_iteration crit_path_total_nets_routed crit_path_total_connections_routed crit_path_total_heap_pushes crit_path_total_heap_pops critical_path_delay geomean_nonvirtual_intradomain_critical_path_delay setup_TNS setup_WNS hold_TNS hold_WNS crit_path_routing_area_total crit_path_routing_area_per_tile router_lookahead_computation_time crit_path_route_time crit_path_total_timing_analysis_time crit_path_total_sta_time placement_technique reward uniform_percentage median_percentage wmedian_percentage wcent_percentage fr_percentage critUni_percentage centroid_percentage + k4_N4_90nm.xml diffeq.blif common 6.72 -1 -1 -1 -1 -1 -1 -1 -1 -1 417 64 -1 -1 success v8.0.0-3198-gd038c933b release VTR_ASSERT_LEVEL=2 GNU 7.5.0 on Linux-4.15.0-60-generic x86_64 2021-01-02T13:20:16 betzgrp-wintermute.eecg.utoronto.ca /home/elgamma8/research/gold/vtr-verilog-to-routing 87228 64 39 1935 1974 1 1104 520 23 23 529 clb auto 0.40 10030 0.93 0.01 6.59694 -1414.7 -6.59694 6.59694 0.45 0.00189405 0.00143772 0.221979 0.167805 24 12059 26 983127 929624 797780. 1508.09 2.59 0.588243 0.472549 11020 20 7062 23191 1573824 393127 6.8984 6.8984 -1529.52 -6.8984 0 0 1.04508e+06 1975.57 0.13 0.43 0.131471 0.112481 simple RL 'Softmax agent' -1 -1 -1 -1 -1 -1 -1 -1 + k4_N4_90nm.xml ex5p.blif common 16.92 -1 -1 -1 -1 -1 -1 -1 -1 -1 346 8 -1 -1 success v8.0.0-3198-gd038c933b release VTR_ASSERT_LEVEL=2 GNU 7.5.0 on Linux-4.15.0-60-generic x86_64 2021-01-02T13:20:16 betzgrp-wintermute.eecg.utoronto.ca /home/elgamma8/research/gold/vtr-verilog-to-routing 68688 8 63 1072 1135 0 909 417 21 21 441 clb auto 0.17 11681 0.71 0.01 6.75152 -301.537 -6.75152 nan 0.34 0.00117768 0.000911645 0.136814 0.106107 34 15896 33 804782 771343 910617. 2064.89 13.76 0.477973 0.383445 13620 21 8417 29539 3341244 830781 6.81396 nan -313.113 -6.81396 0 0 1.15594e+06 2621.17 0.13 0.55 0.0731153 0.0639044 simple RL 'Softmax agent' -1 -1 -1 -1 -1 -1 -1 -1 + k4_N4_90nm.xml s298.blif common 11.05 -1 -1 -1 -1 -1 -1 -1 -1 -1 571 4 -1 -1 success v8.0.0-3198-gd038c933b release VTR_ASSERT_LEVEL=2 GNU 7.5.0 on Linux-4.15.0-60-generic x86_64 2021-01-02T13:20:16 betzgrp-wintermute.eecg.utoronto.ca /home/elgamma8/research/gold/vtr-verilog-to-routing 78820 4 6 1942 1948 1 1193 581 26 26 676 clb auto 0.31 14228 1.11 0.01 11.6554 -90.3611 -11.6554 11.6554 0.56 0.00215172 0.00157042 0.245315 0.182305 26 18055 30 1.28409e+06 1.27294e+06 1.12979e+06 1671.28 6.01 0.62371 0.489649 16623 19 8342 42276 3817766 734253 11.5305 11.5305 -91.3072 -11.5305 0 0 1.43821e+06 2127.53 0.31 0.73 0.120758 0.1047 simple RL 'Softmax agent' -1 -1 -1 -1 -1 -1 -1 -1 From 0b778565370406691184c204323044735ad90947 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 15 Aug 2022 09:33:03 -0700 Subject: [PATCH 026/147] [test] enable new test in strong regression test --- vtr_flow/tasks/regression_tests/vtr_reg_strong/task_list.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/vtr_flow/tasks/regression_tests/vtr_reg_strong/task_list.txt b/vtr_flow/tasks/regression_tests/vtr_reg_strong/task_list.txt index 058abb05c9c..35e0d783fbe 100644 --- a/vtr_flow/tasks/regression_tests/vtr_reg_strong/task_list.txt +++ b/vtr_flow/tasks/regression_tests/vtr_reg_strong/task_list.txt @@ -80,3 +80,4 @@ regression_tests/vtr_reg_strong/strong_verify_rr_graph_bin regression_tests/vtr_reg_strong/strong_verify_rr_graph_titan regression_tests/vtr_reg_strong/koios regression_tests/vtr_reg_strong/koios_no_complex_dsp +regression_tests/vtr_reg_strong/strong_tileable_rr_graph From 8c2bc64d97307f433dcafe802c2d8827860dfca1 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 15 Aug 2022 09:38:08 -0700 Subject: [PATCH 027/147] [lib] enable tileable options in read fpga arch library --- libs/libarchfpga/src/read_xml_arch_file.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libs/libarchfpga/src/read_xml_arch_file.cpp b/libs/libarchfpga/src/read_xml_arch_file.cpp index 95481f264e4..ba85a5a2804 100644 --- a/libs/libarchfpga/src/read_xml_arch_file.cpp +++ b/libs/libarchfpga/src/read_xml_arch_file.cpp @@ -2367,7 +2367,10 @@ static void ProcessLayout(pugi::xml_node layout_tag, t_arch* arch, const pugiuti VTR_ASSERT(layout_tag.name() == std::string("layout")); //Expect no attributes on - expect_only_attributes(layout_tag, {}, loc_data); + //expect_only_attributes(layout_tag, {}, loc_data); + + arch->tileable = get_attribute(layout_tag, "tileable", loc_data, ReqOpt::OPTIONAL).as_bool(false); + arch->through_channel = get_attribute(layout_tag, "through_channel", loc_data, ReqOpt::OPTIONAL).as_bool(false); //Count the number of or tags size_t auto_layout_cnt = 0; From 2a846e4cb096c6f74266302cabd50405186de852 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 15 Aug 2022 10:54:52 -0700 Subject: [PATCH 028/147] [vpr] allocate nodes --- vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp index 9662cb52bcd..721a48f43c5 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp @@ -340,7 +340,7 @@ void alloc_tileable_rr_graph_nodes(RRGraphBuilder& rr_graph_builder, num_nodes += num_node_per_type; } - rr_graph_builder.reserve_nodes(num_nodes); + rr_graph_builder.resize_nodes(num_nodes); rr_node_driver_switches.reserve(num_nodes); } From 54efbc26332cd1bc5945eda007a58b70d94ed889 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 15 Aug 2022 14:43:33 -0700 Subject: [PATCH 029/147] [vpr] debugging tileable rr_graph builder --- libs/librrgraph/src/base/rr_graph_builder.cpp | 14 +++++++++ libs/librrgraph/src/base/rr_graph_builder.h | 4 +++ libs/librrgraph/src/base/rr_graph_storage.cpp | 20 ++++++------- .../tileable_rr_graph_node_builder.cpp | 29 ++++++++----------- 4 files changed, 40 insertions(+), 27 deletions(-) diff --git a/libs/librrgraph/src/base/rr_graph_builder.cpp b/libs/librrgraph/src/base/rr_graph_builder.cpp index 9523000dc83..d7cbea13ff6 100644 --- a/libs/librrgraph/src/base/rr_graph_builder.cpp +++ b/libs/librrgraph/src/base/rr_graph_builder.cpp @@ -66,6 +66,20 @@ void RRGraphBuilder::add_node_to_all_locs(RRNodeId node) { } } +RRNodeId RRGraphBuilder::create_node(int x, int y, t_rr_type type, int ptc, e_side side) { + node_storage_.emplace_back(); + RRNodeId new_node = RRNodeId(node_storage_.size() - 1); + node_storage_.set_node_type(new_node, type); + node_storage_.set_node_coordinates(new_node, x, y, x, y); + node_storage_.set_node_ptc_num(new_node, ptc); + if (CHANX != type && CHANY != type) { + node_storage_.add_node_side(new_node, side); + } + node_lookup_.add_node(new_node, x, y, type, ptc, side); + + return new_node; +} + void RRGraphBuilder::clear() { node_lookup_.clear(); node_storage_.clear(); diff --git a/libs/librrgraph/src/base/rr_graph_builder.h b/libs/librrgraph/src/base/rr_graph_builder.h index a036fea7866..1a539d4fb30 100644 --- a/libs/librrgraph/src/base/rr_graph_builder.h +++ b/libs/librrgraph/src/base/rr_graph_builder.h @@ -118,6 +118,10 @@ class RRGraphBuilder { inline void set_node_type(RRNodeId id, t_rr_type type) { node_storage_.set_node_type(id, type); } + /** @brief Create a new rr_node in the node storage and register it to the node look-up. + * Return a valid node id if succeed. Otherwise, return an invalid id. + */ + RRNodeId create_node(int x, int y, t_rr_type type, int ptc, e_side side = SIDES[0]); /** * @brief Add an existing rr_node in the node storage to the node look-up * diff --git a/libs/librrgraph/src/base/rr_graph_storage.cpp b/libs/librrgraph/src/base/rr_graph_storage.cpp index 5e85557499d..179b159083c 100644 --- a/libs/librrgraph/src/base/rr_graph_storage.cpp +++ b/libs/librrgraph/src/base/rr_graph_storage.cpp @@ -601,21 +601,21 @@ void t_rr_graph_storage::set_node_ptc_num(RRNodeId id, short new_ptc_num) { } void t_rr_graph_storage::set_node_pin_num(RRNodeId id, short new_pin_num) { if (node_type(id) != IPIN && node_type(id) != OPIN) { - VTR_LOG_ERROR("Attempted to set RR node 'pin_num' for non-IPIN/OPIN type '%s'", node_type_string(id)); + VTR_LOG_ERROR("Attempted to set RR node 'pin_num' for non-IPIN/OPIN type '%s'\n", node_type_string(id)); } node_ptc_[id].ptc_.pin_num = new_pin_num; } void t_rr_graph_storage::set_node_track_num(RRNodeId id, short new_track_num) { if (node_type(id) != CHANX && node_type(id) != CHANY) { - VTR_LOG_ERROR("Attempted to set RR node 'track_num' for non-CHANX/CHANY type '%s'", node_type_string(id)); + VTR_LOG_ERROR("Attempted to set RR node 'track_num' for non-CHANX/CHANY type '%s'\n", node_type_string(id)); } node_ptc_[id].ptc_.track_num = new_track_num; } void t_rr_graph_storage::set_node_class_num(RRNodeId id, short new_class_num) { if (node_type(id) != SOURCE && node_type(id) != SINK) { - VTR_LOG_ERROR("Attempted to set RR node 'class_num' for non-SOURCE/SINK type '%s'", node_type_string(id)); + VTR_LOG_ERROR("Attempted to set RR node 'class_num' for non-SOURCE/SINK type '%s'\n", node_type_string(id)); } node_ptc_[id].ptc_.class_num = new_class_num; } @@ -630,7 +630,7 @@ static short get_node_pin_num( RRNodeId id) { auto node_type = node_storage[id].type_; if (node_type != IPIN && node_type != OPIN) { - VTR_LOG_ERROR("Attempted to access RR node 'pin_num' for non-IPIN/OPIN type '%s'", rr_node_typename[node_type]); + VTR_LOG_ERROR("Attempted to access RR node 'pin_num' for non-IPIN/OPIN type '%s'\n", rr_node_typename[node_type]); } return node_ptc[id].ptc_.pin_num; } @@ -641,7 +641,7 @@ static short get_node_track_num( RRNodeId id) { auto node_type = node_storage[id].type_; if (node_type != CHANX && node_type != CHANY) { - VTR_LOG_ERROR("Attempted to access RR node 'track_num' for non-CHANX/CHANY type '%s'", rr_node_typename[node_type]); + VTR_LOG_ERROR("Attempted to access RR node 'track_num' for non-CHANX/CHANY type '%s'\n", rr_node_typename[node_type]); } return node_ptc[id].ptc_.track_num; } @@ -652,7 +652,7 @@ static short get_node_class_num( RRNodeId id) { auto node_type = node_storage[id].type_; if (node_type != SOURCE && node_type != SINK) { - VTR_LOG_ERROR("Attempted to access RR node 'class_num' for non-SOURCE/SINK type '%s'", rr_node_typename[node_type]); + VTR_LOG_ERROR("Attempted to access RR node 'class_num' for non-SOURCE/SINK type '%s'\n", rr_node_typename[node_type]); } return node_ptc[id].ptc_.class_num; } @@ -702,7 +702,7 @@ void t_rr_graph_storage::set_node_coordinates(RRNodeId id, short x1, short y1, s void t_rr_graph_storage::set_node_cost_index(RRNodeId id, RRIndexedDataId new_cost_index) { auto& node = node_storage_[id]; if ((size_t)new_cost_index >= std::numeric_limits::max()) { - VTR_LOG_ERROR("Attempted to set cost_index_ %zu above cost_index storage max value.", + VTR_LOG_ERROR("Attempted to set cost_index_ %zu above cost_index storage max value.\n", new_cost_index); } node.cost_index_ = (size_t)new_cost_index; @@ -719,19 +719,19 @@ void t_rr_graph_storage::set_node_capacity(RRNodeId id, short new_capacity) { void t_rr_graph_storage::set_node_direction(RRNodeId id, Direction new_direction) { if (node_type(id) != CHANX && node_type(id) != CHANY) { - VTR_LOG_ERROR("Attempted to set RR node 'direction' for non-channel type '%s'", node_type_string(id)); + VTR_LOG_ERROR("Attempted to set RR node 'direction' for non-channel type '%s'\n", node_type_string(id)); } node_storage_[id].dir_side_.direction = new_direction; } void t_rr_graph_storage::add_node_side(RRNodeId id, e_side new_side) { if (node_type(id) != IPIN && node_type(id) != OPIN) { - VTR_LOG_ERROR("Attempted to set RR node 'side' for non-channel type '%s'", node_type_string(id)); + VTR_LOG_ERROR("Attempted to set RR node 'side' for non-channel type '%s'\n", node_type_string(id)); } std::bitset side_bits = node_storage_[id].dir_side_.sides; side_bits[size_t(new_side)] = true; if (side_bits.to_ulong() > CHAR_MAX) { - VTR_LOG_ERROR("Invalid side '%s' to be added to rr node %u", SIDE_STRING[new_side], size_t(id)); + VTR_LOG_ERROR("Invalid side '%s' to be added to rr node %u\n", SIDE_STRING[new_side], size_t(id)); } node_storage_[id].dir_side_.sides = static_cast(side_bits.to_ulong()); } diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp index 721a48f43c5..3c845839b01 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp @@ -340,9 +340,9 @@ void alloc_tileable_rr_graph_nodes(RRGraphBuilder& rr_graph_builder, num_nodes += num_node_per_type; } - rr_graph_builder.resize_nodes(num_nodes); + rr_graph_builder.reserve_nodes(num_nodes); - rr_node_driver_switches.reserve(num_nodes); + rr_node_driver_switches.resize(num_nodes); } /************************************************************************ @@ -380,7 +380,7 @@ static void load_one_grid_opin_nodes_basic_info(RRGraphBuilder& rr_graph_builder width, height); for (const int& pin_num : opin_list) { /* Create a new node and fill information */ - const RRNodeId& node = rr_graph_builder.node_lookup().find_node(width, height, OPIN, pin_num, side); + const RRNodeId& node = rr_graph_builder.create_node(width, height, OPIN, pin_num, side); /* node bounding box */ rr_graph_builder.set_node_coordinates(node, grid_coordinate.x() + width, @@ -396,8 +396,7 @@ static void load_one_grid_opin_nodes_basic_info(RRGraphBuilder& rr_graph_builder rr_graph_builder.set_node_cost_index(node, RRIndexedDataId(OPIN_COST_INDEX)); /* Switch info */ - VTR_ASSERT(size_t(node) == rr_node_driver_switches.size()); - rr_node_driver_switches.push_back(delayless_switch); + rr_node_driver_switches[node] = delayless_switch; /* RC data */ rr_graph_builder.set_node_rc_index(node, NodeRCIndex(find_create_rr_rc_data(0., 0., rr_rc_data))); @@ -443,7 +442,7 @@ static void load_one_grid_ipin_nodes_basic_info(RRGraphBuilder& rr_graph_builder std::vector ipin_list = get_grid_side_pins(cur_grid, RECEIVER, side_manager.get_side(), width, height); for (const int& pin_num : ipin_list) { /* Create a new node and fill information */ - const RRNodeId& node = rr_graph_builder.node_lookup().find_node(width, height, IPIN, pin_num, side); + const RRNodeId& node = rr_graph_builder.create_node(width, height, IPIN, pin_num, side); /* node bounding box */ rr_graph_builder.set_node_coordinates(node, grid_coordinate.x() + width, @@ -459,8 +458,7 @@ static void load_one_grid_ipin_nodes_basic_info(RRGraphBuilder& rr_graph_builder rr_graph_builder.set_node_cost_index(node, RRIndexedDataId(IPIN_COST_INDEX)); /* Switch info */ - VTR_ASSERT(size_t(node) == rr_node_driver_switches.size()); - rr_node_driver_switches.push_back(wire_to_ipin_switch); + rr_node_driver_switches[node] = wire_to_ipin_switch; /* RC data */ rr_graph_builder.set_node_rc_index(node, NodeRCIndex(find_create_rr_rc_data(0., 0., rr_rc_data))); @@ -495,7 +493,7 @@ static void load_one_grid_source_nodes_basic_info(RRGraphBuilder& rr_graph_build } /* Create a new node and fill information */ - const RRNodeId& node = rr_graph_builder.node_lookup().find_node(grid_coordinate.x(), grid_coordinate.y(), SOURCE, iclass); + const RRNodeId& node = rr_graph_builder.create_node(grid_coordinate.x(), grid_coordinate.y(), SOURCE, iclass); /* node bounding box */ rr_graph_builder.set_node_coordinates(node, grid_coordinate.x(), @@ -513,8 +511,7 @@ static void load_one_grid_source_nodes_basic_info(RRGraphBuilder& rr_graph_build rr_graph_builder.set_node_cost_index(node, RRIndexedDataId(SOURCE_COST_INDEX)); /* Switch info */ - VTR_ASSERT(size_t(node) == rr_node_driver_switches.size()); - rr_node_driver_switches.push_back(delayless_switch); + rr_node_driver_switches[node] = delayless_switch; /* RC data */ rr_graph_builder.set_node_rc_index(node, NodeRCIndex(find_create_rr_rc_data(0., 0., rr_rc_data))); @@ -546,7 +543,7 @@ static void load_one_grid_sink_nodes_basic_info(RRGraphBuilder& rr_graph_builder } /* Create a new node and fill information */ - const RRNodeId& node = rr_graph_builder.node_lookup().find_node(grid_coordinate.x(), grid_coordinate.y(), SINK, iclass); + const RRNodeId& node = rr_graph_builder.create_node(grid_coordinate.x(), grid_coordinate.y(), SINK, iclass); /* node bounding box */ rr_graph_builder.set_node_coordinates(node, grid_coordinate.x(), @@ -564,8 +561,7 @@ static void load_one_grid_sink_nodes_basic_info(RRGraphBuilder& rr_graph_builder rr_graph_builder.set_node_cost_index(node, RRIndexedDataId(SINK_COST_INDEX)); /* Switch info */ - VTR_ASSERT(size_t(node) == rr_node_driver_switches.size()); - rr_node_driver_switches.push_back(delayless_switch); + rr_node_driver_switches[node] = delayless_switch; /* RC data */ rr_graph_builder.set_node_rc_index(node, NodeRCIndex(find_create_rr_rc_data(0., 0., rr_rc_data))); @@ -670,7 +666,7 @@ static void load_one_chan_rr_nodes_basic_info(RRGraphView& rr_graph, || ((true == chan_details.is_track_end(itrack)) && (Direction::DEC == chan_details.get_track_direction(itrack)))) { /* Create a new chan rr_node */ - const RRNodeId& node = rr_graph_builder.node_lookup().find_node(chan_coordinate.x(), chan_coordinate.y(), chan_type, itrack); + const RRNodeId& node = rr_graph_builder.create_node(chan_coordinate.x(), chan_coordinate.y(), chan_type, itrack); rr_graph_builder.set_node_direction(node, chan_details.get_track_direction(itrack)); rr_graph_builder.set_node_track_num(node, itrack); @@ -680,8 +676,7 @@ static void load_one_chan_rr_nodes_basic_info(RRGraphView& rr_graph, /* assign switch id */ size_t seg_id = chan_details.get_track_segment_id(itrack); - VTR_ASSERT(size_t(node) == rr_node_driver_switches.size()); - rr_node_driver_switches.push_back(RRSwitchId(segment_infs[seg_id].arch_opin_switch)); + rr_node_driver_switches[node] = RRSwitchId(segment_infs[seg_id].arch_opin_switch); /* Update chan_details with node_id */ chan_details.set_track_node_id(itrack, size_t(node)); From a46461bd56bae466425431da3d4cbd725943086b Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 15 Aug 2022 17:07:35 -0700 Subject: [PATCH 030/147] [vpr] debugging tileable rr_graph generator --- libs/librrgraph/src/base/rr_graph_builder.cpp | 11 +++-- libs/librrgraph/src/base/rr_graph_builder.h | 2 +- libs/librrgraph/src/base/rr_graph_view.h | 5 +++ vpr/src/route/rr_graph.cpp | 2 +- .../tileable_rr_graph_builder.cpp | 2 + .../tileable_rr_graph_edge_builder.cpp | 16 +++++--- .../tileable_rr_graph_gsb.cpp | 2 +- .../tileable_rr_graph_node_builder.cpp | 41 +++++++++++++++---- 8 files changed, 61 insertions(+), 20 deletions(-) diff --git a/libs/librrgraph/src/base/rr_graph_builder.cpp b/libs/librrgraph/src/base/rr_graph_builder.cpp index d7cbea13ff6..a55e7ee2882 100644 --- a/libs/librrgraph/src/base/rr_graph_builder.cpp +++ b/libs/librrgraph/src/base/rr_graph_builder.cpp @@ -67,15 +67,20 @@ void RRGraphBuilder::add_node_to_all_locs(RRNodeId node) { } RRNodeId RRGraphBuilder::create_node(int x, int y, t_rr_type type, int ptc, e_side side) { + e_side node_side = SIDES[0]; + /* Only OPIN and IPIN nodes have sides, otherwise force to use a default side */ + if (OPIN == type || IPIN == type) { + node_side = side; + } node_storage_.emplace_back(); RRNodeId new_node = RRNodeId(node_storage_.size() - 1); node_storage_.set_node_type(new_node, type); node_storage_.set_node_coordinates(new_node, x, y, x, y); node_storage_.set_node_ptc_num(new_node, ptc); - if (CHANX != type && CHANY != type) { - node_storage_.add_node_side(new_node, side); + if (OPIN == type || IPIN == type) { + node_storage_.add_node_side(new_node, node_side); } - node_lookup_.add_node(new_node, x, y, type, ptc, side); + node_lookup_.add_node(new_node, x, y, type, ptc, node_side); return new_node; } diff --git a/libs/librrgraph/src/base/rr_graph_builder.h b/libs/librrgraph/src/base/rr_graph_builder.h index 1a539d4fb30..bba33b21cf4 100644 --- a/libs/librrgraph/src/base/rr_graph_builder.h +++ b/libs/librrgraph/src/base/rr_graph_builder.h @@ -121,7 +121,7 @@ class RRGraphBuilder { /** @brief Create a new rr_node in the node storage and register it to the node look-up. * Return a valid node id if succeed. Otherwise, return an invalid id. */ - RRNodeId create_node(int x, int y, t_rr_type type, int ptc, e_side side = SIDES[0]); + RRNodeId create_node(int x, int y, t_rr_type type, int ptc, e_side side = NUM_SIDES); /** * @brief Add an existing rr_node in the node storage to the node look-up * diff --git a/libs/librrgraph/src/base/rr_graph_view.h b/libs/librrgraph/src/base/rr_graph_view.h index b2695e67e62..f5a4312ad07 100644 --- a/libs/librrgraph/src/base/rr_graph_view.h +++ b/libs/librrgraph/src/base/rr_graph_view.h @@ -499,6 +499,11 @@ class RRGraphView { return node_storage_.validate_node(node_id, rr_switch_inf_); } + /** @brief Check if the node id is a valid one in storage */ + inline bool valid_node(RRNodeId node_id) const { + return size_t(node_id) < node_storage_.size(); + } + /** @brief Check if the switch is a valid one in storage */ inline bool valid_switch(RRSwitchId switch_id) const { return (size_t(switch_id) < rr_switch_inf_.size()); diff --git a/vpr/src/route/rr_graph.cpp b/vpr/src/route/rr_graph.cpp index f992602a6ca..0bc7faf11df 100644 --- a/vpr/src/route/rr_graph.cpp +++ b/vpr/src/route/rr_graph.cpp @@ -350,7 +350,7 @@ void create_rr_graph(const t_graph_type graph_type, Warnings); } else { /* We do not support dedicated network for clocks in tileable rr_graph generation */ - VTR_LOG_WARN("Tileable routing resource graph does not support clock modeling yet! Related options are ignored..."); + VTR_LOG_WARN("Tileable routing resource graph does not support clock modeling yet! Related options are ignored...\n"); build_tileable_unidir_rr_graph(block_types, grid, nodes_per_chan, diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp index 031deebd58a..ed43eb14657 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp @@ -168,6 +168,8 @@ void build_tileable_unidir_rr_graph(const std::vector& typ delayless_rr_switch, through_channel); + VTR_LOG("Built %d nodes\n", device_ctx.rr_graph.num_nodes()); + /************************************************************************ * Create the connectivity of OPINs * a. Evenly assign connections to OPINs to routing tracks diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp index 317cafca793..ae24c263708 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp @@ -35,10 +35,14 @@ void build_rr_graph_edges_for_source_nodes(const RRGraphView& rr_graph, rr_graph.node_pin_num(node)); /* Create edges between SOURCE and OPINs */ - const RRNodeId& src_node = rr_graph_builder.node_lookup().find_node(xlow - grids[xlow][ylow].width_offset, - ylow - grids[xlow][ylow].height_offset, - SOURCE, src_node_class_num); - VTR_ASSERT(true == rr_graph.validate_node(src_node)); + const RRNodeId& src_node = rr_graph.node_lookup().find_node(xlow - grids[xlow][ylow].width_offset, + ylow - grids[xlow][ylow].height_offset, + SOURCE, src_node_class_num, SIDES[0]); + VTR_LOG("Des Node: %ld, %s\n", + size_t(node), rr_graph.node_coordinate_to_string(node).c_str()); + VTR_LOG("Src Node: %ld, xlow: %d, ylow:%d, grid.width_offset:%d, grid.height_offset:%d, class_id:%d\n", + size_t(src_node), xlow, ylow, grids[xlow][ylow].width_offset, grids[xlow][ylow].height_offset, src_node_class_num); + VTR_ASSERT(true == rr_graph.valid_node(src_node)); /* add edges to the src_node */ rr_graph_builder.create_edge(src_node, node, rr_node_driver_switches[node]); @@ -68,8 +72,8 @@ void build_rr_graph_edges_for_sink_nodes(const RRGraphView& rr_graph, /* 1. create edges between IPINs and SINKs */ const RRNodeId& sink_node = rr_graph.node_lookup().find_node(xlow - grids[xlow][ylow].width_offset, ylow - grids[xlow][ylow].height_offset, - SINK, sink_node_class_num); - VTR_ASSERT(true == rr_graph.validate_node(sink_node)); + SINK, sink_node_class_num, SIDES[0]); + VTR_ASSERT(true == rr_graph.valid_node(sink_node)); /* add edges to connect the IPIN node to SINK nodes */ rr_graph_builder.create_edge(node, sink_node, rr_node_driver_switches[sink_node]); diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp index 1f0c886ae9d..d5f103737bd 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp @@ -366,7 +366,7 @@ static void build_gsb_one_group_track_to_track_map(const RRGraphView& rr_graph, // from_tracks[side].size(), inode, to_track_id, to_track_ids[to_track_id], // to_track_index, to_tracks[to_side_index].size()); const RRNodeId& to_track_node = rr_gsb.get_chan_node(to_side, to_track_index); - VTR_ASSERT(true == rr_graph.validate_node(to_track_node)); + VTR_ASSERT(true == rr_graph.valid_node(to_track_node)); /* from_track should be IN_PORT */ VTR_ASSERT(IN_PORT == rr_gsb.get_chan_node_direction(from_side, from_track_index)); diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp index 3c845839b01..bec760f5735 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp @@ -343,6 +343,8 @@ void alloc_tileable_rr_graph_nodes(RRGraphBuilder& rr_graph_builder, rr_graph_builder.reserve_nodes(num_nodes); rr_node_driver_switches.resize(num_nodes); + + VTR_LOG("Allocated %d nodes\n", num_nodes); } /************************************************************************ @@ -380,7 +382,7 @@ static void load_one_grid_opin_nodes_basic_info(RRGraphBuilder& rr_graph_builder width, height); for (const int& pin_num : opin_list) { /* Create a new node and fill information */ - const RRNodeId& node = rr_graph_builder.create_node(width, height, OPIN, pin_num, side); + RRNodeId node = rr_graph_builder.create_node(grid_coordinate.x() + width, grid_coordinate.y() + height, OPIN, pin_num, side); /* node bounding box */ rr_graph_builder.set_node_coordinates(node, grid_coordinate.x() + width, @@ -442,7 +444,7 @@ static void load_one_grid_ipin_nodes_basic_info(RRGraphBuilder& rr_graph_builder std::vector ipin_list = get_grid_side_pins(cur_grid, RECEIVER, side_manager.get_side(), width, height); for (const int& pin_num : ipin_list) { /* Create a new node and fill information */ - const RRNodeId& node = rr_graph_builder.create_node(width, height, IPIN, pin_num, side); + RRNodeId node = rr_graph_builder.create_node(grid_coordinate.x() + width, grid_coordinate.y() + height, IPIN, pin_num, side); /* node bounding box */ rr_graph_builder.set_node_coordinates(node, grid_coordinate.x() + width, @@ -486,14 +488,18 @@ static void load_one_grid_source_nodes_basic_info(RRGraphBuilder& rr_graph_build SideManager io_side_manager(io_side); /* Set a SOURCE rr_node for each DRIVER class */ - for (int iclass = 0; iclass < cur_grid.type->num_class; ++iclass) { + VTR_LOG("Grid type=%s, x=%d, y=%d, num_class=%d\n", + cur_grid.type->name, grid_coordinate.x(), grid_coordinate.y(), cur_grid.type->class_inf.size()); + for (int iclass = 0; iclass < cur_grid.type->class_inf.size(); ++iclass) { /* Set a SINK rr_node for the OPIN */ if (DRIVER != cur_grid.type->class_inf[iclass].type) { continue; } /* Create a new node and fill information */ - const RRNodeId& node = rr_graph_builder.create_node(grid_coordinate.x(), grid_coordinate.y(), SOURCE, iclass); + RRNodeId node = rr_graph_builder.create_node(grid_coordinate.x(), grid_coordinate.y(), SOURCE, iclass); + VTR_LOG("Node: %d, x=%d, y=%d, type=SOURCE, class=%d\n", + size_t(node), grid_coordinate.x(), grid_coordinate.y(), iclass); /* node bounding box */ rr_graph_builder.set_node_coordinates(node, grid_coordinate.x(), @@ -502,8 +508,6 @@ static void load_one_grid_source_nodes_basic_info(RRGraphBuilder& rr_graph_build grid_coordinate.y() + cur_grid.type->height - 1); rr_graph_builder.set_node_class_num(node, iclass); - rr_graph_builder.set_node_capacity(node, 1); - /* The capacity should be the number of pins in this class*/ rr_graph_builder.set_node_capacity(node, cur_grid.type->class_inf[iclass].num_pins); @@ -536,14 +540,14 @@ static void load_one_grid_sink_nodes_basic_info(RRGraphBuilder& rr_graph_builder SideManager io_side_manager(io_side); /* Set a SINK rr_node for each RECEIVER class */ - for (int iclass = 0; iclass < cur_grid.type->num_class; ++iclass) { + for (int iclass = 0; iclass < cur_grid.type->class_inf.size(); ++iclass) { /* Set a SINK rr_node for the OPIN */ if (RECEIVER != cur_grid.type->class_inf[iclass].type) { continue; } /* Create a new node and fill information */ - const RRNodeId& node = rr_graph_builder.create_node(grid_coordinate.x(), grid_coordinate.y(), SINK, iclass); + RRNodeId node = rr_graph_builder.create_node(grid_coordinate.x(), grid_coordinate.y(), SINK, iclass); /* node bounding box */ rr_graph_builder.set_node_coordinates(node, grid_coordinate.x(), @@ -637,6 +641,27 @@ static void load_grid_nodes_basic_info(RRGraphBuilder& rr_graph_builder, wire_to_ipin_switch); } } + //Copy the SOURCE/SINK nodes to all offset positions for blocks with width > 1 and/or height > 1 + // This ensures that look-ups on non-root locations will still find the correct SOURCE/SINK + for (size_t x = 0; x < grids.width(); x++) { + for (size_t y = 0; y < grids.height(); y++) { + int width_offset = grids[x][y].width_offset; + int height_offset = grids[x][y].height_offset; + if (width_offset != 0 || height_offset != 0) { + int root_x = x - width_offset; + int root_y = y - height_offset; + + rr_graph_builder.node_lookup().mirror_nodes(vtr::Point(root_x, root_y), + vtr::Point(x, y), + SOURCE, + SIDES[0]); + rr_graph_builder.node_lookup().mirror_nodes(vtr::Point(root_x, root_y), + vtr::Point(x, y), + SINK, + SIDES[0]); + } + } + } } /************************************************************************ From a96afb91dd51eef4ab04a5715ce2714049092821 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 15 Aug 2022 18:43:10 -0700 Subject: [PATCH 031/147] [vpr] fixed a bug --- vpr/src/tileable_rr_graph/rr_graph_builder_utils.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vpr/src/tileable_rr_graph/rr_graph_builder_utils.cpp b/vpr/src/tileable_rr_graph/rr_graph_builder_utils.cpp index cb8afb1db9a..4fc935fae4b 100644 --- a/vpr/src/tileable_rr_graph/rr_graph_builder_utils.cpp +++ b/vpr/src/tileable_rr_graph/rr_graph_builder_utils.cpp @@ -136,7 +136,7 @@ size_t get_grid_num_classes(const t_grid_tile& cur_grid, const e_pin_type& pin_type) { size_t num_classes = 0; - for (int iclass = 0; iclass < cur_grid.type->num_class; ++iclass) { + for (int iclass = 0; iclass < cur_grid.type->class_inf.size(); ++iclass) { /* Bypass unmatched pin_type */ if (pin_type != cur_grid.type->class_inf[iclass].type) { continue; From 00d118d101e3453c4ba247c67219730b31ebff65 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 15 Aug 2022 22:37:41 -0700 Subject: [PATCH 032/147] [vpr] keep debugging the errors in find_node() --- .../tileable_rr_graph_builder.cpp | 1 - .../tileable_rr_graph_edge_builder.cpp | 7 ++++--- .../tileable_rr_graph_node_builder.cpp | 18 ++++++++---------- .../tileable_rr_graph_node_builder.h | 2 +- 4 files changed, 13 insertions(+), 15 deletions(-) diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp index ed43eb14657..ddc8e4399ab 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp @@ -233,7 +233,6 @@ void build_tileable_unidir_rr_graph(const std::vector& typ * Add edges that bridge OPINs and IPINs to the rr_graph ***********************************************************************/ /* Create edges for a tileable rr_graph */ - build_rr_graph_edges(device_ctx.rr_graph, device_ctx.rr_graph_builder, rr_node_driver_switches, diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp index ae24c263708..5b89fca945c 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp @@ -33,11 +33,12 @@ void build_rr_graph_edges_for_source_nodes(const RRGraphView& rr_graph, short ylow = rr_graph.node_ylow(node); short src_node_class_num = get_grid_pin_class_index(grids[xlow][ylow], rr_graph.node_pin_num(node)); + VTR_ASSERT(node == rr_graph.node_lookup().find_node(xlow, ylow, OPIN, rr_graph.node_pin_num(node), TOP)); /* Create edges between SOURCE and OPINs */ - const RRNodeId& src_node = rr_graph.node_lookup().find_node(xlow - grids[xlow][ylow].width_offset, - ylow - grids[xlow][ylow].height_offset, - SOURCE, src_node_class_num, SIDES[0]); + RRNodeId src_node = rr_graph.node_lookup().find_node(xlow - grids[xlow][ylow].width_offset, + ylow - grids[xlow][ylow].height_offset, + SOURCE, src_node_class_num); VTR_LOG("Des Node: %ld, %s\n", size_t(node), rr_graph.node_coordinate_to_string(node).c_str()); VTR_LOG("Src Node: %ld, xlow: %d, ylow:%d, grid.width_offset:%d, grid.height_offset:%d, class_id:%d\n", diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp index bec760f5735..c897fa0f306 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp @@ -488,9 +488,7 @@ static void load_one_grid_source_nodes_basic_info(RRGraphBuilder& rr_graph_build SideManager io_side_manager(io_side); /* Set a SOURCE rr_node for each DRIVER class */ - VTR_LOG("Grid type=%s, x=%d, y=%d, num_class=%d\n", - cur_grid.type->name, grid_coordinate.x(), grid_coordinate.y(), cur_grid.type->class_inf.size()); - for (int iclass = 0; iclass < cur_grid.type->class_inf.size(); ++iclass) { + for (size_t iclass = 0; iclass < cur_grid.type->class_inf.size(); ++iclass) { /* Set a SINK rr_node for the OPIN */ if (DRIVER != cur_grid.type->class_inf[iclass].type) { continue; @@ -498,8 +496,8 @@ static void load_one_grid_source_nodes_basic_info(RRGraphBuilder& rr_graph_build /* Create a new node and fill information */ RRNodeId node = rr_graph_builder.create_node(grid_coordinate.x(), grid_coordinate.y(), SOURCE, iclass); - VTR_LOG("Node: %d, x=%d, y=%d, type=SOURCE, class=%d\n", - size_t(node), grid_coordinate.x(), grid_coordinate.y(), iclass); + VTR_LOG("Node id=%d, x=%d, y=%d, class=%d\n", size_t(node), grid_coordinate.x(), grid_coordinate.y(), iclass); + VTR_ASSERT(RRNodeId(0) == rr_graph_builder.node_lookup().find_node(1, 0, SOURCE, 1)); /* node bounding box */ rr_graph_builder.set_node_coordinates(node, grid_coordinate.x(), @@ -540,7 +538,7 @@ static void load_one_grid_sink_nodes_basic_info(RRGraphBuilder& rr_graph_builder SideManager io_side_manager(io_side); /* Set a SINK rr_node for each RECEIVER class */ - for (int iclass = 0; iclass < cur_grid.type->class_inf.size(); ++iclass) { + for (size_t iclass = 0; iclass < cur_grid.type->class_inf.size(); ++iclass) { /* Set a SINK rr_node for the OPIN */ if (RECEIVER != cur_grid.type->class_inf[iclass].type) { continue; @@ -669,7 +667,7 @@ static void load_grid_nodes_basic_info(RRGraphBuilder& rr_graph_builder, * coordinates: xlow, ylow, xhigh, yhigh, * features: capacity, track_ids, ptc_num, direction ***********************************************************************/ -static void load_one_chan_rr_nodes_basic_info(RRGraphView& rr_graph, +static void load_one_chan_rr_nodes_basic_info(const RRGraphView& rr_graph, RRGraphBuilder& rr_graph_builder, vtr::vector& rr_node_driver_switches, std::map>& rr_node_track_ids, @@ -780,7 +778,7 @@ static void load_one_chan_rr_nodes_basic_info(RRGraphView& rr_graph, * features: capacity, track_ids, ptc_num, direction * grid_info : pb_graph_pin ***********************************************************************/ -static void load_chanx_rr_nodes_basic_info(RRGraphView& rr_graph, +static void load_chanx_rr_nodes_basic_info(const RRGraphView& rr_graph, RRGraphBuilder& rr_graph_builder, vtr::vector& rr_node_driver_switches, std::map>& rr_node_track_ids, @@ -887,7 +885,7 @@ static void load_chanx_rr_nodes_basic_info(RRGraphView& rr_graph, * coordinates: xlow, ylow, xhigh, yhigh, * features: capacity, track_ids, ptc_num, direction ***********************************************************************/ -static void load_chany_rr_nodes_basic_info(RRGraphView& rr_graph, +static void load_chany_rr_nodes_basic_info(const RRGraphView& rr_graph, RRGraphBuilder& rr_graph_builder, vtr::vector& rr_node_driver_switches, std::map>& rr_node_track_ids, @@ -1020,7 +1018,7 @@ static void reverse_dec_chan_rr_node_track_ids(const RRGraphView& rr_graph, /************************************************************************ * Create all the rr_nodes covering both grids and routing channels ***********************************************************************/ -void create_tileable_rr_graph_nodes(RRGraphView& rr_graph, +void create_tileable_rr_graph_nodes(const RRGraphView& rr_graph, RRGraphBuilder& rr_graph_builder, vtr::vector& rr_node_driver_switches, std::map>& rr_node_track_ids, diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.h b/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.h index 116f51e3a89..1372513200a 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.h +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.h @@ -27,7 +27,7 @@ void alloc_tileable_rr_graph_nodes(RRGraphBuilder& rr_graph_builder, const std::vector& segment_infs, const bool& through_channel); -void create_tileable_rr_graph_nodes(RRGraphView& rr_graph, +void create_tileable_rr_graph_nodes(const RRGraphView& rr_graph, RRGraphBuilder& rr_graph_builder, vtr::vector& rr_node_driver_switches, std::map>& rr_node_track_ids, From c460ad1ce6077a4491f45358c49eff4c17a4fcea Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 16 Aug 2022 11:14:30 -0700 Subject: [PATCH 033/147] [vpr] identify bugs in resize() in RRSpatial, Use reserve() to bypass it --- .../librrgraph/src/base/rr_spatial_lookup.cpp | 1 + .../tileable_rr_graph_edge_builder.cpp | 6 ---- .../tileable_rr_graph_node_builder.cpp | 32 +++++++++++++++++-- 3 files changed, 31 insertions(+), 8 deletions(-) diff --git a/libs/librrgraph/src/base/rr_spatial_lookup.cpp b/libs/librrgraph/src/base/rr_spatial_lookup.cpp index 6f6bae475d3..7818a5254e8 100644 --- a/libs/librrgraph/src/base/rr_spatial_lookup.cpp +++ b/libs/librrgraph/src/base/rr_spatial_lookup.cpp @@ -1,4 +1,5 @@ #include "vtr_assert.h" +#include "vtr_log.h" #include "rr_spatial_lookup.h" RRSpatialLookup::RRSpatialLookup() { diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp index 5b89fca945c..195c5eabe9f 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp @@ -33,16 +33,10 @@ void build_rr_graph_edges_for_source_nodes(const RRGraphView& rr_graph, short ylow = rr_graph.node_ylow(node); short src_node_class_num = get_grid_pin_class_index(grids[xlow][ylow], rr_graph.node_pin_num(node)); - VTR_ASSERT(node == rr_graph.node_lookup().find_node(xlow, ylow, OPIN, rr_graph.node_pin_num(node), TOP)); - /* Create edges between SOURCE and OPINs */ RRNodeId src_node = rr_graph.node_lookup().find_node(xlow - grids[xlow][ylow].width_offset, ylow - grids[xlow][ylow].height_offset, SOURCE, src_node_class_num); - VTR_LOG("Des Node: %ld, %s\n", - size_t(node), rr_graph.node_coordinate_to_string(node).c_str()); - VTR_LOG("Src Node: %ld, xlow: %d, ylow:%d, grid.width_offset:%d, grid.height_offset:%d, class_id:%d\n", - size_t(src_node), xlow, ylow, grids[xlow][ylow].width_offset, grids[xlow][ylow].height_offset, src_node_class_num); VTR_ASSERT(true == rr_graph.valid_node(src_node)); /* add edges to the src_node */ diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp index c897fa0f306..f6bf54b917f 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp @@ -496,8 +496,6 @@ static void load_one_grid_source_nodes_basic_info(RRGraphBuilder& rr_graph_build /* Create a new node and fill information */ RRNodeId node = rr_graph_builder.create_node(grid_coordinate.x(), grid_coordinate.y(), SOURCE, iclass); - VTR_LOG("Node id=%d, x=%d, y=%d, class=%d\n", size_t(node), grid_coordinate.x(), grid_coordinate.y(), iclass); - VTR_ASSERT(RRNodeId(0) == rr_graph_builder.node_lookup().find_node(1, 0, SOURCE, 1)); /* node bounding box */ rr_graph_builder.set_node_coordinates(node, grid_coordinate.x(), @@ -596,12 +594,27 @@ static void load_grid_nodes_basic_info(RRGraphBuilder& rr_graph_builder, vtr::Point grid_coordinate(ix, iy); enum e_side io_side = NUM_SIDES; + std::vector wanted_sides{TOP, RIGHT, BOTTOM, LEFT}; + /* If this is the block on borders, we consider IO side */ if (true == is_io_type(grids[ix][iy].type)) { vtr::Point io_device_size(grids.width() - 1, grids.height() - 1); io_side = determine_io_grid_pin_side(io_device_size, grid_coordinate); + wanted_sides.clear(); + wanted_sides.push_back(io_side); } + for (e_side side : wanted_sides) { + for (int width_offset = 0; width_offset < grids[ix][iy].type->width; ++width_offset) { + int x_tile = ix + width_offset; + for (int height_offset = 0; height_offset < grids[ix][iy].type->height; ++height_offset) { + int y_tile = iy + height_offset; + rr_graph_builder.node_lookup().reserve_nodes(x_tile, y_tile, OPIN, grids[ix][iy].type->num_pins, side); + rr_graph_builder.node_lookup().reserve_nodes(x_tile, y_tile, IPIN, grids[ix][iy].type->num_pins, side); + } + } + } + /* Configure source rr_nodes for this grid */ load_one_grid_source_nodes_basic_info(rr_graph_builder, rr_node_driver_switches, @@ -1029,6 +1042,21 @@ void create_tileable_rr_graph_nodes(const RRGraphView& rr_graph, const RRSwitchId& wire_to_ipin_switch, const RRSwitchId& delayless_switch, const bool& through_channel) { + /* Allocates and loads all the structures needed for fast lookups of the * + * index of an rr_node. rr_node_indices is a matrix containing the index * + * of the *first* rr_node at a given (i,j) location. */ + + /* Alloc the lookup table + * .. warning: It is mandatory. There are bugs in resize() when called incrementally in RRSpatialLookup. + * When comment the following block out, you will see errors */ + for (t_rr_type rr_type : RR_TYPES) { + if (rr_type == CHANX) { + rr_graph_builder.node_lookup().resize_nodes(grids.height(), grids.width(), rr_type, NUM_SIDES); + } else { + rr_graph_builder.node_lookup().resize_nodes(grids.width(), grids.height(), rr_type, NUM_SIDES); + } + } + load_grid_nodes_basic_info(rr_graph_builder, rr_node_driver_switches, rr_rc_data, From dcb50bc99ae6e98547bcbe755531fd659aab3303 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 16 Aug 2022 11:27:30 -0700 Subject: [PATCH 034/147] [vpr] consider special case for CHANX when creating a new node --- libs/librrgraph/src/base/rr_graph_builder.cpp | 7 ++++++- vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp | 1 + .../tileable_rr_graph/tileable_rr_graph_node_builder.cpp | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/libs/librrgraph/src/base/rr_graph_builder.cpp b/libs/librrgraph/src/base/rr_graph_builder.cpp index a55e7ee2882..caff0554418 100644 --- a/libs/librrgraph/src/base/rr_graph_builder.cpp +++ b/libs/librrgraph/src/base/rr_graph_builder.cpp @@ -80,7 +80,12 @@ RRNodeId RRGraphBuilder::create_node(int x, int y, t_rr_type type, int ptc, e_si if (OPIN == type || IPIN == type) { node_storage_.add_node_side(new_node, node_side); } - node_lookup_.add_node(new_node, x, y, type, ptc, node_side); + /* Special for CHANX, being consistent with the rule in find_node() */ + if (CHANX == type) { + node_lookup_.add_node(new_node, y, x, type, ptc, node_side); + } else { + node_lookup_.add_node(new_node, x, y, type, ptc, node_side); + } return new_node; } diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp index d5f103737bd..a33eda105d4 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp @@ -158,6 +158,7 @@ static bool is_gsb_in_track_sb_population(const RRGraphView& rr_graph, /* Get segment id */ RRSegmentId seg_id = rr_gsb.get_chan_node_segment(gsb_side, track_id); /* validate offset */ + if (!(offset < segment_inf[size_t(seg_id)].sb.size())) VTR_ASSERT(offset < segment_inf[size_t(seg_id)].sb.size()); /* Get the SB population */ diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp index f6bf54b917f..992874c0c25 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp @@ -702,7 +702,7 @@ static void load_one_chan_rr_nodes_basic_info(const RRGraphView& rr_graph, || ((true == chan_details.is_track_end(itrack)) && (Direction::DEC == chan_details.get_track_direction(itrack)))) { /* Create a new chan rr_node */ - const RRNodeId& node = rr_graph_builder.create_node(chan_coordinate.x(), chan_coordinate.y(), chan_type, itrack); + RRNodeId node = rr_graph_builder.create_node(chan_coordinate.x(), chan_coordinate.y(), chan_type, itrack); rr_graph_builder.set_node_direction(node, chan_details.get_track_direction(itrack)); rr_graph_builder.set_node_track_num(node, itrack); From fa22d5b7a82d3a08462e51b17a16e5e5e010101e Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 16 Aug 2022 11:43:37 -0700 Subject: [PATCH 035/147] [vpr] now tileable rr_graph builder is working. Correctness not checked. Still need to check backward compatibility --- vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp | 4 ++-- vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp index ddc8e4399ab..3df202df572 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp @@ -168,8 +168,6 @@ void build_tileable_unidir_rr_graph(const std::vector& typ delayless_rr_switch, through_channel); - VTR_LOG("Built %d nodes\n", device_ctx.rr_graph.num_nodes()); - /************************************************************************ * Create the connectivity of OPINs * a. Evenly assign connections to OPINs to routing tracks @@ -264,6 +262,7 @@ void build_tileable_unidir_rr_graph(const std::vector& typ /* Allocate and load routing resource switches, which are derived from the switches from the architecture file, * based on their fanin in the rr graph. This routine also adjusts the rr nodes to point to these new rr switches */ + device_ctx.rr_graph_builder.init_fan_in(); alloc_and_load_rr_switch_inf(device_ctx.num_arch_switches, R_minW_nmos, R_minW_pmos, wire_to_arch_ipin_switch, wire_to_rr_ipin_switch); /* Save the channel widths for the newly constructed graph */ @@ -273,6 +272,7 @@ void build_tileable_unidir_rr_graph(const std::vector& typ device_ctx.rr_node_track_ids = rr_node_track_ids; /* Build incoming edges */ + device_ctx.rr_graph_builder.partition_edges(); device_ctx.rr_graph_builder.build_in_edges(); /************************************************************************ diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp index 992874c0c25..6dd205d0f18 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp @@ -343,8 +343,6 @@ void alloc_tileable_rr_graph_nodes(RRGraphBuilder& rr_graph_builder, rr_graph_builder.reserve_nodes(num_nodes); rr_node_driver_switches.resize(num_nodes); - - VTR_LOG("Allocated %d nodes\n", num_nodes); } /************************************************************************ From 2ee2bae4b4bd7222fa7272d38acf3ef098652be7 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 16 Aug 2022 15:12:36 -0700 Subject: [PATCH 036/147] [script] use relative path in lib capn'proto, to solve compilation errors when using VTR as a submodule --- libs/libvtrcapnproto/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/libvtrcapnproto/CMakeLists.txt b/libs/libvtrcapnproto/CMakeLists.txt index cd97b0ec4f1..0f66a10856a 100644 --- a/libs/libvtrcapnproto/CMakeLists.txt +++ b/libs/libvtrcapnproto/CMakeLists.txt @@ -32,7 +32,7 @@ capnp_generate_cpp(CAPNP_SRCS CAPNP_HDRS ) if (VPR_ENABLE_INTERCHANGE) - set(IC_DIR ${CMAKE_SOURCE_DIR}/libs/EXTERNAL/libinterchange/interchange) + set(IC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../EXTERNAL/libinterchange/interchange) set(CAPNPC_SRC_PREFIX ${IC_DIR}) find_program(WGET wget REQUIRED) From d43e6672066a029edf5de19d31218cb719ee0601 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 16 Aug 2022 16:34:13 -0700 Subject: [PATCH 037/147] [lib] add interconnect string version and add invalid type --- libs/libarchfpga/src/physical_types.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libs/libarchfpga/src/physical_types.h b/libs/libarchfpga/src/physical_types.h index bd265299bf8..44aa09d543f 100644 --- a/libs/libarchfpga/src/physical_types.h +++ b/libs/libarchfpga/src/physical_types.h @@ -164,8 +164,11 @@ enum e_pin_type { enum e_interconnect { COMPLETE_INTERC = 1, DIRECT_INTERC = 2, - MUX_INTERC = 3 + MUX_INTERC = 3, + NUM_INTERC_TYPES /* Invalid type */ }; +/* String version of interconnect types. Use for debugging messages */ +constexpr std::array INTERCONNECT_TYPE_STRING = {{"unknown", "complete", "direct", "mux"}}; /* Orientations. */ enum e_side : unsigned char { From f6844ecb7a70197553f33b5e3ad38a2ca79f9a98 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 16 Aug 2022 16:37:05 -0700 Subject: [PATCH 038/147] [lib] typo --- libs/libarchfpga/src/physical_types.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/libarchfpga/src/physical_types.h b/libs/libarchfpga/src/physical_types.h index 44aa09d543f..a652d684dac 100644 --- a/libs/libarchfpga/src/physical_types.h +++ b/libs/libarchfpga/src/physical_types.h @@ -168,7 +168,7 @@ enum e_interconnect { NUM_INTERC_TYPES /* Invalid type */ }; /* String version of interconnect types. Use for debugging messages */ -constexpr std::array INTERCONNECT_TYPE_STRING = {{"unknown", "complete", "direct", "mux"}}; +constexpr std::array INTERCONNECT_TYPE_STRING = {{"unknown", "complete", "direct", "mux"}}; /* Orientations. */ enum e_side : unsigned char { From 3653c773711ca7893e98372792b1b3e560bcf95e Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 17 Aug 2022 09:53:51 -0700 Subject: [PATCH 039/147] [lib] add APIs required by OpenFPGA for rr_graph --- libs/librrgraph/src/base/rr_graph_view.cpp | 5 +++++ libs/librrgraph/src/base/rr_graph_view.h | 3 +++ 2 files changed, 8 insertions(+) diff --git a/libs/librrgraph/src/base/rr_graph_view.cpp b/libs/librrgraph/src/base/rr_graph_view.cpp index 5ae0d7a430e..da435033980 100644 --- a/libs/librrgraph/src/base/rr_graph_view.cpp +++ b/libs/librrgraph/src/base/rr_graph_view.cpp @@ -39,3 +39,8 @@ std::vector RRGraphView::find_edges(const RRNodeId& src_node, const RR } return edge_list; } + +RRSegmentId node_segment(RRNodeId node) const { + RRIndexedDataId cost_index = node_cost_index(node); + return RRSegmentId(rr_indexed_data_[cost_index].seg_index); +} diff --git a/libs/librrgraph/src/base/rr_graph_view.h b/libs/librrgraph/src/base/rr_graph_view.h index f5a4312ad07..7ca760b8d6a 100644 --- a/libs/librrgraph/src/base/rr_graph_view.h +++ b/libs/librrgraph/src/base/rr_graph_view.h @@ -422,6 +422,9 @@ class RRGraphView { return node_storage_.node_cost_index(node); } + /** @brief Get the segment id which a routing resource node represents. Only applicable to nodes whose type is CHANX or CHANY */ + RRSegmentId node_segment(RRNodeId node) const; + /** @brief Return incoming edges for a given routing resource node * Require build_in_edges() to be called first */ From bcc0fd9dbefc8649647b99525421274a538d07f4 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 17 Aug 2022 09:55:54 -0700 Subject: [PATCH 040/147] [lib] syntax --- libs/librrgraph/src/base/rr_graph_view.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/librrgraph/src/base/rr_graph_view.cpp b/libs/librrgraph/src/base/rr_graph_view.cpp index da435033980..f20ba626bea 100644 --- a/libs/librrgraph/src/base/rr_graph_view.cpp +++ b/libs/librrgraph/src/base/rr_graph_view.cpp @@ -40,7 +40,7 @@ std::vector RRGraphView::find_edges(const RRNodeId& src_node, const RR return edge_list; } -RRSegmentId node_segment(RRNodeId node) const { +RRSegmentId RRGraphView::node_segment(RRNodeId node) const { RRIndexedDataId cost_index = node_cost_index(node); return RRSegmentId(rr_indexed_data_[cost_index].seg_index); } From b54d4ad4f3e6bbd0e54a567be3921fdd30efed4d Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 17 Aug 2022 10:16:35 -0700 Subject: [PATCH 041/147] [lib] add missing APIs required by OpenFPGA to RRGraphView --- libs/librrgraph/src/base/rr_graph_view.cpp | 30 +++++++++++++++++++ libs/librrgraph/src/base/rr_graph_view.h | 8 +++++ .../rr_graph_builder_utils.cpp | 2 +- 3 files changed, 39 insertions(+), 1 deletion(-) diff --git a/libs/librrgraph/src/base/rr_graph_view.cpp b/libs/librrgraph/src/base/rr_graph_view.cpp index f20ba626bea..968ca940f47 100644 --- a/libs/librrgraph/src/base/rr_graph_view.cpp +++ b/libs/librrgraph/src/base/rr_graph_view.cpp @@ -30,6 +30,36 @@ std::vector RRGraphView::node_in_edges(RRNodeId node) const { return node_in_edges_[node]; } +std::vector RRGraphView::node_configurable_in_edges(RRNodeId node) const { + /* Note: This is not efficient in runtime, should sort edges by configurability when allocating the array! */ + VTR_ASSERT(size_t(node) < node_storage_.size()); + std::vector ret_edges; + if (node_in_edges_.empty()) { + return ret_edges; + } + for (const RREdgeId& edge : node_in_edges_[node]) { + if (rr_switch_inf_[edge_switch(edge)].configurable()) { + ret_edges.push_back(edge); + } + } + return ret_edges; +} + +std::vector RRGraphView::node_non_configurable_in_edges(RRNodeId node) const { + /* Note: This is not efficient in runtime, should sort edges by configurability when allocating the array! */ + VTR_ASSERT(size_t(node) < node_storage_.size()); + std::vector ret_edges; + if (node_in_edges_.empty()) { + return ret_edges; + } + for (const RREdgeId& edge : node_in_edges_[node]) { + if (!rr_switch_inf_[edge_switch(edge)].configurable()) { + ret_edges.push_back(edge); + } + } + return ret_edges; +} + std::vector RRGraphView::find_edges(const RRNodeId& src_node, const RRNodeId& des_node) const { std::vector edge_list; for (auto iedge : node_out_edges(src_node)) { diff --git a/libs/librrgraph/src/base/rr_graph_view.h b/libs/librrgraph/src/base/rr_graph_view.h index 7ca760b8d6a..162161569a6 100644 --- a/libs/librrgraph/src/base/rr_graph_view.h +++ b/libs/librrgraph/src/base/rr_graph_view.h @@ -353,6 +353,9 @@ class RRGraphView { inline edge_idx_range configurable_edges(RRNodeId node) const { return vtr::make_range(edge_idx_iterator(0), edge_idx_iterator(node_storage_.num_edges(node) - num_non_configurable_edges(node))); } + inline edge_idx_range node_configurable_out_edges(RRNodeId node) const { + return configurable_edges(node); + } /** @brief A non-configurable edge represents a hard-wired connection between routing resources, which could be * a non-configurable buffer that can not be turned off @@ -361,6 +364,9 @@ class RRGraphView { inline edge_idx_range non_configurable_edges(RRNodeId node) const { return vtr::make_range(edge_idx_iterator(node_storage_.num_edges(node) - num_non_configurable_edges(node)), edge_idx_iterator(num_edges(node))); } + inline edge_idx_range node_non_configurable_out_edges(RRNodeId node) const { + return non_configurable_edges(node); + } /** @brief Get outgoing edges for a node. * This API is designed to enable range-based loop to walk through the outgoing edges of a node @@ -429,6 +435,8 @@ class RRGraphView { * Require build_in_edges() to be called first */ std::vector node_in_edges(RRNodeId node) const; + std::vector node_configurable_in_edges(RRNodeId node) const; + std::vector node_non_configurable_in_edges(RRNodeId node) const; /** @brief Return detailed routing segment information with a given id* @note The routing segments here may not be exactly same as those defined in architecture file. They have been * adapted to fit the context of routing resource graphs. diff --git a/vpr/src/tileable_rr_graph/rr_graph_builder_utils.cpp b/vpr/src/tileable_rr_graph/rr_graph_builder_utils.cpp index 4fc935fae4b..c2fb1a580d4 100644 --- a/vpr/src/tileable_rr_graph/rr_graph_builder_utils.cpp +++ b/vpr/src/tileable_rr_graph/rr_graph_builder_utils.cpp @@ -136,7 +136,7 @@ size_t get_grid_num_classes(const t_grid_tile& cur_grid, const e_pin_type& pin_type) { size_t num_classes = 0; - for (int iclass = 0; iclass < cur_grid.type->class_inf.size(); ++iclass) { + for (size_t iclass = 0; iclass < cur_grid.type->class_inf.size(); ++iclass) { /* Bypass unmatched pin_type */ if (pin_type != cur_grid.type->class_inf[iclass].type) { continue; From 4e8ad95dcd623b7c9f362b419511fb9638c92f1e Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 17 Aug 2022 14:05:00 -0700 Subject: [PATCH 042/147] [vpr] remove unused headers --- vpr/src/tileable_rr_graph/openfpga_port.cpp | 438 -------------------- vpr/src/tileable_rr_graph/openfpga_port.h | 95 ----- vpr/src/tileable_rr_graph/rr_chan.h | 5 - 3 files changed, 538 deletions(-) delete mode 100644 vpr/src/tileable_rr_graph/openfpga_port.cpp delete mode 100644 vpr/src/tileable_rr_graph/openfpga_port.h diff --git a/vpr/src/tileable_rr_graph/openfpga_port.cpp b/vpr/src/tileable_rr_graph/openfpga_port.cpp deleted file mode 100644 index 63542cd7d5a..00000000000 --- a/vpr/src/tileable_rr_graph/openfpga_port.cpp +++ /dev/null @@ -1,438 +0,0 @@ -#include -#include -#include - -/* Headers from vtrutil library */ -#include "vtr_assert.h" - -#include "openfpga_port.h" - -/************************************************************************ - * Member functions for BasicPort class - ***********************************************************************/ - -/************************************************************************ - * Constructors - ***********************************************************************/ -/* Default constructor */ -BasicPort::BasicPort() { - /* By default we set an invalid port, which size is 0 */ - lsb_ = 1; - msb_ = 0; - - origin_port_width_ = -1; -} - -/* Quick constructor */ -BasicPort::BasicPort(const char* name, const size_t& lsb, const size_t& msb) { - set_name(std::string(name)); - set_width(lsb, msb); - set_origin_port_width(-1); -} - -BasicPort::BasicPort(const std::string& name, const size_t& lsb, const size_t& msb) { - set_name(name); - set_width(lsb, msb); - set_origin_port_width(-1); -} - -BasicPort::BasicPort(const char* name, const size_t& width) { - set_name(std::string(name)); - set_width(width); - set_origin_port_width(-1); -} - -BasicPort::BasicPort(const std::string& name, const size_t& width) { - set_name(name); - set_width(width); - set_origin_port_width(-1); -} - -/************************************************************************ - * Accessors - ***********************************************************************/ -/* get the port width */ -size_t BasicPort::get_width() const { - if (true == is_valid()) { - return msb_ - lsb_ + 1; - } - return 0; /* invalid port has a zero width */ -} - -/* get the LSB */ -size_t BasicPort::get_msb() const { - return msb_; -} - -/* get the LSB */ -size_t BasicPort::get_lsb() const { - return lsb_; -} - -/* get the name */ -std::string BasicPort::get_name() const { - return name_; -} - -/* Make a range of the pin indices */ -std::vector BasicPort::pins() const { - std::vector pin_indices; - - /* Return if the port is invalid */ - if (false == is_valid()) { - return pin_indices; /* Return an empty vector */ - } - /* For valid ports, create a vector whose length is the port width */ - pin_indices.resize(get_width()); - /* Fill in an incremental sequence */ - std::iota(pin_indices.begin(), pin_indices.end(), get_lsb()); - /* Ensure the last one is MSB */ - VTR_ASSERT(get_msb() == pin_indices.back()); - - return pin_indices; -} - -/* Check if a port can be merged with this port: their name should be the same */ -bool BasicPort::mergeable(const BasicPort& portA) const { - return (0 == this->get_name().compare(portA.get_name())); -} - -/* Check if a port is contained by this port: - * this function will check if the (LSB, MSB) of portA - * is contained by the (LSB, MSB) of this port - */ -bool BasicPort::contained(const BasicPort& portA) const { - return (lsb_ <= portA.get_lsb() && portA.get_msb() <= msb_); -} - -/* Set original port width */ -size_t BasicPort::get_origin_port_width() const { - return origin_port_width_; -} - -/************************************************************************ - * Overloaded operators - ***********************************************************************/ -/* Two ports are the same only when: - * 1. port names are the same - * 2. LSBs are the same - * 3. MSBs are the same - */ -bool BasicPort::operator==(const BasicPort& portA) const { - if ((0 == this->get_name().compare(portA.get_name())) - && (this->get_lsb() == portA.get_lsb()) - && (this->get_msb() == portA.get_msb())) { - return true; - } - return false; -} - -bool BasicPort::operator<(const BasicPort& portA) const { - if ((0 == this->get_name().compare(portA.get_name())) - && (this->get_lsb() < portA.get_lsb()) - && (this->get_msb() < portA.get_msb())) { - return true; - } - return false; -} - -/************************************************************************ - * Mutators - ***********************************************************************/ -/* copy */ -void BasicPort::set(const BasicPort& basic_port) { - name_ = basic_port.get_name(); - lsb_ = basic_port.get_lsb(); - msb_ = basic_port.get_msb(); - origin_port_width_ = basic_port.get_origin_port_width(); - - return; -} - -/* set the port LSB and MSB */ -void BasicPort::set_name(const std::string& name) { - name_ = name; - return; -} - -/* set the port LSB and MSB */ -void BasicPort::set_width(const size_t& width) { - if (0 == width) { - make_invalid(); - return; - } - lsb_ = 0; - msb_ = width - 1; - return; -} - -/* set the port LSB and MSB */ -void BasicPort::set_width(const size_t& lsb, const size_t& msb) { - /* If lsb and msb is invalid, we make a default port */ - if (lsb > msb) { - make_invalid(); - return; - } - set_lsb(lsb); - set_msb(msb); - return; -} - -void BasicPort::set_lsb(const size_t& lsb) { - lsb_ = lsb; - return; -} - -void BasicPort::set_msb(const size_t& msb) { - msb_ = msb; - return; -} - -void BasicPort::set_origin_port_width(const size_t& origin_port_width) { - origin_port_width_ = origin_port_width; - return; -} - -/* Increase the port width */ -void BasicPort::expand(const size_t& width) { - if (0 == width) { - return; /* ignore zero-width port */ - } - /* If current port is invalid, we do not combine */ - if (0 == get_width()) { - lsb_ = 0; - msb_ = width; - return; - } - /* Increase MSB */ - msb_ += width; - return; -} - -/* Swap lsb and msb */ -void BasicPort::revert() { - std::swap(lsb_, msb_); - return; -} - -/* rotate: increase both lsb and msb by an offset */ -bool BasicPort::rotate(const size_t& offset) { - /* If offset is 0, we do nothing */ - if (0 == offset) { - return true; - } - - /* If current width is 0, we set a width using the offset! */ - if (0 == get_width()) { - set_width(offset); - return true; - } - /* check if leads to overflow: - * if limits - msb is larger than offset - */ - if ((std::numeric_limits::max() - msb_ < offset)) { - return false; - } - /* Increase LSB and MSB */ - lsb_ += offset; - msb_ += offset; - return true; -} - -/* rotate: decrease both lsb and msb by an offset */ -bool BasicPort::counter_rotate(const size_t& offset) { - /* If current port is invalid or offset is 0, - * we do nothing - */ - if ((0 == offset) || (0 == get_width())) { - return true; - } - /* check if leads to overflow: - * if limits is larger than offset - */ - if ((std::numeric_limits::min() + lsb_ < offset)) { - return false; - } - /* decrease LSB and MSB */ - lsb_ -= offset; - msb_ -= offset; - return true; -} - -/* Reset to initial port */ -void BasicPort::reset() { - make_invalid(); - return; -} - -/* Combine two ports */ -void BasicPort::combine(const BasicPort& port) { - /* LSB follows the current LSB */ - /* MSB increases */ - VTR_ASSERT(0 < port.get_width()); /* Make sure port is valid */ - /* If current port is invalid, we do not combine */ - if (0 == get_width()) { - return; - } - /* Increase MSB */ - msb_ += port.get_width(); - return; -} - -/* A restricted combine function for two ports, - * Following conditions will be applied: - * 1. the two ports have the same name - * Note: you must run mergable() function first - * to make sure this assumption is valid - * 2. the new MSB will be the maximum MSB of the two ports - * 3. the new LSB will be the minimum LSB of the two ports - * 4. both ports should be valid!!! - */ -void BasicPort::merge(const BasicPort& portA) { - VTR_ASSERT(true == this->mergeable(portA)); - VTR_ASSERT(true == this->is_valid() && true == portA.is_valid()); - /* We skip merging if the portA is already contained by this port */ - if (true == this->contained(portA)) { - return; - } - /* LSB follows the minium LSB of the two ports */ - lsb_ = std::min((int)lsb_, (int)portA.get_lsb()); - /* MSB follows the minium MSB of the two ports */ - msb_ = std::max((int)msb_, (int)portA.get_msb()); - /* Origin port width follows the maximum of the two ports */ - msb_ = std::max((int)origin_port_width_, (int)portA.get_origin_port_width()); - return; -} - -/* Internal functions */ -/* Make a port to be invalid: msb < lsb */ -void BasicPort::make_invalid() { - /* set a default invalid port */ - lsb_ = 1; - msb_ = 0; - return; -} - -/* check if port size is valid > 0 */ -bool BasicPort::is_valid() const { - /* msb should be equal or greater than lsb, if this is a valid port */ - if (msb_ < lsb_) { - return false; - } - return true; -} - -/************************************************************************ - * ConfPorts member functions - ***********************************************************************/ - -/************************************************************************ - * Constructor - ***********************************************************************/ -/* Default constructor */ -ConfPorts::ConfPorts() { - /* default port */ - reserved_.reset(); - regular_.reset(); -} - -/* copy */ -ConfPorts::ConfPorts(const ConfPorts& conf_ports) { - set(conf_ports); -} - -/************************************************************************ - * Accessors - ***********************************************************************/ -size_t ConfPorts::get_reserved_port_width() const { - return reserved_.get_width(); -} - -size_t ConfPorts::get_reserved_port_lsb() const { - return reserved_.get_lsb(); -} - -size_t ConfPorts::get_reserved_port_msb() const { - return reserved_.get_msb(); -} - -size_t ConfPorts::get_regular_port_width() const { - return regular_.get_width(); -} - -size_t ConfPorts::get_regular_port_lsb() const { - return regular_.get_lsb(); -} - -size_t ConfPorts::get_regular_port_msb() const { - return regular_.get_msb(); -} - -/************************************************************************ - * Mutators - ***********************************************************************/ -void ConfPorts::set(const ConfPorts& conf_ports) { - set_reserved_port(conf_ports.get_reserved_port_width()); - set_regular_port(conf_ports.get_regular_port_lsb(), conf_ports.get_regular_port_msb()); - return; -} - -void ConfPorts::set_reserved_port(size_t width) { - reserved_.set_width(width); - return; -} - -void ConfPorts::set_regular_port(size_t width) { - regular_.set_width(width); - return; -} - -void ConfPorts::set_regular_port(size_t lsb, size_t msb) { - regular_.set_width(lsb, msb); - return; -} - -void ConfPorts::set_regular_port_lsb(size_t lsb) { - regular_.set_lsb(lsb); - return; -} - -void ConfPorts::set_regular_port_msb(size_t msb) { - regular_.set_msb(msb); - return; -} - -/* Increase the port width of reserved port */ -void ConfPorts::expand_reserved_port(size_t width) { - reserved_.expand(width); - return; -} - -/* Increase the port width of regular port */ -void ConfPorts::expand_regular_port(size_t width) { - regular_.expand(width); - return; -} - -/* Increase the port width of both ports */ -void ConfPorts::expand(size_t width) { - expand_reserved_port(width); - expand_regular_port(width); -} - -/* rotate */ -bool ConfPorts::rotate_regular_port(size_t offset) { - return regular_.rotate(offset); -} - -/* counter rotate */ -bool ConfPorts::counter_rotate_regular_port(size_t offset) { - return regular_.counter_rotate(offset); -} - -/* Reset to initial port */ -void ConfPorts::reset() { - reserved_.reset(); - regular_.reset(); - return; -} diff --git a/vpr/src/tileable_rr_graph/openfpga_port.h b/vpr/src/tileable_rr_graph/openfpga_port.h deleted file mode 100644 index 5d9a8ef910c..00000000000 --- a/vpr/src/tileable_rr_graph/openfpga_port.h +++ /dev/null @@ -1,95 +0,0 @@ -#ifndef OPENFPGA_PORT_H -#define OPENFPGA_PORT_H - -/******************************************************************** - * Include header files that are required by data structure declaration - *******************************************************************/ -#include -#include - -/* A basic port */ -class BasicPort { - public: /* Constructors */ - BasicPort(); - BasicPort(const char* name, const size_t& lsb, const size_t& msb); - BasicPort(const char* name, const size_t& width); - BasicPort(const std::string& name, const size_t& lsb, const size_t& msb); - BasicPort(const std::string& name, const size_t& width); - - public: /* Overloaded operators */ - bool operator==(const BasicPort& portA) const; - bool operator<(const BasicPort& portA) const; - - public: /* Accessors */ - size_t get_width() const; /* get the port width */ - size_t get_msb() const; /* get the LSB */ - size_t get_lsb() const; /* get the LSB */ - std::string get_name() const; /* get the name */ - bool is_valid() const; /* check if port size is valid > 0 */ - std::vector pins() const; /* Make a range of the pin indices */ - bool mergeable(const BasicPort& portA) const; /* Check if a port can be merged with this port */ - bool contained(const BasicPort& portA) const; /* Check if a port is contained by this port */ - size_t get_origin_port_width() const; - - public: /* Mutators */ - void set(const BasicPort& basic_port); /* copy */ - void set_name(const std::string& name); /* set the port LSB and MSB */ - void set_width(const size_t& width); /* set the port LSB and MSB */ - void set_width(const size_t& lsb, const size_t& msb); /* set the port LSB and MSB */ - void set_lsb(const size_t& lsb); - void set_msb(const size_t& msb); - void expand(const size_t& width); /* Increase the port width */ - void revert(); /* Swap lsb and msb */ - bool rotate(const size_t& offset); /* rotate */ - bool counter_rotate(const size_t& offset); /* counter rotate */ - void reset(); /* Reset to initial port */ - void combine(const BasicPort& port); /* Combine two ports */ - void merge(const BasicPort& portA); - void set_origin_port_width(const size_t& origin_port_width); - - private: /* internal functions */ - void make_invalid(); /* Make a port invalid */ - private: /* Internal Data */ - std::string name_; /* Name of this port */ - size_t msb_; /* Most Significant Bit of this port */ - size_t lsb_; /* Least Significant Bit of this port */ - size_t origin_port_width_; /* Original port width of a port, used by traceback port conversion history */ -}; - -/* Configuration ports: - * 1. reserved configuration port, which is used by RRAM FPGA architecture - * 2. regular configuration port, which is used by any FPGA architecture - */ -class ConfPorts { - public: /* Constructors */ - ConfPorts(); /* default port */ - ConfPorts(const ConfPorts& conf_ports); /* copy */ - public: /* Accessors */ - size_t get_reserved_port_width() const; - size_t get_reserved_port_lsb() const; - size_t get_reserved_port_msb() const; - size_t get_regular_port_width() const; - size_t get_regular_port_lsb() const; - size_t get_regular_port_msb() const; - - public: /* Mutators */ - void set(const ConfPorts& conf_ports); - void set_reserved_port(size_t width); - void set_regular_port(size_t width); - void set_regular_port(size_t lsb, size_t msb); - void set_regular_port_lsb(size_t lsb); - void set_regular_port_msb(size_t msb); - void expand_reserved_port(size_t width); /* Increase the port width of reserved port */ - void expand_regular_port(size_t width); /* Increase the port width of regular port */ - void expand(size_t width); /* Increase the port width of both ports */ - bool rotate_regular_port(size_t offset); /* rotate */ - bool counter_rotate_regular_port(size_t offset); /* counter rotate */ - void reset(); /* Reset to initial port */ - private: /* Internal Data */ - BasicPort reserved_; - BasicPort regular_; -}; - -/* TODO: create a class for BL and WL ports */ - -#endif diff --git a/vpr/src/tileable_rr_graph/rr_chan.h b/vpr/src/tileable_rr_graph/rr_chan.h index 11c40595bd3..2e40e06c3d2 100644 --- a/vpr/src/tileable_rr_graph/rr_chan.h +++ b/vpr/src/tileable_rr_graph/rr_chan.h @@ -9,12 +9,7 @@ /* Headers from vtrutil library */ #include "vtr_geometry.h" -/* Headers from openfpgautil library */ -#include "openfpga_port.h" - /* Headers from vpr library */ -#include "rr_graph_obj.h" - #include "rr_graph_view.h" /******************************************************************** From 885eb58feef2d0fb6789cff017803e032bc3ee82 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 17 Aug 2022 14:36:36 -0700 Subject: [PATCH 043/147] [vpr] add a useful API to get node side --- .../openfpga_rr_graph_utils.cpp | 16 ++++++++++++++++ .../tileable_rr_graph/openfpga_rr_graph_utils.h | 3 +++ 2 files changed, 19 insertions(+) diff --git a/vpr/src/tileable_rr_graph/openfpga_rr_graph_utils.cpp b/vpr/src/tileable_rr_graph/openfpga_rr_graph_utils.cpp index 0855c082691..da17b51b2fc 100644 --- a/vpr/src/tileable_rr_graph/openfpga_rr_graph_utils.cpp +++ b/vpr/src/tileable_rr_graph/openfpga_rr_graph_utils.cpp @@ -183,3 +183,19 @@ bool is_ipin_direct_connected_opin(const RRGraphView& rr_graph, return true; } + +/** @brief Get a side of a given node in a routing resource graph. + * Note that this function expect one valid side to be got. Otherwise, it will fail! */ +e_side get_rr_graph_single_node_side(const RRGraphView& rr_graph, + const RRNodeId& node) { + e_side node_side = NUM_SIDES; + int num_sides = 0; + for (e_side candidate_side : SIDES) { + if (rr_graph.is_node_on_specific_side(node, candidate_side)) { + node_side = candidate_side; + num_sides++; + } + } + VTR_ASSERT(1 == num_sides && node_side != NUM_SIDES); + return node_side; +} diff --git a/vpr/src/tileable_rr_graph/openfpga_rr_graph_utils.h b/vpr/src/tileable_rr_graph/openfpga_rr_graph_utils.h index f3d3f65abe8..cba64125615 100644 --- a/vpr/src/tileable_rr_graph/openfpga_rr_graph_utils.h +++ b/vpr/src/tileable_rr_graph/openfpga_rr_graph_utils.h @@ -39,4 +39,7 @@ bool is_opin_direct_connected_ipin(const RRGraphView& rr_graph, bool is_ipin_direct_connected_opin(const RRGraphView& rr_graph, const RRNodeId& node); +e_side get_rr_graph_single_node_side(const RRGraphView& rr_graph, + const RRNodeId& node); + #endif From e1d6d03cf5954e31f34049ddace7689630993a36 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 17 Aug 2022 16:20:31 -0700 Subject: [PATCH 044/147] [vpr] give access to utility function due to requirement from OpenFPGA --- vpr/src/util/vpr_utils.cpp | 2 +- vpr/src/util/vpr_utils.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/vpr/src/util/vpr_utils.cpp b/vpr/src/util/vpr_utils.cpp index 0a62faa03b0..cddd622237f 100644 --- a/vpr/src/util/vpr_utils.cpp +++ b/vpr/src/util/vpr_utils.cpp @@ -1143,7 +1143,7 @@ static void load_pb_graph_pin_lookup_from_index_rec(t_pb_graph_pin** pb_graph_pi } /* Create a lookup that returns a pb_graph_pin pointer given the pb_graph_pin index */ -static t_pb_graph_pin** alloc_and_load_pb_graph_pin_lookup_from_index(t_logical_block_type_ptr type) { +t_pb_graph_pin** alloc_and_load_pb_graph_pin_lookup_from_index(t_logical_block_type_ptr type) { t_pb_graph_pin** pb_graph_pin_lookup_from_type = nullptr; t_pb_graph_node* pb_graph_head = type->pb_graph_head; diff --git a/vpr/src/util/vpr_utils.h b/vpr/src/util/vpr_utils.h index 60921ac3645..1599d4f86eb 100644 --- a/vpr/src/util/vpr_utils.h +++ b/vpr/src/util/vpr_utils.h @@ -112,6 +112,7 @@ bool primitive_type_feasible(AtomBlockId blk_id, const t_pb_type* cur_pb_type); t_pb_graph_pin* get_pb_graph_node_pin_from_model_port_pin(const t_model_ports* model_port, const int model_pin, const t_pb_graph_node* pb_graph_node); const t_pb_graph_pin* find_pb_graph_pin(const AtomNetlist& netlist, const AtomLookup& netlist_lookup, const AtomPinId pin_id); t_pb_graph_pin* get_pb_graph_node_pin_from_block_pin(ClusterBlockId iblock, int ipin); +t_pb_graph_pin** alloc_and_load_pb_graph_pin_lookup_from_index(t_logical_block_type_ptr type); vtr::vector alloc_and_load_pin_id_to_pb_mapping(); void free_pin_id_to_pb_mapping(vtr::vector& pin_id_to_pb_mapping); From 674a569688455eccbd620e0612afaf50763c7652 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 17 Aug 2022 16:28:36 -0700 Subject: [PATCH 045/147] [vpr] syntax --- vpr/src/util/vpr_utils.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/vpr/src/util/vpr_utils.cpp b/vpr/src/util/vpr_utils.cpp index cddd622237f..3365cacaa61 100644 --- a/vpr/src/util/vpr_utils.cpp +++ b/vpr/src/util/vpr_utils.cpp @@ -73,7 +73,6 @@ static AtomPinId find_atom_pin_for_pb_route_id(ClusterBlockId clb, int pb_route_ static bool block_type_contains_blif_model(t_logical_block_type_ptr type, const std::regex& blif_model_regex); static bool pb_type_contains_blif_model(const t_pb_type* pb_type, const std::regex& blif_model_regex); -static t_pb_graph_pin** alloc_and_load_pb_graph_pin_lookup_from_index(t_logical_block_type_ptr type); static void free_pb_graph_pin_lookup_from_index(t_pb_graph_pin** pb_graph_pin_lookup_from_type); /******************** Subroutine definitions *********************************/ From 090322cd55f02e6f2d359e58afd91c3e486bfba9 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 17 Aug 2022 16:32:02 -0700 Subject: [PATCH 046/147] [vpr] release more API from vpr_utils --- vpr/src/util/vpr_utils.cpp | 3 +-- vpr/src/util/vpr_utils.h | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/vpr/src/util/vpr_utils.cpp b/vpr/src/util/vpr_utils.cpp index 3365cacaa61..104fa703c3f 100644 --- a/vpr/src/util/vpr_utils.cpp +++ b/vpr/src/util/vpr_utils.cpp @@ -73,7 +73,6 @@ static AtomPinId find_atom_pin_for_pb_route_id(ClusterBlockId clb, int pb_route_ static bool block_type_contains_blif_model(t_logical_block_type_ptr type, const std::regex& blif_model_regex); static bool pb_type_contains_blif_model(const t_pb_type* pb_type, const std::regex& blif_model_regex); -static void free_pb_graph_pin_lookup_from_index(t_pb_graph_pin** pb_graph_pin_lookup_from_type); /******************** Subroutine definitions *********************************/ @@ -1170,7 +1169,7 @@ t_pb_graph_pin** alloc_and_load_pb_graph_pin_lookup_from_index(t_logical_block_t } /* Free pb_graph_pin lookup array */ -static void free_pb_graph_pin_lookup_from_index(t_pb_graph_pin** pb_graph_pin_lookup_from_type) { +void free_pb_graph_pin_lookup_from_index(t_pb_graph_pin** pb_graph_pin_lookup_from_type) { if (pb_graph_pin_lookup_from_type == nullptr) { return; } diff --git a/vpr/src/util/vpr_utils.h b/vpr/src/util/vpr_utils.h index 1599d4f86eb..a5fe377cadb 100644 --- a/vpr/src/util/vpr_utils.h +++ b/vpr/src/util/vpr_utils.h @@ -114,6 +114,7 @@ const t_pb_graph_pin* find_pb_graph_pin(const AtomNetlist& netlist, const AtomLo t_pb_graph_pin* get_pb_graph_node_pin_from_block_pin(ClusterBlockId iblock, int ipin); t_pb_graph_pin** alloc_and_load_pb_graph_pin_lookup_from_index(t_logical_block_type_ptr type); vtr::vector alloc_and_load_pin_id_to_pb_mapping(); +void free_pb_graph_pin_lookup_from_index(t_pb_graph_pin** pb_graph_pin_lookup_from_type); void free_pin_id_to_pb_mapping(vtr::vector& pin_id_to_pb_mapping); float compute_primitive_base_cost(const t_pb_graph_node* primitive); From a18c4199afb5a4350c171d3e8be7116330d2a67b Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 17 Aug 2022 16:35:38 -0700 Subject: [PATCH 047/147] [lib] add constant string for logic value, useful for debugging messages --- libs/libvtrutil/src/vtr_logic.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libs/libvtrutil/src/vtr_logic.h b/libs/libvtrutil/src/vtr_logic.h index 30d44c4a6b9..e1ae4ce463d 100644 --- a/libs/libvtrutil/src/vtr_logic.h +++ b/libs/libvtrutil/src/vtr_logic.h @@ -25,9 +25,12 @@ enum class LogicValue { FALSE = 0, TRUE = 1, DONT_CARE = 2, - UNKOWN = 3 + UNKOWN = 3, + NUM_LOGIC_VALUE_TYPES }; +constexpr std::array LOGIC_VALUE_STRING = {{"false", "true", "don't care", "unknown"}}; + } // namespace vtr #endif From 6c781e84795ca263d4660401f5fc125add359ef9 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 17 Aug 2022 18:04:51 -0700 Subject: [PATCH 048/147] [vpr] add missing include --- libs/libvtrutil/src/vtr_logic.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libs/libvtrutil/src/vtr_logic.h b/libs/libvtrutil/src/vtr_logic.h index e1ae4ce463d..b43ee49291e 100644 --- a/libs/libvtrutil/src/vtr_logic.h +++ b/libs/libvtrutil/src/vtr_logic.h @@ -16,6 +16,8 @@ constexpr int FALSE = 0; constexpr int TRUE = 1; +#include + namespace vtr { /** From d0a65ad6b86ae312d8a34fa3954656de3a4f1252 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 23 Aug 2022 14:12:32 -0700 Subject: [PATCH 049/147] [vpr] correct the use of header files --- vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp index 3df202df572..b1bef8021d3 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp @@ -17,7 +17,7 @@ #include "rr_graph.h" #include "check_rr_graph.h" -#include "check_rr_graph_obj.h" +#include "get_parallel_segs.h" #include "rr_graph_builder_utils.h" #include "tileable_chan_details_builder.h" From c854a5eaedcba45c0e778325d583855c29e63a2b Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 23 Aug 2022 15:27:48 -0700 Subject: [PATCH 050/147] [lib] fixed a bug on sharing the storage for incoming edges --- libs/librrgraph/src/base/rr_graph_builder.cpp | 2 +- libs/librrgraph/src/base/rr_graph_builder.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/librrgraph/src/base/rr_graph_builder.cpp b/libs/librrgraph/src/base/rr_graph_builder.cpp index caff0554418..63939f5fc16 100644 --- a/libs/librrgraph/src/base/rr_graph_builder.cpp +++ b/libs/librrgraph/src/base/rr_graph_builder.cpp @@ -28,7 +28,7 @@ MetadataStorage>& RRGraphBuilder::rr_edge_metadata() return rr_edge_metadata_; } -vtr::vector> RRGraphBuilder::node_in_edge_storage() { +vtr::vector>& RRGraphBuilder::node_in_edge_storage() { return node_in_edges_; } diff --git a/libs/librrgraph/src/base/rr_graph_builder.h b/libs/librrgraph/src/base/rr_graph_builder.h index bba33b21cf4..9f015f9c91b 100644 --- a/libs/librrgraph/src/base/rr_graph_builder.h +++ b/libs/librrgraph/src/base/rr_graph_builder.h @@ -46,7 +46,7 @@ class RRGraphBuilder { /** @brief Return a writable object for the meta data on the edge */ MetadataStorage>& rr_edge_metadata(); /** @brief Return a writable object fo the incoming edge storage */ - vtr::vector> node_in_edge_storage(); + vtr::vector>& node_in_edge_storage(); /** @brief Return the size for rr_node_metadata */ inline size_t rr_node_metadata_size() const { From e78f446095456ddad4f70a0b67a912f98931e5ba Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 23 Aug 2022 16:06:33 -0700 Subject: [PATCH 051/147] [vpr] fixed a bug in showing debugging messages --- vpr/src/tileable_rr_graph/rr_gsb.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/vpr/src/tileable_rr_graph/rr_gsb.cpp b/vpr/src/tileable_rr_graph/rr_gsb.cpp index 4aa7b8e4352..803958db2c1 100644 --- a/vpr/src/tileable_rr_graph/rr_gsb.cpp +++ b/vpr/src/tileable_rr_graph/rr_gsb.cpp @@ -825,12 +825,10 @@ void RRGSB::sort_chan_node_in_edges(const RRGraphView& rr_graph, if (NUM_SIDES == side) { VTR_LOG("GSB[%lu][%lu]:\n", get_x(), get_y()); VTR_LOG("SRC node:\n"); - VTR_LOG("Node type: %s\n", rr_graph.node_type_string(src_node)); - VTR_LOG("Node coordinate: %d\n", rr_graph.node_coordinate_to_string(src_node).c_str()); + VTR_LOG("Node info: %s\n", rr_graph.node_coordinate_to_string(src_node).c_str()); VTR_LOG("Node ptc: %d\n", rr_graph.node_ptc_num(src_node)); VTR_LOG("Channel node:\n"); - VTR_LOG("Node type: %s\n", rr_graph.node_type_string(chan_node)); - VTR_LOG("Node coordinate: %d\n", rr_graph.node_coordinate_to_string(chan_node).c_str()); + VTR_LOG("Node info: %s\n", rr_graph.node_coordinate_to_string(chan_node).c_str()); VTR_LOG("Node ptc: %d\n", rr_graph.node_ptc_num(chan_node)); } From 43a80a46bd3c9dc2702c0e225e30663d2fad3401 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 23 Aug 2022 16:15:34 -0700 Subject: [PATCH 052/147] [vpr] fixed a bug on range --- libs/librrgraph/src/base/rr_graph_builder.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/librrgraph/src/base/rr_graph_builder.cpp b/libs/librrgraph/src/base/rr_graph_builder.cpp index 63939f5fc16..f09b54baff0 100644 --- a/libs/librrgraph/src/base/rr_graph_builder.cpp +++ b/libs/librrgraph/src/base/rr_graph_builder.cpp @@ -192,7 +192,7 @@ void RRGraphBuilder::build_in_edges() { node_in_edges_.resize(node_storage_.size()); for (const RRNodeId& src_node: vtr::StrongIdRange(RRNodeId(0), RRNodeId(node_storage_.size()))) { - for (size_t iedge = size_t(node_storage_.first_edge(src_node)); iedge < size_t(node_storage_.last_edge(src_node)); iedge++) { + for (size_t iedge = size_t(node_storage_.first_edge(src_node)); iedge <= size_t(node_storage_.last_edge(src_node)); iedge++) { RRNodeId des_node = node_storage_.edge_sink_node(RREdgeId(iedge)); node_in_edges_[des_node].push_back(RREdgeId(iedge)); } From 4c2b47e484110f6b4f5cc6f602e0d6f9c220fb2d Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 23 Aug 2022 18:37:49 -0700 Subject: [PATCH 053/147] [lib] clean up header files --- libs/librrgraph/src/base/rr_graph_fwd.h | 6 ++---- libs/librrgraph/src/base/rr_graph_utils.h | 4 ++-- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/libs/librrgraph/src/base/rr_graph_fwd.h b/libs/librrgraph/src/base/rr_graph_fwd.h index fee69b34cd2..15199830642 100644 --- a/libs/librrgraph/src/base/rr_graph_fwd.h +++ b/libs/librrgraph/src/base/rr_graph_fwd.h @@ -1,5 +1,5 @@ -#ifndef RR_GRAPH_OBJ_FWD_H -#define RR_GRAPH_OBJ_FWD_H +#ifndef RR_GRAPH_FWD_H +#define RR_GRAPH_FWD_H #include "vtr_strong_id.h" /*************************************************************** @@ -11,8 +11,6 @@ //Forward declaration class t_rr_graph_storage; -class RRGraph; - struct rr_node_id_tag; struct rr_edge_id_tag; struct rr_indexed_data_id_tag; diff --git a/libs/librrgraph/src/base/rr_graph_utils.h b/libs/librrgraph/src/base/rr_graph_utils.h index d3ef4440daa..cf773fb3e3f 100644 --- a/libs/librrgraph/src/base/rr_graph_utils.h +++ b/libs/librrgraph/src/base/rr_graph_utils.h @@ -5,8 +5,8 @@ * the function declaration */ #include -#include "rr_graph_fwd.h" #include "rr_node_types.h" +#include "rr_graph_obj.h" #include "rr_graph_view.h" /* Get node-to-node switches in a RRGraph */ @@ -21,4 +21,4 @@ vtr::vector> get_fan_in_list(const RRGraphView& int seg_index_of_cblock(const RRGraphView& rr_graph, t_rr_type from_rr_type, int to_node); int seg_index_of_sblock(const RRGraphView& rr_graph, int from_node, int to_node); -#endif \ No newline at end of file +#endif From a88ac6e01bc2ef2793c56f10e5fcd5f340277a78 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 23 Aug 2022 22:10:00 -0700 Subject: [PATCH 054/147] [vpr] print more debugging info when rr_gsb encounts fatal errors --- vpr/src/tileable_rr_graph/rr_gsb.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/vpr/src/tileable_rr_graph/rr_gsb.cpp b/vpr/src/tileable_rr_graph/rr_gsb.cpp index 803958db2c1..22df200ff4c 100644 --- a/vpr/src/tileable_rr_graph/rr_gsb.cpp +++ b/vpr/src/tileable_rr_graph/rr_gsb.cpp @@ -827,9 +827,17 @@ void RRGSB::sort_chan_node_in_edges(const RRGraphView& rr_graph, VTR_LOG("SRC node:\n"); VTR_LOG("Node info: %s\n", rr_graph.node_coordinate_to_string(src_node).c_str()); VTR_LOG("Node ptc: %d\n", rr_graph.node_ptc_num(src_node)); + VTR_LOG("Fan-out nodes:\n"); + for (const auto& edge : rr_graph.edge_range(src_node)) { + VTR_LOG("%s\n", rr_graph.node_coordinate_to_string(rr_graph.edge_sink_node(edge))); + } VTR_LOG("Channel node:\n"); VTR_LOG("Node info: %s\n", rr_graph.node_coordinate_to_string(chan_node).c_str()); VTR_LOG("Node ptc: %d\n", rr_graph.node_ptc_num(chan_node)); + VTR_LOG("Fan-in nodes:\n"); + for (const auto& edge : rr_graph.node_in_edges(chan_node)) { + VTR_LOG("%s\n", rr_graph.node_coordinate_to_string(rr_graph.edge_src_node(edge))); + } } VTR_ASSERT(NUM_SIDES != side); From 0d1339e3cb3ddeb45d17a900add7f388382a3753 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 23 Aug 2022 22:24:46 -0700 Subject: [PATCH 055/147] [vpr] format debugging messages --- vpr/src/tileable_rr_graph/rr_gsb.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/vpr/src/tileable_rr_graph/rr_gsb.cpp b/vpr/src/tileable_rr_graph/rr_gsb.cpp index 22df200ff4c..525b3ca5576 100644 --- a/vpr/src/tileable_rr_graph/rr_gsb.cpp +++ b/vpr/src/tileable_rr_graph/rr_gsb.cpp @@ -824,19 +824,21 @@ void RRGSB::sort_chan_node_in_edges(const RRGraphView& rr_graph, /* Must have valid side and index */ if (NUM_SIDES == side) { VTR_LOG("GSB[%lu][%lu]:\n", get_x(), get_y()); + VTR_LOG("----------------------------------\n"); VTR_LOG("SRC node:\n"); VTR_LOG("Node info: %s\n", rr_graph.node_coordinate_to_string(src_node).c_str()); VTR_LOG("Node ptc: %d\n", rr_graph.node_ptc_num(src_node)); VTR_LOG("Fan-out nodes:\n"); - for (const auto& edge : rr_graph.edge_range(src_node)) { - VTR_LOG("%s\n", rr_graph.node_coordinate_to_string(rr_graph.edge_sink_node(edge))); + for (const auto& temp_edge : rr_graph.edge_range(src_node)) { + VTR_LOG("\t%s\n", rr_graph.node_coordinate_to_string(rr_graph.edge_sink_node(temp_edge)).c_str()); } + VTR_LOG("\n----------------------------------\n"); VTR_LOG("Channel node:\n"); VTR_LOG("Node info: %s\n", rr_graph.node_coordinate_to_string(chan_node).c_str()); VTR_LOG("Node ptc: %d\n", rr_graph.node_ptc_num(chan_node)); VTR_LOG("Fan-in nodes:\n"); - for (const auto& edge : rr_graph.node_in_edges(chan_node)) { - VTR_LOG("%s\n", rr_graph.node_coordinate_to_string(rr_graph.edge_src_node(edge))); + for (const auto& temp_edge : rr_graph.node_in_edges(chan_node)) { + VTR_LOG("\t%s\n", rr_graph.node_coordinate_to_string(rr_graph.edge_src_node(temp_edge)).c_str()); } } From c16fcb8fba16b45484e5c41db506533ee706e986 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 23 Aug 2022 23:12:45 -0700 Subject: [PATCH 056/147] [lib] fixed a bug on clear() for rrgraph builder --- libs/librrgraph/src/base/rr_graph_builder.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/libs/librrgraph/src/base/rr_graph_builder.cpp b/libs/librrgraph/src/base/rr_graph_builder.cpp index f09b54baff0..3da9c11c931 100644 --- a/libs/librrgraph/src/base/rr_graph_builder.cpp +++ b/libs/librrgraph/src/base/rr_graph_builder.cpp @@ -1,3 +1,4 @@ +#include "vtr_assert.h" #include "vtr_log.h" #include "rr_graph_builder.h" #include "vtr_time.h" @@ -93,6 +94,7 @@ RRNodeId RRGraphBuilder::create_node(int x, int y, t_rr_type type, int ptc, e_si void RRGraphBuilder::clear() { node_lookup_.clear(); node_storage_.clear(); + node_in_edges_.clear(); rr_node_metadata_.clear(); rr_edge_metadata_.clear(); rr_segments_.clear(); @@ -191,10 +193,11 @@ void RRGraphBuilder::build_in_edges() { node_in_edges_.clear(); node_in_edges_.resize(node_storage_.size()); - for (const RRNodeId& src_node: vtr::StrongIdRange(RRNodeId(0), RRNodeId(node_storage_.size()))) { - for (size_t iedge = size_t(node_storage_.first_edge(src_node)); iedge <= size_t(node_storage_.last_edge(src_node)); iedge++) { - RRNodeId des_node = node_storage_.edge_sink_node(RREdgeId(iedge)); - node_in_edges_[des_node].push_back(RREdgeId(iedge)); + for (RRNodeId src_node : vtr::StrongIdRange(RRNodeId(0), RRNodeId(node_storage_.size()))) { + for (auto iedge : node_storage_.edges(src_node)) { + VTR_ASSERT(src_node == node_storage_.edge_source_node(node_storage_.edge_id(src_node, iedge))); + RRNodeId des_node = node_storage_.edge_sink_node(node_storage_.edge_id(src_node, iedge)); + node_in_edges_[des_node].push_back(node_storage_.edge_id(src_node, iedge)); } } is_incoming_edge_dirty_ = false; @@ -203,7 +206,7 @@ void RRGraphBuilder::build_in_edges() { std::vector RRGraphBuilder::node_in_edges(RRNodeId node) const { VTR_ASSERT(size_t(node) < node_storage_.size()); if (is_incoming_edge_dirty_) { - VTR_LOG_ERROR("Incoming edges are built yet in routing resource graph. Please call build_in_edges()."); + VTR_LOG_ERROR("Incoming edges are not built yet in routing resource graph. Please call build_in_edges()."); return std::vector(); } if (node_in_edges_.empty()) { From 3ca5e2f221c78742d0893209e07c6d084c0ef730 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 24 Aug 2022 12:20:45 -0700 Subject: [PATCH 057/147] [lib] add validate APIs for checking incoming edges --- libs/librrgraph/src/base/rr_graph_view.cpp | 52 ++++++++++++++++++++++ libs/librrgraph/src/base/rr_graph_view.h | 5 +++ 2 files changed, 57 insertions(+) diff --git a/libs/librrgraph/src/base/rr_graph_view.cpp b/libs/librrgraph/src/base/rr_graph_view.cpp index 968ca940f47..22b1a1e1ba1 100644 --- a/libs/librrgraph/src/base/rr_graph_view.cpp +++ b/libs/librrgraph/src/base/rr_graph_view.cpp @@ -1,3 +1,4 @@ +#include #include "rr_graph_view.h" #include "rr_node.h" #include "physical_types.h" @@ -74,3 +75,54 @@ RRSegmentId RRGraphView::node_segment(RRNodeId node) const { RRIndexedDataId cost_index = node_cost_index(node); return RRSegmentId(rr_indexed_data_[cost_index].seg_index); } + +size_t RRGraphView::in_edges_count() const { + size_t edge_count = 0; + for (auto edge_list : node_in_edges_) { + edge_count += edge_list.size(); + } + return edge_count; +} + +bool RRGraphView::validate_in_edges() const { + size_t num_err = 0; + /* For each edge, validate that + * - The source node is in the fan-in edge list of the destination node + * - The sink node is in the fan-out edge list of the source node + */ + for (RRNodeId curr_node : vtr::StrongIdRange(RRNodeId(0), RRNodeId(node_storage_.size()))) { + for (auto iedge : node_storage_.edges(curr_node)) { + RRNodeId des_node = node_storage_.edge_sink_node(node_storage_.edge_id(curr_node, iedge)); + std::vector des_fanin_nodes; + for (auto next_edge : node_in_edges(des_node)) { + RRNodeId prev_edge_des_node = node_storage_.edge_source_node(next_edge); + des_fanin_nodes.push_back(prev_edge_des_node); + } + if (des_fanin_nodes.end() == std::find(des_fanin_nodes.begin(), des_fanin_nodes.end(), des_node)) { + VTR_LOG_ERROR("Node '%s' does not appear in the fannout edges of Node '%s'\n", + node_coordinate_to_string(des_node).c_str(), node_coordinate_to_string(curr_node).c_str()); + num_err++; + } + } + for (auto iedge : node_in_edges(curr_node)) { + RRNodeId src_node = node_storage_.edge_source_node(iedge); + std::vector src_fanout_nodes; + for (auto prev_edge : node_storage_.edges(src_node)) { + RRNodeId prev_edge_des_node = node_storage_.edge_sink_node(node_storage_.edge_id(src_node, prev_edge)); + src_fanout_nodes.push_back(prev_edge_des_node); + } + if (src_fanout_nodes.end() == std::find(src_fanout_nodes.begin(), src_fanout_nodes.end(), curr_node)) { + VTR_LOG_ERROR("Node '%s' does not appear in the fan-in edges of Node '%s'\n", + node_coordinate_to_string(src_node).c_str(), node_coordinate_to_string(curr_node).c_str()); + num_err++; + } + } + } + if (num_err) { + VTR_LOG_ERROR("Found %ld errors when validating incoming edges for routing resource graph\n", num_err); + return false; + } + return true; +} + + diff --git a/libs/librrgraph/src/base/rr_graph_view.h b/libs/librrgraph/src/base/rr_graph_view.h index 162161569a6..e52654c03e6 100644 --- a/libs/librrgraph/src/base/rr_graph_view.h +++ b/libs/librrgraph/src/base/rr_graph_view.h @@ -520,6 +520,11 @@ class RRGraphView { return (size_t(switch_id) < rr_switch_inf_.size()); } + /** @brief Validate if all the fan-in edge lists are valid */ + bool validate_in_edges() const; + /** @brief Count the number of incoming edges for all the nodes */ + size_t in_edges_count() const; + /* -- Internal data storage -- */ /* Note: only read-only object or data structures are allowed!!! */ private: From ad0d96c8b558de9578a190235ce6e07d064de057 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 24 Aug 2022 12:28:15 -0700 Subject: [PATCH 058/147] [lib] add code comments --- libs/librrgraph/src/base/rr_graph_view.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libs/librrgraph/src/base/rr_graph_view.cpp b/libs/librrgraph/src/base/rr_graph_view.cpp index 22b1a1e1ba1..02e03c42c57 100644 --- a/libs/librrgraph/src/base/rr_graph_view.cpp +++ b/libs/librrgraph/src/base/rr_graph_view.cpp @@ -91,6 +91,9 @@ bool RRGraphView::validate_in_edges() const { * - The sink node is in the fan-out edge list of the source node */ for (RRNodeId curr_node : vtr::StrongIdRange(RRNodeId(0), RRNodeId(node_storage_.size()))) { + /* curr_node ---> des_node + * <-?- check if the incoming edge is correct or not + */ for (auto iedge : node_storage_.edges(curr_node)) { RRNodeId des_node = node_storage_.edge_sink_node(node_storage_.edge_id(curr_node, iedge)); std::vector des_fanin_nodes; @@ -104,6 +107,9 @@ bool RRGraphView::validate_in_edges() const { num_err++; } } + /* src_node -?-> curr_node + * <--- check if the fan-out edge is correct or not + */ for (auto iedge : node_in_edges(curr_node)) { RRNodeId src_node = node_storage_.edge_source_node(iedge); std::vector src_fanout_nodes; From f3b5a30913668447922f07f6b13924ff9b54947f Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 24 Aug 2022 13:33:39 -0700 Subject: [PATCH 059/147] [lib] fixed a bug in validating incoming edges --- libs/librrgraph/src/base/rr_graph_view.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libs/librrgraph/src/base/rr_graph_view.cpp b/libs/librrgraph/src/base/rr_graph_view.cpp index 02e03c42c57..edddaed097d 100644 --- a/libs/librrgraph/src/base/rr_graph_view.cpp +++ b/libs/librrgraph/src/base/rr_graph_view.cpp @@ -101,9 +101,9 @@ bool RRGraphView::validate_in_edges() const { RRNodeId prev_edge_des_node = node_storage_.edge_source_node(next_edge); des_fanin_nodes.push_back(prev_edge_des_node); } - if (des_fanin_nodes.end() == std::find(des_fanin_nodes.begin(), des_fanin_nodes.end(), des_node)) { - VTR_LOG_ERROR("Node '%s' does not appear in the fannout edges of Node '%s'\n", - node_coordinate_to_string(des_node).c_str(), node_coordinate_to_string(curr_node).c_str()); + if (des_fanin_nodes.end() == std::find(des_fanin_nodes.begin(), des_fanin_nodes.end(), curr_node)) { + VTR_LOG_ERROR("Node '%s' does not appear in the fan-in edges of Node '%s', while does drive it in its fan-out list\n", + node_coordinate_to_string(curr_node).c_str(), node_coordinate_to_string(des_node).c_str()); num_err++; } } @@ -118,8 +118,8 @@ bool RRGraphView::validate_in_edges() const { src_fanout_nodes.push_back(prev_edge_des_node); } if (src_fanout_nodes.end() == std::find(src_fanout_nodes.begin(), src_fanout_nodes.end(), curr_node)) { - VTR_LOG_ERROR("Node '%s' does not appear in the fan-in edges of Node '%s'\n", - node_coordinate_to_string(src_node).c_str(), node_coordinate_to_string(curr_node).c_str()); + VTR_LOG_ERROR("Node '%s' does not appear in the fan-out edges of Node '%s', while does exist in its fan-in list\n", + node_coordinate_to_string(curr_node).c_str(), node_coordinate_to_string(src_node).c_str()); num_err++; } } From f77645a5164f405807a130116c743a65ac30260a Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 26 Aug 2022 10:30:24 -0700 Subject: [PATCH 060/147] [vpr] now update node-lookup for CHANX and CHANY nodes --- .../tileable_rr_graph_node_builder.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp index 6dd205d0f18..1d12d4c7705 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp @@ -739,6 +739,16 @@ static void load_one_chan_rr_nodes_basic_info(const RRGraphView& rr_graph, rr_graph.node_ylow(rr_node_id), chan_coordinate.x(), chan_coordinate.y()); + /* Update node look-up */ + size_t xlow = std::min(rr_graph.node_xlow(rr_node_id), rr_graph.node_xhigh(rr_node_id)); + size_t xhigh = std::max(rr_graph.node_xlow(rr_node_id), rr_graph.node_xhigh(rr_node_id)); + size_t ylow = std::min(rr_graph.node_ylow(rr_node_id), rr_graph.node_yhigh(rr_node_id)); + size_t yhigh = std::max(rr_graph.node_ylow(rr_node_id), rr_graph.node_yhigh(rr_node_id)); + for (int ix = xlow; ix <= xhigh; ix++) { + for (int iy = ylow; iy <= yhigh; iy++) { + rr_graph_builder.node_lookup().add_node(rr_node_id, ix, iy, rr_graph.node_type(rr_node_id), itrack); + } + } /* Do not update track_ids for length-1 wires, they should have only 1 track_id */ if ((rr_graph.node_xhigh(rr_node_id) > rr_graph.node_xlow(rr_node_id)) From bd49f85218718c9ee87c95bd015df8c6d7a9e9a2 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 26 Aug 2022 10:43:25 -0700 Subject: [PATCH 061/147] [vpr] debugging CHANX and CHANY coord --- .../tileable_rr_graph/tileable_rr_graph_node_builder.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp index 1d12d4c7705..5b44a91919d 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp @@ -744,9 +744,9 @@ static void load_one_chan_rr_nodes_basic_info(const RRGraphView& rr_graph, size_t xhigh = std::max(rr_graph.node_xlow(rr_node_id), rr_graph.node_xhigh(rr_node_id)); size_t ylow = std::min(rr_graph.node_ylow(rr_node_id), rr_graph.node_yhigh(rr_node_id)); size_t yhigh = std::max(rr_graph.node_ylow(rr_node_id), rr_graph.node_yhigh(rr_node_id)); - for (int ix = xlow; ix <= xhigh; ix++) { - for (int iy = ylow; iy <= yhigh; iy++) { - rr_graph_builder.node_lookup().add_node(rr_node_id, ix, iy, rr_graph.node_type(rr_node_id), itrack); + for (size_t ix = xlow; ix <= xhigh; ix++) { + for (size_t iy = ylow; iy <= yhigh; iy++) { + rr_graph_builder.node_lookup().add_node(rr_node_id, ix, iy, rr_graph.node_type(rr_node_id), rr_graph.node_track_num(rr_node_id)); } } From 4155c0b178f6aa73d9aa1e5c14fd7a1dd1fde324 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 26 Aug 2022 10:56:18 -0700 Subject: [PATCH 062/147] [vpr] remove existing node in look-up when updating coordinates --- .../tileable_rr_graph_node_builder.cpp | 28 ++++++++++++++----- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp index 5b44a91919d..db69cd9f9eb 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp @@ -734,19 +734,33 @@ static void load_one_chan_rr_nodes_basic_info(const RRGraphView& rr_graph, VTR_ASSERT(chan_type == rr_graph.node_type(rr_node_id)); VTR_ASSERT(chan_details.get_track_direction(itrack) == rr_graph.node_direction(rr_node_id)); + /* Unset existing node coordinate in the lookup */ + { + size_t xlow = std::min(rr_graph.node_xlow(rr_node_id), rr_graph.node_xhigh(rr_node_id)); + size_t xhigh = std::max(rr_graph.node_xlow(rr_node_id), rr_graph.node_xhigh(rr_node_id)); + size_t ylow = std::min(rr_graph.node_ylow(rr_node_id), rr_graph.node_yhigh(rr_node_id)); + size_t yhigh = std::max(rr_graph.node_ylow(rr_node_id), rr_graph.node_yhigh(rr_node_id)); + for (size_t ix = xlow; ix <= xhigh; ix++) { + for (size_t iy = ylow; iy <= yhigh; iy++) { + rr_graph_builder.node_lookup().add_node(RRNodeId::INVALID(), ix, iy, rr_graph.node_type(rr_node_id), rr_graph.node_track_num(rr_node_id)); + } + } + } /* set xhigh/yhigh and push changes to track_ids */ rr_graph_builder.set_node_coordinates(rr_node_id, rr_graph.node_xlow(rr_node_id), rr_graph.node_ylow(rr_node_id), chan_coordinate.x(), chan_coordinate.y()); /* Update node look-up */ - size_t xlow = std::min(rr_graph.node_xlow(rr_node_id), rr_graph.node_xhigh(rr_node_id)); - size_t xhigh = std::max(rr_graph.node_xlow(rr_node_id), rr_graph.node_xhigh(rr_node_id)); - size_t ylow = std::min(rr_graph.node_ylow(rr_node_id), rr_graph.node_yhigh(rr_node_id)); - size_t yhigh = std::max(rr_graph.node_ylow(rr_node_id), rr_graph.node_yhigh(rr_node_id)); - for (size_t ix = xlow; ix <= xhigh; ix++) { - for (size_t iy = ylow; iy <= yhigh; iy++) { - rr_graph_builder.node_lookup().add_node(rr_node_id, ix, iy, rr_graph.node_type(rr_node_id), rr_graph.node_track_num(rr_node_id)); + { + size_t xlow = std::min(rr_graph.node_xlow(rr_node_id), rr_graph.node_xhigh(rr_node_id)); + size_t xhigh = std::max(rr_graph.node_xlow(rr_node_id), rr_graph.node_xhigh(rr_node_id)); + size_t ylow = std::min(rr_graph.node_ylow(rr_node_id), rr_graph.node_yhigh(rr_node_id)); + size_t yhigh = std::max(rr_graph.node_ylow(rr_node_id), rr_graph.node_yhigh(rr_node_id)); + for (size_t ix = xlow; ix <= xhigh; ix++) { + for (size_t iy = ylow; iy <= yhigh; iy++) { + rr_graph_builder.node_lookup().add_node(rr_node_id, ix, iy, rr_graph.node_type(rr_node_id), rr_graph.node_track_num(rr_node_id)); + } } } From edd61a38d082895473196afd121dd5326c41aa81 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 26 Aug 2022 13:31:43 -0700 Subject: [PATCH 063/147] [vpr] debugging --- .../tileable_rr_graph_node_builder.cpp | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp index db69cd9f9eb..a7c3109b9d4 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp @@ -734,18 +734,6 @@ static void load_one_chan_rr_nodes_basic_info(const RRGraphView& rr_graph, VTR_ASSERT(chan_type == rr_graph.node_type(rr_node_id)); VTR_ASSERT(chan_details.get_track_direction(itrack) == rr_graph.node_direction(rr_node_id)); - /* Unset existing node coordinate in the lookup */ - { - size_t xlow = std::min(rr_graph.node_xlow(rr_node_id), rr_graph.node_xhigh(rr_node_id)); - size_t xhigh = std::max(rr_graph.node_xlow(rr_node_id), rr_graph.node_xhigh(rr_node_id)); - size_t ylow = std::min(rr_graph.node_ylow(rr_node_id), rr_graph.node_yhigh(rr_node_id)); - size_t yhigh = std::max(rr_graph.node_ylow(rr_node_id), rr_graph.node_yhigh(rr_node_id)); - for (size_t ix = xlow; ix <= xhigh; ix++) { - for (size_t iy = ylow; iy <= yhigh; iy++) { - rr_graph_builder.node_lookup().add_node(RRNodeId::INVALID(), ix, iy, rr_graph.node_type(rr_node_id), rr_graph.node_track_num(rr_node_id)); - } - } - } /* set xhigh/yhigh and push changes to track_ids */ rr_graph_builder.set_node_coordinates(rr_node_id, rr_graph.node_xlow(rr_node_id), rr_graph.node_ylow(rr_node_id), @@ -759,7 +747,12 @@ static void load_one_chan_rr_nodes_basic_info(const RRGraphView& rr_graph, size_t yhigh = std::max(rr_graph.node_ylow(rr_node_id), rr_graph.node_yhigh(rr_node_id)); for (size_t ix = xlow; ix <= xhigh; ix++) { for (size_t iy = ylow; iy <= yhigh; iy++) { - rr_graph_builder.node_lookup().add_node(rr_node_id, ix, iy, rr_graph.node_type(rr_node_id), rr_graph.node_track_num(rr_node_id)); + if (CHANX == rr_graph.node_type(rr_node_id)) { + rr_graph_builder.node_lookup().add_node(rr_node_id, iy, ix, rr_graph.node_type(rr_node_id), rr_graph.node_track_num(rr_node_id)); + } else { + VTR_ASSERT_SAFE(CHANY == rr_graph.node_type(rr_node_id)); + rr_graph_builder.node_lookup().add_node(rr_node_id, ix, iy, rr_graph.node_type(rr_node_id), rr_graph.node_track_num(rr_node_id)); + } } } } From 53e6b0091812ab97786b00bc173988aeedf84d75 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 26 Aug 2022 15:05:00 -0700 Subject: [PATCH 064/147] [vpr] now supports multiple ptc number of a routing track in tileable routing resource graph --- libs/librrgraph/src/base/rr_graph_builder.cpp | 73 ++++++++++++++++--- libs/librrgraph/src/base/rr_graph_builder.h | 32 +++++++- libs/librrgraph/src/base/rr_graph_view.cpp | 6 +- libs/librrgraph/src/base/rr_graph_view.h | 6 +- vpr/src/base/vpr_context.h | 2 +- .../tileable_rr_graph_node_builder.cpp | 21 +++--- 6 files changed, 114 insertions(+), 26 deletions(-) diff --git a/libs/librrgraph/src/base/rr_graph_builder.cpp b/libs/librrgraph/src/base/rr_graph_builder.cpp index 3da9c11c931..edefb3c8445 100644 --- a/libs/librrgraph/src/base/rr_graph_builder.cpp +++ b/libs/librrgraph/src/base/rr_graph_builder.cpp @@ -33,6 +33,10 @@ vtr::vector>& RRGraphBuilder::node_in_edge_stora return node_in_edges_; } +vtr::vector>& RRGraphBuilder::node_ptc_storage() { + return node_ptc_nums_; +} + void RRGraphBuilder::add_node_to_all_locs(RRNodeId node) { t_rr_type node_type = node_storage_.node_type(node); short node_ptc_num = node_storage_.node_ptc_num(node); @@ -74,6 +78,7 @@ RRNodeId RRGraphBuilder::create_node(int x, int y, t_rr_type type, int ptc, e_si node_side = side; } node_storage_.emplace_back(); + node_ptc_nums_.emplace_back(); RRNodeId new_node = RRNodeId(node_storage_.size() - 1); node_storage_.set_node_type(new_node, type); node_storage_.set_node_coordinates(new_node, x, y, x, y); @@ -95,6 +100,7 @@ void RRGraphBuilder::clear() { node_lookup_.clear(); node_storage_.clear(); node_in_edges_.clear(); + node_ptc_nums_.clear(); rr_node_metadata_.clear(); rr_edge_metadata_.clear(); rr_segments_.clear(); @@ -204,13 +210,62 @@ void RRGraphBuilder::build_in_edges() { } std::vector RRGraphBuilder::node_in_edges(RRNodeId node) const { - VTR_ASSERT(size_t(node) < node_storage_.size()); - if (is_incoming_edge_dirty_) { - VTR_LOG_ERROR("Incoming edges are not built yet in routing resource graph. Please call build_in_edges()."); - return std::vector(); - } - if (node_in_edges_.empty()) { - return std::vector(); - } - return node_in_edges_[node]; + VTR_ASSERT(size_t(node) < node_storage_.size()); + if (is_incoming_edge_dirty_) { + VTR_LOG_ERROR("Incoming edges are not built yet in routing resource graph. Please call build_in_edges()."); + return std::vector(); + } + if (node_in_edges_.empty()) { + return std::vector(); + } + return node_in_edges_[node]; +} + +void RRGraphBuilder::add_node_track_num(RRNodeId node, vtr::Point node_offset, short track_id) { + VTR_ASSERT(size_t(node) < node_storage_.size()); + VTR_ASSERT_MSG(node_storage_.node_type(node) == CHANX || node_storage_.node_type(node) == CHANY, "Track number valid only for CHANX/CHANY RR nodes"); + + size_t node_length = std::abs(node_storage_.node_xhigh(node) - node_storage_.node_xlow(node)) + + std::abs(node_storage_.node_yhigh(node) - node_storage_.node_ylow(node)); + if (node_length + 1 != node_ptc_nums_[node].size()) { + node_ptc_nums_[node].resize(node_length + 1); + } + + size_t offset = node_offset.x() - node_storage_.node_xlow(node) + node_offset.y() - node_storage_.node_ylow(node); + VTR_ASSERT(offset < node_ptc_nums_[node].size()); + + node_ptc_nums_[node][offset] = track_id; +} + +void RRGraphBuilder::add_track_node_to_lookup(RRNodeId node) { + /* Compute the track id based on the (x, y) coordinate */ + size_t x_start = std::min(node_storage_.node_xlow(node), node_storage_.node_xhigh(node)); + size_t y_start = std::min(node_storage_.node_ylow(node), node_storage_.node_yhigh(node)); + std::vector node_x(std::abs(node_storage_.node_xlow(node) - node_storage_.node_xhigh(node)) + 1); + std::vector node_y(std::abs(node_storage_.node_ylow(node) - node_storage_.node_yhigh(node)) + 1); + + std::iota(node_x.begin(), node_x.end(), x_start); + std::iota(node_y.begin(), node_y.end(), y_start); + + VTR_ASSERT(size_t(std::max(node_storage_.node_xlow(node), node_storage_.node_xhigh(node))) == node_x.back()); + VTR_ASSERT(size_t(std::max(node_storage_.node_ylow(node), node_storage_.node_yhigh(node))) == node_y.back()); + + size_t itype = node_storage_.node_type(node); + + for (const size_t& x : node_x) { + for (const size_t& y : node_y) { + size_t ptc = node_storage_.node_ptc_num(node); + /* Routing channel nodes may have different ptc num + * Find the track ids using the x/y offset + * FIXME: Special case on assigning CHANX (x,y) should be changed to a natural way! + */ + if (CHANX == node_storage_.node_type(node)) { + ptc = node_ptc_nums_[node][x - node_storage_.node_xlow(node)]; + node_lookup_.add_node(node, y, x, CHANX, ptc); + } else if (CHANY == node_storage_.node_type(node)) { + ptc = node_ptc_nums_[node][y - node_storage_.node_ylow(node)]; + node_lookup_.add_node(node, x, y, CHANY, ptc); + } + } + } } diff --git a/libs/librrgraph/src/base/rr_graph_builder.h b/libs/librrgraph/src/base/rr_graph_builder.h index 9f015f9c91b..d557e43ea01 100644 --- a/libs/librrgraph/src/base/rr_graph_builder.h +++ b/libs/librrgraph/src/base/rr_graph_builder.h @@ -47,6 +47,8 @@ class RRGraphBuilder { MetadataStorage>& rr_edge_metadata(); /** @brief Return a writable object fo the incoming edge storage */ vtr::vector>& node_in_edge_storage(); + /** @brief Return a writable object of the node ptc storage (for tileable routing resource graph) */ + vtr::vector>& node_ptc_storage(); /** @brief Return the size for rr_node_metadata */ inline size_t rr_node_metadata_size() const { @@ -197,7 +199,16 @@ class RRGraphBuilder { node_storage_.set_node_track_num(id, new_track_num); } - /** @brief set_ node_class_num() is designed for routing source and sinks, which are SOURCE and SINK nodes */ + /** @brief Add a track id for a given node base on the offset in coordinate, applicable only to CHANX and CHANY nodes. + * This API is used by tileable routing resource graph generator, which requires each routing track has a different + * track id depending their location in FPGA fabric. + */ + void add_node_track_num(RRNodeId node, vtr::Point node_offset, short track_id); + + /** @brief Update the node_lookup for a track node. This is applicable to tileable routing graph */ + void add_track_node_to_lookup(RRNodeId node); + + /** @brief set_node_class_num() is designed for routing source and sinks, which are SOURCE and SINK nodes */ inline void set_node_class_num(RRNodeId id, short new_class_num) { node_storage_.set_node_class_num(id, new_class_num); } @@ -376,6 +387,25 @@ class RRGraphBuilder { * By default, it is empty! Call build_in_edges() to construct it!!! */ vtr::vector> node_in_edges_; + /* Extra ptc number for each routing resource node. This is required by tileable routing resource graph. + * In a tileable routing architecture, routing tracks, e.g., CHANX and CHANY, follows a staggered organization. + * Hence, a routing track may appear in different routing channels, representing different ptc/track id. + * Here is an illustrative example of a X-direction routing track (CHANX) in INC direction, which is organized in staggered way. + * + * Coord(x,y) (1,0) (2,0) (3,0) (4,0) Another track (node) + * ptc=0 ------> ------> + * \ / + * ptc=1 ------> / + * \ / + * ptc=2 ------> / + * \ / + * ptc=3 -------> + * ^ ^ + * | | + * starting point ending point + */ + vtr::vector> node_ptc_nums_; + /** .. warning:: The Metadata should stay as an independent data structure than rest of the internal data, * e.g., node_lookup! */ /* Metadata is an extra data on rr-nodes and edges, respectively, that is not used by vpr diff --git a/libs/librrgraph/src/base/rr_graph_view.cpp b/libs/librrgraph/src/base/rr_graph_view.cpp index edddaed097d..225af722e5b 100644 --- a/libs/librrgraph/src/base/rr_graph_view.cpp +++ b/libs/librrgraph/src/base/rr_graph_view.cpp @@ -11,7 +11,8 @@ RRGraphView::RRGraphView(const t_rr_graph_storage& node_storage, const std::vector& rr_rc_data, const vtr::vector& rr_segments, const vtr::vector& rr_switch_inf, - const vtr::vector>& node_in_edges) + const vtr::vector>& node_in_edges, + const vtr::vector>& node_ptc_nums) : node_storage_(node_storage) , node_lookup_(node_lookup) , rr_node_metadata_(rr_node_metadata) @@ -20,7 +21,8 @@ RRGraphView::RRGraphView(const t_rr_graph_storage& node_storage, , rr_rc_data_(rr_rc_data) , rr_segments_(rr_segments) , rr_switch_inf_(rr_switch_inf) - , node_in_edges_(node_in_edges) { + , node_in_edges_(node_in_edges) + , node_ptc_nums_(node_ptc_nums) { } std::vector RRGraphView::node_in_edges(RRNodeId node) const { diff --git a/libs/librrgraph/src/base/rr_graph_view.h b/libs/librrgraph/src/base/rr_graph_view.h index e52654c03e6..e3c9959e91c 100644 --- a/libs/librrgraph/src/base/rr_graph_view.h +++ b/libs/librrgraph/src/base/rr_graph_view.h @@ -43,7 +43,8 @@ class RRGraphView { const std::vector& rr_rc_data, const vtr::vector& rr_segments, const vtr::vector& rr_switch_inf, - const vtr::vector>& node_in_edges); + const vtr::vector>& node_in_edges, + const vtr::vector>& node_ptc_nums); /* Disable copy constructors and copy assignment operator * This is to avoid accidental copy because it could be an expensive operation considering that the @@ -570,6 +571,9 @@ class RRGraphView { /** A list of incoming edges for each routing resource node. This can be built optionally, as required by applications. * By default, it is empty! Call build_in_edges() to construct it!!! */ const vtr::vector>& node_in_edges_; + + /** A list of extra ptc numbers for each routing resource node. See details in RRGraphBuilder class */ + const vtr::vector>& node_ptc_nums_; }; #endif diff --git a/vpr/src/base/vpr_context.h b/vpr/src/base/vpr_context.h index 09d802e381a..7c5d0ce285f 100644 --- a/vpr/src/base/vpr_context.h +++ b/vpr/src/base/vpr_context.h @@ -194,7 +194,7 @@ struct DeviceContext : public Context { /* A read-only view of routing resource graph to be the ONLY database * for client functions: GUI, placer, router, timing analyzer etc. */ - RRGraphView rr_graph{rr_graph_builder.rr_nodes(), rr_graph_builder.node_lookup(), rr_graph_builder.rr_node_metadata(), rr_graph_builder.rr_edge_metadata(), rr_indexed_data, rr_rc_data, rr_graph_builder.rr_segments(), rr_graph_builder.rr_switch(), rr_graph_builder.node_in_edge_storage()}; + RRGraphView rr_graph{rr_graph_builder.rr_nodes(), rr_graph_builder.node_lookup(), rr_graph_builder.rr_node_metadata(), rr_graph_builder.rr_edge_metadata(), rr_indexed_data, rr_rc_data, rr_graph_builder.rr_segments(), rr_graph_builder.rr_switch(), rr_graph_builder.node_in_edge_storage(), rr_graph_builder.node_ptc_storage()}; /* Track ids for each rr_node in the rr_graph. * This is used by drawer for tileable routing resource graph diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp index 1d12d4c7705..be77036163b 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp @@ -739,22 +739,12 @@ static void load_one_chan_rr_nodes_basic_info(const RRGraphView& rr_graph, rr_graph.node_ylow(rr_node_id), chan_coordinate.x(), chan_coordinate.y()); - /* Update node look-up */ - size_t xlow = std::min(rr_graph.node_xlow(rr_node_id), rr_graph.node_xhigh(rr_node_id)); - size_t xhigh = std::max(rr_graph.node_xlow(rr_node_id), rr_graph.node_xhigh(rr_node_id)); - size_t ylow = std::min(rr_graph.node_ylow(rr_node_id), rr_graph.node_yhigh(rr_node_id)); - size_t yhigh = std::max(rr_graph.node_ylow(rr_node_id), rr_graph.node_yhigh(rr_node_id)); - for (int ix = xlow; ix <= xhigh; ix++) { - for (int iy = ylow; iy <= yhigh; iy++) { - rr_graph_builder.node_lookup().add_node(rr_node_id, ix, iy, rr_graph.node_type(rr_node_id), itrack); - } - } /* Do not update track_ids for length-1 wires, they should have only 1 track_id */ if ((rr_graph.node_xhigh(rr_node_id) > rr_graph.node_xlow(rr_node_id)) || (rr_graph.node_yhigh(rr_node_id) > rr_graph.node_ylow(rr_node_id))) { rr_node_track_ids[rr_node_id].push_back(itrack); - rr_graph_builder.set_node_track_num(rr_node_id, itrack); + rr_graph_builder.add_node_track_num(rr_node_id, chan_coordinate, itrack); } /* Finish here, go to next */ } @@ -788,7 +778,7 @@ static void load_one_chan_rr_nodes_basic_info(const RRGraphView& rr_graph, /* Update track_ids */ rr_node_track_ids[rr_node_id].push_back(itrack); - rr_graph_builder.set_node_track_num(rr_node_id, itrack); + rr_graph_builder.add_node_track_num(rr_node_id, chan_coordindate, itrack); /* Finish here, go to next */ } } @@ -1092,4 +1082,11 @@ void create_tileable_rr_graph_nodes(const RRGraphView& rr_graph, reverse_dec_chan_rr_node_track_ids(rr_graph, rr_node_track_ids); + + /* Update node look-up for CHANX and CHANY nodes */ + for (const RRNodeId& rr_node_id : rr_graph.nodes()) { + if (CHANX == rr_graph.node_type(rr_node_id) || CHANY == rr_graph.node_type(rr_node_id)) { + rr_graph_builder.add_track_node_to_lookup(rr_node_id); + } + } } From 087cf293c01c59e0efe71194d25c4dccff184cac Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 26 Aug 2022 15:12:50 -0700 Subject: [PATCH 065/147] [vpr] typo --- vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp index be77036163b..f5ffc6bfea7 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp @@ -778,7 +778,7 @@ static void load_one_chan_rr_nodes_basic_info(const RRGraphView& rr_graph, /* Update track_ids */ rr_node_track_ids[rr_node_id].push_back(itrack); - rr_graph_builder.add_node_track_num(rr_node_id, chan_coordindate, itrack); + rr_graph_builder.add_node_track_num(rr_node_id, chan_coordinate, itrack); /* Finish here, go to next */ } } From 2a1b88c430a278db03a87e89fa8edbc4530fac0f Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 26 Aug 2022 16:49:11 -0700 Subject: [PATCH 066/147] [vpr] force more assertion --- libs/librrgraph/src/base/rr_graph_builder.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libs/librrgraph/src/base/rr_graph_builder.cpp b/libs/librrgraph/src/base/rr_graph_builder.cpp index edefb3c8445..3af5004396f 100644 --- a/libs/librrgraph/src/base/rr_graph_builder.cpp +++ b/libs/librrgraph/src/base/rr_graph_builder.cpp @@ -223,6 +223,7 @@ std::vector RRGraphBuilder::node_in_edges(RRNodeId node) const { void RRGraphBuilder::add_node_track_num(RRNodeId node, vtr::Point node_offset, short track_id) { VTR_ASSERT(size_t(node) < node_storage_.size()); + VTR_ASSERT(size_t(node) < node_ptc_nums_.size()); VTR_ASSERT_MSG(node_storage_.node_type(node) == CHANX || node_storage_.node_type(node) == CHANY, "Track number valid only for CHANX/CHANY RR nodes"); size_t node_length = std::abs(node_storage_.node_xhigh(node) - node_storage_.node_xlow(node)) @@ -238,6 +239,8 @@ void RRGraphBuilder::add_node_track_num(RRNodeId node, vtr::Point node_o } void RRGraphBuilder::add_track_node_to_lookup(RRNodeId node) { + VTR_ASSERT_MSG(node_storage_.node_type(node) == CHANX || node_storage_.node_type(node) == CHANY, "Update track node look-up is only valid to CHANX/CHANY nodes"); + /* Compute the track id based on the (x, y) coordinate */ size_t x_start = std::min(node_storage_.node_xlow(node), node_storage_.node_xhigh(node)); size_t y_start = std::min(node_storage_.node_ylow(node), node_storage_.node_yhigh(node)); @@ -250,8 +253,6 @@ void RRGraphBuilder::add_track_node_to_lookup(RRNodeId node) { VTR_ASSERT(size_t(std::max(node_storage_.node_xlow(node), node_storage_.node_xhigh(node))) == node_x.back()); VTR_ASSERT(size_t(std::max(node_storage_.node_ylow(node), node_storage_.node_yhigh(node))) == node_y.back()); - size_t itype = node_storage_.node_type(node); - for (const size_t& x : node_x) { for (const size_t& y : node_y) { size_t ptc = node_storage_.node_ptc_num(node); From b080eda506b08df62ef808adbab1b9770d1311f6 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 26 Aug 2022 17:02:56 -0700 Subject: [PATCH 067/147] [vpr] fixed a bug which causes memory issues --- vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp index f5ffc6bfea7..7421574705b 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp @@ -703,7 +703,7 @@ static void load_one_chan_rr_nodes_basic_info(const RRGraphView& rr_graph, RRNodeId node = rr_graph_builder.create_node(chan_coordinate.x(), chan_coordinate.y(), chan_type, itrack); rr_graph_builder.set_node_direction(node, chan_details.get_track_direction(itrack)); - rr_graph_builder.set_node_track_num(node, itrack); + rr_graph_builder.add_node_track_num(node, chan_coordinate, itrack); rr_node_track_ids[node].push_back(itrack); rr_graph_builder.set_node_capacity(node, 1); From ef79f28f18578f61b63783cd9116fc721da8d9f2 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 27 Aug 2022 11:34:08 -0700 Subject: [PATCH 068/147] [lib] add sub_type and subFs support to arch parser --- libs/libarchfpga/src/read_xml_arch_file.cpp | 25 ++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/libs/libarchfpga/src/read_xml_arch_file.cpp b/libs/libarchfpga/src/read_xml_arch_file.cpp index ba85a5a2804..5673b4531c9 100644 --- a/libs/libarchfpga/src/read_xml_arch_file.cpp +++ b/libs/libarchfpga/src/read_xml_arch_file.cpp @@ -2718,8 +2718,9 @@ static void ProcessDevice(pugi::xml_node Node, t_arch* arch, t_default_fc_spec& // tag Cur = get_single_child(Node, "switch_block", loc_data); - expect_only_attributes(Cur, {"type", "fs"}, loc_data); + expect_only_attributes(Cur, {"type", "fs", "sub_type", "sub_fs"}, loc_data); Prop = get_attribute(Cur, "type", loc_data).value(); + /* Parse attribute 'type', representing the major connectivity pattern for switch blocks */ if (strcmp(Prop, "wilton") == 0) { arch->SBType = WILTON; } else if (strcmp(Prop, "universal") == 0) { @@ -2733,9 +2734,31 @@ static void ProcessDevice(pugi::xml_node Node, t_arch* arch, t_default_fc_spec& archfpga_throw(loc_data.filename_c_str(), loc_data.line(Cur), "Unknown property %s for switch block type x\n", Prop); } + /* Parse attribute 'sub_type', representing the minor connectivity pattern for switch blocks + * If not specified, the 'sub_type' is the same as major type + * This option is only valid for tileable routing resource graph builder + * Note that sub_type does not support custom switch block pattern!!! + * If 'sub_type' is specified, the custom switch block for 'type' is not allowed! + */ + std::string sub_type_str = get_attribute(Cur, "sub_type", loc_data, BoolToReqOpt(false)).as_string(""); + if (!sub_type_str.empty()) { + if (sub_type_str == std::string("wilton")) { + arch->SBSubType = WILTON; + } else if (sub_type_str == std::string("universal")) { + arch->SBSubType = UNIVERSAL; + } else if (sub_type_str == std::string("subset")) { + arch->SBSubType = SUBSET; + } else { + archfpga_throw(loc_data.filename_c_str(), loc_data.line(Cur), + "Unknown property %s for switch block subtype x\n", sub_type_str.c_str()); + } + } else { + arch->SBSubType = arch->SBType; + } ReqOpt CUSTOM_SWITCHBLOCK_REQD = BoolToReqOpt(!custom_switch_block); arch->Fs = get_attribute(Cur, "fs", loc_data, CUSTOM_SWITCHBLOCK_REQD).as_int(3); + arch->subFs = get_attribute(Cur, "sub_fs", loc_data, BoolToReqOpt(false)).as_int(arch->Fs); Cur = get_single_child(Node, "default_fc", loc_data, ReqOpt::OPTIONAL); if (Cur) { From 750091edc8ac117cc30b5da0b19a379f31ec8dc2 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 27 Aug 2022 18:44:53 -0700 Subject: [PATCH 069/147] [vpr] added a new option to skip the synchornization between clustering and routing results --- vpr/src/base/read_options.cpp | 7 +++++++ vpr/src/base/read_options.h | 1 + vpr/src/base/vpr_api.cpp | 29 +++++++++++++++++------------ 3 files changed, 25 insertions(+), 12 deletions(-) diff --git a/vpr/src/base/read_options.cpp b/vpr/src/base/read_options.cpp index d6e39e7b17d..e03993c842d 100644 --- a/vpr/src/base/read_options.cpp +++ b/vpr/src/base/read_options.cpp @@ -2602,6 +2602,13 @@ argparse::ArgumentParser create_arg_parser(std::string prog_name, t_options& arg .help("Writes implemented design final timing summary to the specified JSON, XML or TXT file.") .show_in(argparse::ShowIn::HELP_ONLY); + analysis_grp.add_argument(args.skip_sync_clustering_and_routing_results, "--skip_sync_clustering_and_routing_results") + .help( + "Select to skip the synchronization on clustering results based on routing optimization results." + "Note that when this sync-up is disabled, clustering results may be wrong (leading to incorrect bitstreams)!") + .default_value("off") + .show_in(argparse::ShowIn::HELP_ONLY); + auto& power_grp = parser.add_argument_group("power analysis options"); power_grp.add_argument(args.do_power, "--power") diff --git a/vpr/src/base/read_options.h b/vpr/src/base/read_options.h index 687f435f7e1..2be9ec3b22e 100644 --- a/vpr/src/base/read_options.h +++ b/vpr/src/base/read_options.h @@ -221,6 +221,7 @@ struct t_options { argparse::ArgValue post_synth_netlist_unconn_input_handling; argparse::ArgValue post_synth_netlist_unconn_output_handling; argparse::ArgValue write_timing_summary; + argparse::ArgValue skip_sync_clustering_and_routing_results; }; argparse::ArgumentParser create_arg_parser(std::string prog_name, t_options& args); diff --git a/vpr/src/base/vpr_api.cpp b/vpr/src/base/vpr_api.cpp index f161f0e65b6..078b8815310 100644 --- a/vpr/src/base/vpr_api.cpp +++ b/vpr/src/base/vpr_api.cpp @@ -1260,7 +1260,8 @@ bool vpr_analysis_flow(t_vpr_setup& vpr_setup, const t_arch& Arch, const RouteSt VTR_LOG("*****************************************************************************************\n"); } - /* If routing is successful, apply post-routing annotations + /* If routing is successful and users do not force to skip the sync-up, + * - apply post-routing annotations * - apply logic block pin fix-up * * Note: @@ -1268,17 +1269,21 @@ bool vpr_analysis_flow(t_vpr_setup& vpr_setup, const t_arch& Arch, const RouteSt * for packer (default verbosity is set to 2 for compact logs) */ if (route_status.success()) { - sync_netlists_to_routing(g_vpr_ctx.device(), - g_vpr_ctx.mutable_atom(), - g_vpr_ctx.mutable_clustering(), - g_vpr_ctx.placement(), - g_vpr_ctx.routing(), - vpr_setup.PackerOpts.pack_verbosity > 2); - - std::string post_routing_packing_output_file_name = vpr_setup.PackerOpts.output_file + ".post_routing"; - write_packing_results_to_xml(vpr_setup.PackerOpts.global_clocks, - Arch.architecture_id, - post_routing_packing_output_file_name.c_str()); + if (analysis.opts.skip_sync_clustering_and_routing_results) { + sync_netlists_to_routing(g_vpr_ctx.device(), + g_vpr_ctx.mutable_atom(), + g_vpr_ctx.mutable_clustering(), + g_vpr_ctx.placement(), + g_vpr_ctx.routing(), + vpr_setup.PackerOpts.pack_verbosity > 2); + + std::string post_routing_packing_output_file_name = vpr_setup.PackerOpts.output_file + ".post_routing"; + write_packing_results_to_xml(vpr_setup.PackerOpts.global_clocks, + Arch.architecture_id, + post_routing_packing_output_file_name.c_str()); + } else { + VTR_LOG_WARN("Sychronization between packing and routing results is not applied due to users select to skip it\n"); + } } else { VTR_LOG_WARN("Sychronization between packing and routing results is not applied due to illegal circuit implementation\n"); } From f0cf714da1048671841b4bbfa0c457e2cd36ea9e Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 27 Aug 2022 18:47:17 -0700 Subject: [PATCH 070/147] [vpr] syntax --- vpr/src/base/vpr_api.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vpr/src/base/vpr_api.cpp b/vpr/src/base/vpr_api.cpp index 078b8815310..32933566c4c 100644 --- a/vpr/src/base/vpr_api.cpp +++ b/vpr/src/base/vpr_api.cpp @@ -1269,7 +1269,7 @@ bool vpr_analysis_flow(t_vpr_setup& vpr_setup, const t_arch& Arch, const RouteSt * for packer (default verbosity is set to 2 for compact logs) */ if (route_status.success()) { - if (analysis.opts.skip_sync_clustering_and_routing_results) { + if (analysis_opts.skip_sync_clustering_and_routing_results) { sync_netlists_to_routing(g_vpr_ctx.device(), g_vpr_ctx.mutable_atom(), g_vpr_ctx.mutable_clustering(), From e36edc3a9aa3dea8b0c57c8eb2f4d688866c1704 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 27 Aug 2022 18:52:58 -0700 Subject: [PATCH 071/147] [vpr] add options --- vpr/src/base/SetupVPR.cpp | 2 ++ vpr/src/base/vpr_types.h | 1 + 2 files changed, 3 insertions(+) diff --git a/vpr/src/base/SetupVPR.cpp b/vpr/src/base/SetupVPR.cpp index f850a31840f..08d9f1e17b7 100644 --- a/vpr/src/base/SetupVPR.cpp +++ b/vpr/src/base/SetupVPR.cpp @@ -648,6 +648,8 @@ static void SetupAnalysisOpts(const t_options& Options, t_analysis_opts& analysi analysis_opts.timing_update_type = Options.timing_update_type; analysis_opts.write_timing_summary = Options.write_timing_summary; + + analysis_opts.skip_sync_clustering_and_routing_results = Options.skip_sync_clustering_and_routing_results; } static void SetupPowerOpts(const t_options& Options, t_power_opts* power_opts, t_arch* Arch) { diff --git a/vpr/src/base/vpr_types.h b/vpr/src/base/vpr_types.h index 1a537e61ba0..6f505418cd5 100644 --- a/vpr/src/base/vpr_types.h +++ b/vpr/src/base/vpr_types.h @@ -1258,6 +1258,7 @@ struct t_analysis_opts { std::string write_timing_summary; e_timing_update_type timing_update_type; + bool skip_sync_clustering_and_routing_results = false; }; // used to store NoC specific options, when supplied as an input by the user From b5d4f8ca41bc65ce35eae6ef3ec8ce1bf7f6a5a3 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 27 Aug 2022 19:07:07 -0700 Subject: [PATCH 072/147] [vpr] typo --- vpr/src/base/vpr_api.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vpr/src/base/vpr_api.cpp b/vpr/src/base/vpr_api.cpp index 32933566c4c..224a59500c9 100644 --- a/vpr/src/base/vpr_api.cpp +++ b/vpr/src/base/vpr_api.cpp @@ -1269,7 +1269,7 @@ bool vpr_analysis_flow(t_vpr_setup& vpr_setup, const t_arch& Arch, const RouteSt * for packer (default verbosity is set to 2 for compact logs) */ if (route_status.success()) { - if (analysis_opts.skip_sync_clustering_and_routing_results) { + if (!analysis_opts.skip_sync_clustering_and_routing_results) { sync_netlists_to_routing(g_vpr_ctx.device(), g_vpr_ctx.mutable_atom(), g_vpr_ctx.mutable_clustering(), From 78f8c821131c52d424597c391a3bf308fe63452b Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 1 Sep 2022 14:07:36 -0700 Subject: [PATCH 073/147] [vpr] adapt to the API change on check_rr_graph() --- vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp index b1bef8021d3..de96104dd1b 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp @@ -298,8 +298,8 @@ void build_tileable_unidir_rr_graph(const std::vector& typ "Fundamental errors occurred when validating rr_graph object!\n"); } - /* No clock network support yet */ - check_rr_graph(device_ctx.rr_graph, types, device_ctx.rr_indexed_data, grids, device_ctx.chan_width, GRAPH_UNIDIR, OPEN); + /* No clock network support yet; Does not support flatten rr_graph yet */ + check_rr_graph(device_ctx.rr_graph, types, device_ctx.rr_indexed_data, grids, device_ctx.chan_width, GRAPH_UNIDIR, OPEN, false); /************************************************************************ * Free all temp stucts From ce3173cef27b8dc16576709da7894fde66e1e2ce Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 7 Sep 2022 15:09:09 -0700 Subject: [PATCH 074/147] [vpr] remove GSB graph matching APIs --- vpr/src/tileable_rr_graph/rr_chan.cpp | 30 ---- vpr/src/tileable_rr_graph/rr_chan.h | 1 - vpr/src/tileable_rr_graph/rr_gsb.cpp | 249 -------------------------- vpr/src/tileable_rr_graph/rr_gsb.h | 46 +---- 4 files changed, 1 insertion(+), 325 deletions(-) diff --git a/vpr/src/tileable_rr_graph/rr_chan.cpp b/vpr/src/tileable_rr_graph/rr_chan.cpp index 2f69bd659b1..c6a991ea524 100644 --- a/vpr/src/tileable_rr_graph/rr_chan.cpp +++ b/vpr/src/tileable_rr_graph/rr_chan.cpp @@ -66,36 +66,6 @@ RRSegmentId RRChan::get_node_segment(const size_t& track_num) const { return node_segments_[track_num]; } -/* evaluate if two RRChan is mirror to each other */ -bool RRChan::is_mirror(const RRGraphView& rr_graph, const RRChan& cand) const { - /* If any following element does not match, it is not mirror */ - /* 1. type */ - if (this->get_type() != cand.get_type()) { - return false; - } - /* 2. track_width */ - if (this->get_chan_width() != cand.get_chan_width()) { - return false; - } - /* 3. for each node */ - for (size_t inode = 0; inode < this->get_chan_width(); ++inode) { - /* 3.1 check node type */ - if (rr_graph.node_type(this->get_node(inode)) != rr_graph.node_type(cand.get_node(inode))) { - return false; - } - /* 3.2 check node directionality */ - if (rr_graph.node_direction(this->get_node(inode)) != rr_graph.node_direction(cand.get_node(inode))) { - return false; - } - /* 3.3 check node segment */ - if (this->get_node_segment(inode) != cand.get_node_segment(inode)) { - return false; - } - } - - return true; -} - /* Get a list of segments used in this routing channel */ std::vector RRChan::get_segment_ids() const { std::vector seg_list; diff --git a/vpr/src/tileable_rr_graph/rr_chan.h b/vpr/src/tileable_rr_graph/rr_chan.h index 2e40e06c3d2..5ba9bc09af5 100644 --- a/vpr/src/tileable_rr_graph/rr_chan.h +++ b/vpr/src/tileable_rr_graph/rr_chan.h @@ -46,7 +46,6 @@ class RRChan { RRNodeId get_node(const size_t& track_num) const; /* get the rr_node with the track_id */ RRSegmentId get_node_segment(const RRNodeId& node) const; RRSegmentId get_node_segment(const size_t& track_num) const; - bool is_mirror(const RRGraphView& rr_graph, const RRChan& cand) const; /* evaluate if two RR_chan is mirror to each other */ std::vector get_segment_ids() const; /* Get a list of segments used in this routing channel */ std::vector get_node_ids_by_segment_ids(const RRSegmentId& seg_id) const; /* Get a list of segments used in this routing channel */ public: /* Mutators */ diff --git a/vpr/src/tileable_rr_graph/rr_gsb.cpp b/vpr/src/tileable_rr_graph/rr_gsb.cpp index 525b3ca5576..cad8fdb32d4 100644 --- a/vpr/src/tileable_rr_graph/rr_gsb.cpp +++ b/vpr/src/tileable_rr_graph/rr_gsb.cpp @@ -343,37 +343,6 @@ bool RRGSB::is_sb_node_exist_opposite_side(const RRGraphView& rr_graph, return (-1 != index); } -/* check if the candidate CB is a mirror of the current one */ -bool RRGSB::is_cb_mirror(const RRGraphView& rr_graph, const RRGSB& cand, const t_rr_type& cb_type) const { - /* Check if channel width is the same */ - if (get_cb_chan_width(cb_type) != cand.get_cb_chan_width(cb_type)) { - return false; - } - - enum e_side chan_side = get_cb_chan_side(cb_type); - - /* check the numbers/directionality of channel rr_nodes */ - if (false == chan_node_[size_t(chan_side)].is_mirror(rr_graph, cand.chan_node_[size_t(chan_side)])) { - return false; - } - - /* check the equivalence of ipins */ - std::vector ipin_side = get_cb_ipin_sides(cb_type); - for (size_t side = 0; side < ipin_side.size(); ++side) { - /* Ensure we have the same number of IPINs on this side */ - if (get_num_ipin_nodes(ipin_side[side]) != cand.get_num_ipin_nodes(ipin_side[side])) { - return false; - } - for (size_t inode = 0; inode < get_num_ipin_nodes(ipin_side[side]); ++inode) { - if (false == is_cb_node_mirror(rr_graph, cand, cb_type, ipin_side[side], inode)) { - return false; - } - } - } - - return true; -} - /* check if the CB exist in this GSB */ bool RRGSB::is_cb_exist(const t_rr_type& cb_type) const { /* if channel width is zero, there is no CB */ @@ -493,87 +462,6 @@ bool RRGSB::is_sb_mirrorable(const RRGraphView& rr_graph, const RRGSB& cand) con return true; } -/* check if all the routing segments of a side of candidate SB is a mirror of the current one */ -bool RRGSB::is_sb_side_segment_mirror(const RRGraphView& rr_graph, const RRGSB& cand, const e_side& side, const RRSegmentId& seg_id) const { - /* Create a side manager */ - SideManager side_manager(side); - - /* Make sure both Switch blocks has this side!!! */ - VTR_ASSERT(side_manager.to_size_t() < get_num_sides()); - VTR_ASSERT(side_manager.to_size_t() < cand.get_num_sides()); - - /* check the numbers/directionality of channel rr_nodes */ - /* Ensure we have the same channel width on this side */ - if (get_chan_width(side) != cand.get_chan_width(side)) { - return false; - } - for (size_t itrack = 0; itrack < get_chan_width(side); ++itrack) { - /* Bypass unrelated segments */ - if (seg_id != get_chan_node_segment(side, itrack)) { - continue; - } - /* Check the directionality of each node */ - if (get_chan_node_direction(side, itrack) != cand.get_chan_node_direction(side, itrack)) { - return false; - } - /* Check the track_id of each node - * ptc is not necessary, we care the connectivity! - */ - /* For OUT_PORT rr_node, we need to check fan-in */ - if (OUT_PORT != get_chan_node_direction(side, itrack)) { - continue; /* skip IN_PORT */ - } - - if (false == is_sb_node_mirror(rr_graph, cand, side, itrack)) { - return false; - } - } - - /* check the numbers of opin_rr_nodes */ - if (get_num_opin_nodes(side) != cand.get_num_opin_nodes(side)) { - return false; - } - - /* check the numbers of ipin_rr_nodes */ - if (get_num_ipin_nodes(side) != cand.get_num_ipin_nodes(side)) { - return false; - } - - return true; -} - -/* check if a side of candidate SB is a mirror of the current one */ -bool RRGSB::is_sb_side_mirror(const RRGraphView& rr_graph, const RRGSB& cand, const e_side& side) const { - /* get a list of segments */ - std::vector seg_ids = chan_node_[size_t(side)].get_segment_ids(); - - for (size_t iseg = 0; iseg < seg_ids.size(); ++iseg) { - if (false == is_sb_side_segment_mirror(rr_graph, cand, side, seg_ids[iseg])) { - return false; - } - } - - return true; -} - -/* check if the candidate SB is a mirror of the current one */ -bool RRGSB::is_sb_mirror(const RRGraphView& rr_graph, const RRGSB& cand) const { - /* check the numbers of sides */ - if (get_num_sides() != cand.get_num_sides()) { - return false; - } - - /* check the numbers/directionality of channel rr_nodes */ - for (size_t side = 0; side < get_num_sides(); ++side) { - SideManager side_manager(side); - if (false == is_sb_side_mirror(rr_graph, cand, side_manager.get_side())) { - return false; - } - } - - return true; -} - /* Public Accessors: Cooridinator conversion */ /* get the x coordinate of this GSB */ @@ -947,143 +835,6 @@ void RRGSB::clear_one_side(const e_side& node_side) { /************************************************************************ * Internal Accessors: identify mirrors ***********************************************************************/ - -/* check if two rr_nodes have a similar set of drive_rr_nodes - * for each drive_rr_node: - * 1. CHANX or CHANY: should have the same side and index - * 2. OPIN or IPIN: should have the same side and index - * 3. each drive_rr_switch should be the same - */ -bool RRGSB::is_sb_node_mirror(const RRGraphView& rr_graph, - const RRGSB& cand, - const e_side& node_side, - const size_t& track_id) const { - /* Ensure rr_nodes are either the output of short-connection or multiplexer */ - bool is_short_conkt = this->is_sb_node_passing_wire(rr_graph, node_side, track_id); - - if (is_short_conkt != cand.is_sb_node_passing_wire(rr_graph, node_side, track_id)) { - return false; - } - - if (true == is_short_conkt) { - /* Since, both are pass wires, - * The two node should be equivalent - * we can return here - */ - return true; - } - - /* Use unsorted/sorted edges */ - std::vector node_in_edges = get_chan_node_in_edges(rr_graph, node_side, track_id); - std::vector cand_node_in_edges = cand.get_chan_node_in_edges(rr_graph, node_side, track_id); - - /* For non-passing wires, check driving rr_nodes */ - if (node_in_edges.size() != cand_node_in_edges.size()) { - return false; - } - - VTR_ASSERT(node_in_edges.size() == cand_node_in_edges.size()); - - for (size_t iedge = 0; iedge < node_in_edges.size(); ++iedge) { - RREdgeId src_edge = node_in_edges[iedge]; - RREdgeId src_cand_edge = cand_node_in_edges[iedge]; - RRNodeId src_node = rr_graph.edge_src_node(src_edge); - RRNodeId src_cand_node = rr_graph.edge_src_node(src_cand_edge); - /* node type should be the same */ - if (rr_graph.node_type(src_node) != rr_graph.node_type(src_cand_node)) { - return false; - } - /* switch type should be the same */ - if (rr_graph.edge_switch(src_edge) != rr_graph.edge_switch(src_cand_edge)) { - return false; - } - int src_node_id, des_node_id; - enum e_side src_node_side, des_node_side; - this->get_node_side_and_index(rr_graph, src_node, OUT_PORT, src_node_side, src_node_id); - cand.get_node_side_and_index(rr_graph, src_cand_node, OUT_PORT, des_node_side, des_node_id); - if (src_node_id != des_node_id) { - return false; - } - if (src_node_side != des_node_side) { - return false; - } - } - - return true; -} - -/* check if two ipin_nodes have a similar set of drive_rr_nodes - * for each drive_rr_node: - * 1. CHANX or CHANY: should have the same side and index - * 2. each drive_rr_switch should be the same - */ -bool RRGSB::is_cb_node_mirror(const RRGraphView& rr_graph, - const RRGSB& cand, - const t_rr_type& cb_type, - const e_side& node_side, - const size_t& node_id) const { - /* Ensure rr_nodes are either the output of short-connection or multiplexer */ - RRNodeId node = this->get_ipin_node(node_side, node_id); - RRNodeId cand_node = cand.get_ipin_node(node_side, node_id); - - if (rr_graph.node_in_edges(node).size() != rr_graph.node_in_edges(cand_node).size()) { - return false; - } - - std::vector node_in_edges; - for (const RREdgeId& edge : rr_graph.node_in_edges(node)) { - node_in_edges.push_back(edge); - } - - std::vector cand_node_in_edges; - for (const RREdgeId& edge : rr_graph.node_in_edges(cand_node)) { - cand_node_in_edges.push_back(edge); - } - VTR_ASSERT(node_in_edges.size() == cand_node_in_edges.size()); - - for (size_t iedge = 0; iedge < node_in_edges.size(); ++iedge) { - RREdgeId src_edge = node_in_edges[iedge]; - RREdgeId src_cand_edge = cand_node_in_edges[iedge]; - RRNodeId src_node = rr_graph.edge_src_node(src_edge); - RRNodeId src_cand_node = rr_graph.edge_src_node(src_cand_edge); - /* node type should be the same */ - if (rr_graph.node_type(src_node) != rr_graph.node_type(src_cand_node)) { - return false; - } - /* switch type should be the same */ - if (rr_graph.edge_switch(src_edge) != rr_graph.edge_switch(src_cand_edge)) { - return false; - } - - int src_node_id, des_node_id; - enum e_side src_node_side, des_node_side; - enum e_side chan_side = get_cb_chan_side(cb_type); - switch (rr_graph.node_type(src_node)) { - case CHANX: - case CHANY: - /* if the drive rr_nodes are routing tracks, find index */ - src_node_id = this->get_chan_node_index(chan_side, src_node); - des_node_id = cand.get_chan_node_index(chan_side, src_cand_node); - break; - case OPIN: - this->get_node_side_and_index(rr_graph, src_node, OUT_PORT, src_node_side, src_node_id); - cand.get_node_side_and_index(rr_graph, src_cand_node, OUT_PORT, des_node_side, des_node_id); - if (src_node_side != des_node_side) { - return false; - } - break; - default: - VTR_LOG("Invalid type of drive_rr_nodes for ipin_node!\n"); - exit(1); - } - if (src_node_id != des_node_id) { - return false; - } - } - - return true; -} - size_t RRGSB::get_track_id_first_short_connection(const RRGraphView& rr_graph, const e_side& node_side) const { VTR_ASSERT(validate_side(node_side)); diff --git a/vpr/src/tileable_rr_graph/rr_gsb.h b/vpr/src/tileable_rr_graph/rr_gsb.h index 00caa876d29..241007c8490 100644 --- a/vpr/src/tileable_rr_graph/rr_gsb.h +++ b/vpr/src/tileable_rr_graph/rr_gsb.h @@ -117,9 +117,6 @@ class RRGSB { bool is_sb_node_exist_opposite_side(const RRGraphView& rr_graph, const RRNodeId& node, const e_side& node_side) const; public: /* Accessors: to identify mirrors */ - /* check if the candidate SB is a mirror of the current one */ - bool is_cb_mirror(const RRGraphView& rr_graph, const RRGSB& cand, const t_rr_type& cb_type) const; - /* check if the connect block exists in the GSB */ bool is_cb_exist(const t_rr_type& cb_type) const; @@ -133,37 +130,7 @@ class RRGSB { * on being a mirror of the current one */ bool is_sb_mirrorable(const RRGraphView& rr_graph, const RRGSB& cand) const; - - /* check if all the routing segments of a side of candidate SB is a mirror of the current one */ - bool is_sb_side_segment_mirror(const RRGraphView& rr_graph, const RRGSB& cand, const e_side& side, const RRSegmentId& seg_id) const; - - /* check if a side of candidate SB is a mirror of the current one - * Check the specified side of two switch blocks: - * 1. Number of channel/opin/ipin rr_nodes are same - * For channel rr_nodes - * 2. check if their track_ids (ptc_num) are same - * 3. Check if the switches (ids) are same - * For opin/ipin rr_nodes, - * 4. check if their parent type_descriptors same, - * 5. check if pin class id and pin id are same - * If all above are satisfied, the side of the two switch blocks are mirrors! - */ - bool is_sb_side_mirror(const RRGraphView& rr_graph, const RRGSB& cand, const e_side& side) const; - - /* check if the candidate SB is a mirror of the current one - * Idenify mirror Switch blocks - * Check each two switch blocks: - * 1. Number of channel/opin/ipin rr_nodes are same - * For channel rr_nodes - * 2. check if their track_ids (ptc_num) are same - * 3. Check if the switches (ids) are same - * For opin/ipin rr_nodes, - * 4. check if their parent type_descriptors same, - * 5. check if pin class id and pin id are same - * If all above are satisfied, the two switch blocks are mirrors! - */ - bool is_sb_mirror(const RRGraphView& rr_graph, const RRGSB& cand) const; - + public: /* Cooridinator conversion and output */ size_t get_x() const; /* get the x coordinate of this switch block */ size_t get_y() const; /* get the y coordinate of this switch block */ @@ -230,17 +197,6 @@ class RRGSB { const size_t& track_id); private: /* internal functions */ - bool is_sb_node_mirror(const RRGraphView& rr_graph, - const RRGSB& cand, - const e_side& node_side, - const size_t& track_id) const; - - bool is_cb_node_mirror(const RRGraphView& rr_graph, - const RRGSB& cand, - const t_rr_type& cb_type, - const e_side& node_side, - const size_t& node_id) const; - size_t get_track_id_first_short_connection(const RRGraphView& rr_graph, const e_side& node_side) const; private: /* internal validators */ From 6a515ff79beecc3b4ce1830f072b0e441420e19c Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 7 Sep 2022 16:19:34 -0700 Subject: [PATCH 075/147] [vpr] add missing APi required by latest openfpga --- vpr/src/tileable_rr_graph/rr_gsb.cpp | 4 ++++ vpr/src/tileable_rr_graph/rr_gsb.h | 3 +++ 2 files changed, 7 insertions(+) diff --git a/vpr/src/tileable_rr_graph/rr_gsb.cpp b/vpr/src/tileable_rr_graph/rr_gsb.cpp index cad8fdb32d4..9c811a13de1 100644 --- a/vpr/src/tileable_rr_graph/rr_gsb.cpp +++ b/vpr/src/tileable_rr_graph/rr_gsb.cpp @@ -61,6 +61,10 @@ size_t RRGSB::get_max_chan_width() const { return max_chan_width; } +const RRGSB::RRChan& chan(const e_side& chan_side) const { + return chan_node_[size_t(chan_side)]; +} + /* Get the number of routing tracks of a X/Y-direction CB */ size_t RRGSB::get_cb_chan_width(const t_rr_type& cb_type) const { return get_chan_width(get_cb_chan_side(cb_type)); diff --git a/vpr/src/tileable_rr_graph/rr_gsb.h b/vpr/src/tileable_rr_graph/rr_gsb.h index 241007c8490..854bc37eae1 100644 --- a/vpr/src/tileable_rr_graph/rr_gsb.h +++ b/vpr/src/tileable_rr_graph/rr_gsb.h @@ -67,6 +67,9 @@ class RRGSB { /* Get the number of routing tracks of a X/Y-direction CB */ size_t get_cb_chan_width(const t_rr_type& cb_type) const; + /* Return read-only object of the routing channels with a given side */ + const RRChan& chan(const e_side& chan_side) const; + /* Get the sides of CB ipins in the array */ std::vector get_cb_ipin_sides(const t_rr_type& cb_type) const; From abc6555a0b096ec7237094471d3f4cfaa679ffa0 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 7 Sep 2022 16:23:43 -0700 Subject: [PATCH 076/147] [vpr] syntax --- vpr/src/tileable_rr_graph/rr_gsb.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vpr/src/tileable_rr_graph/rr_gsb.cpp b/vpr/src/tileable_rr_graph/rr_gsb.cpp index 9c811a13de1..c21f093983f 100644 --- a/vpr/src/tileable_rr_graph/rr_gsb.cpp +++ b/vpr/src/tileable_rr_graph/rr_gsb.cpp @@ -61,7 +61,7 @@ size_t RRGSB::get_max_chan_width() const { return max_chan_width; } -const RRGSB::RRChan& chan(const e_side& chan_side) const { +const RRChan& RRGSB::chan(const e_side& chan_side) const { return chan_node_[size_t(chan_side)]; } From 3b758f01bb615ffaaccb99df8737219d4cd7494a Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 9 Sep 2022 14:59:04 -0700 Subject: [PATCH 077/147] [lib] now arch parser supports subtile index when parsing pin location assignments --- libs/libarchfpga/src/read_xml_arch_file.cpp | 168 +++++++++++++++++--- 1 file changed, 150 insertions(+), 18 deletions(-) diff --git a/libs/libarchfpga/src/read_xml_arch_file.cpp b/libs/libarchfpga/src/read_xml_arch_file.cpp index 20aececca82..9af15bd42b7 100644 --- a/libs/libarchfpga/src/read_xml_arch_file.cpp +++ b/libs/libarchfpga/src/read_xml_arch_file.cpp @@ -119,6 +119,11 @@ static std::pair ProcessPinString(pugi::xml_node Locations, T type, const char* pin_loc_string, const pugiutil::loc_data& loc_data); +template +static std::pair ProcessInstanceString(pugi::xml_node Locations, + T type, + const char* pin_loc_string, + const pugiutil::loc_data& loc_data); /* Process XML hierarchy */ static void ProcessTiles(pugi::xml_node Node, @@ -609,10 +614,15 @@ static void LoadPinLoc(pugi::xml_node Locations, &sub_tile, token.c_str(), loc_data); - + /* Get the offset in the capacity range */ + auto capacity_range = ProcessInstanceString(Locations, + &sub_tile, + token.c_str(), + loc_data); + VTR_ASSERT(0 <= capacity_range.first && capacity_range.second < sub_tile_capacity); for (int pin_num = pin_range.first; pin_num < pin_range.second; ++pin_num) { VTR_ASSERT(pin_num < (int)sub_tile.sub_tile_to_tile_pin_indices.size() / sub_tile_capacity); - for (int capacity = 0; capacity < sub_tile_capacity; ++capacity) { + for (int capacity = capacity_range.first; capacity <= capacity_range.second; ++capacity) { int sub_tile_pin_index = pin_num + capacity * sub_tile.num_phy_pins / sub_tile_capacity; int physical_pin_index = sub_tile.sub_tile_to_tile_pin_indices[sub_tile_pin_index]; type->pinloc[width][height][side][physical_pin_index] = true; @@ -639,6 +649,99 @@ static void LoadPinLoc(pugi::xml_node Locations, } } +/* Parse the string to extract instance range, e.g., io[4:7] -> (4, 7) + * If no instance range is explicitly defined, we assume the range of type capacity, i.e., (0, capacity - 1) */ +template +static std::pair ProcessInstanceString(pugi::xml_node Locations, + T type, + const char* pin_loc_string, + const pugiutil::loc_data& loc_data) { + int num_tokens; + auto tokens = GetTokensFromString(pin_loc_string, &num_tokens); + + int token_index = 0; + auto token = tokens[token_index]; + + if (token.type != TOKEN_STRING || 0 != strcmp(token.data, type->name)) { + archfpga_throw(loc_data.filename_c_str(), loc_data.line(Locations), + "Wrong physical type name of the port: %s\n", pin_loc_string); + } + + token_index++; + token = tokens[token_index]; + + int first_inst = 0; + int last_inst = type->capacity - 1; + + /* If there is a dot, such as io.input[0:3], it indicates the full range of the capacity, the default value should be returned */ + if (token.type == TOKEN_DOT) { + freeTokens(tokens, num_tokens); + return std::make_pair(first_inst, last_inst); + } + + /* If the string contains index for capacity range, e.g., io[3:3].in[0:5], we skip the capacity range here. */ + if (token.type != TOKEN_OPEN_SQUARE_BRACKET) { + archfpga_throw(loc_data.filename_c_str(), loc_data.line(Locations), + "No open square bracket present: %s\n", pin_loc_string); + } + + token_index++; + token = tokens[token_index]; + + if (token.type != TOKEN_INT) { + archfpga_throw(loc_data.filename_c_str(), loc_data.line(Locations), + "No integer to indicate least significant instance index: %s\n", pin_loc_string); + } + + first_inst = vtr::atoi(token.data); + + token_index++; + token = tokens[token_index]; + + // Single pin is specified + if (token.type != TOKEN_COLON) { + if (token.type != TOKEN_CLOSE_SQUARE_BRACKET) { + archfpga_throw(loc_data.filename_c_str(), loc_data.line(Locations), + "No closing bracket: %s\n", pin_loc_string); + } + + token_index++; + + if (token_index != num_tokens) { + archfpga_throw(loc_data.filename_c_str(), loc_data.line(Locations), + "instance of pin location should be completed, but more tokens are present: %s\n", pin_loc_string); + } + + freeTokens(tokens, num_tokens); + return std::make_pair(first_inst, first_inst); + } + + token_index++; + token = tokens[token_index]; + + if (token.type != TOKEN_INT) { + archfpga_throw(loc_data.filename_c_str(), loc_data.line(Locations), + "No integer to indicate most significant instance index: %s\n", pin_loc_string); + } + + last_inst = vtr::atoi(token.data); + + token_index++; + token = tokens[token_index]; + + if (token.type != TOKEN_CLOSE_SQUARE_BRACKET) { + archfpga_throw(loc_data.filename_c_str(), loc_data.line(Locations), + "No closed square bracket: %s\n", pin_loc_string); + } + + if (first_inst > last_inst) { + std::swap(first_inst, last_inst); + } + + freeTokens(tokens, num_tokens); + return std::make_pair(first_inst, last_inst); +} + template static std::pair ProcessPinString(pugi::xml_node Locations, T type, @@ -658,6 +761,20 @@ static std::pair ProcessPinString(pugi::xml_node Locations, token_index++; token = tokens[token_index]; + /* If the string contains index for capacity range, e.g., io[3:3].in[0:5], we skip the capacity range here. */ + if (token.type == TOKEN_OPEN_SQUARE_BRACKET) { + while (token.type != TOKEN_CLOSE_SQUARE_BRACKET) { + token_index++; + token = tokens[token_index]; + if (token_index == num_tokens) { + archfpga_throw(loc_data.filename_c_str(), loc_data.line(Locations), + "Found an open '[' but miss close ']' of the port: %s\n", pin_loc_string); + } + } + token_index++; + token = tokens[token_index]; + } + if (token.type != TOKEN_DOT) { archfpga_throw(loc_data.filename_c_str(), loc_data.line(Locations), "No dot is present to separate type name and port name: %s\n", pin_loc_string); @@ -3314,19 +3431,30 @@ static void ProcessPinLocations(pugi::xml_node Locations, //Verify that all top-level pins have had their locations specified - //Record all the specified pins - std::map> port_pins_with_specified_locations; + //Record all the specified pins, (capacity, port_name, index) + std::map>> port_pins_with_specified_locations; for (int w = 0; w < PhysicalTileType->width; ++w) { for (int h = 0; h < PhysicalTileType->height; ++h) { for (e_side side : {TOP, RIGHT, BOTTOM, LEFT}) { for (auto token : pin_locs->assignments[sub_tile_index][w][h][side]) { InstPort inst_port(token.c_str()); - //A pin specification should contain only the block name, and not any instace count information + //A pin specification may contain instance count, but should be in the range of capacity + int inst_lsb = 0; + int inst_msb = PhysicalTileType->capacity - 1; if (inst_port.instance_low_index() != InstPort::UNSPECIFIED || inst_port.instance_high_index() != InstPort::UNSPECIFIED) { - archfpga_throw(loc_data.filename_c_str(), loc_data.line(Locations), - "Pin location specification '%s' should not contain an instance range (should only be the block name)", - token.c_str()); + /* Extract range numbers */ + inst_lsb = inst_port.instance_low_index(); + inst_msb = inst_port.instance_high_index(); + if (inst_lsb > inst_msb) { + std::swap(inst_lsb, inst_msb); + } + /* Check if we have a valid range */ + if (inst_lsb < 0 || inst_msb > PhysicalTileType->capacity - 1) { + archfpga_throw(loc_data.filename_c_str(), loc_data.line(Locations), + "Pin location specification '%s' contain an out-of-range instance. Expect [%d:%d]", + token.c_str(), 0 , PhysicalTileType->capacity - 1); + } } //Check that the block name matches @@ -3363,9 +3491,11 @@ static void ProcessPinLocations(pugi::xml_node Locations, VTR_ASSERT(pin_low_idx >= 0); VTR_ASSERT(pin_high_idx >= 0); - for (int ipin = pin_low_idx; ipin <= pin_high_idx; ++ipin) { - //Record that the pin has it's location specified - port_pins_with_specified_locations[inst_port.port_name()].insert(ipin); + for (int iinst = inst_lsb; iinst <= inst_msb; ++iinst) { + for (int ipin = pin_low_idx; ipin <= pin_high_idx; ++ipin) { + //Record that the pin has it's location specified + port_pins_with_specified_locations[iinst][inst_port.port_name()].insert(ipin); + } } } } @@ -3373,13 +3503,15 @@ static void ProcessPinLocations(pugi::xml_node Locations, } //Check for any pins missing location specs - for (const auto& port : SubTile->ports) { - for (int ipin = 0; ipin < port.num_pins; ++ipin) { - if (!port_pins_with_specified_locations[port.name].count(ipin)) { - //Missing - archfpga_throw(loc_data.filename_c_str(), loc_data.line(Locations), - "Pin '%s.%s[%d]' has no pin location specificed (a location is required for pattern=\"custom\")", - SubTile->name, port.name, ipin); + for (int iinst = 0; iinst < PhysicalTileType->capacity; ++iinst) { + for (const auto& port : SubTile->ports) { + for (int ipin = 0; ipin < port.num_pins; ++ipin) { + if (!port_pins_with_specified_locations[port.name].count(ipin)) { + //Missing + archfpga_throw(loc_data.filename_c_str(), loc_data.line(Locations), + "Pin '%s[%d].%s[%d]' has no pin location specificed (a location is required for pattern=\"custom\")", + SubTile->name, iinst, port.name, ipin); + } } } } From f97b7e2e03c3434bad65ca3a15d8a41ccf225fcc Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 9 Sep 2022 15:02:21 -0700 Subject: [PATCH 078/147] [lib] syntax --- libs/libarchfpga/src/read_xml_arch_file.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libs/libarchfpga/src/read_xml_arch_file.cpp b/libs/libarchfpga/src/read_xml_arch_file.cpp index 9af15bd42b7..75557afd6e1 100644 --- a/libs/libarchfpga/src/read_xml_arch_file.cpp +++ b/libs/libarchfpga/src/read_xml_arch_file.cpp @@ -615,10 +615,10 @@ static void LoadPinLoc(pugi::xml_node Locations, token.c_str(), loc_data); /* Get the offset in the capacity range */ - auto capacity_range = ProcessInstanceString(Locations, - &sub_tile, - token.c_str(), - loc_data); + auto capacity_range = ProcessInstanceString(Locations, + &sub_tile, + token.c_str(), + loc_data); VTR_ASSERT(0 <= capacity_range.first && capacity_range.second < sub_tile_capacity); for (int pin_num = pin_range.first; pin_num < pin_range.second; ++pin_num) { VTR_ASSERT(pin_num < (int)sub_tile.sub_tile_to_tile_pin_indices.size() / sub_tile_capacity); @@ -3506,7 +3506,7 @@ static void ProcessPinLocations(pugi::xml_node Locations, for (int iinst = 0; iinst < PhysicalTileType->capacity; ++iinst) { for (const auto& port : SubTile->ports) { for (int ipin = 0; ipin < port.num_pins; ++ipin) { - if (!port_pins_with_specified_locations[port.name].count(ipin)) { + if (!port_pins_with_specified_locations[iinst][port.name].count(ipin)) { //Missing archfpga_throw(loc_data.filename_c_str(), loc_data.line(Locations), "Pin '%s[%d].%s[%d]' has no pin location specificed (a location is required for pattern=\"custom\")", From 7994e804e9ea2be7d65b806699ed2c7692e878b3 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 9 Sep 2022 15:09:41 -0700 Subject: [PATCH 079/147] [lib] syntax --- libs/libarchfpga/src/read_xml_arch_file.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/libarchfpga/src/read_xml_arch_file.cpp b/libs/libarchfpga/src/read_xml_arch_file.cpp index 75557afd6e1..edf257f0e3d 100644 --- a/libs/libarchfpga/src/read_xml_arch_file.cpp +++ b/libs/libarchfpga/src/read_xml_arch_file.cpp @@ -671,7 +671,7 @@ static std::pair ProcessInstanceString(pugi::xml_node Locations, token = tokens[token_index]; int first_inst = 0; - int last_inst = type->capacity - 1; + int last_inst = type->capacity.total() - 1; /* If there is a dot, such as io.input[0:3], it indicates the full range of the capacity, the default value should be returned */ if (token.type == TOKEN_DOT) { From 7482107eb3bc39a25eac2be2c49e8ae331675ee9 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 16 Sep 2022 21:41:12 -0700 Subject: [PATCH 080/147] [lib] add an option to avoid sorting edges when creating them. This is to check whether this is the reason causing back-compatibility issues --- libs/librrgraph/src/base/rr_graph_builder.cpp | 6 ++++-- libs/librrgraph/src/base/rr_graph_builder.h | 2 +- .../tileable_rr_graph/tileable_rr_graph_edge_builder.cpp | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/libs/librrgraph/src/base/rr_graph_builder.cpp b/libs/librrgraph/src/base/rr_graph_builder.cpp index 3af5004396f..7ddf6f96e67 100644 --- a/libs/librrgraph/src/base/rr_graph_builder.cpp +++ b/libs/librrgraph/src/base/rr_graph_builder.cpp @@ -186,9 +186,11 @@ void RRGraphBuilder::create_edge(RRNodeId src, RRNodeId dest, RRSwitchId edge_sw is_incoming_edge_dirty_ = true; } -void RRGraphBuilder::build_edges() { +void RRGraphBuilder::build_edges(const bool& uniquify) { std::sort(edges_to_build_.begin(), edges_to_build_.end()); - edges_to_build_.erase(std::unique(edges_to_build_.begin(), edges_to_build_.end()), edges_to_build_.end()); + if (uniquify) { + edges_to_build_.erase(std::unique(edges_to_build_.begin(), edges_to_build_.end()), edges_to_build_.end()); + } alloc_and_load_edges(&edges_to_build_); edges_to_build_.clear(); is_edge_dirty_ = false; diff --git a/libs/librrgraph/src/base/rr_graph_builder.h b/libs/librrgraph/src/base/rr_graph_builder.h index fb26f5e88de..228a7e94b5c 100644 --- a/libs/librrgraph/src/base/rr_graph_builder.h +++ b/libs/librrgraph/src/base/rr_graph_builder.h @@ -225,7 +225,7 @@ class RRGraphBuilder { /** @brief Allocate and build actual edges in storage. * Once called, the cached edges will be uniquified and added to routing resource nodes, * while the cache will be empty once build-up is accomplished */ - void build_edges(); + void build_edges(const bool& uniquify = true); /** @brief Allocate and build incoming edges for each node. * By default, no incoming edges are kept in storage, to be memory efficient */ diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp index 195c5eabe9f..61b52b72190 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp @@ -136,7 +136,7 @@ void build_rr_graph_edges(const RRGraphView& rr_graph, track2ipin_map, opin2track_map, sb_conn, rr_node_driver_switches); /* Finish this GSB, go to the next*/ - rr_graph_builder.build_edges(); + rr_graph_builder.build_edges(false); } } } From eb75a5a3a1c26f98261d6625aeb7df8b656548b5 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 17 Sep 2022 09:51:25 -0700 Subject: [PATCH 081/147] [vtr] count number of edges before creating them; Found some mismatches in edge count by comparing the current branch to the OpenFPGA's version. --- .../tileable_rr_graph_edge_builder.cpp | 16 +++++++++++----- .../tileable_rr_graph/tileable_rr_graph_gsb.cpp | 6 +++++- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp index 61b52b72190..fc43b4bb955 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp @@ -22,7 +22,8 @@ void build_rr_graph_edges_for_source_nodes(const RRGraphView& rr_graph, RRGraphBuilder& rr_graph_builder, const vtr::vector& rr_node_driver_switches, - const DeviceGrid& grids) { + const DeviceGrid& grids, + size_t& num_edges_to_create) { for (const RRNodeId& node : rr_graph.nodes()) { /* Bypass all the non OPIN nodes */ if (OPIN != rr_graph.node_type(node)) { @@ -41,6 +42,7 @@ void build_rr_graph_edges_for_source_nodes(const RRGraphView& rr_graph, /* add edges to the src_node */ rr_graph_builder.create_edge(src_node, node, rr_node_driver_switches[node]); + num_edges_to_create++; } /* Allocate edges for all the source nodes */ rr_graph_builder.build_edges(); @@ -53,7 +55,8 @@ void build_rr_graph_edges_for_source_nodes(const RRGraphView& rr_graph, void build_rr_graph_edges_for_sink_nodes(const RRGraphView& rr_graph, RRGraphBuilder& rr_graph_builder, const vtr::vector& rr_node_driver_switches, - const DeviceGrid& grids) { + const DeviceGrid& grids, + size_t& num_edges_to_create) { for (const RRNodeId& node : rr_graph.nodes()) { /* Bypass all the non IPIN nodes */ if (IPIN != rr_graph.node_type(node)) { @@ -72,6 +75,7 @@ void build_rr_graph_edges_for_sink_nodes(const RRGraphView& rr_graph, /* add edges to connect the IPIN node to SINK nodes */ rr_graph_builder.create_edge(node, sink_node, rr_node_driver_switches[sink_node]); + num_edges_to_create++; } /* Allocate edges for all the source nodes */ rr_graph_builder.build_edges(); @@ -100,9 +104,10 @@ void build_rr_graph_edges(const RRGraphView& rr_graph, const e_switch_block_type& sb_subtype, const int& subFs, const bool& wire_opposite_side) { + size_t num_edges_to_create = 0; /* Create edges for SOURCE and SINK nodes for a tileable rr_graph */ - build_rr_graph_edges_for_source_nodes(rr_graph, rr_graph_builder, rr_node_driver_switches, grids); - build_rr_graph_edges_for_sink_nodes(rr_graph, rr_graph_builder, rr_node_driver_switches, grids); + build_rr_graph_edges_for_source_nodes(rr_graph, rr_graph_builder, rr_node_driver_switches, grids, num_edges_to_create); + build_rr_graph_edges_for_sink_nodes(rr_graph, rr_graph_builder, rr_node_driver_switches, grids, num_edges_to_create); vtr::Point gsb_range(grids.width() - 2, grids.height() - 2); @@ -134,11 +139,12 @@ void build_rr_graph_edges(const RRGraphView& rr_graph, /* Build edges for a GSB */ build_edges_for_one_tileable_rr_gsb(rr_graph_builder, rr_gsb, track2ipin_map, opin2track_map, - sb_conn, rr_node_driver_switches); + sb_conn, rr_node_driver_switches, num_edges_to_create); /* Finish this GSB, go to the next*/ rr_graph_builder.build_edges(false); } } + VTR_LOG("Number of edges to create: %ld\n", num_edges_to_create); } /************************************************************************ diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp index a33eda105d4..c89f6b51bd8 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp @@ -917,7 +917,8 @@ void build_edges_for_one_tileable_rr_gsb(RRGraphBuilder& rr_graph_builder, const t_track2pin_map& track2ipin_map, const t_pin2track_map& opin2track_map, const t_track2track_map& track2track_map, - const vtr::vector& rr_node_driver_switches) { + const vtr::vector& rr_node_driver_switches, + size_t& num_edges_to_create) { /* Walk through each sides */ for (size_t side = 0; side < rr_gsb.get_num_sides(); ++side) { SideManager side_manager(side); @@ -931,6 +932,7 @@ void build_edges_for_one_tileable_rr_gsb(RRGraphBuilder& rr_graph_builder, /* add edges to the opin_node */ for (const RRNodeId& track_node : opin2track_map[gsb_side][inode]) { rr_graph_builder.create_edge(opin_node, track_node, rr_node_driver_switches[track_node]); + num_edges_to_create++; } } @@ -945,6 +947,7 @@ void build_edges_for_one_tileable_rr_gsb(RRGraphBuilder& rr_graph_builder, const RRNodeId& chan_node = rr_gsb.get_chan_node(gsb_side, inode); for (const RRNodeId& ipin_node : track2ipin_map[gsb_side][inode]) { rr_graph_builder.create_edge(chan_node, ipin_node, rr_node_driver_switches[ipin_node]); + num_edges_to_create++; } } } @@ -954,6 +957,7 @@ void build_edges_for_one_tileable_rr_gsb(RRGraphBuilder& rr_graph_builder, const RRNodeId& chan_node = rr_gsb.get_chan_node(gsb_side, inode); for (const RRNodeId& track_node : track2track_map[gsb_side][inode]) { rr_graph_builder.create_edge(chan_node, track_node, rr_node_driver_switches[track_node]); + num_edges_to_create++; } } } From 5d409cba6becd237e0ddb11c4b9fead25ba9993d Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 17 Sep 2022 09:56:57 -0700 Subject: [PATCH 082/147] [vpr] syntax --- vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.h | 6 ++++-- vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.h | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.h b/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.h index 8e780521da3..9e56e33ca19 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.h +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.h @@ -44,11 +44,13 @@ void build_rr_graph_direct_connections(const RRGraphView& rr_graph, void build_rr_graph_edges_for_source_nodes(const RRGraphView& rr_graph, RRGraphBuilder& rr_graph_builder, const vtr::vector& rr_node_driver_switches, - const DeviceGrid& grids); + const DeviceGrid& grids, + size_t& num_edges_to_create); void build_rr_graph_edges_for_sink_nodes(const RRGraphView& rr_graph, RRGraphBuilder& rr_graph_builder, const vtr::vector& rr_node_driver_switches, - const DeviceGrid& grids); + const DeviceGrid& grids, + size_t& num_edges_to_create); #endif diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.h b/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.h index 43224fbdbc7..9e1d63963ed 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.h +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.h @@ -51,7 +51,8 @@ void build_edges_for_one_tileable_rr_gsb(RRGraphBuilder& rr_graph_builder, const t_track2pin_map& track2ipin_map, const t_pin2track_map& opin2track_map, const t_track2track_map& track2track_map, - const vtr::vector& rr_node_driver_switches); + const vtr::vector& rr_node_driver_switches, + size_t& num_edges); t_track2pin_map build_gsb_track_to_ipin_map(const RRGraphView& rr_graph, const RRGSB& rr_gsb, From 6dff2000ab567207926eb0123efadb3ae1e3b5a1 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 17 Sep 2022 10:21:58 -0700 Subject: [PATCH 083/147] [vpr] add more debugging info about edge count for tileable routing resource graph builder --- .../tileable_rr_graph_edge_builder.cpp | 10 ++++++++-- vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp | 9 ++++++--- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp index fc43b4bb955..f9de406966b 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp @@ -24,6 +24,7 @@ void build_rr_graph_edges_for_source_nodes(const RRGraphView& rr_graph, const vtr::vector& rr_node_driver_switches, const DeviceGrid& grids, size_t& num_edges_to_create) { + size_t& edge_count = 0; for (const RRNodeId& node : rr_graph.nodes()) { /* Bypass all the non OPIN nodes */ if (OPIN != rr_graph.node_type(node)) { @@ -42,10 +43,12 @@ void build_rr_graph_edges_for_source_nodes(const RRGraphView& rr_graph, /* add edges to the src_node */ rr_graph_builder.create_edge(src_node, node, rr_node_driver_switches[node]); - num_edges_to_create++; + edge_count++; } /* Allocate edges for all the source nodes */ rr_graph_builder.build_edges(); + VTR_LOG("Number of edges to create for source nodes: %ld\n", edge_count); + num_edges_to_create += edge_count; } /************************************************************************ @@ -57,6 +60,7 @@ void build_rr_graph_edges_for_sink_nodes(const RRGraphView& rr_graph, const vtr::vector& rr_node_driver_switches, const DeviceGrid& grids, size_t& num_edges_to_create) { + size_t& edge_count = 0; for (const RRNodeId& node : rr_graph.nodes()) { /* Bypass all the non IPIN nodes */ if (IPIN != rr_graph.node_type(node)) { @@ -75,10 +79,12 @@ void build_rr_graph_edges_for_sink_nodes(const RRGraphView& rr_graph, /* add edges to connect the IPIN node to SINK nodes */ rr_graph_builder.create_edge(node, sink_node, rr_node_driver_switches[sink_node]); - num_edges_to_create++; + edge_count++; } /* Allocate edges for all the source nodes */ rr_graph_builder.build_edges(); + VTR_LOG("Number of edges to create for sink nodes: %ld\n", edge_count); + num_edges_to_create += edge_count; } /************************************************************************ diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp index c89f6b51bd8..4e174348808 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp @@ -919,6 +919,7 @@ void build_edges_for_one_tileable_rr_gsb(RRGraphBuilder& rr_graph_builder, const t_track2track_map& track2track_map, const vtr::vector& rr_node_driver_switches, size_t& num_edges_to_create) { + size_t edge_count = 0; /* Walk through each sides */ for (size_t side = 0; side < rr_gsb.get_num_sides(); ++side) { SideManager side_manager(side); @@ -932,7 +933,7 @@ void build_edges_for_one_tileable_rr_gsb(RRGraphBuilder& rr_graph_builder, /* add edges to the opin_node */ for (const RRNodeId& track_node : opin2track_map[gsb_side][inode]) { rr_graph_builder.create_edge(opin_node, track_node, rr_node_driver_switches[track_node]); - num_edges_to_create++; + edge_count++; } } @@ -947,7 +948,7 @@ void build_edges_for_one_tileable_rr_gsb(RRGraphBuilder& rr_graph_builder, const RRNodeId& chan_node = rr_gsb.get_chan_node(gsb_side, inode); for (const RRNodeId& ipin_node : track2ipin_map[gsb_side][inode]) { rr_graph_builder.create_edge(chan_node, ipin_node, rr_node_driver_switches[ipin_node]); - num_edges_to_create++; + edge_count++; } } } @@ -957,10 +958,12 @@ void build_edges_for_one_tileable_rr_gsb(RRGraphBuilder& rr_graph_builder, const RRNodeId& chan_node = rr_gsb.get_chan_node(gsb_side, inode); for (const RRNodeId& track_node : track2track_map[gsb_side][inode]) { rr_graph_builder.create_edge(chan_node, track_node, rr_node_driver_switches[track_node]); - num_edges_to_create++; + edge_count++; } } } + VTR_LOG("Number of edges to create for gsb[%ld][%ld]: %ld\n", rr_gsb.get_x(), rr_gsb.get_y(), edge_count); + num_edges_to_create += edge_count; } /************************************************************************ From 1ba0c0ed5aaba67ec56c08aae7d4e72acd0f1cb3 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 17 Sep 2022 10:25:17 -0700 Subject: [PATCH 084/147] [vpr] syntax --- vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp index f9de406966b..f12fbcc59a1 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp @@ -24,7 +24,7 @@ void build_rr_graph_edges_for_source_nodes(const RRGraphView& rr_graph, const vtr::vector& rr_node_driver_switches, const DeviceGrid& grids, size_t& num_edges_to_create) { - size_t& edge_count = 0; + size_t edge_count = 0; for (const RRNodeId& node : rr_graph.nodes()) { /* Bypass all the non OPIN nodes */ if (OPIN != rr_graph.node_type(node)) { @@ -60,7 +60,7 @@ void build_rr_graph_edges_for_sink_nodes(const RRGraphView& rr_graph, const vtr::vector& rr_node_driver_switches, const DeviceGrid& grids, size_t& num_edges_to_create) { - size_t& edge_count = 0; + size_t edge_count = 0; for (const RRNodeId& node : rr_graph.nodes()) { /* Bypass all the non IPIN nodes */ if (IPIN != rr_graph.node_type(node)) { From 4966634f606d0df1f4eb94442aef3d2242dc7d13 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 17 Sep 2022 22:23:10 -0700 Subject: [PATCH 085/147] [lib] Fixed a bug where subFs was not copied to det_routing arch parameters --- vpr/src/base/SetupVPR.cpp | 2 ++ vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/vpr/src/base/SetupVPR.cpp b/vpr/src/base/SetupVPR.cpp index 8f88140f136..7f6bd0c7dfc 100644 --- a/vpr/src/base/SetupVPR.cpp +++ b/vpr/src/base/SetupVPR.cpp @@ -350,9 +350,11 @@ static void SetupSwitches(const t_arch& Arch, static void SetupRoutingArch(const t_arch& Arch, t_det_routing_arch* RoutingArch) { RoutingArch->switch_block_type = Arch.SBType; + RoutingArch->switch_block_type = Arch.SBSubType; RoutingArch->R_minW_nmos = Arch.R_minW_nmos; RoutingArch->R_minW_pmos = Arch.R_minW_pmos; RoutingArch->Fs = Arch.Fs; + RoutingArch->subFs = Arch.subFs; RoutingArch->directionality = BI_DIRECTIONAL; if (Arch.Segments.size()) { RoutingArch->directionality = Arch.Segments[0].directionality; diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp index 4e174348808..6e5d9407411 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp @@ -374,6 +374,8 @@ static void build_gsb_one_group_track_to_track_map(const RRGraphView& rr_graph, /* to_track should be OUT_PORT */ VTR_ASSERT(OUT_PORT == rr_gsb.get_chan_node_direction(to_side, to_track_index)); + VTR_LOG("Consider a connection from pass tracks %d on side %s to track node %ld on side %s\n", from_track_index, SIDE_STRING[from_side], size_t(to_track_node), SIDE_STRING[to_side]); + /* Check if the to_track_node is already in the list ! */ std::vector::iterator it = std::find(track2track_map[from_side_index][from_track_index].begin(), track2track_map[from_side_index][from_track_index].end(), @@ -383,6 +385,7 @@ static void build_gsb_one_group_track_to_track_map(const RRGraphView& rr_graph, } /* Clear, we should add to the list */ track2track_map[from_side_index][from_track_index].push_back(to_track_node); + VTR_LOG("Built a connection from pass tracks %d on side %s to track node %ld on side %s\n", from_track_index, SIDE_STRING[from_side], size_t(to_track_node), SIDE_STRING[to_side]); } } } @@ -519,6 +522,9 @@ t_track2track_map build_gsb_track_to_track_map(const RRGraphView& rr_graph, /* Currently, I use the same Switch Block pattern for the passing tracks and end tracks, * TODO: This can be improved with different patterns! */ + for (e_side curr_side : SIDES) { + VTR_LOG("Number of pass tracks %d on side %s\n", pass_tracks[size_t(curr_side)].size(), SIDE_STRING[curr_side]); + } build_gsb_one_group_track_to_track_map(rr_graph, rr_gsb, sb_subtype, subFs, wire_opposite_side, /* Pass tracks may not be wired to start tracks */ From 40d40506e451becf6c7af5b8f0a75c39990ccc08 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sun, 18 Sep 2022 10:04:44 -0700 Subject: [PATCH 086/147] [vpr] comment out debug logging --- vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp index 6e5d9407411..d990f201c2c 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp @@ -374,7 +374,7 @@ static void build_gsb_one_group_track_to_track_map(const RRGraphView& rr_graph, /* to_track should be OUT_PORT */ VTR_ASSERT(OUT_PORT == rr_gsb.get_chan_node_direction(to_side, to_track_index)); - VTR_LOG("Consider a connection from pass tracks %d on side %s to track node %ld on side %s\n", from_track_index, SIDE_STRING[from_side], size_t(to_track_node), SIDE_STRING[to_side]); + //VTR_LOG("Consider a connection from pass tracks %d on side %s to track node %ld on side %s\n", from_track_index, SIDE_STRING[from_side], size_t(to_track_node), SIDE_STRING[to_side]); /* Check if the to_track_node is already in the list ! */ std::vector::iterator it = std::find(track2track_map[from_side_index][from_track_index].begin(), @@ -385,7 +385,7 @@ static void build_gsb_one_group_track_to_track_map(const RRGraphView& rr_graph, } /* Clear, we should add to the list */ track2track_map[from_side_index][from_track_index].push_back(to_track_node); - VTR_LOG("Built a connection from pass tracks %d on side %s to track node %ld on side %s\n", from_track_index, SIDE_STRING[from_side], size_t(to_track_node), SIDE_STRING[to_side]); + //VTR_LOG("Built a connection from pass tracks %d on side %s to track node %ld on side %s\n", from_track_index, SIDE_STRING[from_side], size_t(to_track_node), SIDE_STRING[to_side]); } } } @@ -522,9 +522,9 @@ t_track2track_map build_gsb_track_to_track_map(const RRGraphView& rr_graph, /* Currently, I use the same Switch Block pattern for the passing tracks and end tracks, * TODO: This can be improved with different patterns! */ - for (e_side curr_side : SIDES) { - VTR_LOG("Number of pass tracks %d on side %s\n", pass_tracks[size_t(curr_side)].size(), SIDE_STRING[curr_side]); - } + //for (e_side curr_side : SIDES) { + // VTR_LOG("Number of pass tracks %d on side %s\n", pass_tracks[size_t(curr_side)].size(), SIDE_STRING[curr_side]); + //} build_gsb_one_group_track_to_track_map(rr_graph, rr_gsb, sb_subtype, subFs, wire_opposite_side, /* Pass tracks may not be wired to start tracks */ From 2c3197ece7cdc95c74ceb02637f02aab66faa015 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sun, 18 Sep 2022 10:58:08 -0700 Subject: [PATCH 087/147] [vpr] fixed a bug where subtype is not passed correctly --- vpr/src/base/SetupVPR.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vpr/src/base/SetupVPR.cpp b/vpr/src/base/SetupVPR.cpp index 7f6bd0c7dfc..2a2ac25779d 100644 --- a/vpr/src/base/SetupVPR.cpp +++ b/vpr/src/base/SetupVPR.cpp @@ -350,7 +350,7 @@ static void SetupSwitches(const t_arch& Arch, static void SetupRoutingArch(const t_arch& Arch, t_det_routing_arch* RoutingArch) { RoutingArch->switch_block_type = Arch.SBType; - RoutingArch->switch_block_type = Arch.SBSubType; + RoutingArch->switch_block_subtype = Arch.SBSubType; RoutingArch->R_minW_nmos = Arch.R_minW_nmos; RoutingArch->R_minW_pmos = Arch.R_minW_pmos; RoutingArch->Fs = Arch.Fs; From 1374493be37a907cc5040c179b1c77f98330bd08 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sun, 18 Sep 2022 21:45:15 -0700 Subject: [PATCH 088/147] [lib] fixed a bug where free_rr_graph is not thorough --- libs/librrgraph/src/base/rr_graph_builder.cpp | 2 ++ vpr/src/route/rr_graph.cpp | 2 ++ 2 files changed, 4 insertions(+) diff --git a/libs/librrgraph/src/base/rr_graph_builder.cpp b/libs/librrgraph/src/base/rr_graph_builder.cpp index 7ddf6f96e67..ebfc6e4341c 100644 --- a/libs/librrgraph/src/base/rr_graph_builder.cpp +++ b/libs/librrgraph/src/base/rr_graph_builder.cpp @@ -103,7 +103,9 @@ void RRGraphBuilder::clear() { node_ptc_nums_.clear(); rr_node_metadata_.clear(); rr_edge_metadata_.clear(); + segment_ids_.clear(); rr_segments_.clear(); + switch_ids_.clear(); rr_switch_inf_.clear(); edges_to_build_.clear(); is_edge_dirty_ = true; diff --git a/vpr/src/route/rr_graph.cpp b/vpr/src/route/rr_graph.cpp index 9a3538f135a..a043e2ab77d 100644 --- a/vpr/src/route/rr_graph.cpp +++ b/vpr/src/route/rr_graph.cpp @@ -1674,6 +1674,8 @@ void free_rr_graph() { device_ctx.rr_graph_builder.clear(); + device_ctx.rr_node_track_ids.clear(); + device_ctx.rr_indexed_data.clear(); device_ctx.switch_fanin_remap.clear(); From 907ff5851676d42c464d128de48056be9f1df06e Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sun, 18 Sep 2022 21:56:39 -0700 Subject: [PATCH 089/147] [vpr] fixed a bug where tileable rr_graph is not considered during binary search and place --- vpr/src/base/place_and_route.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/vpr/src/base/place_and_route.cpp b/vpr/src/base/place_and_route.cpp index c0956ba822a..8a3c1c13059 100644 --- a/vpr/src/base/place_and_route.cpp +++ b/vpr/src/base/place_and_route.cpp @@ -93,6 +93,10 @@ int binary_search_place_and_route(const t_placer_opts& placer_opts_ref, graph_directionality = GRAPH_BIDIR; } else { graph_type = (det_routing_arch->directionality == BI_DIRECTIONAL ? GRAPH_BIDIR : GRAPH_UNIDIR); + /* Branch on tileable routing */ + if (det_routing_arch->directionality == UNI_DIRECTIONAL && det_routing_arch->tileable) { + graph_type = GRAPH_UNIDIR_TILEABLE; + } graph_directionality = (det_routing_arch->directionality == BI_DIRECTIONAL ? GRAPH_BIDIR : GRAPH_UNIDIR); } From 5ea56610fe823a8e7e72c70371f3ce2ceb825a6a Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sun, 18 Sep 2022 22:13:39 -0700 Subject: [PATCH 090/147] [vpr] fixed a bug on using tileable rr_graph for binary place and route --- vpr/src/route/route_common.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/vpr/src/route/route_common.cpp b/vpr/src/route/route_common.cpp index 03d92e17cde..e8e4f05c1c7 100644 --- a/vpr/src/route/route_common.cpp +++ b/vpr/src/route/route_common.cpp @@ -266,6 +266,10 @@ bool try_route(int width_fac, graph_directionality = GRAPH_BIDIR; } else { graph_type = (det_routing_arch->directionality == BI_DIRECTIONAL ? GRAPH_BIDIR : GRAPH_UNIDIR); + /* Branch on tileable routing */ + if (det_routing_arch->directionality == UNI_DIRECTIONAL && det_routing_arch->tileable) { + graph_type = GRAPH_UNIDIR_TILEABLE; + } graph_directionality = (det_routing_arch->directionality == BI_DIRECTIONAL ? GRAPH_BIDIR : GRAPH_UNIDIR); } From bd63ae21528a9d92cce74c2d5c5cd15a0544663b Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 19 Sep 2022 09:54:17 -0700 Subject: [PATCH 091/147] [vpr] now skip sorting edges for tileable rr_graph builder --- libs/librrgraph/src/base/rr_graph_builder.cpp | 2 +- vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp | 4 ++-- vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libs/librrgraph/src/base/rr_graph_builder.cpp b/libs/librrgraph/src/base/rr_graph_builder.cpp index ebfc6e4341c..a5b0c3cd13b 100644 --- a/libs/librrgraph/src/base/rr_graph_builder.cpp +++ b/libs/librrgraph/src/base/rr_graph_builder.cpp @@ -189,8 +189,8 @@ void RRGraphBuilder::create_edge(RRNodeId src, RRNodeId dest, RRSwitchId edge_sw } void RRGraphBuilder::build_edges(const bool& uniquify) { - std::sort(edges_to_build_.begin(), edges_to_build_.end()); if (uniquify) { + std::sort(edges_to_build_.begin(), edges_to_build_.end()); edges_to_build_.erase(std::unique(edges_to_build_.begin(), edges_to_build_.end()), edges_to_build_.end()); } alloc_and_load_edges(&edges_to_build_); diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp index f12fbcc59a1..cc4d5c6185d 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp @@ -46,7 +46,7 @@ void build_rr_graph_edges_for_source_nodes(const RRGraphView& rr_graph, edge_count++; } /* Allocate edges for all the source nodes */ - rr_graph_builder.build_edges(); + rr_graph_builder.build_edges(false); VTR_LOG("Number of edges to create for source nodes: %ld\n", edge_count); num_edges_to_create += edge_count; } @@ -82,7 +82,7 @@ void build_rr_graph_edges_for_sink_nodes(const RRGraphView& rr_graph, edge_count++; } /* Allocate edges for all the source nodes */ - rr_graph_builder.build_edges(); + rr_graph_builder.build_edges(false); VTR_LOG("Number of edges to create for sink nodes: %ld\n", edge_count); num_edges_to_create += edge_count; } diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp index d990f201c2c..ae6b8e0892e 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp @@ -1442,5 +1442,5 @@ void build_direct_connections_for_one_gsb(const RRGraphView& rr_graph, } } /* Build actual edges */ - rr_graph_builder.build_edges(); + rr_graph_builder.build_edges(false); } From 69476ee33fdb19b52f9f5b8d3837fe7a3a6b5471 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 19 Sep 2022 10:19:43 -0700 Subject: [PATCH 092/147] [vpr] now sort all the edges when building a tileable rr_graph --- .../tileable_rr_graph/tileable_rr_graph_edge_builder.cpp | 6 +++--- vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp index cc4d5c6185d..a30fc51fe35 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp @@ -46,7 +46,7 @@ void build_rr_graph_edges_for_source_nodes(const RRGraphView& rr_graph, edge_count++; } /* Allocate edges for all the source nodes */ - rr_graph_builder.build_edges(false); + rr_graph_builder.build_edges(true); VTR_LOG("Number of edges to create for source nodes: %ld\n", edge_count); num_edges_to_create += edge_count; } @@ -82,7 +82,7 @@ void build_rr_graph_edges_for_sink_nodes(const RRGraphView& rr_graph, edge_count++; } /* Allocate edges for all the source nodes */ - rr_graph_builder.build_edges(false); + rr_graph_builder.build_edges(true); VTR_LOG("Number of edges to create for sink nodes: %ld\n", edge_count); num_edges_to_create += edge_count; } @@ -147,7 +147,7 @@ void build_rr_graph_edges(const RRGraphView& rr_graph, track2ipin_map, opin2track_map, sb_conn, rr_node_driver_switches, num_edges_to_create); /* Finish this GSB, go to the next*/ - rr_graph_builder.build_edges(false); + rr_graph_builder.build_edges(true); } } VTR_LOG("Number of edges to create: %ld\n", num_edges_to_create); diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp index ae6b8e0892e..d33e1a0f84d 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp @@ -1442,5 +1442,5 @@ void build_direct_connections_for_one_gsb(const RRGraphView& rr_graph, } } /* Build actual edges */ - rr_graph_builder.build_edges(false); + rr_graph_builder.build_edges(true); } From b2df63231b62e41710e0b7846db26a8687270066 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 19 Sep 2022 10:58:48 -0700 Subject: [PATCH 093/147] [vpr] sort gsb ipin edges as well --- vpr/src/tileable_rr_graph/rr_gsb.cpp | 114 +++++++++++++++++++++++++++ vpr/src/tileable_rr_graph/rr_gsb.h | 7 ++ 2 files changed, 121 insertions(+) diff --git a/vpr/src/tileable_rr_graph/rr_gsb.cpp b/vpr/src/tileable_rr_graph/rr_gsb.cpp index c21f093983f..ceb92c9fc70 100644 --- a/vpr/src/tileable_rr_graph/rr_gsb.cpp +++ b/vpr/src/tileable_rr_graph/rr_gsb.cpp @@ -22,6 +22,7 @@ RRGSB::RRGSB() { chan_node_.clear(); chan_node_direction_.clear(); chan_node_in_edges_.clear(); + ipin_node_in_edges_.clear(); ipin_node_.clear(); @@ -172,6 +173,34 @@ std::vector RRGSB::get_chan_node_in_edges(const RRGraphView& rr_graph, return chan_node_in_edges_[side_manager.to_size_t()][track_id]; } +std::vector RRGSB::get_ipin_node_in_edges(const RRGraphView& rr_graph, + const e_side& side, + const size_t& ipin_id) const { + SideManager side_manager(side); + VTR_ASSERT(side_manager.validate()); + + /* Ensure the side is valid in the context of this switch block */ + VTR_ASSERT(validate_side(side)); + + /* Ensure the track is valid in the context of this switch block at a specific side */ + VTR_ASSERT(validate_ipin_node_id(side, ipin_id)); + + /* if sorted, we give sorted edges + * if not sorted, we give the empty vector + */ + if (0 == ipin_node_in_edges_.size()) { + std::vector unsorted_edges; + + for (const RREdgeId& edge : rr_graph.node_in_edges(get_ipin_node(side, ipin_id))) { + unsorted_edges.push_back(edge); + } + + return unsorted_edges; + } + + return ipin_node_in_edges_[side_manager.to_size_t()][ipin_id]; +} + /* get the segment id of a channel rr_node */ RRSegmentId RRGSB::get_chan_node_segment(const e_side& side, const size_t& track_id) const { SideManager side_manager(side); @@ -787,6 +816,91 @@ void RRGSB::sort_chan_node_in_edges(const RRGraphView& rr_graph) { } } +void RRGSB::sort_ipin_node_in_edges(const RRGraphView& rr_graph, + const e_side& ipin_side, + const size_t& ipin_id) { + std::map> from_track_edge_map; + + const RRNodeId& ipin_node = ipin_node_[size_t(ipin_side)][ipin_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(ipin_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 */ + if (NUM_SIDES == side) { + VTR_LOG("GSB[%lu][%lu]:\n", get_x(), get_y()); + VTR_LOG("----------------------------------\n"); + VTR_LOG("SRC node:\n"); + VTR_LOG("Node info: %s\n", rr_graph.node_coordinate_to_string(src_node).c_str()); + VTR_LOG("Node ptc: %d\n", rr_graph.node_ptc_num(src_node)); + VTR_LOG("Fan-out nodes:\n"); + for (const auto& temp_edge : rr_graph.edge_range(src_node)) { + VTR_LOG("\t%s\n", rr_graph.node_coordinate_to_string(rr_graph.edge_sink_node(temp_edge)).c_str()); + } + VTR_LOG("\n----------------------------------\n"); + VTR_LOG("Channel node:\n"); + VTR_LOG("Node info: %s\n", rr_graph.node_coordinate_to_string(chan_node).c_str()); + VTR_LOG("Node ptc: %d\n", rr_graph.node_ptc_num(chan_node)); + VTR_LOG("Fan-in nodes:\n"); + for (const auto& temp_edge : rr_graph.node_in_edges(ipin_node)) { + VTR_LOG("\t%s\n", rr_graph.node_coordinate_to_string(rr_graph.edge_src_node(temp_edge)).c_str()); + } + } + + VTR_ASSERT(NUM_SIDES != side); + VTR_ASSERT(OPEN != index); + + 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) { + for (size_t iipin = 0; iipin < ipin_node_[side].size(); ++iipin) { + if ((0 < from_track_edge_map.count(side)) + && (0 < from_track_edge_map.at(side).count(ipin_id))) { + ipin_node_in_edges_[size_t(ipin_side)][ipin_id].push_back(from_track_edge_map[side][iipin]); + } + } + } + + VTR_ASSERT(edge_counter == ipin_node_in_edges_[size_t(ipin_side)][ipin_id].size()); +} + + + +void RRGSB::sort_ipin_node_in_edges(const RRGraphView& rr_graph) { + /* Allocate here, as sort edge is optional, we do not allocate when adding nodes */ + ipin_node_in_edges_.resize(get_num_sides()); + + for (size_t side = 0; side < get_num_sides(); ++side) { + SideManager side_manager(side); + ipin_node_in_edges_[side].resize(ipin_node_[side].get_chan_width()); + for (size_t ipin_id = 0; ipin_id < ipin_node_[side].size(); ++ipin_id) { + sort_ipin_node_in_edges(rr_graph, side_manager.get_side(), ipin_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 854bc37eae1..9c455301763 100644 --- a/vpr/src/tileable_rr_graph/rr_gsb.h +++ b/vpr/src/tileable_rr_graph/rr_gsb.h @@ -91,6 +91,11 @@ class RRGSB { const e_side& side, const size_t& track_id) const; + /* get all the sorted incoming edges for a IPIN rr_node at a given side and ipin_id */ + std::vector get_ipin_node_in_edges(const RRGraphView& rr_graph, + const e_side& side, + const size_t& ipin_id) const; + /* get the segment id of a channel rr_node */ RRSegmentId get_chan_node_segment(const e_side& side, const size_t& track_id) const; @@ -235,6 +240,8 @@ class RRGSB { * [chan_side][chan_node][edge_id_in_gsb_context] */ std::vector>> chan_node_in_edges_; + /* Sequence of edge ids for each input pin node. Same rules applied as the channel nodes */ + std::vector>> ipin_node_in_edges_; /* Logic Block Inputs data */ std::vector> ipin_node_; From 825d44437e94f49e34d0f1cecd5c124b4c504259 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 19 Sep 2022 12:14:04 -0700 Subject: [PATCH 094/147] [vpr] syntax --- vpr/src/tileable_rr_graph/rr_gsb.cpp | 6 +++--- vpr/src/tileable_rr_graph/rr_gsb.h | 7 +++++++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/vpr/src/tileable_rr_graph/rr_gsb.cpp b/vpr/src/tileable_rr_graph/rr_gsb.cpp index ceb92c9fc70..a0d35329b53 100644 --- a/vpr/src/tileable_rr_graph/rr_gsb.cpp +++ b/vpr/src/tileable_rr_graph/rr_gsb.cpp @@ -855,8 +855,8 @@ void RRGSB::sort_ipin_node_in_edges(const RRGraphView& rr_graph, } VTR_LOG("\n----------------------------------\n"); VTR_LOG("Channel node:\n"); - VTR_LOG("Node info: %s\n", rr_graph.node_coordinate_to_string(chan_node).c_str()); - VTR_LOG("Node ptc: %d\n", rr_graph.node_ptc_num(chan_node)); + VTR_LOG("Node info: %s\n", rr_graph.node_coordinate_to_string(ipin_node).c_str()); + VTR_LOG("Node ptc: %d\n", rr_graph.node_ptc_num(ipin_node)); VTR_LOG("Fan-in nodes:\n"); for (const auto& temp_edge : rr_graph.node_in_edges(ipin_node)) { VTR_LOG("\t%s\n", rr_graph.node_coordinate_to_string(rr_graph.edge_src_node(temp_edge)).c_str()); @@ -893,7 +893,7 @@ void RRGSB::sort_ipin_node_in_edges(const RRGraphView& rr_graph) { for (size_t side = 0; side < get_num_sides(); ++side) { SideManager side_manager(side); - ipin_node_in_edges_[side].resize(ipin_node_[side].get_chan_width()); + ipin_node_in_edges_[side].resize(ipin_node_[side].size()); for (size_t ipin_id = 0; ipin_id < ipin_node_[side].size(); ++ipin_id) { sort_ipin_node_in_edges(rr_graph, side_manager.get_side(), ipin_id); } diff --git a/vpr/src/tileable_rr_graph/rr_gsb.h b/vpr/src/tileable_rr_graph/rr_gsb.h index 9c455301763..6d2c718b8cb 100644 --- a/vpr/src/tileable_rr_graph/rr_gsb.h +++ b/vpr/src/tileable_rr_graph/rr_gsb.h @@ -182,6 +182,8 @@ class RRGSB { /* Sort all the incoming edges for routing channel rr_node */ void sort_chan_node_in_edges(const RRGraphView& rr_graph); + /* Sort all the incoming edges for input pin rr_node */ + void sort_ipin_node_in_edges(const RRGraphView& rr_graph); public: /* Mutators: cleaners */ void clear(); @@ -204,6 +206,11 @@ class RRGSB { const e_side& chan_side, const size_t& track_id); + /* Sort all the incoming edges for one input pin rr_node */ + void sort_ipin_node_in_edges(const RRGraphView& rr_graph, + const e_side& chan_side, + const size_t& ipin_id); + private: /* internal functions */ size_t get_track_id_first_short_connection(const RRGraphView& rr_graph, const e_side& node_side) const; From a8349b6f8086021c327a00d5c31cc06444eac2c7 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 19 Sep 2022 13:21:22 -0700 Subject: [PATCH 095/147] [vtr] fixed a bug when sorting in_edges for IPINs. --- vpr/src/tileable_rr_graph/rr_gsb.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/vpr/src/tileable_rr_graph/rr_gsb.cpp b/vpr/src/tileable_rr_graph/rr_gsb.cpp index a0d35329b53..267282060b3 100644 --- a/vpr/src/tileable_rr_graph/rr_gsb.cpp +++ b/vpr/src/tileable_rr_graph/rr_gsb.cpp @@ -838,9 +838,14 @@ void RRGSB::sort_ipin_node_in_edges(const RRGraphView& rr_graph, for (const RREdgeId& edge : rr_graph.node_in_edges(ipin_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); + /* The driver routing channel node can be either an input or an output to the GSB. + * Just try to find a qualified one. */ e_side side = NUM_SIDES; int index = 0; get_node_side_and_index(rr_graph, src_node, IN_PORT, side, index); + if (NUM_SIDES == side || OPEN == index) { + get_node_side_and_index(rr_graph, src_node, OUT_PORT, side, index); + } /* Must have valid side and index */ if (NUM_SIDES == side) { @@ -854,7 +859,7 @@ void RRGSB::sort_ipin_node_in_edges(const RRGraphView& rr_graph, VTR_LOG("\t%s\n", rr_graph.node_coordinate_to_string(rr_graph.edge_sink_node(temp_edge)).c_str()); } VTR_LOG("\n----------------------------------\n"); - VTR_LOG("Channel node:\n"); + VTR_LOG("IPIN node:\n"); VTR_LOG("Node info: %s\n", rr_graph.node_coordinate_to_string(ipin_node).c_str()); VTR_LOG("Node ptc: %d\n", rr_graph.node_ptc_num(ipin_node)); VTR_LOG("Fan-in nodes:\n"); From bb895cb73226336caff2eb49017ead3a3dc27f99 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 19 Sep 2022 13:30:54 -0700 Subject: [PATCH 096/147] [vpr] debugging --- vpr/src/tileable_rr_graph/rr_gsb.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/vpr/src/tileable_rr_graph/rr_gsb.cpp b/vpr/src/tileable_rr_graph/rr_gsb.cpp index 267282060b3..e0d900f3dd8 100644 --- a/vpr/src/tileable_rr_graph/rr_gsb.cpp +++ b/vpr/src/tileable_rr_graph/rr_gsb.cpp @@ -879,10 +879,10 @@ void RRGSB::sort_ipin_node_in_edges(const RRGraphView& rr_graph, /* Store the sorted edge */ for (size_t side = 0; side < get_num_sides(); ++side) { - for (size_t iipin = 0; iipin < ipin_node_[side].size(); ++iipin) { + 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(ipin_id))) { - ipin_node_in_edges_[size_t(ipin_side)][ipin_id].push_back(from_track_edge_map[side][iipin]); + && (0 < from_track_edge_map.at(side).count(itrack))) { + ipin_node_in_edges_[size_t(ipin_side)][ipin_id].push_back(from_track_edge_map[side][itrack]); } } } From 657624796fbdab8c69d14f788bd501a31ef35784 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 19 Sep 2022 14:51:55 -0700 Subject: [PATCH 097/147] [vtr] fixed a bug on sorting incoming edges for IPIN nodes: Only consider a limited sides because channel nodes could be duplicated on multiple sides --- vpr/src/tileable_rr_graph/rr_gsb.cpp | 33 ++++++++++++++-------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/vpr/src/tileable_rr_graph/rr_gsb.cpp b/vpr/src/tileable_rr_graph/rr_gsb.cpp index e0d900f3dd8..5fae25de8ad 100644 --- a/vpr/src/tileable_rr_graph/rr_gsb.cpp +++ b/vpr/src/tileable_rr_graph/rr_gsb.cpp @@ -819,7 +819,9 @@ void RRGSB::sort_chan_node_in_edges(const RRGraphView& rr_graph) { void RRGSB::sort_ipin_node_in_edges(const RRGraphView& rr_graph, const e_side& ipin_side, const size_t& ipin_id) { - std::map> from_track_edge_map; + std::map from_track_edge_map; + + e_side chan_side = get_cb_chan_side(ipin_side); const RRNodeId& ipin_node = ipin_node_[size_t(ipin_side)][ipin_id]; @@ -848,7 +850,7 @@ void RRGSB::sort_ipin_node_in_edges(const RRGraphView& rr_graph, } /* Must have valid side and index */ - if (NUM_SIDES == side) { + if (NUM_SIDES == side || side != chan_side) { VTR_LOG("GSB[%lu][%lu]:\n", get_x(), get_y()); VTR_LOG("----------------------------------\n"); VTR_LOG("SRC node:\n"); @@ -868,39 +870,36 @@ void RRGSB::sort_ipin_node_in_edges(const RRGraphView& rr_graph, } } - VTR_ASSERT(NUM_SIDES != side); + VTR_ASSERT(NUM_SIDES != side && side == chan_side); VTR_ASSERT(OPEN != index); VTR_ASSERT((CHANX == rr_graph.node_type(src_node)) || (CHANY == rr_graph.node_type(src_node))); - from_track_edge_map[side][index] = edge; + from_track_edge_map[index] = edge; edge_counter++; } /* Store the sorted edge */ - for (size_t side = 0; side < get_num_sides(); ++side) { - 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))) { - ipin_node_in_edges_[size_t(ipin_side)][ipin_id].push_back(from_track_edge_map[side][itrack]); - } + for (size_t itrack = 0; itrack < chan_node_[size_t(chan_side)].get_chan_width(); ++itrack) { + if (0 < from_track_edge_map.count(itrack)) { + ipin_node_in_edges_[size_t(ipin_side)][ipin_id].push_back(from_track_edge_map[itrack]); } } VTR_ASSERT(edge_counter == ipin_node_in_edges_[size_t(ipin_side)][ipin_id].size()); } - - void RRGSB::sort_ipin_node_in_edges(const RRGraphView& rr_graph) { /* Allocate here, as sort edge is optional, we do not allocate when adding nodes */ ipin_node_in_edges_.resize(get_num_sides()); - for (size_t side = 0; side < get_num_sides(); ++side) { - SideManager side_manager(side); - ipin_node_in_edges_[side].resize(ipin_node_[side].size()); - for (size_t ipin_id = 0; ipin_id < ipin_node_[side].size(); ++ipin_id) { - sort_ipin_node_in_edges(rr_graph, side_manager.get_side(), ipin_id); + for (t_rr_type cb_type : {CHANX, CHANY}) { + for (e_side ipin_side : get_cb_ipin_sides(cb_type)) { + SideManager side_manager(ipin_side); + ipin_node_in_edges_[size_t(ipin_side)].resize(ipin_node_[size_t(ipin_side)].size()); + for (size_t ipin_id = 0; ipin_id < ipin_node_[size_t(ipin_side)].size(); ++ipin_id) { + sort_ipin_node_in_edges(rr_graph, side_manager.get_side(), ipin_id); + } } } } From 332bc9085753b387773cfc37c31689705fa554f4 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 19 Sep 2022 15:05:28 -0700 Subject: [PATCH 098/147] [vpr] fixed a bug --- vpr/src/tileable_rr_graph/rr_gsb.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/vpr/src/tileable_rr_graph/rr_gsb.cpp b/vpr/src/tileable_rr_graph/rr_gsb.cpp index 5fae25de8ad..78de9164771 100644 --- a/vpr/src/tileable_rr_graph/rr_gsb.cpp +++ b/vpr/src/tileable_rr_graph/rr_gsb.cpp @@ -842,15 +842,14 @@ void RRGSB::sort_ipin_node_in_edges(const RRGraphView& rr_graph, const RRNodeId& src_node = rr_graph.edge_src_node(edge); /* The driver routing channel node can be either an input or an output to the GSB. * Just try to find a qualified one. */ - e_side side = NUM_SIDES; int index = 0; - get_node_side_and_index(rr_graph, src_node, IN_PORT, side, index); - if (NUM_SIDES == side || OPEN == index) { - get_node_side_and_index(rr_graph, src_node, OUT_PORT, side, index); + get_node_index(rr_graph, src_node, chan_side, IN_PORT); + if (OPEN == index) { + get_node_index(rr_graph, src_node, chan_side, OUT_PORT); } /* Must have valid side and index */ - if (NUM_SIDES == side || side != chan_side) { + if (OPEN == index) { VTR_LOG("GSB[%lu][%lu]:\n", get_x(), get_y()); VTR_LOG("----------------------------------\n"); VTR_LOG("SRC node:\n"); @@ -870,7 +869,6 @@ void RRGSB::sort_ipin_node_in_edges(const RRGraphView& rr_graph, } } - VTR_ASSERT(NUM_SIDES != side && side == chan_side); VTR_ASSERT(OPEN != index); VTR_ASSERT((CHANX == rr_graph.node_type(src_node)) From 2f1bfd32080e81c63b0ea3116fbafff2f085202e Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 19 Sep 2022 15:35:06 -0700 Subject: [PATCH 099/147] [vtr] fixed a bug --- vpr/src/tileable_rr_graph/rr_gsb.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/vpr/src/tileable_rr_graph/rr_gsb.cpp b/vpr/src/tileable_rr_graph/rr_gsb.cpp index 78de9164771..78b1e51c60e 100644 --- a/vpr/src/tileable_rr_graph/rr_gsb.cpp +++ b/vpr/src/tileable_rr_graph/rr_gsb.cpp @@ -842,10 +842,10 @@ void RRGSB::sort_ipin_node_in_edges(const RRGraphView& rr_graph, const RRNodeId& src_node = rr_graph.edge_src_node(edge); /* The driver routing channel node can be either an input or an output to the GSB. * Just try to find a qualified one. */ - int index = 0; - get_node_index(rr_graph, src_node, chan_side, IN_PORT); + int index = OPEN; + index = get_node_index(rr_graph, src_node, chan_side, IN_PORT); if (OPEN == index) { - get_node_index(rr_graph, src_node, chan_side, OUT_PORT); + index = get_node_index(rr_graph, src_node, chan_side, OUT_PORT); } /* Must have valid side and index */ From d3a80393684234a4b53279cf383bace369cc854f Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 26 Sep 2022 14:01:44 -0700 Subject: [PATCH 100/147] [lib] replace the use of SIGSTKSZ which is not supported in Ubuntu 21.04+ --- .../src/catch2/internal/catch_fatal_condition_handler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/EXTERNAL/libcatch2/src/catch2/internal/catch_fatal_condition_handler.cpp b/libs/EXTERNAL/libcatch2/src/catch2/internal/catch_fatal_condition_handler.cpp index 9383257cecb..4f35b27b7a5 100644 --- a/libs/EXTERNAL/libcatch2/src/catch2/internal/catch_fatal_condition_handler.cpp +++ b/libs/EXTERNAL/libcatch2/src/catch2/internal/catch_fatal_condition_handler.cpp @@ -202,7 +202,7 @@ namespace Catch { FatalConditionHandler::FatalConditionHandler() { assert(!altStackMem && "Cannot initialize POSIX signal handler when one already exists"); if (altStackSize == 0) { - altStackSize = std::max(static_cast(SIGSTKSZ), minStackSizeForErrors); + altStackSize = std::max(static_cast(/*SIGSTKSZ*/32768), minStackSizeForErrors); } altStackMem = new char[altStackSize](); } From 1a8c8757c32bc2cac93609a6bb9d8bc0cb3248b7 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 30 Sep 2022 15:21:38 -0700 Subject: [PATCH 101/147] [vpr] fixed a bug in finding direct connection in tileable rr_graph; Remove verbose outputs --- .../openfpga_rr_graph_utils.cpp | 2 +- .../tileable_rr_graph_edge_builder.cpp | 1 - .../tileable_rr_graph_gsb.cpp | 23 +++++++++---------- 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/vpr/src/tileable_rr_graph/openfpga_rr_graph_utils.cpp b/vpr/src/tileable_rr_graph/openfpga_rr_graph_utils.cpp index da17b51b2fc..ea3b52a5440 100644 --- a/vpr/src/tileable_rr_graph/openfpga_rr_graph_utils.cpp +++ b/vpr/src/tileable_rr_graph/openfpga_rr_graph_utils.cpp @@ -149,7 +149,7 @@ bool is_opin_direct_connected_ipin(const RRGraphView& rr_graph, VTR_ASSERT(1 == rr_graph.node_out_edges(node).size()); for (auto edge : rr_graph.node_out_edges(node)) { - const RRNodeId& sink_node = rr_graph.edge_sink_node(RREdgeId(edge)); + const RRNodeId& sink_node = rr_graph.edge_sink_node(node, edge); if (IPIN != rr_graph.node_type(sink_node)) { return false; } diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp index a30fc51fe35..5d6345ba8ab 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp @@ -150,7 +150,6 @@ void build_rr_graph_edges(const RRGraphView& rr_graph, rr_graph_builder.build_edges(true); } } - VTR_LOG("Number of edges to create: %ld\n", num_edges_to_create); } /************************************************************************ diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp index d33e1a0f84d..8a17720dd7b 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp @@ -968,7 +968,6 @@ void build_edges_for_one_tileable_rr_gsb(RRGraphBuilder& rr_graph_builder, } } } - VTR_LOG("Number of edges to create for gsb[%ld][%ld]: %ld\n", rr_gsb.get_x(), rr_gsb.get_y(), edge_count); num_edges_to_create += edge_count; } @@ -1420,23 +1419,23 @@ void build_direct_connections_for_one_gsb(const RRGraphView& rr_graph, std::vector ipin_grid_side = find_grid_pin_sides(grids[to_grid_coordinate.x()][to_grid_coordinate.y()], ipin); VTR_ASSERT(1 == ipin_grid_side.size()); - const RRNodeId& opin_node_id = rr_graph.node_lookup().find_node(from_grid_coordinate.x() - from_grid_width_ofs, + RRNodeId opin_node_id = rr_graph.node_lookup().find_node(from_grid_coordinate.x() - from_grid_width_ofs, from_grid_coordinate.y() - from_grid_height_ofs, OPIN, opin, opin_grid_side[0]); - const RRNodeId& ipin_node_id = rr_graph.node_lookup().find_node(to_grid_coordinate.x() - to_grid_width_ofs, + RRNodeId ipin_node_id = rr_graph.node_lookup().find_node(to_grid_coordinate.x() - to_grid_width_ofs, to_grid_coordinate.y() - to_grid_height_ofs, IPIN, ipin, ipin_grid_side[0]); - /* - * VTR_LOG("Direct connection: from grid[%lu][%lu].pin[%lu] at side %s to grid[%lu][%lu].pin[%lu] at side %s\n", - * from_grid_coordinate.x() - from_grid_width_ofs, - * from_grid_coordinate.y() - from_grid_height_ofs, - * opin, SIDE_STRING[opin_grid_side[0]], - * to_grid_coordinate.x() - to_grid_width_ofs, - * to_grid_coordinate.y() - to_grid_height_ofs, - * ipin, SIDE_STRING[ipin_grid_side[0]]); - */ + + VTR_LOG("Direct connection: from grid[%lu][%lu].pin[%lu] at side %s to grid[%lu][%lu].pin[%lu] at side %s\n", + from_grid_coordinate.x() - from_grid_width_ofs, + from_grid_coordinate.y() - from_grid_height_ofs, + opin, SIDE_STRING[opin_grid_side[0]], + to_grid_coordinate.x() - to_grid_width_ofs, + to_grid_coordinate.y() - to_grid_height_ofs, + ipin, SIDE_STRING[ipin_grid_side[0]]); /* add edges to the opin_node */ + VTR_ASSERT(opin_node_id && ipin_node_id); rr_graph_builder.create_edge(opin_node_id, ipin_node_id, delayless_switch); } } From 970afa5b96231272b305bbc3112ee9af662477ea Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 30 Sep 2022 15:26:37 -0700 Subject: [PATCH 102/147] [vpr] remove verbose outputs --- vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp | 2 -- vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp | 3 ++- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp index 5d6345ba8ab..b009874badf 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp @@ -47,7 +47,6 @@ void build_rr_graph_edges_for_source_nodes(const RRGraphView& rr_graph, } /* Allocate edges for all the source nodes */ rr_graph_builder.build_edges(true); - VTR_LOG("Number of edges to create for source nodes: %ld\n", edge_count); num_edges_to_create += edge_count; } @@ -83,7 +82,6 @@ void build_rr_graph_edges_for_sink_nodes(const RRGraphView& rr_graph, } /* Allocate edges for all the source nodes */ rr_graph_builder.build_edges(true); - VTR_LOG("Number of edges to create for sink nodes: %ld\n", edge_count); num_edges_to_create += edge_count; } diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp index 8a17720dd7b..b91d6426e2c 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp @@ -1425,7 +1425,7 @@ void build_direct_connections_for_one_gsb(const RRGraphView& rr_graph, RRNodeId ipin_node_id = rr_graph.node_lookup().find_node(to_grid_coordinate.x() - to_grid_width_ofs, to_grid_coordinate.y() - to_grid_height_ofs, IPIN, ipin, ipin_grid_side[0]); - + /* VTR_LOG("Direct connection: from grid[%lu][%lu].pin[%lu] at side %s to grid[%lu][%lu].pin[%lu] at side %s\n", from_grid_coordinate.x() - from_grid_width_ofs, from_grid_coordinate.y() - from_grid_height_ofs, @@ -1433,6 +1433,7 @@ void build_direct_connections_for_one_gsb(const RRGraphView& rr_graph, to_grid_coordinate.x() - to_grid_width_ofs, to_grid_coordinate.y() - to_grid_height_ofs, ipin, SIDE_STRING[ipin_grid_side[0]]); + */ /* add edges to the opin_node */ VTR_ASSERT(opin_node_id && ipin_node_id); From c33574d8db85efbc664798034992d43a7e49de77 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 3 Oct 2022 11:08:31 -0700 Subject: [PATCH 103/147] [CMake] Added an option 'VTR_ENABLE_VERSION_UP_TO_DATE' which allows users to skip version build (by default is always on). This can reduce build time when use VTR as a submodule --- CMakeLists.txt | 1 + libs/libvtrutil/CMakeLists.txt | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6dc4c952d47..7fb08dac96e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,6 +31,7 @@ option(VTR_ENABLE_SANITIZE "Enable address/leak/undefined-behaviour sanitizers ( option(VTR_ENABLE_PROFILING "Enable performance profiler (gprof)" OFF) option(VTR_ENABLE_COVERAGE "Enable code coverage tracking (gcov)" OFF) option(VTR_ENABLE_DEBUG_LOGGING "Enable debug logging" OFF) +option(VTR_ENABLE_VERSION_UP_TO_DATE "Enable version number up-to-date during compilation" ON) #Allow the user to decide whether to compile the graphics library set(VPR_USE_EZGL "auto" CACHE STRING "Specify whether vpr uses the graphics library") diff --git a/libs/libvtrutil/CMakeLists.txt b/libs/libvtrutil/CMakeLists.txt index 6e69ae53085..08bac8b8d64 100644 --- a/libs/libvtrutil/CMakeLists.txt +++ b/libs/libvtrutil/CMakeLists.txt @@ -98,7 +98,9 @@ target_include_directories(libvtrutil PUBLIC ${LIB_INCLUDE_DIRS}) set_target_properties(libvtrutil PROPERTIES PREFIX "") #Avoid extra 'lib' prefix #Ensure version is always up to date by requiring version to be run first -add_dependencies(libvtrutil version) +if (VTR_ENABLE_VERSION_UP_TO_DATE) + add_dependencies(libvtrutil version) +endif() #Specify link-time dependancies target_link_libraries(libvtrutil From 147200b1edce48a22705f470c9fa937cb56e1b10 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 3 Oct 2022 11:18:06 -0700 Subject: [PATCH 104/147] [cmake] bypass custom build on version number with an option --- libs/libvtrutil/CMakeLists.txt | 37 +++++++++++++++++----------------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/libs/libvtrutil/CMakeLists.txt b/libs/libvtrutil/CMakeLists.txt index 08bac8b8d64..ba4df59e77d 100644 --- a/libs/libvtrutil/CMakeLists.txt +++ b/libs/libvtrutil/CMakeLists.txt @@ -61,24 +61,25 @@ endif() # 2) The custom command depends on the touched version input file and generates the processed # version file, with updated values. The custom command uses the configure_version.cmake # script to generate the up-to-date vtr_version.cpp -add_custom_target(version ALL - COMMAND ${CMAKE_COMMAND} -E touch ${VTR_VERSION_FILE_IN}) - -add_custom_command(OUTPUT ${VTR_VERSION_FILE_OUT} - COMMAND ${CMAKE_COMMAND} - -D IN_FILE=${VTR_VERSION_FILE_IN} - -D OUT_FILE=${VTR_VERSION_FILE_OUT} - -D VTR_VERSION_MAJOR=${VTR_VERSION_MAJOR} - -D VTR_VERSION_MINOR=${VTR_VERSION_MINOR} - -D VTR_VERSION_PATCH=${VTR_VERSION_PATCH} - -D VTR_VERSION_PRERELEASE=${VTR_VERSION_PRERELEASE} - -D VTR_COMPILER_INFO=${VTR_COMPILER_INFO} - -D VTR_BUILD_INFO=${VTR_BUILD_INFO} - -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules/configure_version.cmake - MAIN_DEPENDENCY ${VTR_VERSION_FILE_IN} - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - VERBATIM) - +if (VTR_ENABLE_VERSION_UP_TO_DATE) + add_custom_target(version ALL + COMMAND ${CMAKE_COMMAND} -E touch ${VTR_VERSION_FILE_IN}) + + add_custom_command(OUTPUT ${VTR_VERSION_FILE_OUT} + COMMAND ${CMAKE_COMMAND} + -D IN_FILE=${VTR_VERSION_FILE_IN} + -D OUT_FILE=${VTR_VERSION_FILE_OUT} + -D VTR_VERSION_MAJOR=${VTR_VERSION_MAJOR} + -D VTR_VERSION_MINOR=${VTR_VERSION_MINOR} + -D VTR_VERSION_PATCH=${VTR_VERSION_PATCH} + -D VTR_VERSION_PRERELEASE=${VTR_VERSION_PRERELEASE} + -D VTR_COMPILER_INFO=${VTR_COMPILER_INFO} + -D VTR_BUILD_INFO=${VTR_BUILD_INFO} + -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules/configure_version.cmake + MAIN_DEPENDENCY ${VTR_VERSION_FILE_IN} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + VERBATIM) +endif() # # Source files and library From 942d1bbfff837d9c5409f6f0932dec574fb7e7c2 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 3 Oct 2022 11:36:29 -0700 Subject: [PATCH 105/147] [cmake] rename option to be short 'VTR_ENABLE_VERSION' --- CMakeLists.txt | 2 +- libs/libvtrutil/CMakeLists.txt | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7fb08dac96e..c050a83931a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,7 +31,7 @@ option(VTR_ENABLE_SANITIZE "Enable address/leak/undefined-behaviour sanitizers ( option(VTR_ENABLE_PROFILING "Enable performance profiler (gprof)" OFF) option(VTR_ENABLE_COVERAGE "Enable code coverage tracking (gcov)" OFF) option(VTR_ENABLE_DEBUG_LOGGING "Enable debug logging" OFF) -option(VTR_ENABLE_VERSION_UP_TO_DATE "Enable version number up-to-date during compilation" ON) +option(VTR_ENABLE_VERSION "Enable version number up-to-date during compilation" ON) #Allow the user to decide whether to compile the graphics library set(VPR_USE_EZGL "auto" CACHE STRING "Specify whether vpr uses the graphics library") diff --git a/libs/libvtrutil/CMakeLists.txt b/libs/libvtrutil/CMakeLists.txt index ba4df59e77d..a624c1b1a8c 100644 --- a/libs/libvtrutil/CMakeLists.txt +++ b/libs/libvtrutil/CMakeLists.txt @@ -61,7 +61,7 @@ endif() # 2) The custom command depends on the touched version input file and generates the processed # version file, with updated values. The custom command uses the configure_version.cmake # script to generate the up-to-date vtr_version.cpp -if (VTR_ENABLE_VERSION_UP_TO_DATE) +if (VTR_ENABLE_VERSION) add_custom_target(version ALL COMMAND ${CMAKE_COMMAND} -E touch ${VTR_VERSION_FILE_IN}) @@ -79,6 +79,9 @@ if (VTR_ENABLE_VERSION_UP_TO_DATE) MAIN_DEPENDENCY ${VTR_VERSION_FILE_IN} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} VERBATIM) +else() +# Just copy the input file to output file with version number + configure_file(${VTR_VERSION_FILE_IN} ${VTR_VERSION_FILE_OUT}) endif() # @@ -99,7 +102,7 @@ target_include_directories(libvtrutil PUBLIC ${LIB_INCLUDE_DIRS}) set_target_properties(libvtrutil PROPERTIES PREFIX "") #Avoid extra 'lib' prefix #Ensure version is always up to date by requiring version to be run first -if (VTR_ENABLE_VERSION_UP_TO_DATE) +if (VTR_ENABLE_VERSION) add_dependencies(libvtrutil version) endif() From 69773dbfbbcf682084be44cca2251d0f3e2e41ff Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 3 Oct 2022 21:01:49 -0700 Subject: [PATCH 106/147] [vpr] enable tileable rr_graph when building routing structs --- vpr/src/route/route_common.cpp | 4 ++++ vpr/src/route/router_delay_profiling.cpp | 3 +++ 2 files changed, 7 insertions(+) diff --git a/vpr/src/route/route_common.cpp b/vpr/src/route/route_common.cpp index e8e4f05c1c7..ee94f96d681 100644 --- a/vpr/src/route/route_common.cpp +++ b/vpr/src/route/route_common.cpp @@ -213,6 +213,10 @@ void try_graph(int width_fac, const t_router_opts& router_opts, t_det_routing_ar graph_directionality = GRAPH_BIDIR; } else { graph_type = (det_routing_arch->directionality == BI_DIRECTIONAL ? GRAPH_BIDIR : GRAPH_UNIDIR); + /* Branch on tileable routing */ + if (det_routing_arch->directionality == UNI_DIRECTIONAL && det_routing_arch->tileable) { + graph_type = GRAPH_UNIDIR_TILEABLE; + } graph_directionality = (det_routing_arch->directionality == BI_DIRECTIONAL ? GRAPH_BIDIR : GRAPH_UNIDIR); } diff --git a/vpr/src/route/router_delay_profiling.cpp b/vpr/src/route/router_delay_profiling.cpp index 50578ff1f9a..2e990a96455 100644 --- a/vpr/src/route/router_delay_profiling.cpp +++ b/vpr/src/route/router_delay_profiling.cpp @@ -221,6 +221,9 @@ void alloc_routing_structs(t_chan_width chan_width, graph_type = GRAPH_GLOBAL; } else { graph_type = (det_routing_arch->directionality == BI_DIRECTIONAL ? GRAPH_BIDIR : GRAPH_UNIDIR); + if ((UNI_DIRECTIONAL == det_routing_arch->directionality) && (true == det_routing_arch->tileable)) { + graph_type = GRAPH_UNIDIR_TILEABLE; + } } create_rr_graph(graph_type, From c70f97b7db73563fe881ab35713cf933c155fcfc Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 3 Oct 2022 21:15:50 -0700 Subject: [PATCH 107/147] [vpr] code format --- libs/libarchfpga/src/read_xml_arch_file.cpp | 2 +- .../rr_graph_builder_utils.cpp | 4 ++-- vpr/src/tileable_rr_graph/rr_gsb.cpp | 6 ++--- vpr/src/tileable_rr_graph/rr_gsb.h | 2 +- .../tileable_rr_graph_gsb.cpp | 18 ++++----------- .../tileable_rr_graph_node_builder.cpp | 23 +++++++++---------- 6 files changed, 21 insertions(+), 34 deletions(-) diff --git a/libs/libarchfpga/src/read_xml_arch_file.cpp b/libs/libarchfpga/src/read_xml_arch_file.cpp index edf257f0e3d..541cf23a121 100644 --- a/libs/libarchfpga/src/read_xml_arch_file.cpp +++ b/libs/libarchfpga/src/read_xml_arch_file.cpp @@ -3453,7 +3453,7 @@ static void ProcessPinLocations(pugi::xml_node Locations, if (inst_lsb < 0 || inst_msb > PhysicalTileType->capacity - 1) { archfpga_throw(loc_data.filename_c_str(), loc_data.line(Locations), "Pin location specification '%s' contain an out-of-range instance. Expect [%d:%d]", - token.c_str(), 0 , PhysicalTileType->capacity - 1); + token.c_str(), 0, PhysicalTileType->capacity - 1); } } diff --git a/vpr/src/tileable_rr_graph/rr_graph_builder_utils.cpp b/vpr/src/tileable_rr_graph/rr_graph_builder_utils.cpp index c2fb1a580d4..a97b37e2d88 100644 --- a/vpr/src/tileable_rr_graph/rr_graph_builder_utils.cpp +++ b/vpr/src/tileable_rr_graph/rr_graph_builder_utils.cpp @@ -282,8 +282,8 @@ bool is_chanx_left_to_multi_height_grid(const DeviceGrid& grids, VTR_ASSERT(chanx_coord.x() < grids.width() - 1); if (grids.width() - 2 == chanx_coord.x()) { /* This is already the RIGHT side of FPGA fabric, - * it is the same results as chanx is right to a multi-height grid - */ + * it is the same results as chanx is right to a multi-height grid + */ return true; } diff --git a/vpr/src/tileable_rr_graph/rr_gsb.cpp b/vpr/src/tileable_rr_graph/rr_gsb.cpp index 78b1e51c60e..901a9c0bef7 100644 --- a/vpr/src/tileable_rr_graph/rr_gsb.cpp +++ b/vpr/src/tileable_rr_graph/rr_gsb.cpp @@ -844,7 +844,7 @@ void RRGSB::sort_ipin_node_in_edges(const RRGraphView& rr_graph, * Just try to find a qualified one. */ int index = OPEN; index = get_node_index(rr_graph, src_node, chan_side, IN_PORT); - if (OPEN == index) { + if (OPEN == index) { index = get_node_index(rr_graph, src_node, chan_side, OUT_PORT); } @@ -871,8 +871,7 @@ void RRGSB::sort_ipin_node_in_edges(const RRGraphView& rr_graph, VTR_ASSERT(OPEN != index); - VTR_ASSERT((CHANX == rr_graph.node_type(src_node)) - || (CHANY == rr_graph.node_type(src_node))); + VTR_ASSERT(CHANX == rr_graph.node_type(src_node) || CHANY == rr_graph.node_type(src_node)); from_track_edge_map[index] = edge; edge_counter++; } @@ -902,7 +901,6 @@ void RRGSB::sort_ipin_node_in_edges(const RRGraphView& rr_graph) { } } - /************************************************************************ * 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 6d2c718b8cb..77f7b192cd0 100644 --- a/vpr/src/tileable_rr_graph/rr_gsb.h +++ b/vpr/src/tileable_rr_graph/rr_gsb.h @@ -138,7 +138,7 @@ class RRGSB { * on being a mirror of the current one */ bool is_sb_mirrorable(const RRGraphView& rr_graph, const RRGSB& cand) const; - + public: /* Cooridinator conversion and output */ size_t get_x() const; /* get the x coordinate of this switch block */ size_t get_y() const; /* get the y coordinate of this switch block */ diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp index b91d6426e2c..e039fbf7418 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp @@ -158,7 +158,6 @@ static bool is_gsb_in_track_sb_population(const RRGraphView& rr_graph, /* Get segment id */ RRSegmentId seg_id = rr_gsb.get_chan_node_segment(gsb_side, track_id); /* validate offset */ - if (!(offset < segment_inf[size_t(seg_id)].sb.size())) VTR_ASSERT(offset < segment_inf[size_t(seg_id)].sb.size()); /* Get the SB population */ @@ -1420,20 +1419,11 @@ void build_direct_connections_for_one_gsb(const RRGraphView& rr_graph, VTR_ASSERT(1 == ipin_grid_side.size()); RRNodeId opin_node_id = rr_graph.node_lookup().find_node(from_grid_coordinate.x() - from_grid_width_ofs, - from_grid_coordinate.y() - from_grid_height_ofs, - OPIN, opin, opin_grid_side[0]); + from_grid_coordinate.y() - from_grid_height_ofs, + OPIN, opin, opin_grid_side[0]); RRNodeId ipin_node_id = rr_graph.node_lookup().find_node(to_grid_coordinate.x() - to_grid_width_ofs, - to_grid_coordinate.y() - to_grid_height_ofs, - IPIN, ipin, ipin_grid_side[0]); - /* - VTR_LOG("Direct connection: from grid[%lu][%lu].pin[%lu] at side %s to grid[%lu][%lu].pin[%lu] at side %s\n", - from_grid_coordinate.x() - from_grid_width_ofs, - from_grid_coordinate.y() - from_grid_height_ofs, - opin, SIDE_STRING[opin_grid_side[0]], - to_grid_coordinate.x() - to_grid_width_ofs, - to_grid_coordinate.y() - to_grid_height_ofs, - ipin, SIDE_STRING[ipin_grid_side[0]]); - */ + to_grid_coordinate.y() - to_grid_height_ofs, + IPIN, ipin, ipin_grid_side[0]); /* add edges to the opin_node */ VTR_ASSERT(opin_node_id && ipin_node_id); diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp index 7421574705b..e3b063a33ff 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp @@ -603,15 +603,15 @@ static void load_grid_nodes_basic_info(RRGraphBuilder& rr_graph_builder, } for (e_side side : wanted_sides) { - for (int width_offset = 0; width_offset < grids[ix][iy].type->width; ++width_offset) { - int x_tile = ix + width_offset; - for (int height_offset = 0; height_offset < grids[ix][iy].type->height; ++height_offset) { - int y_tile = iy + height_offset; - rr_graph_builder.node_lookup().reserve_nodes(x_tile, y_tile, OPIN, grids[ix][iy].type->num_pins, side); - rr_graph_builder.node_lookup().reserve_nodes(x_tile, y_tile, IPIN, grids[ix][iy].type->num_pins, side); - } - } - } + for (int width_offset = 0; width_offset < grids[ix][iy].type->width; ++width_offset) { + int x_tile = ix + width_offset; + for (int height_offset = 0; height_offset < grids[ix][iy].type->height; ++height_offset) { + int y_tile = iy + height_offset; + rr_graph_builder.node_lookup().reserve_nodes(x_tile, y_tile, OPIN, grids[ix][iy].type->num_pins, side); + rr_graph_builder.node_lookup().reserve_nodes(x_tile, y_tile, IPIN, grids[ix][iy].type->num_pins, side); + } + } + } /* Configure source rr_nodes for this grid */ load_one_grid_source_nodes_basic_info(rr_graph_builder, @@ -1013,8 +1013,7 @@ static void reverse_dec_chan_rr_node_track_ids(const RRGraphView& rr_graph, // this should call rr_graph_builder to do the job for (const RRNodeId& node : rr_graph.nodes()) { /* Bypass condition: only focus on CHANX and CHANY in DEC_DIRECTION */ - if ( (CHANX != rr_graph.node_type(node)) - && (CHANY != rr_graph.node_type(node)) ) { + if (CHANX != rr_graph.node_type(node) && CHANY != rr_graph.node_type(node)) { continue; } /* Reach here, we must have a node of CHANX or CHANY */ @@ -1022,7 +1021,7 @@ static void reverse_dec_chan_rr_node_track_ids(const RRGraphView& rr_graph, continue; } std::reverse(rr_node_track_ids[node].begin(), - rr_node_track_ids[node].end() ); + rr_node_track_ids[node].end()); } } From 3264072d5d4b646efaef911095767d58b5647461 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 1 Nov 2022 15:44:44 -0700 Subject: [PATCH 108/147] [vpr] a more sophiscated version of read blif api --- vpr/src/base/read_blif.cpp | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/vpr/src/base/read_blif.cpp b/vpr/src/base/read_blif.cpp index 2425a18d239..33d953cf111 100644 --- a/vpr/src/base/read_blif.cpp +++ b/vpr/src/base/read_blif.cpp @@ -718,19 +718,16 @@ bool is_binary_param(const std::string& param) { return true; } -bool is_real_param(const std::string& param) { - const std::string chars = "012345678."; - +bool is_real_param(const std::string ¶m) { /* Must be non-empty */ if (param.empty()) { return false; } - /* The string mustn't contain any other chars that the expected ones */ - for (size_t i = 0; i < param.length(); ++i) { - if (chars.find(param[i]) == std::string::npos) { - return false; - } + /* The string must match the regular expression */ + static const std::regex real_number_expr("[+-]?([0-9]*\\.[0-9]+)|([0-9]+\\.[0-9]*)"); + if (!std::regex_match(param, real_number_expr)) { + return false; } /* This is a real number param */ From c1622751a7d24ef60ca3bf2b03d511682d669325 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 1 Nov 2022 15:58:24 -0700 Subject: [PATCH 109/147] [test] update golden for new test --- .../strong_tileable_rr_graph/config/golden_results.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_tileable_rr_graph/config/golden_results.txt b/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_tileable_rr_graph/config/golden_results.txt index 7abe3a1a1c3..8576e7f7dc7 100644 --- a/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_tileable_rr_graph/config/golden_results.txt +++ b/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_tileable_rr_graph/config/golden_results.txt @@ -1,4 +1,4 @@ - arch circuit script_params vtr_flow_elapsed_time error odin_synth_time max_odin_mem abc_depth abc_synth_time abc_cec_time abc_sec_time max_abc_mem ace_time max_ace_mem num_clb num_io num_memories num_mult vpr_status vpr_revision vpr_build_info vpr_compiler vpr_compiled hostname rundir max_vpr_mem num_primary_inputs num_primary_outputs num_pre_packed_nets num_pre_packed_blocks num_netlist_clocks num_post_packed_nets num_post_packed_blocks device_width device_height device_grid_tiles device_limiting_resources device_name pack_time placed_wirelength_est place_time place_quench_time placed_CPD_est placed_setup_TNS_est placed_setup_WNS_est placed_geomean_nonvirtual_intradomain_critical_path_delay_est place_delay_matrix_lookup_time place_quench_timing_analysis_time place_quench_sta_time place_total_timing_analysis_time place_total_sta_time min_chan_width routed_wirelength min_chan_width_route_success_iteration logic_block_area_total logic_block_area_used min_chan_width_routing_area_total min_chan_width_routing_area_per_tile min_chan_width_route_time min_chan_width_total_timing_analysis_time min_chan_width_total_sta_time crit_path_routed_wirelength crit_path_route_success_iteration crit_path_total_nets_routed crit_path_total_connections_routed crit_path_total_heap_pushes crit_path_total_heap_pops critical_path_delay geomean_nonvirtual_intradomain_critical_path_delay setup_TNS setup_WNS hold_TNS hold_WNS crit_path_routing_area_total crit_path_routing_area_per_tile router_lookahead_computation_time crit_path_route_time crit_path_total_timing_analysis_time crit_path_total_sta_time placement_technique reward uniform_percentage median_percentage wmedian_percentage wcent_percentage fr_percentage critUni_percentage centroid_percentage - k4_N4_90nm.xml diffeq.blif common 6.72 -1 -1 -1 -1 -1 -1 -1 -1 -1 417 64 -1 -1 success v8.0.0-3198-gd038c933b release VTR_ASSERT_LEVEL=2 GNU 7.5.0 on Linux-4.15.0-60-generic x86_64 2021-01-02T13:20:16 betzgrp-wintermute.eecg.utoronto.ca /home/elgamma8/research/gold/vtr-verilog-to-routing 87228 64 39 1935 1974 1 1104 520 23 23 529 clb auto 0.40 10030 0.93 0.01 6.59694 -1414.7 -6.59694 6.59694 0.45 0.00189405 0.00143772 0.221979 0.167805 24 12059 26 983127 929624 797780. 1508.09 2.59 0.588243 0.472549 11020 20 7062 23191 1573824 393127 6.8984 6.8984 -1529.52 -6.8984 0 0 1.04508e+06 1975.57 0.13 0.43 0.131471 0.112481 simple RL 'Softmax agent' -1 -1 -1 -1 -1 -1 -1 -1 - k4_N4_90nm.xml ex5p.blif common 16.92 -1 -1 -1 -1 -1 -1 -1 -1 -1 346 8 -1 -1 success v8.0.0-3198-gd038c933b release VTR_ASSERT_LEVEL=2 GNU 7.5.0 on Linux-4.15.0-60-generic x86_64 2021-01-02T13:20:16 betzgrp-wintermute.eecg.utoronto.ca /home/elgamma8/research/gold/vtr-verilog-to-routing 68688 8 63 1072 1135 0 909 417 21 21 441 clb auto 0.17 11681 0.71 0.01 6.75152 -301.537 -6.75152 nan 0.34 0.00117768 0.000911645 0.136814 0.106107 34 15896 33 804782 771343 910617. 2064.89 13.76 0.477973 0.383445 13620 21 8417 29539 3341244 830781 6.81396 nan -313.113 -6.81396 0 0 1.15594e+06 2621.17 0.13 0.55 0.0731153 0.0639044 simple RL 'Softmax agent' -1 -1 -1 -1 -1 -1 -1 -1 - k4_N4_90nm.xml s298.blif common 11.05 -1 -1 -1 -1 -1 -1 -1 -1 -1 571 4 -1 -1 success v8.0.0-3198-gd038c933b release VTR_ASSERT_LEVEL=2 GNU 7.5.0 on Linux-4.15.0-60-generic x86_64 2021-01-02T13:20:16 betzgrp-wintermute.eecg.utoronto.ca /home/elgamma8/research/gold/vtr-verilog-to-routing 78820 4 6 1942 1948 1 1193 581 26 26 676 clb auto 0.31 14228 1.11 0.01 11.6554 -90.3611 -11.6554 11.6554 0.56 0.00215172 0.00157042 0.245315 0.182305 26 18055 30 1.28409e+06 1.27294e+06 1.12979e+06 1671.28 6.01 0.62371 0.489649 16623 19 8342 42276 3817766 734253 11.5305 11.5305 -91.3072 -11.5305 0 0 1.43821e+06 2127.53 0.31 0.73 0.120758 0.1047 simple RL 'Softmax agent' -1 -1 -1 -1 -1 -1 -1 -1 +arch circuit script_params vtr_flow_elapsed_time vtr_max_mem_stage vtr_max_mem error odin_synth_time max_odin_mem yosys_synth_time max_yosys_mem abc_depth abc_synth_time abc_cec_time abc_sec_time max_abc_mem ace_time max_ace_mem num_clb num_io num_memories num_mult vpr_status vpr_revision vpr_build_info vpr_compiler vpr_compiled hostname rundir max_vpr_mem num_primary_inputs num_primary_outputs num_pre_packed_nets num_pre_packed_blocks num_netlist_clocks num_post_packed_nets num_post_packed_blocks device_width device_height device_grid_tiles device_limiting_resources device_name pack_mem pack_time placed_wirelength_est place_mem place_time place_quench_time placed_CPD_est placed_setup_TNS_est placed_setup_WNS_est placed_geomean_nonvirtual_intradomain_critical_path_delay_est place_delay_matrix_lookup_time place_quench_timing_analysis_time place_quench_sta_time place_total_timing_analysis_time place_total_sta_time min_chan_width routed_wirelength min_chan_width_route_success_iteration logic_block_area_total logic_block_area_used min_chan_width_routing_area_total min_chan_width_routing_area_per_tile min_chan_width_route_time min_chan_width_total_timing_analysis_time min_chan_width_total_sta_time crit_path_routed_wirelength crit_path_route_success_iteration crit_path_total_nets_routed crit_path_total_connections_routed crit_path_total_heap_pushes crit_path_total_heap_pops critical_path_delay geomean_nonvirtual_intradomain_critical_path_delay setup_TNS setup_WNS hold_TNS hold_WNS crit_path_routing_area_total crit_path_routing_area_per_tile router_lookahead_computation_time crit_path_route_time crit_path_total_timing_analysis_time crit_path_total_sta_time +k4_N4_tileable_90nm.xml diffeq.blif common 9.82 vpr 61.45 MiB -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 417 64 -1 -1 success v8.0.0-6725-gff83963de-dirty release IPO VTR_ASSERT_LEVEL=2 GNU 9.3.0 on Linux-4.4.0-19041-Microsoft x86_64 2022-11-01T15:38:22 LAPTOP-CVNHOGSN /home/tangxifan/vtr-verilog-to-routing/vtr_flow/tasks 62920 64 39 1935 1974 1 1104 520 23 23 529 clb auto 18.8 MiB 0.14 10227 61.2 MiB 0.57 0.01 6.71028 -1587.65 -6.71028 6.71028 0.25 0.0007736 0.0005813 0.0896507 0.0699632 34 17207 50 983127 929624 921133. 1741.27 7.25 0.536827 0.433199 14874 22 8645 29434 2727679 902790 6.8984 6.8984 -1779.84 -6.8984 0 0 1.17586e+06 2222.80 0.07 0.39 0.058014 0.0505961 +k4_N4_tileable_90nm.xml ex5p.blif common 15.22 vpr 52.07 MiB -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 346 8 -1 -1 success v8.0.0-6725-gff83963de-dirty release IPO VTR_ASSERT_LEVEL=2 GNU 9.3.0 on Linux-4.4.0-19041-Microsoft x86_64 2022-11-01T15:38:22 LAPTOP-CVNHOGSN /home/tangxifan/vtr-verilog-to-routing/vtr_flow/tasks 53324 8 63 1072 1135 0 909 417 21 21 441 clb auto 14.2 MiB 0.10 11660 52.1 MiB 0.46 0.00 7.1886 -311.061 -7.1886 nan 0.20 0.000496 0.0003719 0.0573232 0.0458367 56 22886 46 804782 771343 1.13430e+06 2572.11 12.88 0.310125 0.253318 18533 21 8880 28500 4332796 1534540 7.97924 nan -339.269 -7.97924 0 0 1.45200e+06 3292.52 0.08 0.50 0.0368923 0.0322975 +k4_N4_tileable_90nm.xml s298.blif common 21.05 vpr 75.85 MiB -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 571 4 -1 -1 success v8.0.0-6725-gff83963de-dirty release IPO VTR_ASSERT_LEVEL=2 GNU 9.3.0 on Linux-4.4.0-19041-Microsoft x86_64 2022-11-01T15:38:22 LAPTOP-CVNHOGSN /home/tangxifan/vtr-verilog-to-routing/vtr_flow/tasks 77672 4 6 1942 1948 1 1193 581 26 26 676 clb auto 21.3 MiB 0.14 14254 75.9 MiB 0.69 0.01 13.2884 -103 -13.2884 13.2884 0.33 0.0008181 0.0006197 0.0966404 0.0764946 42 26119 42 1.28409e+06 1.27294e+06 1.41510e+06 2093.35 17.58 0.615507 0.493511 22147 19 9442 45483 4771423 1297512 13.6006 13.6006 -107.558 -13.6006 0 0 1.86822e+06 2763.64 0.19 0.67 0.0640435 0.0560669 From 921e1ba453919f8f1987625fe53c61e79973e646 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 1 Nov 2022 16:21:21 -0700 Subject: [PATCH 110/147] [vpr] code format --- vpr/src/base/read_blif.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vpr/src/base/read_blif.cpp b/vpr/src/base/read_blif.cpp index 33d953cf111..326216896f4 100644 --- a/vpr/src/base/read_blif.cpp +++ b/vpr/src/base/read_blif.cpp @@ -718,7 +718,7 @@ bool is_binary_param(const std::string& param) { return true; } -bool is_real_param(const std::string ¶m) { +bool is_real_param(const std::string& param) { /* Must be non-empty */ if (param.empty()) { return false; From 96ea971d7c92445f2b2f51c35ac2a5cdb7f3d374 Mon Sep 17 00:00:00 2001 From: Tao Li Date: Thu, 26 Jan 2023 14:29:59 -0800 Subject: [PATCH 111/147] Support route constraint. --- vpr/src/base/route_constraint.cpp | 43 ++++++++++++++++++++ vpr/src/base/route_constraint.h | 65 +++++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+) create mode 100644 vpr/src/base/route_constraint.cpp create mode 100644 vpr/src/base/route_constraint.h diff --git a/vpr/src/base/route_constraint.cpp b/vpr/src/base/route_constraint.cpp new file mode 100644 index 00000000000..2e2d9d524b2 --- /dev/null +++ b/vpr/src/base/route_constraint.cpp @@ -0,0 +1,43 @@ +#include "route_constraint.h" + +RouteConstraint::RouteConstraint() { + net_name_ = std::string(""); + net_type_ = std::string(""); + route_method_ = std::string(""); + is_valid_ = false; +} + +void RouteConstraint::set_net_name(std::string name) { + net_name_ = name; + return; +} + +std::string RouteConstraint::get_net_name() const { + return net_name_; +} + +void RouteConstraint::set_net_type(std::string type) { + net_type_ = type; + return; +} + +std::string RouteConstraint::get_net_type() const { + return net_type_; +} + +void RouteConstraint::set_route_model(std::string route_method) { + route_method_ = route_method; + return; +} + +std::string RouteConstraint::get_route_model() const { + return route_method_; +} + +void RouteConstraint::set_is_valid(bool value) { + is_valid_ = value;; +} + +bool RouteConstraint::get_is_valid() const { + return is_valid_; +} diff --git a/vpr/src/base/route_constraint.h b/vpr/src/base/route_constraint.h new file mode 100644 index 00000000000..50b967e3f31 --- /dev/null +++ b/vpr/src/base/route_constraint.h @@ -0,0 +1,65 @@ +#ifndef ROUTE_CONSTRAINT_H +#define ROUTE_CONSTRAINT_H + +#include "vpr_types.h" + +/** + * @file + * @brief This file defines the RouteConstraint class. + */ + +class RouteConstraint { + public: + /** + * @brief Constructor for the RouteConstraint class, sets member variables to invalid values + */ + RouteConstraint(); + + /** + * @brief get net name + */ + std::string get_net_name() const; + + /** + * @brief set net name + */ + void set_net_name(std::string); + + /** + * @brief get net type + */ + std::string get_net_type() const; + + /** + * @brief set net type + */ + void set_net_type(std::string); + + /** + * @brief get route model + */ + std::string get_route_model() const; + + /** + * @brief set route model + */ + void set_route_model(std::string); + + /** + * @brief set is valid + */ + void set_is_valid(bool); + + /** + * @brief get is valid + */ + bool get_is_valid() const; + + private: + std::string net_name_; + std::string net_type_; + std::string route_method_; + bool is_valid_; +}; + +#endif /* ROUTE_CONSTRAINT_H */ From 671c9d292605d8a87a1575044ca4c512a5bb96ab Mon Sep 17 00:00:00 2001 From: Tao Li Date: Thu, 26 Jan 2023 19:22:22 -0800 Subject: [PATCH 112/147] Support route constraints. --- vpr/src/base/gen/vpr_constraints_uxsdcxx.h | 253 +++++++++++++++++- .../gen/vpr_constraints_uxsdcxx_interface.h | 111 +++++--- vpr/src/base/vpr_api.cpp | 11 +- vpr/src/base/vpr_constraints.cpp | 42 +++ vpr/src/base/vpr_constraints.h | 34 +++ vpr/src/base/vpr_constraints.xsd | 21 ++ vpr/src/base/vpr_constraints_reader.cpp | 4 + vpr/src/base/vpr_constraints_serializer.h | 68 +++++ vpr/src/base/vpr_context.h | 5 + vpr/src/util/vpr_utils.cpp | 29 +- vpr/src/util/vpr_utils.h | 6 + 11 files changed, 526 insertions(+), 58 deletions(-) diff --git a/vpr/src/base/gen/vpr_constraints_uxsdcxx.h b/vpr/src/base/gen/vpr_constraints_uxsdcxx.h index 3248c338281..836f6b95b49 100644 --- a/vpr/src/base/gen/vpr_constraints_uxsdcxx.h +++ b/vpr/src/base/gen/vpr_constraints_uxsdcxx.h @@ -4,9 +4,9 @@ * https://github.com/duck2/uxsdcxx * Modify only if your build process doesn't involve regenerating this file. * - * Cmdline: uxsdcxx.py vpr_constraints.xsd - * Input file: /home/khalid88/Documents/uxsdcxx/vpr_constraints.xsd - * md5sum of input file: 6b6011a6e6446347b234da82e517422e + * Cmdline: uxsdcxx.py /home/tao/works/dev/clock/test/xml_gen/vpr_constraints.xsd + * Input file: /home/tao/works/dev/clock/test/xml_gen/vpr_constraints.xsd + * md5sum of input file: 1ab0562dd315daffe9ac257ab683233e */ #include @@ -25,8 +25,6 @@ #include "pugixml.hpp" #include "vpr_constraints_uxsdcxx_interface.h" -#include "region.h" - /* All uxsdcxx functions and structs live in this namespace. */ namespace uxsd { @@ -52,6 +50,10 @@ inline void load_partition(const pugi::xml_node& root, T& out, Context& context, template inline void load_partition_list(const pugi::xml_node& root, T& out, Context& context, const std::function* report_error, ptrdiff_t* offset_debug); template +inline void load_set_global_signal(const pugi::xml_node& root, T& out, Context& context, const std::function* report_error, ptrdiff_t* offset_debug); +template +inline void load_global_route_constraints(const pugi::xml_node& root, T& out, Context& context, const std::function* report_error, ptrdiff_t* offset_debug); +template inline void load_vpr_constraints(const pugi::xml_node& root, T& out, Context& context, const std::function* report_error, ptrdiff_t* offset_debug); /* Declarations for internal write functions for the complex types. */ @@ -60,6 +62,8 @@ inline void write_partition(T& in, std::ostream& os, const void* data, void* ite template inline void write_partition_list(T& in, std::ostream& os, const void* data, void* iter); template +inline void write_global_route_constraints(T& in, std::ostream& os, const void* data, void* iter); +template inline void write_vpr_constraints(T& in, std::ostream& os, const void* data, void* iter); /* Load function for the root element. */ @@ -142,8 +146,17 @@ constexpr const char* atok_lookup_t_partition[] = {"name"}; enum class gtok_t_partition_list { PARTITION }; constexpr const char* gtok_lookup_t_partition_list[] = {"partition"}; -enum class gtok_t_vpr_constraints { PARTITION_LIST }; -constexpr const char* gtok_lookup_t_vpr_constraints[] = {"partition_list"}; + +enum class atok_t_set_global_signal { NAME, + ROUTE_MODEL, + TYPE }; +constexpr const char* atok_lookup_t_set_global_signal[] = {"name", "route_model", "type"}; + +enum class gtok_t_global_route_constraints { SET_GLOBAL_SIGNAL }; +constexpr const char* gtok_lookup_t_global_route_constraints[] = {"set_global_signal"}; +enum class gtok_t_vpr_constraints { PARTITION_LIST, + GLOBAL_ROUTE_CONSTRAINTS }; +constexpr const char* gtok_lookup_t_vpr_constraints[] = {"partition_list", "global_route_constraints"}; enum class atok_t_vpr_constraints { TOOL_NAME }; constexpr const char* atok_lookup_t_vpr_constraints[] = {"tool_name"}; @@ -348,6 +361,84 @@ inline gtok_t_partition_list lex_node_t_partition_list(const char* in, const std noreturn_report(report_error, ("Found unrecognized child " + std::string(in) + " of .").c_str()); } +inline atok_t_set_global_signal lex_attr_t_set_global_signal(const char* in, const std::function* report_error) { + unsigned int len = strlen(in); + switch (len) { + case 4: + switch (*((triehash_uu32*)&in[0])) { + case onechar('n', 0, 32) | onechar('a', 8, 32) | onechar('m', 16, 32) | onechar('e', 24, 32): + return atok_t_set_global_signal::NAME; + break; + case onechar('t', 0, 32) | onechar('y', 8, 32) | onechar('p', 16, 32) | onechar('e', 24, 32): + return atok_t_set_global_signal::TYPE; + break; + default: + break; + } + break; + case 11: + switch (*((triehash_uu64*)&in[0])) { + case onechar('r', 0, 64) | onechar('o', 8, 64) | onechar('u', 16, 64) | onechar('t', 24, 64) | onechar('e', 32, 64) | onechar('_', 40, 64) | onechar('m', 48, 64) | onechar('o', 56, 64): + switch (in[8]) { + case onechar('d', 0, 8): + switch (in[9]) { + case onechar('e', 0, 8): + switch (in[10]) { + case onechar('l', 0, 8): + return atok_t_set_global_signal::ROUTE_MODEL; + break; + default: + break; + } + break; + default: + break; + } + break; + default: + break; + } + break; + default: + break; + } + break; + default: + break; + } + noreturn_report(report_error, ("Found unrecognized attribute " + std::string(in) + " of .").c_str()); +} + +inline gtok_t_global_route_constraints lex_node_t_global_route_constraints(const char* in, const std::function* report_error) { + unsigned int len = strlen(in); + switch (len) { + case 17: + switch (*((triehash_uu64*)&in[0])) { + case onechar('s', 0, 64) | onechar('e', 8, 64) | onechar('t', 16, 64) | onechar('_', 24, 64) | onechar('g', 32, 64) | onechar('l', 40, 64) | onechar('o', 48, 64) | onechar('b', 56, 64): + switch (*((triehash_uu64*)&in[8])) { + case onechar('a', 0, 64) | onechar('l', 8, 64) | onechar('_', 16, 64) | onechar('s', 24, 64) | onechar('i', 32, 64) | onechar('g', 40, 64) | onechar('n', 48, 64) | onechar('a', 56, 64): + switch (in[16]) { + case onechar('l', 0, 8): + return gtok_t_global_route_constraints::SET_GLOBAL_SIGNAL; + break; + default: + break; + } + break; + default: + break; + } + break; + default: + break; + } + break; + default: + break; + } + noreturn_report(report_error, ("Found unrecognized child " + std::string(in) + " of .").c_str()); +} + inline gtok_t_vpr_constraints lex_node_t_vpr_constraints(const char* in, const std::function* report_error) { unsigned int len = strlen(in); switch (len) { @@ -378,6 +469,27 @@ inline gtok_t_vpr_constraints lex_node_t_vpr_constraints(const char* in, const s break; } break; + case 24: + switch (*((triehash_uu64*)&in[0])) { + case onechar('g', 0, 64) | onechar('l', 8, 64) | onechar('o', 16, 64) | onechar('b', 24, 64) | onechar('a', 32, 64) | onechar('l', 40, 64) | onechar('_', 48, 64) | onechar('r', 56, 64): + switch (*((triehash_uu64*)&in[8])) { + case onechar('o', 0, 64) | onechar('u', 8, 64) | onechar('t', 16, 64) | onechar('e', 24, 64) | onechar('_', 32, 64) | onechar('c', 40, 64) | onechar('o', 48, 64) | onechar('n', 56, 64): + switch (*((triehash_uu64*)&in[16])) { + case onechar('s', 0, 64) | onechar('t', 8, 64) | onechar('r', 16, 64) | onechar('a', 24, 64) | onechar('i', 32, 64) | onechar('n', 40, 64) | onechar('t', 48, 64) | onechar('s', 56, 64): + return gtok_t_vpr_constraints::GLOBAL_ROUTE_CONSTRAINTS; + break; + default: + break; + } + break; + default: + break; + } + break; + default: + break; + } + break; default: break; } @@ -427,8 +539,6 @@ template /* Internal loading functions, which validate and load a PugiXML DOM tree into memory. */ inline int load_int(const char* in, const std::function* report_error) { int out; - // global variable, must set to 0 before using it to avoid changed by other errors - errno = 0; out = std::strtol(in, NULL, 10); if (errno != 0) noreturn_report(report_error, ("Invalid value `" + std::string(in) + "` when loading into a int.").c_str()); @@ -674,6 +784,97 @@ inline void load_partition_list(const pugi::xml_node& root, T& out, Context& con if (state != 0) dfa_error("end of input", gstate_t_partition_list[state], gtok_lookup_t_partition_list, 1, report_error); } +template +inline void load_set_global_signal(const pugi::xml_node& root, T& out, Context& context, const std::function* report_error, ptrdiff_t* offset_debug) { + (void)root; + (void)out; + (void)context; + (void)report_error; + // Update current file offset in case an error is encountered. + *offset_debug = root.offset_debug(); + + for (pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()) { + atok_t_set_global_signal in = lex_attr_t_set_global_signal(attr.name(), report_error); + switch (in) { + case atok_t_set_global_signal::NAME: + out.set_set_global_signal_name(attr.value(), context); + break; + case atok_t_set_global_signal::ROUTE_MODEL: + out.set_set_global_signal_route_model(attr.value(), context); + break; + case atok_t_set_global_signal::TYPE: + out.set_set_global_signal_type(attr.value(), context); + break; + default: + break; /* Not possible. */ + } + } + + if (root.first_child().type() == pugi::node_element) + noreturn_report(report_error, "Unexpected child element in ."); +} + +constexpr int NUM_T_GLOBAL_ROUTE_CONSTRAINTS_STATES = 2; +constexpr const int NUM_T_GLOBAL_ROUTE_CONSTRAINTS_INPUTS = 1; +constexpr int gstate_t_global_route_constraints[NUM_T_GLOBAL_ROUTE_CONSTRAINTS_STATES][NUM_T_GLOBAL_ROUTE_CONSTRAINTS_INPUTS] = { + {0}, + {0}, +}; +template +inline void load_global_route_constraints(const pugi::xml_node& root, T& out, Context& context, const std::function* report_error, ptrdiff_t* offset_debug) { + (void)root; + (void)out; + (void)context; + (void)report_error; + // Update current file offset in case an error is encountered. + *offset_debug = root.offset_debug(); + + if (root.first_attribute()) + noreturn_report(report_error, "Unexpected attribute in ."); + + // Preallocate arrays by counting child nodes (if any) + size_t set_global_signal_count = 0; + { + int next, state = 1; + for (pugi::xml_node node = root.first_child(); node; node = node.next_sibling()) { + *offset_debug = node.offset_debug(); + gtok_t_global_route_constraints in = lex_node_t_global_route_constraints(node.name(), report_error); + next = gstate_t_global_route_constraints[state][(int)in]; + if (next == -1) + dfa_error(gtok_lookup_t_global_route_constraints[(int)in], gstate_t_global_route_constraints[state], gtok_lookup_t_global_route_constraints, 1, report_error); + state = next; + switch (in) { + case gtok_t_global_route_constraints::SET_GLOBAL_SIGNAL: + set_global_signal_count += 1; + break; + default: + break; /* Not possible. */ + } + } + + out.preallocate_global_route_constraints_set_global_signal(context, set_global_signal_count); + } + int next, state = 1; + for (pugi::xml_node node = root.first_child(); node; node = node.next_sibling()) { + *offset_debug = node.offset_debug(); + gtok_t_global_route_constraints in = lex_node_t_global_route_constraints(node.name(), report_error); + next = gstate_t_global_route_constraints[state][(int)in]; + if (next == -1) + dfa_error(gtok_lookup_t_global_route_constraints[(int)in], gstate_t_global_route_constraints[state], gtok_lookup_t_global_route_constraints, 1, report_error); + state = next; + switch (in) { + case gtok_t_global_route_constraints::SET_GLOBAL_SIGNAL: { + auto child_context = out.add_global_route_constraints_set_global_signal(context); + load_set_global_signal(node, out, child_context, report_error, offset_debug); + out.finish_global_route_constraints_set_global_signal(child_context); + } break; + default: + break; /* Not possible. */ + } + } + if (state != 0) dfa_error("end of input", gstate_t_global_route_constraints[state], gtok_lookup_t_global_route_constraints, 1, report_error); +} + template inline void load_vpr_constraints(const pugi::xml_node& root, T& out, Context& context, const std::function* report_error, ptrdiff_t* offset_debug) { (void)root; @@ -694,7 +895,7 @@ inline void load_vpr_constraints(const pugi::xml_node& root, T& out, Context& co } } - std::bitset<1> gstate = 0; + std::bitset<2> gstate = 0; for (pugi::xml_node node = root.first_child(); node; node = node.next_sibling()) { *offset_debug = node.offset_debug(); gtok_t_vpr_constraints in = lex_node_t_vpr_constraints(node.name(), report_error); @@ -708,11 +909,16 @@ inline void load_vpr_constraints(const pugi::xml_node& root, T& out, Context& co load_partition_list(node, out, child_context, report_error, offset_debug); out.finish_vpr_constraints_partition_list(child_context); } break; + case gtok_t_vpr_constraints::GLOBAL_ROUTE_CONSTRAINTS: { + auto child_context = out.init_vpr_constraints_global_route_constraints(context); + load_global_route_constraints(node, out, child_context, report_error, offset_debug); + out.finish_vpr_constraints_global_route_constraints(child_context); + } break; default: break; /* Not possible. */ } } - std::bitset<1> test_gstate = gstate | std::bitset<1>(0b0); + std::bitset<2> test_gstate = gstate | std::bitset<2>(0b00); if (!test_gstate.all()) all_error(test_gstate, gtok_lookup_t_vpr_constraints, report_error); } @@ -734,7 +940,7 @@ inline void write_partition(T& in, std::ostream& os, Context& context) { for (size_t i = 0, n = in.num_partition_add_region(context); i < n; i++) { auto child_context = in.get_partition_add_region(i, context); os << " +inline void write_global_route_constraints(T& in, std::ostream& os, Context& context) { + (void)in; + (void)os; + (void)context; + { + for (size_t i = 0, n = in.num_global_route_constraints_set_global_signal(context); i < n; i++) { + auto child_context = in.get_global_route_constraints_set_global_signal(i, context); + os << "\n"; + } + } +} + template inline void write_vpr_constraints(T& in, std::ostream& os, Context& context) { (void)in; @@ -773,6 +996,12 @@ inline void write_vpr_constraints(T& in, std::ostream& os, Context& context) { write_partition_list(in, os, child_context); os << "\n"; } + { + auto child_context = in.get_vpr_constraints_global_route_constraints(context); + os << "\n"; + write_global_route_constraints(in, os, child_context); + os << "\n"; + } } inline void dfa_error(const char* wrong, const int* states, const char* const* lookup, int len, const std::function* report_error) { diff --git a/vpr/src/base/gen/vpr_constraints_uxsdcxx_interface.h b/vpr/src/base/gen/vpr_constraints_uxsdcxx_interface.h index 6da8558b84d..d554afa970b 100644 --- a/vpr/src/base/gen/vpr_constraints_uxsdcxx_interface.h +++ b/vpr/src/base/gen/vpr_constraints_uxsdcxx_interface.h @@ -4,9 +4,9 @@ * https://github.com/duck2/uxsdcxx * Modify only if your build process doesn't involve regenerating this file. * - * Cmdline: uxsdcxx.py vpr_constraints.xsd - * Input file: /home/khalid88/Documents/uxsdcxx/vpr_constraints.xsd - * md5sum of input file: 6b6011a6e6446347b234da82e517422e + * Cmdline: uxsdcxx.py /home/tao/works/dev/clock/test/xml_gen/vpr_constraints.xsd + * Input file: /home/tao/works/dev/clock/test/xml_gen/vpr_constraints.xsd + * md5sum of input file: 1ab0562dd315daffe9ac257ab683233e */ #include @@ -24,11 +24,15 @@ struct DefaultVprConstraintsContextTypes { using AddRegionReadContext = void*; using PartitionReadContext = void*; using PartitionListReadContext = void*; + using SetGlobalSignalReadContext = void*; + using GlobalRouteConstraintsReadContext = void*; using VprConstraintsReadContext = void*; using AddAtomWriteContext = void*; using AddRegionWriteContext = void*; using PartitionWriteContext = void*; using PartitionListWriteContext = void*; + using SetGlobalSignalWriteContext = void*; + using GlobalRouteConstraintsWriteContext = void*; using VprConstraintsWriteContext = void*; }; @@ -42,22 +46,22 @@ class VprConstraintsBase { virtual void finish_write() = 0; virtual void error_encountered(const char* file, int line, const char* message) = 0; /** Generated for complex type "add_atom": - * - * - * - */ + * + * + * + */ virtual inline const char* get_add_atom_name_pattern(typename ContextTypes::AddAtomReadContext& ctx) = 0; virtual inline void set_add_atom_name_pattern(const char* name_pattern, typename ContextTypes::AddAtomWriteContext& ctx) = 0; /** Generated for complex type "add_region": - * - * - * - * - * - * - * - */ + * + * + * + * + * + * + * + */ virtual inline int get_add_region_subtile(typename ContextTypes::AddRegionReadContext& ctx) = 0; virtual inline void set_add_region_subtile(int subtile, typename ContextTypes::AddRegionWriteContext& ctx) = 0; virtual inline int get_add_region_x_high(typename ContextTypes::AddRegionReadContext& ctx) = 0; @@ -66,16 +70,16 @@ class VprConstraintsBase { virtual inline int get_add_region_y_low(typename ContextTypes::AddRegionReadContext& ctx) = 0; /** Generated for complex type "partition": - * - * - * - * - * - * - * - * - * - */ + * + * + * + * + * + * + * + * + * + */ virtual inline const char* get_partition_name(typename ContextTypes::PartitionReadContext& ctx) = 0; virtual inline void set_partition_name(const char* name, typename ContextTypes::PartitionWriteContext& ctx) = 0; virtual inline void preallocate_partition_add_atom(typename ContextTypes::PartitionWriteContext& ctx, size_t size) = 0; @@ -90,31 +94,62 @@ class VprConstraintsBase { virtual inline typename ContextTypes::AddRegionReadContext get_partition_add_region(int n, typename ContextTypes::PartitionReadContext& ctx) = 0; /** Generated for complex type "partition_list": - * - * - * - * - * - */ + * + * + * + * + * + */ virtual inline void preallocate_partition_list_partition(typename ContextTypes::PartitionListWriteContext& ctx, size_t size) = 0; virtual inline typename ContextTypes::PartitionWriteContext add_partition_list_partition(typename ContextTypes::PartitionListWriteContext& ctx) = 0; virtual inline void finish_partition_list_partition(typename ContextTypes::PartitionWriteContext& ctx) = 0; virtual inline size_t num_partition_list_partition(typename ContextTypes::PartitionListReadContext& ctx) = 0; virtual inline typename ContextTypes::PartitionReadContext get_partition_list_partition(int n, typename ContextTypes::PartitionListReadContext& ctx) = 0; + /** Generated for complex type "set_global_signal": + * + * + * + * + * + */ + virtual inline const char* get_set_global_signal_name(typename ContextTypes::SetGlobalSignalReadContext& ctx) = 0; + virtual inline void set_set_global_signal_name(const char* name, typename ContextTypes::SetGlobalSignalWriteContext& ctx) = 0; + virtual inline const char* get_set_global_signal_route_model(typename ContextTypes::SetGlobalSignalReadContext& ctx) = 0; + virtual inline void set_set_global_signal_route_model(const char* route_model, typename ContextTypes::SetGlobalSignalWriteContext& ctx) = 0; + virtual inline const char* get_set_global_signal_type(typename ContextTypes::SetGlobalSignalReadContext& ctx) = 0; + virtual inline void set_set_global_signal_type(const char* type, typename ContextTypes::SetGlobalSignalWriteContext& ctx) = 0; + + /** Generated for complex type "global_route_constraints": + * + * + * + * + * + */ + virtual inline void preallocate_global_route_constraints_set_global_signal(typename ContextTypes::GlobalRouteConstraintsWriteContext& ctx, size_t size) = 0; + virtual inline typename ContextTypes::SetGlobalSignalWriteContext add_global_route_constraints_set_global_signal(typename ContextTypes::GlobalRouteConstraintsWriteContext& ctx) = 0; + virtual inline void finish_global_route_constraints_set_global_signal(typename ContextTypes::SetGlobalSignalWriteContext& ctx) = 0; + virtual inline size_t num_global_route_constraints_set_global_signal(typename ContextTypes::GlobalRouteConstraintsReadContext& ctx) = 0; + virtual inline typename ContextTypes::SetGlobalSignalReadContext get_global_route_constraints_set_global_signal(int n, typename ContextTypes::GlobalRouteConstraintsReadContext& ctx) = 0; + /** Generated for complex type "vpr_constraints": - * - * - * - * - * - * - */ + * + * + * + * + * + * + * + */ virtual inline const char* get_vpr_constraints_tool_name(typename ContextTypes::VprConstraintsReadContext& ctx) = 0; virtual inline void set_vpr_constraints_tool_name(const char* tool_name, typename ContextTypes::VprConstraintsWriteContext& ctx) = 0; virtual inline typename ContextTypes::PartitionListWriteContext init_vpr_constraints_partition_list(typename ContextTypes::VprConstraintsWriteContext& ctx) = 0; virtual inline void finish_vpr_constraints_partition_list(typename ContextTypes::PartitionListWriteContext& ctx) = 0; virtual inline typename ContextTypes::PartitionListReadContext get_vpr_constraints_partition_list(typename ContextTypes::VprConstraintsReadContext& ctx) = 0; + virtual inline typename ContextTypes::GlobalRouteConstraintsWriteContext init_vpr_constraints_global_route_constraints(typename ContextTypes::VprConstraintsWriteContext& ctx) = 0; + virtual inline void finish_vpr_constraints_global_route_constraints(typename ContextTypes::GlobalRouteConstraintsWriteContext& ctx) = 0; + virtual inline typename ContextTypes::GlobalRouteConstraintsReadContext get_vpr_constraints_global_route_constraints(typename ContextTypes::VprConstraintsReadContext& ctx) = 0; }; } /* namespace uxsd */ diff --git a/vpr/src/base/vpr_api.cpp b/vpr/src/base/vpr_api.cpp index 123991d4c8e..3911ecd16fb 100644 --- a/vpr/src/base/vpr_api.cpp +++ b/vpr/src/base/vpr_api.cpp @@ -346,10 +346,15 @@ void vpr_init_with_options(const t_options* options, t_vpr_setup* vpr_setup, t_a } } - //Initialize vpr floorplanning constraints + //Initialize vpr floorplanning and routing constraints auto& filename_opts = vpr_setup->FileNameOpts; if (!filename_opts.read_vpr_constraints_file.empty()) { load_vpr_constraints_file(filename_opts.read_vpr_constraints_file.c_str()); + + // give a notificaiton on routing constraints overiding clock modeling + if (g_vpr_ctx.routing().constraints.get_route_constraint_num() && options->clock_modeling.provenance() == argparse::Provenance::SPECIFIED) { + VTR_LOG_WARN("Route constraint(s) detected and will override clock modeling setting.\n"); + } } fflush(stdout); @@ -766,6 +771,10 @@ RouteStatus vpr_route_flow(t_vpr_setup& vpr_setup, const t_arch& arch, bool is_f //Assume successful route_status = RouteStatus(true, -1); } else { //Do or load + + // apply route constraints + apply_route_constraints(g_vpr_ctx.routing().constraints); + int chan_width = router_opts.fixed_channel_width; auto& cluster_ctx = g_vpr_ctx.clustering(); diff --git a/vpr/src/base/vpr_constraints.cpp b/vpr/src/base/vpr_constraints.cpp index 95c7e7b7358..5dec3889dfe 100644 --- a/vpr/src/base/vpr_constraints.cpp +++ b/vpr/src/base/vpr_constraints.cpp @@ -1,5 +1,6 @@ #include "vpr_constraints.h" #include "partition.h" +#include "route_constraint.h" void VprConstraints::add_constrained_atom(const AtomBlockId blk_id, const PartitionId part_id) { auto got = constrained_atoms.find(blk_id); @@ -58,6 +59,47 @@ PartitionRegion VprConstraints::get_partition_pr(PartitionId part_id) { return pr; } +void VprConstraints::add_route_constraint(RouteConstraint rc) { + route_constraints_.insert({rc.get_net_name(), rc}); + return; +} + +RouteConstraint VprConstraints::get_route_constraint_by_net_name(std::string net_name) const { + RouteConstraint rc; + auto const& rc_itr = route_constraints_.find(net_name); + if (rc_itr == route_constraints_.end()) { + rc.set_net_name("INVALID"); + rc.set_net_type("INVALID"); + rc.set_route_model("INVALID"); + rc.set_is_valid(false); + } else { + rc = rc_itr->second; + } + return rc; +} + +RouteConstraint VprConstraints::get_route_constraint_by_idx(std::size_t idx) const { + RouteConstraint rc; + if ((route_constraints_.size() == 0) || (idx > route_constraints_.size() - 1)) { + rc.set_net_name("INVALID"); + rc.set_net_type("INVALID"); + rc.set_route_model("INVALID"); + rc.set_is_valid(false); + } else { + std::size_t i = 0; + for (auto const& rc_itr : route_constraints_) { + if (i == idx) { + rc = rc_itr.second; + } + } + } + return rc; +} + +int VprConstraints::get_route_constraint_num(void) const { + return route_constraints_.size(); +} + void print_constraints(FILE* fp, VprConstraints constraints) { Partition temp_part; std::vector atoms; diff --git a/vpr/src/base/vpr_constraints.h b/vpr/src/base/vpr_constraints.h index fd3f64842a4..fbe4e314f75 100644 --- a/vpr/src/base/vpr_constraints.h +++ b/vpr/src/base/vpr_constraints.h @@ -5,6 +5,7 @@ #include "vpr_utils.h" #include "partition.h" #include "partition_region.h" +#include "route_constraint.h" /** * @file @@ -87,6 +88,34 @@ class VprConstraints { */ PartitionRegion get_partition_pr(PartitionId part_id); + /** + * @brief add route constraint + * + * @param net_name the route constraint + */ + void add_route_constraint(RouteConstraint rc); + + /** + * @brief returns route constraint by index + * + * @param index the constraint index + */ + RouteConstraint get_route_constraint_by_idx(std::size_t index) const; + + /** + * @brief returns route constraint of a specific net + * + * @param net_name the net name + */ + RouteConstraint get_route_constraint_by_net_name(std::string net_name) const; + + /** + * @brief returns number of route constraints + * + * @param void + */ + int get_route_constraint_num(void) const; + private: /** * Store all constrained atoms @@ -97,6 +126,11 @@ class VprConstraints { * Store all partitions */ vtr::vector partitions; + + /** + * store all route constraints + */ + std::unordered_map route_constraints_; }; ///@brief used to print floorplanning constraints data from a VprConstraints object diff --git a/vpr/src/base/vpr_constraints.xsd b/vpr/src/base/vpr_constraints.xsd index 406e2abcda4..9144e656081 100644 --- a/vpr/src/base/vpr_constraints.xsd +++ b/vpr/src/base/vpr_constraints.xsd @@ -59,6 +59,26 @@ + + + + + + + + + + + + + + + - + - - + diff --git a/vpr/src/base/vpr_constraints_serializer.h b/vpr/src/base/vpr_constraints_serializer.h index 4c2666d0d6d..ddfe531e587 100644 --- a/vpr/src/base/vpr_constraints_serializer.h +++ b/vpr/src/base/vpr_constraints_serializer.h @@ -356,48 +356,66 @@ class VprConstraintsSerializer final : public uxsd::VprConstraintsBase - * - * + * + * + * * - * - * - * - */ + * + * + * + */ virtual inline const char* get_vpr_constraints_tool_name(void*& /*ctx*/) final { return temp_.c_str(); } - virtual inline void set_vpr_constraints_tool_name(const char* /*tool_name*/, void*& /*ctx*/) final {} + virtual inline void set_vpr_constraints_tool_name(const char* /*tool_name*/, void*& /*ctx*/) final { + } virtual inline void set_vpr_constraints_constraints_comment(const char* /*constraints_comment*/, void*& /*ctx*/) final {} virtual inline const char* get_vpr_constraints_constraints_comment(void*& /*ctx*/) final { return temp_.c_str(); } - virtual inline void* init_vpr_constraints_partition_list(void*& /*ctx*/) final { + + virtual inline void preallocate_vpr_constraints_partition_list(void*& /*ctx*/, size_t) final { + } + + virtual inline void* add_vpr_constraints_partition_list(void*& /*ctx*/) final { return nullptr; } virtual inline void finish_vpr_constraints_partition_list(void*& /*ctx*/) final { + return; } - virtual inline void* get_vpr_constraints_partition_list(void*& /*ctx*/) final { + virtual inline size_t num_vpr_constraints_partition_list(void*& /*ctx*/) final { + return 0; + } + + virtual inline void* get_vpr_constraints_partition_list(int, void*& /*ctx*/) final { return nullptr; } - virtual inline void* init_vpr_constraints_global_route_constraints(void*& /*ctx*/) final { + virtual inline void preallocate_vpr_constraints_global_route_constraints(void*& /*ctx*/, size_t) final { + } + + virtual inline void* add_vpr_constraints_global_route_constraints(void*& /*ctx*/) final { return nullptr; } virtual inline void finish_vpr_constraints_global_route_constraints(void*& /*ctx*/) final { + return; + } + virtual inline size_t num_vpr_constraints_global_route_constraints(void*& /*ctx*/) final { + return 0; } - virtual inline void* get_vpr_constraints_global_route_constraints(void*& /*ctx*/) final { + virtual inline void* get_vpr_constraints_global_route_constraints(int, void*& /*cts*/) final { return nullptr; } virtual void finish_load() final { + return; } //temp data for writes From afed57f519a605842ea2b84a41d7d8ffcb70899d Mon Sep 17 00:00:00 2001 From: Tao Li Date: Thu, 2 Feb 2023 21:09:21 -0800 Subject: [PATCH 115/147] Code format clang-7. --- vpr/src/base/gen/vpr_constraints_uxsdcxx.h | 1860 +++++++++-------- .../gen/vpr_constraints_uxsdcxx_interface.h | 251 ++- vpr/src/base/vpr_api.cpp | 2 +- vpr/src/base/vpr_constraints.cpp | 8 +- vpr/src/base/vpr_constraints_serializer.h | 40 +- vpr/src/base/vpr_context.h | 2 +- vpr/src/util/vpr_utils.cpp | 6 +- 7 files changed, 1107 insertions(+), 1062 deletions(-) diff --git a/vpr/src/base/gen/vpr_constraints_uxsdcxx.h b/vpr/src/base/gen/vpr_constraints_uxsdcxx.h index db6e59cc088..12feabd08ab 100644 --- a/vpr/src/base/gen/vpr_constraints_uxsdcxx.h +++ b/vpr/src/base/gen/vpr_constraints_uxsdcxx.h @@ -11,7 +11,6 @@ #include - #include #include #include @@ -33,1026 +32,1073 @@ namespace uxsd { * Internal function for getting line and column number from file based on * byte offset. */ -inline void get_line_number(const char *filename, std::ptrdiff_t offset, int * line, int * col); +inline void get_line_number(const char* filename, std::ptrdiff_t offset, int* line, int* col); -[[noreturn]] inline void noreturn_report(const std::function * report_error, const char *msg) { +[[noreturn]] inline void noreturn_report(const std::function* report_error, const char* msg) { (*report_error)(msg); throw std::runtime_error("Unreachable!"); } /* Declarations for internal load functions for the complex types. */ -template -inline void load_add_atom(const pugi::xml_node &root, T &out, Context &context, const std::function *report_error, ptrdiff_t *offset_debug); -template -inline void load_add_region(const pugi::xml_node &root, T &out, Context &context, const std::function *report_error, ptrdiff_t *offset_debug); -inline void load_add_region_required_attributes(const pugi::xml_node &root, int * x_high, int * x_low, int * y_high, int * y_low, const std::function * report_error); -template -inline void load_partition(const pugi::xml_node &root, T &out, Context &context, const std::function *report_error, ptrdiff_t *offset_debug); -template -inline void load_partition_list(const pugi::xml_node &root, T &out, Context &context, const std::function *report_error, ptrdiff_t *offset_debug); -template -inline void load_set_global_signal(const pugi::xml_node &root, T &out, Context &context, const std::function *report_error, ptrdiff_t *offset_debug); -template -inline void load_global_route_constraints(const pugi::xml_node &root, T &out, Context &context, const std::function *report_error, ptrdiff_t *offset_debug); -template -inline void load_vpr_constraints(const pugi::xml_node &root, T &out, Context &context, const std::function *report_error, ptrdiff_t *offset_debug); +template +inline void load_add_atom(const pugi::xml_node& root, T& out, Context& context, const std::function* report_error, ptrdiff_t* offset_debug); +template +inline void load_add_region(const pugi::xml_node& root, T& out, Context& context, const std::function* report_error, ptrdiff_t* offset_debug); +inline void load_add_region_required_attributes(const pugi::xml_node& root, int* x_high, int* x_low, int* y_high, int* y_low, const std::function* report_error); +template +inline void load_partition(const pugi::xml_node& root, T& out, Context& context, const std::function* report_error, ptrdiff_t* offset_debug); +template +inline void load_partition_list(const pugi::xml_node& root, T& out, Context& context, const std::function* report_error, ptrdiff_t* offset_debug); +template +inline void load_set_global_signal(const pugi::xml_node& root, T& out, Context& context, const std::function* report_error, ptrdiff_t* offset_debug); +template +inline void load_global_route_constraints(const pugi::xml_node& root, T& out, Context& context, const std::function* report_error, ptrdiff_t* offset_debug); +template +inline void load_vpr_constraints(const pugi::xml_node& root, T& out, Context& context, const std::function* report_error, ptrdiff_t* offset_debug); /* Declarations for internal write functions for the complex types. */ -template -inline void write_partition(T &in, std::ostream &os, const void *data, void *iter); -template -inline void write_partition_list(T &in, std::ostream &os, const void *data, void *iter); -template -inline void write_global_route_constraints(T &in, std::ostream &os, const void *data, void *iter); -template -inline void write_vpr_constraints(T &in, std::ostream &os, const void *data, void *iter); +template +inline void write_partition(T& in, std::ostream& os, const void* data, void* iter); +template +inline void write_partition_list(T& in, std::ostream& os, const void* data, void* iter); +template +inline void write_global_route_constraints(T& in, std::ostream& os, const void* data, void* iter); +template +inline void write_vpr_constraints(T& in, std::ostream& os, const void* data, void* iter); /* Load function for the root element. */ -template -inline void load_vpr_constraints_xml(T &out, Context &context, const char * filename, std::istream &is){ - pugi::xml_document doc; - pugi::xml_parse_result result = doc.load(is); - if(!result) { - int line, col; - get_line_number(filename, result.offset, &line, &col); - std::stringstream msg; - msg << "Unable to load XML file '" << filename << "', "; - msg << result.description() << " (line: " << line; - msg << " col: " << col << ")"; out.error_encountered(filename, line, msg.str().c_str()); - } - ptrdiff_t offset_debug = 0; - std::function report_error = [filename, &out, &offset_debug](const char * message) { - int line, col; - get_line_number(filename, offset_debug, &line, &col); - out.error_encountered(filename, line, message); - // If error_encountered didn't throw, throw now to unwind. - throw std::runtime_error(message); - }; - out.start_load(&report_error); - - for(pugi::xml_node node= doc.first_child(); node; node = node.next_sibling()){ - if(std::strcmp(node.name(), "vpr_constraints") == 0){ - /* If errno is set up to this point, it messes with strtol errno checking. */ - errno = 0; - load_vpr_constraints(node, out, context, &report_error, &offset_debug); - } else { - offset_debug = node.offset_debug(); - report_error(("Invalid root-level element " + std::string(node.name())).c_str()); - } - } - out.finish_load(); +template +inline void load_vpr_constraints_xml(T& out, Context& context, const char* filename, std::istream& is) { + pugi::xml_document doc; + pugi::xml_parse_result result = doc.load(is); + if (!result) { + int line, col; + get_line_number(filename, result.offset, &line, &col); + std::stringstream msg; + msg << "Unable to load XML file '" << filename << "', "; + msg << result.description() << " (line: " << line; + msg << " col: " << col << ")"; + out.error_encountered(filename, line, msg.str().c_str()); + } + ptrdiff_t offset_debug = 0; + std::function report_error = [filename, &out, &offset_debug](const char* message) { + int line, col; + get_line_number(filename, offset_debug, &line, &col); + out.error_encountered(filename, line, message); + // If error_encountered didn't throw, throw now to unwind. + throw std::runtime_error(message); + }; + out.start_load(&report_error); + + for (pugi::xml_node node = doc.first_child(); node; node = node.next_sibling()) { + if (std::strcmp(node.name(), "vpr_constraints") == 0) { + /* If errno is set up to this point, it messes with strtol errno checking. */ + errno = 0; + load_vpr_constraints(node, out, context, &report_error, &offset_debug); + } else { + offset_debug = node.offset_debug(); + report_error(("Invalid root-level element " + std::string(node.name())).c_str()); + } + } + out.finish_load(); } /* Write function for the root element. */ -template -inline void write_vpr_constraints_xml(T &in, Context &context, std::ostream &os){ - in.start_write(); - os << "\n"; - write_vpr_constraints(in, os, context); - os << "\n"; - in.finish_write(); +template +inline void write_vpr_constraints_xml(T& in, Context& context, std::ostream& os) { + in.start_write(); + os << "\n"; + write_vpr_constraints(in, os, context); + os << "\n"; + in.finish_write(); } - typedef const uint32_t __attribute__((aligned(1))) triehash_uu32; typedef const uint64_t __attribute__((aligned(1))) triehash_uu64; static_assert(alignof(triehash_uu32) == 1, "Unaligned 32-bit access not found."); static_assert(alignof(triehash_uu64) == 1, "Unaligned 64-bit access not found."); #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ -#define onechar(c, s, l) (((uint64_t)(c)) << (s)) +# define onechar(c, s, l) (((uint64_t)(c)) << (s)) #else -#define onechar(c, s, l) (((uint64_t)(c)) << (l-8-s)) +# define onechar(c, s, l) (((uint64_t)(c)) << (l - 8 - s)) #endif /* Tokens for attribute and node names. */ -enum class atok_t_add_atom {NAME_PATTERN}; -constexpr const char *atok_lookup_t_add_atom[] = {"name_pattern"}; - - -enum class atok_t_add_region {SUBTILE, X_HIGH, X_LOW, Y_HIGH, Y_LOW}; -constexpr const char *atok_lookup_t_add_region[] = {"subtile", "x_high", "x_low", "y_high", "y_low"}; - -enum class gtok_t_partition {ADD_ATOM, ADD_REGION}; -constexpr const char *gtok_lookup_t_partition[] = {"add_atom", "add_region"}; -enum class atok_t_partition {NAME}; -constexpr const char *atok_lookup_t_partition[] = {"name"}; - -enum class gtok_t_partition_list {PARTITION}; -constexpr const char *gtok_lookup_t_partition_list[] = {"partition"}; - -enum class atok_t_set_global_signal {NAME, ROUTE_MODEL, TYPE}; -constexpr const char *atok_lookup_t_set_global_signal[] = {"name", "route_model", "type"}; - -enum class gtok_t_global_route_constraints {SET_GLOBAL_SIGNAL}; -constexpr const char *gtok_lookup_t_global_route_constraints[] = {"set_global_signal"}; -enum class gtok_t_vpr_constraints {PARTITION_LIST, GLOBAL_ROUTE_CONSTRAINTS}; -constexpr const char *gtok_lookup_t_vpr_constraints[] = {"partition_list", "global_route_constraints"}; -enum class atok_t_vpr_constraints {TOOL_NAME}; -constexpr const char *atok_lookup_t_vpr_constraints[] = {"tool_name"}; - +enum class atok_t_add_atom { NAME_PATTERN }; +constexpr const char* atok_lookup_t_add_atom[] = {"name_pattern"}; + +enum class atok_t_add_region { SUBTILE, + X_HIGH, + X_LOW, + Y_HIGH, + Y_LOW }; +constexpr const char* atok_lookup_t_add_region[] = {"subtile", "x_high", "x_low", "y_high", "y_low"}; + +enum class gtok_t_partition { ADD_ATOM, + ADD_REGION }; +constexpr const char* gtok_lookup_t_partition[] = {"add_atom", "add_region"}; +enum class atok_t_partition { NAME }; +constexpr const char* atok_lookup_t_partition[] = {"name"}; + +enum class gtok_t_partition_list { PARTITION }; +constexpr const char* gtok_lookup_t_partition_list[] = {"partition"}; + +enum class atok_t_set_global_signal { NAME, + ROUTE_MODEL, + TYPE }; +constexpr const char* atok_lookup_t_set_global_signal[] = {"name", "route_model", "type"}; + +enum class gtok_t_global_route_constraints { SET_GLOBAL_SIGNAL }; +constexpr const char* gtok_lookup_t_global_route_constraints[] = {"set_global_signal"}; +enum class gtok_t_vpr_constraints { PARTITION_LIST, + GLOBAL_ROUTE_CONSTRAINTS }; +constexpr const char* gtok_lookup_t_vpr_constraints[] = {"partition_list", "global_route_constraints"}; +enum class atok_t_vpr_constraints { TOOL_NAME }; +constexpr const char* atok_lookup_t_vpr_constraints[] = {"tool_name"}; /* Internal lexers. These convert the PugiXML node names to input tokens. */ -inline atok_t_add_atom lex_attr_t_add_atom(const char *in, const std::function * report_error){ - unsigned int len = strlen(in); - switch(len){ - case 12: - switch(*((triehash_uu64*)&in[0])){ - case onechar('n', 0, 64) | onechar('a', 8, 64) | onechar('m', 16, 64) | onechar('e', 24, 64) | onechar('_', 32, 64) | onechar('p', 40, 64) | onechar('a', 48, 64) | onechar('t', 56, 64): - switch(*((triehash_uu32*)&in[8])){ - case onechar('t', 0, 32) | onechar('e', 8, 32) | onechar('r', 16, 32) | onechar('n', 24, 32): - return atok_t_add_atom::NAME_PATTERN; - break; - default: break; - } - break; - default: break; - } - break; - default: break; - } - noreturn_report(report_error, ("Found unrecognized attribute " + std::string(in) + " of .").c_str()); +inline atok_t_add_atom lex_attr_t_add_atom(const char* in, const std::function* report_error) { + unsigned int len = strlen(in); + switch (len) { + case 12: + switch (*((triehash_uu64*)&in[0])) { + case onechar('n', 0, 64) | onechar('a', 8, 64) | onechar('m', 16, 64) | onechar('e', 24, 64) | onechar('_', 32, 64) | onechar('p', 40, 64) | onechar('a', 48, 64) | onechar('t', 56, 64): + switch (*((triehash_uu32*)&in[8])) { + case onechar('t', 0, 32) | onechar('e', 8, 32) | onechar('r', 16, 32) | onechar('n', 24, 32): + return atok_t_add_atom::NAME_PATTERN; + break; + default: + break; + } + break; + default: + break; + } + break; + default: + break; + } + noreturn_report(report_error, ("Found unrecognized attribute " + std::string(in) + " of .").c_str()); } -inline atok_t_add_region lex_attr_t_add_region(const char *in, const std::function * report_error){ - unsigned int len = strlen(in); - switch(len){ - case 5: - switch(*((triehash_uu32*)&in[0])){ - case onechar('x', 0, 32) | onechar('_', 8, 32) | onechar('l', 16, 32) | onechar('o', 24, 32): - switch(in[4]){ - case onechar('w', 0, 8): - return atok_t_add_region::X_LOW; - break; - default: break; - } - break; - case onechar('y', 0, 32) | onechar('_', 8, 32) | onechar('l', 16, 32) | onechar('o', 24, 32): - switch(in[4]){ - case onechar('w', 0, 8): - return atok_t_add_region::Y_LOW; - break; - default: break; - } - break; - default: break; - } - break; - case 6: - switch(*((triehash_uu32*)&in[0])){ - case onechar('x', 0, 32) | onechar('_', 8, 32) | onechar('h', 16, 32) | onechar('i', 24, 32): - switch(in[4]){ - case onechar('g', 0, 8): - switch(in[5]){ - case onechar('h', 0, 8): - return atok_t_add_region::X_HIGH; - break; - default: break; - } - break; - default: break; - } - break; - case onechar('y', 0, 32) | onechar('_', 8, 32) | onechar('h', 16, 32) | onechar('i', 24, 32): - switch(in[4]){ - case onechar('g', 0, 8): - switch(in[5]){ - case onechar('h', 0, 8): - return atok_t_add_region::Y_HIGH; - break; - default: break; - } - break; - default: break; - } - break; - default: break; - } - break; - case 7: - switch(*((triehash_uu32*)&in[0])){ - case onechar('s', 0, 32) | onechar('u', 8, 32) | onechar('b', 16, 32) | onechar('t', 24, 32): - switch(in[4]){ - case onechar('i', 0, 8): - switch(in[5]){ - case onechar('l', 0, 8): - switch(in[6]){ - case onechar('e', 0, 8): - return atok_t_add_region::SUBTILE; - break; - default: break; - } - break; - default: break; - } - break; - default: break; - } - break; - default: break; - } - break; - default: break; - } - noreturn_report(report_error, ("Found unrecognized attribute " + std::string(in) + " of .").c_str()); +inline atok_t_add_region lex_attr_t_add_region(const char* in, const std::function* report_error) { + unsigned int len = strlen(in); + switch (len) { + case 5: + switch (*((triehash_uu32*)&in[0])) { + case onechar('x', 0, 32) | onechar('_', 8, 32) | onechar('l', 16, 32) | onechar('o', 24, 32): + switch (in[4]) { + case onechar('w', 0, 8): + return atok_t_add_region::X_LOW; + break; + default: + break; + } + break; + case onechar('y', 0, 32) | onechar('_', 8, 32) | onechar('l', 16, 32) | onechar('o', 24, 32): + switch (in[4]) { + case onechar('w', 0, 8): + return atok_t_add_region::Y_LOW; + break; + default: + break; + } + break; + default: + break; + } + break; + case 6: + switch (*((triehash_uu32*)&in[0])) { + case onechar('x', 0, 32) | onechar('_', 8, 32) | onechar('h', 16, 32) | onechar('i', 24, 32): + switch (in[4]) { + case onechar('g', 0, 8): + switch (in[5]) { + case onechar('h', 0, 8): + return atok_t_add_region::X_HIGH; + break; + default: + break; + } + break; + default: + break; + } + break; + case onechar('y', 0, 32) | onechar('_', 8, 32) | onechar('h', 16, 32) | onechar('i', 24, 32): + switch (in[4]) { + case onechar('g', 0, 8): + switch (in[5]) { + case onechar('h', 0, 8): + return atok_t_add_region::Y_HIGH; + break; + default: + break; + } + break; + default: + break; + } + break; + default: + break; + } + break; + case 7: + switch (*((triehash_uu32*)&in[0])) { + case onechar('s', 0, 32) | onechar('u', 8, 32) | onechar('b', 16, 32) | onechar('t', 24, 32): + switch (in[4]) { + case onechar('i', 0, 8): + switch (in[5]) { + case onechar('l', 0, 8): + switch (in[6]) { + case onechar('e', 0, 8): + return atok_t_add_region::SUBTILE; + break; + default: + break; + } + break; + default: + break; + } + break; + default: + break; + } + break; + default: + break; + } + break; + default: + break; + } + noreturn_report(report_error, ("Found unrecognized attribute " + std::string(in) + " of .").c_str()); } -inline gtok_t_partition lex_node_t_partition(const char *in, const std::function *report_error){ - unsigned int len = strlen(in); - switch(len){ - case 8: - switch(*((triehash_uu64*)&in[0])){ - case onechar('a', 0, 64) | onechar('d', 8, 64) | onechar('d', 16, 64) | onechar('_', 24, 64) | onechar('a', 32, 64) | onechar('t', 40, 64) | onechar('o', 48, 64) | onechar('m', 56, 64): - return gtok_t_partition::ADD_ATOM; - break; - default: break; - } - break; - case 10: - switch(*((triehash_uu64*)&in[0])){ - case onechar('a', 0, 64) | onechar('d', 8, 64) | onechar('d', 16, 64) | onechar('_', 24, 64) | onechar('r', 32, 64) | onechar('e', 40, 64) | onechar('g', 48, 64) | onechar('i', 56, 64): - switch(in[8]){ - case onechar('o', 0, 8): - switch(in[9]){ - case onechar('n', 0, 8): - return gtok_t_partition::ADD_REGION; - break; - default: break; - } - break; - default: break; - } - break; - default: break; - } - break; - default: break; - } - noreturn_report(report_error, ("Found unrecognized child " + std::string(in) + " of .").c_str()); +inline gtok_t_partition lex_node_t_partition(const char* in, const std::function* report_error) { + unsigned int len = strlen(in); + switch (len) { + case 8: + switch (*((triehash_uu64*)&in[0])) { + case onechar('a', 0, 64) | onechar('d', 8, 64) | onechar('d', 16, 64) | onechar('_', 24, 64) | onechar('a', 32, 64) | onechar('t', 40, 64) | onechar('o', 48, 64) | onechar('m', 56, 64): + return gtok_t_partition::ADD_ATOM; + break; + default: + break; + } + break; + case 10: + switch (*((triehash_uu64*)&in[0])) { + case onechar('a', 0, 64) | onechar('d', 8, 64) | onechar('d', 16, 64) | onechar('_', 24, 64) | onechar('r', 32, 64) | onechar('e', 40, 64) | onechar('g', 48, 64) | onechar('i', 56, 64): + switch (in[8]) { + case onechar('o', 0, 8): + switch (in[9]) { + case onechar('n', 0, 8): + return gtok_t_partition::ADD_REGION; + break; + default: + break; + } + break; + default: + break; + } + break; + default: + break; + } + break; + default: + break; + } + noreturn_report(report_error, ("Found unrecognized child " + std::string(in) + " of .").c_str()); } -inline atok_t_partition lex_attr_t_partition(const char *in, const std::function * report_error){ - unsigned int len = strlen(in); - switch(len){ - case 4: - switch(*((triehash_uu32*)&in[0])){ - case onechar('n', 0, 32) | onechar('a', 8, 32) | onechar('m', 16, 32) | onechar('e', 24, 32): - return atok_t_partition::NAME; - break; - default: break; - } - break; - default: break; - } - noreturn_report(report_error, ("Found unrecognized attribute " + std::string(in) + " of .").c_str()); +inline atok_t_partition lex_attr_t_partition(const char* in, const std::function* report_error) { + unsigned int len = strlen(in); + switch (len) { + case 4: + switch (*((triehash_uu32*)&in[0])) { + case onechar('n', 0, 32) | onechar('a', 8, 32) | onechar('m', 16, 32) | onechar('e', 24, 32): + return atok_t_partition::NAME; + break; + default: + break; + } + break; + default: + break; + } + noreturn_report(report_error, ("Found unrecognized attribute " + std::string(in) + " of .").c_str()); } -inline gtok_t_partition_list lex_node_t_partition_list(const char *in, const std::function *report_error){ - unsigned int len = strlen(in); - switch(len){ - case 9: - switch(*((triehash_uu64*)&in[0])){ - case onechar('p', 0, 64) | onechar('a', 8, 64) | onechar('r', 16, 64) | onechar('t', 24, 64) | onechar('i', 32, 64) | onechar('t', 40, 64) | onechar('i', 48, 64) | onechar('o', 56, 64): - switch(in[8]){ - case onechar('n', 0, 8): - return gtok_t_partition_list::PARTITION; - break; - default: break; - } - break; - default: break; - } - break; - default: break; - } - noreturn_report(report_error, ("Found unrecognized child " + std::string(in) + " of .").c_str()); +inline gtok_t_partition_list lex_node_t_partition_list(const char* in, const std::function* report_error) { + unsigned int len = strlen(in); + switch (len) { + case 9: + switch (*((triehash_uu64*)&in[0])) { + case onechar('p', 0, 64) | onechar('a', 8, 64) | onechar('r', 16, 64) | onechar('t', 24, 64) | onechar('i', 32, 64) | onechar('t', 40, 64) | onechar('i', 48, 64) | onechar('o', 56, 64): + switch (in[8]) { + case onechar('n', 0, 8): + return gtok_t_partition_list::PARTITION; + break; + default: + break; + } + break; + default: + break; + } + break; + default: + break; + } + noreturn_report(report_error, ("Found unrecognized child " + std::string(in) + " of .").c_str()); } -inline atok_t_set_global_signal lex_attr_t_set_global_signal(const char *in, const std::function * report_error){ - unsigned int len = strlen(in); - switch(len){ - case 4: - switch(*((triehash_uu32*)&in[0])){ - case onechar('n', 0, 32) | onechar('a', 8, 32) | onechar('m', 16, 32) | onechar('e', 24, 32): - return atok_t_set_global_signal::NAME; - break; - case onechar('t', 0, 32) | onechar('y', 8, 32) | onechar('p', 16, 32) | onechar('e', 24, 32): - return atok_t_set_global_signal::TYPE; - break; - default: break; - } - break; - case 11: - switch(*((triehash_uu64*)&in[0])){ - case onechar('r', 0, 64) | onechar('o', 8, 64) | onechar('u', 16, 64) | onechar('t', 24, 64) | onechar('e', 32, 64) | onechar('_', 40, 64) | onechar('m', 48, 64) | onechar('o', 56, 64): - switch(in[8]){ - case onechar('d', 0, 8): - switch(in[9]){ - case onechar('e', 0, 8): - switch(in[10]){ - case onechar('l', 0, 8): - return atok_t_set_global_signal::ROUTE_MODEL; - break; - default: break; - } - break; - default: break; - } - break; - default: break; - } - break; - default: break; - } - break; - default: break; - } - noreturn_report(report_error, ("Found unrecognized attribute " + std::string(in) + " of .").c_str()); +inline atok_t_set_global_signal lex_attr_t_set_global_signal(const char* in, const std::function* report_error) { + unsigned int len = strlen(in); + switch (len) { + case 4: + switch (*((triehash_uu32*)&in[0])) { + case onechar('n', 0, 32) | onechar('a', 8, 32) | onechar('m', 16, 32) | onechar('e', 24, 32): + return atok_t_set_global_signal::NAME; + break; + case onechar('t', 0, 32) | onechar('y', 8, 32) | onechar('p', 16, 32) | onechar('e', 24, 32): + return atok_t_set_global_signal::TYPE; + break; + default: + break; + } + break; + case 11: + switch (*((triehash_uu64*)&in[0])) { + case onechar('r', 0, 64) | onechar('o', 8, 64) | onechar('u', 16, 64) | onechar('t', 24, 64) | onechar('e', 32, 64) | onechar('_', 40, 64) | onechar('m', 48, 64) | onechar('o', 56, 64): + switch (in[8]) { + case onechar('d', 0, 8): + switch (in[9]) { + case onechar('e', 0, 8): + switch (in[10]) { + case onechar('l', 0, 8): + return atok_t_set_global_signal::ROUTE_MODEL; + break; + default: + break; + } + break; + default: + break; + } + break; + default: + break; + } + break; + default: + break; + } + break; + default: + break; + } + noreturn_report(report_error, ("Found unrecognized attribute " + std::string(in) + " of .").c_str()); } -inline gtok_t_global_route_constraints lex_node_t_global_route_constraints(const char *in, const std::function *report_error){ - unsigned int len = strlen(in); - switch(len){ - case 17: - switch(*((triehash_uu64*)&in[0])){ - case onechar('s', 0, 64) | onechar('e', 8, 64) | onechar('t', 16, 64) | onechar('_', 24, 64) | onechar('g', 32, 64) | onechar('l', 40, 64) | onechar('o', 48, 64) | onechar('b', 56, 64): - switch(*((triehash_uu64*)&in[8])){ - case onechar('a', 0, 64) | onechar('l', 8, 64) | onechar('_', 16, 64) | onechar('s', 24, 64) | onechar('i', 32, 64) | onechar('g', 40, 64) | onechar('n', 48, 64) | onechar('a', 56, 64): - switch(in[16]){ - case onechar('l', 0, 8): - return gtok_t_global_route_constraints::SET_GLOBAL_SIGNAL; - break; - default: break; - } - break; - default: break; - } - break; - default: break; - } - break; - default: break; - } - noreturn_report(report_error, ("Found unrecognized child " + std::string(in) + " of .").c_str()); +inline gtok_t_global_route_constraints lex_node_t_global_route_constraints(const char* in, const std::function* report_error) { + unsigned int len = strlen(in); + switch (len) { + case 17: + switch (*((triehash_uu64*)&in[0])) { + case onechar('s', 0, 64) | onechar('e', 8, 64) | onechar('t', 16, 64) | onechar('_', 24, 64) | onechar('g', 32, 64) | onechar('l', 40, 64) | onechar('o', 48, 64) | onechar('b', 56, 64): + switch (*((triehash_uu64*)&in[8])) { + case onechar('a', 0, 64) | onechar('l', 8, 64) | onechar('_', 16, 64) | onechar('s', 24, 64) | onechar('i', 32, 64) | onechar('g', 40, 64) | onechar('n', 48, 64) | onechar('a', 56, 64): + switch (in[16]) { + case onechar('l', 0, 8): + return gtok_t_global_route_constraints::SET_GLOBAL_SIGNAL; + break; + default: + break; + } + break; + default: + break; + } + break; + default: + break; + } + break; + default: + break; + } + noreturn_report(report_error, ("Found unrecognized child " + std::string(in) + " of .").c_str()); } -inline gtok_t_vpr_constraints lex_node_t_vpr_constraints(const char *in, const std::function *report_error){ - unsigned int len = strlen(in); - switch(len){ - case 14: - switch(*((triehash_uu64*)&in[0])){ - case onechar('p', 0, 64) | onechar('a', 8, 64) | onechar('r', 16, 64) | onechar('t', 24, 64) | onechar('i', 32, 64) | onechar('t', 40, 64) | onechar('i', 48, 64) | onechar('o', 56, 64): - switch(*((triehash_uu32*)&in[8])){ - case onechar('n', 0, 32) | onechar('_', 8, 32) | onechar('l', 16, 32) | onechar('i', 24, 32): - switch(in[12]){ - case onechar('s', 0, 8): - switch(in[13]){ - case onechar('t', 0, 8): - return gtok_t_vpr_constraints::PARTITION_LIST; - break; - default: break; - } - break; - default: break; - } - break; - default: break; - } - break; - default: break; - } - break; - case 24: - switch(*((triehash_uu64*)&in[0])){ - case onechar('g', 0, 64) | onechar('l', 8, 64) | onechar('o', 16, 64) | onechar('b', 24, 64) | onechar('a', 32, 64) | onechar('l', 40, 64) | onechar('_', 48, 64) | onechar('r', 56, 64): - switch(*((triehash_uu64*)&in[8])){ - case onechar('o', 0, 64) | onechar('u', 8, 64) | onechar('t', 16, 64) | onechar('e', 24, 64) | onechar('_', 32, 64) | onechar('c', 40, 64) | onechar('o', 48, 64) | onechar('n', 56, 64): - switch(*((triehash_uu64*)&in[16])){ - case onechar('s', 0, 64) | onechar('t', 8, 64) | onechar('r', 16, 64) | onechar('a', 24, 64) | onechar('i', 32, 64) | onechar('n', 40, 64) | onechar('t', 48, 64) | onechar('s', 56, 64): - return gtok_t_vpr_constraints::GLOBAL_ROUTE_CONSTRAINTS; - break; - default: break; - } - break; - default: break; - } - break; - default: break; - } - break; - default: break; - } - noreturn_report(report_error, ("Found unrecognized child " + std::string(in) + " of .").c_str()); +inline gtok_t_vpr_constraints lex_node_t_vpr_constraints(const char* in, const std::function* report_error) { + unsigned int len = strlen(in); + switch (len) { + case 14: + switch (*((triehash_uu64*)&in[0])) { + case onechar('p', 0, 64) | onechar('a', 8, 64) | onechar('r', 16, 64) | onechar('t', 24, 64) | onechar('i', 32, 64) | onechar('t', 40, 64) | onechar('i', 48, 64) | onechar('o', 56, 64): + switch (*((triehash_uu32*)&in[8])) { + case onechar('n', 0, 32) | onechar('_', 8, 32) | onechar('l', 16, 32) | onechar('i', 24, 32): + switch (in[12]) { + case onechar('s', 0, 8): + switch (in[13]) { + case onechar('t', 0, 8): + return gtok_t_vpr_constraints::PARTITION_LIST; + break; + default: + break; + } + break; + default: + break; + } + break; + default: + break; + } + break; + default: + break; + } + break; + case 24: + switch (*((triehash_uu64*)&in[0])) { + case onechar('g', 0, 64) | onechar('l', 8, 64) | onechar('o', 16, 64) | onechar('b', 24, 64) | onechar('a', 32, 64) | onechar('l', 40, 64) | onechar('_', 48, 64) | onechar('r', 56, 64): + switch (*((triehash_uu64*)&in[8])) { + case onechar('o', 0, 64) | onechar('u', 8, 64) | onechar('t', 16, 64) | onechar('e', 24, 64) | onechar('_', 32, 64) | onechar('c', 40, 64) | onechar('o', 48, 64) | onechar('n', 56, 64): + switch (*((triehash_uu64*)&in[16])) { + case onechar('s', 0, 64) | onechar('t', 8, 64) | onechar('r', 16, 64) | onechar('a', 24, 64) | onechar('i', 32, 64) | onechar('n', 40, 64) | onechar('t', 48, 64) | onechar('s', 56, 64): + return gtok_t_vpr_constraints::GLOBAL_ROUTE_CONSTRAINTS; + break; + default: + break; + } + break; + default: + break; + } + break; + default: + break; + } + break; + default: + break; + } + noreturn_report(report_error, ("Found unrecognized child " + std::string(in) + " of .").c_str()); } -inline atok_t_vpr_constraints lex_attr_t_vpr_constraints(const char *in, const std::function * report_error){ - unsigned int len = strlen(in); - switch(len){ - case 9: - switch(*((triehash_uu64*)&in[0])){ - case onechar('t', 0, 64) | onechar('o', 8, 64) | onechar('o', 16, 64) | onechar('l', 24, 64) | onechar('_', 32, 64) | onechar('n', 40, 64) | onechar('a', 48, 64) | onechar('m', 56, 64): - switch(in[8]){ - case onechar('e', 0, 8): - return atok_t_vpr_constraints::TOOL_NAME; - break; - default: break; - } - break; - default: break; - } - break; - default: break; - } - noreturn_report(report_error, ("Found unrecognized attribute " + std::string(in) + " of .").c_str()); +inline atok_t_vpr_constraints lex_attr_t_vpr_constraints(const char* in, const std::function* report_error) { + unsigned int len = strlen(in); + switch (len) { + case 9: + switch (*((triehash_uu64*)&in[0])) { + case onechar('t', 0, 64) | onechar('o', 8, 64) | onechar('o', 16, 64) | onechar('l', 24, 64) | onechar('_', 32, 64) | onechar('n', 40, 64) | onechar('a', 48, 64) | onechar('m', 56, 64): + switch (in[8]) { + case onechar('e', 0, 8): + return atok_t_vpr_constraints::TOOL_NAME; + break; + default: + break; + } + break; + default: + break; + } + break; + default: + break; + } + noreturn_report(report_error, ("Found unrecognized attribute " + std::string(in) + " of .").c_str()); } /** * Internal error function for xs:choice and xs:sequence validators. */ -[[noreturn]] inline void dfa_error(const char *wrong, const int *states, const char * const *lookup, int len, const std::function * report_error); +[[noreturn]] inline void dfa_error(const char* wrong, const int* states, const char* const* lookup, int len, const std::function* report_error); /** * Internal error function for attribute validators. */ template -[[noreturn]] inline void attr_error(std::bitset astate, const char * const *lookup, const std::function * report_error); - +[[noreturn]] inline void attr_error(std::bitset astate, const char* const* lookup, const std::function* report_error); /* Internal loading functions, which validate and load a PugiXML DOM tree into memory. */ -inline int load_int(const char *in, const std::function * report_error){ - int out; - out = std::strtol(in, NULL, 10); - if(errno != 0) - noreturn_report(report_error, ("Invalid value `" + std::string(in) + "` when loading into a int.").c_str()); - return out; +inline int load_int(const char* in, const std::function* report_error) { + int out; + out = std::strtol(in, NULL, 10); + if (errno != 0) + noreturn_report(report_error, ("Invalid value `" + std::string(in) + "` when loading into a int.").c_str()); + return out; } -inline void load_add_region_required_attributes(const pugi::xml_node &root, int * x_high, int * x_low, int * y_high, int * y_low, const std::function * report_error){ - std::bitset<5> astate = 0; - for(pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()){ - atok_t_add_region in = lex_attr_t_add_region(attr.name(), report_error); - if(astate[(int)in] == 0) astate[(int)in] = 1; - else noreturn_report(report_error, ("Duplicate attribute " + std::string(attr.name()) + " in .").c_str()); - switch(in){ - case atok_t_add_region::SUBTILE: - /* Attribute subtile set after element init */ - break; - case atok_t_add_region::X_HIGH: - *x_high = load_int(attr.value(), report_error); - break; - case atok_t_add_region::X_LOW: - *x_low = load_int(attr.value(), report_error); - break; - case atok_t_add_region::Y_HIGH: - *y_high = load_int(attr.value(), report_error); - break; - case atok_t_add_region::Y_LOW: - *y_low = load_int(attr.value(), report_error); - break; - default: break; /* Not possible. */ - } - } - std::bitset<5> test_astate = astate | std::bitset<5>(0b00001); - if(!test_astate.all()) attr_error(test_astate, atok_lookup_t_add_region, report_error); +inline void load_add_region_required_attributes(const pugi::xml_node& root, int* x_high, int* x_low, int* y_high, int* y_low, const std::function* report_error) { + std::bitset<5> astate = 0; + for (pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()) { + atok_t_add_region in = lex_attr_t_add_region(attr.name(), report_error); + if (astate[(int)in] == 0) + astate[(int)in] = 1; + else + noreturn_report(report_error, ("Duplicate attribute " + std::string(attr.name()) + " in .").c_str()); + switch (in) { + case atok_t_add_region::SUBTILE: + /* Attribute subtile set after element init */ + break; + case atok_t_add_region::X_HIGH: + *x_high = load_int(attr.value(), report_error); + break; + case atok_t_add_region::X_LOW: + *x_low = load_int(attr.value(), report_error); + break; + case atok_t_add_region::Y_HIGH: + *y_high = load_int(attr.value(), report_error); + break; + case atok_t_add_region::Y_LOW: + *y_low = load_int(attr.value(), report_error); + break; + default: + break; /* Not possible. */ + } + } + std::bitset<5> test_astate = astate | std::bitset<5>(0b00001); + if (!test_astate.all()) attr_error(test_astate, atok_lookup_t_add_region, report_error); } template -inline void load_add_atom(const pugi::xml_node &root, T &out, Context &context, const std::function *report_error, ptrdiff_t *offset_debug){ - (void)root; - (void)out; - (void)context; - (void)report_error; - // Update current file offset in case an error is encountered. - *offset_debug = root.offset_debug(); - - for(pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()){ - atok_t_add_atom in = lex_attr_t_add_atom(attr.name(), report_error); - switch(in){ - case atok_t_add_atom::NAME_PATTERN: - out.set_add_atom_name_pattern(attr.value(), context); - break; - default: break; /* Not possible. */ - } - } - - if(root.first_child().type() == pugi::node_element) - noreturn_report(report_error, "Unexpected child element in ."); - +inline void load_add_atom(const pugi::xml_node& root, T& out, Context& context, const std::function* report_error, ptrdiff_t* offset_debug) { + (void)root; + (void)out; + (void)context; + (void)report_error; + // Update current file offset in case an error is encountered. + *offset_debug = root.offset_debug(); + + for (pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()) { + atok_t_add_atom in = lex_attr_t_add_atom(attr.name(), report_error); + switch (in) { + case atok_t_add_atom::NAME_PATTERN: + out.set_add_atom_name_pattern(attr.value(), context); + break; + default: + break; /* Not possible. */ + } + } + + if (root.first_child().type() == pugi::node_element) + noreturn_report(report_error, "Unexpected child element in ."); } template -inline void load_add_region(const pugi::xml_node &root, T &out, Context &context, const std::function *report_error, ptrdiff_t *offset_debug){ - (void)root; - (void)out; - (void)context; - (void)report_error; - // Update current file offset in case an error is encountered. - *offset_debug = root.offset_debug(); - - for(pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()){ - atok_t_add_region in = lex_attr_t_add_region(attr.name(), report_error); - switch(in){ - case atok_t_add_region::SUBTILE: - out.set_add_region_subtile(load_int(attr.value(), report_error), context); - break; - case atok_t_add_region::X_HIGH: - /* Attribute x_high is already set */ - break; - case atok_t_add_region::X_LOW: - /* Attribute x_low is already set */ - break; - case atok_t_add_region::Y_HIGH: - /* Attribute y_high is already set */ - break; - case atok_t_add_region::Y_LOW: - /* Attribute y_low is already set */ - break; - default: break; /* Not possible. */ - } - } - - if(root.first_child().type() == pugi::node_element) - noreturn_report(report_error, "Unexpected child element in ."); - +inline void load_add_region(const pugi::xml_node& root, T& out, Context& context, const std::function* report_error, ptrdiff_t* offset_debug) { + (void)root; + (void)out; + (void)context; + (void)report_error; + // Update current file offset in case an error is encountered. + *offset_debug = root.offset_debug(); + + for (pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()) { + atok_t_add_region in = lex_attr_t_add_region(attr.name(), report_error); + switch (in) { + case atok_t_add_region::SUBTILE: + out.set_add_region_subtile(load_int(attr.value(), report_error), context); + break; + case atok_t_add_region::X_HIGH: + /* Attribute x_high is already set */ + break; + case atok_t_add_region::X_LOW: + /* Attribute x_low is already set */ + break; + case atok_t_add_region::Y_HIGH: + /* Attribute y_high is already set */ + break; + case atok_t_add_region::Y_LOW: + /* Attribute y_low is already set */ + break; + default: + break; /* Not possible. */ + } + } + + if (root.first_child().type() == pugi::node_element) + noreturn_report(report_error, "Unexpected child element in ."); } constexpr int NUM_T_PARTITION_STATES = 2; constexpr const int NUM_T_PARTITION_INPUTS = 2; constexpr int gstate_t_partition[NUM_T_PARTITION_STATES][NUM_T_PARTITION_INPUTS] = { - {0, 0}, - {0, 0}, + {0, 0}, + {0, 0}, }; template -inline void load_partition(const pugi::xml_node &root, T &out, Context &context, const std::function *report_error, ptrdiff_t *offset_debug){ - (void)root; - (void)out; - (void)context; - (void)report_error; - // Update current file offset in case an error is encountered. - *offset_debug = root.offset_debug(); - - for(pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()){ - atok_t_partition in = lex_attr_t_partition(attr.name(), report_error); - switch(in){ - case atok_t_partition::NAME: - out.set_partition_name(attr.value(), context); - break; - default: break; /* Not possible. */ - } - } - - // Preallocate arrays by counting child nodes (if any) - size_t add_atom_count = 0; - size_t add_region_count = 0; - { - int next, state=1; - for(pugi::xml_node node = root.first_child(); node; node = node.next_sibling()) { - *offset_debug = node.offset_debug(); - gtok_t_partition in = lex_node_t_partition(node.name(), report_error); - next = gstate_t_partition[state][(int)in]; - if(next == -1) - dfa_error(gtok_lookup_t_partition[(int)in], gstate_t_partition[state], gtok_lookup_t_partition, 2, report_error); - state = next; - switch(in) { - case gtok_t_partition::ADD_ATOM: - add_atom_count += 1; - break; - case gtok_t_partition::ADD_REGION: - add_region_count += 1; - break; - default: break; /* Not possible. */ - } - } - - out.preallocate_partition_add_atom(context, add_atom_count); - out.preallocate_partition_add_region(context, add_region_count); - } - int next, state=1; - for(pugi::xml_node node = root.first_child(); node; node = node.next_sibling()){ - *offset_debug = node.offset_debug(); - gtok_t_partition in = lex_node_t_partition(node.name(), report_error); - next = gstate_t_partition[state][(int)in]; - if(next == -1) - dfa_error(gtok_lookup_t_partition[(int)in], gstate_t_partition[state], gtok_lookup_t_partition, 2, report_error); - state = next; - switch(in){ - case gtok_t_partition::ADD_ATOM: - { - auto child_context = out.add_partition_add_atom(context); - load_add_atom(node, out, child_context, report_error, offset_debug); - out.finish_partition_add_atom(child_context); - } - break; - case gtok_t_partition::ADD_REGION: - { - int add_region_x_high; - memset(&add_region_x_high, 0, sizeof(add_region_x_high)); - int add_region_x_low; - memset(&add_region_x_low, 0, sizeof(add_region_x_low)); - int add_region_y_high; - memset(&add_region_y_high, 0, sizeof(add_region_y_high)); - int add_region_y_low; - memset(&add_region_y_low, 0, sizeof(add_region_y_low)); - load_add_region_required_attributes(node, &add_region_x_high, &add_region_x_low, &add_region_y_high, &add_region_y_low, report_error); - auto child_context = out.add_partition_add_region(context, add_region_x_high, add_region_x_low, add_region_y_high, add_region_y_low); - load_add_region(node, out, child_context, report_error, offset_debug); - out.finish_partition_add_region(child_context); - } - break; - default: break; /* Not possible. */ - } - } - if(state != 0) dfa_error("end of input", gstate_t_partition[state], gtok_lookup_t_partition, 2, report_error); - +inline void load_partition(const pugi::xml_node& root, T& out, Context& context, const std::function* report_error, ptrdiff_t* offset_debug) { + (void)root; + (void)out; + (void)context; + (void)report_error; + // Update current file offset in case an error is encountered. + *offset_debug = root.offset_debug(); + + for (pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()) { + atok_t_partition in = lex_attr_t_partition(attr.name(), report_error); + switch (in) { + case atok_t_partition::NAME: + out.set_partition_name(attr.value(), context); + break; + default: + break; /* Not possible. */ + } + } + + // Preallocate arrays by counting child nodes (if any) + size_t add_atom_count = 0; + size_t add_region_count = 0; + { + int next, state = 1; + for (pugi::xml_node node = root.first_child(); node; node = node.next_sibling()) { + *offset_debug = node.offset_debug(); + gtok_t_partition in = lex_node_t_partition(node.name(), report_error); + next = gstate_t_partition[state][(int)in]; + if (next == -1) + dfa_error(gtok_lookup_t_partition[(int)in], gstate_t_partition[state], gtok_lookup_t_partition, 2, report_error); + state = next; + switch (in) { + case gtok_t_partition::ADD_ATOM: + add_atom_count += 1; + break; + case gtok_t_partition::ADD_REGION: + add_region_count += 1; + break; + default: + break; /* Not possible. */ + } + } + + out.preallocate_partition_add_atom(context, add_atom_count); + out.preallocate_partition_add_region(context, add_region_count); + } + int next, state = 1; + for (pugi::xml_node node = root.first_child(); node; node = node.next_sibling()) { + *offset_debug = node.offset_debug(); + gtok_t_partition in = lex_node_t_partition(node.name(), report_error); + next = gstate_t_partition[state][(int)in]; + if (next == -1) + dfa_error(gtok_lookup_t_partition[(int)in], gstate_t_partition[state], gtok_lookup_t_partition, 2, report_error); + state = next; + switch (in) { + case gtok_t_partition::ADD_ATOM: { + auto child_context = out.add_partition_add_atom(context); + load_add_atom(node, out, child_context, report_error, offset_debug); + out.finish_partition_add_atom(child_context); + } break; + case gtok_t_partition::ADD_REGION: { + int add_region_x_high; + memset(&add_region_x_high, 0, sizeof(add_region_x_high)); + int add_region_x_low; + memset(&add_region_x_low, 0, sizeof(add_region_x_low)); + int add_region_y_high; + memset(&add_region_y_high, 0, sizeof(add_region_y_high)); + int add_region_y_low; + memset(&add_region_y_low, 0, sizeof(add_region_y_low)); + load_add_region_required_attributes(node, &add_region_x_high, &add_region_x_low, &add_region_y_high, &add_region_y_low, report_error); + auto child_context = out.add_partition_add_region(context, add_region_x_high, add_region_x_low, add_region_y_high, add_region_y_low); + load_add_region(node, out, child_context, report_error, offset_debug); + out.finish_partition_add_region(child_context); + } break; + default: + break; /* Not possible. */ + } + } + if (state != 0) dfa_error("end of input", gstate_t_partition[state], gtok_lookup_t_partition, 2, report_error); } constexpr int NUM_T_PARTITION_LIST_STATES = 2; constexpr const int NUM_T_PARTITION_LIST_INPUTS = 1; constexpr int gstate_t_partition_list[NUM_T_PARTITION_LIST_STATES][NUM_T_PARTITION_LIST_INPUTS] = { - {0}, - {0}, + {0}, + {0}, }; template -inline void load_partition_list(const pugi::xml_node &root, T &out, Context &context, const std::function *report_error, ptrdiff_t *offset_debug){ - (void)root; - (void)out; - (void)context; - (void)report_error; - // Update current file offset in case an error is encountered. - *offset_debug = root.offset_debug(); - - if(root.first_attribute()) - noreturn_report(report_error, "Unexpected attribute in ."); - - // Preallocate arrays by counting child nodes (if any) - size_t partition_count = 0; - { - int next, state=1; - for(pugi::xml_node node = root.first_child(); node; node = node.next_sibling()) { - *offset_debug = node.offset_debug(); - gtok_t_partition_list in = lex_node_t_partition_list(node.name(), report_error); - next = gstate_t_partition_list[state][(int)in]; - if(next == -1) - dfa_error(gtok_lookup_t_partition_list[(int)in], gstate_t_partition_list[state], gtok_lookup_t_partition_list, 1, report_error); - state = next; - switch(in) { - case gtok_t_partition_list::PARTITION: - partition_count += 1; - break; - default: break; /* Not possible. */ - } - } - - out.preallocate_partition_list_partition(context, partition_count); - } - int next, state=1; - for(pugi::xml_node node = root.first_child(); node; node = node.next_sibling()){ - *offset_debug = node.offset_debug(); - gtok_t_partition_list in = lex_node_t_partition_list(node.name(), report_error); - next = gstate_t_partition_list[state][(int)in]; - if(next == -1) - dfa_error(gtok_lookup_t_partition_list[(int)in], gstate_t_partition_list[state], gtok_lookup_t_partition_list, 1, report_error); - state = next; - switch(in){ - case gtok_t_partition_list::PARTITION: - { - auto child_context = out.add_partition_list_partition(context); - load_partition(node, out, child_context, report_error, offset_debug); - out.finish_partition_list_partition(child_context); - } - break; - default: break; /* Not possible. */ - } - } - if(state != 0) dfa_error("end of input", gstate_t_partition_list[state], gtok_lookup_t_partition_list, 1, report_error); - +inline void load_partition_list(const pugi::xml_node& root, T& out, Context& context, const std::function* report_error, ptrdiff_t* offset_debug) { + (void)root; + (void)out; + (void)context; + (void)report_error; + // Update current file offset in case an error is encountered. + *offset_debug = root.offset_debug(); + + if (root.first_attribute()) + noreturn_report(report_error, "Unexpected attribute in ."); + + // Preallocate arrays by counting child nodes (if any) + size_t partition_count = 0; + { + int next, state = 1; + for (pugi::xml_node node = root.first_child(); node; node = node.next_sibling()) { + *offset_debug = node.offset_debug(); + gtok_t_partition_list in = lex_node_t_partition_list(node.name(), report_error); + next = gstate_t_partition_list[state][(int)in]; + if (next == -1) + dfa_error(gtok_lookup_t_partition_list[(int)in], gstate_t_partition_list[state], gtok_lookup_t_partition_list, 1, report_error); + state = next; + switch (in) { + case gtok_t_partition_list::PARTITION: + partition_count += 1; + break; + default: + break; /* Not possible. */ + } + } + + out.preallocate_partition_list_partition(context, partition_count); + } + int next, state = 1; + for (pugi::xml_node node = root.first_child(); node; node = node.next_sibling()) { + *offset_debug = node.offset_debug(); + gtok_t_partition_list in = lex_node_t_partition_list(node.name(), report_error); + next = gstate_t_partition_list[state][(int)in]; + if (next == -1) + dfa_error(gtok_lookup_t_partition_list[(int)in], gstate_t_partition_list[state], gtok_lookup_t_partition_list, 1, report_error); + state = next; + switch (in) { + case gtok_t_partition_list::PARTITION: { + auto child_context = out.add_partition_list_partition(context); + load_partition(node, out, child_context, report_error, offset_debug); + out.finish_partition_list_partition(child_context); + } break; + default: + break; /* Not possible. */ + } + } + if (state != 0) dfa_error("end of input", gstate_t_partition_list[state], gtok_lookup_t_partition_list, 1, report_error); } template -inline void load_set_global_signal(const pugi::xml_node &root, T &out, Context &context, const std::function *report_error, ptrdiff_t *offset_debug){ - (void)root; - (void)out; - (void)context; - (void)report_error; - // Update current file offset in case an error is encountered. - *offset_debug = root.offset_debug(); - - for(pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()){ - atok_t_set_global_signal in = lex_attr_t_set_global_signal(attr.name(), report_error); - switch(in){ - case atok_t_set_global_signal::NAME: - out.set_set_global_signal_name(attr.value(), context); - break; - case atok_t_set_global_signal::ROUTE_MODEL: - out.set_set_global_signal_route_model(attr.value(), context); - break; - case atok_t_set_global_signal::TYPE: - out.set_set_global_signal_type(attr.value(), context); - break; - default: break; /* Not possible. */ - } - } - - if(root.first_child().type() == pugi::node_element) - noreturn_report(report_error, "Unexpected child element in ."); - +inline void load_set_global_signal(const pugi::xml_node& root, T& out, Context& context, const std::function* report_error, ptrdiff_t* offset_debug) { + (void)root; + (void)out; + (void)context; + (void)report_error; + // Update current file offset in case an error is encountered. + *offset_debug = root.offset_debug(); + + for (pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()) { + atok_t_set_global_signal in = lex_attr_t_set_global_signal(attr.name(), report_error); + switch (in) { + case atok_t_set_global_signal::NAME: + out.set_set_global_signal_name(attr.value(), context); + break; + case atok_t_set_global_signal::ROUTE_MODEL: + out.set_set_global_signal_route_model(attr.value(), context); + break; + case atok_t_set_global_signal::TYPE: + out.set_set_global_signal_type(attr.value(), context); + break; + default: + break; /* Not possible. */ + } + } + + if (root.first_child().type() == pugi::node_element) + noreturn_report(report_error, "Unexpected child element in ."); } constexpr int NUM_T_GLOBAL_ROUTE_CONSTRAINTS_STATES = 2; constexpr const int NUM_T_GLOBAL_ROUTE_CONSTRAINTS_INPUTS = 1; constexpr int gstate_t_global_route_constraints[NUM_T_GLOBAL_ROUTE_CONSTRAINTS_STATES][NUM_T_GLOBAL_ROUTE_CONSTRAINTS_INPUTS] = { - {0}, - {0}, + {0}, + {0}, }; template -inline void load_global_route_constraints(const pugi::xml_node &root, T &out, Context &context, const std::function *report_error, ptrdiff_t *offset_debug){ - (void)root; - (void)out; - (void)context; - (void)report_error; - // Update current file offset in case an error is encountered. - *offset_debug = root.offset_debug(); - - if(root.first_attribute()) - noreturn_report(report_error, "Unexpected attribute in ."); - - // Preallocate arrays by counting child nodes (if any) - size_t set_global_signal_count = 0; - { - int next, state=1; - for(pugi::xml_node node = root.first_child(); node; node = node.next_sibling()) { - *offset_debug = node.offset_debug(); - gtok_t_global_route_constraints in = lex_node_t_global_route_constraints(node.name(), report_error); - next = gstate_t_global_route_constraints[state][(int)in]; - if(next == -1) - dfa_error(gtok_lookup_t_global_route_constraints[(int)in], gstate_t_global_route_constraints[state], gtok_lookup_t_global_route_constraints, 1, report_error); - state = next; - switch(in) { - case gtok_t_global_route_constraints::SET_GLOBAL_SIGNAL: - set_global_signal_count += 1; - break; - default: break; /* Not possible. */ - } - } - - out.preallocate_global_route_constraints_set_global_signal(context, set_global_signal_count); - } - int next, state=1; - for(pugi::xml_node node = root.first_child(); node; node = node.next_sibling()){ - *offset_debug = node.offset_debug(); - gtok_t_global_route_constraints in = lex_node_t_global_route_constraints(node.name(), report_error); - next = gstate_t_global_route_constraints[state][(int)in]; - if(next == -1) - dfa_error(gtok_lookup_t_global_route_constraints[(int)in], gstate_t_global_route_constraints[state], gtok_lookup_t_global_route_constraints, 1, report_error); - state = next; - switch(in){ - case gtok_t_global_route_constraints::SET_GLOBAL_SIGNAL: - { - auto child_context = out.add_global_route_constraints_set_global_signal(context); - load_set_global_signal(node, out, child_context, report_error, offset_debug); - out.finish_global_route_constraints_set_global_signal(child_context); - } - break; - default: break; /* Not possible. */ - } - } - if(state != 0) dfa_error("end of input", gstate_t_global_route_constraints[state], gtok_lookup_t_global_route_constraints, 1, report_error); - +inline void load_global_route_constraints(const pugi::xml_node& root, T& out, Context& context, const std::function* report_error, ptrdiff_t* offset_debug) { + (void)root; + (void)out; + (void)context; + (void)report_error; + // Update current file offset in case an error is encountered. + *offset_debug = root.offset_debug(); + + if (root.first_attribute()) + noreturn_report(report_error, "Unexpected attribute in ."); + + // Preallocate arrays by counting child nodes (if any) + size_t set_global_signal_count = 0; + { + int next, state = 1; + for (pugi::xml_node node = root.first_child(); node; node = node.next_sibling()) { + *offset_debug = node.offset_debug(); + gtok_t_global_route_constraints in = lex_node_t_global_route_constraints(node.name(), report_error); + next = gstate_t_global_route_constraints[state][(int)in]; + if (next == -1) + dfa_error(gtok_lookup_t_global_route_constraints[(int)in], gstate_t_global_route_constraints[state], gtok_lookup_t_global_route_constraints, 1, report_error); + state = next; + switch (in) { + case gtok_t_global_route_constraints::SET_GLOBAL_SIGNAL: + set_global_signal_count += 1; + break; + default: + break; /* Not possible. */ + } + } + + out.preallocate_global_route_constraints_set_global_signal(context, set_global_signal_count); + } + int next, state = 1; + for (pugi::xml_node node = root.first_child(); node; node = node.next_sibling()) { + *offset_debug = node.offset_debug(); + gtok_t_global_route_constraints in = lex_node_t_global_route_constraints(node.name(), report_error); + next = gstate_t_global_route_constraints[state][(int)in]; + if (next == -1) + dfa_error(gtok_lookup_t_global_route_constraints[(int)in], gstate_t_global_route_constraints[state], gtok_lookup_t_global_route_constraints, 1, report_error); + state = next; + switch (in) { + case gtok_t_global_route_constraints::SET_GLOBAL_SIGNAL: { + auto child_context = out.add_global_route_constraints_set_global_signal(context); + load_set_global_signal(node, out, child_context, report_error, offset_debug); + out.finish_global_route_constraints_set_global_signal(child_context); + } break; + default: + break; /* Not possible. */ + } + } + if (state != 0) dfa_error("end of input", gstate_t_global_route_constraints[state], gtok_lookup_t_global_route_constraints, 1, report_error); } constexpr int NUM_T_VPR_CONSTRAINTS_STATES = 1; constexpr const int NUM_T_VPR_CONSTRAINTS_INPUTS = 2; constexpr int gstate_t_vpr_constraints[NUM_T_VPR_CONSTRAINTS_STATES][NUM_T_VPR_CONSTRAINTS_INPUTS] = { - {0, 0}, + {0, 0}, }; template -inline void load_vpr_constraints(const pugi::xml_node &root, T &out, Context &context, const std::function *report_error, ptrdiff_t *offset_debug){ - (void)root; - (void)out; - (void)context; - (void)report_error; - // Update current file offset in case an error is encountered. - *offset_debug = root.offset_debug(); - - for(pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()){ - atok_t_vpr_constraints in = lex_attr_t_vpr_constraints(attr.name(), report_error); - switch(in){ - case atok_t_vpr_constraints::TOOL_NAME: - out.set_vpr_constraints_tool_name(attr.value(), context); - break; - default: break; /* Not possible. */ - } - } - - // Preallocate arrays by counting child nodes (if any) - size_t partition_list_count = 0; - size_t global_route_constraints_count = 0; - { - int next, state=0; - for(pugi::xml_node node = root.first_child(); node; node = node.next_sibling()) { - *offset_debug = node.offset_debug(); - gtok_t_vpr_constraints in = lex_node_t_vpr_constraints(node.name(), report_error); - next = gstate_t_vpr_constraints[state][(int)in]; - if(next == -1) - dfa_error(gtok_lookup_t_vpr_constraints[(int)in], gstate_t_vpr_constraints[state], gtok_lookup_t_vpr_constraints, 2, report_error); - state = next; - switch(in) { - case gtok_t_vpr_constraints::PARTITION_LIST: - partition_list_count += 1; - break; - case gtok_t_vpr_constraints::GLOBAL_ROUTE_CONSTRAINTS: - global_route_constraints_count += 1; - break; - default: break; /* Not possible. */ - } - } - - out.preallocate_vpr_constraints_partition_list(context, partition_list_count); - out.preallocate_vpr_constraints_global_route_constraints(context, global_route_constraints_count); - } - int next, state=0; - for(pugi::xml_node node = root.first_child(); node; node = node.next_sibling()){ - *offset_debug = node.offset_debug(); - gtok_t_vpr_constraints in = lex_node_t_vpr_constraints(node.name(), report_error); - next = gstate_t_vpr_constraints[state][(int)in]; - if(next == -1) - dfa_error(gtok_lookup_t_vpr_constraints[(int)in], gstate_t_vpr_constraints[state], gtok_lookup_t_vpr_constraints, 2, report_error); - state = next; - switch(in){ - case gtok_t_vpr_constraints::PARTITION_LIST: - { - auto child_context = out.add_vpr_constraints_partition_list(context); - load_partition_list(node, out, child_context, report_error, offset_debug); - out.finish_vpr_constraints_partition_list(child_context); - } - break; - case gtok_t_vpr_constraints::GLOBAL_ROUTE_CONSTRAINTS: - { - auto child_context = out.add_vpr_constraints_global_route_constraints(context); - load_global_route_constraints(node, out, child_context, report_error, offset_debug); - out.finish_vpr_constraints_global_route_constraints(child_context); - } - break; - default: break; /* Not possible. */ - } - } - if(state != 0) dfa_error("end of input", gstate_t_vpr_constraints[state], gtok_lookup_t_vpr_constraints, 2, report_error); - +inline void load_vpr_constraints(const pugi::xml_node& root, T& out, Context& context, const std::function* report_error, ptrdiff_t* offset_debug) { + (void)root; + (void)out; + (void)context; + (void)report_error; + // Update current file offset in case an error is encountered. + *offset_debug = root.offset_debug(); + + for (pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()) { + atok_t_vpr_constraints in = lex_attr_t_vpr_constraints(attr.name(), report_error); + switch (in) { + case atok_t_vpr_constraints::TOOL_NAME: + out.set_vpr_constraints_tool_name(attr.value(), context); + break; + default: + break; /* Not possible. */ + } + } + + // Preallocate arrays by counting child nodes (if any) + size_t partition_list_count = 0; + size_t global_route_constraints_count = 0; + { + int next, state = 0; + for (pugi::xml_node node = root.first_child(); node; node = node.next_sibling()) { + *offset_debug = node.offset_debug(); + gtok_t_vpr_constraints in = lex_node_t_vpr_constraints(node.name(), report_error); + next = gstate_t_vpr_constraints[state][(int)in]; + if (next == -1) + dfa_error(gtok_lookup_t_vpr_constraints[(int)in], gstate_t_vpr_constraints[state], gtok_lookup_t_vpr_constraints, 2, report_error); + state = next; + switch (in) { + case gtok_t_vpr_constraints::PARTITION_LIST: + partition_list_count += 1; + break; + case gtok_t_vpr_constraints::GLOBAL_ROUTE_CONSTRAINTS: + global_route_constraints_count += 1; + break; + default: + break; /* Not possible. */ + } + } + + out.preallocate_vpr_constraints_partition_list(context, partition_list_count); + out.preallocate_vpr_constraints_global_route_constraints(context, global_route_constraints_count); + } + int next, state = 0; + for (pugi::xml_node node = root.first_child(); node; node = node.next_sibling()) { + *offset_debug = node.offset_debug(); + gtok_t_vpr_constraints in = lex_node_t_vpr_constraints(node.name(), report_error); + next = gstate_t_vpr_constraints[state][(int)in]; + if (next == -1) + dfa_error(gtok_lookup_t_vpr_constraints[(int)in], gstate_t_vpr_constraints[state], gtok_lookup_t_vpr_constraints, 2, report_error); + state = next; + switch (in) { + case gtok_t_vpr_constraints::PARTITION_LIST: { + auto child_context = out.add_vpr_constraints_partition_list(context); + load_partition_list(node, out, child_context, report_error, offset_debug); + out.finish_vpr_constraints_partition_list(child_context); + } break; + case gtok_t_vpr_constraints::GLOBAL_ROUTE_CONSTRAINTS: { + auto child_context = out.add_vpr_constraints_global_route_constraints(context); + load_global_route_constraints(node, out, child_context, report_error, offset_debug); + out.finish_vpr_constraints_global_route_constraints(child_context); + } break; + default: + break; /* Not possible. */ + } + } + if (state != 0) dfa_error("end of input", gstate_t_vpr_constraints[state], gtok_lookup_t_vpr_constraints, 2, report_error); } - /* Internal writing functions, which uxsdcxx uses to write out a class. */ template -inline void write_partition(T &in, std::ostream &os, Context &context){ - (void)in; - (void)os; - (void)context; - { - for(size_t i=0, n=in.num_partition_add_atom(context); i\n"; - } - } - { - for(size_t i=0, n=in.num_partition_add_region(context); i\n"; - } - } +inline void write_partition(T& in, std::ostream& os, Context& context) { + (void)in; + (void)os; + (void)context; + { + for (size_t i = 0, n = in.num_partition_add_atom(context); i < n; i++) { + auto child_context = in.get_partition_add_atom(i, context); + os << "\n"; + } + } + { + for (size_t i = 0, n = in.num_partition_add_region(context); i < n; i++) { + auto child_context = in.get_partition_add_region(i, context); + os << "\n"; + } + } } template -inline void write_partition_list(T &in, std::ostream &os, Context &context){ - (void)in; - (void)os; - (void)context; - { - for(size_t i=0, n=in.num_partition_list_partition(context); i"; - write_partition(in, os, child_context); - os << "\n"; - } - } +inline void write_partition_list(T& in, std::ostream& os, Context& context) { + (void)in; + (void)os; + (void)context; + { + for (size_t i = 0, n = in.num_partition_list_partition(context); i < n; i++) { + auto child_context = in.get_partition_list_partition(i, context); + os << ""; + write_partition(in, os, child_context); + os << "\n"; + } + } } template -inline void write_global_route_constraints(T &in, std::ostream &os, Context &context){ - (void)in; - (void)os; - (void)context; - { - for(size_t i=0, n=in.num_global_route_constraints_set_global_signal(context); i\n"; - } - } +inline void write_global_route_constraints(T& in, std::ostream& os, Context& context) { + (void)in; + (void)os; + (void)context; + { + for (size_t i = 0, n = in.num_global_route_constraints_set_global_signal(context); i < n; i++) { + auto child_context = in.get_global_route_constraints_set_global_signal(i, context); + os << "\n"; + } + } } template -inline void write_vpr_constraints(T &in, std::ostream &os, Context &context){ - (void)in; - (void)os; - (void)context; - { - for(size_t i=0, n=in.num_vpr_constraints_partition_list(context); i\n"; - write_partition_list(in, os, child_context); - os << "\n"; - } - } - { - for(size_t i=0, n=in.num_vpr_constraints_global_route_constraints(context); i\n"; - write_global_route_constraints(in, os, child_context); - os << "\n"; - } - } +inline void write_vpr_constraints(T& in, std::ostream& os, Context& context) { + (void)in; + (void)os; + (void)context; + { + for (size_t i = 0, n = in.num_vpr_constraints_partition_list(context); i < n; i++) { + auto child_context = in.get_vpr_constraints_partition_list(i, context); + os << "\n"; + write_partition_list(in, os, child_context); + os << "\n"; + } + } + { + for (size_t i = 0, n = in.num_vpr_constraints_global_route_constraints(context); i < n; i++) { + auto child_context = in.get_vpr_constraints_global_route_constraints(i, context); + os << "\n"; + write_global_route_constraints(in, os, child_context); + os << "\n"; + } + } } -inline void dfa_error(const char *wrong, const int *states, const char * const *lookup, int len, const std::function * report_error){ - std::vector expected; - for(int i=0; i* report_error) { + std::vector expected; + for (int i = 0; i < len; i++) { + if (states[i] != -1) expected.push_back(lookup[i]); + } - std::string expected_or = expected[0]; - for(unsigned int i=1; i -inline void attr_error(std::bitset astate, const char * const *lookup, const std::function * report_error){ - std::vector missing; - for(unsigned int i=0; i astate, const char* const* lookup, const std::function* report_error) { + std::vector missing; + for (unsigned int i = 0; i < N; i++) { + if (astate[i] == 0) missing.push_back(lookup[i]); + } - std::string missing_and = missing[0]; - for(unsigned int i=1; i f(fopen(filename, "rb"), fclose); - - if (!f) { - throw std::runtime_error(std::string("Failed to open file") + filename); - } - - int current_line = 1; - std::ptrdiff_t offset = 0; - std::ptrdiff_t last_line_offset = 0; - std::ptrdiff_t current_line_offset = 0; - - char buffer[1024]; - std::size_t size; - - while ((size = fread(buffer, 1, sizeof(buffer), f.get())) > 0) { - for (std::size_t i = 0; i < size; ++i) { - if (buffer[i] == '\n') { - current_line += 1; - last_line_offset = current_line_offset; - current_line_offset = offset + i; - - if(target_offset < current_line_offset) { - if(target_offset < last_line_offset) { - throw std::runtime_error("Assertion violation"); - } - - *line = current_line - 1; - *col = target_offset - last_line_offset; - return; - } - } - } - - offset += size; - } - - *line = current_line; - *col = target_offset - current_line_offset; +inline void get_line_number(const char* filename, std::ptrdiff_t target_offset, int* line, int* col) { + std::unique_ptr f(fopen(filename, "rb"), fclose); + + if (!f) { + throw std::runtime_error(std::string("Failed to open file") + filename); + } + + int current_line = 1; + std::ptrdiff_t offset = 0; + std::ptrdiff_t last_line_offset = 0; + std::ptrdiff_t current_line_offset = 0; + + char buffer[1024]; + std::size_t size; + + while ((size = fread(buffer, 1, sizeof(buffer), f.get())) > 0) { + for (std::size_t i = 0; i < size; ++i) { + if (buffer[i] == '\n') { + current_line += 1; + last_line_offset = current_line_offset; + current_line_offset = offset + i; + + if (target_offset < current_line_offset) { + if (target_offset < last_line_offset) { + throw std::runtime_error("Assertion violation"); + } + + *line = current_line - 1; + *col = target_offset - last_line_offset; + return; + } + } + } + + offset += size; + } + + *line = current_line; + *col = target_offset - current_line_offset; } - } /* namespace uxsd */ diff --git a/vpr/src/base/gen/vpr_constraints_uxsdcxx_interface.h b/vpr/src/base/gen/vpr_constraints_uxsdcxx_interface.h index 39f24f91d5a..280bf58c793 100644 --- a/vpr/src/base/gen/vpr_constraints_uxsdcxx_interface.h +++ b/vpr/src/base/gen/vpr_constraints_uxsdcxx_interface.h @@ -11,7 +11,6 @@ #include - /* All uxsdcxx functions and structs live in this namespace. */ #include @@ -21,140 +20,140 @@ namespace uxsd { /* Base class for the schema. */ struct DefaultVprConstraintsContextTypes { -using AddAtomReadContext = void *; - using AddRegionReadContext = void *; - using PartitionReadContext = void *; - using PartitionListReadContext = void *; - using SetGlobalSignalReadContext = void *; - using GlobalRouteConstraintsReadContext = void *; - using VprConstraintsReadContext = void *; -using AddAtomWriteContext = void *; - using AddRegionWriteContext = void *; - using PartitionWriteContext = void *; - using PartitionListWriteContext = void *; - using SetGlobalSignalWriteContext = void *; - using GlobalRouteConstraintsWriteContext = void *; - using VprConstraintsWriteContext = void *; + using AddAtomReadContext = void*; + using AddRegionReadContext = void*; + using PartitionReadContext = void*; + using PartitionListReadContext = void*; + using SetGlobalSignalReadContext = void*; + using GlobalRouteConstraintsReadContext = void*; + using VprConstraintsReadContext = void*; + using AddAtomWriteContext = void*; + using AddRegionWriteContext = void*; + using PartitionWriteContext = void*; + using PartitionListWriteContext = void*; + using SetGlobalSignalWriteContext = void*; + using GlobalRouteConstraintsWriteContext = void*; + using VprConstraintsWriteContext = void*; }; -template +template class VprConstraintsBase { -public: - virtual ~VprConstraintsBase() {} - virtual void start_load(const std::function *report_error) = 0; - virtual void finish_load() = 0; - virtual void start_write() = 0; - virtual void finish_write() = 0; - virtual void error_encountered(const char * file, int line, const char *message) = 0; - /** Generated for complex type "add_atom": - * - * - * - */ - virtual inline const char * get_add_atom_name_pattern(typename ContextTypes::AddAtomReadContext &ctx) = 0; - virtual inline void set_add_atom_name_pattern(const char * name_pattern, typename ContextTypes::AddAtomWriteContext &ctx) = 0; + public: + virtual ~VprConstraintsBase() {} + virtual void start_load(const std::function* report_error) = 0; + virtual void finish_load() = 0; + virtual void start_write() = 0; + virtual void finish_write() = 0; + virtual void error_encountered(const char* file, int line, const char* message) = 0; + /** Generated for complex type "add_atom": + * + * + * + */ + virtual inline const char* get_add_atom_name_pattern(typename ContextTypes::AddAtomReadContext& ctx) = 0; + virtual inline void set_add_atom_name_pattern(const char* name_pattern, typename ContextTypes::AddAtomWriteContext& ctx) = 0; - /** Generated for complex type "add_region": - * - * - * - * - * - * - * - */ - virtual inline int get_add_region_subtile(typename ContextTypes::AddRegionReadContext &ctx) = 0; - virtual inline void set_add_region_subtile(int subtile, typename ContextTypes::AddRegionWriteContext &ctx) = 0; - virtual inline int get_add_region_x_high(typename ContextTypes::AddRegionReadContext &ctx) = 0; - virtual inline int get_add_region_x_low(typename ContextTypes::AddRegionReadContext &ctx) = 0; - virtual inline int get_add_region_y_high(typename ContextTypes::AddRegionReadContext &ctx) = 0; - virtual inline int get_add_region_y_low(typename ContextTypes::AddRegionReadContext &ctx) = 0; + /** Generated for complex type "add_region": + * + * + * + * + * + * + * + */ + virtual inline int get_add_region_subtile(typename ContextTypes::AddRegionReadContext& ctx) = 0; + virtual inline void set_add_region_subtile(int subtile, typename ContextTypes::AddRegionWriteContext& ctx) = 0; + virtual inline int get_add_region_x_high(typename ContextTypes::AddRegionReadContext& ctx) = 0; + virtual inline int get_add_region_x_low(typename ContextTypes::AddRegionReadContext& ctx) = 0; + virtual inline int get_add_region_y_high(typename ContextTypes::AddRegionReadContext& ctx) = 0; + virtual inline int get_add_region_y_low(typename ContextTypes::AddRegionReadContext& ctx) = 0; - /** Generated for complex type "partition": - * - * - * - * - * - * - * - * - * - */ - virtual inline const char * get_partition_name(typename ContextTypes::PartitionReadContext &ctx) = 0; - virtual inline void set_partition_name(const char * name, typename ContextTypes::PartitionWriteContext &ctx) = 0; - virtual inline void preallocate_partition_add_atom(typename ContextTypes::PartitionWriteContext &ctx, size_t size) = 0; - virtual inline typename ContextTypes::AddAtomWriteContext add_partition_add_atom(typename ContextTypes::PartitionWriteContext &ctx) = 0; - virtual inline void finish_partition_add_atom(typename ContextTypes::AddAtomWriteContext &ctx) = 0; - virtual inline size_t num_partition_add_atom(typename ContextTypes::PartitionReadContext &ctx) = 0; - virtual inline typename ContextTypes::AddAtomReadContext get_partition_add_atom(int n, typename ContextTypes::PartitionReadContext &ctx) = 0; - virtual inline void preallocate_partition_add_region(typename ContextTypes::PartitionWriteContext &ctx, size_t size) = 0; - virtual inline typename ContextTypes::AddRegionWriteContext add_partition_add_region(typename ContextTypes::PartitionWriteContext &ctx, int x_high, int x_low, int y_high, int y_low) = 0; - virtual inline void finish_partition_add_region(typename ContextTypes::AddRegionWriteContext &ctx) = 0; - virtual inline size_t num_partition_add_region(typename ContextTypes::PartitionReadContext &ctx) = 0; - virtual inline typename ContextTypes::AddRegionReadContext get_partition_add_region(int n, typename ContextTypes::PartitionReadContext &ctx) = 0; + /** Generated for complex type "partition": + * + * + * + * + * + * + * + * + * + */ + virtual inline const char* get_partition_name(typename ContextTypes::PartitionReadContext& ctx) = 0; + virtual inline void set_partition_name(const char* name, typename ContextTypes::PartitionWriteContext& ctx) = 0; + virtual inline void preallocate_partition_add_atom(typename ContextTypes::PartitionWriteContext& ctx, size_t size) = 0; + virtual inline typename ContextTypes::AddAtomWriteContext add_partition_add_atom(typename ContextTypes::PartitionWriteContext& ctx) = 0; + virtual inline void finish_partition_add_atom(typename ContextTypes::AddAtomWriteContext& ctx) = 0; + virtual inline size_t num_partition_add_atom(typename ContextTypes::PartitionReadContext& ctx) = 0; + virtual inline typename ContextTypes::AddAtomReadContext get_partition_add_atom(int n, typename ContextTypes::PartitionReadContext& ctx) = 0; + virtual inline void preallocate_partition_add_region(typename ContextTypes::PartitionWriteContext& ctx, size_t size) = 0; + virtual inline typename ContextTypes::AddRegionWriteContext add_partition_add_region(typename ContextTypes::PartitionWriteContext& ctx, int x_high, int x_low, int y_high, int y_low) = 0; + virtual inline void finish_partition_add_region(typename ContextTypes::AddRegionWriteContext& ctx) = 0; + virtual inline size_t num_partition_add_region(typename ContextTypes::PartitionReadContext& ctx) = 0; + virtual inline typename ContextTypes::AddRegionReadContext get_partition_add_region(int n, typename ContextTypes::PartitionReadContext& ctx) = 0; - /** Generated for complex type "partition_list": - * - * - * - * - * - */ - virtual inline void preallocate_partition_list_partition(typename ContextTypes::PartitionListWriteContext &ctx, size_t size) = 0; - virtual inline typename ContextTypes::PartitionWriteContext add_partition_list_partition(typename ContextTypes::PartitionListWriteContext &ctx) = 0; - virtual inline void finish_partition_list_partition(typename ContextTypes::PartitionWriteContext &ctx) = 0; - virtual inline size_t num_partition_list_partition(typename ContextTypes::PartitionListReadContext &ctx) = 0; - virtual inline typename ContextTypes::PartitionReadContext get_partition_list_partition(int n, typename ContextTypes::PartitionListReadContext &ctx) = 0; + /** Generated for complex type "partition_list": + * + * + * + * + * + */ + virtual inline void preallocate_partition_list_partition(typename ContextTypes::PartitionListWriteContext& ctx, size_t size) = 0; + virtual inline typename ContextTypes::PartitionWriteContext add_partition_list_partition(typename ContextTypes::PartitionListWriteContext& ctx) = 0; + virtual inline void finish_partition_list_partition(typename ContextTypes::PartitionWriteContext& ctx) = 0; + virtual inline size_t num_partition_list_partition(typename ContextTypes::PartitionListReadContext& ctx) = 0; + virtual inline typename ContextTypes::PartitionReadContext get_partition_list_partition(int n, typename ContextTypes::PartitionListReadContext& ctx) = 0; - /** Generated for complex type "set_global_signal": - * - * - * - * - * - */ - virtual inline const char * get_set_global_signal_name(typename ContextTypes::SetGlobalSignalReadContext &ctx) = 0; - virtual inline void set_set_global_signal_name(const char * name, typename ContextTypes::SetGlobalSignalWriteContext &ctx) = 0; - virtual inline const char * get_set_global_signal_route_model(typename ContextTypes::SetGlobalSignalReadContext &ctx) = 0; - virtual inline void set_set_global_signal_route_model(const char * route_model, typename ContextTypes::SetGlobalSignalWriteContext &ctx) = 0; - virtual inline const char * get_set_global_signal_type(typename ContextTypes::SetGlobalSignalReadContext &ctx) = 0; - virtual inline void set_set_global_signal_type(const char * type, typename ContextTypes::SetGlobalSignalWriteContext &ctx) = 0; + /** Generated for complex type "set_global_signal": + * + * + * + * + * + */ + virtual inline const char* get_set_global_signal_name(typename ContextTypes::SetGlobalSignalReadContext& ctx) = 0; + virtual inline void set_set_global_signal_name(const char* name, typename ContextTypes::SetGlobalSignalWriteContext& ctx) = 0; + virtual inline const char* get_set_global_signal_route_model(typename ContextTypes::SetGlobalSignalReadContext& ctx) = 0; + virtual inline void set_set_global_signal_route_model(const char* route_model, typename ContextTypes::SetGlobalSignalWriteContext& ctx) = 0; + virtual inline const char* get_set_global_signal_type(typename ContextTypes::SetGlobalSignalReadContext& ctx) = 0; + virtual inline void set_set_global_signal_type(const char* type, typename ContextTypes::SetGlobalSignalWriteContext& ctx) = 0; - /** Generated for complex type "global_route_constraints": - * - * - * - * - * - */ - virtual inline void preallocate_global_route_constraints_set_global_signal(typename ContextTypes::GlobalRouteConstraintsWriteContext &ctx, size_t size) = 0; - virtual inline typename ContextTypes::SetGlobalSignalWriteContext add_global_route_constraints_set_global_signal(typename ContextTypes::GlobalRouteConstraintsWriteContext &ctx) = 0; - virtual inline void finish_global_route_constraints_set_global_signal(typename ContextTypes::SetGlobalSignalWriteContext &ctx) = 0; - virtual inline size_t num_global_route_constraints_set_global_signal(typename ContextTypes::GlobalRouteConstraintsReadContext &ctx) = 0; - virtual inline typename ContextTypes::SetGlobalSignalReadContext get_global_route_constraints_set_global_signal(int n, typename ContextTypes::GlobalRouteConstraintsReadContext &ctx) = 0; + /** Generated for complex type "global_route_constraints": + * + * + * + * + * + */ + virtual inline void preallocate_global_route_constraints_set_global_signal(typename ContextTypes::GlobalRouteConstraintsWriteContext& ctx, size_t size) = 0; + virtual inline typename ContextTypes::SetGlobalSignalWriteContext add_global_route_constraints_set_global_signal(typename ContextTypes::GlobalRouteConstraintsWriteContext& ctx) = 0; + virtual inline void finish_global_route_constraints_set_global_signal(typename ContextTypes::SetGlobalSignalWriteContext& ctx) = 0; + virtual inline size_t num_global_route_constraints_set_global_signal(typename ContextTypes::GlobalRouteConstraintsReadContext& ctx) = 0; + virtual inline typename ContextTypes::SetGlobalSignalReadContext get_global_route_constraints_set_global_signal(int n, typename ContextTypes::GlobalRouteConstraintsReadContext& ctx) = 0; - /** Generated for complex type "vpr_constraints": - * - * - * - * - * - * - * - */ - virtual inline const char * get_vpr_constraints_tool_name(typename ContextTypes::VprConstraintsReadContext &ctx) = 0; - virtual inline void set_vpr_constraints_tool_name(const char * tool_name, typename ContextTypes::VprConstraintsWriteContext &ctx) = 0; - virtual inline void preallocate_vpr_constraints_partition_list(typename ContextTypes::VprConstraintsWriteContext &ctx, size_t size) = 0; - virtual inline typename ContextTypes::PartitionListWriteContext add_vpr_constraints_partition_list(typename ContextTypes::VprConstraintsWriteContext &ctx) = 0; - virtual inline void finish_vpr_constraints_partition_list(typename ContextTypes::PartitionListWriteContext &ctx) = 0; - virtual inline size_t num_vpr_constraints_partition_list(typename ContextTypes::VprConstraintsReadContext &ctx) = 0; - virtual inline typename ContextTypes::PartitionListReadContext get_vpr_constraints_partition_list(int n, typename ContextTypes::VprConstraintsReadContext &ctx) = 0; - virtual inline void preallocate_vpr_constraints_global_route_constraints(typename ContextTypes::VprConstraintsWriteContext &ctx, size_t size) = 0; - virtual inline typename ContextTypes::GlobalRouteConstraintsWriteContext add_vpr_constraints_global_route_constraints(typename ContextTypes::VprConstraintsWriteContext &ctx) = 0; - virtual inline void finish_vpr_constraints_global_route_constraints(typename ContextTypes::GlobalRouteConstraintsWriteContext &ctx) = 0; - virtual inline size_t num_vpr_constraints_global_route_constraints(typename ContextTypes::VprConstraintsReadContext &ctx) = 0; - virtual inline typename ContextTypes::GlobalRouteConstraintsReadContext get_vpr_constraints_global_route_constraints(int n, typename ContextTypes::VprConstraintsReadContext &ctx) = 0; + /** Generated for complex type "vpr_constraints": + * + * + * + * + * + * + * + */ + virtual inline const char* get_vpr_constraints_tool_name(typename ContextTypes::VprConstraintsReadContext& ctx) = 0; + virtual inline void set_vpr_constraints_tool_name(const char* tool_name, typename ContextTypes::VprConstraintsWriteContext& ctx) = 0; + virtual inline void preallocate_vpr_constraints_partition_list(typename ContextTypes::VprConstraintsWriteContext& ctx, size_t size) = 0; + virtual inline typename ContextTypes::PartitionListWriteContext add_vpr_constraints_partition_list(typename ContextTypes::VprConstraintsWriteContext& ctx) = 0; + virtual inline void finish_vpr_constraints_partition_list(typename ContextTypes::PartitionListWriteContext& ctx) = 0; + virtual inline size_t num_vpr_constraints_partition_list(typename ContextTypes::VprConstraintsReadContext& ctx) = 0; + virtual inline typename ContextTypes::PartitionListReadContext get_vpr_constraints_partition_list(int n, typename ContextTypes::VprConstraintsReadContext& ctx) = 0; + virtual inline void preallocate_vpr_constraints_global_route_constraints(typename ContextTypes::VprConstraintsWriteContext& ctx, size_t size) = 0; + virtual inline typename ContextTypes::GlobalRouteConstraintsWriteContext add_vpr_constraints_global_route_constraints(typename ContextTypes::VprConstraintsWriteContext& ctx) = 0; + virtual inline void finish_vpr_constraints_global_route_constraints(typename ContextTypes::GlobalRouteConstraintsWriteContext& ctx) = 0; + virtual inline size_t num_vpr_constraints_global_route_constraints(typename ContextTypes::VprConstraintsReadContext& ctx) = 0; + virtual inline typename ContextTypes::GlobalRouteConstraintsReadContext get_vpr_constraints_global_route_constraints(int n, typename ContextTypes::VprConstraintsReadContext& ctx) = 0; }; } /* namespace uxsd */ diff --git a/vpr/src/base/vpr_api.cpp b/vpr/src/base/vpr_api.cpp index 3911ecd16fb..2d48433521b 100644 --- a/vpr/src/base/vpr_api.cpp +++ b/vpr/src/base/vpr_api.cpp @@ -351,7 +351,7 @@ void vpr_init_with_options(const t_options* options, t_vpr_setup* vpr_setup, t_a if (!filename_opts.read_vpr_constraints_file.empty()) { load_vpr_constraints_file(filename_opts.read_vpr_constraints_file.c_str()); - // give a notificaiton on routing constraints overiding clock modeling + // give a notificaiton on routing constraints overiding clock modeling if (g_vpr_ctx.routing().constraints.get_route_constraint_num() && options->clock_modeling.provenance() == argparse::Provenance::SPECIFIED) { VTR_LOG_WARN("Route constraint(s) detected and will override clock modeling setting.\n"); } diff --git a/vpr/src/base/vpr_constraints.cpp b/vpr/src/base/vpr_constraints.cpp index 5dec3889dfe..eae4985c4f4 100644 --- a/vpr/src/base/vpr_constraints.cpp +++ b/vpr/src/base/vpr_constraints.cpp @@ -66,7 +66,7 @@ void VprConstraints::add_route_constraint(RouteConstraint rc) { RouteConstraint VprConstraints::get_route_constraint_by_net_name(std::string net_name) const { RouteConstraint rc; - auto const& rc_itr = route_constraints_.find(net_name); + auto const& rc_itr = route_constraints_.find(net_name); if (rc_itr == route_constraints_.end()) { rc.set_net_name("INVALID"); rc.set_net_type("INVALID"); @@ -88,9 +88,9 @@ RouteConstraint VprConstraints::get_route_constraint_by_idx(std::size_t idx) con } else { std::size_t i = 0; for (auto const& rc_itr : route_constraints_) { - if (i == idx) { - rc = rc_itr.second; - } + if (i == idx) { + rc = rc_itr.second; + } } } return rc; diff --git a/vpr/src/base/vpr_constraints_serializer.h b/vpr/src/base/vpr_constraints_serializer.h index ddfe531e587..b57756f5c7a 100644 --- a/vpr/src/base/vpr_constraints_serializer.h +++ b/vpr/src/base/vpr_constraints_serializer.h @@ -306,12 +306,12 @@ class VprConstraintsSerializer final : public uxsd::VprConstraintsBase - * - * - * - * - */ + * + * + * + * + * + */ virtual inline const char* get_set_global_signal_name(RouteConstraint& rc) final { return rc.get_net_name().c_str(); } @@ -335,12 +335,12 @@ class VprConstraintsSerializer final : public uxsd::VprConstraintsBase - * - * - * - * - */ + * + * + * + * + * + */ virtual inline void preallocate_global_route_constraints_set_global_signal(void*& /*ctx*/, size_t /*size*/) final {} virtual inline void* add_global_route_constraints_set_global_signal(void*& /*ctx*/) final { return nullptr; @@ -356,14 +356,14 @@ class VprConstraintsSerializer final : public uxsd::VprConstraintsBase - * - * - * - * - * - * - */ + * + * + * + * + * + * + * + */ virtual inline const char* get_vpr_constraints_tool_name(void*& /*ctx*/) final { return temp_.c_str(); } diff --git a/vpr/src/base/vpr_context.h b/vpr/src/base/vpr_context.h index 421f8e2958c..a05119fd06d 100644 --- a/vpr/src/base/vpr_context.h +++ b/vpr/src/base/vpr_context.h @@ -435,7 +435,7 @@ struct RoutingContext : public Context { /** * @brief Routing constraints, read only - */ + */ VprConstraints constraints; }; diff --git a/vpr/src/util/vpr_utils.cpp b/vpr/src/util/vpr_utils.cpp index 57bc95f4b36..80a54c0c47e 100644 --- a/vpr/src/util/vpr_utils.cpp +++ b/vpr/src/util/vpr_utils.cpp @@ -786,7 +786,7 @@ int get_max_primitives_in_pb_type(t_pb_type* pb_type) { for (j = 0; j < pb_type->modes[i].num_pb_type_children; j++) { temp_size += pb_type->modes[i].pb_type_children[j].num_pb * get_max_primitives_in_pb_type( - &pb_type->modes[i].pb_type_children[j]); + &pb_type->modes[i].pb_type_children[j]); } if (temp_size > max_size) { max_size = temp_size; @@ -809,7 +809,7 @@ int get_max_nets_in_pb_type(const t_pb_type* pb_type) { for (j = 0; j < pb_type->modes[i].num_pb_type_children; j++) { temp_nets += pb_type->modes[i].pb_type_children[j].num_pb * get_max_nets_in_pb_type( - &pb_type->modes[i].pb_type_children[j]); + &pb_type->modes[i].pb_type_children[j]); } if (temp_nets > max_nets) { max_nets = temp_nets; @@ -1535,7 +1535,7 @@ void free_pb_stats(t_pb* pb) { pb->pb_stats->num_pins_of_net_in_pb.clear(); if (pb->pb_stats->feasible_blocks) { - delete[] (pb->pb_stats->feasible_blocks); + delete[](pb->pb_stats->feasible_blocks); } if (!pb->parent_pb) { pb->pb_stats->transitive_fanout_candidates.clear(); From 5462d26a0f63798536a552b40e4842a88cd35fed Mon Sep 17 00:00:00 2001 From: Tao Li Date: Wed, 15 Feb 2023 13:42:04 -0800 Subject: [PATCH 116/147] Route constraint for local clock and reset. --- vpr/src/base/gen/vpr_constraints_uxsdcxx.h | 328 +++++++++++++++--- .../gen/vpr_constraints_uxsdcxx_interface.h | 55 ++- vpr/src/base/route_constraint.cpp | 43 +++ vpr/src/base/route_constraint.h | 65 ++++ vpr/src/base/vpr_api.cpp | 21 +- vpr/src/base/vpr_constraints.cpp | 64 ++++ vpr/src/base/vpr_constraints.h | 34 ++ vpr/src/base/vpr_constraints.xsd | 26 +- vpr/src/base/vpr_constraints_reader.cpp | 56 ++- vpr/src/base/vpr_constraints_reader.h | 2 +- vpr/src/base/vpr_constraints_serializer.h | 96 ++++- vpr/src/base/vpr_constraints_writer.cpp | 26 ++ vpr/src/base/vpr_constraints_writer.h | 2 + vpr/src/base/vpr_context.h | 5 + vpr/src/util/vpr_utils.cpp | 17 + vpr/src/util/vpr_utils.h | 4 + 16 files changed, 768 insertions(+), 76 deletions(-) create mode 100644 vpr/src/base/route_constraint.cpp create mode 100644 vpr/src/base/route_constraint.h diff --git a/vpr/src/base/gen/vpr_constraints_uxsdcxx.h b/vpr/src/base/gen/vpr_constraints_uxsdcxx.h index 3248c338281..12feabd08ab 100644 --- a/vpr/src/base/gen/vpr_constraints_uxsdcxx.h +++ b/vpr/src/base/gen/vpr_constraints_uxsdcxx.h @@ -4,9 +4,9 @@ * https://github.com/duck2/uxsdcxx * Modify only if your build process doesn't involve regenerating this file. * - * Cmdline: uxsdcxx.py vpr_constraints.xsd - * Input file: /home/khalid88/Documents/uxsdcxx/vpr_constraints.xsd - * md5sum of input file: 6b6011a6e6446347b234da82e517422e + * Cmdline: uxsdcxx.py /home/tao/works/dev/clock/vtr-verilog-to-routing/vpr/src/base/vpr_constraints.xsd + * Input file: /home/tao/works/dev/clock/vtr-verilog-to-routing/vpr/src/base/vpr_constraints.xsd + * md5sum of input file: 2d6f442d8044f76e8f1b1d276b7358da */ #include @@ -25,8 +25,6 @@ #include "pugixml.hpp" #include "vpr_constraints_uxsdcxx_interface.h" -#include "region.h" - /* All uxsdcxx functions and structs live in this namespace. */ namespace uxsd { @@ -52,6 +50,10 @@ inline void load_partition(const pugi::xml_node& root, T& out, Context& context, template inline void load_partition_list(const pugi::xml_node& root, T& out, Context& context, const std::function* report_error, ptrdiff_t* offset_debug); template +inline void load_set_global_signal(const pugi::xml_node& root, T& out, Context& context, const std::function* report_error, ptrdiff_t* offset_debug); +template +inline void load_global_route_constraints(const pugi::xml_node& root, T& out, Context& context, const std::function* report_error, ptrdiff_t* offset_debug); +template inline void load_vpr_constraints(const pugi::xml_node& root, T& out, Context& context, const std::function* report_error, ptrdiff_t* offset_debug); /* Declarations for internal write functions for the complex types. */ @@ -60,6 +62,8 @@ inline void write_partition(T& in, std::ostream& os, const void* data, void* ite template inline void write_partition_list(T& in, std::ostream& os, const void* data, void* iter); template +inline void write_global_route_constraints(T& in, std::ostream& os, const void* data, void* iter); +template inline void write_vpr_constraints(T& in, std::ostream& os, const void* data, void* iter); /* Load function for the root element. */ @@ -142,8 +146,17 @@ constexpr const char* atok_lookup_t_partition[] = {"name"}; enum class gtok_t_partition_list { PARTITION }; constexpr const char* gtok_lookup_t_partition_list[] = {"partition"}; -enum class gtok_t_vpr_constraints { PARTITION_LIST }; -constexpr const char* gtok_lookup_t_vpr_constraints[] = {"partition_list"}; + +enum class atok_t_set_global_signal { NAME, + ROUTE_MODEL, + TYPE }; +constexpr const char* atok_lookup_t_set_global_signal[] = {"name", "route_model", "type"}; + +enum class gtok_t_global_route_constraints { SET_GLOBAL_SIGNAL }; +constexpr const char* gtok_lookup_t_global_route_constraints[] = {"set_global_signal"}; +enum class gtok_t_vpr_constraints { PARTITION_LIST, + GLOBAL_ROUTE_CONSTRAINTS }; +constexpr const char* gtok_lookup_t_vpr_constraints[] = {"partition_list", "global_route_constraints"}; enum class atok_t_vpr_constraints { TOOL_NAME }; constexpr const char* atok_lookup_t_vpr_constraints[] = {"tool_name"}; @@ -348,6 +361,84 @@ inline gtok_t_partition_list lex_node_t_partition_list(const char* in, const std noreturn_report(report_error, ("Found unrecognized child " + std::string(in) + " of .").c_str()); } +inline atok_t_set_global_signal lex_attr_t_set_global_signal(const char* in, const std::function* report_error) { + unsigned int len = strlen(in); + switch (len) { + case 4: + switch (*((triehash_uu32*)&in[0])) { + case onechar('n', 0, 32) | onechar('a', 8, 32) | onechar('m', 16, 32) | onechar('e', 24, 32): + return atok_t_set_global_signal::NAME; + break; + case onechar('t', 0, 32) | onechar('y', 8, 32) | onechar('p', 16, 32) | onechar('e', 24, 32): + return atok_t_set_global_signal::TYPE; + break; + default: + break; + } + break; + case 11: + switch (*((triehash_uu64*)&in[0])) { + case onechar('r', 0, 64) | onechar('o', 8, 64) | onechar('u', 16, 64) | onechar('t', 24, 64) | onechar('e', 32, 64) | onechar('_', 40, 64) | onechar('m', 48, 64) | onechar('o', 56, 64): + switch (in[8]) { + case onechar('d', 0, 8): + switch (in[9]) { + case onechar('e', 0, 8): + switch (in[10]) { + case onechar('l', 0, 8): + return atok_t_set_global_signal::ROUTE_MODEL; + break; + default: + break; + } + break; + default: + break; + } + break; + default: + break; + } + break; + default: + break; + } + break; + default: + break; + } + noreturn_report(report_error, ("Found unrecognized attribute " + std::string(in) + " of .").c_str()); +} + +inline gtok_t_global_route_constraints lex_node_t_global_route_constraints(const char* in, const std::function* report_error) { + unsigned int len = strlen(in); + switch (len) { + case 17: + switch (*((triehash_uu64*)&in[0])) { + case onechar('s', 0, 64) | onechar('e', 8, 64) | onechar('t', 16, 64) | onechar('_', 24, 64) | onechar('g', 32, 64) | onechar('l', 40, 64) | onechar('o', 48, 64) | onechar('b', 56, 64): + switch (*((triehash_uu64*)&in[8])) { + case onechar('a', 0, 64) | onechar('l', 8, 64) | onechar('_', 16, 64) | onechar('s', 24, 64) | onechar('i', 32, 64) | onechar('g', 40, 64) | onechar('n', 48, 64) | onechar('a', 56, 64): + switch (in[16]) { + case onechar('l', 0, 8): + return gtok_t_global_route_constraints::SET_GLOBAL_SIGNAL; + break; + default: + break; + } + break; + default: + break; + } + break; + default: + break; + } + break; + default: + break; + } + noreturn_report(report_error, ("Found unrecognized child " + std::string(in) + " of .").c_str()); +} + inline gtok_t_vpr_constraints lex_node_t_vpr_constraints(const char* in, const std::function* report_error) { unsigned int len = strlen(in); switch (len) { @@ -378,6 +469,27 @@ inline gtok_t_vpr_constraints lex_node_t_vpr_constraints(const char* in, const s break; } break; + case 24: + switch (*((triehash_uu64*)&in[0])) { + case onechar('g', 0, 64) | onechar('l', 8, 64) | onechar('o', 16, 64) | onechar('b', 24, 64) | onechar('a', 32, 64) | onechar('l', 40, 64) | onechar('_', 48, 64) | onechar('r', 56, 64): + switch (*((triehash_uu64*)&in[8])) { + case onechar('o', 0, 64) | onechar('u', 8, 64) | onechar('t', 16, 64) | onechar('e', 24, 64) | onechar('_', 32, 64) | onechar('c', 40, 64) | onechar('o', 48, 64) | onechar('n', 56, 64): + switch (*((triehash_uu64*)&in[16])) { + case onechar('s', 0, 64) | onechar('t', 8, 64) | onechar('r', 16, 64) | onechar('a', 24, 64) | onechar('i', 32, 64) | onechar('n', 40, 64) | onechar('t', 48, 64) | onechar('s', 56, 64): + return gtok_t_vpr_constraints::GLOBAL_ROUTE_CONSTRAINTS; + break; + default: + break; + } + break; + default: + break; + } + break; + default: + break; + } + break; default: break; } @@ -412,12 +524,6 @@ inline atok_t_vpr_constraints lex_attr_t_vpr_constraints(const char* in, const s */ [[noreturn]] inline void dfa_error(const char* wrong, const int* states, const char* const* lookup, int len, const std::function* report_error); -/** - * Internal error function for xs:all validators. - */ -template -[[noreturn]] inline void all_error(std::bitset gstate, const char* const* lookup, const std::function* report_error); - /** * Internal error function for attribute validators. */ @@ -427,8 +533,6 @@ template /* Internal loading functions, which validate and load a PugiXML DOM tree into memory. */ inline int load_int(const char* in, const std::function* report_error) { int out; - // global variable, must set to 0 before using it to avoid changed by other errors - errno = 0; out = std::strtol(in, NULL, 10); if (errno != 0) noreturn_report(report_error, ("Invalid value `" + std::string(in) + "` when loading into a int.").c_str()); @@ -674,6 +778,102 @@ inline void load_partition_list(const pugi::xml_node& root, T& out, Context& con if (state != 0) dfa_error("end of input", gstate_t_partition_list[state], gtok_lookup_t_partition_list, 1, report_error); } +template +inline void load_set_global_signal(const pugi::xml_node& root, T& out, Context& context, const std::function* report_error, ptrdiff_t* offset_debug) { + (void)root; + (void)out; + (void)context; + (void)report_error; + // Update current file offset in case an error is encountered. + *offset_debug = root.offset_debug(); + + for (pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()) { + atok_t_set_global_signal in = lex_attr_t_set_global_signal(attr.name(), report_error); + switch (in) { + case atok_t_set_global_signal::NAME: + out.set_set_global_signal_name(attr.value(), context); + break; + case atok_t_set_global_signal::ROUTE_MODEL: + out.set_set_global_signal_route_model(attr.value(), context); + break; + case atok_t_set_global_signal::TYPE: + out.set_set_global_signal_type(attr.value(), context); + break; + default: + break; /* Not possible. */ + } + } + + if (root.first_child().type() == pugi::node_element) + noreturn_report(report_error, "Unexpected child element in ."); +} + +constexpr int NUM_T_GLOBAL_ROUTE_CONSTRAINTS_STATES = 2; +constexpr const int NUM_T_GLOBAL_ROUTE_CONSTRAINTS_INPUTS = 1; +constexpr int gstate_t_global_route_constraints[NUM_T_GLOBAL_ROUTE_CONSTRAINTS_STATES][NUM_T_GLOBAL_ROUTE_CONSTRAINTS_INPUTS] = { + {0}, + {0}, +}; +template +inline void load_global_route_constraints(const pugi::xml_node& root, T& out, Context& context, const std::function* report_error, ptrdiff_t* offset_debug) { + (void)root; + (void)out; + (void)context; + (void)report_error; + // Update current file offset in case an error is encountered. + *offset_debug = root.offset_debug(); + + if (root.first_attribute()) + noreturn_report(report_error, "Unexpected attribute in ."); + + // Preallocate arrays by counting child nodes (if any) + size_t set_global_signal_count = 0; + { + int next, state = 1; + for (pugi::xml_node node = root.first_child(); node; node = node.next_sibling()) { + *offset_debug = node.offset_debug(); + gtok_t_global_route_constraints in = lex_node_t_global_route_constraints(node.name(), report_error); + next = gstate_t_global_route_constraints[state][(int)in]; + if (next == -1) + dfa_error(gtok_lookup_t_global_route_constraints[(int)in], gstate_t_global_route_constraints[state], gtok_lookup_t_global_route_constraints, 1, report_error); + state = next; + switch (in) { + case gtok_t_global_route_constraints::SET_GLOBAL_SIGNAL: + set_global_signal_count += 1; + break; + default: + break; /* Not possible. */ + } + } + + out.preallocate_global_route_constraints_set_global_signal(context, set_global_signal_count); + } + int next, state = 1; + for (pugi::xml_node node = root.first_child(); node; node = node.next_sibling()) { + *offset_debug = node.offset_debug(); + gtok_t_global_route_constraints in = lex_node_t_global_route_constraints(node.name(), report_error); + next = gstate_t_global_route_constraints[state][(int)in]; + if (next == -1) + dfa_error(gtok_lookup_t_global_route_constraints[(int)in], gstate_t_global_route_constraints[state], gtok_lookup_t_global_route_constraints, 1, report_error); + state = next; + switch (in) { + case gtok_t_global_route_constraints::SET_GLOBAL_SIGNAL: { + auto child_context = out.add_global_route_constraints_set_global_signal(context); + load_set_global_signal(node, out, child_context, report_error, offset_debug); + out.finish_global_route_constraints_set_global_signal(child_context); + } break; + default: + break; /* Not possible. */ + } + } + if (state != 0) dfa_error("end of input", gstate_t_global_route_constraints[state], gtok_lookup_t_global_route_constraints, 1, report_error); +} + +constexpr int NUM_T_VPR_CONSTRAINTS_STATES = 1; +constexpr const int NUM_T_VPR_CONSTRAINTS_INPUTS = 2; +constexpr int gstate_t_vpr_constraints[NUM_T_VPR_CONSTRAINTS_STATES][NUM_T_VPR_CONSTRAINTS_INPUTS] = { + {0, 0}, +}; template inline void load_vpr_constraints(const pugi::xml_node& root, T& out, Context& context, const std::function* report_error, ptrdiff_t* offset_debug) { (void)root; @@ -694,26 +894,57 @@ inline void load_vpr_constraints(const pugi::xml_node& root, T& out, Context& co } } - std::bitset<1> gstate = 0; + // Preallocate arrays by counting child nodes (if any) + size_t partition_list_count = 0; + size_t global_route_constraints_count = 0; + { + int next, state = 0; + for (pugi::xml_node node = root.first_child(); node; node = node.next_sibling()) { + *offset_debug = node.offset_debug(); + gtok_t_vpr_constraints in = lex_node_t_vpr_constraints(node.name(), report_error); + next = gstate_t_vpr_constraints[state][(int)in]; + if (next == -1) + dfa_error(gtok_lookup_t_vpr_constraints[(int)in], gstate_t_vpr_constraints[state], gtok_lookup_t_vpr_constraints, 2, report_error); + state = next; + switch (in) { + case gtok_t_vpr_constraints::PARTITION_LIST: + partition_list_count += 1; + break; + case gtok_t_vpr_constraints::GLOBAL_ROUTE_CONSTRAINTS: + global_route_constraints_count += 1; + break; + default: + break; /* Not possible. */ + } + } + + out.preallocate_vpr_constraints_partition_list(context, partition_list_count); + out.preallocate_vpr_constraints_global_route_constraints(context, global_route_constraints_count); + } + int next, state = 0; for (pugi::xml_node node = root.first_child(); node; node = node.next_sibling()) { *offset_debug = node.offset_debug(); gtok_t_vpr_constraints in = lex_node_t_vpr_constraints(node.name(), report_error); - if (gstate[(int)in] == 0) - gstate[(int)in] = 1; - else - noreturn_report(report_error, ("Duplicate element " + std::string(node.name()) + " in .").c_str()); + next = gstate_t_vpr_constraints[state][(int)in]; + if (next == -1) + dfa_error(gtok_lookup_t_vpr_constraints[(int)in], gstate_t_vpr_constraints[state], gtok_lookup_t_vpr_constraints, 2, report_error); + state = next; switch (in) { case gtok_t_vpr_constraints::PARTITION_LIST: { - auto child_context = out.init_vpr_constraints_partition_list(context); + auto child_context = out.add_vpr_constraints_partition_list(context); load_partition_list(node, out, child_context, report_error, offset_debug); out.finish_vpr_constraints_partition_list(child_context); } break; + case gtok_t_vpr_constraints::GLOBAL_ROUTE_CONSTRAINTS: { + auto child_context = out.add_vpr_constraints_global_route_constraints(context); + load_global_route_constraints(node, out, child_context, report_error, offset_debug); + out.finish_vpr_constraints_global_route_constraints(child_context); + } break; default: break; /* Not possible. */ } } - std::bitset<1> test_gstate = gstate | std::bitset<1>(0b0); - if (!test_gstate.all()) all_error(test_gstate, gtok_lookup_t_vpr_constraints, report_error); + if (state != 0) dfa_error("end of input", gstate_t_vpr_constraints[state], gtok_lookup_t_vpr_constraints, 2, report_error); } /* Internal writing functions, which uxsdcxx uses to write out a class. */ @@ -734,7 +965,7 @@ inline void write_partition(T& in, std::ostream& os, Context& context) { for (size_t i = 0, n = in.num_partition_add_region(context); i < n; i++) { auto child_context = in.get_partition_add_region(i, context); os << " +inline void write_global_route_constraints(T& in, std::ostream& os, Context& context) { + (void)in; + (void)os; + (void)context; + { + for (size_t i = 0, n = in.num_global_route_constraints_set_global_signal(context); i < n; i++) { + auto child_context = in.get_global_route_constraints_set_global_signal(i, context); + os << "\n"; + } + } +} + template inline void write_vpr_constraints(T& in, std::ostream& os, Context& context) { (void)in; (void)os; (void)context; { - auto child_context = in.get_vpr_constraints_partition_list(context); - os << "\n"; - write_partition_list(in, os, child_context); - os << "\n"; + for (size_t i = 0, n = in.num_vpr_constraints_partition_list(context); i < n; i++) { + auto child_context = in.get_vpr_constraints_partition_list(i, context); + os << "\n"; + write_partition_list(in, os, child_context); + os << "\n"; + } + } + { + for (size_t i = 0, n = in.num_vpr_constraints_global_route_constraints(context); i < n; i++) { + auto child_context = in.get_vpr_constraints_global_route_constraints(i, context); + os << "\n"; + write_global_route_constraints(in, os, child_context); + os << "\n"; + } } } @@ -788,20 +1046,6 @@ inline void dfa_error(const char* wrong, const int* states, const char* const* l noreturn_report(report_error, ("Expected " + expected_or + ", found " + std::string(wrong)).c_str()); } -template -inline void all_error(std::bitset gstate, const char* const* lookup, const std::function* report_error) { - std::vector missing; - for (unsigned int i = 0; i < N; i++) { - if (gstate[i] == 0) missing.push_back(lookup[i]); - } - - std::string missing_and = missing[0]; - for (unsigned int i = 1; i < missing.size(); i++) - missing_and += std::string(", ") + missing[i]; - - noreturn_report(report_error, ("Didn't find required elements " + missing_and + ".").c_str()); -} - template inline void attr_error(std::bitset astate, const char* const* lookup, const std::function* report_error) { std::vector missing; diff --git a/vpr/src/base/gen/vpr_constraints_uxsdcxx_interface.h b/vpr/src/base/gen/vpr_constraints_uxsdcxx_interface.h index 6da8558b84d..280bf58c793 100644 --- a/vpr/src/base/gen/vpr_constraints_uxsdcxx_interface.h +++ b/vpr/src/base/gen/vpr_constraints_uxsdcxx_interface.h @@ -4,9 +4,9 @@ * https://github.com/duck2/uxsdcxx * Modify only if your build process doesn't involve regenerating this file. * - * Cmdline: uxsdcxx.py vpr_constraints.xsd - * Input file: /home/khalid88/Documents/uxsdcxx/vpr_constraints.xsd - * md5sum of input file: 6b6011a6e6446347b234da82e517422e + * Cmdline: uxsdcxx.py /home/tao/works/dev/clock/vtr-verilog-to-routing/vpr/src/base/vpr_constraints.xsd + * Input file: /home/tao/works/dev/clock/vtr-verilog-to-routing/vpr/src/base/vpr_constraints.xsd + * md5sum of input file: 2d6f442d8044f76e8f1b1d276b7358da */ #include @@ -24,11 +24,15 @@ struct DefaultVprConstraintsContextTypes { using AddRegionReadContext = void*; using PartitionReadContext = void*; using PartitionListReadContext = void*; + using SetGlobalSignalReadContext = void*; + using GlobalRouteConstraintsReadContext = void*; using VprConstraintsReadContext = void*; using AddAtomWriteContext = void*; using AddRegionWriteContext = void*; using PartitionWriteContext = void*; using PartitionListWriteContext = void*; + using SetGlobalSignalWriteContext = void*; + using GlobalRouteConstraintsWriteContext = void*; using VprConstraintsWriteContext = void*; }; @@ -92,7 +96,7 @@ class VprConstraintsBase { /** Generated for complex type "partition_list": * * - * + * * * */ @@ -102,19 +106,54 @@ class VprConstraintsBase { virtual inline size_t num_partition_list_partition(typename ContextTypes::PartitionListReadContext& ctx) = 0; virtual inline typename ContextTypes::PartitionReadContext get_partition_list_partition(int n, typename ContextTypes::PartitionListReadContext& ctx) = 0; + /** Generated for complex type "set_global_signal": + * + * + * + * + * + */ + virtual inline const char* get_set_global_signal_name(typename ContextTypes::SetGlobalSignalReadContext& ctx) = 0; + virtual inline void set_set_global_signal_name(const char* name, typename ContextTypes::SetGlobalSignalWriteContext& ctx) = 0; + virtual inline const char* get_set_global_signal_route_model(typename ContextTypes::SetGlobalSignalReadContext& ctx) = 0; + virtual inline void set_set_global_signal_route_model(const char* route_model, typename ContextTypes::SetGlobalSignalWriteContext& ctx) = 0; + virtual inline const char* get_set_global_signal_type(typename ContextTypes::SetGlobalSignalReadContext& ctx) = 0; + virtual inline void set_set_global_signal_type(const char* type, typename ContextTypes::SetGlobalSignalWriteContext& ctx) = 0; + + /** Generated for complex type "global_route_constraints": + * + * + * + * + * + */ + virtual inline void preallocate_global_route_constraints_set_global_signal(typename ContextTypes::GlobalRouteConstraintsWriteContext& ctx, size_t size) = 0; + virtual inline typename ContextTypes::SetGlobalSignalWriteContext add_global_route_constraints_set_global_signal(typename ContextTypes::GlobalRouteConstraintsWriteContext& ctx) = 0; + virtual inline void finish_global_route_constraints_set_global_signal(typename ContextTypes::SetGlobalSignalWriteContext& ctx) = 0; + virtual inline size_t num_global_route_constraints_set_global_signal(typename ContextTypes::GlobalRouteConstraintsReadContext& ctx) = 0; + virtual inline typename ContextTypes::SetGlobalSignalReadContext get_global_route_constraints_set_global_signal(int n, typename ContextTypes::GlobalRouteConstraintsReadContext& ctx) = 0; + /** Generated for complex type "vpr_constraints": * - * + * * - * + * + * * * */ virtual inline const char* get_vpr_constraints_tool_name(typename ContextTypes::VprConstraintsReadContext& ctx) = 0; virtual inline void set_vpr_constraints_tool_name(const char* tool_name, typename ContextTypes::VprConstraintsWriteContext& ctx) = 0; - virtual inline typename ContextTypes::PartitionListWriteContext init_vpr_constraints_partition_list(typename ContextTypes::VprConstraintsWriteContext& ctx) = 0; + virtual inline void preallocate_vpr_constraints_partition_list(typename ContextTypes::VprConstraintsWriteContext& ctx, size_t size) = 0; + virtual inline typename ContextTypes::PartitionListWriteContext add_vpr_constraints_partition_list(typename ContextTypes::VprConstraintsWriteContext& ctx) = 0; virtual inline void finish_vpr_constraints_partition_list(typename ContextTypes::PartitionListWriteContext& ctx) = 0; - virtual inline typename ContextTypes::PartitionListReadContext get_vpr_constraints_partition_list(typename ContextTypes::VprConstraintsReadContext& ctx) = 0; + virtual inline size_t num_vpr_constraints_partition_list(typename ContextTypes::VprConstraintsReadContext& ctx) = 0; + virtual inline typename ContextTypes::PartitionListReadContext get_vpr_constraints_partition_list(int n, typename ContextTypes::VprConstraintsReadContext& ctx) = 0; + virtual inline void preallocate_vpr_constraints_global_route_constraints(typename ContextTypes::VprConstraintsWriteContext& ctx, size_t size) = 0; + virtual inline typename ContextTypes::GlobalRouteConstraintsWriteContext add_vpr_constraints_global_route_constraints(typename ContextTypes::VprConstraintsWriteContext& ctx) = 0; + virtual inline void finish_vpr_constraints_global_route_constraints(typename ContextTypes::GlobalRouteConstraintsWriteContext& ctx) = 0; + virtual inline size_t num_vpr_constraints_global_route_constraints(typename ContextTypes::VprConstraintsReadContext& ctx) = 0; + virtual inline typename ContextTypes::GlobalRouteConstraintsReadContext get_vpr_constraints_global_route_constraints(int n, typename ContextTypes::VprConstraintsReadContext& ctx) = 0; }; } /* namespace uxsd */ diff --git a/vpr/src/base/route_constraint.cpp b/vpr/src/base/route_constraint.cpp new file mode 100644 index 00000000000..a7dadc3a1ec --- /dev/null +++ b/vpr/src/base/route_constraint.cpp @@ -0,0 +1,43 @@ +#include "route_constraint.h" + +RouteConstraint::RouteConstraint() { + net_name_ = std::string(""); + net_type_ = std::string(""); + route_method_ = std::string(""); + is_valid_ = false; +} + +void RouteConstraint::set_net_name(std::string name) { + net_name_ = name; + return; +} + +std::string RouteConstraint::get_net_name() const { + return net_name_; +} + +void RouteConstraint::set_net_type(std::string type) { + net_type_ = type; + return; +} + +std::string RouteConstraint::get_net_type() const { + return net_type_; +} + +void RouteConstraint::set_route_model(std::string route_method) { + route_method_ = route_method; + return; +} + +std::string RouteConstraint::get_route_model() const { + return route_method_; +} + +void RouteConstraint::set_is_valid(bool value) { + is_valid_ = value; +} + +bool RouteConstraint::get_is_valid() const { + return is_valid_; +} diff --git a/vpr/src/base/route_constraint.h b/vpr/src/base/route_constraint.h new file mode 100644 index 00000000000..50b967e3f31 --- /dev/null +++ b/vpr/src/base/route_constraint.h @@ -0,0 +1,65 @@ +#ifndef ROUTE_CONSTRAINT_H +#define ROUTE_CONSTRAINT_H + +#include "vpr_types.h" + +/** + * @file + * @brief This file defines the RouteConstraint class. + */ + +class RouteConstraint { + public: + /** + * @brief Constructor for the RouteConstraint class, sets member variables to invalid values + */ + RouteConstraint(); + + /** + * @brief get net name + */ + std::string get_net_name() const; + + /** + * @brief set net name + */ + void set_net_name(std::string); + + /** + * @brief get net type + */ + std::string get_net_type() const; + + /** + * @brief set net type + */ + void set_net_type(std::string); + + /** + * @brief get route model + */ + std::string get_route_model() const; + + /** + * @brief set route model + */ + void set_route_model(std::string); + + /** + * @brief set is valid + */ + void set_is_valid(bool); + + /** + * @brief get is valid + */ + bool get_is_valid() const; + + private: + std::string net_name_; + std::string net_type_; + std::string route_method_; + bool is_valid_; +}; + +#endif /* ROUTE_CONSTRAINT_H */ diff --git a/vpr/src/base/vpr_api.cpp b/vpr/src/base/vpr_api.cpp index 6a4fafc9a10..f8e481f3a24 100644 --- a/vpr/src/base/vpr_api.cpp +++ b/vpr/src/base/vpr_api.cpp @@ -346,10 +346,15 @@ void vpr_init_with_options(const t_options* options, t_vpr_setup* vpr_setup, t_a } } - //Initialize vpr floorplanning constraints + //Initialize vpr floorplanning and routing constraints auto& filename_opts = vpr_setup->FileNameOpts; if (!filename_opts.read_vpr_constraints_file.empty()) { - load_vpr_constraints_file(filename_opts.read_vpr_constraints_file.c_str()); + load_vpr_constraints_files(filename_opts.read_vpr_constraints_file.c_str()); + + // give a notificaiton on routing constraints overiding clock modeling + if (g_vpr_ctx.routing().constraints.get_route_constraint_num() && options->clock_modeling.provenance() == argparse::Provenance::SPECIFIED) { + VTR_LOG_WARN("Route constraint(s) detected and will override clock modeling setting.\n"); + } } fflush(stdout); @@ -696,7 +701,7 @@ bool vpr_place_flow(t_vpr_setup& vpr_setup, const t_arch& arch) { //Write out a vpr floorplanning constraints file if the option is specified if (!filename_opts.write_vpr_constraints_file.empty()) { - write_vpr_floorplan_constraints(filename_opts.write_vpr_constraints_file.c_str(), placer_opts.place_constraint_expand, placer_opts.place_constraint_subtile, + write_vpr_floorplan_constraints("vpr_floorplan_constraints.xml" /*filename_opts.write_vpr_constraints_file.c_str()*/, placer_opts.place_constraint_expand, placer_opts.place_constraint_subtile, placer_opts.floorplan_num_horizontal_partitions, placer_opts.floorplan_num_vertical_partitions); } @@ -766,6 +771,11 @@ RouteStatus vpr_route_flow(t_vpr_setup& vpr_setup, const t_arch& arch, bool is_f //Assume successful route_status = RouteStatus(true, -1); } else { //Do or load + + // apply route constraints + // use mutable routing context here to apply change on the constraints when binding the constraint to real net + apply_route_constraints(g_vpr_ctx.mutable_routing().constraints); + int chan_width = router_opts.fixed_channel_width; auto& cluster_ctx = g_vpr_ctx.clustering(); @@ -847,6 +857,11 @@ RouteStatus vpr_route_flow(t_vpr_setup& vpr_setup, const t_arch& arch, bool is_f //Update interactive graphics update_screen(ScreenUpdatePriority::MAJOR, graphics_msg.c_str(), ROUTING, timing_info); + + //Write out a vpr floorplanning constraints file if the option is specified + if (!filename_opts.write_vpr_constraints_file.empty()) { + write_vpr_route_constraints(g_vpr_ctx.routing().constraints, "vpr_route_constraints.xml" /*filename_opts.write_vpr_constraints_file.c_str()*/); + } } return route_status; diff --git a/vpr/src/base/vpr_constraints.cpp b/vpr/src/base/vpr_constraints.cpp index 95c7e7b7358..4b9850be670 100644 --- a/vpr/src/base/vpr_constraints.cpp +++ b/vpr/src/base/vpr_constraints.cpp @@ -1,5 +1,7 @@ #include "vpr_constraints.h" #include "partition.h" +#include "route_constraint.h" +#include void VprConstraints::add_constrained_atom(const AtomBlockId blk_id, const PartitionId part_id) { auto got = constrained_atoms.find(blk_id); @@ -58,6 +60,68 @@ PartitionRegion VprConstraints::get_partition_pr(PartitionId part_id) { return pr; } +void VprConstraints::add_route_constraint(RouteConstraint rc) { + route_constraints_.insert({rc.get_net_name(), rc}); + return; +} + +RouteConstraint VprConstraints::get_route_constraint_by_net_name(std::string net_name) { + RouteConstraint rc; + auto const& rc_itr = route_constraints_.find(net_name); + if (rc_itr == route_constraints_.end()) { + // try regexp + bool found_thru_regex = false; + for (auto constraint : route_constraints_) { + if (std::regex_match(net_name, std::regex(constraint.first))) { + { + rc = constraint.second; + + // mark as invalid so write constraint function will not write constraint + // of regexpr name + // instead a matched constraint is inerted in + constraint.second.set_is_valid(false); + rc.set_is_valid(true); + route_constraints_.insert({net_name, rc}); + + found_thru_regex = true; + break; + } + } + } + if (!found_thru_regex) { + rc.set_net_name("INVALID"); + rc.set_net_type("INVALID"); + rc.set_route_model("INVALID"); + rc.set_is_valid(false); + } + } else { + rc = rc_itr->second; + } + return rc; +} + +RouteConstraint VprConstraints::get_route_constraint_by_idx(std::size_t idx) const { + RouteConstraint rc; + if ((route_constraints_.size() == 0) || (idx > route_constraints_.size() - 1)) { + rc.set_net_name("INVALID"); + rc.set_net_type("INVALID"); + rc.set_route_model("INVALID"); + rc.set_is_valid(false); + } else { + std::size_t i = 0; + for (auto const& rc_itr : route_constraints_) { + if (i == idx) { + rc = rc_itr.second; + } + } + } + return rc; +} + +int VprConstraints::get_route_constraint_num(void) const { + return route_constraints_.size(); +} + void print_constraints(FILE* fp, VprConstraints constraints) { Partition temp_part; std::vector atoms; diff --git a/vpr/src/base/vpr_constraints.h b/vpr/src/base/vpr_constraints.h index fd3f64842a4..61d7ed9d6b6 100644 --- a/vpr/src/base/vpr_constraints.h +++ b/vpr/src/base/vpr_constraints.h @@ -5,6 +5,7 @@ #include "vpr_utils.h" #include "partition.h" #include "partition_region.h" +#include "route_constraint.h" /** * @file @@ -87,6 +88,34 @@ class VprConstraints { */ PartitionRegion get_partition_pr(PartitionId part_id); + /** + * @brief add route constraint + * + * @param net_name the route constraint + */ + void add_route_constraint(RouteConstraint rc); + + /** + * @brief returns route constraint by index + * + * @param index the constraint index + */ + RouteConstraint get_route_constraint_by_idx(std::size_t index) const; + + /** + * @brief returns route constraint of a specific net + * + * @param net_name the net name + */ + RouteConstraint get_route_constraint_by_net_name(std::string net_name); + + /** + * @brief returns number of route constraints + * + * @param void + */ + int get_route_constraint_num(void) const; + private: /** * Store all constrained atoms @@ -97,6 +126,11 @@ class VprConstraints { * Store all partitions */ vtr::vector partitions; + + /** + * store all route constraints + */ + std::unordered_map route_constraints_; }; ///@brief used to print floorplanning constraints data from a VprConstraints object diff --git a/vpr/src/base/vpr_constraints.xsd b/vpr/src/base/vpr_constraints.xsd index 406e2abcda4..2ed93b77347 100644 --- a/vpr/src/base/vpr_constraints.xsd +++ b/vpr/src/base/vpr_constraints.xsd @@ -59,16 +59,36 @@ + + + + + + + + + + + + + + + - + - - + + diff --git a/vpr/src/base/vpr_constraints_reader.cpp b/vpr/src/base/vpr_constraints_reader.cpp index 8e69b7b42b4..eec6d772490 100644 --- a/vpr/src/base/vpr_constraints_reader.cpp +++ b/vpr/src/base/vpr_constraints_reader.cpp @@ -10,31 +10,59 @@ #include #include "vpr_constraints_reader.h" +#include "vtr_token.h" -void load_vpr_constraints_file(const char* read_vpr_constraints_name) { - vtr::ScopedStartFinishTimer timer("Loading VPR constraints file"); +void load_vpr_constraints_files(const char* read_vpr_constraints_name) { + vtr::ScopedStartFinishTimer timer("Loading VPR constraints file(s)"); VprConstraintsSerializer reader; - if (vtr::check_file_name_extension(read_vpr_constraints_name, ".xml")) { - try { - std::ifstream file(read_vpr_constraints_name); - void* context; - uxsd::load_vpr_constraints_xml(reader, context, read_vpr_constraints_name, file); - } catch (pugiutil::XmlError& e) { - vpr_throw(VPR_ERROR_ROUTE, read_vpr_constraints_name, e.line(), "%s", e.what()); + // file name from arguments could be a serial of files, seperated by colon ":" + // at this point, caller has already checked that the required constraint file name is not emtpy + int num_tokens = 0, num_file_read = 0; + bool found_file = false; + t_token* tokens = GetTokensFromString(read_vpr_constraints_name, &num_tokens); + std::string in_tokens(""); + for (int i = 0; i < num_tokens; i++) { + if ((tokens[i].type == TOKEN_COLON)) { // end of one input file + found_file = true; + } else if (i == num_tokens - 1) { // end of inputs, append token anyway + in_tokens += std::string(tokens[i].data); + found_file = true; + } else { + in_tokens += std::string(tokens[i].data); + } + if (found_file) { + const char* file_name = in_tokens.c_str(); + if (vtr::check_file_name_extension(file_name, ".xml")) { + try { + std::ifstream file(file_name); + void* context; + uxsd::load_vpr_constraints_xml(reader, context, file_name, file); + } catch (pugiutil::XmlError& e) { + vpr_throw(VPR_ERROR_ROUTE, file_name, e.line(), "%s", e.what()); + } + } else { + VTR_LOG_WARN( + "VPR constraints file '%s' may be in incorrect format. " + "Expecting .xml format. Not reading file.\n", + file_name); + } + in_tokens.clear(); + num_file_read++; + found_file = false; } - } else { - VTR_LOG_WARN( - "VPR constraints file '%s' may be in incorrect format. " - "Expecting .xml format. Not reading file.\n", - read_vpr_constraints_name); } + VTR_LOG("Read in '%d' constraint file(s) successfully.\n", num_file_read); //Update the floorplanning constraints in the floorplanning constraints context auto& floorplanning_ctx = g_vpr_ctx.mutable_floorplanning(); floorplanning_ctx.constraints = reader.constraints_; + // update vpr constraints for routing + auto& routing_ctx = g_vpr_ctx.mutable_routing(); + routing_ctx.constraints = reader.constraints_; + VprConstraints ctx_constraints = floorplanning_ctx.constraints; if (getEchoEnabled() && isEchoFileEnabled(E_ECHO_VPR_CONSTRAINTS)) { diff --git a/vpr/src/base/vpr_constraints_reader.h b/vpr/src/base/vpr_constraints_reader.h index 95fcc988607..60aefc25b5b 100644 --- a/vpr/src/base/vpr_constraints_reader.h +++ b/vpr/src/base/vpr_constraints_reader.h @@ -5,6 +5,6 @@ #ifndef VPR_CONSTRAINTS_READER_H_ #define VPR_CONSTRAINTS_READER_H_ -void load_vpr_constraints_file(const char* read_vpr_constraints_name); +void load_vpr_constraints_files(const char* read_vpr_constraints_name); #endif /* VPR_CONSTRAINTS_READER_H_ */ diff --git a/vpr/src/base/vpr_constraints_serializer.h b/vpr/src/base/vpr_constraints_serializer.h index 4007b7c5c3b..b57756f5c7a 100644 --- a/vpr/src/base/vpr_constraints_serializer.h +++ b/vpr/src/base/vpr_constraints_serializer.h @@ -2,6 +2,7 @@ #define VPR_CONSTRAINTS_SERIALIZER_H_ #include "region.h" +#include "route_constraint.h" #include "vpr_constraints.h" #include "partition.h" #include "partition_region.h" @@ -69,11 +70,15 @@ struct VprConstraintsContextTypes : public uxsd::DefaultVprConstraintsContextTyp using AddRegionReadContext = Region; using PartitionReadContext = partition_info; using PartitionListReadContext = void*; + using SetGlobalSignalReadContext = RouteConstraint; + using GlobalRouteConstraintsReadContext = void*; using VprConstraintsReadContext = void*; using AddAtomWriteContext = void*; using AddRegionWriteContext = void*; using PartitionWriteContext = void*; using PartitionListWriteContext = void*; + using SetGlobalSignalWriteContext = void*; + using GlobalRouteConstraintsWriteContext = void*; using VprConstraintsWriteContext = void*; }; @@ -300,11 +305,62 @@ class VprConstraintsSerializer final : public uxsd::VprConstraintsBase + * + * + * + * + */ + virtual inline const char* get_set_global_signal_name(RouteConstraint& rc) final { + return rc.get_net_name().c_str(); + } + virtual inline void set_set_global_signal_name(const char* name, void*& /*ctx*/) final { + std::string net_name = std::string(name); + loaded_route_constraint.set_net_name(net_name); + return; + } + virtual inline const char* get_set_global_signal_route_model(RouteConstraint& rc) final { + return rc.get_route_model().c_str(); + } + virtual inline void set_set_global_signal_route_model(const char* route_model, void*& /*ctx*/) final { + loaded_route_constraint.set_route_model(std::string(route_model)); + loaded_route_constraint.set_is_valid(true); + } + virtual inline const char* get_set_global_signal_type(RouteConstraint& rc) final { + return rc.get_net_type().c_str(); + } + virtual inline void set_set_global_signal_type(const char* type, void*& /*ctx*/) final { + loaded_route_constraint.set_net_type(std::string(type)); + } + + /** Generated for complex type "global_route_constraints": + * + * + * + * + * + */ + virtual inline void preallocate_global_route_constraints_set_global_signal(void*& /*ctx*/, size_t /*size*/) final {} + virtual inline void* add_global_route_constraints_set_global_signal(void*& /*ctx*/) final { + return nullptr; + } + virtual inline void finish_global_route_constraints_set_global_signal(void*& /*ctx*/) final { + constraints_.add_route_constraint(loaded_route_constraint); + } + virtual inline size_t num_global_route_constraints_set_global_signal(void*& /*ctx*/) final { + return constraints_.get_route_constraint_num(); + } + virtual inline RouteConstraint get_global_route_constraints_set_global_signal(int n, void*& /*ctx*/) final { + return constraints_.get_route_constraint_by_idx((std::size_t)n); + } + /** Generated for complex type "vpr_constraints": * - * + * * - * + * + * * * */ @@ -312,25 +368,54 @@ class VprConstraintsSerializer final : public uxsd::VprConstraintsBase::max_digits10); + void* context; + uxsd::write_vpr_constraints_xml(writer, context, fp); + } else { + VPR_FATAL_ERROR(VPR_ERROR_ROUTE, + "Unknown extension on output %s", + file_name); + } + + return; +} diff --git a/vpr/src/base/vpr_constraints_writer.h b/vpr/src/base/vpr_constraints_writer.h index 756f8c17c29..caac1abd85b 100644 --- a/vpr/src/base/vpr_constraints_writer.h +++ b/vpr/src/base/vpr_constraints_writer.h @@ -47,4 +47,6 @@ void setup_vpr_floorplan_constraints_cutpoints(VprConstraints& constraints, int void create_partition(Partition& part, std::string part_name, int xmin, int ymin, int xmax, int ymax); +void write_vpr_route_constraints(const VprConstraints& constraints, const char* file_name); + #endif /* VPR_SRC_BASE_VPR_CONSTRAINTS_WRITER_H_ */ diff --git a/vpr/src/base/vpr_context.h b/vpr/src/base/vpr_context.h index 0ed27f1a070..0b7d123d1b3 100644 --- a/vpr/src/base/vpr_context.h +++ b/vpr/src/base/vpr_context.h @@ -438,6 +438,11 @@ struct RoutingContext : public Context { vtr::Cache>, RouterLookahead> cached_router_lookahead_; + + /** + * @brief Routing constraints, read only + */ + VprConstraints constraints; }; /** diff --git a/vpr/src/util/vpr_utils.cpp b/vpr/src/util/vpr_utils.cpp index ec8bb686a28..1583065d0ed 100644 --- a/vpr/src/util/vpr_utils.cpp +++ b/vpr/src/util/vpr_utils.cpp @@ -20,6 +20,7 @@ #include "pack_types.h" #include "device_grid.h" #include "timing_fail_error.h" +#include "route_constraint.h" /* This module contains subroutines that are used in several unrelated parts * * of VPR. They are VPR-specific utility routines. */ @@ -2191,3 +2192,19 @@ bool is_node_on_tile(t_physical_tile_type_ptr physical_tile, } } } + +void apply_route_constraints(VprConstraints& vpr_constraint) { + ClusteringContext& mutable_cluster_ctx = g_vpr_ctx.mutable_clustering(); + for (auto net_id : mutable_cluster_ctx.clb_nlist.nets()) { + std::string net_name = mutable_cluster_ctx.clb_nlist.net_name(net_id); + RouteConstraint rc = vpr_constraint.get_route_constraint_by_net_name(net_name); + if (rc.get_is_valid()) { + mutable_cluster_ctx.clb_nlist.set_net_is_global(net_id, true); + if (rc.get_route_model() == "route") { + mutable_cluster_ctx.clb_nlist.set_net_is_ignored(net_id, false); + } else { + mutable_cluster_ctx.clb_nlist.set_net_is_ignored(net_id, true); + } + } + } +} diff --git a/vpr/src/util/vpr_utils.h b/vpr/src/util/vpr_utils.h index e13909f7a01..d2ba2eefd5c 100644 --- a/vpr/src/util/vpr_utils.h +++ b/vpr/src/util/vpr_utils.h @@ -191,4 +191,8 @@ bool is_node_on_tile(t_physical_tile_type_ptr physical_tile, t_rr_type node_type, int node_ptc); +// apply route constraints for route flow +class VprConstraints; +void apply_route_constraints(VprConstraints& constraint); + #endif From 99c132d176ad95dbd9f868ab2991a2b05058f643 Mon Sep 17 00:00:00 2001 From: Tao Li Date: Sat, 25 Feb 2023 23:00:27 -0800 Subject: [PATCH 117/147] Update with regexpr and multi-files readin. --- vpr/src/base/vpr_api.cpp | 5 ++- vpr/src/base/vpr_constraints.cpp | 32 ++++++++++++--- vpr/src/base/vpr_constraints.h | 2 +- vpr/src/base/vpr_constraints_reader.cpp | 52 ++++++++++++++++++------- vpr/src/base/vpr_constraints_reader.h | 2 +- vpr/src/util/vpr_utils.cpp | 2 +- vpr/src/util/vpr_utils.h | 2 +- 7 files changed, 72 insertions(+), 25 deletions(-) diff --git a/vpr/src/base/vpr_api.cpp b/vpr/src/base/vpr_api.cpp index 2d48433521b..e094bc25eb3 100644 --- a/vpr/src/base/vpr_api.cpp +++ b/vpr/src/base/vpr_api.cpp @@ -349,7 +349,7 @@ void vpr_init_with_options(const t_options* options, t_vpr_setup* vpr_setup, t_a //Initialize vpr floorplanning and routing constraints auto& filename_opts = vpr_setup->FileNameOpts; if (!filename_opts.read_vpr_constraints_file.empty()) { - load_vpr_constraints_file(filename_opts.read_vpr_constraints_file.c_str()); + load_vpr_constraints_files(filename_opts.read_vpr_constraints_file.c_str()); // give a notificaiton on routing constraints overiding clock modeling if (g_vpr_ctx.routing().constraints.get_route_constraint_num() && options->clock_modeling.provenance() == argparse::Provenance::SPECIFIED) { @@ -773,7 +773,8 @@ RouteStatus vpr_route_flow(t_vpr_setup& vpr_setup, const t_arch& arch, bool is_f } else { //Do or load // apply route constraints - apply_route_constraints(g_vpr_ctx.routing().constraints); + // use mutable routing context here to apply change on the constraints when binding the constraint to real net + apply_route_constraints(g_vpr_ctx.mutable_routing().constraints); int chan_width = router_opts.fixed_channel_width; diff --git a/vpr/src/base/vpr_constraints.cpp b/vpr/src/base/vpr_constraints.cpp index eae4985c4f4..4b9850be670 100644 --- a/vpr/src/base/vpr_constraints.cpp +++ b/vpr/src/base/vpr_constraints.cpp @@ -1,6 +1,7 @@ #include "vpr_constraints.h" #include "partition.h" #include "route_constraint.h" +#include void VprConstraints::add_constrained_atom(const AtomBlockId blk_id, const PartitionId part_id) { auto got = constrained_atoms.find(blk_id); @@ -64,14 +65,35 @@ void VprConstraints::add_route_constraint(RouteConstraint rc) { return; } -RouteConstraint VprConstraints::get_route_constraint_by_net_name(std::string net_name) const { +RouteConstraint VprConstraints::get_route_constraint_by_net_name(std::string net_name) { RouteConstraint rc; auto const& rc_itr = route_constraints_.find(net_name); if (rc_itr == route_constraints_.end()) { - rc.set_net_name("INVALID"); - rc.set_net_type("INVALID"); - rc.set_route_model("INVALID"); - rc.set_is_valid(false); + // try regexp + bool found_thru_regex = false; + for (auto constraint : route_constraints_) { + if (std::regex_match(net_name, std::regex(constraint.first))) { + { + rc = constraint.second; + + // mark as invalid so write constraint function will not write constraint + // of regexpr name + // instead a matched constraint is inerted in + constraint.second.set_is_valid(false); + rc.set_is_valid(true); + route_constraints_.insert({net_name, rc}); + + found_thru_regex = true; + break; + } + } + } + if (!found_thru_regex) { + rc.set_net_name("INVALID"); + rc.set_net_type("INVALID"); + rc.set_route_model("INVALID"); + rc.set_is_valid(false); + } } else { rc = rc_itr->second; } diff --git a/vpr/src/base/vpr_constraints.h b/vpr/src/base/vpr_constraints.h index fbe4e314f75..61d7ed9d6b6 100644 --- a/vpr/src/base/vpr_constraints.h +++ b/vpr/src/base/vpr_constraints.h @@ -107,7 +107,7 @@ class VprConstraints { * * @param net_name the net name */ - RouteConstraint get_route_constraint_by_net_name(std::string net_name) const; + RouteConstraint get_route_constraint_by_net_name(std::string net_name); /** * @brief returns number of route constraints diff --git a/vpr/src/base/vpr_constraints_reader.cpp b/vpr/src/base/vpr_constraints_reader.cpp index 193ae901d57..eec6d772490 100644 --- a/vpr/src/base/vpr_constraints_reader.cpp +++ b/vpr/src/base/vpr_constraints_reader.cpp @@ -10,26 +10,50 @@ #include #include "vpr_constraints_reader.h" +#include "vtr_token.h" -void load_vpr_constraints_file(const char* read_vpr_constraints_name) { - vtr::ScopedStartFinishTimer timer("Loading VPR constraints file"); +void load_vpr_constraints_files(const char* read_vpr_constraints_name) { + vtr::ScopedStartFinishTimer timer("Loading VPR constraints file(s)"); VprConstraintsSerializer reader; - if (vtr::check_file_name_extension(read_vpr_constraints_name, ".xml")) { - try { - std::ifstream file(read_vpr_constraints_name); - void* context; - uxsd::load_vpr_constraints_xml(reader, context, read_vpr_constraints_name, file); - } catch (pugiutil::XmlError& e) { - vpr_throw(VPR_ERROR_ROUTE, read_vpr_constraints_name, e.line(), "%s", e.what()); + // file name from arguments could be a serial of files, seperated by colon ":" + // at this point, caller has already checked that the required constraint file name is not emtpy + int num_tokens = 0, num_file_read = 0; + bool found_file = false; + t_token* tokens = GetTokensFromString(read_vpr_constraints_name, &num_tokens); + std::string in_tokens(""); + for (int i = 0; i < num_tokens; i++) { + if ((tokens[i].type == TOKEN_COLON)) { // end of one input file + found_file = true; + } else if (i == num_tokens - 1) { // end of inputs, append token anyway + in_tokens += std::string(tokens[i].data); + found_file = true; + } else { + in_tokens += std::string(tokens[i].data); + } + if (found_file) { + const char* file_name = in_tokens.c_str(); + if (vtr::check_file_name_extension(file_name, ".xml")) { + try { + std::ifstream file(file_name); + void* context; + uxsd::load_vpr_constraints_xml(reader, context, file_name, file); + } catch (pugiutil::XmlError& e) { + vpr_throw(VPR_ERROR_ROUTE, file_name, e.line(), "%s", e.what()); + } + } else { + VTR_LOG_WARN( + "VPR constraints file '%s' may be in incorrect format. " + "Expecting .xml format. Not reading file.\n", + file_name); + } + in_tokens.clear(); + num_file_read++; + found_file = false; } - } else { - VTR_LOG_WARN( - "VPR constraints file '%s' may be in incorrect format. " - "Expecting .xml format. Not reading file.\n", - read_vpr_constraints_name); } + VTR_LOG("Read in '%d' constraint file(s) successfully.\n", num_file_read); //Update the floorplanning constraints in the floorplanning constraints context auto& floorplanning_ctx = g_vpr_ctx.mutable_floorplanning(); diff --git a/vpr/src/base/vpr_constraints_reader.h b/vpr/src/base/vpr_constraints_reader.h index 95fcc988607..60aefc25b5b 100644 --- a/vpr/src/base/vpr_constraints_reader.h +++ b/vpr/src/base/vpr_constraints_reader.h @@ -5,6 +5,6 @@ #ifndef VPR_CONSTRAINTS_READER_H_ #define VPR_CONSTRAINTS_READER_H_ -void load_vpr_constraints_file(const char* read_vpr_constraints_name); +void load_vpr_constraints_files(const char* read_vpr_constraints_name); #endif /* VPR_CONSTRAINTS_READER_H_ */ diff --git a/vpr/src/util/vpr_utils.cpp b/vpr/src/util/vpr_utils.cpp index 80a54c0c47e..1583065d0ed 100644 --- a/vpr/src/util/vpr_utils.cpp +++ b/vpr/src/util/vpr_utils.cpp @@ -2193,7 +2193,7 @@ bool is_node_on_tile(t_physical_tile_type_ptr physical_tile, } } -void apply_route_constraints(const VprConstraints& vpr_constraint) { +void apply_route_constraints(VprConstraints& vpr_constraint) { ClusteringContext& mutable_cluster_ctx = g_vpr_ctx.mutable_clustering(); for (auto net_id : mutable_cluster_ctx.clb_nlist.nets()) { std::string net_name = mutable_cluster_ctx.clb_nlist.net_name(net_id); diff --git a/vpr/src/util/vpr_utils.h b/vpr/src/util/vpr_utils.h index 349c7cb2790..d2ba2eefd5c 100644 --- a/vpr/src/util/vpr_utils.h +++ b/vpr/src/util/vpr_utils.h @@ -193,6 +193,6 @@ bool is_node_on_tile(t_physical_tile_type_ptr physical_tile, // apply route constraints for route flow class VprConstraints; -void apply_route_constraints(const VprConstraints& constraint); +void apply_route_constraints(VprConstraints& constraint); #endif From 7a4150d1879388d7a59e6c565f2fd757e2d600cd Mon Sep 17 00:00:00 2001 From: Tao Li Date: Fri, 3 Mar 2023 00:09:01 -0800 Subject: [PATCH 118/147] Dev vpr constraint writer for route constrain. --- libs/libvtrutil/src/vtr_geometry.h | 14 ++++---- libs/libvtrutil/src/vtr_strong_id.h | 6 ++-- vpr/src/base/vpr_api.cpp | 3 ++ vpr/src/base/vpr_constraints.cpp | 1 + vpr/src/base/vpr_constraints_serializer.h | 16 ++++++--- vpr/src/base/vpr_constraints_writer.cpp | 44 +++++++++++++++++++++++ vpr/src/base/vpr_constraints_writer.h | 8 +++++ 7 files changed, 78 insertions(+), 14 deletions(-) diff --git a/libs/libvtrutil/src/vtr_geometry.h b/libs/libvtrutil/src/vtr_geometry.h index 3685c308653..280d40dc7e8 100644 --- a/libs/libvtrutil/src/vtr_geometry.h +++ b/libs/libvtrutil/src/vtr_geometry.h @@ -71,13 +71,13 @@ class Point { T y() const; ///@brief == operator - friend bool operator== <>(Point lhs, Point rhs); + friend bool operator==<>(Point lhs, Point rhs); ///@brief != operator - friend bool operator!= <>(Point lhs, Point rhs); + friend bool operator!=<>(Point lhs, Point rhs); ///@brief < operator - friend bool operator< <>(Point lhs, Point rhs); + friend bool operator<<>(Point lhs, Point rhs); public: //Mutators ///@brief Set x and y values @@ -172,10 +172,10 @@ class Rect { bool empty() const; ///@brief == operator - friend bool operator== <>(const Rect& lhs, const Rect& rhs); + friend bool operator==<>(const Rect& lhs, const Rect& rhs); ///@brief != operator - friend bool operator!= <>(const Rect& lhs, const Rect& rhs); + friend bool operator!=<>(const Rect& lhs, const Rect& rhs); public: //Mutators ///@brief set xmin to a point @@ -296,10 +296,10 @@ class RectUnion { * * Note: does not check whether the representations they are equivalent */ - friend bool operator== <>(const RectUnion& lhs, const RectUnion& rhs); + friend bool operator==<>(const RectUnion& lhs, const RectUnion& rhs); ///@brief != operator - friend bool operator!= <>(const RectUnion& lhs, const RectUnion& rhs); + friend bool operator!=<>(const RectUnion& lhs, const RectUnion& rhs); private: // Note that a union of rectanges may have holes and may not be contiguous diff --git a/libs/libvtrutil/src/vtr_strong_id.h b/libs/libvtrutil/src/vtr_strong_id.h index 1ce922ab5da..1eb7523a6d2 100644 --- a/libs/libvtrutil/src/vtr_strong_id.h +++ b/libs/libvtrutil/src/vtr_strong_id.h @@ -202,11 +202,11 @@ class StrongId { * Note that since these are templated functions we provide an empty set of template parameters * after the function name (i.e. <>) */ - friend bool operator== <>(const StrongId& lhs, const StrongId& rhs); + friend bool operator==<>(const StrongId& lhs, const StrongId& rhs); ///@brief != operator - friend bool operator!= <>(const StrongId& lhs, const StrongId& rhs); + friend bool operator!=<>(const StrongId& lhs, const StrongId& rhs); ///@brief < operator - friend bool operator< <>(const StrongId& lhs, const StrongId& rhs); + friend bool operator<<>(const StrongId& lhs, const StrongId& rhs); private: T id_; diff --git a/vpr/src/base/vpr_api.cpp b/vpr/src/base/vpr_api.cpp index e094bc25eb3..abcb68e1d8e 100644 --- a/vpr/src/base/vpr_api.cpp +++ b/vpr/src/base/vpr_api.cpp @@ -400,6 +400,9 @@ bool vpr_flow(t_vpr_setup& vpr_setup, t_arch& arch) { vpr_analysis_flow(vpr_setup, arch, route_status, is_flat); } + // write out constratins + write_vpr_constraints(vpr_setup); + //close the graphics vpr_close_graphics(vpr_setup); diff --git a/vpr/src/base/vpr_constraints.cpp b/vpr/src/base/vpr_constraints.cpp index 4b9850be670..ae65dcf28e6 100644 --- a/vpr/src/base/vpr_constraints.cpp +++ b/vpr/src/base/vpr_constraints.cpp @@ -112,6 +112,7 @@ RouteConstraint VprConstraints::get_route_constraint_by_idx(std::size_t idx) con for (auto const& rc_itr : route_constraints_) { if (i == idx) { rc = rc_itr.second; + break; } } } diff --git a/vpr/src/base/vpr_constraints_serializer.h b/vpr/src/base/vpr_constraints_serializer.h index b57756f5c7a..bba5ee0f1d2 100644 --- a/vpr/src/base/vpr_constraints_serializer.h +++ b/vpr/src/base/vpr_constraints_serializer.h @@ -313,7 +313,8 @@ class VprConstraintsSerializer final : public uxsd::VprConstraintsBase */ virtual inline const char* get_set_global_signal_name(RouteConstraint& rc) final { - return rc.get_net_name().c_str(); + temp_name_string_ = rc.get_net_name(); + return temp_name_string_.c_str(); } virtual inline void set_set_global_signal_name(const char* name, void*& /*ctx*/) final { std::string net_name = std::string(name); @@ -321,14 +322,16 @@ class VprConstraintsSerializer final : public uxsd::VprConstraintsBase::max_digits10); + void* context; + uxsd::write_vpr_constraints_xml(writer, context, fp); + } else { + VPR_FATAL_ERROR(VPR_ERROR_ROUTE, + "Unknown extension on output %s", + file_name); + } + } + return; +} + void write_vpr_floorplan_constraints(const char* file_name, int expand, bool subtile, int horizontal_partitions, int vertical_partitions) { VprConstraints constraints; diff --git a/vpr/src/base/vpr_constraints_writer.h b/vpr/src/base/vpr_constraints_writer.h index 756f8c17c29..8ca7e9d58f8 100644 --- a/vpr/src/base/vpr_constraints_writer.h +++ b/vpr/src/base/vpr_constraints_writer.h @@ -25,6 +25,14 @@ #ifndef VPR_SRC_BASE_VPR_CONSTRAINTS_WRITER_H_ #define VPR_SRC_BASE_VPR_CONSTRAINTS_WRITER_H_ +/** + * @brief Write out vpr constratins to an XML file based on current placement and + * route constraint settings + * + * @param vpr_setup VPR setup information +*/ +void write_vpr_constraints(t_vpr_setup& vpr_setup); + /** * @brief Write out floorplan constraints to an XML file based on current placement * From ac6b2f4b573fcf948d5bbf9510f98794ec4a75e2 Mon Sep 17 00:00:00 2001 From: Tao Li Date: Fri, 3 Mar 2023 09:41:26 -0800 Subject: [PATCH 119/147] Revert un-wanted changes made by editor. --- libs/libvtrutil/src/vtr_geometry.h | 14 +++++++------- libs/libvtrutil/src/vtr_strong_id.h | 6 +++--- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/libs/libvtrutil/src/vtr_geometry.h b/libs/libvtrutil/src/vtr_geometry.h index 280d40dc7e8..3685c308653 100644 --- a/libs/libvtrutil/src/vtr_geometry.h +++ b/libs/libvtrutil/src/vtr_geometry.h @@ -71,13 +71,13 @@ class Point { T y() const; ///@brief == operator - friend bool operator==<>(Point lhs, Point rhs); + friend bool operator== <>(Point lhs, Point rhs); ///@brief != operator - friend bool operator!=<>(Point lhs, Point rhs); + friend bool operator!= <>(Point lhs, Point rhs); ///@brief < operator - friend bool operator<<>(Point lhs, Point rhs); + friend bool operator< <>(Point lhs, Point rhs); public: //Mutators ///@brief Set x and y values @@ -172,10 +172,10 @@ class Rect { bool empty() const; ///@brief == operator - friend bool operator==<>(const Rect& lhs, const Rect& rhs); + friend bool operator== <>(const Rect& lhs, const Rect& rhs); ///@brief != operator - friend bool operator!=<>(const Rect& lhs, const Rect& rhs); + friend bool operator!= <>(const Rect& lhs, const Rect& rhs); public: //Mutators ///@brief set xmin to a point @@ -296,10 +296,10 @@ class RectUnion { * * Note: does not check whether the representations they are equivalent */ - friend bool operator==<>(const RectUnion& lhs, const RectUnion& rhs); + friend bool operator== <>(const RectUnion& lhs, const RectUnion& rhs); ///@brief != operator - friend bool operator!=<>(const RectUnion& lhs, const RectUnion& rhs); + friend bool operator!= <>(const RectUnion& lhs, const RectUnion& rhs); private: // Note that a union of rectanges may have holes and may not be contiguous diff --git a/libs/libvtrutil/src/vtr_strong_id.h b/libs/libvtrutil/src/vtr_strong_id.h index 1eb7523a6d2..1ce922ab5da 100644 --- a/libs/libvtrutil/src/vtr_strong_id.h +++ b/libs/libvtrutil/src/vtr_strong_id.h @@ -202,11 +202,11 @@ class StrongId { * Note that since these are templated functions we provide an empty set of template parameters * after the function name (i.e. <>) */ - friend bool operator==<>(const StrongId& lhs, const StrongId& rhs); + friend bool operator== <>(const StrongId& lhs, const StrongId& rhs); ///@brief != operator - friend bool operator!=<>(const StrongId& lhs, const StrongId& rhs); + friend bool operator!= <>(const StrongId& lhs, const StrongId& rhs); ///@brief < operator - friend bool operator<<>(const StrongId& lhs, const StrongId& rhs); + friend bool operator< <>(const StrongId& lhs, const StrongId& rhs); private: T id_; From 60721ba4845910feb54e037206fe5566a42ddb0f Mon Sep 17 00:00:00 2001 From: Tao Li Date: Fri, 3 Mar 2023 14:37:22 -0800 Subject: [PATCH 120/147] Fix CLANG 6/7/10 compile issue. --- vpr/src/base/vpr_constraints_writer.cpp | 2 +- vpr/src/base/vpr_constraints_writer.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/vpr/src/base/vpr_constraints_writer.cpp b/vpr/src/base/vpr_constraints_writer.cpp index a962a2e8bce..d94cf7ffb1d 100644 --- a/vpr/src/base/vpr_constraints_writer.cpp +++ b/vpr/src/base/vpr_constraints_writer.cpp @@ -58,7 +58,7 @@ void write_vpr_constraints(t_vpr_setup& vpr_setup) { } else { VPR_FATAL_ERROR(VPR_ERROR_ROUTE, "Unknown extension on output %s", - file_name); + file_name.c_str()); } } return; diff --git a/vpr/src/base/vpr_constraints_writer.h b/vpr/src/base/vpr_constraints_writer.h index 8ca7e9d58f8..158a87aa040 100644 --- a/vpr/src/base/vpr_constraints_writer.h +++ b/vpr/src/base/vpr_constraints_writer.h @@ -30,7 +30,7 @@ * route constraint settings * * @param vpr_setup VPR setup information -*/ + */ void write_vpr_constraints(t_vpr_setup& vpr_setup); /** From 5795b7df753903b215c1273cfe910113375f6aa8 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 3 Mar 2023 16:49:13 -0800 Subject: [PATCH 121/147] [libs] add an invalidator to rrgraph builder so that we can modify the graph after build-up --- libs/librrgraph/src/base/rr_graph_builder.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libs/librrgraph/src/base/rr_graph_builder.h b/libs/librrgraph/src/base/rr_graph_builder.h index 228a7e94b5c..eb447bdff8d 100644 --- a/libs/librrgraph/src/base/rr_graph_builder.h +++ b/libs/librrgraph/src/base/rr_graph_builder.h @@ -297,6 +297,9 @@ class RRGraphBuilder { return node_storage_.count_rr_switches(num_arch_switches, arch_switch_inf, arch_switch_fanins); } + /* Unlock storage; required to modify an routing resource graph after edge is read */ + inline void unlock_storage() { node_storage_.edges_read_ = false; } + /** @brief Reserve the lists of nodes, edges, switches etc. to be memory efficient. * This function is mainly used to reserve memory space inside RRGraph, * when adding a large number of nodes/edge/switches/segments, From 69d852d7e968e9033c9f26541fae6e96eca72e5d Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 6 Mar 2023 15:52:54 -0800 Subject: [PATCH 122/147] [core] debugging --- libs/librrgraph/src/base/rr_graph_builder.h | 2 +- libs/librrgraph/src/base/rr_graph_storage.cpp | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/libs/librrgraph/src/base/rr_graph_builder.h b/libs/librrgraph/src/base/rr_graph_builder.h index eb447bdff8d..02ff4409054 100644 --- a/libs/librrgraph/src/base/rr_graph_builder.h +++ b/libs/librrgraph/src/base/rr_graph_builder.h @@ -298,7 +298,7 @@ class RRGraphBuilder { } /* Unlock storage; required to modify an routing resource graph after edge is read */ - inline void unlock_storage() { node_storage_.edges_read_ = false; } + inline void unlock_storage() { node_storage_.edges_read_ = false; node_storage_.partitioned_ = false; } /** @brief Reserve the lists of nodes, edges, switches etc. to be memory efficient. * This function is mainly used to reserve memory space inside RRGraph, diff --git a/libs/librrgraph/src/base/rr_graph_storage.cpp b/libs/librrgraph/src/base/rr_graph_storage.cpp index fdb5325489d..3cb20273e79 100644 --- a/libs/librrgraph/src/base/rr_graph_storage.cpp +++ b/libs/librrgraph/src/base/rr_graph_storage.cpp @@ -371,7 +371,10 @@ void t_rr_graph_storage::assign_first_edges() { bool t_rr_graph_storage::verify_first_edges() const { size_t num_edges = edge_src_node_.size(); - VTR_ASSERT(node_first_edge_[RRNodeId(node_storage_.size())] == RREdgeId(num_edges)); + if (node_first_edge_[RRNodeId(node_storage_.size())] != RREdgeId(num_edges)) { + VTR_LOG("node first edge is '%lu' while expected edge id is '%lu'\n", size_t(node_first_edge_[RRNodeId(node_storage_.size())]), num_edges); + VTR_ASSERT(node_first_edge_[RRNodeId(node_storage_.size())] == RREdgeId(num_edges)); + } // Each edge should belong with the edge range defined by // [node_first_edge_[src_node], node_first_edge_[src_node+1]). From 67a84e1f16296e77de9642ffa1929924acb87d6c Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 6 Mar 2023 16:06:34 -0800 Subject: [PATCH 123/147] [core] debugging --- libs/librrgraph/src/base/rr_graph_builder.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/librrgraph/src/base/rr_graph_builder.h b/libs/librrgraph/src/base/rr_graph_builder.h index 02ff4409054..6932339dd79 100644 --- a/libs/librrgraph/src/base/rr_graph_builder.h +++ b/libs/librrgraph/src/base/rr_graph_builder.h @@ -298,7 +298,7 @@ class RRGraphBuilder { } /* Unlock storage; required to modify an routing resource graph after edge is read */ - inline void unlock_storage() { node_storage_.edges_read_ = false; node_storage_.partitioned_ = false; } + inline void unlock_storage() { node_storage_.edges_read_ = false; node_storage_.partitioned_ = false; node_storage_.node_first_edge_.clear();} /** @brief Reserve the lists of nodes, edges, switches etc. to be memory efficient. * This function is mainly used to reserve memory space inside RRGraph, From 8e623dc487f9ba671f65f5fe896daac62bda9952 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 6 Mar 2023 16:35:52 -0800 Subject: [PATCH 124/147] [core] debugging --- libs/librrgraph/src/base/rr_graph_storage.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/librrgraph/src/base/rr_graph_storage.h b/libs/librrgraph/src/base/rr_graph_storage.h index bbd388a7779..105129b2b90 100644 --- a/libs/librrgraph/src/base/rr_graph_storage.h +++ b/libs/librrgraph/src/base/rr_graph_storage.h @@ -630,7 +630,7 @@ class t_rr_graph_storage { return side_tt[size_t(side)]; } - private: + public: friend struct edge_swapper; friend class edge_sort_iterator; friend class edge_compare_dest_node; From 1a9b9708bbbf7ddd8f4786a0b5afd5db5f1404eb Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 6 Mar 2023 21:43:36 -0800 Subject: [PATCH 125/147] [core] allow clock to be included optionally when building a gsb --- vpr/src/tileable_rr_graph/rr_graph_view_util.cpp | 8 ++++++-- vpr/src/tileable_rr_graph/rr_graph_view_util.h | 3 ++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/vpr/src/tileable_rr_graph/rr_graph_view_util.cpp b/vpr/src/tileable_rr_graph/rr_graph_view_util.cpp index 90dadea3964..f7b4c063cd6 100644 --- a/vpr/src/tileable_rr_graph/rr_graph_view_util.cpp +++ b/vpr/src/tileable_rr_graph/rr_graph_view_util.cpp @@ -91,7 +91,8 @@ std::vector find_rr_graph_grid_nodes(const RRGraphView& rr_graph, const int& x, const int& y, const t_rr_type& rr_type, - const e_side& side) { + const e_side& side, + bool include_clock) { std::vector indices; VTR_ASSERT(rr_type == IPIN || rr_type == OPIN); @@ -108,7 +109,10 @@ std::vector find_rr_graph_grid_nodes(const RRGraphView& rr_graph, for (int pin = 0; pin < device_grid[x][y].type->num_pins; ++pin) { /* Skip those pins have been ignored during rr_graph build-up */ if (true == device_grid[x][y].type->is_ignored_pin[pin]) { - continue; + /* If specified, force to include all the clock pins */ + if (!include_clock || std::find(device_grid[x][y].type->get_clock_pin_indeces().begin(), device_grid[x][y].type->get_clock_pin_indeces().end(), pin) != device_grid[x][y].type->get_clock_pin_indeces().end()) { + continue; + } } if (false == device_grid[x][y].type->pinloc[width_offset][height_offset][side][pin]) { /* Not the pin on this side, we skip */ diff --git a/vpr/src/tileable_rr_graph/rr_graph_view_util.h b/vpr/src/tileable_rr_graph/rr_graph_view_util.h index 0834f34ef22..ec7d352aa49 100644 --- a/vpr/src/tileable_rr_graph/rr_graph_view_util.h +++ b/vpr/src/tileable_rr_graph/rr_graph_view_util.h @@ -29,6 +29,7 @@ std::vector find_rr_graph_grid_nodes(const RRGraphView& rr_graph, const int& x, const int& y, const t_rr_type& rr_type, - const e_side& side); + const e_side& side, + bool include_clock = false); #endif From 4199c48f319c2f68ec0703546fbc41c76cd20ace Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 6 Mar 2023 21:48:49 -0800 Subject: [PATCH 126/147] [core] typo --- vpr/src/tileable_rr_graph/rr_graph_view_util.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vpr/src/tileable_rr_graph/rr_graph_view_util.cpp b/vpr/src/tileable_rr_graph/rr_graph_view_util.cpp index f7b4c063cd6..98a28e0acda 100644 --- a/vpr/src/tileable_rr_graph/rr_graph_view_util.cpp +++ b/vpr/src/tileable_rr_graph/rr_graph_view_util.cpp @@ -110,7 +110,7 @@ std::vector find_rr_graph_grid_nodes(const RRGraphView& rr_graph, /* Skip those pins have been ignored during rr_graph build-up */ if (true == device_grid[x][y].type->is_ignored_pin[pin]) { /* If specified, force to include all the clock pins */ - if (!include_clock || std::find(device_grid[x][y].type->get_clock_pin_indeces().begin(), device_grid[x][y].type->get_clock_pin_indeces().end(), pin) != device_grid[x][y].type->get_clock_pin_indeces().end()) { + if (!include_clock || std::find(device_grid[x][y].type->get_clock_pin_indices().begin(), device_grid[x][y].type->get_clock_pin_indeces().end(), pin) != device_grid[x][y].type->get_clock_pin_indeces().end()) { continue; } } From 2796b587a6a06a5dd509464081a4c278f128a297 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 6 Mar 2023 21:49:28 -0800 Subject: [PATCH 127/147] [core] syntax --- vpr/src/tileable_rr_graph/rr_graph_view_util.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vpr/src/tileable_rr_graph/rr_graph_view_util.cpp b/vpr/src/tileable_rr_graph/rr_graph_view_util.cpp index 98a28e0acda..d6c79685824 100644 --- a/vpr/src/tileable_rr_graph/rr_graph_view_util.cpp +++ b/vpr/src/tileable_rr_graph/rr_graph_view_util.cpp @@ -110,7 +110,7 @@ std::vector find_rr_graph_grid_nodes(const RRGraphView& rr_graph, /* Skip those pins have been ignored during rr_graph build-up */ if (true == device_grid[x][y].type->is_ignored_pin[pin]) { /* If specified, force to include all the clock pins */ - if (!include_clock || std::find(device_grid[x][y].type->get_clock_pin_indices().begin(), device_grid[x][y].type->get_clock_pin_indeces().end(), pin) != device_grid[x][y].type->get_clock_pin_indeces().end()) { + if (!include_clock || std::find(device_grid[x][y].type->get_clock_pin_indices().begin(), device_grid[x][y].type->get_clock_pin_indices().end(), pin) != device_grid[x][y].type->get_clock_pin_indices().end()) { continue; } } From ebb804ee3da336b555ecf7d95c88272bb0faa14a Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 6 Mar 2023 21:50:14 -0800 Subject: [PATCH 128/147] [core] debugging --- vpr/src/tileable_rr_graph/rr_graph_view_util.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vpr/src/tileable_rr_graph/rr_graph_view_util.cpp b/vpr/src/tileable_rr_graph/rr_graph_view_util.cpp index d6c79685824..fed488d5683 100644 --- a/vpr/src/tileable_rr_graph/rr_graph_view_util.cpp +++ b/vpr/src/tileable_rr_graph/rr_graph_view_util.cpp @@ -110,7 +110,7 @@ std::vector find_rr_graph_grid_nodes(const RRGraphView& rr_graph, /* Skip those pins have been ignored during rr_graph build-up */ if (true == device_grid[x][y].type->is_ignored_pin[pin]) { /* If specified, force to include all the clock pins */ - if (!include_clock || std::find(device_grid[x][y].type->get_clock_pin_indices().begin(), device_grid[x][y].type->get_clock_pin_indices().end(), pin) != device_grid[x][y].type->get_clock_pin_indices().end()) { + if (!include_clock || std::find(device_grid[x][y].type->get_clock_pins_indices().begin(), device_grid[x][y].type->get_clock_pins_indices().end(), pin) != device_grid[x][y].type->get_clock_pins_indices().end()) { continue; } } From 0f40ecba43479b0f830151adcecbf641fb2e9fe3 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 6 Mar 2023 21:56:15 -0800 Subject: [PATCH 129/147] [core] fixed a bug --- vpr/src/tileable_rr_graph/rr_graph_view_util.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vpr/src/tileable_rr_graph/rr_graph_view_util.cpp b/vpr/src/tileable_rr_graph/rr_graph_view_util.cpp index fed488d5683..66baf26a1f6 100644 --- a/vpr/src/tileable_rr_graph/rr_graph_view_util.cpp +++ b/vpr/src/tileable_rr_graph/rr_graph_view_util.cpp @@ -110,7 +110,7 @@ std::vector find_rr_graph_grid_nodes(const RRGraphView& rr_graph, /* Skip those pins have been ignored during rr_graph build-up */ if (true == device_grid[x][y].type->is_ignored_pin[pin]) { /* If specified, force to include all the clock pins */ - if (!include_clock || std::find(device_grid[x][y].type->get_clock_pins_indices().begin(), device_grid[x][y].type->get_clock_pins_indices().end(), pin) != device_grid[x][y].type->get_clock_pins_indices().end()) { + if (!include_clock || std::find(device_grid[x][y].type->get_clock_pins_indices().begin(), device_grid[x][y].type->get_clock_pins_indices().end(), pin) == device_grid[x][y].type->get_clock_pins_indices().end()) { continue; } } From fb90ee867de298fb7be53795d640bb4889ec7a3a Mon Sep 17 00:00:00 2001 From: Tulong4Dev Date: Tue, 7 Mar 2023 18:41:51 -0800 Subject: [PATCH 130/147] Code clean up: fix memory leak issue. --- vpr/src/base/vpr_constraints_reader.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/vpr/src/base/vpr_constraints_reader.cpp b/vpr/src/base/vpr_constraints_reader.cpp index eec6d772490..1140e5269c6 100644 --- a/vpr/src/base/vpr_constraints_reader.cpp +++ b/vpr/src/base/vpr_constraints_reader.cpp @@ -54,6 +54,7 @@ void load_vpr_constraints_files(const char* read_vpr_constraints_name) { } } VTR_LOG("Read in '%d' constraint file(s) successfully.\n", num_file_read); + freeTokens(tokens, num_tokens); //Update the floorplanning constraints in the floorplanning constraints context auto& floorplanning_ctx = g_vpr_ctx.mutable_floorplanning(); From 89cc2e22091e99a9d4f401432e3ea6569b773c58 Mon Sep 17 00:00:00 2001 From: Tulong4Dev Date: Tue, 7 Mar 2023 18:56:41 -0800 Subject: [PATCH 131/147] Fix the memory leak. --- vpr/src/base/vpr_constraints_reader.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/vpr/src/base/vpr_constraints_reader.cpp b/vpr/src/base/vpr_constraints_reader.cpp index eec6d772490..1140e5269c6 100644 --- a/vpr/src/base/vpr_constraints_reader.cpp +++ b/vpr/src/base/vpr_constraints_reader.cpp @@ -54,6 +54,7 @@ void load_vpr_constraints_files(const char* read_vpr_constraints_name) { } } VTR_LOG("Read in '%d' constraint file(s) successfully.\n", num_file_read); + freeTokens(tokens, num_tokens); //Update the floorplanning constraints in the floorplanning constraints context auto& floorplanning_ctx = g_vpr_ctx.mutable_floorplanning(); From 5119ac8621195ddc2288a4ca4a9e34a8743157cb Mon Sep 17 00:00:00 2001 From: Tulong4Dev Date: Thu, 9 Mar 2023 16:09:17 -0800 Subject: [PATCH 132/147] add test. --- .../strong_vpr_constraint/config/config.txt | 28 +++++++++++++++++++ .../config/golden_results.txt | 2 ++ .../strong_vpr_constraint/route_constaint.xml | 6 ++++ .../route_constraint.xml | 6 ++++ .../vtr_reg_strong/task_list.txt | 1 + 5 files changed, 43 insertions(+) create mode 100644 vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_vpr_constraint/config/config.txt create mode 100644 vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_vpr_constraint/config/golden_results.txt create mode 100644 vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_vpr_constraint/route_constaint.xml create mode 100644 vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_vpr_constraint/route_constraint.xml diff --git a/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_vpr_constraint/config/config.txt b/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_vpr_constraint/config/config.txt new file mode 100644 index 00000000000..62141e7a2ed --- /dev/null +++ b/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_vpr_constraint/config/config.txt @@ -0,0 +1,28 @@ +############################################## +# Configuration file for running experiments +############################################## + +# Path to directory of circuits to use +circuits_dir=benchmarks/blif + +# Path to directory of architectures to use +archs_dir=arch/timing + +# Add circuits to list to sweep +circuit_list_add=bigkey.blif + +# Add architectures to list to sweep +arch_list_add=k6_frac_N10_40nm.xml + +# Parse info and how to parse +parse_file=vpr_standard.txt + +# How to parse QoR info +qor_parse_file=qor_standard.txt + +# Pass requirements +pass_requirements_file=pass_requirements.txt + +# Script parameters +script_params_common =-starting_stage vpr --route_chan_width 300 --max_router_iterations 400 --router_lookahead map --initial_pres_fac 1.0 --router_profiler_astar_fac 1.5 --seed 3 +script_params_list_add = -read_vpr_constraints tasks/regression_tests/vtr_reg_strong/strong_tight_floorplan/bigkey_tight.xml:tasks/regression_tests/vtr_reg_strong/strong_tight_floorplan/route_constraint.xml --write_vpr_constraints vpr_constraints.xml diff --git a/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_vpr_constraint/config/golden_results.txt b/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_vpr_constraint/config/golden_results.txt new file mode 100644 index 00000000000..90f0ebd8dda --- /dev/null +++ b/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_vpr_constraint/config/golden_results.txt @@ -0,0 +1,2 @@ + arch circuit script_params vtr_flow_elapsed_time vtr_max_mem_stage vtr_max_mem error odin_synth_time max_odin_mem yosys_synth_time max_yosys_mem abc_depth abc_synth_time abc_cec_time abc_sec_time max_abc_mem ace_time max_ace_mem num_clb num_io num_memories num_mult vpr_status vpr_revision vpr_build_info vpr_compiler vpr_compiled hostname rundir max_vpr_mem num_primary_inputs num_primary_outputs num_pre_packed_nets num_pre_packed_blocks num_netlist_clocks num_post_packed_nets num_post_packed_blocks device_width device_height device_grid_tiles device_limiting_resources device_name pack_mem pack_time placed_wirelength_est place_mem place_time place_quench_time placed_CPD_est placed_setup_TNS_est placed_setup_WNS_est placed_geomean_nonvirtual_intradomain_critical_path_delay_est place_delay_matrix_lookup_time place_quench_timing_analysis_time place_quench_sta_time place_total_timing_analysis_time place_total_sta_time min_chan_width routed_wirelength min_chan_width_route_success_iteration logic_block_area_total logic_block_area_used min_chan_width_routing_area_total min_chan_width_routing_area_per_tile min_chan_width_route_time min_chan_width_total_timing_analysis_time min_chan_width_total_sta_time crit_path_routed_wirelength crit_path_route_success_iteration crit_path_total_nets_routed crit_path_total_connections_routed crit_path_total_heap_pushes crit_path_total_heap_pops critical_path_delay geomean_nonvirtual_intradomain_critical_path_delay setup_TNS setup_WNS hold_TNS hold_WNS crit_path_routing_area_total crit_path_routing_area_per_tile router_lookahead_computation_time crit_path_route_time crit_path_total_timing_analysis_time crit_path_total_sta_time + k6_frac_N10_40nm.xml bigkey.blif common_-read_vpr_constraints_tasks/regression_tests/vtr_reg_strong/strong_tight_floorplan/bigkey_tight.xml 7.06 vpr 72.98 MiB -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 149 229 -1 -1 success v8.0.0-6989-g4a9293e1e-dirty release IPO VTR_ASSERT_LEVEL=3 GNU 11.3.0 on Linux-5.15.0-58-generic x86_64 2023-02-04T01:37:29 dev /home/dev/Desktop/CAS-Atlantic/vtr-verilog-to-routing 74736 229 197 2152 2349 1 1011 575 16 16 256 io auto 35.6 MiB 2.58 8243 73.0 MiB 1.15 0.02 2.69979 -598.935 -2.69979 2.69979 0.04 0.00335255 0.00286435 0.318486 0.278508 -1 11385 11 1.05632e+07 8.03021e+06 4.24953e+06 16599.7 0.22 0.468953 0.419533 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 diff --git a/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_vpr_constraint/route_constaint.xml b/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_vpr_constraint/route_constaint.xml new file mode 100644 index 00000000000..eb54291e557 --- /dev/null +++ b/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_vpr_constraint/route_constaint.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_vpr_constraint/route_constraint.xml b/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_vpr_constraint/route_constraint.xml new file mode 100644 index 00000000000..eb54291e557 --- /dev/null +++ b/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_vpr_constraint/route_constraint.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/vtr_flow/tasks/regression_tests/vtr_reg_strong/task_list.txt b/vtr_flow/tasks/regression_tests/vtr_reg_strong/task_list.txt index 38a3f4409f9..900c1ab0c0b 100644 --- a/vtr_flow/tasks/regression_tests/vtr_reg_strong/task_list.txt +++ b/vtr_flow/tasks/regression_tests/vtr_reg_strong/task_list.txt @@ -82,3 +82,4 @@ regression_tests/vtr_reg_strong/koios regression_tests/vtr_reg_strong/koios_no_complex_dsp regression_tests/vtr_reg_strong/strong_timing_fail regression_tests/vtr_reg_strong/strong_timing_no_fail +regression_tests/vtr_reg_strong/strong_vpr_constraint From d501af232fc6fed1e7f0fcf4b61586df4fb2cf22 Mon Sep 17 00:00:00 2001 From: Tulong4Dev Date: Fri, 10 Mar 2023 16:03:25 -0800 Subject: [PATCH 133/147] Update test. --- vtr_flow/benchmarks/microbenchmarks/and_clk.blif | 9 +++++++++ .../strong_vpr_constraint/config/config.txt | 11 +++++------ .../strong_vpr_constraint/floor_plan.xml | 9 +++++++++ .../strong_vpr_constraint/route_constaint.xml | 6 ------ .../strong_vpr_constraint/route_constraint.xml | 2 +- 5 files changed, 24 insertions(+), 13 deletions(-) create mode 100644 vtr_flow/benchmarks/microbenchmarks/and_clk.blif create mode 100644 vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_vpr_constraint/floor_plan.xml delete mode 100644 vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_vpr_constraint/route_constaint.xml diff --git a/vtr_flow/benchmarks/microbenchmarks/and_clk.blif b/vtr_flow/benchmarks/microbenchmarks/and_clk.blif new file mode 100644 index 00000000000..a810fda32f6 --- /dev/null +++ b/vtr_flow/benchmarks/microbenchmarks/and_clk.blif @@ -0,0 +1,9 @@ +.model discrete_dffn +.inputs clk_ni d_i +.outputs d_o + +.names clk_ni int_clk_reg_exp_0 +0 1 +.subckt dffeas d=d_i q=d_o clk=int_clk_reg_exp_0 + +.end diff --git a/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_vpr_constraint/config/config.txt b/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_vpr_constraint/config/config.txt index 62141e7a2ed..c714d686d4d 100644 --- a/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_vpr_constraint/config/config.txt +++ b/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_vpr_constraint/config/config.txt @@ -3,16 +3,16 @@ ############################################## # Path to directory of circuits to use -circuits_dir=benchmarks/blif +circuits_dir=benchmarks/microbenchmarks # Path to directory of architectures to use -archs_dir=arch/timing +archs_dir=arch/titan # Add circuits to list to sweep -circuit_list_add=bigkey.blif +circuit_list_add=and_clk.blif # Add architectures to list to sweep -arch_list_add=k6_frac_N10_40nm.xml +arch_list_add=stratixiv_arch.timing.xml # Parse info and how to parse parse_file=vpr_standard.txt @@ -24,5 +24,4 @@ qor_parse_file=qor_standard.txt pass_requirements_file=pass_requirements.txt # Script parameters -script_params_common =-starting_stage vpr --route_chan_width 300 --max_router_iterations 400 --router_lookahead map --initial_pres_fac 1.0 --router_profiler_astar_fac 1.5 --seed 3 -script_params_list_add = -read_vpr_constraints tasks/regression_tests/vtr_reg_strong/strong_tight_floorplan/bigkey_tight.xml:tasks/regression_tests/vtr_reg_strong/strong_tight_floorplan/route_constraint.xml --write_vpr_constraints vpr_constraints.xml +script_params_common =-starting_stage vpr --route_chan_width 300 --max_router_iterations 400 --router_lookahead map --initial_pres_fac 1.0 --router_profiler_astar_fac 1.5 --seed 3 --read_vpr_constraints ../../../../floor_plan.xml:../../../../route_constraint.xml --write_vpr_constraints vpr_constraints.xml diff --git a/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_vpr_constraint/floor_plan.xml b/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_vpr_constraint/floor_plan.xml new file mode 100644 index 00000000000..507d4e14296 --- /dev/null +++ b/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_vpr_constraint/floor_plan.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_vpr_constraint/route_constaint.xml b/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_vpr_constraint/route_constaint.xml deleted file mode 100644 index eb54291e557..00000000000 --- a/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_vpr_constraint/route_constaint.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_vpr_constraint/route_constraint.xml b/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_vpr_constraint/route_constraint.xml index eb54291e557..53e293c579e 100644 --- a/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_vpr_constraint/route_constraint.xml +++ b/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_vpr_constraint/route_constraint.xml @@ -1,6 +1,6 @@ - + From bcc1881a7703cb2d0220f02bfd7965a77532771e Mon Sep 17 00:00:00 2001 From: Tulong4Dev Date: Fri, 10 Mar 2023 21:14:42 -0800 Subject: [PATCH 134/147] fix write constraint; update with simple test. --- vpr/src/base/vpr_constraints.cpp | 3 +- .../k4_frac_N4_fracff_localClkGen_40nm.xml | 635 ++++++++++++++++++ .../benchmarks/microbenchmarks/and_clk.blif | 5 +- .../strong_vpr_constraint/config/config.txt | 6 +- .../strong_vpr_constraint/floor_plan.xml | 2 +- .../route_constraint.xml | 9 +- 6 files changed, 650 insertions(+), 10 deletions(-) create mode 100644 vtr_flow/arch/timing/k4_frac_N4_fracff_localClkGen_40nm.xml diff --git a/vpr/src/base/vpr_constraints.cpp b/vpr/src/base/vpr_constraints.cpp index ae65dcf28e6..742cc014955 100644 --- a/vpr/src/base/vpr_constraints.cpp +++ b/vpr/src/base/vpr_constraints.cpp @@ -78,8 +78,9 @@ RouteConstraint VprConstraints::get_route_constraint_by_net_name(std::string net // mark as invalid so write constraint function will not write constraint // of regexpr name - // instead a matched constraint is inerted in + // instead a matched constraint is inserted in constraint.second.set_is_valid(false); + rc.set_net_name(net_name); rc.set_is_valid(true); route_constraints_.insert({net_name, rc}); diff --git a/vtr_flow/arch/timing/k4_frac_N4_fracff_localClkGen_40nm.xml b/vtr_flow/arch/timing/k4_frac_N4_fracff_localClkGen_40nm.xml new file mode 100644 index 00000000000..6b027fe6a21 --- /dev/null +++ b/vtr_flow/arch/timing/k4_frac_N4_fracff_localClkGen_40nm.xml @@ -0,0 +1,635 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + io.outpad io.inpad + io.outpad io.inpad + io.outpad io.inpad + io.outpad io.inpad + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 1 1 1 1 + 1 1 1 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 235e-12 + 235e-12 + 235e-12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 261e-12 + 261e-12 + 261e-12 + 261e-12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vtr_flow/benchmarks/microbenchmarks/and_clk.blif b/vtr_flow/benchmarks/microbenchmarks/and_clk.blif index a810fda32f6..3f31b82b8d7 100644 --- a/vtr_flow/benchmarks/microbenchmarks/and_clk.blif +++ b/vtr_flow/benchmarks/microbenchmarks/and_clk.blif @@ -1,9 +1,12 @@ + .model discrete_dffn .inputs clk_ni d_i .outputs d_o .names clk_ni int_clk_reg_exp_0 0 1 -.subckt dffeas d=d_i q=d_o clk=int_clk_reg_exp_0 + +.subckt dff D=d_i Q=d_o C=int_clk_reg_exp_0 .end + diff --git a/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_vpr_constraint/config/config.txt b/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_vpr_constraint/config/config.txt index c714d686d4d..a3ceed7c14d 100644 --- a/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_vpr_constraint/config/config.txt +++ b/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_vpr_constraint/config/config.txt @@ -6,13 +6,13 @@ circuits_dir=benchmarks/microbenchmarks # Path to directory of architectures to use -archs_dir=arch/titan +archs_dir=arch/timing # Add circuits to list to sweep circuit_list_add=and_clk.blif # Add architectures to list to sweep -arch_list_add=stratixiv_arch.timing.xml +arch_list_add=k4_frac_N4_fracff_localClkGen_40nm.xml # Parse info and how to parse parse_file=vpr_standard.txt @@ -24,4 +24,4 @@ qor_parse_file=qor_standard.txt pass_requirements_file=pass_requirements.txt # Script parameters -script_params_common =-starting_stage vpr --route_chan_width 300 --max_router_iterations 400 --router_lookahead map --initial_pres_fac 1.0 --router_profiler_astar_fac 1.5 --seed 3 --read_vpr_constraints ../../../../floor_plan.xml:../../../../route_constraint.xml --write_vpr_constraints vpr_constraints.xml +script_params_common =-starting_stage vpr --route_chan_width 300 --max_router_iterations 400 --router_lookahead map --initial_pres_fac 1.0 --router_profiler_astar_fac 1.5 --seed 3 --read_vpr_constraints ../../../../floor_plan.xml:../../../../route_constraint.xml --write_vpr_constraints vpr_constraints.xml --clock_modeling ideal diff --git a/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_vpr_constraint/floor_plan.xml b/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_vpr_constraint/floor_plan.xml index 507d4e14296..861adf40966 100644 --- a/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_vpr_constraint/floor_plan.xml +++ b/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_vpr_constraint/floor_plan.xml @@ -2,7 +2,7 @@ - + diff --git a/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_vpr_constraint/route_constraint.xml b/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_vpr_constraint/route_constraint.xml index 53e293c579e..ca3d794706b 100644 --- a/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_vpr_constraint/route_constraint.xml +++ b/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_vpr_constraint/route_constraint.xml @@ -1,6 +1,7 @@ - - - - + + + + + From 63b028d201507bb0dfa06350c1b0ea4b8095970b Mon Sep 17 00:00:00 2001 From: Tulong4Dev Date: Sat, 11 Mar 2023 17:26:42 -0800 Subject: [PATCH 135/147] Update new test golden result. --- .../strong_vpr_constraint/config/golden_results.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_vpr_constraint/config/golden_results.txt b/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_vpr_constraint/config/golden_results.txt index 90f0ebd8dda..76b5c59b6fa 100644 --- a/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_vpr_constraint/config/golden_results.txt +++ b/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_vpr_constraint/config/golden_results.txt @@ -1,2 +1,2 @@ - arch circuit script_params vtr_flow_elapsed_time vtr_max_mem_stage vtr_max_mem error odin_synth_time max_odin_mem yosys_synth_time max_yosys_mem abc_depth abc_synth_time abc_cec_time abc_sec_time max_abc_mem ace_time max_ace_mem num_clb num_io num_memories num_mult vpr_status vpr_revision vpr_build_info vpr_compiler vpr_compiled hostname rundir max_vpr_mem num_primary_inputs num_primary_outputs num_pre_packed_nets num_pre_packed_blocks num_netlist_clocks num_post_packed_nets num_post_packed_blocks device_width device_height device_grid_tiles device_limiting_resources device_name pack_mem pack_time placed_wirelength_est place_mem place_time place_quench_time placed_CPD_est placed_setup_TNS_est placed_setup_WNS_est placed_geomean_nonvirtual_intradomain_critical_path_delay_est place_delay_matrix_lookup_time place_quench_timing_analysis_time place_quench_sta_time place_total_timing_analysis_time place_total_sta_time min_chan_width routed_wirelength min_chan_width_route_success_iteration logic_block_area_total logic_block_area_used min_chan_width_routing_area_total min_chan_width_routing_area_per_tile min_chan_width_route_time min_chan_width_total_timing_analysis_time min_chan_width_total_sta_time crit_path_routed_wirelength crit_path_route_success_iteration crit_path_total_nets_routed crit_path_total_connections_routed crit_path_total_heap_pushes crit_path_total_heap_pops critical_path_delay geomean_nonvirtual_intradomain_critical_path_delay setup_TNS setup_WNS hold_TNS hold_WNS crit_path_routing_area_total crit_path_routing_area_per_tile router_lookahead_computation_time crit_path_route_time crit_path_total_timing_analysis_time crit_path_total_sta_time - k6_frac_N10_40nm.xml bigkey.blif common_-read_vpr_constraints_tasks/regression_tests/vtr_reg_strong/strong_tight_floorplan/bigkey_tight.xml 7.06 vpr 72.98 MiB -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 149 229 -1 -1 success v8.0.0-6989-g4a9293e1e-dirty release IPO VTR_ASSERT_LEVEL=3 GNU 11.3.0 on Linux-5.15.0-58-generic x86_64 2023-02-04T01:37:29 dev /home/dev/Desktop/CAS-Atlantic/vtr-verilog-to-routing 74736 229 197 2152 2349 1 1011 575 16 16 256 io auto 35.6 MiB 2.58 8243 73.0 MiB 1.15 0.02 2.69979 -598.935 -2.69979 2.69979 0.04 0.00335255 0.00286435 0.318486 0.278508 -1 11385 11 1.05632e+07 8.03021e+06 4.24953e+06 16599.7 0.22 0.468953 0.419533 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +arch circuit script_params vtr_flow_elapsed_time vtr_max_mem_stage vtr_max_mem error odin_synth_time max_odin_mem parmys_synth_time max_parmys_mem abc_depth abc_synth_time abc_cec_time abc_sec_time max_abc_mem ace_time max_ace_mem num_clb num_io num_memories num_mult vpr_status vpr_revision vpr_build_info vpr_compiler vpr_compiled hostname rundir max_vpr_mem num_primary_inputs num_primary_outputs num_pre_packed_nets num_pre_packed_blocks num_netlist_clocks num_post_packed_nets num_post_packed_blocks device_width device_height device_grid_tiles device_limiting_resources device_name pack_mem pack_time placed_wirelength_est place_mem place_time place_quench_time placed_CPD_est placed_setup_TNS_est placed_setup_WNS_est placed_geomean_nonvirtual_intradomain_critical_path_delay_est place_delay_matrix_lookup_time place_quench_timing_analysis_time place_quench_sta_time place_total_timing_analysis_time place_total_sta_time min_chan_width routed_wirelength min_chan_width_route_success_iteration logic_block_area_total logic_block_area_used min_chan_width_routing_area_total min_chan_width_routing_area_per_tile min_chan_width_route_time min_chan_width_total_timing_analysis_time min_chan_width_total_sta_time crit_path_num_rr_graph_nodes crit_path_num_rr_graph_edges crit_path_collapsed_nodes crit_path_routed_wirelength crit_path_route_success_iteration crit_path_total_nets_routed crit_path_total_connections_routed crit_path_total_heap_pushes crit_path_total_heap_pops crit_path_total_internal_heap_pushes crit_path_total_internal_heap_pops crit_path_total_external_heap_pushes crit_path_total_external_heap_pops crit_path_total_external_SOURCE_pushes crit_path_total_external_SOURCE_pops crit_path_total_internal_SOURCE_pushes crit_path_total_internal_SOURCE_pops crit_path_total_external_SINK_pushes crit_path_total_external_SINK_pops crit_path_total_internal_SINK_pushes crit_path_total_internal_SINK_pops crit_path_total_external_IPIN_pushes crit_path_total_external_IPIN_pops crit_path_total_internal_IPIN_pushes crit_path_total_internal_IPIN_pops crit_path_total_external_OPIN_pushes crit_path_total_external_OPIN_pops crit_path_total_internal_OPIN_pushes crit_path_total_internal_OPIN_pops crit_path_total_external_CHANX_pushes crit_path_total_external_CHANX_pops crit_path_total_internal_CHANX_pushes crit_path_total_internal_CHANX_pops crit_path_total_external_CHANY_pushes crit_path_total_external_CHANY_pops crit_path_total_internal_CHANY_pushes crit_path_total_internal_CHANY_pops crit_path_rt_node_SOURCE_pushes crit_path_rt_node_SINK_pushes crit_path_rt_node_IPIN_pushes crit_path_rt_node_OPIN_pushes crit_path_rt_node_CHANX_pushes crit_path_rt_node_CHANY_pushes crit_path_adding_all_rt crit_path_adding_high_fanout_rt crit_path_total_number_of_adding_all_rt_from_calling_high_fanout_rt critical_path_delay geomean_nonvirtual_intradomain_critical_path_delay setup_TNS setup_WNS hold_TNS hold_WNS crit_path_routing_area_total crit_path_routing_area_per_tile router_lookahead_computation_time crit_path_route_time crit_path_create_rr_graph_time crit_path_create_intra_cluster_rr_graph_time crit_path_tile_lookahead_computation_time crit_path_router_lookahead_computation_time crit_path_total_timing_analysis_time crit_path_total_sta_time +k4_frac_N4_fracff_localClkGen_40nm.xml and_clk.blif common 1.13 vpr 199.32 MiB -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 2 2 -1 -1 success d501af232-dirty debug VTR_ASSERT_LEVEL=3 sanitizers GNU 9.4.0 on Linux-5.15.0-67-generic x86_64 2023-03-10T20:33:07 workstation /home/tao/works/dev/route/vtr-verilog-to-routing/vtr_flow/tasks 204100 2 1 4 5 1 4 5 4 4 16 clb auto 59.9 MiB 0.02 11 198.0 MiB 0.01 0.00 1.13498 -1.13498 -1.13498 1.13498 0.03 0.000154368 0.000127356 0.00093834 0.000650842 -1 8 1 215576 107788 120301. 7518.81 0.01 0.00241288 0.00171572 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 From f3b42d289e476d387e4f7f04bd2b20d2c9156754 Mon Sep 17 00:00:00 2001 From: Tulong4Dev Date: Sat, 11 Mar 2023 20:42:42 -0800 Subject: [PATCH 136/147] update document. --- doc/src/vpr/command_line_usage.rst | 6 ++--- doc/src/vpr/route_constraints.rst | 39 ++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 3 deletions(-) create mode 100644 doc/src/vpr/route_constraints.rst diff --git a/doc/src/vpr/command_line_usage.rst b/doc/src/vpr/command_line_usage.rst index f589969d8ef..6ce335eb15a 100644 --- a/doc/src/vpr/command_line_usage.rst +++ b/doc/src/vpr/command_line_usage.rst @@ -358,13 +358,13 @@ Use the options below to override this default naming behaviour. .. seealso:: :ref:`Routing Resource XML File `. -.. option:: --read_vpr_constraints +.. option:: --read_vpr_constraints ::...: - Reads the :ref:`floorplanning constraints ` that packing and placement must respect from the specified XML file. + Reads the :ref:`floorplanning constraints ` that packing and placement must respect from the specified XML file; and/or reads the :ref:`global route constraints ` that router must respect from the specified XML file. Multiple files are allowed and should be seperated with a colomn char. .. option:: --write_vpr_constraints - Writes out new :ref:`floorplanning constraints ` based on current placement to the specified XML file. + Writes out new :ref:`floorplanning constraints ` based on current placement to the specified XML file; and/or writes out new :ref:`global route constraints ` based on current global routecounstraints to the specified XML file. Note that a single combined file is written to even there are multiple input constraint files read in. .. option:: --read_router_lookahead diff --git a/doc/src/vpr/route_constraints.rst b/doc/src/vpr/route_constraints.rst new file mode 100644 index 00000000000..484e90f2574 --- /dev/null +++ b/doc/src/vpr/route_constraints.rst @@ -0,0 +1,39 @@ + +VPR Placement Constraints +========================= +.. _vpr_constraints_file: +VPR supports running flows with route constraints. Route constraints are set on global signals to specify if they should be routed or not. For example, a user may want to route a specific internal clock even clock modeling option is set to not route it. + +The route constraints should be specified by the user using an XML constraints file format, as described in the section below. + +A Constraints File Example +-------------------------- + +.. code-block:: xml + :caption: An example of a route constraints file in XML format. + :linenos: + + + + + + + + + +.. _end: + +Constraints File Format +----------------------- + +VPR has a specific XML format which must be used when creating a route constraints file. The purpose of this constraints file is to specify + +#. The signals that should be constrained for routing +#. The route model for such signals + +The file is passed as an input to VPR when running with route constraints. When the file is read in, its information is used to guide VPR route or not route such signals. + +.. note:: Use the VPR option :vpr:option:`--read_vpr_constraints` to specify the VPR route constraints file that is to be loaded. + +.. note:: Wildcard names of signals are supported to specify a list of signals. The wildcard expression should follow the C/C++ regexpr rule. + From 0dbd6851f523c2641ca112913366ac1b19fc31aa Mon Sep 17 00:00:00 2001 From: Tulong4Dev Date: Mon, 13 Mar 2023 19:53:36 -0700 Subject: [PATCH 137/147] update golden results. --- .../strong_vpr_constraint/config/golden_results.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_vpr_constraint/config/golden_results.txt b/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_vpr_constraint/config/golden_results.txt index 76b5c59b6fa..9e3589ac487 100644 --- a/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_vpr_constraint/config/golden_results.txt +++ b/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_vpr_constraint/config/golden_results.txt @@ -1,2 +1,2 @@ arch circuit script_params vtr_flow_elapsed_time vtr_max_mem_stage vtr_max_mem error odin_synth_time max_odin_mem parmys_synth_time max_parmys_mem abc_depth abc_synth_time abc_cec_time abc_sec_time max_abc_mem ace_time max_ace_mem num_clb num_io num_memories num_mult vpr_status vpr_revision vpr_build_info vpr_compiler vpr_compiled hostname rundir max_vpr_mem num_primary_inputs num_primary_outputs num_pre_packed_nets num_pre_packed_blocks num_netlist_clocks num_post_packed_nets num_post_packed_blocks device_width device_height device_grid_tiles device_limiting_resources device_name pack_mem pack_time placed_wirelength_est place_mem place_time place_quench_time placed_CPD_est placed_setup_TNS_est placed_setup_WNS_est placed_geomean_nonvirtual_intradomain_critical_path_delay_est place_delay_matrix_lookup_time place_quench_timing_analysis_time place_quench_sta_time place_total_timing_analysis_time place_total_sta_time min_chan_width routed_wirelength min_chan_width_route_success_iteration logic_block_area_total logic_block_area_used min_chan_width_routing_area_total min_chan_width_routing_area_per_tile min_chan_width_route_time min_chan_width_total_timing_analysis_time min_chan_width_total_sta_time crit_path_num_rr_graph_nodes crit_path_num_rr_graph_edges crit_path_collapsed_nodes crit_path_routed_wirelength crit_path_route_success_iteration crit_path_total_nets_routed crit_path_total_connections_routed crit_path_total_heap_pushes crit_path_total_heap_pops crit_path_total_internal_heap_pushes crit_path_total_internal_heap_pops crit_path_total_external_heap_pushes crit_path_total_external_heap_pops crit_path_total_external_SOURCE_pushes crit_path_total_external_SOURCE_pops crit_path_total_internal_SOURCE_pushes crit_path_total_internal_SOURCE_pops crit_path_total_external_SINK_pushes crit_path_total_external_SINK_pops crit_path_total_internal_SINK_pushes crit_path_total_internal_SINK_pops crit_path_total_external_IPIN_pushes crit_path_total_external_IPIN_pops crit_path_total_internal_IPIN_pushes crit_path_total_internal_IPIN_pops crit_path_total_external_OPIN_pushes crit_path_total_external_OPIN_pops crit_path_total_internal_OPIN_pushes crit_path_total_internal_OPIN_pops crit_path_total_external_CHANX_pushes crit_path_total_external_CHANX_pops crit_path_total_internal_CHANX_pushes crit_path_total_internal_CHANX_pops crit_path_total_external_CHANY_pushes crit_path_total_external_CHANY_pops crit_path_total_internal_CHANY_pushes crit_path_total_internal_CHANY_pops crit_path_rt_node_SOURCE_pushes crit_path_rt_node_SINK_pushes crit_path_rt_node_IPIN_pushes crit_path_rt_node_OPIN_pushes crit_path_rt_node_CHANX_pushes crit_path_rt_node_CHANY_pushes crit_path_adding_all_rt crit_path_adding_high_fanout_rt crit_path_total_number_of_adding_all_rt_from_calling_high_fanout_rt critical_path_delay geomean_nonvirtual_intradomain_critical_path_delay setup_TNS setup_WNS hold_TNS hold_WNS crit_path_routing_area_total crit_path_routing_area_per_tile router_lookahead_computation_time crit_path_route_time crit_path_create_rr_graph_time crit_path_create_intra_cluster_rr_graph_time crit_path_tile_lookahead_computation_time crit_path_router_lookahead_computation_time crit_path_total_timing_analysis_time crit_path_total_sta_time -k4_frac_N4_fracff_localClkGen_40nm.xml and_clk.blif common 1.13 vpr 199.32 MiB -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 2 2 -1 -1 success d501af232-dirty debug VTR_ASSERT_LEVEL=3 sanitizers GNU 9.4.0 on Linux-5.15.0-67-generic x86_64 2023-03-10T20:33:07 workstation /home/tao/works/dev/route/vtr-verilog-to-routing/vtr_flow/tasks 204100 2 1 4 5 1 4 5 4 4 16 clb auto 59.9 MiB 0.02 11 198.0 MiB 0.01 0.00 1.13498 -1.13498 -1.13498 1.13498 0.03 0.000154368 0.000127356 0.00093834 0.000650842 -1 8 1 215576 107788 120301. 7518.81 0.01 0.00241288 0.00171572 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +k4_frac_N4_fracff_localClkGen_40nm.xml and_clk.blif common 1.19 vpr 198.86 MiB -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 2 2 -1 -1 success d501af232-dirty debug VTR_ASSERT_LEVEL=3 sanitizers GNU 9.4.0 on Linux-5.15.0-67-generic x86_64 2023-03-10T20:33:07 workstation /home/tao/works/dev/route/vtr-verilog-to-routing/vtr_flow/tasks 203636 2 1 4 5 1 4 5 4 4 16 clb auto 59.1 MiB 0.02 11 197.6 MiB 0.01 0.00 1.13498 -1.13498 -1.13498 1.13498 0.03 0.000154861 0.00012795 0.000938791 0.000647688 -1 8 1 215576 107788 120301. 7518.81 0.01 0.00242291 0.00172363 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 From 71db0a4f9e632e0e493af0b008ee8ce8b78b5529 Mon Sep 17 00:00:00 2001 From: Tulong4Dev Date: Tue, 14 Mar 2023 14:18:28 -0700 Subject: [PATCH 138/147] update golden result from release build. --- .../strong_vpr_constraint/config/golden_results.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_vpr_constraint/config/golden_results.txt b/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_vpr_constraint/config/golden_results.txt index 9e3589ac487..359030d6c0d 100644 --- a/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_vpr_constraint/config/golden_results.txt +++ b/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_vpr_constraint/config/golden_results.txt @@ -1,2 +1,2 @@ arch circuit script_params vtr_flow_elapsed_time vtr_max_mem_stage vtr_max_mem error odin_synth_time max_odin_mem parmys_synth_time max_parmys_mem abc_depth abc_synth_time abc_cec_time abc_sec_time max_abc_mem ace_time max_ace_mem num_clb num_io num_memories num_mult vpr_status vpr_revision vpr_build_info vpr_compiler vpr_compiled hostname rundir max_vpr_mem num_primary_inputs num_primary_outputs num_pre_packed_nets num_pre_packed_blocks num_netlist_clocks num_post_packed_nets num_post_packed_blocks device_width device_height device_grid_tiles device_limiting_resources device_name pack_mem pack_time placed_wirelength_est place_mem place_time place_quench_time placed_CPD_est placed_setup_TNS_est placed_setup_WNS_est placed_geomean_nonvirtual_intradomain_critical_path_delay_est place_delay_matrix_lookup_time place_quench_timing_analysis_time place_quench_sta_time place_total_timing_analysis_time place_total_sta_time min_chan_width routed_wirelength min_chan_width_route_success_iteration logic_block_area_total logic_block_area_used min_chan_width_routing_area_total min_chan_width_routing_area_per_tile min_chan_width_route_time min_chan_width_total_timing_analysis_time min_chan_width_total_sta_time crit_path_num_rr_graph_nodes crit_path_num_rr_graph_edges crit_path_collapsed_nodes crit_path_routed_wirelength crit_path_route_success_iteration crit_path_total_nets_routed crit_path_total_connections_routed crit_path_total_heap_pushes crit_path_total_heap_pops crit_path_total_internal_heap_pushes crit_path_total_internal_heap_pops crit_path_total_external_heap_pushes crit_path_total_external_heap_pops crit_path_total_external_SOURCE_pushes crit_path_total_external_SOURCE_pops crit_path_total_internal_SOURCE_pushes crit_path_total_internal_SOURCE_pops crit_path_total_external_SINK_pushes crit_path_total_external_SINK_pops crit_path_total_internal_SINK_pushes crit_path_total_internal_SINK_pops crit_path_total_external_IPIN_pushes crit_path_total_external_IPIN_pops crit_path_total_internal_IPIN_pushes crit_path_total_internal_IPIN_pops crit_path_total_external_OPIN_pushes crit_path_total_external_OPIN_pops crit_path_total_internal_OPIN_pushes crit_path_total_internal_OPIN_pops crit_path_total_external_CHANX_pushes crit_path_total_external_CHANX_pops crit_path_total_internal_CHANX_pushes crit_path_total_internal_CHANX_pops crit_path_total_external_CHANY_pushes crit_path_total_external_CHANY_pops crit_path_total_internal_CHANY_pushes crit_path_total_internal_CHANY_pops crit_path_rt_node_SOURCE_pushes crit_path_rt_node_SINK_pushes crit_path_rt_node_IPIN_pushes crit_path_rt_node_OPIN_pushes crit_path_rt_node_CHANX_pushes crit_path_rt_node_CHANY_pushes crit_path_adding_all_rt crit_path_adding_high_fanout_rt crit_path_total_number_of_adding_all_rt_from_calling_high_fanout_rt critical_path_delay geomean_nonvirtual_intradomain_critical_path_delay setup_TNS setup_WNS hold_TNS hold_WNS crit_path_routing_area_total crit_path_routing_area_per_tile router_lookahead_computation_time crit_path_route_time crit_path_create_rr_graph_time crit_path_create_intra_cluster_rr_graph_time crit_path_tile_lookahead_computation_time crit_path_router_lookahead_computation_time crit_path_total_timing_analysis_time crit_path_total_sta_time -k4_frac_N4_fracff_localClkGen_40nm.xml and_clk.blif common 1.19 vpr 198.86 MiB -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 2 2 -1 -1 success d501af232-dirty debug VTR_ASSERT_LEVEL=3 sanitizers GNU 9.4.0 on Linux-5.15.0-67-generic x86_64 2023-03-10T20:33:07 workstation /home/tao/works/dev/route/vtr-verilog-to-routing/vtr_flow/tasks 203636 2 1 4 5 1 4 5 4 4 16 clb auto 59.1 MiB 0.02 11 197.6 MiB 0.01 0.00 1.13498 -1.13498 -1.13498 1.13498 0.03 0.000154861 0.00012795 0.000938791 0.000647688 -1 8 1 215576 107788 120301. 7518.81 0.01 0.00242291 0.00172363 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +k4_frac_N4_fracff_localClkGen_40nm.xml and_clk.blif common 0.67 vpr 186.86 MiB -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 2 2 -1 -1 success 0dbd6851f release IPO VTR_ASSERT_LEVEL=3 sanitizers GNU 9.4.0 on Linux-5.15.0-67-generic x86_64 2023-03-14T11:14:58 workstation /home/tao/works/dev/route/vtr-verilog-to-routing/vtr_flow/tasks 191344 2 1 4 5 1 4 5 4 4 16 clb auto 45.8 MiB 0.01 11 185.3 MiB 0.00 0.00 1.13498 -1.13498 -1.13498 1.13498 0.01 6.4456e-05 6.0907e-05 0.000407814 0.00028842 -1 8 1 215576 107788 120301. 7518.81 0.00 0.000999195 0.000686301 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 From bd59994063664ed21c4816636bb0195cb2d34083 Mon Sep 17 00:00:00 2001 From: Tulong4Dev Date: Thu, 16 Mar 2023 21:50:04 -0700 Subject: [PATCH 139/147] update golden. --- .../strong_vpr_constraint/config/golden_results.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_vpr_constraint/config/golden_results.txt b/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_vpr_constraint/config/golden_results.txt index 359030d6c0d..243f67c8e75 100644 --- a/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_vpr_constraint/config/golden_results.txt +++ b/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_vpr_constraint/config/golden_results.txt @@ -1,2 +1,2 @@ arch circuit script_params vtr_flow_elapsed_time vtr_max_mem_stage vtr_max_mem error odin_synth_time max_odin_mem parmys_synth_time max_parmys_mem abc_depth abc_synth_time abc_cec_time abc_sec_time max_abc_mem ace_time max_ace_mem num_clb num_io num_memories num_mult vpr_status vpr_revision vpr_build_info vpr_compiler vpr_compiled hostname rundir max_vpr_mem num_primary_inputs num_primary_outputs num_pre_packed_nets num_pre_packed_blocks num_netlist_clocks num_post_packed_nets num_post_packed_blocks device_width device_height device_grid_tiles device_limiting_resources device_name pack_mem pack_time placed_wirelength_est place_mem place_time place_quench_time placed_CPD_est placed_setup_TNS_est placed_setup_WNS_est placed_geomean_nonvirtual_intradomain_critical_path_delay_est place_delay_matrix_lookup_time place_quench_timing_analysis_time place_quench_sta_time place_total_timing_analysis_time place_total_sta_time min_chan_width routed_wirelength min_chan_width_route_success_iteration logic_block_area_total logic_block_area_used min_chan_width_routing_area_total min_chan_width_routing_area_per_tile min_chan_width_route_time min_chan_width_total_timing_analysis_time min_chan_width_total_sta_time crit_path_num_rr_graph_nodes crit_path_num_rr_graph_edges crit_path_collapsed_nodes crit_path_routed_wirelength crit_path_route_success_iteration crit_path_total_nets_routed crit_path_total_connections_routed crit_path_total_heap_pushes crit_path_total_heap_pops crit_path_total_internal_heap_pushes crit_path_total_internal_heap_pops crit_path_total_external_heap_pushes crit_path_total_external_heap_pops crit_path_total_external_SOURCE_pushes crit_path_total_external_SOURCE_pops crit_path_total_internal_SOURCE_pushes crit_path_total_internal_SOURCE_pops crit_path_total_external_SINK_pushes crit_path_total_external_SINK_pops crit_path_total_internal_SINK_pushes crit_path_total_internal_SINK_pops crit_path_total_external_IPIN_pushes crit_path_total_external_IPIN_pops crit_path_total_internal_IPIN_pushes crit_path_total_internal_IPIN_pops crit_path_total_external_OPIN_pushes crit_path_total_external_OPIN_pops crit_path_total_internal_OPIN_pushes crit_path_total_internal_OPIN_pops crit_path_total_external_CHANX_pushes crit_path_total_external_CHANX_pops crit_path_total_internal_CHANX_pushes crit_path_total_internal_CHANX_pops crit_path_total_external_CHANY_pushes crit_path_total_external_CHANY_pops crit_path_total_internal_CHANY_pushes crit_path_total_internal_CHANY_pops crit_path_rt_node_SOURCE_pushes crit_path_rt_node_SINK_pushes crit_path_rt_node_IPIN_pushes crit_path_rt_node_OPIN_pushes crit_path_rt_node_CHANX_pushes crit_path_rt_node_CHANY_pushes crit_path_adding_all_rt crit_path_adding_high_fanout_rt crit_path_total_number_of_adding_all_rt_from_calling_high_fanout_rt critical_path_delay geomean_nonvirtual_intradomain_critical_path_delay setup_TNS setup_WNS hold_TNS hold_WNS crit_path_routing_area_total crit_path_routing_area_per_tile router_lookahead_computation_time crit_path_route_time crit_path_create_rr_graph_time crit_path_create_intra_cluster_rr_graph_time crit_path_tile_lookahead_computation_time crit_path_router_lookahead_computation_time crit_path_total_timing_analysis_time crit_path_total_sta_time -k4_frac_N4_fracff_localClkGen_40nm.xml and_clk.blif common 0.67 vpr 186.86 MiB -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 2 2 -1 -1 success 0dbd6851f release IPO VTR_ASSERT_LEVEL=3 sanitizers GNU 9.4.0 on Linux-5.15.0-67-generic x86_64 2023-03-14T11:14:58 workstation /home/tao/works/dev/route/vtr-verilog-to-routing/vtr_flow/tasks 191344 2 1 4 5 1 4 5 4 4 16 clb auto 45.8 MiB 0.01 11 185.3 MiB 0.00 0.00 1.13498 -1.13498 -1.13498 1.13498 0.01 6.4456e-05 6.0907e-05 0.000407814 0.00028842 -1 8 1 215576 107788 120301. 7518.81 0.00 0.000999195 0.000686301 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +k4_frac_N4_fracff_localClkGen_40nm.xml and_clk.blif common 0.67 vpr 186.86 MiB -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 2 2 -1 -1 success 0dbd6851f release IPO VTR_ASSERT_LEVEL=3 sanitizers GNU 9.4.0 on Linux-5.15.0-67-generic x86_64 2023-03-14T11:14:58 workstation /home/tao/works/dev/route/vtr-verilog-to-routing/vtr_flow/tasks 61038 2 1 4 5 1 4 5 4 4 16 clb auto 45.8 MiB 0.01 11 185.3 MiB 0.00 0.00 1.13498 -1.13498 -1.13498 1.13498 0.01 6.4456e-05 6.0907e-05 0.000407814 0.00028842 -1 8 1 215576 107788 120301. 7518.81 0.00 0.000999195 0.000686301 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 From 8593cb5cb40cc65fc36fea97f552648b05ee255b Mon Sep 17 00:00:00 2001 From: Tulong4Dev Date: Fri, 17 Mar 2023 18:11:14 -0700 Subject: [PATCH 140/147] update golden result with deep-cleaned build. --- .../strong_vpr_constraint/config/golden_results.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_vpr_constraint/config/golden_results.txt b/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_vpr_constraint/config/golden_results.txt index 243f67c8e75..1de222ff286 100644 --- a/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_vpr_constraint/config/golden_results.txt +++ b/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_vpr_constraint/config/golden_results.txt @@ -1,2 +1,2 @@ arch circuit script_params vtr_flow_elapsed_time vtr_max_mem_stage vtr_max_mem error odin_synth_time max_odin_mem parmys_synth_time max_parmys_mem abc_depth abc_synth_time abc_cec_time abc_sec_time max_abc_mem ace_time max_ace_mem num_clb num_io num_memories num_mult vpr_status vpr_revision vpr_build_info vpr_compiler vpr_compiled hostname rundir max_vpr_mem num_primary_inputs num_primary_outputs num_pre_packed_nets num_pre_packed_blocks num_netlist_clocks num_post_packed_nets num_post_packed_blocks device_width device_height device_grid_tiles device_limiting_resources device_name pack_mem pack_time placed_wirelength_est place_mem place_time place_quench_time placed_CPD_est placed_setup_TNS_est placed_setup_WNS_est placed_geomean_nonvirtual_intradomain_critical_path_delay_est place_delay_matrix_lookup_time place_quench_timing_analysis_time place_quench_sta_time place_total_timing_analysis_time place_total_sta_time min_chan_width routed_wirelength min_chan_width_route_success_iteration logic_block_area_total logic_block_area_used min_chan_width_routing_area_total min_chan_width_routing_area_per_tile min_chan_width_route_time min_chan_width_total_timing_analysis_time min_chan_width_total_sta_time crit_path_num_rr_graph_nodes crit_path_num_rr_graph_edges crit_path_collapsed_nodes crit_path_routed_wirelength crit_path_route_success_iteration crit_path_total_nets_routed crit_path_total_connections_routed crit_path_total_heap_pushes crit_path_total_heap_pops crit_path_total_internal_heap_pushes crit_path_total_internal_heap_pops crit_path_total_external_heap_pushes crit_path_total_external_heap_pops crit_path_total_external_SOURCE_pushes crit_path_total_external_SOURCE_pops crit_path_total_internal_SOURCE_pushes crit_path_total_internal_SOURCE_pops crit_path_total_external_SINK_pushes crit_path_total_external_SINK_pops crit_path_total_internal_SINK_pushes crit_path_total_internal_SINK_pops crit_path_total_external_IPIN_pushes crit_path_total_external_IPIN_pops crit_path_total_internal_IPIN_pushes crit_path_total_internal_IPIN_pops crit_path_total_external_OPIN_pushes crit_path_total_external_OPIN_pops crit_path_total_internal_OPIN_pushes crit_path_total_internal_OPIN_pops crit_path_total_external_CHANX_pushes crit_path_total_external_CHANX_pops crit_path_total_internal_CHANX_pushes crit_path_total_internal_CHANX_pops crit_path_total_external_CHANY_pushes crit_path_total_external_CHANY_pops crit_path_total_internal_CHANY_pushes crit_path_total_internal_CHANY_pops crit_path_rt_node_SOURCE_pushes crit_path_rt_node_SINK_pushes crit_path_rt_node_IPIN_pushes crit_path_rt_node_OPIN_pushes crit_path_rt_node_CHANX_pushes crit_path_rt_node_CHANY_pushes crit_path_adding_all_rt crit_path_adding_high_fanout_rt crit_path_total_number_of_adding_all_rt_from_calling_high_fanout_rt critical_path_delay geomean_nonvirtual_intradomain_critical_path_delay setup_TNS setup_WNS hold_TNS hold_WNS crit_path_routing_area_total crit_path_routing_area_per_tile router_lookahead_computation_time crit_path_route_time crit_path_create_rr_graph_time crit_path_create_intra_cluster_rr_graph_time crit_path_tile_lookahead_computation_time crit_path_router_lookahead_computation_time crit_path_total_timing_analysis_time crit_path_total_sta_time -k4_frac_N4_fracff_localClkGen_40nm.xml and_clk.blif common 0.67 vpr 186.86 MiB -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 2 2 -1 -1 success 0dbd6851f release IPO VTR_ASSERT_LEVEL=3 sanitizers GNU 9.4.0 on Linux-5.15.0-67-generic x86_64 2023-03-14T11:14:58 workstation /home/tao/works/dev/route/vtr-verilog-to-routing/vtr_flow/tasks 61038 2 1 4 5 1 4 5 4 4 16 clb auto 45.8 MiB 0.01 11 185.3 MiB 0.00 0.00 1.13498 -1.13498 -1.13498 1.13498 0.01 6.4456e-05 6.0907e-05 0.000407814 0.00028842 -1 8 1 215576 107788 120301. 7518.81 0.00 0.000999195 0.000686301 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +k4_frac_N4_fracff_localClkGen_40nm.xml and_clk.blif common 0.07 vpr 46.89 MiB -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 2 2 -1 -1 success bd5999406-dirty release IPO VTR_ASSERT_LEVEL=2 GNU 9.4.0 on Linux-5.15.0-67-generic x86_64 2023-03-17T17:48:18 workstation /home/tao/works/dev/route/vtr-verilog-to-routing/vtr_flow/tasks 48016 2 1 4 5 1 4 5 4 4 16 clb auto 7.9 MiB 0.00 11 46.9 MiB 0.00 0.00 1.13498 -1.13498 -1.13498 1.13498 0.00 3.031e-06 1.541e-06 3.5814e-05 2.5748e-05 -1 8 1 215576 107788 120301. 7518.81 0.00 0.00010342 7.9026e-05 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 From 294c49ba167ee439ada0c8efd59f466e4c977dbf Mon Sep 17 00:00:00 2001 From: Tulong4Dev Date: Wed, 22 Mar 2023 15:13:25 -0700 Subject: [PATCH 141/147] clean up code based on review comments. --- doc/src/vpr/route_constraints.rst | 7 ++++- vpr/src/base/route_constraint.cpp | 8 +++--- vpr/src/base/route_constraint.h | 8 +++--- vpr/src/base/vpr_constraints.cpp | 32 +++++++++++------------ vpr/src/base/vpr_constraints.h | 4 +-- vpr/src/base/vpr_constraints_serializer.h | 6 ++--- vpr/src/base/vpr_constraints_writer.cpp | 2 +- vpr/src/util/vpr_utils.cpp | 6 ++--- 8 files changed, 38 insertions(+), 35 deletions(-) diff --git a/doc/src/vpr/route_constraints.rst b/doc/src/vpr/route_constraints.rst index 484e90f2574..fe921cd5a23 100644 --- a/doc/src/vpr/route_constraints.rst +++ b/doc/src/vpr/route_constraints.rst @@ -1,9 +1,11 @@ -VPR Placement Constraints +VPR Route Constraints ========================= .. _vpr_constraints_file: VPR supports running flows with route constraints. Route constraints are set on global signals to specify if they should be routed or not. For example, a user may want to route a specific internal clock even clock modeling option is set to not route it. +.. note:: The constraint specified in this file overrides the setting of option "--clock_modeling" if it is specified. A message will be issued in such case: "Route constraint(s) detected and will override clock modeling setting". + The route constraints should be specified by the user using an XML constraints file format, as described in the section below. A Constraints File Example @@ -18,11 +20,14 @@ A Constraints File Example + .. _end: +.. note:: The "route_model" in constraint specified in this file only support "ideal" and "route" only. + Constraints File Format ----------------------- diff --git a/vpr/src/base/route_constraint.cpp b/vpr/src/base/route_constraint.cpp index a7dadc3a1ec..4ed76deb108 100644 --- a/vpr/src/base/route_constraint.cpp +++ b/vpr/src/base/route_constraint.cpp @@ -12,7 +12,7 @@ void RouteConstraint::set_net_name(std::string name) { return; } -std::string RouteConstraint::get_net_name() const { +std::string RouteConstraint::net_name() const { return net_name_; } @@ -21,7 +21,7 @@ void RouteConstraint::set_net_type(std::string type) { return; } -std::string RouteConstraint::get_net_type() const { +std::string RouteConstraint::net_type() const { return net_type_; } @@ -30,7 +30,7 @@ void RouteConstraint::set_route_model(std::string route_method) { return; } -std::string RouteConstraint::get_route_model() const { +std::string RouteConstraint::route_model() const { return route_method_; } @@ -38,6 +38,6 @@ void RouteConstraint::set_is_valid(bool value) { is_valid_ = value; } -bool RouteConstraint::get_is_valid() const { +bool RouteConstraint::is_valid() const { return is_valid_; } diff --git a/vpr/src/base/route_constraint.h b/vpr/src/base/route_constraint.h index 50b967e3f31..58b2839d060 100644 --- a/vpr/src/base/route_constraint.h +++ b/vpr/src/base/route_constraint.h @@ -18,7 +18,7 @@ class RouteConstraint { /** * @brief get net name */ - std::string get_net_name() const; + std::string net_name() const; /** * @brief set net name @@ -28,7 +28,7 @@ class RouteConstraint { /** * @brief get net type */ - std::string get_net_type() const; + std::string net_type() const; /** * @brief set net type @@ -38,7 +38,7 @@ class RouteConstraint { /** * @brief get route model */ - std::string get_route_model() const; + std::string route_model() const; /** * @brief set route model @@ -53,7 +53,7 @@ class RouteConstraint { /** * @brief get is valid */ - bool get_is_valid() const; + bool is_valid() const; private: std::string net_name_; diff --git a/vpr/src/base/vpr_constraints.cpp b/vpr/src/base/vpr_constraints.cpp index 742cc014955..64dcfd310c8 100644 --- a/vpr/src/base/vpr_constraints.cpp +++ b/vpr/src/base/vpr_constraints.cpp @@ -61,11 +61,11 @@ PartitionRegion VprConstraints::get_partition_pr(PartitionId part_id) { } void VprConstraints::add_route_constraint(RouteConstraint rc) { - route_constraints_.insert({rc.get_net_name(), rc}); + route_constraints_.insert({rc.net_name(), rc}); return; } -RouteConstraint VprConstraints::get_route_constraint_by_net_name(std::string net_name) { +const RouteConstraint VprConstraints::get_route_constraint_by_net_name(std::string net_name) { RouteConstraint rc; auto const& rc_itr = route_constraints_.find(net_name); if (rc_itr == route_constraints_.end()) { @@ -73,20 +73,18 @@ RouteConstraint VprConstraints::get_route_constraint_by_net_name(std::string net bool found_thru_regex = false; for (auto constraint : route_constraints_) { if (std::regex_match(net_name, std::regex(constraint.first))) { - { - rc = constraint.second; - - // mark as invalid so write constraint function will not write constraint - // of regexpr name - // instead a matched constraint is inserted in - constraint.second.set_is_valid(false); - rc.set_net_name(net_name); - rc.set_is_valid(true); - route_constraints_.insert({net_name, rc}); - - found_thru_regex = true; - break; - } + rc = constraint.second; + + // mark as invalid so write constraint function will not write constraint + // of regexpr name + // instead a matched constraint is inserted in + constraint.second.set_is_valid(false); + rc.set_net_name(net_name); + rc.set_is_valid(true); + route_constraints_.insert({net_name, rc}); + + found_thru_regex = true; + break; } } if (!found_thru_regex) { @@ -101,7 +99,7 @@ RouteConstraint VprConstraints::get_route_constraint_by_net_name(std::string net return rc; } -RouteConstraint VprConstraints::get_route_constraint_by_idx(std::size_t idx) const { +const RouteConstraint VprConstraints::get_route_constraint_by_idx(std::size_t idx) const { RouteConstraint rc; if ((route_constraints_.size() == 0) || (idx > route_constraints_.size() - 1)) { rc.set_net_name("INVALID"); diff --git a/vpr/src/base/vpr_constraints.h b/vpr/src/base/vpr_constraints.h index 61d7ed9d6b6..f9343267a9e 100644 --- a/vpr/src/base/vpr_constraints.h +++ b/vpr/src/base/vpr_constraints.h @@ -100,14 +100,14 @@ class VprConstraints { * * @param index the constraint index */ - RouteConstraint get_route_constraint_by_idx(std::size_t index) const; + const RouteConstraint get_route_constraint_by_idx(std::size_t index) const; /** * @brief returns route constraint of a specific net * * @param net_name the net name */ - RouteConstraint get_route_constraint_by_net_name(std::string net_name); + const RouteConstraint get_route_constraint_by_net_name(std::string net_name); /** * @brief returns number of route constraints diff --git a/vpr/src/base/vpr_constraints_serializer.h b/vpr/src/base/vpr_constraints_serializer.h index bba5ee0f1d2..77f8184cbc1 100644 --- a/vpr/src/base/vpr_constraints_serializer.h +++ b/vpr/src/base/vpr_constraints_serializer.h @@ -313,7 +313,7 @@ class VprConstraintsSerializer final : public uxsd::VprConstraintsBase */ virtual inline const char* get_set_global_signal_name(RouteConstraint& rc) final { - temp_name_string_ = rc.get_net_name(); + temp_name_string_ = rc.net_name(); return temp_name_string_.c_str(); } virtual inline void set_set_global_signal_name(const char* name, void*& /*ctx*/) final { @@ -322,7 +322,7 @@ class VprConstraintsSerializer final : public uxsd::VprConstraintsBase Date: Thu, 23 Mar 2023 18:02:53 -0700 Subject: [PATCH 142/147] support route constraints. --- vpr/src/base/route_constraint.cpp | 8 +-- vpr/src/base/route_constraint.h | 8 +-- vpr/src/base/vpr_api.cpp | 7 +- vpr/src/base/vpr_constraints.cpp | 32 ++++----- vpr/src/base/vpr_constraints.h | 4 +- vpr/src/base/vpr_constraints_serializer.h | 16 +++-- vpr/src/base/vpr_constraints_writer.cpp | 70 ++++++++++++------- vpr/src/base/vpr_constraints_writer.h | 10 ++- vpr/src/util/vpr_utils.cpp | 4 +- .../vtr_reg_strong/task_list.txt | 2 + 10 files changed, 95 insertions(+), 66 deletions(-) diff --git a/vpr/src/base/route_constraint.cpp b/vpr/src/base/route_constraint.cpp index a7dadc3a1ec..4ed76deb108 100644 --- a/vpr/src/base/route_constraint.cpp +++ b/vpr/src/base/route_constraint.cpp @@ -12,7 +12,7 @@ void RouteConstraint::set_net_name(std::string name) { return; } -std::string RouteConstraint::get_net_name() const { +std::string RouteConstraint::net_name() const { return net_name_; } @@ -21,7 +21,7 @@ void RouteConstraint::set_net_type(std::string type) { return; } -std::string RouteConstraint::get_net_type() const { +std::string RouteConstraint::net_type() const { return net_type_; } @@ -30,7 +30,7 @@ void RouteConstraint::set_route_model(std::string route_method) { return; } -std::string RouteConstraint::get_route_model() const { +std::string RouteConstraint::route_model() const { return route_method_; } @@ -38,6 +38,6 @@ void RouteConstraint::set_is_valid(bool value) { is_valid_ = value; } -bool RouteConstraint::get_is_valid() const { +bool RouteConstraint::is_valid() const { return is_valid_; } diff --git a/vpr/src/base/route_constraint.h b/vpr/src/base/route_constraint.h index 50b967e3f31..58b2839d060 100644 --- a/vpr/src/base/route_constraint.h +++ b/vpr/src/base/route_constraint.h @@ -18,7 +18,7 @@ class RouteConstraint { /** * @brief get net name */ - std::string get_net_name() const; + std::string net_name() const; /** * @brief set net name @@ -28,7 +28,7 @@ class RouteConstraint { /** * @brief get net type */ - std::string get_net_type() const; + std::string net_type() const; /** * @brief set net type @@ -38,7 +38,7 @@ class RouteConstraint { /** * @brief get route model */ - std::string get_route_model() const; + std::string route_model() const; /** * @brief set route model @@ -53,7 +53,7 @@ class RouteConstraint { /** * @brief get is valid */ - bool get_is_valid() const; + bool is_valid() const; private: std::string net_name_; diff --git a/vpr/src/base/vpr_api.cpp b/vpr/src/base/vpr_api.cpp index f8e481f3a24..2c79268a44a 100644 --- a/vpr/src/base/vpr_api.cpp +++ b/vpr/src/base/vpr_api.cpp @@ -701,7 +701,7 @@ bool vpr_place_flow(t_vpr_setup& vpr_setup, const t_arch& arch) { //Write out a vpr floorplanning constraints file if the option is specified if (!filename_opts.write_vpr_constraints_file.empty()) { - write_vpr_floorplan_constraints("vpr_floorplan_constraints.xml" /*filename_opts.write_vpr_constraints_file.c_str()*/, placer_opts.place_constraint_expand, placer_opts.place_constraint_subtile, + write_vpr_floorplan_constraints(filename_opts.write_vpr_constraints_file.c_str(), placer_opts.place_constraint_expand, placer_opts.place_constraint_subtile, placer_opts.floorplan_num_horizontal_partitions, placer_opts.floorplan_num_vertical_partitions); } @@ -857,11 +857,6 @@ RouteStatus vpr_route_flow(t_vpr_setup& vpr_setup, const t_arch& arch, bool is_f //Update interactive graphics update_screen(ScreenUpdatePriority::MAJOR, graphics_msg.c_str(), ROUTING, timing_info); - - //Write out a vpr floorplanning constraints file if the option is specified - if (!filename_opts.write_vpr_constraints_file.empty()) { - write_vpr_route_constraints(g_vpr_ctx.routing().constraints, "vpr_route_constraints.xml" /*filename_opts.write_vpr_constraints_file.c_str()*/); - } } return route_status; diff --git a/vpr/src/base/vpr_constraints.cpp b/vpr/src/base/vpr_constraints.cpp index 4b9850be670..64dcfd310c8 100644 --- a/vpr/src/base/vpr_constraints.cpp +++ b/vpr/src/base/vpr_constraints.cpp @@ -61,11 +61,11 @@ PartitionRegion VprConstraints::get_partition_pr(PartitionId part_id) { } void VprConstraints::add_route_constraint(RouteConstraint rc) { - route_constraints_.insert({rc.get_net_name(), rc}); + route_constraints_.insert({rc.net_name(), rc}); return; } -RouteConstraint VprConstraints::get_route_constraint_by_net_name(std::string net_name) { +const RouteConstraint VprConstraints::get_route_constraint_by_net_name(std::string net_name) { RouteConstraint rc; auto const& rc_itr = route_constraints_.find(net_name); if (rc_itr == route_constraints_.end()) { @@ -73,19 +73,18 @@ RouteConstraint VprConstraints::get_route_constraint_by_net_name(std::string net bool found_thru_regex = false; for (auto constraint : route_constraints_) { if (std::regex_match(net_name, std::regex(constraint.first))) { - { - rc = constraint.second; - - // mark as invalid so write constraint function will not write constraint - // of regexpr name - // instead a matched constraint is inerted in - constraint.second.set_is_valid(false); - rc.set_is_valid(true); - route_constraints_.insert({net_name, rc}); - - found_thru_regex = true; - break; - } + rc = constraint.second; + + // mark as invalid so write constraint function will not write constraint + // of regexpr name + // instead a matched constraint is inserted in + constraint.second.set_is_valid(false); + rc.set_net_name(net_name); + rc.set_is_valid(true); + route_constraints_.insert({net_name, rc}); + + found_thru_regex = true; + break; } } if (!found_thru_regex) { @@ -100,7 +99,7 @@ RouteConstraint VprConstraints::get_route_constraint_by_net_name(std::string net return rc; } -RouteConstraint VprConstraints::get_route_constraint_by_idx(std::size_t idx) const { +const RouteConstraint VprConstraints::get_route_constraint_by_idx(std::size_t idx) const { RouteConstraint rc; if ((route_constraints_.size() == 0) || (idx > route_constraints_.size() - 1)) { rc.set_net_name("INVALID"); @@ -112,6 +111,7 @@ RouteConstraint VprConstraints::get_route_constraint_by_idx(std::size_t idx) con for (auto const& rc_itr : route_constraints_) { if (i == idx) { rc = rc_itr.second; + break; } } } diff --git a/vpr/src/base/vpr_constraints.h b/vpr/src/base/vpr_constraints.h index 61d7ed9d6b6..f9343267a9e 100644 --- a/vpr/src/base/vpr_constraints.h +++ b/vpr/src/base/vpr_constraints.h @@ -100,14 +100,14 @@ class VprConstraints { * * @param index the constraint index */ - RouteConstraint get_route_constraint_by_idx(std::size_t index) const; + const RouteConstraint get_route_constraint_by_idx(std::size_t index) const; /** * @brief returns route constraint of a specific net * * @param net_name the net name */ - RouteConstraint get_route_constraint_by_net_name(std::string net_name); + const RouteConstraint get_route_constraint_by_net_name(std::string net_name); /** * @brief returns number of route constraints diff --git a/vpr/src/base/vpr_constraints_serializer.h b/vpr/src/base/vpr_constraints_serializer.h index b57756f5c7a..77f8184cbc1 100644 --- a/vpr/src/base/vpr_constraints_serializer.h +++ b/vpr/src/base/vpr_constraints_serializer.h @@ -313,7 +313,8 @@ class VprConstraintsSerializer final : public uxsd::VprConstraintsBase */ virtual inline const char* get_set_global_signal_name(RouteConstraint& rc) final { - return rc.get_net_name().c_str(); + temp_name_string_ = rc.net_name(); + return temp_name_string_.c_str(); } virtual inline void set_set_global_signal_name(const char* name, void*& /*ctx*/) final { std::string net_name = std::string(name); @@ -321,14 +322,16 @@ class VprConstraintsSerializer final : public uxsd::VprConstraintsBase::max_digits10); + void* context; + uxsd::write_vpr_constraints_xml(writer, context, fp); + } else { + VPR_FATAL_ERROR(VPR_ERROR_ROUTE, + "Unknown extension on output %s", + file_name.c_str()); + } + } + return; +} + void write_vpr_floorplan_constraints(const char* file_name, int expand, bool subtile, int horizontal_partitions, int vertical_partitions) { VprConstraints constraints; @@ -214,29 +258,3 @@ void create_partition(Partition& part, std::string part_name, int xmin, int ymin part_pr.set_partition_region(part_regions); part.set_part_region(part_pr); } - -void write_vpr_route_constraints(const VprConstraints& constraints, const char* file_name) { - VprConstraints write_constraints; - for (int i = 0; i < constraints.get_route_constraint_num(); i++) { - RouteConstraint rc = constraints.get_route_constraint_by_idx(i); - if (rc.get_is_valid()) { - write_constraints.add_route_constraint(rc); - } - } - - VprConstraintsSerializer writer(write_constraints); - - if (vtr::check_file_name_extension(file_name, ".xml")) { - std::fstream fp; - fp.open(file_name, std::fstream::out | std::fstream::trunc); - fp.precision(std::numeric_limits::max_digits10); - void* context; - uxsd::write_vpr_constraints_xml(writer, context, fp); - } else { - VPR_FATAL_ERROR(VPR_ERROR_ROUTE, - "Unknown extension on output %s", - file_name); - } - - return; -} diff --git a/vpr/src/base/vpr_constraints_writer.h b/vpr/src/base/vpr_constraints_writer.h index caac1abd85b..158a87aa040 100644 --- a/vpr/src/base/vpr_constraints_writer.h +++ b/vpr/src/base/vpr_constraints_writer.h @@ -25,6 +25,14 @@ #ifndef VPR_SRC_BASE_VPR_CONSTRAINTS_WRITER_H_ #define VPR_SRC_BASE_VPR_CONSTRAINTS_WRITER_H_ +/** + * @brief Write out vpr constratins to an XML file based on current placement and + * route constraint settings + * + * @param vpr_setup VPR setup information + */ +void write_vpr_constraints(t_vpr_setup& vpr_setup); + /** * @brief Write out floorplan constraints to an XML file based on current placement * @@ -47,6 +55,4 @@ void setup_vpr_floorplan_constraints_cutpoints(VprConstraints& constraints, int void create_partition(Partition& part, std::string part_name, int xmin, int ymin, int xmax, int ymax); -void write_vpr_route_constraints(const VprConstraints& constraints, const char* file_name); - #endif /* VPR_SRC_BASE_VPR_CONSTRAINTS_WRITER_H_ */ diff --git a/vpr/src/util/vpr_utils.cpp b/vpr/src/util/vpr_utils.cpp index 1583065d0ed..8288cb1d8c5 100644 --- a/vpr/src/util/vpr_utils.cpp +++ b/vpr/src/util/vpr_utils.cpp @@ -2198,9 +2198,9 @@ void apply_route_constraints(VprConstraints& vpr_constraint) { for (auto net_id : mutable_cluster_ctx.clb_nlist.nets()) { std::string net_name = mutable_cluster_ctx.clb_nlist.net_name(net_id); RouteConstraint rc = vpr_constraint.get_route_constraint_by_net_name(net_name); - if (rc.get_is_valid()) { + if (rc.is_valid()) { mutable_cluster_ctx.clb_nlist.set_net_is_global(net_id, true); - if (rc.get_route_model() == "route") { + if (rc.route_model() == "route") { mutable_cluster_ctx.clb_nlist.set_net_is_ignored(net_id, false); } else { mutable_cluster_ctx.clb_nlist.set_net_is_ignored(net_id, true); diff --git a/vtr_flow/tasks/regression_tests/vtr_reg_strong/task_list.txt b/vtr_flow/tasks/regression_tests/vtr_reg_strong/task_list.txt index 53c065e2338..3c16003523d 100644 --- a/vtr_flow/tasks/regression_tests/vtr_reg_strong/task_list.txt +++ b/vtr_flow/tasks/regression_tests/vtr_reg_strong/task_list.txt @@ -1,3 +1,4 @@ +regression_tests/vtr_reg_strong/koios regression_tests/vtr_reg_strong/strong_absorb_buffers regression_tests/vtr_reg_strong/strong_analysis_only regression_tests/vtr_reg_strong/strong_analytic_placer @@ -83,3 +84,4 @@ regression_tests/vtr_reg_strong/koios_no_complex_dsp regression_tests/vtr_reg_strong/strong_timing_fail regression_tests/vtr_reg_strong/strong_timing_no_fail regression_tests/vtr_reg_strong/strong_tileable_rr_graph +regression_tests/vtr_reg_strong/strong_vpr_constraint From 4c43c7486b77e30b40577465a2d611211e3ff635 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 14 Apr 2023 19:51:43 -0700 Subject: [PATCH 143/147] [core] resovle mering conflicts which causes compilation failures --- libs/librrgraph/src/base/rr_graph_builder.cpp | 2 -- libs/librrgraph/src/base/rr_graph_builder.h | 2 +- vpr/src/route/router_lookahead_map.cpp | 4 ++- vpr/src/route/rr_graph.cpp | 32 ++++--------------- vpr/src/route/rr_graph.h | 11 +++++-- .../tileable_rr_graph_builder.cpp | 16 +++++----- 6 files changed, 28 insertions(+), 39 deletions(-) diff --git a/libs/librrgraph/src/base/rr_graph_builder.cpp b/libs/librrgraph/src/base/rr_graph_builder.cpp index a5b0c3cd13b..e1b24083159 100644 --- a/libs/librrgraph/src/base/rr_graph_builder.cpp +++ b/libs/librrgraph/src/base/rr_graph_builder.cpp @@ -103,9 +103,7 @@ void RRGraphBuilder::clear() { node_ptc_nums_.clear(); rr_node_metadata_.clear(); rr_edge_metadata_.clear(); - segment_ids_.clear(); rr_segments_.clear(); - switch_ids_.clear(); rr_switch_inf_.clear(); edges_to_build_.clear(); is_edge_dirty_ = true; diff --git a/libs/librrgraph/src/base/rr_graph_builder.h b/libs/librrgraph/src/base/rr_graph_builder.h index 7ccc04815e5..089a0c393da 100644 --- a/libs/librrgraph/src/base/rr_graph_builder.h +++ b/libs/librrgraph/src/base/rr_graph_builder.h @@ -296,7 +296,7 @@ class RRGraphBuilder { } /* Unlock storage; required to modify an routing resource graph after edge is read */ - inline void unlock_storage() { node_storage_.edges_read_ = false; node_storage_.partitioned_ = false; node_storage_.node_first_edge_.clear();} + inline void unlock_storage() { node_storage_.edges_read_ = false; node_storage_.partitioned_ = false; node_storage_.clear_node_first_edge();} /** @brief Reserve the lists of nodes, edges, switches etc. to be memory efficient. * This function is mainly used to reserve memory space inside RRGraph, diff --git a/vpr/src/route/router_lookahead_map.cpp b/vpr/src/route/router_lookahead_map.cpp index 9836e7cfb91..7f86e6352a0 100644 --- a/vpr/src/route/router_lookahead_map.cpp +++ b/vpr/src/route/router_lookahead_map.cpp @@ -1350,7 +1350,9 @@ static void compute_tile_lookahead(std::unordered_map>& switch_fanin_remap, - const std::map arch_sw_inf, - const float R_minW_nmos, - const float R_minW_pmos, - const int wire_to_arch_ipin_switch, - int* wire_to_rr_ipin_switch); - static void remap_rr_node_switch_indices(RRGraphBuilder& rr_graph_builder, const t_arch_switch_fanin& switch_fanin); @@ -451,16 +443,6 @@ static void alloc_rr_switch_inf(RRGraphBuilder& rr_graph_builder, static t_seg_details* alloc_and_load_global_route_seg_details(const int global_route_switch, int* num_seg_details = nullptr); -static std::vector> alloc_and_load_actual_fc(const std::vector& types, - const int max_pins, - const std::vector& segment_inf, - const int* sets_per_seg_type, - const t_chan_width* nodes_per_chan, - const e_fc_type fc_type, - const enum e_directionality directionality, - bool* Fc_clipped, - bool is_flat); - static RRNodeId pick_best_direct_connect_target_rr_node(const RRGraphView& rr_graph, RRNodeId from_rr, const std::vector& candidate_rr_nodes); @@ -1417,13 +1399,13 @@ void build_tile_rr_graph(RRGraphBuilder& rr_graph_builder, * and count how many different fan-ins exist for each arch switch. * Then we create these rr switches and update the switch indices * of rr_nodes to index into the rr_switch_inf array. */ -static void alloc_and_load_rr_switch_inf(RRGraphBuilder& rr_graph_builder, - std::vector>& switch_fanin_remap, - const std::map arch_sw_inf, - const float R_minW_nmos, - const float R_minW_pmos, - const int wire_to_arch_ipin_switch, - int* wire_to_rr_ipin_switch) { +void alloc_and_load_rr_switch_inf(RRGraphBuilder& rr_graph_builder, + std::vector>& switch_fanin_remap, + const std::map arch_sw_inf, + const float R_minW_nmos, + const float R_minW_pmos, + const int wire_to_arch_ipin_switch, + int* wire_to_rr_ipin_switch) { /* we will potentially be creating a couple of versions of each arch switch where * each version corresponds to a different fan-in. We will need to fill device_ctx.rr_switch_inf * with this expanded list of switches. diff --git a/vpr/src/route/rr_graph.h b/vpr/src/route/rr_graph.h index 72a662f324f..0b49e71b218 100644 --- a/vpr/src/route/rr_graph.h +++ b/vpr/src/route/rr_graph.h @@ -46,7 +46,13 @@ t_rr_switch_inf create_rr_switch_from_arch_switch(const t_arch_switch_inf& arch_ const float R_minW_nmos, const float R_minW_pmos); -void alloc_and_load_rr_switch_inf(const int num_arch_switches, const float R_minW_nmos, const float R_minW_pmos, const int wire_to_arch_ipin_switch, int* wire_to_rr_ipin_switch); +void alloc_and_load_rr_switch_inf(RRGraphBuilder& rr_graph_builder, + std::vector>& switch_fanin_remap, + const std::map arch_sw_inf, + const float R_minW_nmos, + const float R_minW_pmos, + const int wire_to_arch_ipin_switch, + int* wire_to_rr_ipin_switch); void rr_graph_externals(const std::vector& segment_inf, const std::vector& segment_inf_x, @@ -63,7 +69,8 @@ std::vector> alloc_and_load_actual_fc(const std::vector& typ RRSwitchId wire_to_ipin_rr_switch = RRSwitchId::INVALID(); RRSwitchId delayless_rr_switch = RRSwitchId::INVALID(); - device_ctx.rr_graph_builder.reserve_switches(device_ctx.num_arch_switches); + device_ctx.rr_graph_builder.reserve_switches(device_ctx.arch_switch_inf.size()); /* Create the switches */ - for (int iswitch = 0; iswitch < device_ctx.num_arch_switches; ++iswitch) { - const t_rr_switch_inf& temp_rr_switch = create_rr_switch_from_arch_switch(iswitch, R_minW_nmos, R_minW_pmos); + for (size_t iswitch = 0; iswitch < device_ctx.arch_switch_inf.size(); ++iswitch) { + const t_rr_switch_inf& temp_rr_switch = create_rr_switch_from_arch_switch(device_ctx.arch_switch_inf[iswitch], R_minW_nmos, R_minW_pmos); RRSwitchId rr_switch = device_ctx.rr_graph_builder.add_rr_switch(temp_rr_switch); - if (iswitch == wire_to_arch_ipin_switch) { + if ((int)iswitch == wire_to_arch_ipin_switch) { wire_to_ipin_rr_switch = rr_switch; } - if (iswitch == delayless_switch) { + if ((int)iswitch == delayless_switch) { delayless_rr_switch = rr_switch; } } @@ -207,7 +207,7 @@ void build_tileable_unidir_rr_graph(const std::vector& typ /* [0..num_types-1][0..num_pins-1] */ std::vector> Fc_in; Fc_in = alloc_and_load_actual_fc(types, max_pins, segment_inf, sets_per_seg_type, (const t_chan_width*)&chan_width, - e_fc_type::IN, UNI_DIRECTIONAL, &Fc_clipped); + e_fc_type::IN, UNI_DIRECTIONAL, &Fc_clipped, false); if (Fc_clipped) { *Warnings |= RR_GRAPH_WARN_FC_CLIPPED; } @@ -216,7 +216,7 @@ void build_tileable_unidir_rr_graph(const std::vector& typ /* [0..num_types-1][0..num_pins-1] */ std::vector> Fc_out; Fc_out = alloc_and_load_actual_fc(types, max_pins, segment_inf, sets_per_seg_type, (const t_chan_width*)&chan_width, - e_fc_type::OUT, UNI_DIRECTIONAL, &Fc_clipped); + e_fc_type::OUT, UNI_DIRECTIONAL, &Fc_clipped, false); if (Fc_clipped) { *Warnings |= RR_GRAPH_WARN_FC_CLIPPED; @@ -263,7 +263,7 @@ void build_tileable_unidir_rr_graph(const std::vector& typ /* Allocate and load routing resource switches, which are derived from the switches from the architecture file, * based on their fanin in the rr graph. This routine also adjusts the rr nodes to point to these new rr switches */ device_ctx.rr_graph_builder.init_fan_in(); - alloc_and_load_rr_switch_inf(device_ctx.num_arch_switches, R_minW_nmos, R_minW_pmos, wire_to_arch_ipin_switch, wire_to_rr_ipin_switch); + alloc_and_load_rr_switch_inf(device_ctx.rr_graph_builder, device_ctx.switch_fanin_remap, device_ctx.all_sw_inf, R_minW_nmos, R_minW_pmos, wire_to_arch_ipin_switch, wire_to_rr_ipin_switch); /* Save the channel widths for the newly constructed graph */ device_ctx.chan_width = chan_width; From 6ac416c70ec00448a4e5c1b2ad560d461fbe9cef Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 14 Apr 2023 21:13:41 -0700 Subject: [PATCH 144/147] [core] code format --- vpr/src/route/rr_graph.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/vpr/src/route/rr_graph.cpp b/vpr/src/route/rr_graph.cpp index cfea765b9e2..4459d5fa9c1 100644 --- a/vpr/src/route/rr_graph.cpp +++ b/vpr/src/route/rr_graph.cpp @@ -1688,14 +1688,14 @@ static t_seg_details* alloc_and_load_global_route_seg_details(const int global_r /* Calculates the number of track connections from each block pin to each segment type */ std::vector> alloc_and_load_actual_fc(const std::vector& types, - const int max_pins, - const std::vector& segment_inf, - const int* sets_per_seg_type, - const t_chan_width* nodes_per_chan, - const e_fc_type fc_type, - const enum e_directionality directionality, - bool* Fc_clipped, - bool is_flat) { + const int max_pins, + const std::vector& segment_inf, + const int* sets_per_seg_type, + const t_chan_width* nodes_per_chan, + const e_fc_type fc_type, + const enum e_directionality directionality, + bool* Fc_clipped, + bool is_flat) { //Initialize Fc of all blocks to zero auto zeros = vtr::Matrix({size_t(max_pins), segment_inf.size()}, 0); std::vector> Fc(types.size(), zeros); From d70659f424425dbaa6ecdb6dea40bf1841f02dac Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 14 Apr 2023 21:16:41 -0700 Subject: [PATCH 145/147] [test] comment out testcase 'strong_vpr_constraints' due to a merging conflict --- vtr_flow/tasks/regression_tests/vtr_reg_strong/task_list.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/vtr_flow/tasks/regression_tests/vtr_reg_strong/task_list.txt b/vtr_flow/tasks/regression_tests/vtr_reg_strong/task_list.txt index cf4854f14df..7ca5174654e 100644 --- a/vtr_flow/tasks/regression_tests/vtr_reg_strong/task_list.txt +++ b/vtr_flow/tasks/regression_tests/vtr_reg_strong/task_list.txt @@ -84,5 +84,4 @@ regression_tests/vtr_reg_strong/koios_no_complex_dsp regression_tests/vtr_reg_strong/strong_timing_fail regression_tests/vtr_reg_strong/strong_timing_no_fail regression_tests/vtr_reg_strong/strong_tileable_rr_graph -regression_tests/vtr_reg_strong/strong_vpr_constraint regression_tests/vtr_reg_strong/strong_noc From 42e48e544825b502e59902ea4bc906af83684ff1 Mon Sep 17 00:00:00 2001 From: Tulong4Dev Date: Wed, 19 Apr 2023 15:55:05 -0700 Subject: [PATCH 146/147] add missing new line when writing place constraint --- vpr/src/base/gen/vpr_constraints_uxsdcxx.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vpr/src/base/gen/vpr_constraints_uxsdcxx.h b/vpr/src/base/gen/vpr_constraints_uxsdcxx.h index 12feabd08ab..166a5629425 100644 --- a/vpr/src/base/gen/vpr_constraints_uxsdcxx.h +++ b/vpr/src/base/gen/vpr_constraints_uxsdcxx.h @@ -1064,7 +1064,7 @@ inline void get_line_number(const char* filename, std::ptrdiff_t target_offset, std::unique_ptr f(fopen(filename, "rb"), fclose); if (!f) { - throw std::runtime_error(std::string("Failed to open file") + filename); + throw std::runtime_error(std::string("Failed to open file ") + filename); } int current_line = 1; From e0dd3c1467c708ff2e19f615aed41c5702931128 Mon Sep 17 00:00:00 2001 From: Tulong4Dev Date: Mon, 19 Jun 2023 10:38:23 -0700 Subject: [PATCH 147/147] support packer constraint. --- vpr/src/base/gen/vpr_constraints_uxsdcxx.h | 2093 +++++++++-------- .../gen/vpr_constraints_uxsdcxx_interface.h | 303 +-- vpr/src/base/packer_constraint.cpp | 33 + vpr/src/base/packer_constraint.h | 54 + vpr/src/base/vpr_constraints.cpp | 61 + vpr/src/base/vpr_constraints.h | 35 + vpr/src/base/vpr_constraints.xsd | 21 + vpr/src/base/vpr_constraints_serializer.h | 69 + 8 files changed, 1578 insertions(+), 1091 deletions(-) create mode 100644 vpr/src/base/packer_constraint.cpp create mode 100644 vpr/src/base/packer_constraint.h diff --git a/vpr/src/base/gen/vpr_constraints_uxsdcxx.h b/vpr/src/base/gen/vpr_constraints_uxsdcxx.h index 166a5629425..24e12ef884c 100644 --- a/vpr/src/base/gen/vpr_constraints_uxsdcxx.h +++ b/vpr/src/base/gen/vpr_constraints_uxsdcxx.h @@ -4,13 +4,14 @@ * https://github.com/duck2/uxsdcxx * Modify only if your build process doesn't involve regenerating this file. * - * Cmdline: uxsdcxx.py /home/tao/works/dev/clock/vtr-verilog-to-routing/vpr/src/base/vpr_constraints.xsd - * Input file: /home/tao/works/dev/clock/vtr-verilog-to-routing/vpr/src/base/vpr_constraints.xsd - * md5sum of input file: 2d6f442d8044f76e8f1b1d276b7358da + * Cmdline: uxsdcxx.py /home/tao/works/dev/route_constraints/vtr-verilog-to-routing/vpr/src/base/vpr_constraints.xsd + * Input file: /home/tao/works/dev/route_constraints/vtr-verilog-to-routing/vpr/src/base/vpr_constraints.xsd + * md5sum of input file: 9f078b743b3fa356a41cf239f150a599 */ #include + #include #include #include @@ -32,1073 +33,1251 @@ namespace uxsd { * Internal function for getting line and column number from file based on * byte offset. */ -inline void get_line_number(const char* filename, std::ptrdiff_t offset, int* line, int* col); +inline void get_line_number(const char *filename, std::ptrdiff_t offset, int * line, int * col); -[[noreturn]] inline void noreturn_report(const std::function* report_error, const char* msg) { +[[noreturn]] inline void noreturn_report(const std::function * report_error, const char *msg) { (*report_error)(msg); throw std::runtime_error("Unreachable!"); } /* Declarations for internal load functions for the complex types. */ -template -inline void load_add_atom(const pugi::xml_node& root, T& out, Context& context, const std::function* report_error, ptrdiff_t* offset_debug); -template -inline void load_add_region(const pugi::xml_node& root, T& out, Context& context, const std::function* report_error, ptrdiff_t* offset_debug); -inline void load_add_region_required_attributes(const pugi::xml_node& root, int* x_high, int* x_low, int* y_high, int* y_low, const std::function* report_error); -template -inline void load_partition(const pugi::xml_node& root, T& out, Context& context, const std::function* report_error, ptrdiff_t* offset_debug); -template -inline void load_partition_list(const pugi::xml_node& root, T& out, Context& context, const std::function* report_error, ptrdiff_t* offset_debug); -template -inline void load_set_global_signal(const pugi::xml_node& root, T& out, Context& context, const std::function* report_error, ptrdiff_t* offset_debug); -template -inline void load_global_route_constraints(const pugi::xml_node& root, T& out, Context& context, const std::function* report_error, ptrdiff_t* offset_debug); -template -inline void load_vpr_constraints(const pugi::xml_node& root, T& out, Context& context, const std::function* report_error, ptrdiff_t* offset_debug); +template +inline void load_add_atom(const pugi::xml_node &root, T &out, Context &context, const std::function *report_error, ptrdiff_t *offset_debug); +template +inline void load_add_region(const pugi::xml_node &root, T &out, Context &context, const std::function *report_error, ptrdiff_t *offset_debug); +inline void load_add_region_required_attributes(const pugi::xml_node &root, int * x_high, int * x_low, int * y_high, int * y_low, const std::function * report_error); +template +inline void load_partition(const pugi::xml_node &root, T &out, Context &context, const std::function *report_error, ptrdiff_t *offset_debug); +template +inline void load_partition_list(const pugi::xml_node &root, T &out, Context &context, const std::function *report_error, ptrdiff_t *offset_debug); +template +inline void load_set_global_signal(const pugi::xml_node &root, T &out, Context &context, const std::function *report_error, ptrdiff_t *offset_debug); +template +inline void load_global_route_constraints(const pugi::xml_node &root, T &out, Context &context, const std::function *report_error, ptrdiff_t *offset_debug); +template +inline void load_assignment(const pugi::xml_node &root, T &out, Context &context, const std::function *report_error, ptrdiff_t *offset_debug); +template +inline void load_packer_constraints(const pugi::xml_node &root, T &out, Context &context, const std::function *report_error, ptrdiff_t *offset_debug); +template +inline void load_vpr_constraints(const pugi::xml_node &root, T &out, Context &context, const std::function *report_error, ptrdiff_t *offset_debug); /* Declarations for internal write functions for the complex types. */ -template -inline void write_partition(T& in, std::ostream& os, const void* data, void* iter); -template -inline void write_partition_list(T& in, std::ostream& os, const void* data, void* iter); -template -inline void write_global_route_constraints(T& in, std::ostream& os, const void* data, void* iter); -template -inline void write_vpr_constraints(T& in, std::ostream& os, const void* data, void* iter); +template +inline void write_partition(T &in, std::ostream &os, const void *data, void *iter); +template +inline void write_partition_list(T &in, std::ostream &os, const void *data, void *iter); +template +inline void write_global_route_constraints(T &in, std::ostream &os, const void *data, void *iter); +template +inline void write_packer_constraints(T &in, std::ostream &os, const void *data, void *iter); +template +inline void write_vpr_constraints(T &in, std::ostream &os, const void *data, void *iter); /* Load function for the root element. */ -template -inline void load_vpr_constraints_xml(T& out, Context& context, const char* filename, std::istream& is) { - pugi::xml_document doc; - pugi::xml_parse_result result = doc.load(is); - if (!result) { - int line, col; - get_line_number(filename, result.offset, &line, &col); - std::stringstream msg; - msg << "Unable to load XML file '" << filename << "', "; - msg << result.description() << " (line: " << line; - msg << " col: " << col << ")"; - out.error_encountered(filename, line, msg.str().c_str()); - } - ptrdiff_t offset_debug = 0; - std::function report_error = [filename, &out, &offset_debug](const char* message) { - int line, col; - get_line_number(filename, offset_debug, &line, &col); - out.error_encountered(filename, line, message); - // If error_encountered didn't throw, throw now to unwind. - throw std::runtime_error(message); - }; - out.start_load(&report_error); - - for (pugi::xml_node node = doc.first_child(); node; node = node.next_sibling()) { - if (std::strcmp(node.name(), "vpr_constraints") == 0) { - /* If errno is set up to this point, it messes with strtol errno checking. */ - errno = 0; - load_vpr_constraints(node, out, context, &report_error, &offset_debug); - } else { - offset_debug = node.offset_debug(); - report_error(("Invalid root-level element " + std::string(node.name())).c_str()); - } - } - out.finish_load(); +template +inline void load_vpr_constraints_xml(T &out, Context &context, const char * filename, std::istream &is){ + pugi::xml_document doc; + pugi::xml_parse_result result = doc.load(is); + if(!result) { + int line, col; + get_line_number(filename, result.offset, &line, &col); + std::stringstream msg; + msg << "Unable to load XML file '" << filename << "', "; + msg << result.description() << " (line: " << line; + msg << " col: " << col << ")"; out.error_encountered(filename, line, msg.str().c_str()); + } + ptrdiff_t offset_debug = 0; + std::function report_error = [filename, &out, &offset_debug](const char * message) { + int line, col; + get_line_number(filename, offset_debug, &line, &col); + out.error_encountered(filename, line, message); + // If error_encountered didn't throw, throw now to unwind. + throw std::runtime_error(message); + }; + out.start_load(&report_error); + + for(pugi::xml_node node= doc.first_child(); node; node = node.next_sibling()){ + if(std::strcmp(node.name(), "vpr_constraints") == 0){ + /* If errno is set up to this point, it messes with strtol errno checking. */ + errno = 0; + load_vpr_constraints(node, out, context, &report_error, &offset_debug); + } else { + offset_debug = node.offset_debug(); + report_error(("Invalid root-level element " + std::string(node.name())).c_str()); + } + } + out.finish_load(); } /* Write function for the root element. */ -template -inline void write_vpr_constraints_xml(T& in, Context& context, std::ostream& os) { - in.start_write(); - os << "\n"; - write_vpr_constraints(in, os, context); - os << "\n"; - in.finish_write(); +template +inline void write_vpr_constraints_xml(T &in, Context &context, std::ostream &os){ + in.start_write(); + os << "\n"; + write_vpr_constraints(in, os, context); + os << "\n"; + in.finish_write(); } + typedef const uint32_t __attribute__((aligned(1))) triehash_uu32; typedef const uint64_t __attribute__((aligned(1))) triehash_uu64; static_assert(alignof(triehash_uu32) == 1, "Unaligned 32-bit access not found."); static_assert(alignof(triehash_uu64) == 1, "Unaligned 64-bit access not found."); #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ -# define onechar(c, s, l) (((uint64_t)(c)) << (s)) +#define onechar(c, s, l) (((uint64_t)(c)) << (s)) #else -# define onechar(c, s, l) (((uint64_t)(c)) << (l - 8 - s)) +#define onechar(c, s, l) (((uint64_t)(c)) << (l-8-s)) #endif /* Tokens for attribute and node names. */ -enum class atok_t_add_atom { NAME_PATTERN }; -constexpr const char* atok_lookup_t_add_atom[] = {"name_pattern"}; - -enum class atok_t_add_region { SUBTILE, - X_HIGH, - X_LOW, - Y_HIGH, - Y_LOW }; -constexpr const char* atok_lookup_t_add_region[] = {"subtile", "x_high", "x_low", "y_high", "y_low"}; - -enum class gtok_t_partition { ADD_ATOM, - ADD_REGION }; -constexpr const char* gtok_lookup_t_partition[] = {"add_atom", "add_region"}; -enum class atok_t_partition { NAME }; -constexpr const char* atok_lookup_t_partition[] = {"name"}; - -enum class gtok_t_partition_list { PARTITION }; -constexpr const char* gtok_lookup_t_partition_list[] = {"partition"}; - -enum class atok_t_set_global_signal { NAME, - ROUTE_MODEL, - TYPE }; -constexpr const char* atok_lookup_t_set_global_signal[] = {"name", "route_model", "type"}; - -enum class gtok_t_global_route_constraints { SET_GLOBAL_SIGNAL }; -constexpr const char* gtok_lookup_t_global_route_constraints[] = {"set_global_signal"}; -enum class gtok_t_vpr_constraints { PARTITION_LIST, - GLOBAL_ROUTE_CONSTRAINTS }; -constexpr const char* gtok_lookup_t_vpr_constraints[] = {"partition_list", "global_route_constraints"}; -enum class atok_t_vpr_constraints { TOOL_NAME }; -constexpr const char* atok_lookup_t_vpr_constraints[] = {"tool_name"}; +enum class atok_t_add_atom {NAME_PATTERN}; +constexpr const char *atok_lookup_t_add_atom[] = {"name_pattern"}; + + +enum class atok_t_add_region {SUBTILE, X_HIGH, X_LOW, Y_HIGH, Y_LOW}; +constexpr const char *atok_lookup_t_add_region[] = {"subtile", "x_high", "x_low", "y_high", "y_low"}; + +enum class gtok_t_partition {ADD_ATOM, ADD_REGION}; +constexpr const char *gtok_lookup_t_partition[] = {"add_atom", "add_region"}; +enum class atok_t_partition {NAME}; +constexpr const char *atok_lookup_t_partition[] = {"name"}; + +enum class gtok_t_partition_list {PARTITION}; +constexpr const char *gtok_lookup_t_partition_list[] = {"partition"}; + +enum class atok_t_set_global_signal {NAME, ROUTE_MODEL, TYPE}; +constexpr const char *atok_lookup_t_set_global_signal[] = {"name", "route_model", "type"}; + +enum class gtok_t_global_route_constraints {SET_GLOBAL_SIGNAL}; +constexpr const char *gtok_lookup_t_global_route_constraints[] = {"set_global_signal"}; + +enum class atok_t_assignment {NET, PIN}; +constexpr const char *atok_lookup_t_assignment[] = {"net", "pin"}; + +enum class gtok_t_packer_constraints {ASSIGNMENT}; +constexpr const char *gtok_lookup_t_packer_constraints[] = {"assignment"}; +enum class gtok_t_vpr_constraints {PARTITION_LIST, GLOBAL_ROUTE_CONSTRAINTS, PACKER_CONSTRAINTS}; +constexpr const char *gtok_lookup_t_vpr_constraints[] = {"partition_list", "global_route_constraints", "packer_constraints"}; +enum class atok_t_vpr_constraints {TOOL_NAME}; +constexpr const char *atok_lookup_t_vpr_constraints[] = {"tool_name"}; + /* Internal lexers. These convert the PugiXML node names to input tokens. */ -inline atok_t_add_atom lex_attr_t_add_atom(const char* in, const std::function* report_error) { - unsigned int len = strlen(in); - switch (len) { - case 12: - switch (*((triehash_uu64*)&in[0])) { - case onechar('n', 0, 64) | onechar('a', 8, 64) | onechar('m', 16, 64) | onechar('e', 24, 64) | onechar('_', 32, 64) | onechar('p', 40, 64) | onechar('a', 48, 64) | onechar('t', 56, 64): - switch (*((triehash_uu32*)&in[8])) { - case onechar('t', 0, 32) | onechar('e', 8, 32) | onechar('r', 16, 32) | onechar('n', 24, 32): - return atok_t_add_atom::NAME_PATTERN; - break; - default: - break; - } - break; - default: - break; - } - break; - default: - break; - } - noreturn_report(report_error, ("Found unrecognized attribute " + std::string(in) + " of .").c_str()); +inline atok_t_add_atom lex_attr_t_add_atom(const char *in, const std::function * report_error){ + unsigned int len = strlen(in); + switch(len){ + case 12: + switch(*((triehash_uu64*)&in[0])){ + case onechar('n', 0, 64) | onechar('a', 8, 64) | onechar('m', 16, 64) | onechar('e', 24, 64) | onechar('_', 32, 64) | onechar('p', 40, 64) | onechar('a', 48, 64) | onechar('t', 56, 64): + switch(*((triehash_uu32*)&in[8])){ + case onechar('t', 0, 32) | onechar('e', 8, 32) | onechar('r', 16, 32) | onechar('n', 24, 32): + return atok_t_add_atom::NAME_PATTERN; + break; + default: break; + } + break; + default: break; + } + break; + default: break; + } + noreturn_report(report_error, ("Found unrecognized attribute " + std::string(in) + " of .").c_str()); } -inline atok_t_add_region lex_attr_t_add_region(const char* in, const std::function* report_error) { - unsigned int len = strlen(in); - switch (len) { - case 5: - switch (*((triehash_uu32*)&in[0])) { - case onechar('x', 0, 32) | onechar('_', 8, 32) | onechar('l', 16, 32) | onechar('o', 24, 32): - switch (in[4]) { - case onechar('w', 0, 8): - return atok_t_add_region::X_LOW; - break; - default: - break; - } - break; - case onechar('y', 0, 32) | onechar('_', 8, 32) | onechar('l', 16, 32) | onechar('o', 24, 32): - switch (in[4]) { - case onechar('w', 0, 8): - return atok_t_add_region::Y_LOW; - break; - default: - break; - } - break; - default: - break; - } - break; - case 6: - switch (*((triehash_uu32*)&in[0])) { - case onechar('x', 0, 32) | onechar('_', 8, 32) | onechar('h', 16, 32) | onechar('i', 24, 32): - switch (in[4]) { - case onechar('g', 0, 8): - switch (in[5]) { - case onechar('h', 0, 8): - return atok_t_add_region::X_HIGH; - break; - default: - break; - } - break; - default: - break; - } - break; - case onechar('y', 0, 32) | onechar('_', 8, 32) | onechar('h', 16, 32) | onechar('i', 24, 32): - switch (in[4]) { - case onechar('g', 0, 8): - switch (in[5]) { - case onechar('h', 0, 8): - return atok_t_add_region::Y_HIGH; - break; - default: - break; - } - break; - default: - break; - } - break; - default: - break; - } - break; - case 7: - switch (*((triehash_uu32*)&in[0])) { - case onechar('s', 0, 32) | onechar('u', 8, 32) | onechar('b', 16, 32) | onechar('t', 24, 32): - switch (in[4]) { - case onechar('i', 0, 8): - switch (in[5]) { - case onechar('l', 0, 8): - switch (in[6]) { - case onechar('e', 0, 8): - return atok_t_add_region::SUBTILE; - break; - default: - break; - } - break; - default: - break; - } - break; - default: - break; - } - break; - default: - break; - } - break; - default: - break; - } - noreturn_report(report_error, ("Found unrecognized attribute " + std::string(in) + " of .").c_str()); +inline atok_t_add_region lex_attr_t_add_region(const char *in, const std::function * report_error){ + unsigned int len = strlen(in); + switch(len){ + case 5: + switch(*((triehash_uu32*)&in[0])){ + case onechar('x', 0, 32) | onechar('_', 8, 32) | onechar('l', 16, 32) | onechar('o', 24, 32): + switch(in[4]){ + case onechar('w', 0, 8): + return atok_t_add_region::X_LOW; + break; + default: break; + } + break; + case onechar('y', 0, 32) | onechar('_', 8, 32) | onechar('l', 16, 32) | onechar('o', 24, 32): + switch(in[4]){ + case onechar('w', 0, 8): + return atok_t_add_region::Y_LOW; + break; + default: break; + } + break; + default: break; + } + break; + case 6: + switch(*((triehash_uu32*)&in[0])){ + case onechar('x', 0, 32) | onechar('_', 8, 32) | onechar('h', 16, 32) | onechar('i', 24, 32): + switch(in[4]){ + case onechar('g', 0, 8): + switch(in[5]){ + case onechar('h', 0, 8): + return atok_t_add_region::X_HIGH; + break; + default: break; + } + break; + default: break; + } + break; + case onechar('y', 0, 32) | onechar('_', 8, 32) | onechar('h', 16, 32) | onechar('i', 24, 32): + switch(in[4]){ + case onechar('g', 0, 8): + switch(in[5]){ + case onechar('h', 0, 8): + return atok_t_add_region::Y_HIGH; + break; + default: break; + } + break; + default: break; + } + break; + default: break; + } + break; + case 7: + switch(*((triehash_uu32*)&in[0])){ + case onechar('s', 0, 32) | onechar('u', 8, 32) | onechar('b', 16, 32) | onechar('t', 24, 32): + switch(in[4]){ + case onechar('i', 0, 8): + switch(in[5]){ + case onechar('l', 0, 8): + switch(in[6]){ + case onechar('e', 0, 8): + return atok_t_add_region::SUBTILE; + break; + default: break; + } + break; + default: break; + } + break; + default: break; + } + break; + default: break; + } + break; + default: break; + } + noreturn_report(report_error, ("Found unrecognized attribute " + std::string(in) + " of .").c_str()); +} + +inline gtok_t_partition lex_node_t_partition(const char *in, const std::function *report_error){ + unsigned int len = strlen(in); + switch(len){ + case 8: + switch(*((triehash_uu64*)&in[0])){ + case onechar('a', 0, 64) | onechar('d', 8, 64) | onechar('d', 16, 64) | onechar('_', 24, 64) | onechar('a', 32, 64) | onechar('t', 40, 64) | onechar('o', 48, 64) | onechar('m', 56, 64): + return gtok_t_partition::ADD_ATOM; + break; + default: break; + } + break; + case 10: + switch(*((triehash_uu64*)&in[0])){ + case onechar('a', 0, 64) | onechar('d', 8, 64) | onechar('d', 16, 64) | onechar('_', 24, 64) | onechar('r', 32, 64) | onechar('e', 40, 64) | onechar('g', 48, 64) | onechar('i', 56, 64): + switch(in[8]){ + case onechar('o', 0, 8): + switch(in[9]){ + case onechar('n', 0, 8): + return gtok_t_partition::ADD_REGION; + break; + default: break; + } + break; + default: break; + } + break; + default: break; + } + break; + default: break; + } + noreturn_report(report_error, ("Found unrecognized child " + std::string(in) + " of .").c_str()); +} +inline atok_t_partition lex_attr_t_partition(const char *in, const std::function * report_error){ + unsigned int len = strlen(in); + switch(len){ + case 4: + switch(*((triehash_uu32*)&in[0])){ + case onechar('n', 0, 32) | onechar('a', 8, 32) | onechar('m', 16, 32) | onechar('e', 24, 32): + return atok_t_partition::NAME; + break; + default: break; + } + break; + default: break; + } + noreturn_report(report_error, ("Found unrecognized attribute " + std::string(in) + " of .").c_str()); } -inline gtok_t_partition lex_node_t_partition(const char* in, const std::function* report_error) { - unsigned int len = strlen(in); - switch (len) { - case 8: - switch (*((triehash_uu64*)&in[0])) { - case onechar('a', 0, 64) | onechar('d', 8, 64) | onechar('d', 16, 64) | onechar('_', 24, 64) | onechar('a', 32, 64) | onechar('t', 40, 64) | onechar('o', 48, 64) | onechar('m', 56, 64): - return gtok_t_partition::ADD_ATOM; - break; - default: - break; - } - break; - case 10: - switch (*((triehash_uu64*)&in[0])) { - case onechar('a', 0, 64) | onechar('d', 8, 64) | onechar('d', 16, 64) | onechar('_', 24, 64) | onechar('r', 32, 64) | onechar('e', 40, 64) | onechar('g', 48, 64) | onechar('i', 56, 64): - switch (in[8]) { - case onechar('o', 0, 8): - switch (in[9]) { - case onechar('n', 0, 8): - return gtok_t_partition::ADD_REGION; - break; - default: - break; - } - break; - default: - break; - } - break; - default: - break; - } - break; - default: - break; - } - noreturn_report(report_error, ("Found unrecognized child " + std::string(in) + " of .").c_str()); +inline gtok_t_partition_list lex_node_t_partition_list(const char *in, const std::function *report_error){ + unsigned int len = strlen(in); + switch(len){ + case 9: + switch(*((triehash_uu64*)&in[0])){ + case onechar('p', 0, 64) | onechar('a', 8, 64) | onechar('r', 16, 64) | onechar('t', 24, 64) | onechar('i', 32, 64) | onechar('t', 40, 64) | onechar('i', 48, 64) | onechar('o', 56, 64): + switch(in[8]){ + case onechar('n', 0, 8): + return gtok_t_partition_list::PARTITION; + break; + default: break; + } + break; + default: break; + } + break; + default: break; + } + noreturn_report(report_error, ("Found unrecognized child " + std::string(in) + " of .").c_str()); } -inline atok_t_partition lex_attr_t_partition(const char* in, const std::function* report_error) { - unsigned int len = strlen(in); - switch (len) { - case 4: - switch (*((triehash_uu32*)&in[0])) { - case onechar('n', 0, 32) | onechar('a', 8, 32) | onechar('m', 16, 32) | onechar('e', 24, 32): - return atok_t_partition::NAME; - break; - default: - break; - } - break; - default: - break; - } - noreturn_report(report_error, ("Found unrecognized attribute " + std::string(in) + " of .").c_str()); + +inline atok_t_set_global_signal lex_attr_t_set_global_signal(const char *in, const std::function * report_error){ + unsigned int len = strlen(in); + switch(len){ + case 4: + switch(*((triehash_uu32*)&in[0])){ + case onechar('n', 0, 32) | onechar('a', 8, 32) | onechar('m', 16, 32) | onechar('e', 24, 32): + return atok_t_set_global_signal::NAME; + break; + case onechar('t', 0, 32) | onechar('y', 8, 32) | onechar('p', 16, 32) | onechar('e', 24, 32): + return atok_t_set_global_signal::TYPE; + break; + default: break; + } + break; + case 11: + switch(*((triehash_uu64*)&in[0])){ + case onechar('r', 0, 64) | onechar('o', 8, 64) | onechar('u', 16, 64) | onechar('t', 24, 64) | onechar('e', 32, 64) | onechar('_', 40, 64) | onechar('m', 48, 64) | onechar('o', 56, 64): + switch(in[8]){ + case onechar('d', 0, 8): + switch(in[9]){ + case onechar('e', 0, 8): + switch(in[10]){ + case onechar('l', 0, 8): + return atok_t_set_global_signal::ROUTE_MODEL; + break; + default: break; + } + break; + default: break; + } + break; + default: break; + } + break; + default: break; + } + break; + default: break; + } + noreturn_report(report_error, ("Found unrecognized attribute " + std::string(in) + " of .").c_str()); } -inline gtok_t_partition_list lex_node_t_partition_list(const char* in, const std::function* report_error) { - unsigned int len = strlen(in); - switch (len) { - case 9: - switch (*((triehash_uu64*)&in[0])) { - case onechar('p', 0, 64) | onechar('a', 8, 64) | onechar('r', 16, 64) | onechar('t', 24, 64) | onechar('i', 32, 64) | onechar('t', 40, 64) | onechar('i', 48, 64) | onechar('o', 56, 64): - switch (in[8]) { - case onechar('n', 0, 8): - return gtok_t_partition_list::PARTITION; - break; - default: - break; - } - break; - default: - break; - } - break; - default: - break; - } - noreturn_report(report_error, ("Found unrecognized child " + std::string(in) + " of .").c_str()); +inline gtok_t_global_route_constraints lex_node_t_global_route_constraints(const char *in, const std::function *report_error){ + unsigned int len = strlen(in); + switch(len){ + case 17: + switch(*((triehash_uu64*)&in[0])){ + case onechar('s', 0, 64) | onechar('e', 8, 64) | onechar('t', 16, 64) | onechar('_', 24, 64) | onechar('g', 32, 64) | onechar('l', 40, 64) | onechar('o', 48, 64) | onechar('b', 56, 64): + switch(*((triehash_uu64*)&in[8])){ + case onechar('a', 0, 64) | onechar('l', 8, 64) | onechar('_', 16, 64) | onechar('s', 24, 64) | onechar('i', 32, 64) | onechar('g', 40, 64) | onechar('n', 48, 64) | onechar('a', 56, 64): + switch(in[16]){ + case onechar('l', 0, 8): + return gtok_t_global_route_constraints::SET_GLOBAL_SIGNAL; + break; + default: break; + } + break; + default: break; + } + break; + default: break; + } + break; + default: break; + } + noreturn_report(report_error, ("Found unrecognized child " + std::string(in) + " of .").c_str()); } -inline atok_t_set_global_signal lex_attr_t_set_global_signal(const char* in, const std::function* report_error) { - unsigned int len = strlen(in); - switch (len) { - case 4: - switch (*((triehash_uu32*)&in[0])) { - case onechar('n', 0, 32) | onechar('a', 8, 32) | onechar('m', 16, 32) | onechar('e', 24, 32): - return atok_t_set_global_signal::NAME; - break; - case onechar('t', 0, 32) | onechar('y', 8, 32) | onechar('p', 16, 32) | onechar('e', 24, 32): - return atok_t_set_global_signal::TYPE; - break; - default: - break; - } - break; - case 11: - switch (*((triehash_uu64*)&in[0])) { - case onechar('r', 0, 64) | onechar('o', 8, 64) | onechar('u', 16, 64) | onechar('t', 24, 64) | onechar('e', 32, 64) | onechar('_', 40, 64) | onechar('m', 48, 64) | onechar('o', 56, 64): - switch (in[8]) { - case onechar('d', 0, 8): - switch (in[9]) { - case onechar('e', 0, 8): - switch (in[10]) { - case onechar('l', 0, 8): - return atok_t_set_global_signal::ROUTE_MODEL; - break; - default: - break; - } - break; - default: - break; - } - break; - default: - break; - } - break; - default: - break; - } - break; - default: - break; - } - noreturn_report(report_error, ("Found unrecognized attribute " + std::string(in) + " of .").c_str()); +inline atok_t_assignment lex_attr_t_assignment(const char *in, const std::function * report_error){ + unsigned int len = strlen(in); + switch(len){ + case 3: + switch(in[0]){ + case onechar('n', 0, 8): + switch(in[1]){ + case onechar('e', 0, 8): + switch(in[2]){ + case onechar('t', 0, 8): + return atok_t_assignment::NET; + break; + default: break; + } + break; + default: break; + } + break; + case onechar('p', 0, 8): + switch(in[1]){ + case onechar('i', 0, 8): + switch(in[2]){ + case onechar('n', 0, 8): + return atok_t_assignment::PIN; + break; + default: break; + } + break; + default: break; + } + break; + default: break; + } + break; + default: break; + } + noreturn_report(report_error, ("Found unrecognized attribute " + std::string(in) + " of .").c_str()); } -inline gtok_t_global_route_constraints lex_node_t_global_route_constraints(const char* in, const std::function* report_error) { - unsigned int len = strlen(in); - switch (len) { - case 17: - switch (*((triehash_uu64*)&in[0])) { - case onechar('s', 0, 64) | onechar('e', 8, 64) | onechar('t', 16, 64) | onechar('_', 24, 64) | onechar('g', 32, 64) | onechar('l', 40, 64) | onechar('o', 48, 64) | onechar('b', 56, 64): - switch (*((triehash_uu64*)&in[8])) { - case onechar('a', 0, 64) | onechar('l', 8, 64) | onechar('_', 16, 64) | onechar('s', 24, 64) | onechar('i', 32, 64) | onechar('g', 40, 64) | onechar('n', 48, 64) | onechar('a', 56, 64): - switch (in[16]) { - case onechar('l', 0, 8): - return gtok_t_global_route_constraints::SET_GLOBAL_SIGNAL; - break; - default: - break; - } - break; - default: - break; - } - break; - default: - break; - } - break; - default: - break; - } - noreturn_report(report_error, ("Found unrecognized child " + std::string(in) + " of .").c_str()); +inline gtok_t_packer_constraints lex_node_t_packer_constraints(const char *in, const std::function *report_error){ + unsigned int len = strlen(in); + switch(len){ + case 10: + switch(*((triehash_uu64*)&in[0])){ + case onechar('a', 0, 64) | onechar('s', 8, 64) | onechar('s', 16, 64) | onechar('i', 24, 64) | onechar('g', 32, 64) | onechar('n', 40, 64) | onechar('m', 48, 64) | onechar('e', 56, 64): + switch(in[8]){ + case onechar('n', 0, 8): + switch(in[9]){ + case onechar('t', 0, 8): + return gtok_t_packer_constraints::ASSIGNMENT; + break; + default: break; + } + break; + default: break; + } + break; + default: break; + } + break; + default: break; + } + noreturn_report(report_error, ("Found unrecognized child " + std::string(in) + " of .").c_str()); } -inline gtok_t_vpr_constraints lex_node_t_vpr_constraints(const char* in, const std::function* report_error) { - unsigned int len = strlen(in); - switch (len) { - case 14: - switch (*((triehash_uu64*)&in[0])) { - case onechar('p', 0, 64) | onechar('a', 8, 64) | onechar('r', 16, 64) | onechar('t', 24, 64) | onechar('i', 32, 64) | onechar('t', 40, 64) | onechar('i', 48, 64) | onechar('o', 56, 64): - switch (*((triehash_uu32*)&in[8])) { - case onechar('n', 0, 32) | onechar('_', 8, 32) | onechar('l', 16, 32) | onechar('i', 24, 32): - switch (in[12]) { - case onechar('s', 0, 8): - switch (in[13]) { - case onechar('t', 0, 8): - return gtok_t_vpr_constraints::PARTITION_LIST; - break; - default: - break; - } - break; - default: - break; - } - break; - default: - break; - } - break; - default: - break; - } - break; - case 24: - switch (*((triehash_uu64*)&in[0])) { - case onechar('g', 0, 64) | onechar('l', 8, 64) | onechar('o', 16, 64) | onechar('b', 24, 64) | onechar('a', 32, 64) | onechar('l', 40, 64) | onechar('_', 48, 64) | onechar('r', 56, 64): - switch (*((triehash_uu64*)&in[8])) { - case onechar('o', 0, 64) | onechar('u', 8, 64) | onechar('t', 16, 64) | onechar('e', 24, 64) | onechar('_', 32, 64) | onechar('c', 40, 64) | onechar('o', 48, 64) | onechar('n', 56, 64): - switch (*((triehash_uu64*)&in[16])) { - case onechar('s', 0, 64) | onechar('t', 8, 64) | onechar('r', 16, 64) | onechar('a', 24, 64) | onechar('i', 32, 64) | onechar('n', 40, 64) | onechar('t', 48, 64) | onechar('s', 56, 64): - return gtok_t_vpr_constraints::GLOBAL_ROUTE_CONSTRAINTS; - break; - default: - break; - } - break; - default: - break; - } - break; - default: - break; - } - break; - default: - break; - } - noreturn_report(report_error, ("Found unrecognized child " + std::string(in) + " of .").c_str()); +inline gtok_t_vpr_constraints lex_node_t_vpr_constraints(const char *in, const std::function *report_error){ + unsigned int len = strlen(in); + switch(len){ + case 14: + switch(*((triehash_uu64*)&in[0])){ + case onechar('p', 0, 64) | onechar('a', 8, 64) | onechar('r', 16, 64) | onechar('t', 24, 64) | onechar('i', 32, 64) | onechar('t', 40, 64) | onechar('i', 48, 64) | onechar('o', 56, 64): + switch(*((triehash_uu32*)&in[8])){ + case onechar('n', 0, 32) | onechar('_', 8, 32) | onechar('l', 16, 32) | onechar('i', 24, 32): + switch(in[12]){ + case onechar('s', 0, 8): + switch(in[13]){ + case onechar('t', 0, 8): + return gtok_t_vpr_constraints::PARTITION_LIST; + break; + default: break; + } + break; + default: break; + } + break; + default: break; + } + break; + default: break; + } + break; + case 18: + switch(*((triehash_uu64*)&in[0])){ + case onechar('p', 0, 64) | onechar('a', 8, 64) | onechar('c', 16, 64) | onechar('k', 24, 64) | onechar('e', 32, 64) | onechar('r', 40, 64) | onechar('_', 48, 64) | onechar('c', 56, 64): + switch(*((triehash_uu64*)&in[8])){ + case onechar('o', 0, 64) | onechar('n', 8, 64) | onechar('s', 16, 64) | onechar('t', 24, 64) | onechar('r', 32, 64) | onechar('a', 40, 64) | onechar('i', 48, 64) | onechar('n', 56, 64): + switch(in[16]){ + case onechar('t', 0, 8): + switch(in[17]){ + case onechar('s', 0, 8): + return gtok_t_vpr_constraints::PACKER_CONSTRAINTS; + break; + default: break; + } + break; + default: break; + } + break; + default: break; + } + break; + default: break; + } + break; + case 24: + switch(*((triehash_uu64*)&in[0])){ + case onechar('g', 0, 64) | onechar('l', 8, 64) | onechar('o', 16, 64) | onechar('b', 24, 64) | onechar('a', 32, 64) | onechar('l', 40, 64) | onechar('_', 48, 64) | onechar('r', 56, 64): + switch(*((triehash_uu64*)&in[8])){ + case onechar('o', 0, 64) | onechar('u', 8, 64) | onechar('t', 16, 64) | onechar('e', 24, 64) | onechar('_', 32, 64) | onechar('c', 40, 64) | onechar('o', 48, 64) | onechar('n', 56, 64): + switch(*((triehash_uu64*)&in[16])){ + case onechar('s', 0, 64) | onechar('t', 8, 64) | onechar('r', 16, 64) | onechar('a', 24, 64) | onechar('i', 32, 64) | onechar('n', 40, 64) | onechar('t', 48, 64) | onechar('s', 56, 64): + return gtok_t_vpr_constraints::GLOBAL_ROUTE_CONSTRAINTS; + break; + default: break; + } + break; + default: break; + } + break; + default: break; + } + break; + default: break; + } + noreturn_report(report_error, ("Found unrecognized child " + std::string(in) + " of .").c_str()); } -inline atok_t_vpr_constraints lex_attr_t_vpr_constraints(const char* in, const std::function* report_error) { - unsigned int len = strlen(in); - switch (len) { - case 9: - switch (*((triehash_uu64*)&in[0])) { - case onechar('t', 0, 64) | onechar('o', 8, 64) | onechar('o', 16, 64) | onechar('l', 24, 64) | onechar('_', 32, 64) | onechar('n', 40, 64) | onechar('a', 48, 64) | onechar('m', 56, 64): - switch (in[8]) { - case onechar('e', 0, 8): - return atok_t_vpr_constraints::TOOL_NAME; - break; - default: - break; - } - break; - default: - break; - } - break; - default: - break; - } - noreturn_report(report_error, ("Found unrecognized attribute " + std::string(in) + " of .").c_str()); +inline atok_t_vpr_constraints lex_attr_t_vpr_constraints(const char *in, const std::function * report_error){ + unsigned int len = strlen(in); + switch(len){ + case 9: + switch(*((triehash_uu64*)&in[0])){ + case onechar('t', 0, 64) | onechar('o', 8, 64) | onechar('o', 16, 64) | onechar('l', 24, 64) | onechar('_', 32, 64) | onechar('n', 40, 64) | onechar('a', 48, 64) | onechar('m', 56, 64): + switch(in[8]){ + case onechar('e', 0, 8): + return atok_t_vpr_constraints::TOOL_NAME; + break; + default: break; + } + break; + default: break; + } + break; + default: break; + } + noreturn_report(report_error, ("Found unrecognized attribute " + std::string(in) + " of .").c_str()); } /** * Internal error function for xs:choice and xs:sequence validators. */ -[[noreturn]] inline void dfa_error(const char* wrong, const int* states, const char* const* lookup, int len, const std::function* report_error); +[[noreturn]] inline void dfa_error(const char *wrong, const int *states, const char * const *lookup, int len, const std::function * report_error); /** * Internal error function for attribute validators. */ template -[[noreturn]] inline void attr_error(std::bitset astate, const char* const* lookup, const std::function* report_error); +[[noreturn]] inline void attr_error(std::bitset astate, const char * const *lookup, const std::function * report_error); + /* Internal loading functions, which validate and load a PugiXML DOM tree into memory. */ -inline int load_int(const char* in, const std::function* report_error) { - int out; - out = std::strtol(in, NULL, 10); - if (errno != 0) - noreturn_report(report_error, ("Invalid value `" + std::string(in) + "` when loading into a int.").c_str()); - return out; +inline int load_int(const char *in, const std::function * report_error){ + int out; + out = std::strtol(in, NULL, 10); + if(errno != 0) + noreturn_report(report_error, ("Invalid value `" + std::string(in) + "` when loading into a int.").c_str()); + return out; } -inline void load_add_region_required_attributes(const pugi::xml_node& root, int* x_high, int* x_low, int* y_high, int* y_low, const std::function* report_error) { - std::bitset<5> astate = 0; - for (pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()) { - atok_t_add_region in = lex_attr_t_add_region(attr.name(), report_error); - if (astate[(int)in] == 0) - astate[(int)in] = 1; - else - noreturn_report(report_error, ("Duplicate attribute " + std::string(attr.name()) + " in .").c_str()); - switch (in) { - case atok_t_add_region::SUBTILE: - /* Attribute subtile set after element init */ - break; - case atok_t_add_region::X_HIGH: - *x_high = load_int(attr.value(), report_error); - break; - case atok_t_add_region::X_LOW: - *x_low = load_int(attr.value(), report_error); - break; - case atok_t_add_region::Y_HIGH: - *y_high = load_int(attr.value(), report_error); - break; - case atok_t_add_region::Y_LOW: - *y_low = load_int(attr.value(), report_error); - break; - default: - break; /* Not possible. */ - } - } - std::bitset<5> test_astate = astate | std::bitset<5>(0b00001); - if (!test_astate.all()) attr_error(test_astate, atok_lookup_t_add_region, report_error); +inline void load_add_region_required_attributes(const pugi::xml_node &root, int * x_high, int * x_low, int * y_high, int * y_low, const std::function * report_error){ + std::bitset<5> astate = 0; + for(pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()){ + atok_t_add_region in = lex_attr_t_add_region(attr.name(), report_error); + if(astate[(int)in] == 0) astate[(int)in] = 1; + else noreturn_report(report_error, ("Duplicate attribute " + std::string(attr.name()) + " in .").c_str()); + switch(in){ + case atok_t_add_region::SUBTILE: + /* Attribute subtile set after element init */ + break; + case atok_t_add_region::X_HIGH: + *x_high = load_int(attr.value(), report_error); + break; + case atok_t_add_region::X_LOW: + *x_low = load_int(attr.value(), report_error); + break; + case atok_t_add_region::Y_HIGH: + *y_high = load_int(attr.value(), report_error); + break; + case atok_t_add_region::Y_LOW: + *y_low = load_int(attr.value(), report_error); + break; + default: break; /* Not possible. */ + } + } + std::bitset<5> test_astate = astate | std::bitset<5>(0b00001); + if(!test_astate.all()) attr_error(test_astate, atok_lookup_t_add_region, report_error); } template -inline void load_add_atom(const pugi::xml_node& root, T& out, Context& context, const std::function* report_error, ptrdiff_t* offset_debug) { - (void)root; - (void)out; - (void)context; - (void)report_error; - // Update current file offset in case an error is encountered. - *offset_debug = root.offset_debug(); - - for (pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()) { - atok_t_add_atom in = lex_attr_t_add_atom(attr.name(), report_error); - switch (in) { - case atok_t_add_atom::NAME_PATTERN: - out.set_add_atom_name_pattern(attr.value(), context); - break; - default: - break; /* Not possible. */ - } - } - - if (root.first_child().type() == pugi::node_element) - noreturn_report(report_error, "Unexpected child element in ."); +inline void load_add_atom(const pugi::xml_node &root, T &out, Context &context, const std::function *report_error, ptrdiff_t *offset_debug){ + (void)root; + (void)out; + (void)context; + (void)report_error; + // Update current file offset in case an error is encountered. + *offset_debug = root.offset_debug(); + + for(pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()){ + atok_t_add_atom in = lex_attr_t_add_atom(attr.name(), report_error); + switch(in){ + case atok_t_add_atom::NAME_PATTERN: + out.set_add_atom_name_pattern(attr.value(), context); + break; + default: break; /* Not possible. */ + } + } + + if(root.first_child().type() == pugi::node_element) + noreturn_report(report_error, "Unexpected child element in ."); + } template -inline void load_add_region(const pugi::xml_node& root, T& out, Context& context, const std::function* report_error, ptrdiff_t* offset_debug) { - (void)root; - (void)out; - (void)context; - (void)report_error; - // Update current file offset in case an error is encountered. - *offset_debug = root.offset_debug(); - - for (pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()) { - atok_t_add_region in = lex_attr_t_add_region(attr.name(), report_error); - switch (in) { - case atok_t_add_region::SUBTILE: - out.set_add_region_subtile(load_int(attr.value(), report_error), context); - break; - case atok_t_add_region::X_HIGH: - /* Attribute x_high is already set */ - break; - case atok_t_add_region::X_LOW: - /* Attribute x_low is already set */ - break; - case atok_t_add_region::Y_HIGH: - /* Attribute y_high is already set */ - break; - case atok_t_add_region::Y_LOW: - /* Attribute y_low is already set */ - break; - default: - break; /* Not possible. */ - } - } - - if (root.first_child().type() == pugi::node_element) - noreturn_report(report_error, "Unexpected child element in ."); +inline void load_add_region(const pugi::xml_node &root, T &out, Context &context, const std::function *report_error, ptrdiff_t *offset_debug){ + (void)root; + (void)out; + (void)context; + (void)report_error; + // Update current file offset in case an error is encountered. + *offset_debug = root.offset_debug(); + + for(pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()){ + atok_t_add_region in = lex_attr_t_add_region(attr.name(), report_error); + switch(in){ + case atok_t_add_region::SUBTILE: + out.set_add_region_subtile(load_int(attr.value(), report_error), context); + break; + case atok_t_add_region::X_HIGH: + /* Attribute x_high is already set */ + break; + case atok_t_add_region::X_LOW: + /* Attribute x_low is already set */ + break; + case atok_t_add_region::Y_HIGH: + /* Attribute y_high is already set */ + break; + case atok_t_add_region::Y_LOW: + /* Attribute y_low is already set */ + break; + default: break; /* Not possible. */ + } + } + + if(root.first_child().type() == pugi::node_element) + noreturn_report(report_error, "Unexpected child element in ."); + } constexpr int NUM_T_PARTITION_STATES = 2; constexpr const int NUM_T_PARTITION_INPUTS = 2; constexpr int gstate_t_partition[NUM_T_PARTITION_STATES][NUM_T_PARTITION_INPUTS] = { - {0, 0}, - {0, 0}, + {0, 0}, + {0, 0}, }; template -inline void load_partition(const pugi::xml_node& root, T& out, Context& context, const std::function* report_error, ptrdiff_t* offset_debug) { - (void)root; - (void)out; - (void)context; - (void)report_error; - // Update current file offset in case an error is encountered. - *offset_debug = root.offset_debug(); - - for (pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()) { - atok_t_partition in = lex_attr_t_partition(attr.name(), report_error); - switch (in) { - case atok_t_partition::NAME: - out.set_partition_name(attr.value(), context); - break; - default: - break; /* Not possible. */ - } - } - - // Preallocate arrays by counting child nodes (if any) - size_t add_atom_count = 0; - size_t add_region_count = 0; - { - int next, state = 1; - for (pugi::xml_node node = root.first_child(); node; node = node.next_sibling()) { - *offset_debug = node.offset_debug(); - gtok_t_partition in = lex_node_t_partition(node.name(), report_error); - next = gstate_t_partition[state][(int)in]; - if (next == -1) - dfa_error(gtok_lookup_t_partition[(int)in], gstate_t_partition[state], gtok_lookup_t_partition, 2, report_error); - state = next; - switch (in) { - case gtok_t_partition::ADD_ATOM: - add_atom_count += 1; - break; - case gtok_t_partition::ADD_REGION: - add_region_count += 1; - break; - default: - break; /* Not possible. */ - } - } - - out.preallocate_partition_add_atom(context, add_atom_count); - out.preallocate_partition_add_region(context, add_region_count); - } - int next, state = 1; - for (pugi::xml_node node = root.first_child(); node; node = node.next_sibling()) { - *offset_debug = node.offset_debug(); - gtok_t_partition in = lex_node_t_partition(node.name(), report_error); - next = gstate_t_partition[state][(int)in]; - if (next == -1) - dfa_error(gtok_lookup_t_partition[(int)in], gstate_t_partition[state], gtok_lookup_t_partition, 2, report_error); - state = next; - switch (in) { - case gtok_t_partition::ADD_ATOM: { - auto child_context = out.add_partition_add_atom(context); - load_add_atom(node, out, child_context, report_error, offset_debug); - out.finish_partition_add_atom(child_context); - } break; - case gtok_t_partition::ADD_REGION: { - int add_region_x_high; - memset(&add_region_x_high, 0, sizeof(add_region_x_high)); - int add_region_x_low; - memset(&add_region_x_low, 0, sizeof(add_region_x_low)); - int add_region_y_high; - memset(&add_region_y_high, 0, sizeof(add_region_y_high)); - int add_region_y_low; - memset(&add_region_y_low, 0, sizeof(add_region_y_low)); - load_add_region_required_attributes(node, &add_region_x_high, &add_region_x_low, &add_region_y_high, &add_region_y_low, report_error); - auto child_context = out.add_partition_add_region(context, add_region_x_high, add_region_x_low, add_region_y_high, add_region_y_low); - load_add_region(node, out, child_context, report_error, offset_debug); - out.finish_partition_add_region(child_context); - } break; - default: - break; /* Not possible. */ - } - } - if (state != 0) dfa_error("end of input", gstate_t_partition[state], gtok_lookup_t_partition, 2, report_error); +inline void load_partition(const pugi::xml_node &root, T &out, Context &context, const std::function *report_error, ptrdiff_t *offset_debug){ + (void)root; + (void)out; + (void)context; + (void)report_error; + // Update current file offset in case an error is encountered. + *offset_debug = root.offset_debug(); + + for(pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()){ + atok_t_partition in = lex_attr_t_partition(attr.name(), report_error); + switch(in){ + case atok_t_partition::NAME: + out.set_partition_name(attr.value(), context); + break; + default: break; /* Not possible. */ + } + } + + // Preallocate arrays by counting child nodes (if any) + size_t add_atom_count = 0; + size_t add_region_count = 0; + { + int next, state=1; + for(pugi::xml_node node = root.first_child(); node; node = node.next_sibling()) { + *offset_debug = node.offset_debug(); + gtok_t_partition in = lex_node_t_partition(node.name(), report_error); + next = gstate_t_partition[state][(int)in]; + if(next == -1) + dfa_error(gtok_lookup_t_partition[(int)in], gstate_t_partition[state], gtok_lookup_t_partition, 2, report_error); + state = next; + switch(in) { + case gtok_t_partition::ADD_ATOM: + add_atom_count += 1; + break; + case gtok_t_partition::ADD_REGION: + add_region_count += 1; + break; + default: break; /* Not possible. */ + } + } + + out.preallocate_partition_add_atom(context, add_atom_count); + out.preallocate_partition_add_region(context, add_region_count); + } + int next, state=1; + for(pugi::xml_node node = root.first_child(); node; node = node.next_sibling()){ + *offset_debug = node.offset_debug(); + gtok_t_partition in = lex_node_t_partition(node.name(), report_error); + next = gstate_t_partition[state][(int)in]; + if(next == -1) + dfa_error(gtok_lookup_t_partition[(int)in], gstate_t_partition[state], gtok_lookup_t_partition, 2, report_error); + state = next; + switch(in){ + case gtok_t_partition::ADD_ATOM: + { + auto child_context = out.add_partition_add_atom(context); + load_add_atom(node, out, child_context, report_error, offset_debug); + out.finish_partition_add_atom(child_context); + } + break; + case gtok_t_partition::ADD_REGION: + { + int add_region_x_high; + memset(&add_region_x_high, 0, sizeof(add_region_x_high)); + int add_region_x_low; + memset(&add_region_x_low, 0, sizeof(add_region_x_low)); + int add_region_y_high; + memset(&add_region_y_high, 0, sizeof(add_region_y_high)); + int add_region_y_low; + memset(&add_region_y_low, 0, sizeof(add_region_y_low)); + load_add_region_required_attributes(node, &add_region_x_high, &add_region_x_low, &add_region_y_high, &add_region_y_low, report_error); + auto child_context = out.add_partition_add_region(context, add_region_x_high, add_region_x_low, add_region_y_high, add_region_y_low); + load_add_region(node, out, child_context, report_error, offset_debug); + out.finish_partition_add_region(child_context); + } + break; + default: break; /* Not possible. */ + } + } + if(state != 0) dfa_error("end of input", gstate_t_partition[state], gtok_lookup_t_partition, 2, report_error); + } constexpr int NUM_T_PARTITION_LIST_STATES = 2; constexpr const int NUM_T_PARTITION_LIST_INPUTS = 1; constexpr int gstate_t_partition_list[NUM_T_PARTITION_LIST_STATES][NUM_T_PARTITION_LIST_INPUTS] = { - {0}, - {0}, + {0}, + {0}, }; template -inline void load_partition_list(const pugi::xml_node& root, T& out, Context& context, const std::function* report_error, ptrdiff_t* offset_debug) { - (void)root; - (void)out; - (void)context; - (void)report_error; - // Update current file offset in case an error is encountered. - *offset_debug = root.offset_debug(); - - if (root.first_attribute()) - noreturn_report(report_error, "Unexpected attribute in ."); - - // Preallocate arrays by counting child nodes (if any) - size_t partition_count = 0; - { - int next, state = 1; - for (pugi::xml_node node = root.first_child(); node; node = node.next_sibling()) { - *offset_debug = node.offset_debug(); - gtok_t_partition_list in = lex_node_t_partition_list(node.name(), report_error); - next = gstate_t_partition_list[state][(int)in]; - if (next == -1) - dfa_error(gtok_lookup_t_partition_list[(int)in], gstate_t_partition_list[state], gtok_lookup_t_partition_list, 1, report_error); - state = next; - switch (in) { - case gtok_t_partition_list::PARTITION: - partition_count += 1; - break; - default: - break; /* Not possible. */ - } - } - - out.preallocate_partition_list_partition(context, partition_count); - } - int next, state = 1; - for (pugi::xml_node node = root.first_child(); node; node = node.next_sibling()) { - *offset_debug = node.offset_debug(); - gtok_t_partition_list in = lex_node_t_partition_list(node.name(), report_error); - next = gstate_t_partition_list[state][(int)in]; - if (next == -1) - dfa_error(gtok_lookup_t_partition_list[(int)in], gstate_t_partition_list[state], gtok_lookup_t_partition_list, 1, report_error); - state = next; - switch (in) { - case gtok_t_partition_list::PARTITION: { - auto child_context = out.add_partition_list_partition(context); - load_partition(node, out, child_context, report_error, offset_debug); - out.finish_partition_list_partition(child_context); - } break; - default: - break; /* Not possible. */ - } - } - if (state != 0) dfa_error("end of input", gstate_t_partition_list[state], gtok_lookup_t_partition_list, 1, report_error); +inline void load_partition_list(const pugi::xml_node &root, T &out, Context &context, const std::function *report_error, ptrdiff_t *offset_debug){ + (void)root; + (void)out; + (void)context; + (void)report_error; + // Update current file offset in case an error is encountered. + *offset_debug = root.offset_debug(); + + if(root.first_attribute()) + noreturn_report(report_error, "Unexpected attribute in ."); + + // Preallocate arrays by counting child nodes (if any) + size_t partition_count = 0; + { + int next, state=1; + for(pugi::xml_node node = root.first_child(); node; node = node.next_sibling()) { + *offset_debug = node.offset_debug(); + gtok_t_partition_list in = lex_node_t_partition_list(node.name(), report_error); + next = gstate_t_partition_list[state][(int)in]; + if(next == -1) + dfa_error(gtok_lookup_t_partition_list[(int)in], gstate_t_partition_list[state], gtok_lookup_t_partition_list, 1, report_error); + state = next; + switch(in) { + case gtok_t_partition_list::PARTITION: + partition_count += 1; + break; + default: break; /* Not possible. */ + } + } + + out.preallocate_partition_list_partition(context, partition_count); + } + int next, state=1; + for(pugi::xml_node node = root.first_child(); node; node = node.next_sibling()){ + *offset_debug = node.offset_debug(); + gtok_t_partition_list in = lex_node_t_partition_list(node.name(), report_error); + next = gstate_t_partition_list[state][(int)in]; + if(next == -1) + dfa_error(gtok_lookup_t_partition_list[(int)in], gstate_t_partition_list[state], gtok_lookup_t_partition_list, 1, report_error); + state = next; + switch(in){ + case gtok_t_partition_list::PARTITION: + { + auto child_context = out.add_partition_list_partition(context); + load_partition(node, out, child_context, report_error, offset_debug); + out.finish_partition_list_partition(child_context); + } + break; + default: break; /* Not possible. */ + } + } + if(state != 0) dfa_error("end of input", gstate_t_partition_list[state], gtok_lookup_t_partition_list, 1, report_error); + } template -inline void load_set_global_signal(const pugi::xml_node& root, T& out, Context& context, const std::function* report_error, ptrdiff_t* offset_debug) { - (void)root; - (void)out; - (void)context; - (void)report_error; - // Update current file offset in case an error is encountered. - *offset_debug = root.offset_debug(); - - for (pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()) { - atok_t_set_global_signal in = lex_attr_t_set_global_signal(attr.name(), report_error); - switch (in) { - case atok_t_set_global_signal::NAME: - out.set_set_global_signal_name(attr.value(), context); - break; - case atok_t_set_global_signal::ROUTE_MODEL: - out.set_set_global_signal_route_model(attr.value(), context); - break; - case atok_t_set_global_signal::TYPE: - out.set_set_global_signal_type(attr.value(), context); - break; - default: - break; /* Not possible. */ - } - } - - if (root.first_child().type() == pugi::node_element) - noreturn_report(report_error, "Unexpected child element in ."); +inline void load_set_global_signal(const pugi::xml_node &root, T &out, Context &context, const std::function *report_error, ptrdiff_t *offset_debug){ + (void)root; + (void)out; + (void)context; + (void)report_error; + // Update current file offset in case an error is encountered. + *offset_debug = root.offset_debug(); + + for(pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()){ + atok_t_set_global_signal in = lex_attr_t_set_global_signal(attr.name(), report_error); + switch(in){ + case atok_t_set_global_signal::NAME: + out.set_set_global_signal_name(attr.value(), context); + break; + case atok_t_set_global_signal::ROUTE_MODEL: + out.set_set_global_signal_route_model(attr.value(), context); + break; + case atok_t_set_global_signal::TYPE: + out.set_set_global_signal_type(attr.value(), context); + break; + default: break; /* Not possible. */ + } + } + + if(root.first_child().type() == pugi::node_element) + noreturn_report(report_error, "Unexpected child element in ."); + } constexpr int NUM_T_GLOBAL_ROUTE_CONSTRAINTS_STATES = 2; constexpr const int NUM_T_GLOBAL_ROUTE_CONSTRAINTS_INPUTS = 1; constexpr int gstate_t_global_route_constraints[NUM_T_GLOBAL_ROUTE_CONSTRAINTS_STATES][NUM_T_GLOBAL_ROUTE_CONSTRAINTS_INPUTS] = { - {0}, - {0}, + {0}, + {0}, }; template -inline void load_global_route_constraints(const pugi::xml_node& root, T& out, Context& context, const std::function* report_error, ptrdiff_t* offset_debug) { - (void)root; - (void)out; - (void)context; - (void)report_error; - // Update current file offset in case an error is encountered. - *offset_debug = root.offset_debug(); - - if (root.first_attribute()) - noreturn_report(report_error, "Unexpected attribute in ."); - - // Preallocate arrays by counting child nodes (if any) - size_t set_global_signal_count = 0; - { - int next, state = 1; - for (pugi::xml_node node = root.first_child(); node; node = node.next_sibling()) { - *offset_debug = node.offset_debug(); - gtok_t_global_route_constraints in = lex_node_t_global_route_constraints(node.name(), report_error); - next = gstate_t_global_route_constraints[state][(int)in]; - if (next == -1) - dfa_error(gtok_lookup_t_global_route_constraints[(int)in], gstate_t_global_route_constraints[state], gtok_lookup_t_global_route_constraints, 1, report_error); - state = next; - switch (in) { - case gtok_t_global_route_constraints::SET_GLOBAL_SIGNAL: - set_global_signal_count += 1; - break; - default: - break; /* Not possible. */ - } - } - - out.preallocate_global_route_constraints_set_global_signal(context, set_global_signal_count); - } - int next, state = 1; - for (pugi::xml_node node = root.first_child(); node; node = node.next_sibling()) { - *offset_debug = node.offset_debug(); - gtok_t_global_route_constraints in = lex_node_t_global_route_constraints(node.name(), report_error); - next = gstate_t_global_route_constraints[state][(int)in]; - if (next == -1) - dfa_error(gtok_lookup_t_global_route_constraints[(int)in], gstate_t_global_route_constraints[state], gtok_lookup_t_global_route_constraints, 1, report_error); - state = next; - switch (in) { - case gtok_t_global_route_constraints::SET_GLOBAL_SIGNAL: { - auto child_context = out.add_global_route_constraints_set_global_signal(context); - load_set_global_signal(node, out, child_context, report_error, offset_debug); - out.finish_global_route_constraints_set_global_signal(child_context); - } break; - default: - break; /* Not possible. */ - } - } - if (state != 0) dfa_error("end of input", gstate_t_global_route_constraints[state], gtok_lookup_t_global_route_constraints, 1, report_error); +inline void load_global_route_constraints(const pugi::xml_node &root, T &out, Context &context, const std::function *report_error, ptrdiff_t *offset_debug){ + (void)root; + (void)out; + (void)context; + (void)report_error; + // Update current file offset in case an error is encountered. + *offset_debug = root.offset_debug(); + + if(root.first_attribute()) + noreturn_report(report_error, "Unexpected attribute in ."); + + // Preallocate arrays by counting child nodes (if any) + size_t set_global_signal_count = 0; + { + int next, state=1; + for(pugi::xml_node node = root.first_child(); node; node = node.next_sibling()) { + *offset_debug = node.offset_debug(); + gtok_t_global_route_constraints in = lex_node_t_global_route_constraints(node.name(), report_error); + next = gstate_t_global_route_constraints[state][(int)in]; + if(next == -1) + dfa_error(gtok_lookup_t_global_route_constraints[(int)in], gstate_t_global_route_constraints[state], gtok_lookup_t_global_route_constraints, 1, report_error); + state = next; + switch(in) { + case gtok_t_global_route_constraints::SET_GLOBAL_SIGNAL: + set_global_signal_count += 1; + break; + default: break; /* Not possible. */ + } + } + + out.preallocate_global_route_constraints_set_global_signal(context, set_global_signal_count); + } + int next, state=1; + for(pugi::xml_node node = root.first_child(); node; node = node.next_sibling()){ + *offset_debug = node.offset_debug(); + gtok_t_global_route_constraints in = lex_node_t_global_route_constraints(node.name(), report_error); + next = gstate_t_global_route_constraints[state][(int)in]; + if(next == -1) + dfa_error(gtok_lookup_t_global_route_constraints[(int)in], gstate_t_global_route_constraints[state], gtok_lookup_t_global_route_constraints, 1, report_error); + state = next; + switch(in){ + case gtok_t_global_route_constraints::SET_GLOBAL_SIGNAL: + { + auto child_context = out.add_global_route_constraints_set_global_signal(context); + load_set_global_signal(node, out, child_context, report_error, offset_debug); + out.finish_global_route_constraints_set_global_signal(child_context); + } + break; + default: break; /* Not possible. */ + } + } + if(state != 0) dfa_error("end of input", gstate_t_global_route_constraints[state], gtok_lookup_t_global_route_constraints, 1, report_error); + +} + +template +inline void load_assignment(const pugi::xml_node &root, T &out, Context &context, const std::function *report_error, ptrdiff_t *offset_debug){ + (void)root; + (void)out; + (void)context; + (void)report_error; + // Update current file offset in case an error is encountered. + *offset_debug = root.offset_debug(); + + for(pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()){ + atok_t_assignment in = lex_attr_t_assignment(attr.name(), report_error); + switch(in){ + case atok_t_assignment::NET: + out.set_assignment_net(attr.value(), context); + break; + case atok_t_assignment::PIN: + out.set_assignment_pin(attr.value(), context); + break; + default: break; /* Not possible. */ + } + } + + if(root.first_child().type() == pugi::node_element) + noreturn_report(report_error, "Unexpected child element in ."); + +} + +constexpr int NUM_T_PACKER_CONSTRAINTS_STATES = 2; +constexpr const int NUM_T_PACKER_CONSTRAINTS_INPUTS = 1; +constexpr int gstate_t_packer_constraints[NUM_T_PACKER_CONSTRAINTS_STATES][NUM_T_PACKER_CONSTRAINTS_INPUTS] = { + {0}, + {0}, +}; +template +inline void load_packer_constraints(const pugi::xml_node &root, T &out, Context &context, const std::function *report_error, ptrdiff_t *offset_debug){ + (void)root; + (void)out; + (void)context; + (void)report_error; + // Update current file offset in case an error is encountered. + *offset_debug = root.offset_debug(); + + if(root.first_attribute()) + noreturn_report(report_error, "Unexpected attribute in ."); + + // Preallocate arrays by counting child nodes (if any) + size_t assignment_count = 0; + { + int next, state=1; + for(pugi::xml_node node = root.first_child(); node; node = node.next_sibling()) { + *offset_debug = node.offset_debug(); + gtok_t_packer_constraints in = lex_node_t_packer_constraints(node.name(), report_error); + next = gstate_t_packer_constraints[state][(int)in]; + if(next == -1) + dfa_error(gtok_lookup_t_packer_constraints[(int)in], gstate_t_packer_constraints[state], gtok_lookup_t_packer_constraints, 1, report_error); + state = next; + switch(in) { + case gtok_t_packer_constraints::ASSIGNMENT: + assignment_count += 1; + break; + default: break; /* Not possible. */ + } + } + + out.preallocate_packer_constraints_assignment(context, assignment_count); + } + int next, state=1; + for(pugi::xml_node node = root.first_child(); node; node = node.next_sibling()){ + *offset_debug = node.offset_debug(); + gtok_t_packer_constraints in = lex_node_t_packer_constraints(node.name(), report_error); + next = gstate_t_packer_constraints[state][(int)in]; + if(next == -1) + dfa_error(gtok_lookup_t_packer_constraints[(int)in], gstate_t_packer_constraints[state], gtok_lookup_t_packer_constraints, 1, report_error); + state = next; + switch(in){ + case gtok_t_packer_constraints::ASSIGNMENT: + { + auto child_context = out.add_packer_constraints_assignment(context); + load_assignment(node, out, child_context, report_error, offset_debug); + out.finish_packer_constraints_assignment(child_context); + } + break; + default: break; /* Not possible. */ + } + } + if(state != 0) dfa_error("end of input", gstate_t_packer_constraints[state], gtok_lookup_t_packer_constraints, 1, report_error); + } constexpr int NUM_T_VPR_CONSTRAINTS_STATES = 1; -constexpr const int NUM_T_VPR_CONSTRAINTS_INPUTS = 2; +constexpr const int NUM_T_VPR_CONSTRAINTS_INPUTS = 3; constexpr int gstate_t_vpr_constraints[NUM_T_VPR_CONSTRAINTS_STATES][NUM_T_VPR_CONSTRAINTS_INPUTS] = { - {0, 0}, + {0, 0, 0}, }; template -inline void load_vpr_constraints(const pugi::xml_node& root, T& out, Context& context, const std::function* report_error, ptrdiff_t* offset_debug) { - (void)root; - (void)out; - (void)context; - (void)report_error; - // Update current file offset in case an error is encountered. - *offset_debug = root.offset_debug(); - - for (pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()) { - atok_t_vpr_constraints in = lex_attr_t_vpr_constraints(attr.name(), report_error); - switch (in) { - case atok_t_vpr_constraints::TOOL_NAME: - out.set_vpr_constraints_tool_name(attr.value(), context); - break; - default: - break; /* Not possible. */ - } - } - - // Preallocate arrays by counting child nodes (if any) - size_t partition_list_count = 0; - size_t global_route_constraints_count = 0; - { - int next, state = 0; - for (pugi::xml_node node = root.first_child(); node; node = node.next_sibling()) { - *offset_debug = node.offset_debug(); - gtok_t_vpr_constraints in = lex_node_t_vpr_constraints(node.name(), report_error); - next = gstate_t_vpr_constraints[state][(int)in]; - if (next == -1) - dfa_error(gtok_lookup_t_vpr_constraints[(int)in], gstate_t_vpr_constraints[state], gtok_lookup_t_vpr_constraints, 2, report_error); - state = next; - switch (in) { - case gtok_t_vpr_constraints::PARTITION_LIST: - partition_list_count += 1; - break; - case gtok_t_vpr_constraints::GLOBAL_ROUTE_CONSTRAINTS: - global_route_constraints_count += 1; - break; - default: - break; /* Not possible. */ - } - } - - out.preallocate_vpr_constraints_partition_list(context, partition_list_count); - out.preallocate_vpr_constraints_global_route_constraints(context, global_route_constraints_count); - } - int next, state = 0; - for (pugi::xml_node node = root.first_child(); node; node = node.next_sibling()) { - *offset_debug = node.offset_debug(); - gtok_t_vpr_constraints in = lex_node_t_vpr_constraints(node.name(), report_error); - next = gstate_t_vpr_constraints[state][(int)in]; - if (next == -1) - dfa_error(gtok_lookup_t_vpr_constraints[(int)in], gstate_t_vpr_constraints[state], gtok_lookup_t_vpr_constraints, 2, report_error); - state = next; - switch (in) { - case gtok_t_vpr_constraints::PARTITION_LIST: { - auto child_context = out.add_vpr_constraints_partition_list(context); - load_partition_list(node, out, child_context, report_error, offset_debug); - out.finish_vpr_constraints_partition_list(child_context); - } break; - case gtok_t_vpr_constraints::GLOBAL_ROUTE_CONSTRAINTS: { - auto child_context = out.add_vpr_constraints_global_route_constraints(context); - load_global_route_constraints(node, out, child_context, report_error, offset_debug); - out.finish_vpr_constraints_global_route_constraints(child_context); - } break; - default: - break; /* Not possible. */ - } - } - if (state != 0) dfa_error("end of input", gstate_t_vpr_constraints[state], gtok_lookup_t_vpr_constraints, 2, report_error); +inline void load_vpr_constraints(const pugi::xml_node &root, T &out, Context &context, const std::function *report_error, ptrdiff_t *offset_debug){ + (void)root; + (void)out; + (void)context; + (void)report_error; + // Update current file offset in case an error is encountered. + *offset_debug = root.offset_debug(); + + for(pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()){ + atok_t_vpr_constraints in = lex_attr_t_vpr_constraints(attr.name(), report_error); + switch(in){ + case atok_t_vpr_constraints::TOOL_NAME: + out.set_vpr_constraints_tool_name(attr.value(), context); + break; + default: break; /* Not possible. */ + } + } + + // Preallocate arrays by counting child nodes (if any) + size_t partition_list_count = 0; + size_t global_route_constraints_count = 0; + size_t packer_constraints_count = 0; + { + int next, state=0; + for(pugi::xml_node node = root.first_child(); node; node = node.next_sibling()) { + *offset_debug = node.offset_debug(); + gtok_t_vpr_constraints in = lex_node_t_vpr_constraints(node.name(), report_error); + next = gstate_t_vpr_constraints[state][(int)in]; + if(next == -1) + dfa_error(gtok_lookup_t_vpr_constraints[(int)in], gstate_t_vpr_constraints[state], gtok_lookup_t_vpr_constraints, 3, report_error); + state = next; + switch(in) { + case gtok_t_vpr_constraints::PARTITION_LIST: + partition_list_count += 1; + break; + case gtok_t_vpr_constraints::GLOBAL_ROUTE_CONSTRAINTS: + global_route_constraints_count += 1; + break; + case gtok_t_vpr_constraints::PACKER_CONSTRAINTS: + packer_constraints_count += 1; + break; + default: break; /* Not possible. */ + } + } + + out.preallocate_vpr_constraints_partition_list(context, partition_list_count); + out.preallocate_vpr_constraints_global_route_constraints(context, global_route_constraints_count); + out.preallocate_vpr_constraints_packer_constraints(context, packer_constraints_count); + } + int next, state=0; + for(pugi::xml_node node = root.first_child(); node; node = node.next_sibling()){ + *offset_debug = node.offset_debug(); + gtok_t_vpr_constraints in = lex_node_t_vpr_constraints(node.name(), report_error); + next = gstate_t_vpr_constraints[state][(int)in]; + if(next == -1) + dfa_error(gtok_lookup_t_vpr_constraints[(int)in], gstate_t_vpr_constraints[state], gtok_lookup_t_vpr_constraints, 3, report_error); + state = next; + switch(in){ + case gtok_t_vpr_constraints::PARTITION_LIST: + { + auto child_context = out.add_vpr_constraints_partition_list(context); + load_partition_list(node, out, child_context, report_error, offset_debug); + out.finish_vpr_constraints_partition_list(child_context); + } + break; + case gtok_t_vpr_constraints::GLOBAL_ROUTE_CONSTRAINTS: + { + auto child_context = out.add_vpr_constraints_global_route_constraints(context); + load_global_route_constraints(node, out, child_context, report_error, offset_debug); + out.finish_vpr_constraints_global_route_constraints(child_context); + } + break; + case gtok_t_vpr_constraints::PACKER_CONSTRAINTS: + { + auto child_context = out.add_vpr_constraints_packer_constraints(context); + load_packer_constraints(node, out, child_context, report_error, offset_debug); + out.finish_vpr_constraints_packer_constraints(child_context); + } + break; + default: break; /* Not possible. */ + } + } + if(state != 0) dfa_error("end of input", gstate_t_vpr_constraints[state], gtok_lookup_t_vpr_constraints, 3, report_error); + } + /* Internal writing functions, which uxsdcxx uses to write out a class. */ template -inline void write_partition(T& in, std::ostream& os, Context& context) { - (void)in; - (void)os; - (void)context; - { - for (size_t i = 0, n = in.num_partition_add_atom(context); i < n; i++) { - auto child_context = in.get_partition_add_atom(i, context); - os << "\n"; - } - } - { - for (size_t i = 0, n = in.num_partition_add_region(context); i < n; i++) { - auto child_context = in.get_partition_add_region(i, context); - os << "\n"; - } - } +inline void write_partition(T &in, std::ostream &os, Context &context){ + (void)in; + (void)os; + (void)context; + { + for(size_t i=0, n=in.num_partition_add_atom(context); i\n"; + } + } + { + for(size_t i=0, n=in.num_partition_add_region(context); i\n"; + } + } } template -inline void write_partition_list(T& in, std::ostream& os, Context& context) { - (void)in; - (void)os; - (void)context; - { - for (size_t i = 0, n = in.num_partition_list_partition(context); i < n; i++) { - auto child_context = in.get_partition_list_partition(i, context); - os << ""; - write_partition(in, os, child_context); - os << "\n"; - } - } +inline void write_partition_list(T &in, std::ostream &os, Context &context){ + (void)in; + (void)os; + (void)context; + { + for(size_t i=0, n=in.num_partition_list_partition(context); i"; + write_partition(in, os, child_context); + os << "\n"; + } + } } template -inline void write_global_route_constraints(T& in, std::ostream& os, Context& context) { - (void)in; - (void)os; - (void)context; - { - for (size_t i = 0, n = in.num_global_route_constraints_set_global_signal(context); i < n; i++) { - auto child_context = in.get_global_route_constraints_set_global_signal(i, context); - os << "\n"; - } - } +inline void write_global_route_constraints(T &in, std::ostream &os, Context &context){ + (void)in; + (void)os; + (void)context; + { + for(size_t i=0, n=in.num_global_route_constraints_set_global_signal(context); i\n"; + } + } } template -inline void write_vpr_constraints(T& in, std::ostream& os, Context& context) { - (void)in; - (void)os; - (void)context; - { - for (size_t i = 0, n = in.num_vpr_constraints_partition_list(context); i < n; i++) { - auto child_context = in.get_vpr_constraints_partition_list(i, context); - os << "\n"; - write_partition_list(in, os, child_context); - os << "\n"; - } - } - { - for (size_t i = 0, n = in.num_vpr_constraints_global_route_constraints(context); i < n; i++) { - auto child_context = in.get_vpr_constraints_global_route_constraints(i, context); - os << "\n"; - write_global_route_constraints(in, os, child_context); - os << "\n"; - } - } +inline void write_packer_constraints(T &in, std::ostream &os, Context &context){ + (void)in; + (void)os; + (void)context; + { + for(size_t i=0, n=in.num_packer_constraints_assignment(context); i\n"; + } + } } -inline void dfa_error(const char* wrong, const int* states, const char* const* lookup, int len, const std::function* report_error) { - std::vector expected; - for (int i = 0; i < len; i++) { - if (states[i] != -1) expected.push_back(lookup[i]); - } +template +inline void write_vpr_constraints(T &in, std::ostream &os, Context &context){ + (void)in; + (void)os; + (void)context; + { + for(size_t i=0, n=in.num_vpr_constraints_partition_list(context); i\n"; + write_partition_list(in, os, child_context); + os << "\n"; + } + } + { + for(size_t i=0, n=in.num_vpr_constraints_global_route_constraints(context); i\n"; + write_global_route_constraints(in, os, child_context); + os << "\n"; + } + } + { + for(size_t i=0, n=in.num_vpr_constraints_packer_constraints(context); i\n"; + write_packer_constraints(in, os, child_context); + os << "\n"; + } + } +} - std::string expected_or = expected[0]; - for (unsigned int i = 1; i < expected.size(); i++) - expected_or += std::string(" or ") + expected[i]; +inline void dfa_error(const char *wrong, const int *states, const char * const *lookup, int len, const std::function * report_error){ + std::vector expected; + for(int i=0; i -inline void attr_error(std::bitset astate, const char* const* lookup, const std::function* report_error) { - std::vector missing; - for (unsigned int i = 0; i < N; i++) { - if (astate[i] == 0) missing.push_back(lookup[i]); - } +inline void attr_error(std::bitset astate, const char * const *lookup, const std::function * report_error){ + std::vector missing; + for(unsigned int i=0; i f(fopen(filename, "rb"), fclose); - - if (!f) { - throw std::runtime_error(std::string("Failed to open file ") + filename); - } - - int current_line = 1; - std::ptrdiff_t offset = 0; - std::ptrdiff_t last_line_offset = 0; - std::ptrdiff_t current_line_offset = 0; - - char buffer[1024]; - std::size_t size; - - while ((size = fread(buffer, 1, sizeof(buffer), f.get())) > 0) { - for (std::size_t i = 0; i < size; ++i) { - if (buffer[i] == '\n') { - current_line += 1; - last_line_offset = current_line_offset; - current_line_offset = offset + i; - - if (target_offset < current_line_offset) { - if (target_offset < last_line_offset) { - throw std::runtime_error("Assertion violation"); - } - - *line = current_line - 1; - *col = target_offset - last_line_offset; - return; - } - } - } - - offset += size; - } - - *line = current_line; - *col = target_offset - current_line_offset; +inline void get_line_number(const char *filename, std::ptrdiff_t target_offset, int * line, int * col) { + std::unique_ptr f(fopen(filename, "rb"), fclose); + + if (!f) { + throw std::runtime_error(std::string("Failed to open file") + filename); + } + + int current_line = 1; + std::ptrdiff_t offset = 0; + std::ptrdiff_t last_line_offset = 0; + std::ptrdiff_t current_line_offset = 0; + + char buffer[1024]; + std::size_t size; + + while ((size = fread(buffer, 1, sizeof(buffer), f.get())) > 0) { + for (std::size_t i = 0; i < size; ++i) { + if (buffer[i] == '\n') { + current_line += 1; + last_line_offset = current_line_offset; + current_line_offset = offset + i; + + if(target_offset < current_line_offset) { + if(target_offset < last_line_offset) { + throw std::runtime_error("Assertion violation"); + } + + *line = current_line - 1; + *col = target_offset - last_line_offset; + return; + } + } + } + + offset += size; + } + + *line = current_line; + *col = target_offset - current_line_offset; } + } /* namespace uxsd */ diff --git a/vpr/src/base/gen/vpr_constraints_uxsdcxx_interface.h b/vpr/src/base/gen/vpr_constraints_uxsdcxx_interface.h index 280bf58c793..9e6ab7bb31a 100644 --- a/vpr/src/base/gen/vpr_constraints_uxsdcxx_interface.h +++ b/vpr/src/base/gen/vpr_constraints_uxsdcxx_interface.h @@ -4,13 +4,14 @@ * https://github.com/duck2/uxsdcxx * Modify only if your build process doesn't involve regenerating this file. * - * Cmdline: uxsdcxx.py /home/tao/works/dev/clock/vtr-verilog-to-routing/vpr/src/base/vpr_constraints.xsd - * Input file: /home/tao/works/dev/clock/vtr-verilog-to-routing/vpr/src/base/vpr_constraints.xsd - * md5sum of input file: 2d6f442d8044f76e8f1b1d276b7358da + * Cmdline: uxsdcxx.py /home/tao/works/dev/route_constraints/vtr-verilog-to-routing/vpr/src/base/vpr_constraints.xsd + * Input file: /home/tao/works/dev/route_constraints/vtr-verilog-to-routing/vpr/src/base/vpr_constraints.xsd + * md5sum of input file: 9f078b743b3fa356a41cf239f150a599 */ #include + /* All uxsdcxx functions and structs live in this namespace. */ #include @@ -20,140 +21,174 @@ namespace uxsd { /* Base class for the schema. */ struct DefaultVprConstraintsContextTypes { - using AddAtomReadContext = void*; - using AddRegionReadContext = void*; - using PartitionReadContext = void*; - using PartitionListReadContext = void*; - using SetGlobalSignalReadContext = void*; - using GlobalRouteConstraintsReadContext = void*; - using VprConstraintsReadContext = void*; - using AddAtomWriteContext = void*; - using AddRegionWriteContext = void*; - using PartitionWriteContext = void*; - using PartitionListWriteContext = void*; - using SetGlobalSignalWriteContext = void*; - using GlobalRouteConstraintsWriteContext = void*; - using VprConstraintsWriteContext = void*; +using AddAtomReadContext = void *; + using AddRegionReadContext = void *; + using PartitionReadContext = void *; + using PartitionListReadContext = void *; + using SetGlobalSignalReadContext = void *; + using GlobalRouteConstraintsReadContext = void *; + using AssignmentReadContext = void *; + using PackerConstraintsReadContext = void *; + using VprConstraintsReadContext = void *; +using AddAtomWriteContext = void *; + using AddRegionWriteContext = void *; + using PartitionWriteContext = void *; + using PartitionListWriteContext = void *; + using SetGlobalSignalWriteContext = void *; + using GlobalRouteConstraintsWriteContext = void *; + using AssignmentWriteContext = void *; + using PackerConstraintsWriteContext = void *; + using VprConstraintsWriteContext = void *; }; -template +template class VprConstraintsBase { - public: - virtual ~VprConstraintsBase() {} - virtual void start_load(const std::function* report_error) = 0; - virtual void finish_load() = 0; - virtual void start_write() = 0; - virtual void finish_write() = 0; - virtual void error_encountered(const char* file, int line, const char* message) = 0; - /** Generated for complex type "add_atom": - * - * - * - */ - virtual inline const char* get_add_atom_name_pattern(typename ContextTypes::AddAtomReadContext& ctx) = 0; - virtual inline void set_add_atom_name_pattern(const char* name_pattern, typename ContextTypes::AddAtomWriteContext& ctx) = 0; - - /** Generated for complex type "add_region": - * - * - * - * - * - * - * - */ - virtual inline int get_add_region_subtile(typename ContextTypes::AddRegionReadContext& ctx) = 0; - virtual inline void set_add_region_subtile(int subtile, typename ContextTypes::AddRegionWriteContext& ctx) = 0; - virtual inline int get_add_region_x_high(typename ContextTypes::AddRegionReadContext& ctx) = 0; - virtual inline int get_add_region_x_low(typename ContextTypes::AddRegionReadContext& ctx) = 0; - virtual inline int get_add_region_y_high(typename ContextTypes::AddRegionReadContext& ctx) = 0; - virtual inline int get_add_region_y_low(typename ContextTypes::AddRegionReadContext& ctx) = 0; - - /** Generated for complex type "partition": - * - * - * - * - * - * - * - * - * - */ - virtual inline const char* get_partition_name(typename ContextTypes::PartitionReadContext& ctx) = 0; - virtual inline void set_partition_name(const char* name, typename ContextTypes::PartitionWriteContext& ctx) = 0; - virtual inline void preallocate_partition_add_atom(typename ContextTypes::PartitionWriteContext& ctx, size_t size) = 0; - virtual inline typename ContextTypes::AddAtomWriteContext add_partition_add_atom(typename ContextTypes::PartitionWriteContext& ctx) = 0; - virtual inline void finish_partition_add_atom(typename ContextTypes::AddAtomWriteContext& ctx) = 0; - virtual inline size_t num_partition_add_atom(typename ContextTypes::PartitionReadContext& ctx) = 0; - virtual inline typename ContextTypes::AddAtomReadContext get_partition_add_atom(int n, typename ContextTypes::PartitionReadContext& ctx) = 0; - virtual inline void preallocate_partition_add_region(typename ContextTypes::PartitionWriteContext& ctx, size_t size) = 0; - virtual inline typename ContextTypes::AddRegionWriteContext add_partition_add_region(typename ContextTypes::PartitionWriteContext& ctx, int x_high, int x_low, int y_high, int y_low) = 0; - virtual inline void finish_partition_add_region(typename ContextTypes::AddRegionWriteContext& ctx) = 0; - virtual inline size_t num_partition_add_region(typename ContextTypes::PartitionReadContext& ctx) = 0; - virtual inline typename ContextTypes::AddRegionReadContext get_partition_add_region(int n, typename ContextTypes::PartitionReadContext& ctx) = 0; - - /** Generated for complex type "partition_list": - * - * - * - * - * - */ - virtual inline void preallocate_partition_list_partition(typename ContextTypes::PartitionListWriteContext& ctx, size_t size) = 0; - virtual inline typename ContextTypes::PartitionWriteContext add_partition_list_partition(typename ContextTypes::PartitionListWriteContext& ctx) = 0; - virtual inline void finish_partition_list_partition(typename ContextTypes::PartitionWriteContext& ctx) = 0; - virtual inline size_t num_partition_list_partition(typename ContextTypes::PartitionListReadContext& ctx) = 0; - virtual inline typename ContextTypes::PartitionReadContext get_partition_list_partition(int n, typename ContextTypes::PartitionListReadContext& ctx) = 0; - - /** Generated for complex type "set_global_signal": - * - * - * - * - * - */ - virtual inline const char* get_set_global_signal_name(typename ContextTypes::SetGlobalSignalReadContext& ctx) = 0; - virtual inline void set_set_global_signal_name(const char* name, typename ContextTypes::SetGlobalSignalWriteContext& ctx) = 0; - virtual inline const char* get_set_global_signal_route_model(typename ContextTypes::SetGlobalSignalReadContext& ctx) = 0; - virtual inline void set_set_global_signal_route_model(const char* route_model, typename ContextTypes::SetGlobalSignalWriteContext& ctx) = 0; - virtual inline const char* get_set_global_signal_type(typename ContextTypes::SetGlobalSignalReadContext& ctx) = 0; - virtual inline void set_set_global_signal_type(const char* type, typename ContextTypes::SetGlobalSignalWriteContext& ctx) = 0; - - /** Generated for complex type "global_route_constraints": - * - * - * - * - * - */ - virtual inline void preallocate_global_route_constraints_set_global_signal(typename ContextTypes::GlobalRouteConstraintsWriteContext& ctx, size_t size) = 0; - virtual inline typename ContextTypes::SetGlobalSignalWriteContext add_global_route_constraints_set_global_signal(typename ContextTypes::GlobalRouteConstraintsWriteContext& ctx) = 0; - virtual inline void finish_global_route_constraints_set_global_signal(typename ContextTypes::SetGlobalSignalWriteContext& ctx) = 0; - virtual inline size_t num_global_route_constraints_set_global_signal(typename ContextTypes::GlobalRouteConstraintsReadContext& ctx) = 0; - virtual inline typename ContextTypes::SetGlobalSignalReadContext get_global_route_constraints_set_global_signal(int n, typename ContextTypes::GlobalRouteConstraintsReadContext& ctx) = 0; - - /** Generated for complex type "vpr_constraints": - * - * - * - * - * - * - * - */ - virtual inline const char* get_vpr_constraints_tool_name(typename ContextTypes::VprConstraintsReadContext& ctx) = 0; - virtual inline void set_vpr_constraints_tool_name(const char* tool_name, typename ContextTypes::VprConstraintsWriteContext& ctx) = 0; - virtual inline void preallocate_vpr_constraints_partition_list(typename ContextTypes::VprConstraintsWriteContext& ctx, size_t size) = 0; - virtual inline typename ContextTypes::PartitionListWriteContext add_vpr_constraints_partition_list(typename ContextTypes::VprConstraintsWriteContext& ctx) = 0; - virtual inline void finish_vpr_constraints_partition_list(typename ContextTypes::PartitionListWriteContext& ctx) = 0; - virtual inline size_t num_vpr_constraints_partition_list(typename ContextTypes::VprConstraintsReadContext& ctx) = 0; - virtual inline typename ContextTypes::PartitionListReadContext get_vpr_constraints_partition_list(int n, typename ContextTypes::VprConstraintsReadContext& ctx) = 0; - virtual inline void preallocate_vpr_constraints_global_route_constraints(typename ContextTypes::VprConstraintsWriteContext& ctx, size_t size) = 0; - virtual inline typename ContextTypes::GlobalRouteConstraintsWriteContext add_vpr_constraints_global_route_constraints(typename ContextTypes::VprConstraintsWriteContext& ctx) = 0; - virtual inline void finish_vpr_constraints_global_route_constraints(typename ContextTypes::GlobalRouteConstraintsWriteContext& ctx) = 0; - virtual inline size_t num_vpr_constraints_global_route_constraints(typename ContextTypes::VprConstraintsReadContext& ctx) = 0; - virtual inline typename ContextTypes::GlobalRouteConstraintsReadContext get_vpr_constraints_global_route_constraints(int n, typename ContextTypes::VprConstraintsReadContext& ctx) = 0; +public: + virtual ~VprConstraintsBase() {} + virtual void start_load(const std::function *report_error) = 0; + virtual void finish_load() = 0; + virtual void start_write() = 0; + virtual void finish_write() = 0; + virtual void error_encountered(const char * file, int line, const char *message) = 0; + /** Generated for complex type "add_atom": + * + * + * + */ + virtual inline const char * get_add_atom_name_pattern(typename ContextTypes::AddAtomReadContext &ctx) = 0; + virtual inline void set_add_atom_name_pattern(const char * name_pattern, typename ContextTypes::AddAtomWriteContext &ctx) = 0; + + /** Generated for complex type "add_region": + * + * + * + * + * + * + * + */ + virtual inline int get_add_region_subtile(typename ContextTypes::AddRegionReadContext &ctx) = 0; + virtual inline void set_add_region_subtile(int subtile, typename ContextTypes::AddRegionWriteContext &ctx) = 0; + virtual inline int get_add_region_x_high(typename ContextTypes::AddRegionReadContext &ctx) = 0; + virtual inline int get_add_region_x_low(typename ContextTypes::AddRegionReadContext &ctx) = 0; + virtual inline int get_add_region_y_high(typename ContextTypes::AddRegionReadContext &ctx) = 0; + virtual inline int get_add_region_y_low(typename ContextTypes::AddRegionReadContext &ctx) = 0; + + /** Generated for complex type "partition": + * + * + * + * + * + * + * + * + * + */ + virtual inline const char * get_partition_name(typename ContextTypes::PartitionReadContext &ctx) = 0; + virtual inline void set_partition_name(const char * name, typename ContextTypes::PartitionWriteContext &ctx) = 0; + virtual inline void preallocate_partition_add_atom(typename ContextTypes::PartitionWriteContext &ctx, size_t size) = 0; + virtual inline typename ContextTypes::AddAtomWriteContext add_partition_add_atom(typename ContextTypes::PartitionWriteContext &ctx) = 0; + virtual inline void finish_partition_add_atom(typename ContextTypes::AddAtomWriteContext &ctx) = 0; + virtual inline size_t num_partition_add_atom(typename ContextTypes::PartitionReadContext &ctx) = 0; + virtual inline typename ContextTypes::AddAtomReadContext get_partition_add_atom(int n, typename ContextTypes::PartitionReadContext &ctx) = 0; + virtual inline void preallocate_partition_add_region(typename ContextTypes::PartitionWriteContext &ctx, size_t size) = 0; + virtual inline typename ContextTypes::AddRegionWriteContext add_partition_add_region(typename ContextTypes::PartitionWriteContext &ctx, int x_high, int x_low, int y_high, int y_low) = 0; + virtual inline void finish_partition_add_region(typename ContextTypes::AddRegionWriteContext &ctx) = 0; + virtual inline size_t num_partition_add_region(typename ContextTypes::PartitionReadContext &ctx) = 0; + virtual inline typename ContextTypes::AddRegionReadContext get_partition_add_region(int n, typename ContextTypes::PartitionReadContext &ctx) = 0; + + /** Generated for complex type "partition_list": + * + * + * + * + * + */ + virtual inline void preallocate_partition_list_partition(typename ContextTypes::PartitionListWriteContext &ctx, size_t size) = 0; + virtual inline typename ContextTypes::PartitionWriteContext add_partition_list_partition(typename ContextTypes::PartitionListWriteContext &ctx) = 0; + virtual inline void finish_partition_list_partition(typename ContextTypes::PartitionWriteContext &ctx) = 0; + virtual inline size_t num_partition_list_partition(typename ContextTypes::PartitionListReadContext &ctx) = 0; + virtual inline typename ContextTypes::PartitionReadContext get_partition_list_partition(int n, typename ContextTypes::PartitionListReadContext &ctx) = 0; + + /** Generated for complex type "set_global_signal": + * + * + * + * + * + */ + virtual inline const char * get_set_global_signal_name(typename ContextTypes::SetGlobalSignalReadContext &ctx) = 0; + virtual inline void set_set_global_signal_name(const char * name, typename ContextTypes::SetGlobalSignalWriteContext &ctx) = 0; + virtual inline const char * get_set_global_signal_route_model(typename ContextTypes::SetGlobalSignalReadContext &ctx) = 0; + virtual inline void set_set_global_signal_route_model(const char * route_model, typename ContextTypes::SetGlobalSignalWriteContext &ctx) = 0; + virtual inline const char * get_set_global_signal_type(typename ContextTypes::SetGlobalSignalReadContext &ctx) = 0; + virtual inline void set_set_global_signal_type(const char * type, typename ContextTypes::SetGlobalSignalWriteContext &ctx) = 0; + + /** Generated for complex type "global_route_constraints": + * + * + * + * + * + */ + virtual inline void preallocate_global_route_constraints_set_global_signal(typename ContextTypes::GlobalRouteConstraintsWriteContext &ctx, size_t size) = 0; + virtual inline typename ContextTypes::SetGlobalSignalWriteContext add_global_route_constraints_set_global_signal(typename ContextTypes::GlobalRouteConstraintsWriteContext &ctx) = 0; + virtual inline void finish_global_route_constraints_set_global_signal(typename ContextTypes::SetGlobalSignalWriteContext &ctx) = 0; + virtual inline size_t num_global_route_constraints_set_global_signal(typename ContextTypes::GlobalRouteConstraintsReadContext &ctx) = 0; + virtual inline typename ContextTypes::SetGlobalSignalReadContext get_global_route_constraints_set_global_signal(int n, typename ContextTypes::GlobalRouteConstraintsReadContext &ctx) = 0; + + /** Generated for complex type "assignment": + * + * + * + * + */ + virtual inline const char * get_assignment_net(typename ContextTypes::AssignmentReadContext &ctx) = 0; + virtual inline void set_assignment_net(const char * net, typename ContextTypes::AssignmentWriteContext &ctx) = 0; + virtual inline const char * get_assignment_pin(typename ContextTypes::AssignmentReadContext &ctx) = 0; + virtual inline void set_assignment_pin(const char * pin, typename ContextTypes::AssignmentWriteContext &ctx) = 0; + + /** Generated for complex type "packer_constraints": + * + * + * + * + * + */ + virtual inline void preallocate_packer_constraints_assignment(typename ContextTypes::PackerConstraintsWriteContext &ctx, size_t size) = 0; + virtual inline typename ContextTypes::AssignmentWriteContext add_packer_constraints_assignment(typename ContextTypes::PackerConstraintsWriteContext &ctx) = 0; + virtual inline void finish_packer_constraints_assignment(typename ContextTypes::AssignmentWriteContext &ctx) = 0; + virtual inline size_t num_packer_constraints_assignment(typename ContextTypes::PackerConstraintsReadContext &ctx) = 0; + virtual inline typename ContextTypes::AssignmentReadContext get_packer_constraints_assignment(int n, typename ContextTypes::PackerConstraintsReadContext &ctx) = 0; + + /** Generated for complex type "vpr_constraints": + * + * + * + * + * + * + * + * + */ + virtual inline const char * get_vpr_constraints_tool_name(typename ContextTypes::VprConstraintsReadContext &ctx) = 0; + virtual inline void set_vpr_constraints_tool_name(const char * tool_name, typename ContextTypes::VprConstraintsWriteContext &ctx) = 0; + virtual inline void preallocate_vpr_constraints_partition_list(typename ContextTypes::VprConstraintsWriteContext &ctx, size_t size) = 0; + virtual inline typename ContextTypes::PartitionListWriteContext add_vpr_constraints_partition_list(typename ContextTypes::VprConstraintsWriteContext &ctx) = 0; + virtual inline void finish_vpr_constraints_partition_list(typename ContextTypes::PartitionListWriteContext &ctx) = 0; + virtual inline size_t num_vpr_constraints_partition_list(typename ContextTypes::VprConstraintsReadContext &ctx) = 0; + virtual inline typename ContextTypes::PartitionListReadContext get_vpr_constraints_partition_list(int n, typename ContextTypes::VprConstraintsReadContext &ctx) = 0; + virtual inline void preallocate_vpr_constraints_global_route_constraints(typename ContextTypes::VprConstraintsWriteContext &ctx, size_t size) = 0; + virtual inline typename ContextTypes::GlobalRouteConstraintsWriteContext add_vpr_constraints_global_route_constraints(typename ContextTypes::VprConstraintsWriteContext &ctx) = 0; + virtual inline void finish_vpr_constraints_global_route_constraints(typename ContextTypes::GlobalRouteConstraintsWriteContext &ctx) = 0; + virtual inline size_t num_vpr_constraints_global_route_constraints(typename ContextTypes::VprConstraintsReadContext &ctx) = 0; + virtual inline typename ContextTypes::GlobalRouteConstraintsReadContext get_vpr_constraints_global_route_constraints(int n, typename ContextTypes::VprConstraintsReadContext &ctx) = 0; + virtual inline void preallocate_vpr_constraints_packer_constraints(typename ContextTypes::VprConstraintsWriteContext &ctx, size_t size) = 0; + virtual inline typename ContextTypes::PackerConstraintsWriteContext add_vpr_constraints_packer_constraints(typename ContextTypes::VprConstraintsWriteContext &ctx) = 0; + virtual inline void finish_vpr_constraints_packer_constraints(typename ContextTypes::PackerConstraintsWriteContext &ctx) = 0; + virtual inline size_t num_vpr_constraints_packer_constraints(typename ContextTypes::VprConstraintsReadContext &ctx) = 0; + virtual inline typename ContextTypes::PackerConstraintsReadContext get_vpr_constraints_packer_constraints(int n, typename ContextTypes::VprConstraintsReadContext &ctx) = 0; }; } /* namespace uxsd */ diff --git a/vpr/src/base/packer_constraint.cpp b/vpr/src/base/packer_constraint.cpp new file mode 100644 index 00000000000..b5cbdc44904 --- /dev/null +++ b/vpr/src/base/packer_constraint.cpp @@ -0,0 +1,33 @@ +#include "packer_constraint.h" + +PackerConstraint::PackerConstraint() { + net_name_ = std::string(""); + pin_name_ = std::string(""); + is_valid_ = false; +} + +void PackerConstraint::set_net_name(std::string name) { + net_name_ = name; + return; +} + +std::string PackerConstraint::net_name() const { + return net_name_; +} + +void PackerConstraint::set_pin_name(std::string name) { + pin_name_ = name; + return; +} + +std::string PackerConstraint::pin_name() const { + return net_name_; +} + +void PackerConstraint::set_is_valid(bool value) { + is_valid_ = value; +} + +bool PackerConstraint::is_valid() const { + return is_valid_; +} diff --git a/vpr/src/base/packer_constraint.h b/vpr/src/base/packer_constraint.h new file mode 100644 index 00000000000..d480d8586a7 --- /dev/null +++ b/vpr/src/base/packer_constraint.h @@ -0,0 +1,54 @@ +#ifndef PACKER_CONSTRAINT_H +#define PACKER_CONSTRAINT_H + +#include "vpr_types.h" + +/** + * @file + * @brief This file defines the PackerConstraint class. + */ + +class PackerConstraint { + public: + /** + * @brief Constructor for the PackerConstraint class, sets member variables to invalid values + */ + PackerConstraint(); + + /** + * @brief get net name + */ + std::string net_name() const; + + /** + * @brief set net name + */ + void set_net_name(std::string); + + /** + * @brief get pin name + */ + std::string pin_name() const; + + /** + * @brief set pin name + */ + void set_pin_name(std::string); + + /** + * @brief set is valid + */ + void set_is_valid(bool); + + /** + * @brief get is valid + */ + bool is_valid() const; + + private: + std::string net_name_; + std::string pin_name_; + bool is_valid_; +}; + +#endif /* PACKER_CONSTRAINT_H */ diff --git a/vpr/src/base/vpr_constraints.cpp b/vpr/src/base/vpr_constraints.cpp index 64dcfd310c8..b99b79dea81 100644 --- a/vpr/src/base/vpr_constraints.cpp +++ b/vpr/src/base/vpr_constraints.cpp @@ -1,6 +1,7 @@ #include "vpr_constraints.h" #include "partition.h" #include "route_constraint.h" +#include "packer_constraint.h" #include void VprConstraints::add_constrained_atom(const AtomBlockId blk_id, const PartitionId part_id) { @@ -122,6 +123,66 @@ int VprConstraints::get_route_constraint_num(void) const { return route_constraints_.size(); } +void VprConstraints::add_packer_constraint(PackerConstraint rc) { + packer_constraints_.insert({rc.net_name(), rc}); + return; +} + +const PackerConstraint VprConstraints::get_packer_constraint_by_net_name(std::string net_name) { + PackerConstraint pc; + auto const& pc_itr = packer_constraints_.find(net_name); + if (pc_itr == packer_constraints_.end()) { + // try regexp + bool found_thru_regex = false; + for (auto constraint : packer_constraints_) { + if (std::regex_match(net_name, std::regex(constraint.first))) { + pc = constraint.second; + + // mark as invalid so write constraint function will not write constraint + // of regexpr name + // instead a matched constraint is inserted in + constraint.second.set_is_valid(false); + pc.set_net_name(net_name); + pc.set_is_valid(true); + packer_constraints_.insert({net_name, pc}); + + found_thru_regex = true; + break; + } + } + if (!found_thru_regex) { + pc.set_net_name("INVALID"); + pc.set_pin_name("INVALID"); + pc.set_is_valid(false); + } + } else { + pc = pc_itr->second; + } + return pc; +} + +const PackerConstraint VprConstraints::get_packer_constraint_by_idx(std::size_t idx) const { + PackerConstraint pc; + if ((packer_constraints_.size() == 0) || (idx > packer_constraints_.size() - 1)) { + pc.set_net_name("INVALID"); + pc.set_pin_name("INVALID"); + pc.set_is_valid(false); + } else { + std::size_t i = 0; + for (auto const& pc_itr : packer_constraints_) { + if (i == idx) { + pc = pc_itr.second; + break; + } + } + } + return pc; +} + +int VprConstraints::get_packer_constraint_num(void) const { + return packer_constraints_.size(); +} + void print_constraints(FILE* fp, VprConstraints constraints) { Partition temp_part; std::vector atoms; diff --git a/vpr/src/base/vpr_constraints.h b/vpr/src/base/vpr_constraints.h index f9343267a9e..eaf4ac20446 100644 --- a/vpr/src/base/vpr_constraints.h +++ b/vpr/src/base/vpr_constraints.h @@ -6,6 +6,7 @@ #include "partition.h" #include "partition_region.h" #include "route_constraint.h" +#include "packer_constraint.h" /** * @file @@ -116,6 +117,34 @@ class VprConstraints { */ int get_route_constraint_num(void) const; + /** + * @brief add packer constraint + * + * @param net_name the packer constraint + */ + void add_packer_constraint(PackerConstraint rc); + + /** + * @brief returns packer constraint by index + * + * @param index the constraint index + */ + const PackerConstraint get_packer_constraint_by_idx(std::size_t index) const; + + /** + * @brief returns packer constraint of a specific net + * + * @param net_name the net name + */ + const PackerConstraint get_packer_constraint_by_net_name(std::string net_name); + + /** + * @brief returns number of packer constraints + * + * @param void + */ + int get_packer_constraint_num(void) const; + private: /** * Store all constrained atoms @@ -131,6 +160,12 @@ class VprConstraints { * store all route constraints */ std::unordered_map route_constraints_; + + /** + * store all packer constraints + */ + std::unordered_map packer_constraints_; + }; ///@brief used to print floorplanning constraints data from a VprConstraints object diff --git a/vpr/src/base/vpr_constraints.xsd b/vpr/src/base/vpr_constraints.xsd index 2ed93b77347..ee81318f600 100644 --- a/vpr/src/base/vpr_constraints.xsd +++ b/vpr/src/base/vpr_constraints.xsd @@ -79,6 +79,26 @@ + + + + + + + + + + + +