fixed bugs for UNIVERSAL and WILTON switch blocks

This commit is contained in:
tangxifan 2019-06-25 14:15:29 -06:00
parent a88263a4c2
commit 4d3b5f12b4
7 changed files with 196 additions and 215 deletions

View File

@ -150,7 +150,7 @@
<!-- ODIN II specific config ends -->
<!-- Physical descriptions begin -->
<layout auto="1.0"/>
<layout auto="1.0" tileable_routing="off"/>
<spice_settings>
<parameters>
<options sim_temp="25" post="off" captab="off" fast="on"/>

View File

@ -255,6 +255,91 @@ void add_one_edge_for_two_rr_nodes(const t_rr_graph* rr_graph,
return;
}
/************************************************************************
* Add a set of edges for a source rr_node
* For src rr_node, update the edge list and update switch_id,
* For des rr_node, update the fan_in
***********************************************************************/
void add_edges_for_two_rr_nodes(const t_rr_graph* rr_graph,
const int src_rr_node_id,
const std::vector<int> des_rr_node_ids,
const std::vector<short> driver_switches) {
/* Check src_rr_node id is in range */
assert ( (-1 < src_rr_node_id) && (src_rr_node_id < rr_graph->num_rr_nodes) );
t_rr_node* src_rr_node = &(rr_graph->rr_node[src_rr_node_id]);
/* Check des_rr_node and driver_switches should match in size */
assert ( des_rr_node_ids.size() == driver_switches.size() );
/* Get a stamp of the current num_edges of src_rr_node */
int start_edge_id = src_rr_node->num_edges;
/* To avoid adding redundant edges,
* we will search the edge list and
* check if each des_rr_node_id already exists
* We rebuild a vector des_rr_node_ids_to_add where redundancy is removed
*/
std::vector<int> des_rr_node_ids_to_add;
std::vector<short> driver_switches_to_add;
for (size_t inode = 0; inode < des_rr_node_ids.size(); ++inode) {
/* search */
bool is_redundant = false;
for (int iedge = 0; iedge < src_rr_node->num_edges; ++iedge) {
if (des_rr_node_ids[inode] == src_rr_node->edges[iedge]) {
is_redundant = true;
break;
}
}
/* add or skip */
if (true == is_redundant) {
continue; /* go to the next */
}
assert (false == is_redundant);
/* add to the list */
des_rr_node_ids_to_add.push_back(des_rr_node_ids[inode]);
driver_switches_to_add.push_back(driver_switches[inode]);
}
/* Allocate edge and switch to src_rr_node */
src_rr_node->num_edges += des_rr_node_ids_to_add.size();
if (NULL == src_rr_node->edges) {
/* calloc */
src_rr_node->edges = (int*) my_calloc( src_rr_node->num_edges, sizeof(int) );
src_rr_node->switches = (short*) my_calloc( src_rr_node->num_edges, sizeof(short) );
} else {
/* realloc */
src_rr_node->edges = (int*) my_realloc(src_rr_node->edges,
src_rr_node->num_edges * sizeof(int));
src_rr_node->switches = (short*) my_realloc(src_rr_node->switches,
src_rr_node->num_edges * sizeof(short));
}
for (size_t inode = 0; inode < des_rr_node_ids_to_add.size(); ++inode) {
/* Check des_rr_node id is in range */
int des_rr_node_id = des_rr_node_ids_to_add[inode];
assert ( (-1 < des_rr_node_id) && (des_rr_node_id < rr_graph->num_rr_nodes) );
t_rr_node* des_rr_node = &(rr_graph->rr_node[des_rr_node_id]);
/* Fill edge and switch info */
src_rr_node->edges[start_edge_id] = des_rr_node_id;
src_rr_node->switches[start_edge_id] = driver_switches_to_add[inode];
/* Update the des_rr_node */
des_rr_node->fan_in++;
/* Increment the start_edge_id */
start_edge_id++;
}
/* Check */
assert( start_edge_id == src_rr_node->num_edges );
return;
}
/************************************************************************
* Get the coordinator of a starting point of a routing track
* For routing tracks in INC_DIRECTION

View File

@ -30,6 +30,11 @@ void add_one_edge_for_two_rr_nodes(const t_rr_graph* rr_graph,
const int des_rr_node_id,
const short switch_id);
void add_edges_for_two_rr_nodes(const t_rr_graph* rr_graph,
const int src_rr_node_id,
const std::vector<int> des_rr_node,
const std::vector<short> driver_switches);
DeviceCoordinator get_track_rr_node_start_coordinator(const t_rr_node* track_rr_node);
DeviceCoordinator get_track_rr_node_end_coordinator(const t_rr_node* track_rr_node);

View File

@ -209,6 +209,9 @@ bool is_gsb_in_track_sb_population(const RRGSB& rr_gsb,
static
std::vector<size_t> get_to_track_list(const int Fs, const int to_track, const int num_to_tracks) {
std::vector<size_t> to_tracks;
/* Ensure a clear start */
to_tracks.clear();
for (int i = 0; i < Fs; i = i + 3) {
/* TODO: currently, for Fs > 3, I always search the next from_track until Fs is satisfied
* The optimal track selection should be done in a more scientific way!!!
@ -244,6 +247,8 @@ std::vector<size_t> get_switch_block_to_track_id(const enum e_switch_block_type
* connect. It supports any Fs % 3 == 0, switch blocks.
*/
std::vector<size_t> to_tracks;
/* Ensure a clear start */
to_tracks.clear();
/* TODO: currently, for Fs > 3, I always search the next from_track until Fs is satisfied
* The optimal track selection should be done in a more scientific way!!!
@ -251,9 +256,12 @@ std::vector<size_t> get_switch_block_to_track_id(const enum e_switch_block_type
assert (0 == Fs % 3);
/* Adapt from_track to fit in the range of num_to_tracks */
size_t actual_from_track = from_track % num_to_tracks;
switch (switch_block_type) {
case SUBSET: /* NB: Global routing uses SUBSET too */
to_tracks = get_to_track_list(Fs, from_track, num_to_tracks);
to_tracks = get_to_track_list(Fs, actual_from_track, num_to_tracks);
/* Finish, we return */
return to_tracks;
case UNIVERSAL:
@ -266,9 +274,9 @@ std::vector<size_t> get_switch_block_to_track_id(const enum e_switch_block_type
Side side_manager(from_side);
if ( (to_side == side_manager.get_opposite())
|| (to_side == side_manager.get_rotate_counterclockwise()) ) {
to_tracks = get_to_track_list(Fs, from_track, num_to_tracks);
to_tracks = get_to_track_list(Fs, actual_from_track, num_to_tracks);
} else if (to_side == side_manager.get_rotate_clockwise()) {
to_tracks = get_to_track_list(Fs, num_to_tracks - 1 - from_track, num_to_tracks);
to_tracks = get_to_track_list(Fs, num_to_tracks - 1 - actual_from_track, num_to_tracks);
}
}
@ -281,9 +289,9 @@ std::vector<size_t> get_switch_block_to_track_id(const enum e_switch_block_type
Side side_manager(from_side);
if ( (to_side == side_manager.get_opposite())
|| (to_side == side_manager.get_rotate_clockwise()) ) {
to_tracks = get_to_track_list(Fs, from_track, num_to_tracks);
to_tracks = get_to_track_list(Fs, actual_from_track, num_to_tracks);
} else if (to_side == side_manager.get_rotate_counterclockwise()) {
to_tracks = get_to_track_list(Fs, num_to_tracks - 1 - from_track, num_to_tracks);
to_tracks = get_to_track_list(Fs, num_to_tracks - 1 - actual_from_track, num_to_tracks);
}
}
/* Finish, we return */
@ -293,35 +301,35 @@ std::vector<size_t> get_switch_block_to_track_id(const enum e_switch_block_type
/* See S. Wilton Phd thesis, U of T, 1996 p. 103 for details on following. */
if (from_side == LEFT) {
if (to_side == RIGHT) { /* CHANX to CHANX */
to_tracks = get_to_track_list(Fs, from_track, num_to_tracks);
to_tracks = get_to_track_list(Fs, actual_from_track, num_to_tracks);
} else if (to_side == TOP) { /* from CHANX to CHANY */
to_tracks = get_to_track_list(Fs, (num_to_tracks - (from_track % num_to_tracks)) % num_to_tracks, num_to_tracks);
to_tracks = get_to_track_list(Fs, (num_to_tracks - actual_from_track ) % num_to_tracks, num_to_tracks);
} else if (to_side == BOTTOM) {
to_tracks = get_to_track_list(Fs, (num_to_tracks + from_track - 1) % num_to_tracks, num_to_tracks);
to_tracks = get_to_track_list(Fs, (num_to_tracks + actual_from_track - 1) % num_to_tracks, num_to_tracks);
}
} else if (from_side == RIGHT) {
if (to_side == LEFT) { /* CHANX to CHANX */
to_tracks = get_to_track_list(Fs, from_track, num_to_tracks);
to_tracks = get_to_track_list(Fs, actual_from_track, num_to_tracks);
} else if (to_side == TOP) { /* from CHANX to CHANY */
to_tracks = get_to_track_list(Fs, (num_to_tracks + from_track - 1) % num_to_tracks, num_to_tracks);
to_tracks = get_to_track_list(Fs, (num_to_tracks + actual_from_track - 1) % num_to_tracks, num_to_tracks);
} else if (to_side == BOTTOM) {
to_tracks = get_to_track_list(Fs, (num_to_tracks - 2 - from_track) % num_to_tracks, num_to_tracks);
to_tracks = get_to_track_list(Fs, (2 * num_to_tracks - 2 - actual_from_track) % num_to_tracks, num_to_tracks);
}
} else if (from_side == BOTTOM) {
if (to_side == TOP) { /* CHANY to CHANY */
to_tracks = get_to_track_list(Fs, from_track, num_to_tracks);
to_tracks = get_to_track_list(Fs, actual_from_track, num_to_tracks);
} else if (to_side == LEFT) { /* from CHANY to CHANX */
to_tracks = get_to_track_list(Fs, (from_track + 1) % num_to_tracks, num_to_tracks);
to_tracks = get_to_track_list(Fs, (actual_from_track + 1) % num_to_tracks, num_to_tracks);
} else if (to_side == RIGHT) {
to_tracks = get_to_track_list(Fs, (2 * num_to_tracks - 2 - from_track) % num_to_tracks, num_to_tracks);
to_tracks = get_to_track_list(Fs, (2 * num_to_tracks - 2 - actual_from_track) % num_to_tracks, num_to_tracks);
}
} else if (from_side == TOP) {
if (to_side == BOTTOM) { /* CHANY to CHANY */
to_tracks = get_to_track_list(Fs, from_track, num_to_tracks);
} else if (to_side == LEFT) { /* from CHANY to CHANX */
to_tracks = get_to_track_list(Fs, (num_to_tracks - (from_track % num_to_tracks)) % num_to_tracks, num_to_tracks);
to_tracks = get_to_track_list(Fs, (num_to_tracks - actual_from_track) % num_to_tracks, num_to_tracks);
} else if (to_side == RIGHT) {
to_tracks = get_to_track_list(Fs, (from_track + 1) % num_to_tracks, num_to_tracks);
to_tracks = get_to_track_list(Fs, (actual_from_track + 1) % num_to_tracks, num_to_tracks);
}
}
/* Finish, we return */
@ -388,11 +396,22 @@ void build_gsb_one_group_track_to_track_map(const t_rr_graph* rr_graph,
for (size_t to_track_id = 0; to_track_id < to_track_ids.size(); ++to_track_id) {
size_t from_side_index = side_manager.to_size_t();
size_t from_track_index = from_tracks[side][inode];
/* Check the id is still in the range !*/
assert ( to_track_ids[to_track_id] < to_tracks[to_side_index].size() );
size_t to_track_index = to_tracks[to_side_index][to_track_ids[to_track_id]];
//printf("from_track(size=%lu): %lu , to_track_ids[%lu]:%lu, to_track_index: %lu in a group of %lu tracks\n",
// from_tracks[side].size(), inode, to_track_id, to_track_ids[to_track_id],
// to_track_index, to_tracks[to_side_index].size());
t_rr_node* to_track_node = rr_gsb.get_chan_node(to_side, to_track_index);
/* Check if the to_track_node is already in the list ! */
std::vector<int>::iterator it = std::find((*track2track_map)[from_side_index][from_track_index].begin(),
(*track2track_map)[from_side_index][from_track_index].end(),
to_track_node - rr_graph->rr_node);
if (it != (*track2track_map)[from_side_index][from_track_index].end()) {
continue; /* the node_id is already in the list, go for the next */
}
/* Clear, we should add to the list */
(*track2track_map)[from_side_index][from_track_index].push_back(to_track_node - rr_graph->rr_node);
}
}
@ -927,13 +946,15 @@ void build_edges_for_one_tileable_rr_gsb(const t_rr_graph* rr_graph,
t_rr_node* opin_node = rr_gsb->get_opin_node(gsb_side, inode);
/* 1. create edges between OPINs and CHANX|CHANY, using opin2track_map */
int num_edges = opin2track_map[side_manager.to_size_t()][inode].size();
std::vector<short> driver_switches;
int num_edges = opin2track_map[gsb_side][inode].size();
for (int iedge = 0; iedge < num_edges; ++iedge) {
int track_node_id = opin2track_map[side_manager.to_size_t()][inode][iedge];
/* add edges to the chan_node */
add_one_edge_for_two_rr_nodes(rr_graph, opin_node - rr_graph->rr_node, track_node_id,
rr_graph->rr_node[track_node_id].driver_switch);
driver_switches.push_back(rr_graph->rr_node[track_node_id].driver_switch);
}
/* add edges to the opin_node */
add_edges_for_two_rr_nodes(rr_graph, opin_node - rr_graph->rr_node,
opin2track_map[gsb_side][inode], driver_switches);
}
/* Find CHANX or CHANY */
@ -945,26 +966,30 @@ void build_edges_for_one_tileable_rr_gsb(const t_rr_graph* rr_graph,
/* 2. create edges between CHANX|CHANY and IPINs, using ipin2track_map */
for (size_t inode = 0; inode < rr_gsb->get_chan_width(gsb_side); ++inode) {
t_rr_node* chan_node = rr_gsb->get_chan_node(gsb_side, inode);
int num_edges = track2ipin_map[side_manager.to_size_t()][inode].size();
std::vector<short> driver_switches;
int num_edges = track2ipin_map[gsb_side][inode].size();
for (int iedge = 0; iedge < num_edges; ++iedge) {
int ipin_node_id = track2ipin_map[side_manager.to_size_t()][inode][iedge];
/* add edges to the chan_node */
add_one_edge_for_two_rr_nodes(rr_graph, chan_node - rr_graph->rr_node, ipin_node_id,
rr_graph->rr_node[ipin_node_id].driver_switch);
int ipin_node_id = track2ipin_map[gsb_side][inode][iedge];
driver_switches.push_back(rr_graph->rr_node[ipin_node_id].driver_switch);
}
/* add edges to the chan_node */
add_edges_for_two_rr_nodes(rr_graph, chan_node - rr_graph->rr_node,
track2ipin_map[gsb_side][inode], driver_switches);
}
}
/* 3. create edges between CHANX|CHANY and CHANX|CHANY, using track2track_map */
for (size_t inode = 0; inode < rr_gsb->get_chan_width(gsb_side); ++inode) {
t_rr_node* chan_node = rr_gsb->get_chan_node(gsb_side, inode);
int num_edges = track2track_map[side_manager.to_size_t()][inode].size();
std::vector<short> driver_switches;
int num_edges = track2track_map[gsb_side][inode].size();
for (int iedge = 0; iedge < num_edges; ++iedge) {
int track_node_id = track2track_map[side_manager.to_size_t()][inode][iedge];
/* add edges to the chan_node */
add_one_edge_for_two_rr_nodes(rr_graph, chan_node - rr_graph->rr_node, track_node_id,
rr_graph->rr_node[track_node_id].driver_switch);
int track_node_id = track2track_map[gsb_side][inode][iedge];
driver_switches.push_back(rr_graph->rr_node[track_node_id].driver_switch);
}
/* add edges to the chan_node */
add_edges_for_two_rr_nodes(rr_graph, chan_node - rr_graph->rr_node,
track2track_map[gsb_side][inode], driver_switches);
}
}

View File

@ -1,7 +1,46 @@
/***********************************/
/* SPICE Modeling for VPR */
/* Xifan TANG, EPFL/LSI */
/***********************************/
/**********************************************************
* MIT License
*
* Copyright (c) 2018 LNIS - The University of Utah
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
***********************************************************************/
/************************************************************************
* Filename: fpga_x2p_unique_routing.c
* Created by: Xifan Tang
* Change history:
* +-------------------------------------+
* | Date | Author | Notes
* +-------------------------------------+
* | 2019/06/25 | Xifan Tang | Created
* +-------------------------------------+
***********************************************************************/
/************************************************************************
* This file contains builders for the data structures
* 1. RRGSB: General Switch Block (GSB).
* 2. RRChan: Generic routing channels
* We also include functions to identify unique modules of
* Switch Blocks and Connection Blocks based on the data structures
* t_sb and t_cb
***********************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -1096,157 +1135,6 @@ RRGSB build_rr_gsb(DeviceCoordinator& device_range,
return rr_gsb;
}
/* Rotate the Switch block and try to add to rotatable mirrors */
static
RRGSB rotate_rr_switch_block_for_mirror(DeviceCoordinator& device_range,
const RRGSB& rr_switch_block) {
RRGSB rotated_rr_switch_block;
rotated_rr_switch_block.set(rr_switch_block);
size_t Fco_offset = 1;
/* For the 4 Switch Blocks at the four corners */
/* 1. BOTTOM-LEFT corner:
* nothing to do. This is the base we like
*/
if ( ( 0 == rotated_rr_switch_block.get_sb_x())
&& ( 0 == rotated_rr_switch_block.get_sb_y()) ) {
return rotated_rr_switch_block;
}
/* 2. TOP-LEFT corner:
* swap the opin_node between TOP and BOTTOM,
* swap the chan_node between TOP and BOTTOM,
*/
if ( ( 0 == rotated_rr_switch_block.get_sb_x())
&& (device_range.get_y() == rotated_rr_switch_block.get_sb_y()) ) {
rotated_rr_switch_block.swap_opin_node(TOP, BOTTOM);
rotated_rr_switch_block.swap_chan_node(TOP, BOTTOM);
return rotated_rr_switch_block;
}
/* 3. TOP-RIGHT corner:
* swap the opin_node between TOP and BOTTOM,
* swap the chan_node between TOP and BOTTOM,
* swap the opin_node between LEFT and RIGHT,
* swap the chan_node between LEFT and RIGHT,
*/
if ( (device_range.get_x() == rotated_rr_switch_block.get_sb_x())
&& (device_range.get_y() == rotated_rr_switch_block.get_sb_y()) ) {
rotated_rr_switch_block.swap_opin_node(TOP, BOTTOM);
rotated_rr_switch_block.swap_chan_node(TOP, BOTTOM);
rotated_rr_switch_block.swap_opin_node(LEFT, RIGHT);
rotated_rr_switch_block.swap_chan_node(LEFT, RIGHT);
return rotated_rr_switch_block;
}
/* 4. BOTTOM-RIGHT corner:
* swap the opin_node between LEFT and RIGHT,
* swap the chan_node between LEFT and RIGHT,
*/
if ( (device_range.get_x() == rotated_rr_switch_block.get_sb_x())
&& (0 == rotated_rr_switch_block.get_sb_y()) ) {
rotated_rr_switch_block.swap_opin_node(LEFT, RIGHT);
rotated_rr_switch_block.swap_chan_node(LEFT, RIGHT);
return rotated_rr_switch_block;
}
/* For Switch blocks on the borders */
/* 1. BOTTOM side:
* nothing to do. This is the base we like
*/
if ( 0 == rotated_rr_switch_block.get_sb_y()) {
return rotated_rr_switch_block;
}
/* 2. TOP side:
* swap the opin_node between TOP and BOTTOM,
* swap the chan_node between TOP and BOTTOM,
*/
if (device_range.get_y() == rotated_rr_switch_block.get_sb_y() ) {
/* For RIGHT SIDE: X-channel in INC_DIRECTION, rotate by an offset of its x-coordinator */
rotated_rr_switch_block.rotate_side_chan_node_by_direction(RIGHT, INC_DIRECTION, Fco_offset * (rotated_rr_switch_block.get_sb_x() - 1));
/* Rotate the same nodes on the opposite side */
rotated_rr_switch_block.rotate_side_chan_node_by_direction(LEFT, INC_DIRECTION, Fco_offset * (rotated_rr_switch_block.get_sb_x() - 1));
/* For LEFT SIDE: X-channel in DEC_DIRECTION, rotate by an offset of its x-coordinator */
rotated_rr_switch_block.counter_rotate_side_chan_node_by_direction(LEFT, DEC_DIRECTION, Fco_offset * (rotated_rr_switch_block.get_sb_x() - 1));
/* Rotate the same nodes on the opposite side */
rotated_rr_switch_block.counter_rotate_side_chan_node_by_direction(RIGHT, DEC_DIRECTION, Fco_offset * (rotated_rr_switch_block.get_sb_x() - 1));
//rotated_rr_switch_block.swap_opin_node(TOP, BOTTOM);
//rotated_rr_switch_block.swap_chan_node(TOP, BOTTOM);
//rotated_rr_switch_block.reverse_opin_node(TOP);
//rotated_rr_switch_block.reverse_opin_node(BOTTOM);
return rotated_rr_switch_block;
}
/* 3. RIGHT side:
* swap the opin_node between LEFT and RIGHT,
* swap the chan_node between LEFT and RIGHT,
*/
if (device_range.get_x() == rotated_rr_switch_block.get_sb_x() ) {
/* For TOP SIDE: Y-channel in INC_DIRECTION, rotate by an offset of its y-coordinator */
rotated_rr_switch_block.rotate_side_chan_node_by_direction(TOP, INC_DIRECTION, Fco_offset * (rotated_rr_switch_block.get_sb_y() - 1));
/* Rotate the same nodes on the opposite side */
rotated_rr_switch_block.rotate_side_chan_node_by_direction(BOTTOM, INC_DIRECTION, Fco_offset * (rotated_rr_switch_block.get_sb_y() - 1));
/* For BOTTOM SIDE: Y-channel in DEC_DIRECTION, rotate by an offset of its y-coordinator */
rotated_rr_switch_block.counter_rotate_side_chan_node_by_direction(BOTTOM, DEC_DIRECTION, Fco_offset * (rotated_rr_switch_block.get_sb_y() - 1));
/* Rotate the same nodes on the opposite side */
rotated_rr_switch_block.counter_rotate_side_chan_node_by_direction(TOP, DEC_DIRECTION, Fco_offset * (rotated_rr_switch_block.get_sb_y() - 1));
//rotated_rr_switch_block.swap_opin_node(LEFT, RIGHT);
//rotated_rr_switch_block.swap_chan_node(LEFT, RIGHT);
//rotated_rr_switch_block.reverse_opin_node(LEFT);
//rotated_rr_switch_block.reverse_opin_node(RIGHT);
return rotated_rr_switch_block;
}
/* 4. LEFT side:
* nothing to do. This is the base we like
*/
if (0 == rotated_rr_switch_block.get_sb_x() ) {
return rotated_rr_switch_block;
}
/* SB[1][1] is the baseline, we do not modify */
if ( (1 == rotated_rr_switch_block.get_sb_x())
&& (1 == rotated_rr_switch_block.get_sb_y()) ) {
return rotated_rr_switch_block;
}
/* Reach here, it means we have a SB at the center region */
/* For TOP SIDE: Y-channel in INC_DIRECTION, rotate by an offset of its y-coordinator */
if (1 < rotated_rr_switch_block.get_sb_y()) {
rotated_rr_switch_block.rotate_side_chan_node_by_direction(TOP, INC_DIRECTION, Fco_offset * (rotated_rr_switch_block.get_sb_y() - 1));
/* Rotate the same nodes on the opposite side */
rotated_rr_switch_block.rotate_side_chan_node_by_direction(BOTTOM, INC_DIRECTION, Fco_offset * (rotated_rr_switch_block.get_sb_y() - 1));
}
/* For RIGHT SIDE: X-channel in INC_DIRECTION, rotate by an offset of its x-coordinator */
if (1 < rotated_rr_switch_block.get_sb_x()) {
rotated_rr_switch_block.rotate_side_chan_node_by_direction(RIGHT, INC_DIRECTION, Fco_offset * (rotated_rr_switch_block.get_sb_x() - 1));
/* Rotate the same nodes on the opposite side */
rotated_rr_switch_block.rotate_side_chan_node_by_direction(LEFT, INC_DIRECTION, Fco_offset * (rotated_rr_switch_block.get_sb_x() - 1));
}
/* For BOTTOM SIDE: Y-channel in DEC_DIRECTION, rotate by an offset of its y-coordinator */
if ( 1 < rotated_rr_switch_block.get_sb_y()) {
rotated_rr_switch_block.counter_rotate_side_chan_node_by_direction(BOTTOM, DEC_DIRECTION, Fco_offset * (rotated_rr_switch_block.get_sb_y() - 1));
/* Rotate the same nodes on the opposite side */
rotated_rr_switch_block.counter_rotate_side_chan_node_by_direction(TOP, DEC_DIRECTION, Fco_offset * (rotated_rr_switch_block.get_sb_y() - 1));
}
/* For LEFT SIDE: X-channel in DEC_DIRECTION, rotate by an offset of its x-coordinator */
if ( 1 < rotated_rr_switch_block.get_sb_x()) {
rotated_rr_switch_block.counter_rotate_side_chan_node_by_direction(LEFT, DEC_DIRECTION, Fco_offset * (rotated_rr_switch_block.get_sb_x() - 1));
/* Rotate the same nodes on the opposite side */
rotated_rr_switch_block.counter_rotate_side_chan_node_by_direction(RIGHT, DEC_DIRECTION, Fco_offset * (rotated_rr_switch_block.get_sb_x() - 1));
}
return rotated_rr_switch_block;
}
/* sort drive_rr_nodes of a rr_node inside rr_gsb subject to the index of rr_gsb array */
static
void sort_rr_gsb_one_ipin_node_drive_rr_nodes(const RRGSB& rr_gsb,
@ -1504,33 +1392,9 @@ DeviceRRGSB build_device_rr_gsb(boolean output_sb_xml, char* sb_xml_dir,
}
}
/* Create directory if needed */
if (TRUE == output_sb_xml) {
create_dir_path(sb_xml_dir);
}
for (size_t ix = 0; ix <= sb_range.get_x(); ++ix) {
for (size_t iy = 0; iy <= sb_range.get_y(); ++iy) {
RRGSB rr_gsb = LL_device_rr_gsb.get_gsb(ix, iy);
RRGSB rotated_rr_sb = rotate_rr_switch_block_for_mirror(sb_range, rr_gsb);
if (TRUE == output_sb_xml) {
std::string fname_prefix(sb_xml_dir);
/* Add slash if needed */
//if ('/' != fname_prefix.back()) {
// fname_prefix += "/";
//}
//fname_prefix += "rotated_";
//write_rr_switch_block_to_xml(fname_prefix, rotated_rr_sb);
write_rr_switch_block_to_xml(fname_prefix, rr_gsb);
}
}
}
return LL_device_rr_gsb;
}
/* Rotatable will be done in the next step
void identify_rotatable_switch_blocks();
void identify_rotatable_connection_blocks();
*/
/************************************************************************
* End of file : fpga_x2p_unique_routing.c
***********************************************************************/

View File

@ -1447,7 +1447,7 @@ const char* RRGSB::gen_gsb_verilog_module_name() const {
std::string y_str = std::to_string(get_sb_y());
char* ret = (char*)my_malloc(sizeof(char)*
( 2 + 1
( 3 + 1
+ x_str.length() + 2
+ y_str.length() + 1
+ 1));

View File

@ -31,7 +31,7 @@ void write_rr_switch_block_to_xml(std::string fname_prefix, RRGSB& rr_gsb) {
/* Output each side */
for (size_t side = 0; side < rr_gsb.get_num_sides(); ++side) {
Side gsb_side_manager(side);
enum e_side gsb_side = gsb_side;
enum e_side gsb_side = gsb_side_manager.get_side();
/* Output IPIN nodes */
for (size_t inode = 0; inode < rr_gsb.get_num_ipin_nodes(gsb_side); ++inode) {
@ -117,7 +117,9 @@ void write_rr_switch_block_to_xml(std::string fname_prefix, RRGSB& rr_gsb) {
enum e_side drive_node_side = NUM_SIDES;
int drive_node_index = -1;
rr_gsb.get_node_side_and_index(drive_rr_nodes[jnode], IN_PORT, &drive_node_side, &drive_node_index);
assert(-1 != drive_node_index);
Side drive_side(drive_node_side);
if (OPIN == drive_rr_nodes[jnode]->type) {
Side grid_side(rr_gsb.get_opin_node_grid_side(drive_node_side, drive_node_index));
fp << "\t\t<driver_node type=\"" << rr_node_typename[OPIN]