add rr_blocks XML writer to help debugging Switch Block Rotation

This commit is contained in:
tangxifan 2019-05-28 14:52:44 -06:00
parent c75ffa858b
commit af91fca1e0
4 changed files with 177 additions and 29 deletions

View File

@ -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, rotated_rr_switch_block.get_y() - 1); 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, rotated_rr_switch_block.get_y() - 1); 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, rotated_rr_switch_block.get_x() - 1); 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, rotated_rr_switch_block.get_x() - 1); 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.
@ -1184,7 +1211,7 @@ DeviceRRSwitchBlock build_device_rr_switch_blocks(int LL_num_rr_nodes, t_rr_node
/* For each switch block, determine the size of array */ /* For each switch block, determine the size of array */
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 = build_rr_switch_block(sb_range, ix, iy, RRSwitchBlock rr_sb = build_rr_switch_block(sb_range, ix, iy,
LL_num_rr_nodes, LL_rr_node, LL_num_rr_nodes, LL_rr_node,
LL_rr_node_indices, LL_rr_node_indices,
num_segments, LL_rr_indexed_data); num_segments, LL_rr_indexed_data);
@ -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;
} }

View File

@ -203,7 +203,7 @@ void RRChan::rotate_by_node_direction(enum e_direction node_direction, size_t of
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] == get_node_segment(inode)) ) { && (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));
} }
@ -219,7 +219,7 @@ 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] == get_node_segment(inode)) ) { && (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 */
@ -255,7 +255,7 @@ void RRChan::counter_rotate_by_node_direction(enum e_direction node_direction, s
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] == get_node_segment(inode)) ) { && (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));
} }
@ -271,7 +271,7 @@ 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] == get_node_segment(inode)) ) { && (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 */
@ -1118,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);
@ -1857,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;

View File

@ -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;
}

View File

@ -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