Merge branch 'refactoring' into dev

This commit is contained in:
tangxifan 2020-03-05 21:25:36 -07:00
commit ee4d5e46a0
6 changed files with 448 additions and 6 deletions

View File

@ -0,0 +1,169 @@
/************************************************************************
* This file contains functions that are used to build edges
* between nodes of a tileable routing resource graph
***********************************************************************/
#include <algorithm>
/* 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<RRNodeId, RRSwitchId>& 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<RRNodeId, RRSwitchId>& 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<RRNodeId, RRSwitchId>& rr_node_driver_switches,
const DeviceGrid& grids,
const vtr::Point<size_t>& device_chan_width,
const std::vector<t_segment_inf>& segment_inf,
int** Fc_in, int** 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<size_t> 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<size_t> 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<t_direct_inf>& directs,
const std::vector<t_clb_to_clb_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<size_t> 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 */

View File

@ -0,0 +1,42 @@
#ifndef TILEABLE_RR_GRAPH_EDGE_BUILDER_H
#define TILEABLE_RR_GRAPH_EDGE_BUILDER_H
/********************************************************************
* Include header files that are required by function declaration
*******************************************************************/
#include <vector>
/* Headers from vtrutil library */
#include "vtr_geometry.h"
#include "physical_types.h"
#include "device_grid.h"
#include "rr_graph_obj.h"
#include "clb2clb_directs.h"
/********************************************************************
* Function declaration
*******************************************************************/
/* begin namespace openfpga */
namespace openfpga {
void build_rr_graph_edges(RRGraph& rr_graph,
const vtr::vector<RRNodeId, RRSwitchId>& rr_node_driver_switches,
const DeviceGrid& grids,
const vtr::Point<size_t>& device_chan_width,
const std::vector<t_segment_inf>& segment_inf,
int** Fc_in, int** 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(RRGraph& rr_graph,
const DeviceGrid& grids,
const RRSwitchId& delayless_switch,
const std::vector<t_direct_inf>& directs,
const std::vector<t_clb_to_clb_directs>& clb_to_clb_directs);
} /* end namespace openfpga */
#endif

View File

@ -620,7 +620,7 @@ RRChan build_one_tileable_rr_chan(const vtr::Point<size_t>& chan_coordinate,
***********************************************************************/
RRGSB build_one_tileable_rr_gsb(const DeviceGrid& grids,
const RRGraph& rr_graph,
const std::vector<size_t>& device_chan_width,
const vtr::Point<size_t>& device_chan_width,
const std::vector<t_segment_inf>& segment_inf,
const vtr::Point<size_t>& gsb_coordinate) {
/* Create an object to return */
@ -650,9 +650,9 @@ RRGSB build_one_tileable_rr_gsb(const DeviceGrid& grids,
/* 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[0], grids.width() - 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[1], grids.height() - 1,
ChanNodeDetails chany_details = build_unidir_chan_node_details(device_chan_width.y(), grids.height() - 1,
false, false, segment_inf);
switch (side) {
@ -907,7 +907,7 @@ void build_edges_for_one_tileable_rr_gsb(RRGraph& rr_graph,
const t_track2pin_map& track2ipin_map,
const t_pin2track_map& opin2track_map,
const t_track2track_map& track2track_map,
const vtr::vector<RRNodeId, RRSwitchId> rr_node_driver_switches) {
const vtr::vector<RRNodeId, RRSwitchId>& rr_node_driver_switches) {
/* Walk through each sides */
for (size_t side = 0; side < rr_gsb.get_num_sides(); ++side) {

View File

@ -44,7 +44,7 @@ t_track2track_map build_gsb_track_to_track_map(const RRGraph& rr_graph,
RRGSB build_one_tileable_rr_gsb(const DeviceGrid& grids,
const RRGraph& rr_graph,
const std::vector<size_t>& device_chan_width,
const vtr::Point<size_t>& device_chan_width,
const std::vector<t_segment_inf>& segment_inf,
const vtr::Point<size_t>& gsb_coordinate);
@ -53,7 +53,7 @@ void build_edges_for_one_tileable_rr_gsb(RRGraph& rr_graph,
const t_track2pin_map& track2ipin_map,
const t_pin2track_map& opin2track_map,
const t_track2track_map& track2track_map,
const vtr::vector<RRNodeId, RRSwitchId> rr_node_driver_switches);
const vtr::vector<RRNodeId, RRSwitchId>& rr_node_driver_switches);
t_track2pin_map build_gsb_track_to_ipin_map(const RRGraph& rr_graph,
const RRGSB& rr_gsb,

View File

@ -738,12 +738,222 @@ void load_one_chan_rr_nodes_basic_info(RRGraph& rr_graph,
}
}
/************************************************************************
* 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(RRGraph& rr_graph,
vtr::vector<RRNodeId, RRSwitchId>& rr_node_driver_switches,
std::map<RRNodeId, std::vector<size_t>>& rr_node_track_ids,
const DeviceGrid& grids,
const size_t& chan_width,
const std::vector<t_segment_inf>& segment_infs) {
/* 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<size_t> track_node_ids;
for (size_t ix = 1; ix < grids.width() - 1; ++ix) {
vtr::Point<size_t> chanx_coord(ix, iy);
/* Bypass if the routing channel does not exist */
if (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)) {
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)) {
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);
/* 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, INC_DIRECTION, 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, DEC_DIRECTION, 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_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(RRGraph& rr_graph,
vtr::vector<RRNodeId, RRSwitchId>& rr_node_driver_switches,
std::map<RRNodeId, std::vector<size_t>>& rr_node_track_ids,
const DeviceGrid& grids,
const size_t& chan_width,
const std::vector<t_segment_inf>& segment_infs) {
/* 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<size_t> track_node_ids;
for (size_t iy = 1; iy < grids.height() - 1; ++iy) {
vtr::Point<size_t> chany_coord(ix, iy);
/* Bypass if the routing channel does not exist */
if (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)) {
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)) {
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 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 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);
/* 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, INC_DIRECTION, 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, DEC_DIRECTION, 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_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 RRGraph& rr_graph,
std::map<RRNodeId, std::vector<size_t>>& rr_node_track_ids) {
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 (DEC_DIRECTION != 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(RRGraph& rr_graph,
vtr::vector<RRNodeId, RRSwitchId>& rr_node_driver_switches,
std::map<RRNodeId, std::vector<size_t>>& rr_node_track_ids,
const DeviceGrid& grids,
const vtr::Point<size_t>& chan_width,
const std::vector<t_segment_inf>& segment_infs,
const RRSwitchId& wire_to_ipin_switch,
const RRSwitchId& delayless_switch) {
load_grid_nodes_basic_info(rr_graph,
@ -752,6 +962,23 @@ void create_tileable_rr_graph_nodes(RRGraph& rr_graph,
wire_to_ipin_switch,
delayless_switch);
load_chanx_rr_nodes_basic_info(rr_graph,
rr_node_driver_switches,
rr_node_track_ids,
grids,
chan_width.x(),
segment_infs);
load_chany_rr_nodes_basic_info(rr_graph,
rr_node_driver_switches,
rr_node_track_ids,
grids,
chan_width.y(),
segment_infs);
reverse_dec_chan_rr_node_track_ids(rr_graph,
rr_node_track_ids);
}
} /* end namespace openfpga */

View File

@ -29,10 +29,14 @@ void alloc_tileable_rr_graph_nodes(RRGraph& rr_graph,
void create_tileable_rr_graph_nodes(RRGraph& rr_graph,
vtr::vector<RRNodeId, RRSwitchId>& rr_node_driver_switches,
std::map<RRNodeId, std::vector<size_t>>& rr_node_track_ids,
const DeviceGrid& grids,
const vtr::Point<size_t>& chan_width,
const std::vector<t_segment_inf>& segment_infs,
const RRSwitchId& wire_to_ipin_switch,
const RRSwitchId& delayless_switch);
} /* end namespace openfpga */
#endif