Merge branch 'multimode_clb' of https://github.com/LNIS-Projects/OpenFPGA into multimode_clb
This commit is contained in:
commit
4ef25a7550
|
@ -1,3 +1,6 @@
|
||||||
|
#ifndef FPGA_X2P_PBTYPES_UTILS_H
|
||||||
|
#define FPGA_X2P_PBTYPES_UTILS_H
|
||||||
|
|
||||||
void check_pb_graph_edge(t_pb_graph_edge pb_graph_edge);
|
void check_pb_graph_edge(t_pb_graph_edge pb_graph_edge);
|
||||||
|
|
||||||
void check_pb_graph_pin_edges(t_pb_graph_pin pb_graph_pin);
|
void check_pb_graph_pin_edges(t_pb_graph_pin pb_graph_pin);
|
||||||
|
@ -236,3 +239,5 @@ boolean is_pb_used_for_wiring(t_pb_graph_node* cur_pb_graph_node,
|
||||||
t_rr_node* pb_rr_graph);
|
t_rr_node* pb_rr_graph);
|
||||||
|
|
||||||
char* get_pb_graph_full_name_in_hierarchy(t_pb_graph_node* cur_pb_graph_node);
|
char* get_pb_graph_full_name_in_hierarchy(t_pb_graph_node* cur_pb_graph_node);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#include "fpga_x2p_globals.h"
|
#include "fpga_x2p_globals.h"
|
||||||
#include "fpga_x2p_utils.h"
|
#include "fpga_x2p_utils.h"
|
||||||
#include "fpga_x2p_backannotate_utils.h"
|
#include "fpga_x2p_backannotate_utils.h"
|
||||||
|
#include "write_rr_blocks.h"
|
||||||
#include "fpga_x2p_unique_routing.h"
|
#include "fpga_x2p_unique_routing.h"
|
||||||
|
|
||||||
/***** subroutines declaration *****/
|
/***** subroutines declaration *****/
|
||||||
|
@ -820,7 +821,7 @@ DeviceRRChan build_device_rr_chan(int LL_num_rr_nodes, t_rr_node* LL_rr_node,
|
||||||
* For channels chanX with DEC_DIRECTION on the right side, they should be marked as inputs
|
* For channels chanX with DEC_DIRECTION on the right side, they should be marked as inputs
|
||||||
*/
|
*/
|
||||||
static
|
static
|
||||||
RRSwitchBlock build_rr_switch_block(DeviceCoordinator device_range,
|
RRSwitchBlock build_rr_switch_block(DeviceCoordinator& device_range,
|
||||||
size_t sb_x, size_t sb_y,
|
size_t sb_x, size_t sb_y,
|
||||||
int LL_num_rr_nodes, t_rr_node* LL_rr_node,
|
int LL_num_rr_nodes, t_rr_node* LL_rr_node,
|
||||||
t_ivec*** LL_rr_node_indices, int num_segments,
|
t_ivec*** LL_rr_node_indices, int num_segments,
|
||||||
|
@ -1044,6 +1045,7 @@ RRSwitchBlock rotate_rr_switch_block_for_mirror(DeviceCoordinator& device_range,
|
||||||
const RRSwitchBlock& rr_switch_block) {
|
const RRSwitchBlock& rr_switch_block) {
|
||||||
RRSwitchBlock rotated_rr_switch_block;
|
RRSwitchBlock rotated_rr_switch_block;
|
||||||
rotated_rr_switch_block.set(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 */
|
/* For the 4 Switch Blocks at the four corners */
|
||||||
/* 1. BOTTOM-LEFT corner:
|
/* 1. BOTTOM-LEFT corner:
|
||||||
|
@ -1103,10 +1105,22 @@ RRSwitchBlock rotate_rr_switch_block_for_mirror(DeviceCoordinator& device_range,
|
||||||
* swap the chan_node between TOP and BOTTOM,
|
* swap the chan_node between TOP and BOTTOM,
|
||||||
*/
|
*/
|
||||||
if (device_range.get_y() == rotated_rr_switch_block.get_y() ) {
|
if (device_range.get_y() == rotated_rr_switch_block.get_y() ) {
|
||||||
rotated_rr_switch_block.swap_opin_node(TOP, BOTTOM);
|
|
||||||
rotated_rr_switch_block.swap_chan_node(TOP, BOTTOM);
|
/* For RIGHT SIDE: X-channel in INC_DIRECTION, rotate by an offset of its x-coordinator */
|
||||||
rotated_rr_switch_block.reverse_opin_node(TOP);
|
rotated_rr_switch_block.rotate_side_chan_node_by_direction(RIGHT, INC_DIRECTION, Fco_offset * (rotated_rr_switch_block.get_x() - 1));
|
||||||
rotated_rr_switch_block.reverse_opin_node(BOTTOM);
|
/* 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_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_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_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;
|
return rotated_rr_switch_block;
|
||||||
}
|
}
|
||||||
/* 3. RIGHT side:
|
/* 3. RIGHT side:
|
||||||
|
@ -1114,10 +1128,22 @@ RRSwitchBlock rotate_rr_switch_block_for_mirror(DeviceCoordinator& device_range,
|
||||||
* swap the chan_node between LEFT and RIGHT,
|
* swap the chan_node between LEFT and RIGHT,
|
||||||
*/
|
*/
|
||||||
if (device_range.get_x() == rotated_rr_switch_block.get_x() ) {
|
if (device_range.get_x() == rotated_rr_switch_block.get_x() ) {
|
||||||
rotated_rr_switch_block.swap_opin_node(LEFT, RIGHT);
|
|
||||||
rotated_rr_switch_block.swap_chan_node(LEFT, RIGHT);
|
/* For TOP SIDE: Y-channel in INC_DIRECTION, rotate by an offset of its y-coordinator */
|
||||||
rotated_rr_switch_block.reverse_opin_node(LEFT);
|
rotated_rr_switch_block.rotate_side_chan_node_by_direction(TOP, INC_DIRECTION, Fco_offset * (rotated_rr_switch_block.get_y() - 1));
|
||||||
rotated_rr_switch_block.reverse_opin_node(RIGHT);
|
/* 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_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_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_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;
|
return rotated_rr_switch_block;
|
||||||
}
|
}
|
||||||
/* 4. LEFT side:
|
/* 4. LEFT side:
|
||||||
|
@ -1136,35 +1162,36 @@ RRSwitchBlock rotate_rr_switch_block_for_mirror(DeviceCoordinator& device_range,
|
||||||
/* Reach here, it means we have a SB at the center region */
|
/* 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 */
|
/* For TOP SIDE: Y-channel in INC_DIRECTION, rotate by an offset of its y-coordinator */
|
||||||
if (1 < rotated_rr_switch_block.get_y()) {
|
if (1 < rotated_rr_switch_block.get_y()) {
|
||||||
rotated_rr_switch_block.rotate_side_chan_node_by_direction(TOP, INC_DIRECTION, rotated_rr_switch_block.get_y() - 1);
|
rotated_rr_switch_block.rotate_side_chan_node_by_direction(TOP, INC_DIRECTION, Fco_offset * (rotated_rr_switch_block.get_y() - 1));
|
||||||
/* Rotate the same nodes on the opposite side */
|
/* Rotate the same nodes on the opposite side */
|
||||||
rotated_rr_switch_block.rotate_side_chan_node_by_direction(BOTTOM, INC_DIRECTION, rotated_rr_switch_block.get_y() - 1);
|
rotated_rr_switch_block.rotate_side_chan_node_by_direction(BOTTOM, INC_DIRECTION, Fco_offset * (rotated_rr_switch_block.get_y() - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* For RIGHT SIDE: X-channel in INC_DIRECTION, rotate by an offset of its x-coordinator */
|
/* For RIGHT SIDE: X-channel in INC_DIRECTION, rotate by an offset of its x-coordinator */
|
||||||
if (1 < rotated_rr_switch_block.get_x()) {
|
if (1 < rotated_rr_switch_block.get_x()) {
|
||||||
rotated_rr_switch_block.rotate_side_chan_node_by_direction(RIGHT, INC_DIRECTION, rotated_rr_switch_block.get_x() - 1);
|
rotated_rr_switch_block.rotate_side_chan_node_by_direction(RIGHT, INC_DIRECTION, Fco_offset * (rotated_rr_switch_block.get_x() - 1));
|
||||||
/* Rotate the same nodes on the opposite side */
|
/* Rotate the same nodes on the opposite side */
|
||||||
rotated_rr_switch_block.rotate_side_chan_node_by_direction(LEFT, INC_DIRECTION, rotated_rr_switch_block.get_x() - 1);
|
rotated_rr_switch_block.rotate_side_chan_node_by_direction(LEFT, INC_DIRECTION, Fco_offset * (rotated_rr_switch_block.get_x() - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* For BOTTOM SIDE: Y-channel in DEC_DIRECTION, rotate by an offset of its y-coordinator */
|
/* For BOTTOM SIDE: Y-channel in DEC_DIRECTION, rotate by an offset of its y-coordinator */
|
||||||
if (device_range.get_y() - 1 > rotated_rr_switch_block.get_y()) {
|
if ( 1 < rotated_rr_switch_block.get_y()) {
|
||||||
rotated_rr_switch_block.counter_rotate_side_chan_node_by_direction(BOTTOM, DEC_DIRECTION, device_range.get_y() - 1 - rotated_rr_switch_block.get_y());
|
rotated_rr_switch_block.counter_rotate_side_chan_node_by_direction(BOTTOM, DEC_DIRECTION, Fco_offset * (rotated_rr_switch_block.get_y() - 1));
|
||||||
/* Rotate the same nodes on the opposite side */
|
/* Rotate the same nodes on the opposite side */
|
||||||
rotated_rr_switch_block.counter_rotate_side_chan_node_by_direction(TOP, DEC_DIRECTION, device_range.get_y() - 1 - rotated_rr_switch_block.get_y());
|
rotated_rr_switch_block.counter_rotate_side_chan_node_by_direction(TOP, DEC_DIRECTION, Fco_offset * (rotated_rr_switch_block.get_y() - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* For LEFT SIDE: X-channel in DEC_DIRECTION, rotate by an offset of its x-coordinator */
|
/* For LEFT SIDE: X-channel in DEC_DIRECTION, rotate by an offset of its x-coordinator */
|
||||||
if (device_range.get_x() - 1 > rotated_rr_switch_block.get_x()) {
|
if ( 1 < rotated_rr_switch_block.get_x()) {
|
||||||
rotated_rr_switch_block.counter_rotate_side_chan_node_by_direction(LEFT, DEC_DIRECTION, device_range.get_x() - 1 - rotated_rr_switch_block.get_x());
|
rotated_rr_switch_block.counter_rotate_side_chan_node_by_direction(LEFT, DEC_DIRECTION, Fco_offset * (rotated_rr_switch_block.get_x() - 1));
|
||||||
/* Rotate the same nodes on the opposite side */
|
/* Rotate the same nodes on the opposite side */
|
||||||
rotated_rr_switch_block.counter_rotate_side_chan_node_by_direction(RIGHT, DEC_DIRECTION, device_range.get_x() - 1 - rotated_rr_switch_block.get_x());
|
rotated_rr_switch_block.counter_rotate_side_chan_node_by_direction(RIGHT, DEC_DIRECTION, Fco_offset * (rotated_rr_switch_block.get_x() - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
return rotated_rr_switch_block;
|
return rotated_rr_switch_block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Build a list of Switch blocks, each of which contains a collection of rr_nodes
|
/* Build a list of Switch blocks, each of which contains a collection of rr_nodes
|
||||||
* We will maintain a list of unique switch blocks, which will be outputted as a Verilog module
|
* We will maintain a list of unique switch blocks, which will be outputted as a Verilog module
|
||||||
* Each switch block in the FPGA fabric will be an instance of these modules.
|
* Each switch block in the FPGA fabric will be an instance of these modules.
|
||||||
|
@ -1206,11 +1233,7 @@ DeviceRRSwitchBlock build_device_rr_switch_blocks(int LL_num_rr_nodes, t_rr_node
|
||||||
|
|
||||||
for (size_t ix = 0; ix <= sb_range.get_x(); ++ix) {
|
for (size_t ix = 0; ix <= sb_range.get_x(); ++ix) {
|
||||||
for (size_t iy = 0; iy <= sb_range.get_y(); ++iy) {
|
for (size_t iy = 0; iy <= sb_range.get_y(); ++iy) {
|
||||||
//RRSwitchBlock rr_sb = LL_device_rr_switch_block.get_switch_block(ix, iy);
|
RRSwitchBlock rr_sb = LL_device_rr_switch_block.get_switch_block(ix, iy);
|
||||||
RRSwitchBlock rr_sb = build_rr_switch_block(sb_range, ix, iy,
|
|
||||||
LL_num_rr_nodes, LL_rr_node,
|
|
||||||
LL_rr_node_indices,
|
|
||||||
num_segments, LL_rr_indexed_data);
|
|
||||||
RRSwitchBlock rotated_rr_sb = rotate_rr_switch_block_for_mirror(sb_range, rr_sb);
|
RRSwitchBlock rotated_rr_sb = rotate_rr_switch_block_for_mirror(sb_range, rr_sb);
|
||||||
DeviceCoordinator sb_coordinator = rr_sb.get_coordinator();
|
DeviceCoordinator sb_coordinator = rr_sb.get_coordinator();
|
||||||
LL_device_rr_switch_block.add_rotatable_mirror(sb_coordinator, rotated_rr_sb);
|
LL_device_rr_switch_block.add_rotatable_mirror(sb_coordinator, rotated_rr_sb);
|
||||||
|
@ -1223,6 +1246,8 @@ DeviceRRSwitchBlock build_device_rr_switch_blocks(int LL_num_rr_nodes, t_rr_node
|
||||||
"Detect %d rotatable unique switch blocks from %d switch blocks.\n",
|
"Detect %d rotatable unique switch blocks from %d switch blocks.\n",
|
||||||
LL_device_rr_switch_block.get_num_rotatable_mirror(), (nx + 1) * (ny + 1) );
|
LL_device_rr_switch_block.get_num_rotatable_mirror(), (nx + 1) * (ny + 1) );
|
||||||
|
|
||||||
|
write_device_rr_switch_block_to_xml(LL_device_rr_switch_block);
|
||||||
|
|
||||||
return LL_device_rr_switch_block;
|
return LL_device_rr_switch_block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -101,6 +101,26 @@ bool RRChan::is_mirror(RRChan& cand) const {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Get a list of segments used in this routing channel */
|
||||||
|
std::vector<size_t> RRChan::get_segment_ids() const {
|
||||||
|
std::vector<size_t> seg_list;
|
||||||
|
|
||||||
|
/* make sure a clean start */
|
||||||
|
seg_list.clear();
|
||||||
|
|
||||||
|
/* Traverse node_segments */
|
||||||
|
for (size_t inode = 0; inode < get_chan_width(); ++inode) {
|
||||||
|
std::vector<size_t>::iterator it;
|
||||||
|
/* Try to find the node_segment id in the list */
|
||||||
|
it = find(seg_list.begin(), seg_list.end(), node_segments_[inode]);
|
||||||
|
if ( it != seg_list.end() ) {
|
||||||
|
/* Not found, add it to the list */
|
||||||
|
seg_list.push_back(node_segments_[inode]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return seg_list;
|
||||||
|
}
|
||||||
|
|
||||||
/* Mutators */
|
/* Mutators */
|
||||||
void RRChan::set(const RRChan& rr_chan) {
|
void RRChan::set(const RRChan& rr_chan) {
|
||||||
|
@ -166,7 +186,7 @@ void RRChan::rotate(size_t rotate_begin, size_t rotate_end, size_t offset) {
|
||||||
|
|
||||||
/* rotate all the channel nodes by a given offset:
|
/* rotate all the channel nodes by a given offset:
|
||||||
* Routing Channel nodes are divided into different groups using segment ids
|
* Routing Channel nodes are divided into different groups using segment ids
|
||||||
* each group is rotated separatedly
|
* each group should be rotated separatedly
|
||||||
*/
|
*/
|
||||||
void RRChan::rotate_by_node_direction(enum e_direction node_direction, size_t offset) {
|
void RRChan::rotate_by_node_direction(enum e_direction node_direction, size_t offset) {
|
||||||
/* skip if there are no nodes */
|
/* skip if there are no nodes */
|
||||||
|
@ -174,11 +194,16 @@ void RRChan::rotate_by_node_direction(enum e_direction node_direction, size_t of
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* get a list of segment_ids existing in the routing channel */
|
||||||
|
std::vector<size_t> seg_ids = get_segment_ids();
|
||||||
|
|
||||||
|
for (size_t iseg = 0; iseg < seg_ids.size(); ++iseg) {
|
||||||
/* Get the channel nodes of a given direction */
|
/* Get the channel nodes of a given direction */
|
||||||
std::vector<t_rr_node*> nodes;
|
std::vector<t_rr_node*> nodes;
|
||||||
std::vector<size_t> node_segments;
|
std::vector<size_t> node_segments;
|
||||||
for (size_t inode = 0; inode < get_chan_width(); ++inode) {
|
for (size_t inode = 0; inode < get_chan_width(); ++inode) {
|
||||||
if (node_direction == get_node(inode)->direction) {
|
if ( (node_direction == get_node(inode)->direction)
|
||||||
|
&& (seg_ids[iseg] == (size_t)get_node_segment(inode)) ) {
|
||||||
nodes.push_back(get_node(inode));
|
nodes.push_back(get_node(inode));
|
||||||
node_segments.push_back(get_node_segment(inode));
|
node_segments.push_back(get_node_segment(inode));
|
||||||
}
|
}
|
||||||
|
@ -193,7 +218,8 @@ void RRChan::rotate_by_node_direction(enum e_direction node_direction, size_t of
|
||||||
|
|
||||||
/* back-annotate to to the original chan nodes*/
|
/* back-annotate to to the original chan nodes*/
|
||||||
for (size_t inode = 0; inode < get_chan_width(); ++inode) {
|
for (size_t inode = 0; inode < get_chan_width(); ++inode) {
|
||||||
if (node_direction == get_node(inode)->direction) {
|
if ( (node_direction == get_node(inode)->direction)
|
||||||
|
&& (seg_ids[iseg] == (size_t)get_node_segment(inode)) ) {
|
||||||
nodes_[inode] = nodes.front();
|
nodes_[inode] = nodes.front();
|
||||||
node_segments_[inode] = node_segments.front();
|
node_segments_[inode] = node_segments.front();
|
||||||
/* pop up temp vectors */
|
/* pop up temp vectors */
|
||||||
|
@ -205,6 +231,7 @@ void RRChan::rotate_by_node_direction(enum e_direction node_direction, size_t of
|
||||||
/* Make sure temp vectors are all poped out */
|
/* Make sure temp vectors are all poped out */
|
||||||
assert ( 0 == nodes.size());
|
assert ( 0 == nodes.size());
|
||||||
assert ( 0 == node_segments.size());
|
assert ( 0 == node_segments.size());
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -219,11 +246,16 @@ void RRChan::counter_rotate_by_node_direction(enum e_direction node_direction, s
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* get a list of segment_ids existing in the routing channel */
|
||||||
|
std::vector<size_t> seg_ids = get_segment_ids();
|
||||||
|
|
||||||
|
for (size_t iseg = 0; iseg < seg_ids.size(); ++iseg) {
|
||||||
/* Get the channel nodes of a given direction */
|
/* Get the channel nodes of a given direction */
|
||||||
std::vector<t_rr_node*> nodes;
|
std::vector<t_rr_node*> nodes;
|
||||||
std::vector<size_t> node_segments;
|
std::vector<size_t> node_segments;
|
||||||
for (size_t inode = 0; inode < get_chan_width(); ++inode) {
|
for (size_t inode = 0; inode < get_chan_width(); ++inode) {
|
||||||
if (node_direction == get_node(inode)->direction) {
|
if ( (node_direction == get_node(inode)->direction)
|
||||||
|
&& (seg_ids[iseg] == (size_t)get_node_segment(inode)) ) {
|
||||||
nodes.push_back(get_node(inode));
|
nodes.push_back(get_node(inode));
|
||||||
node_segments.push_back(get_node_segment(inode));
|
node_segments.push_back(get_node_segment(inode));
|
||||||
}
|
}
|
||||||
|
@ -238,7 +270,8 @@ void RRChan::counter_rotate_by_node_direction(enum e_direction node_direction, s
|
||||||
|
|
||||||
/* back-annotate to to the original chan nodes*/
|
/* back-annotate to to the original chan nodes*/
|
||||||
for (size_t inode = 0; inode < get_chan_width(); ++inode) {
|
for (size_t inode = 0; inode < get_chan_width(); ++inode) {
|
||||||
if (node_direction == get_node(inode)->direction) {
|
if ( (node_direction == get_node(inode)->direction)
|
||||||
|
&& (seg_ids[iseg] == (size_t)get_node_segment(inode)) ) {
|
||||||
nodes_[inode] = nodes.front();
|
nodes_[inode] = nodes.front();
|
||||||
node_segments_[inode] = node_segments.front();
|
node_segments_[inode] = node_segments.front();
|
||||||
/* pop up temp vectors */
|
/* pop up temp vectors */
|
||||||
|
@ -250,6 +283,7 @@ void RRChan::counter_rotate_by_node_direction(enum e_direction node_direction, s
|
||||||
/* Make sure temp vectors are all poped out */
|
/* Make sure temp vectors are all poped out */
|
||||||
assert ( 0 == nodes.size());
|
assert ( 0 == nodes.size());
|
||||||
assert ( 0 == node_segments.size());
|
assert ( 0 == node_segments.size());
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1084,6 +1118,7 @@ void RRSwitchBlock::set(const RRSwitchBlock& src) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Set the coordinator (x,y) for the switch block */
|
/* Set the coordinator (x,y) for the switch block */
|
||||||
void RRSwitchBlock::set_coordinator(size_t x, size_t y) {
|
void RRSwitchBlock::set_coordinator(size_t x, size_t y) {
|
||||||
coordinator_.set(x, y);
|
coordinator_.set(x, y);
|
||||||
|
@ -1763,6 +1798,9 @@ void DeviceRRSwitchBlock::add_rr_switch_block(DeviceCoordinator& coordinator,
|
||||||
|
|
||||||
/* Add a switch block to the array, which will automatically identify and update the lists of unique mirrors and rotatable mirrors */
|
/* Add a switch block to the array, which will automatically identify and update the lists of unique mirrors and rotatable mirrors */
|
||||||
void DeviceRRSwitchBlock::build_unique_mirror() {
|
void DeviceRRSwitchBlock::build_unique_mirror() {
|
||||||
|
/* Make sure a clean start */
|
||||||
|
clear_mirror();
|
||||||
|
|
||||||
for (size_t ix = 0; ix < rr_switch_block_.size(); ++ix) {
|
for (size_t ix = 0; ix < rr_switch_block_.size(); ++ix) {
|
||||||
for (size_t iy = 0; iy < rr_switch_block_[ix].size(); ++iy) {
|
for (size_t iy = 0; iy < rr_switch_block_[ix].size(); ++iy) {
|
||||||
bool is_unique_mirror = true;
|
bool is_unique_mirror = true;
|
||||||
|
@ -1820,6 +1858,9 @@ void DeviceRRSwitchBlock::add_rotatable_mirror(DeviceCoordinator& coordinator,
|
||||||
rotatable_mirror_.push_back(coordinator);
|
rotatable_mirror_.push_back(coordinator);
|
||||||
/* Record the id of unique mirror */
|
/* Record the id of unique mirror */
|
||||||
rr_switch_block_rotatable_mirror_id_[coordinator.get_x()][coordinator.get_y()] = rotatable_mirror_.size() - 1;
|
rr_switch_block_rotatable_mirror_id_[coordinator.get_x()][coordinator.get_y()] = rotatable_mirror_.size() - 1;
|
||||||
|
/*
|
||||||
|
printf("Detect a rotatable mirror: SB[%lu][%lu]\n", coordinator.get_x(), coordinator.get_y());
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@ -1830,15 +1871,34 @@ void DeviceRRSwitchBlock::clear() {
|
||||||
/* clean rr_switch_block array */
|
/* clean rr_switch_block array */
|
||||||
for (size_t x = 0; x < rr_switch_block_.size(); ++x) {
|
for (size_t x = 0; x < rr_switch_block_.size(); ++x) {
|
||||||
rr_switch_block_[x].clear();
|
rr_switch_block_[x].clear();
|
||||||
|
rr_switch_block_mirror_id_[x].clear();
|
||||||
|
rr_switch_block_rotatable_mirror_id_[x].clear();
|
||||||
}
|
}
|
||||||
rr_switch_block_.clear();
|
rr_switch_block_.clear();
|
||||||
|
rr_switch_block_mirror_id_.clear();
|
||||||
|
rr_switch_block_rotatable_mirror_id_.clear();
|
||||||
|
|
||||||
|
/* clean unique mirror */
|
||||||
|
clear_mirror();
|
||||||
|
|
||||||
|
/* clean unique mirror */
|
||||||
|
clear_rotatable_mirror();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* clean the content related to unique_mirrors */
|
||||||
|
void DeviceRRSwitchBlock::clear_mirror() {
|
||||||
/* clean unique mirror */
|
/* clean unique mirror */
|
||||||
unique_mirror_.clear();
|
unique_mirror_.clear();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* clean the content related to rotatable_mirrors */
|
||||||
|
void DeviceRRSwitchBlock::clear_rotatable_mirror() {
|
||||||
/* clean unique mirror */
|
/* clean unique mirror */
|
||||||
rotatable_mirror_.clear();
|
rotatable_mirror_.clear();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,6 +47,7 @@ class RRChan {
|
||||||
int get_node_segment(t_rr_node* node) const;
|
int get_node_segment(t_rr_node* node) const;
|
||||||
int get_node_segment(size_t track_num) const;
|
int get_node_segment(size_t track_num) const;
|
||||||
bool is_mirror(RRChan& cand) const; /* evaluate if two RR_chan is mirror to each other */
|
bool is_mirror(RRChan& cand) const; /* evaluate if two RR_chan is mirror to each other */
|
||||||
|
std::vector<size_t> get_segment_ids() const; /* Get a list of segments used in this routing channel */
|
||||||
public: /* Mutators */
|
public: /* Mutators */
|
||||||
void set(const RRChan&); /* copy */
|
void set(const RRChan&); /* copy */
|
||||||
void set_type(t_rr_type type); /* modify type */
|
void set_type(t_rr_type type); /* modify type */
|
||||||
|
@ -253,6 +254,8 @@ class DeviceRRSwitchBlock {
|
||||||
void build_unique_mirror(); /* Add a switch block to the array, which will automatically identify and update the lists of unique mirrors and rotatable mirrors */
|
void build_unique_mirror(); /* Add a switch block to the array, which will automatically identify and update the lists of unique mirrors and rotatable mirrors */
|
||||||
void add_rotatable_mirror(DeviceCoordinator& coordinator, RRSwitchBlock& rr_sb); /* Add a switch block to the array, which will automatically identify and update the lists of unique mirrors and rotatable mirrors */
|
void add_rotatable_mirror(DeviceCoordinator& coordinator, RRSwitchBlock& rr_sb); /* Add a switch block to the array, which will automatically identify and update the lists of unique mirrors and rotatable mirrors */
|
||||||
void clear(); /* clean the content */
|
void clear(); /* clean the content */
|
||||||
|
void clear_mirror(); /* clean the content */
|
||||||
|
void clear_rotatable_mirror(); /* clean the content */
|
||||||
private: /* Validators */
|
private: /* Validators */
|
||||||
bool validate_coordinator(DeviceCoordinator& coordinator) const; /* Validate if the (x,y) is the range of this device */
|
bool validate_coordinator(DeviceCoordinator& coordinator) const; /* Validate if the (x,y) is the range of this device */
|
||||||
bool validate_unique_mirror_index(size_t index) const; /* Validate if the index in the range of unique_mirror vector*/
|
bool validate_unique_mirror_index(size_t index) const; /* Validate if the index in the range of unique_mirror vector*/
|
||||||
|
|
|
@ -0,0 +1,111 @@
|
||||||
|
/*
|
||||||
|
* Output internal structure of classes defined in rr_blocks.h to XML format
|
||||||
|
*/
|
||||||
|
#include <fstream>
|
||||||
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include "rr_blocks.h"
|
||||||
|
#include "write_rr_blocks.h"
|
||||||
|
|
||||||
|
#include "fpga_x2p_utils.h"
|
||||||
|
|
||||||
|
void write_rr_switch_block_to_xml(std::string fname_prefix, RRSwitchBlock& rr_sb) {
|
||||||
|
/* Create a file handler*/
|
||||||
|
std::fstream fp;
|
||||||
|
std::string fname = fname_prefix;
|
||||||
|
fname += rr_sb.gen_verilog_instance_name();
|
||||||
|
fname += ".xml";
|
||||||
|
|
||||||
|
printf("Output SB XML: %s\n", fname.c_str());
|
||||||
|
|
||||||
|
/* Open a file */
|
||||||
|
fp.open(fname, std::fstream::out | std::fstream::trunc);
|
||||||
|
|
||||||
|
/* Output location of the Switch Block */
|
||||||
|
fp << "<rr_sb x=\"" << rr_sb.get_x() << "\" y=\"" << rr_sb.get_y() << "\""
|
||||||
|
<< " num_sides=\"" << rr_sb.get_num_sides() << "\">" << std::endl;
|
||||||
|
|
||||||
|
/* Output each side */
|
||||||
|
for (size_t side = 0; side < rr_sb.get_num_sides(); ++side) {
|
||||||
|
Side side_manager(side);
|
||||||
|
/* Output chan nodes */
|
||||||
|
for (size_t inode = 0; inode < rr_sb.get_chan_width(side_manager.get_side()); ++inode) {
|
||||||
|
/* We only care OUT_PORT */
|
||||||
|
if (OUT_PORT != rr_sb.get_chan_node_direction(side_manager.get_side(), inode)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/* Output drivers */
|
||||||
|
size_t num_drive_rr_nodes = 0;
|
||||||
|
t_rr_node** drive_rr_nodes = 0;
|
||||||
|
t_rr_node* cur_rr_node = rr_sb.get_chan_node(side_manager.get_side(), inode);
|
||||||
|
|
||||||
|
/* Output node information: location, index, side */
|
||||||
|
fp << "\t<" << convert_chan_type_to_string(cur_rr_node->type)
|
||||||
|
<< " side=\"" << side_manager.to_string()
|
||||||
|
<< "\" index=\"" << inode << "\">"
|
||||||
|
<< std::endl;
|
||||||
|
|
||||||
|
/* Check if this node is directly connected to the node on the opposite side */
|
||||||
|
if (true == rr_sb.is_node_imply_short_connection(cur_rr_node)) {
|
||||||
|
/* Double check if the interc lies inside a channel wire, that is interc between segments */
|
||||||
|
assert(true == rr_sb.is_node_exist_opposite_side(cur_rr_node, side_manager.get_side()));
|
||||||
|
num_drive_rr_nodes = 0;
|
||||||
|
drive_rr_nodes = NULL;
|
||||||
|
} else {
|
||||||
|
num_drive_rr_nodes = cur_rr_node->num_drive_rr_nodes;
|
||||||
|
drive_rr_nodes = cur_rr_node->drive_rr_nodes;
|
||||||
|
}
|
||||||
|
/* Direct connection: output the node on the opposite side */
|
||||||
|
if (0 == num_drive_rr_nodes) {
|
||||||
|
Side oppo_side = side_manager.get_opposite();
|
||||||
|
fp << "\t\t<drive_node type=\"" << convert_chan_type_to_string(cur_rr_node->type)
|
||||||
|
<< "\" side=\"" << oppo_side.to_string()
|
||||||
|
<< "\" index=\"" << rr_sb.get_node_index(cur_rr_node, oppo_side.get_side(), IN_PORT) << "\"/>"
|
||||||
|
<< std::endl;
|
||||||
|
} else {
|
||||||
|
for (size_t jnode = 0; jnode < num_drive_rr_nodes; ++jnode) {
|
||||||
|
enum e_side drive_node_side = NUM_SIDES;
|
||||||
|
int drive_node_index = -1;
|
||||||
|
rr_sb.get_node_side_and_index(drive_rr_nodes[jnode], IN_PORT, &drive_node_side, &drive_node_index);
|
||||||
|
Side drive_side(drive_node_side);
|
||||||
|
std::string node_type_str;
|
||||||
|
if (OPIN == drive_rr_nodes[jnode]->type) {
|
||||||
|
node_type_str = "opin";
|
||||||
|
} else {
|
||||||
|
node_type_str = convert_chan_type_to_string(drive_rr_nodes[jnode]->type);
|
||||||
|
}
|
||||||
|
fp << "\t\t<drive_node type=\"" << node_type_str
|
||||||
|
<< "\" side=\"" << drive_side.to_string()
|
||||||
|
<< "\" index=\"" << drive_node_index << "\"/>"
|
||||||
|
<< std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fp << "\t</" << convert_chan_type_to_string(cur_rr_node->type) << ">" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fp << "</rr_sb>" << std::endl;
|
||||||
|
|
||||||
|
/* close a file */
|
||||||
|
fp.close();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Output each rr_switch_block to a XML file */
|
||||||
|
void write_device_rr_switch_block_to_xml(DeviceRRSwitchBlock& LL_device_rr_switch_block) {
|
||||||
|
std::string fname_prefix("/var/tmp/xtang/sb_xml/");
|
||||||
|
DeviceCoordinator sb_range = LL_device_rr_switch_block.get_switch_block_range();
|
||||||
|
|
||||||
|
/* For each switch block, an XML file will be outputted */
|
||||||
|
for (size_t ix = 0; ix < sb_range.get_x(); ++ix) {
|
||||||
|
for (size_t iy = 0; iy < sb_range.get_y(); ++iy) {
|
||||||
|
RRSwitchBlock rr_sb = LL_device_rr_switch_block.get_switch_block(ix, iy);
|
||||||
|
write_rr_switch_block_to_xml(fname_prefix, rr_sb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
#ifndef WRITE_RR_BLOCKS_H
|
||||||
|
#define WRITE_RR_BLOCKS_H
|
||||||
|
|
||||||
|
void write_rr_switch_block_to_xml(std::string fname_prefix, RRSwitchBlock& rr_sb) {
|
||||||
|
|
||||||
|
void write_device_rr_switch_block_to_xml(DeviceRRSwitchBlock& LL_device_rr_switch_block);
|
||||||
|
|
||||||
|
#endif
|
|
@ -1033,10 +1033,13 @@ void verilog_generate_sdc_disable_unused_sbs_muxs(FILE* fp) {
|
||||||
}
|
}
|
||||||
t_rr_node* cur_rr_node = rr_sb.get_chan_node(side_manager.get_side(), itrack);
|
t_rr_node* cur_rr_node = rr_sb.get_chan_node(side_manager.get_side(), itrack);
|
||||||
for (int imux = 0 ; imux < cur_rr_node->fan_in; ++imux) {
|
for (int imux = 0 ; imux < cur_rr_node->fan_in; ++imux) {
|
||||||
|
if (1 == cur_rr_node->fan_in) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (imux == cur_rr_node->id_path) {
|
if (imux == cur_rr_node->id_path) {
|
||||||
fprintf(fp, "#"); // comments out if the node is active
|
fprintf(fp, "#"); // comments out if the node is active
|
||||||
}
|
}
|
||||||
//if(cur_rr_node->name_mux == NULL) assert (NULL != cur_rr_node->name_mux);
|
//if(cur_rr_node->name_mux == NULL) assert (NULL != cur_rr_node->name_mux);
|
||||||
fprintf(fp, "set_disable_timing %s[%d]\n",
|
fprintf(fp, "set_disable_timing %s[%d]\n",
|
||||||
cur_rr_node->name_mux, imux);
|
cur_rr_node->name_mux, imux);
|
||||||
}
|
}
|
||||||
|
@ -1070,10 +1073,13 @@ void verilog_generate_sdc_disable_unused_sbs_muxs(FILE* fp, int LL_nx, int LL_ny
|
||||||
if (OUT_PORT == cur_sb_info->chan_rr_node_direction[side][itrack]) {
|
if (OUT_PORT == cur_sb_info->chan_rr_node_direction[side][itrack]) {
|
||||||
cur_rr_node = cur_sb_info->chan_rr_node[side][itrack];
|
cur_rr_node = cur_sb_info->chan_rr_node[side][itrack];
|
||||||
for (imux = 0 ; imux < cur_rr_node-> fan_in; imux++) {
|
for (imux = 0 ; imux < cur_rr_node-> fan_in; imux++) {
|
||||||
|
if (1 == cur_rr_node->fan_in) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (imux == cur_rr_node->id_path) {
|
if (imux == cur_rr_node->id_path) {
|
||||||
fprintf(fp, "#"); // comments out if the node is active
|
fprintf(fp, "#"); // comments out if the node is active
|
||||||
}
|
}
|
||||||
//if(cur_rr_node->name_mux == NULL) assert (NULL != cur_rr_node->name_mux);
|
//if(cur_rr_node->name_mux == NULL) assert (NULL != cur_rr_node->name_mux);
|
||||||
fprintf(fp, "set_disable_timing %s[%d]\n",
|
fprintf(fp, "set_disable_timing %s[%d]\n",
|
||||||
cur_rr_node->name_mux, imux);
|
cur_rr_node->name_mux, imux);
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,7 @@ set vpr_route_chan_width = 200
|
||||||
#make -j32
|
#make -j32
|
||||||
# Remove previous designs
|
# Remove previous designs
|
||||||
rm -rf $verilog_output_dirpath/$verilog_output_dirname
|
rm -rf $verilog_output_dirpath/$verilog_output_dirname
|
||||||
|
rm -rf $verilog_output_dirpath/$verilog_output_dirname\_compact
|
||||||
|
|
||||||
# Run VPR
|
# Run VPR
|
||||||
#valgrind
|
#valgrind
|
||||||
|
|
Loading…
Reference in New Issue