[engine] now move rr_gsb mirror function outside the class, because of the circuit_lib should be used
This commit is contained in:
parent
85532dd129
commit
2f84ce5955
|
@ -3,6 +3,7 @@
|
||||||
***********************************************************************/
|
***********************************************************************/
|
||||||
#include "vtr_log.h"
|
#include "vtr_log.h"
|
||||||
#include "vtr_assert.h"
|
#include "vtr_assert.h"
|
||||||
|
#include "rr_gsb_utils.h"
|
||||||
#include "device_rr_gsb.h"
|
#include "device_rr_gsb.h"
|
||||||
|
|
||||||
/* namespace openfpga begins */
|
/* namespace openfpga begins */
|
||||||
|
@ -230,7 +231,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 */
|
/* 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) {
|
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);
|
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, rr_gsb_[ix][iy], unique_module, cb_type)) {
|
||||||
/* This is a mirror, raise the flag and we finish */
|
/* This is a mirror, raise the flag and we finish */
|
||||||
is_unique_module = false;
|
is_unique_module = false;
|
||||||
/* Record the id of unique mirror */
|
/* Record the id of unique mirror */
|
||||||
|
@ -266,7 +267,7 @@ void DeviceRRGSB::build_sb_unique_module(const RRGraph& rr_graph) {
|
||||||
* else the sb is unique
|
* else the sb is unique
|
||||||
*/
|
*/
|
||||||
const RRGSB& unique_module = get_sb_unique_module(id);
|
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, rr_gsb_[ix][iy], unique_module)) {
|
||||||
/* This is a mirror, raise the flag and we finish */
|
/* This is a mirror, raise the flag and we finish */
|
||||||
is_unique_module = false;
|
is_unique_module = false;
|
||||||
/* Record the id of unique mirror */
|
/* Record the id of unique mirror */
|
||||||
|
|
|
@ -55,4 +55,258 @@ std::vector<RRNodeId> get_rr_gsb_chan_node_configurable_driver_nodes(const RRGra
|
||||||
return driver_nodes;
|
return driver_nodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @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 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 (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;
|
||||||
|
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 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) {
|
||||||
|
/* Bypass unrelated segments */
|
||||||
|
if (seg_id != 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, 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check the numbers of ipin_rr_nodes */
|
||||||
|
if (base.get_num_ipin_nodes(side) != cand.get_num_ipin_nodes(side)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** @brief check if a side of candidate SB is a mirror of the current one */
|
||||||
|
static
|
||||||
|
bool is_sb_side_mirror(const RRGraph& rr_graph, 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, 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 */
|
||||||
|
bool is_sb_mirror(const RRGraph& rr_graph, 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, 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
|
||||||
|
*/
|
||||||
|
bool is_cb_node_mirror(const RRGraph& rr_graph,
|
||||||
|
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 (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 = 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 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 == base.chan(chan_side).is_mirror(rr_graph, cand.chan_node(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, base, cand, cb_type, ipin_side[side], inode)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
} /* end namespace openfpga */
|
} /* end namespace openfpga */
|
||||||
|
|
|
@ -23,6 +23,10 @@ std::vector<RRNodeId> get_rr_gsb_chan_node_configurable_driver_nodes(const RRGra
|
||||||
const e_side& chan_side,
|
const e_side& chan_side,
|
||||||
const size_t& track_id);
|
const size_t& track_id);
|
||||||
|
|
||||||
|
bool is_sb_mirror(const RRGraph& rr_graph, const RRGSB& base, const RRGSB& cand);
|
||||||
|
|
||||||
|
bool is_cb_mirror(const RRGraph& rr_graph, const RRGSB& base, const RRGSB& cand, const t_rr_type& cb_type);
|
||||||
|
|
||||||
} /* end namespace openfpga */
|
} /* end namespace openfpga */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -65,6 +65,10 @@ size_t RRGSB::get_max_chan_width() const {
|
||||||
return max_chan_width;
|
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 */
|
/* 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 {
|
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));
|
||||||
|
@ -346,37 +350,6 @@ bool RRGSB::is_sb_node_exist_opposite_side(const RRGraph& rr_graph,
|
||||||
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);
|
|
||||||
|
|
||||||
/* 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 */
|
/* check if the CB exist in this GSB */
|
||||||
bool RRGSB::is_cb_exist(const t_rr_type& cb_type) const {
|
bool RRGSB::is_cb_exist(const t_rr_type& cb_type) const {
|
||||||
/* if channel width is zero, there is no CB */
|
/* 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;
|
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 */
|
/* Public Accessors: Cooridinator conversion */
|
||||||
|
|
||||||
/* get the x coordinate of this GSB */
|
/* 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
|
* 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 {
|
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));
|
||||||
|
|
||||||
|
|
|
@ -66,6 +66,9 @@ class RRGSB {
|
||||||
/* Get the maximum number of routing tracks on all sides */
|
/* Get the maximum number of routing tracks on all sides */
|
||||||
size_t get_max_chan_width() const;
|
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 */
|
/* 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;
|
size_t get_cb_chan_width(const t_rr_type& cb_type) const;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue