experimentally developing through channels inside multi-width and multi-height grids.
Still debugging.
This commit is contained in:
parent
8a996ceae5
commit
610c71671f
|
@ -1590,7 +1590,9 @@ struct t_clock_arch_spec {
|
|||
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;
|
||||
|
|
|
@ -2536,7 +2536,8 @@ static void ProcessLayout(pugi::xml_node layout_tag, t_arch* arch, const pugiuti
|
|||
//Expect only tileable attributes on <layout>
|
||||
//expect_only_attributes(layout_tag, {"tileable"}, loc_data);
|
||||
|
||||
arch->tileable = get_attribute(layout_tag, "tileable", loc_data).as_bool(false);
|
||||
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 <auto_layout> or <fixed_layout> tags
|
||||
size_t auto_layout_cnt = 0;
|
||||
|
|
|
@ -193,7 +193,7 @@
|
|||
</tiles>
|
||||
<!-- ODIN II specific config ends -->
|
||||
<!-- Physical descriptions begin -->
|
||||
<layout tileable="tileable">
|
||||
<layout tileable="true" through_channel="false">
|
||||
<!--auto_layout aspect_ratio="1.0"-->
|
||||
<fixed_layout name="4x4" width="5" height="4">
|
||||
<!--Perimeter of 'io' blocks with 'EMPTY' blocks at corners-->
|
||||
|
|
|
@ -324,6 +324,7 @@ static void SetupRoutingArch(const t_arch& Arch,
|
|||
|
||||
/* 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) {
|
||||
|
|
|
@ -359,7 +359,8 @@ int binary_search_place_and_route(const t_placer_opts& placer_opts_ref,
|
|||
segment_inf,
|
||||
router_opts.base_cost_type,
|
||||
router_opts.trim_empty_channels,
|
||||
router_opts.trim_obs_channels,
|
||||
/* Xifan tang: The trimming on obstacle(through) channel inside multi-height and multi-width grids are not open to command-line options. OpenFPGA opens this options through an XML syntax */
|
||||
router_opts.trim_obs_channels || det_routing_arch->through_channel,
|
||||
router_opts.clock_modeling,
|
||||
arch->Directs, arch->num_directs,
|
||||
&warnings);
|
||||
|
|
|
@ -851,7 +851,8 @@ void vpr_create_rr_graph(t_vpr_setup& vpr_setup, const t_arch& arch, int chan_wi
|
|||
vpr_setup.Segments,
|
||||
router_opts.base_cost_type,
|
||||
router_opts.trim_empty_channels,
|
||||
router_opts.trim_obs_channels,
|
||||
/* Xifan tang: The trimming on obstacle(through) channel inside multi-height and multi-width grids are not open to command-line options. OpenFPGA opens this options through an XML syntax */
|
||||
router_opts.trim_obs_channels || det_routing_arch->through_channel,
|
||||
router_opts.clock_modeling,
|
||||
arch.Directs, arch.num_directs,
|
||||
&warnings);
|
||||
|
|
|
@ -1012,6 +1012,7 @@ struct t_det_routing_arch {
|
|||
|
||||
/* Xifan Tang: tileable routing */
|
||||
bool tileable;
|
||||
bool through_channel;
|
||||
|
||||
short global_route_switch;
|
||||
short delayless_switch;
|
||||
|
|
|
@ -236,7 +236,8 @@ void try_graph(int width_fac, const t_router_opts& router_opts, t_det_routing_ar
|
|||
segment_inf,
|
||||
router_opts.base_cost_type,
|
||||
router_opts.trim_empty_channels,
|
||||
router_opts.trim_obs_channels,
|
||||
/* Xifan tang: The trimming on obstacle(through) channel inside multi-height and multi-width grids are not open to command-line options. OpenFPGA opens this options through an XML syntax */
|
||||
router_opts.trim_obs_channels || det_routing_arch->through_channel,
|
||||
router_opts.clock_modeling,
|
||||
directs, num_directs,
|
||||
&warning_count);
|
||||
|
|
|
@ -366,6 +366,7 @@ void create_rr_graph(const t_graph_type graph_type,
|
|||
base_cost_type,
|
||||
directs, num_directs,
|
||||
&det_routing_arch->wire_to_rr_ipin_switch,
|
||||
trim_obs_channels, /* 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);
|
||||
}
|
||||
|
|
|
@ -212,7 +212,8 @@ bool is_chany_exist(const DeviceGrid& grids,
|
|||
* +-----------------+
|
||||
***********************************************************************/
|
||||
bool is_chanx_right_to_multi_height_grid(const DeviceGrid& grids,
|
||||
const vtr::Point<size_t>& chanx_coord) {
|
||||
const vtr::Point<size_t>& 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,
|
||||
|
@ -221,10 +222,12 @@ bool is_chanx_right_to_multi_height_grid(const DeviceGrid& grids,
|
|||
return true;
|
||||
}
|
||||
|
||||
/* We check the left neighbor of chanx, if it does not exist, the chanx is left to a multi-height grid */
|
||||
vtr::Point<size_t> left_chanx_coord(chanx_coord.x() - 1, chanx_coord.y());
|
||||
if (false == is_chanx_exist(grids, left_chanx_coord)) {
|
||||
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<size_t> left_chanx_coord(chanx_coord.x() - 1, chanx_coord.y());
|
||||
if (false == is_chanx_exist(grids, left_chanx_coord)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -244,7 +247,8 @@ 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<size_t>& chanx_coord) {
|
||||
const vtr::Point<size_t>& 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,
|
||||
|
@ -253,10 +257,13 @@ bool is_chanx_left_to_multi_height_grid(const DeviceGrid& grids,
|
|||
return true;
|
||||
}
|
||||
|
||||
/* We check the right neighbor of chanx, if it does not exist, the chanx is left to a multi-height grid */
|
||||
vtr::Point<size_t> right_chanx_coord(chanx_coord.x() + 1, chanx_coord.y());
|
||||
if (false == is_chanx_exist(grids, right_chanx_coord)) {
|
||||
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<size_t> right_chanx_coord(chanx_coord.x() + 1, chanx_coord.y());
|
||||
if (false == is_chanx_exist(grids, right_chanx_coord)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -281,7 +288,8 @@ 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<size_t>& chany_coord) {
|
||||
const vtr::Point<size_t>& 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,
|
||||
|
@ -290,10 +298,12 @@ bool is_chany_top_to_multi_width_grid(const DeviceGrid& grids,
|
|||
return true;
|
||||
}
|
||||
|
||||
/* We check the bottom neighbor of chany, if it does not exist, the chany is left to a multi-height grid */
|
||||
vtr::Point<size_t> bottom_chany_coord(chany_coord.x(), chany_coord.y() - 1);
|
||||
if (false == is_chany_exist(grids, bottom_chany_coord)) {
|
||||
return true;
|
||||
if (false == through_channel) {
|
||||
/* We check the bottom neighbor of chany, if it does not exist, the chany is left to a multi-height grid */
|
||||
vtr::Point<size_t> bottom_chany_coord(chany_coord.x(), chany_coord.y() - 1);
|
||||
if (false == is_chany_exist(grids, bottom_chany_coord)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -318,7 +328,8 @@ 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<size_t>& chany_coord) {
|
||||
const vtr::Point<size_t>& 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,
|
||||
|
@ -327,10 +338,12 @@ bool is_chany_bottom_to_multi_width_grid(const DeviceGrid& grids,
|
|||
return true;
|
||||
}
|
||||
|
||||
/* We check the top neighbor of chany, if it does not exist, the chany is left to a multi-height grid */
|
||||
vtr::Point<size_t> top_chany_coord(chany_coord.x(), chany_coord.y() + 1);
|
||||
if (false == is_chany_exist(grids, top_chany_coord)) {
|
||||
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<size_t> top_chany_coord(chany_coord.x(), chany_coord.y() + 1);
|
||||
if (false == is_chany_exist(grids, top_chany_coord)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
|
@ -46,16 +46,20 @@ bool is_chany_exist(const DeviceGrid& grids,
|
|||
const vtr::Point<size_t>& chany_coord);
|
||||
|
||||
bool is_chanx_right_to_multi_height_grid(const DeviceGrid& grids,
|
||||
const vtr::Point<size_t>& chanx_coord);
|
||||
const vtr::Point<size_t>& chanx_coord,
|
||||
const bool& through_channel);
|
||||
|
||||
bool is_chanx_left_to_multi_height_grid(const DeviceGrid& grids,
|
||||
const vtr::Point<size_t>& chanx_coord);
|
||||
const vtr::Point<size_t>& chanx_coord,
|
||||
const bool& through_channel);
|
||||
|
||||
bool is_chany_top_to_multi_width_grid(const DeviceGrid& grids,
|
||||
const vtr::Point<size_t>& chany_coord);
|
||||
const vtr::Point<size_t>& chany_coord,
|
||||
const bool& through_channel);
|
||||
|
||||
bool is_chany_bottom_to_multi_width_grid(const DeviceGrid& grids,
|
||||
const vtr::Point<size_t>& chany_coord);
|
||||
const vtr::Point<size_t>& chany_coord,
|
||||
const bool& through_channel);
|
||||
|
||||
short get_rr_node_actual_track_id(const RRGraph& rr_graph,
|
||||
const RRNodeId& track_rr_node,
|
||||
|
|
|
@ -83,6 +83,7 @@ void build_tileable_unidir_rr_graph(const std::vector<t_physical_tile_type>& typ
|
|||
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) {
|
||||
|
||||
|
@ -149,7 +150,8 @@ void build_tileable_unidir_rr_graph(const std::vector<t_physical_tile_type>& typ
|
|||
rr_node_driver_switches,
|
||||
grids,
|
||||
device_chan_width,
|
||||
segment_inf);
|
||||
segment_inf,
|
||||
through_channel);
|
||||
|
||||
/************************
|
||||
* Create all the rr_nodes
|
||||
|
@ -161,7 +163,8 @@ void build_tileable_unidir_rr_graph(const std::vector<t_physical_tile_type>& typ
|
|||
device_chan_width,
|
||||
segment_inf,
|
||||
wire_to_ipin_rr_switch,
|
||||
delayless_rr_switch);
|
||||
delayless_rr_switch,
|
||||
through_channel);
|
||||
|
||||
/************************************************************************
|
||||
* Create the connectivity of OPINs
|
||||
|
|
|
@ -30,6 +30,7 @@ void build_tileable_unidir_rr_graph(const std::vector<t_physical_tile_type>& typ
|
|||
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);
|
||||
|
||||
|
|
|
@ -177,26 +177,27 @@ 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<t_segment_inf>& segment_infs) {
|
||||
const std::vector<t_segment_inf>& 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<size_t> chanx_coord(ix, iy);
|
||||
|
||||
/* Bypass if the routing channel does not exist */
|
||||
/* Bypass if the routing channel does not exist when through channels are not allowed */
|
||||
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)) {
|
||||
if (true == is_chanx_right_to_multi_height_grid(grids, chanx_coord, through_channel)) {
|
||||
force_start = true;
|
||||
}
|
||||
|
||||
|
@ -204,7 +205,7 @@ size_t estimate_num_chanx_rr_nodes(const DeviceGrid& grids,
|
|||
* - 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)) {
|
||||
if (true == is_chanx_left_to_multi_height_grid(grids, chanx_coord, through_channel)) {
|
||||
force_end = true;
|
||||
}
|
||||
|
||||
|
@ -228,14 +229,15 @@ size_t estimate_num_chanx_rr_nodes(const DeviceGrid& grids,
|
|||
static
|
||||
size_t estimate_num_chany_rr_nodes(const DeviceGrid& grids,
|
||||
const size_t& chan_width,
|
||||
const std::vector<t_segment_inf>& segment_infs) {
|
||||
const std::vector<t_segment_inf>& 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<size_t> chany_coord(ix, iy);
|
||||
|
||||
/* Bypass if the routing channel does not exist */
|
||||
/* Bypass if the routing channel does not exist when through channels are not allowed */
|
||||
if (false == is_chany_exist(grids, chany_coord)) {
|
||||
continue;
|
||||
}
|
||||
|
@ -247,7 +249,7 @@ size_t estimate_num_chany_rr_nodes(const DeviceGrid& grids,
|
|||
* - 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)) {
|
||||
if (true == is_chany_top_to_multi_width_grid(grids, chany_coord, through_channel)) {
|
||||
force_start = true;
|
||||
}
|
||||
|
||||
|
@ -255,7 +257,7 @@ size_t estimate_num_chany_rr_nodes(const DeviceGrid& grids,
|
|||
* - 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)) {
|
||||
if (true == is_chany_bottom_to_multi_width_grid(grids, chany_coord, through_channel)) {
|
||||
force_end = true;
|
||||
}
|
||||
|
||||
|
@ -276,7 +278,8 @@ size_t estimate_num_chany_rr_nodes(const DeviceGrid& grids,
|
|||
static
|
||||
std::vector<size_t> estimate_num_rr_nodes(const DeviceGrid& grids,
|
||||
const vtr::Point<size_t>& chan_width,
|
||||
const std::vector<t_segment_inf>& segment_infs) {
|
||||
const std::vector<t_segment_inf>& segment_infs,
|
||||
const bool& through_channel) {
|
||||
|
||||
/* Reset the OPIN, IPIN, SOURCE, SINK counter to be zero */
|
||||
std::vector<size_t> num_rr_nodes_per_type(NUM_RR_TYPES, 0);
|
||||
|
@ -304,8 +307,14 @@ std::vector<size_t> 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);
|
||||
num_rr_nodes_per_type[CHANY] = estimate_num_chany_rr_nodes(grids, chan_width.y(), segment_infs);
|
||||
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;
|
||||
}
|
||||
|
@ -321,10 +330,14 @@ void alloc_tileable_rr_graph_nodes(RRGraph& rr_graph,
|
|||
vtr::vector<RRNodeId, RRSwitchId>& rr_node_driver_switches,
|
||||
const DeviceGrid& grids,
|
||||
const vtr::Point<size_t>& chan_width,
|
||||
const std::vector<t_segment_inf>& segment_infs) {
|
||||
const std::vector<t_segment_inf>& segment_infs,
|
||||
const bool& through_channel) {
|
||||
VTR_ASSERT(0 == rr_graph.nodes().size());
|
||||
|
||||
std::vector<size_t> num_rr_nodes_per_type = estimate_num_rr_nodes(grids, chan_width, segment_infs);
|
||||
std::vector<size_t> 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;
|
||||
|
@ -764,7 +777,8 @@ void load_chanx_rr_nodes_basic_info(RRGraph& rr_graph,
|
|||
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) {
|
||||
const std::vector<t_segment_inf>& segment_infs,
|
||||
const bool& through_channel) {
|
||||
|
||||
/* For X-direction Channel: CHANX */
|
||||
for (size_t iy = 0; iy < grids.height() - 1; ++iy) {
|
||||
|
@ -774,8 +788,9 @@ void load_chanx_rr_nodes_basic_info(RRGraph& rr_graph,
|
|||
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)) {
|
||||
/* 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;
|
||||
}
|
||||
|
||||
|
@ -786,7 +801,7 @@ void load_chanx_rr_nodes_basic_info(RRGraph& rr_graph,
|
|||
* - 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)) {
|
||||
if (true == is_chanx_right_to_multi_height_grid(grids, chanx_coord, through_channel)) {
|
||||
force_start = true;
|
||||
}
|
||||
|
||||
|
@ -794,7 +809,7 @@ void load_chanx_rr_nodes_basic_info(RRGraph& rr_graph,
|
|||
* - 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)) {
|
||||
if (true == is_chanx_left_to_multi_height_grid(grids, chanx_coord, through_channel)) {
|
||||
force_end = true;
|
||||
}
|
||||
|
||||
|
@ -810,21 +825,35 @@ void load_chanx_rr_nodes_basic_info(RRGraph& rr_graph,
|
|||
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
|
||||
/* 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
|
||||
* | |
|
||||
*/
|
||||
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);
|
||||
if (true == is_chanx_exist(grids, chanx_coord)) {
|
||||
/* 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);
|
||||
|
@ -855,7 +884,8 @@ void load_chany_rr_nodes_basic_info(RRGraph& rr_graph,
|
|||
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) {
|
||||
const std::vector<t_segment_inf>& segment_infs,
|
||||
const bool& through_channel) {
|
||||
|
||||
/* For Y-direction Channel: CHANY */
|
||||
for (size_t ix = 0; ix < grids.width() - 1; ++ix) {
|
||||
|
@ -865,8 +895,9 @@ void load_chany_rr_nodes_basic_info(RRGraph& rr_graph,
|
|||
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)) {
|
||||
/* 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;
|
||||
}
|
||||
|
||||
|
@ -877,7 +908,7 @@ void load_chany_rr_nodes_basic_info(RRGraph& rr_graph,
|
|||
* - 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)) {
|
||||
if (true == is_chany_top_to_multi_width_grid(grids, chany_coord, through_channel)) {
|
||||
force_start = true;
|
||||
}
|
||||
|
||||
|
@ -885,7 +916,7 @@ void load_chany_rr_nodes_basic_info(RRGraph& rr_graph,
|
|||
* - 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)) {
|
||||
if (true == is_chany_bottom_to_multi_width_grid(grids, chany_coord, through_channel)) {
|
||||
force_end = true;
|
||||
}
|
||||
|
||||
|
@ -901,21 +932,37 @@ void load_chany_rr_nodes_basic_info(RRGraph& rr_graph,
|
|||
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
|
||||
|
||||
/* 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
|
||||
*/
|
||||
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);
|
||||
if (true == is_chany_exist(grids, chany_coord)) {
|
||||
/* 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);
|
||||
|
@ -969,7 +1016,8 @@ void create_tileable_rr_graph_nodes(RRGraph& rr_graph,
|
|||
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) {
|
||||
const RRSwitchId& delayless_switch,
|
||||
const bool& through_channel) {
|
||||
load_grid_nodes_basic_info(rr_graph,
|
||||
rr_node_driver_switches,
|
||||
grids,
|
||||
|
@ -981,14 +1029,16 @@ void create_tileable_rr_graph_nodes(RRGraph& rr_graph,
|
|||
rr_node_track_ids,
|
||||
grids,
|
||||
chan_width.x(),
|
||||
segment_infs);
|
||||
segment_infs,
|
||||
through_channel);
|
||||
|
||||
load_chany_rr_nodes_basic_info(rr_graph,
|
||||
rr_node_driver_switches,
|
||||
rr_node_track_ids,
|
||||
grids,
|
||||
chan_width.y(),
|
||||
segment_infs);
|
||||
segment_infs,
|
||||
through_channel);
|
||||
|
||||
reverse_dec_chan_rr_node_track_ids(rr_graph,
|
||||
rr_node_track_ids);
|
||||
|
|
|
@ -25,7 +25,8 @@ void alloc_tileable_rr_graph_nodes(RRGraph& rr_graph,
|
|||
vtr::vector<RRNodeId, RRSwitchId>& driver_switches,
|
||||
const DeviceGrid& grids,
|
||||
const vtr::Point<size_t>& chan_width,
|
||||
const std::vector<t_segment_inf>& segment_infs);
|
||||
const std::vector<t_segment_inf>& segment_infs,
|
||||
const bool& through_channel);
|
||||
|
||||
void create_tileable_rr_graph_nodes(RRGraph& rr_graph,
|
||||
vtr::vector<RRNodeId, RRSwitchId>& rr_node_driver_switches,
|
||||
|
@ -34,7 +35,8 @@ void create_tileable_rr_graph_nodes(RRGraph& rr_graph,
|
|||
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);
|
||||
const RRSwitchId& delayless_switch,
|
||||
const bool& through_channel);
|
||||
|
||||
|
||||
} /* end namespace openfpga */
|
||||
|
|
Loading…
Reference in New Issue