fixed bugs for UNIVERSAL and WILTON switch blocks
This commit is contained in:
parent
a88263a4c2
commit
4d3b5f12b4
|
@ -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"/>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
***********************************************************************/
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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]
|
||||
|
|
Loading…
Reference in New Issue