Merge pull request #766 from lnis-uofu/rr_gsb_mirror

Now switch_id is no longer a metric to fail GSB mirrorable functions but circuit model is.
This commit is contained in:
Ganesh Gore 2022-09-06 22:58:37 -06:00 committed by GitHub
commit 65d7f592c9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 354 additions and 330 deletions

View File

@ -3,6 +3,7 @@
***********************************************************************/
#include "vtr_log.h"
#include "vtr_assert.h"
#include "rr_gsb_utils.h"
#include "device_rr_gsb.h"
/* namespace openfpga begins */
@ -11,6 +12,9 @@ namespace openfpga {
/************************************************************************
* Constructors
***********************************************************************/
DeviceRRGSB::DeviceRRGSB(const VprDeviceAnnotation& device_annotation)
: device_annotation_(device_annotation) {
}
/************************************************************************
* Public accessors
@ -230,7 +234,7 @@ void DeviceRRGSB::build_cb_unique_module(const RRGraph& rr_graph, const t_rr_typ
/* Traverse the unique_mirror list and check it is an mirror of another */
for (size_t id = 0; id < get_num_cb_unique_module(cb_type); ++id) {
const RRGSB& unique_module = get_cb_unique_module(cb_type, id);
if (true == rr_gsb_[ix][iy].is_cb_mirror(rr_graph, unique_module, cb_type)) {
if (true == is_cb_mirror(rr_graph, device_annotation_, rr_gsb_[ix][iy], unique_module, cb_type)) {
/* This is a mirror, raise the flag and we finish */
is_unique_module = false;
/* Record the id of unique mirror */
@ -266,7 +270,7 @@ void DeviceRRGSB::build_sb_unique_module(const RRGraph& rr_graph) {
* else the sb is unique
*/
const RRGSB& unique_module = get_sb_unique_module(id);
if (true == rr_gsb_[ix][iy].is_sb_mirror(rr_graph, unique_module)) {
if (true == is_sb_mirror(rr_graph, device_annotation_, rr_gsb_[ix][iy], unique_module)) {
/* This is a mirror, raise the flag and we finish */
is_unique_module = false;
/* Record the id of unique mirror */

View File

@ -11,6 +11,7 @@
#include "rr_graph_obj.h"
#include "rr_gsb.h"
#include "vpr_device_annotation.h"
/* namespace openfpga begins */
namespace openfpga {
@ -26,6 +27,7 @@ namespace openfpga {
*******************************************************************/
class DeviceRRGSB {
public: /* Contructors */
DeviceRRGSB(const VprDeviceAnnotation& device_annotation);
public: /* Accessors */
vtr::Point<size_t> get_gsb_range() const; /* get the max coordinate of the switch block array */
const RRGSB& get_gsb(const vtr::Point<size_t>& coordinate) const; /* Get a rr switch block in the array with a coordinate */
@ -84,6 +86,9 @@ class DeviceRRGSB {
std::vector<std::vector<size_t>> cby_unique_module_id_; /* A map from rr_gsb to its unique mirror */
std::vector<vtr::Point<size_t>> cby_unique_module_; /* For each side of connection block, we identify a list of unique modules based on its connection. This is a matrix [0..num_module] */
/* Cached data */
const VprDeviceAnnotation& device_annotation_;
};
} /* End namespace openfpga*/

View File

@ -124,7 +124,7 @@ class OpenfpgaContext : public Context {
openfpga::VprBitstreamAnnotation vpr_bitstream_annotation_;
/* Device-level annotation */
openfpga::DeviceRRGSB device_rr_gsb_;
openfpga::DeviceRRGSB device_rr_gsb_{vpr_device_annotation_};
/* Library of physical implmentation of routing multiplexers */
openfpga::MuxLibrary mux_lib_;

View File

@ -4,6 +4,7 @@
*******************************************************************/
/* Headers from vtrutil library */
#include "vtr_assert.h"
#include "vtr_log.h"
/* Headers from openfpgautil library */
#include "openfpga_side_manager.h"
@ -55,4 +56,326 @@ std::vector<RRNodeId> get_rr_gsb_chan_node_configurable_driver_nodes(const RRGra
return driver_nodes;
}
/** @brief Evaluate if two routing channels are mirror to each other */
static
bool is_chan_mirror(const RRGraph& rr_graph,
const VprDeviceAnnotation& device_annotation,
const RRChan& base,
const RRChan& cand) {
/* If any following element does not match, it is not mirror */
/* 1. type */
if (base.get_type() != cand.get_type()) {
return false;
}
/* 2. track_width */
if (base.get_chan_width() != cand.get_chan_width()) {
return false;
}
/* 3. for each node */
for (size_t inode = 0; inode < base.get_chan_width(); ++inode) {
/* 3.1 check node type */
if (rr_graph.node_type(base.get_node(inode)) != rr_graph.node_type(cand.get_node(inode))) {
return false;
}
/* 3.2 check node directionality */
if (rr_graph.node_direction(base.get_node(inode)) != rr_graph.node_direction(cand.get_node(inode))) {
return false;
}
/* 3.3 check node segment */
/* FIXME: Maybe this is too tight! Consider to remove the restrictions on segments */
if (device_annotation.rr_segment_circuit_model(base.get_node_segment(inode)) != device_annotation.rr_segment_circuit_model(cand.get_node_segment(inode))) {
return false;
}
}
return true;
}
/** @brief check if two rr_nodes in two GSBs 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
*/
static
bool is_sb_node_mirror(const RRGraph& rr_graph,
const VprDeviceAnnotation& device_annotation,
const RRGSB& base,
const RRGSB& cand,
const e_side& node_side,
const size_t& track_id) {
/* Ensure rr_nodes are either the output of short-connection or multiplexer */
bool is_short_conkt = base.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<RREdgeId> node_in_edges = base.get_chan_node_in_edges(rr_graph, node_side, track_id);
std::vector<RREdgeId> 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 (device_annotation.rr_switch_circuit_model(rr_graph.edge_switch(src_edge)) != device_annotation.rr_switch_circuit_model(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;
base.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;
}
/** @brief Check if all the routing segments of a side of candidate SB is a mirror of the current one */
static
bool is_sb_side_segment_mirror(const RRGraph& rr_graph,
const VprDeviceAnnotation& device_annotation,
const RRGSB& base,
const RRGSB& cand,
const e_side& side,
const RRSegmentId& seg_id) {
/* Create a side manager */
SideManager side_manager(side);
/* Make sure both Switch blocks has this side!!! */
VTR_ASSERT ( side_manager.to_size_t() < base.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 (base.get_chan_width(side) != cand.get_chan_width(side)) {
return false;
}
for (size_t itrack = 0; itrack < base.get_chan_width(side); ++itrack) {
/* FIXME: Maybe this is too tight! Consider to remove the restrictions on segments */
if (device_annotation.rr_segment_circuit_model(seg_id) != device_annotation.rr_segment_circuit_model(base.get_chan_node_segment(side, itrack))) {
continue;
}
/* Check the directionality of each node */
if (base.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 != base.get_chan_node_direction(side, itrack)) {
continue; /* skip IN_PORT */
}
if (false == is_sb_node_mirror(rr_graph, device_annotation, base, cand, side, itrack)) {
return false;
}
}
/* check the numbers of opin_rr_nodes */
if (base.get_num_opin_nodes(side) != cand.get_num_opin_nodes(side)) {
return false;
}
return true;
}
/** @brief 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!
*/
static
bool is_sb_side_mirror(const RRGraph& rr_graph,
const VprDeviceAnnotation& device_annotation,
const RRGSB& base,
const RRGSB& cand,
const e_side& side) {
/* get a list of segments */
std::vector<RRSegmentId> seg_ids = base.get_chan_segment_ids(side);
for (size_t iseg = 0; iseg < seg_ids.size(); ++iseg) {
if (false == is_sb_side_segment_mirror(rr_graph, device_annotation, base, cand, side, seg_ids[iseg])) {
return false;
}
}
return true;
}
/** @brief Identify if the Switch Block part of two GSBs are mirror (same in structure) or not. Return true if so, otherwise return false
* 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 VprDeviceAnnotation& device_annotation,
const RRGSB& base,
const RRGSB& cand) {
/* check the numbers of sides */
if (base.get_num_sides() != cand.get_num_sides()) {
return false;
}
/* check the numbers/directionality of channel rr_nodes */
for (size_t side = 0; side < base.get_num_sides(); ++side) {
SideManager side_manager(side);
if (false == is_sb_side_mirror(rr_graph, device_annotation, base, cand, side_manager.get_side())) {
return false;
}
}
return true;
}
/** @brief 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
*/
static
bool is_cb_node_mirror(const RRGraph& rr_graph,
const VprDeviceAnnotation& device_annotation,
const RRGSB& base,
const RRGSB& cand,
const t_rr_type& cb_type,
const e_side& node_side,
const size_t& node_id) {
/* Ensure rr_nodes are either the output of short-connection or multiplexer */
RRNodeId node = base.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<RREdgeId> node_in_edges;
for (const RREdgeId& edge : rr_graph.node_in_edges(node)) {
node_in_edges.push_back(edge);
}
std::vector<RREdgeId> 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 (device_annotation.rr_switch_circuit_model(rr_graph.edge_switch(src_edge)) != device_annotation.rr_switch_circuit_model(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 = base.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 = base.get_chan_node_index(chan_side, src_node);
des_node_id = cand.get_chan_node_index(chan_side, src_cand_node);
break;
case OPIN:
base.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;
}
/** @brief Check if the candidate CB is a mirror of the current baselien */
bool is_cb_mirror(const RRGraph& rr_graph,
const VprDeviceAnnotation& device_annotation,
const RRGSB& base,
const RRGSB& cand,
const t_rr_type& cb_type) {
/* Check if channel width is the same */
if ( base.get_cb_chan_width(cb_type) != cand.get_cb_chan_width(cb_type) ) {
return false;
}
enum e_side chan_side = base.get_cb_chan_side(cb_type);
/* check the numbers/directionality of channel rr_nodes */
if ( false == is_chan_mirror(rr_graph, device_annotation, base.chan(chan_side), cand.chan(chan_side)) ) {
return false;
}
/* check the equivalence of ipins */
std::vector<enum e_side> ipin_side = base.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 ( base.get_num_ipin_nodes(ipin_side[side]) != cand.get_num_ipin_nodes(ipin_side[side]) ) {
return false;
}
for (size_t inode = 0; inode < base.get_num_ipin_nodes(ipin_side[side]); ++inode) {
if (false == is_cb_node_mirror(rr_graph, device_annotation, base, cand, cb_type, ipin_side[side], inode)) {
return false;
}
}
}
return true;
}
} /* end namespace openfpga */

View File

@ -7,6 +7,7 @@
#include <string>
#include <vector>
#include "rr_gsb.h"
#include "vpr_device_annotation.h"
/********************************************************************
* Function declaration
@ -23,6 +24,17 @@ std::vector<RRNodeId> get_rr_gsb_chan_node_configurable_driver_nodes(const RRGra
const e_side& chan_side,
const size_t& track_id);
bool is_sb_mirror(const RRGraph& rr_graph,
const VprDeviceAnnotation& device_annotation,
const RRGSB& base,
const RRGSB& cand);
bool is_cb_mirror(const RRGraph& rr_graph,
const VprDeviceAnnotation& device_annotation,
const RRGSB& base,
const RRGSB& cand,
const t_rr_type& cb_type);
} /* end namespace openfpga */
#endif

View File

@ -69,36 +69,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 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<RRSegmentId> RRChan::get_segment_ids() const {
std::vector<RRSegmentId> seg_list;

View File

@ -51,7 +51,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 RRGraph& rr_graph, const RRChan& cand) const; /* evaluate if two RR_chan is mirror to each other */
std::vector<RRSegmentId> get_segment_ids() const; /* Get a list of segments used in this routing channel */
std::vector<size_t> get_node_ids_by_segment_ids(const RRSegmentId& seg_id) const; /* Get a list of segments used in this routing channel */
public: /* Mutators */

View File

@ -65,6 +65,10 @@ size_t RRGSB::get_max_chan_width() const {
return max_chan_width;
}
const RRChan& RRGSB::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));
@ -346,37 +350,6 @@ bool RRGSB::is_sb_node_exist_opposite_side(const RRGraph& rr_graph,
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<enum e_side> 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 */
@ -495,89 +468,6 @@ bool RRGSB::is_sb_mirrorable(const RRGraph& rr_graph, const RRGSB& cand) const {
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<RRSegmentId> 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 */
@ -940,143 +830,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 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<RREdgeId> node_in_edges = get_chan_node_in_edges(rr_graph, node_side, track_id);
std::vector<RREdgeId> 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<RREdgeId> node_in_edges;
for (const RREdgeId& edge : rr_graph.node_in_edges(node)) {
node_in_edges.push_back(edge);
}
std::vector<RREdgeId> 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));

View File

@ -66,6 +66,9 @@ class RRGSB {
/* Get the maximum number of routing tracks on all sides */
size_t get_max_chan_width() const;
/* Return read-only object of the routing channels with a given side */
const RRChan& chan(const e_side& chan_side) 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;
@ -118,9 +121,6 @@ class RRGSB {
/* 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;
@ -135,37 +135,6 @@ class RRGSB {
*/
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 */
@ -231,17 +200,6 @@ class RRGSB {
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 */