update class rr_switch_block and be ready for updating the downstream verilog generator
This commit is contained in:
parent
502344b13a
commit
4aab93b729
|
@ -0,0 +1,57 @@
|
|||
#include <algorithm>
|
||||
#include "device_coordinator.h"
|
||||
|
||||
/* Member functions for DeviceCoordinator */
|
||||
/* Public constructors */
|
||||
/*
|
||||
DeviceCoordinator::DeviceCoordinator(DeviceCoordinator& coordinator) {
|
||||
set(coordinator.get_x(), coordinator.get_y());
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
DeviceCoordinator::DeviceCoordinator(size_t x, size_t y) {
|
||||
set(x, y);
|
||||
return;
|
||||
}
|
||||
|
||||
DeviceCoordinator::DeviceCoordinator() {
|
||||
set(0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Public accessors */
|
||||
size_t DeviceCoordinator::get_x() const {
|
||||
return x_;
|
||||
}
|
||||
|
||||
size_t DeviceCoordinator::get_y() const {
|
||||
return y_;
|
||||
}
|
||||
|
||||
/* Public mutators */
|
||||
void DeviceCoordinator::set(size_t x, size_t y) {
|
||||
set_x(x);
|
||||
set_y(y);
|
||||
return;
|
||||
}
|
||||
|
||||
void DeviceCoordinator::set_x(size_t x) {
|
||||
x_ = x;
|
||||
return;
|
||||
}
|
||||
|
||||
void DeviceCoordinator::set_y(size_t y) {
|
||||
y_ = y;
|
||||
return;
|
||||
}
|
||||
|
||||
void DeviceCoordinator::rotate() {
|
||||
std::swap(x_, y_);
|
||||
return;
|
||||
}
|
||||
|
||||
void DeviceCoordinator::clear() {
|
||||
set(0, 0);
|
||||
return;
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
#ifndef DEVICE_COORDINATOR_H
|
||||
#define DEVICE_COORDINATOR_H
|
||||
|
||||
/* Coordinator System for FPGA Device
|
||||
* It is based on a 3-D (x,y,z) coordinator system
|
||||
* (x,y) is used for all the routing resources,
|
||||
* z is used for only grid, which have multiple logic blocks
|
||||
*/
|
||||
class DeviceCoordinator {
|
||||
public: /* Contructors */
|
||||
/*
|
||||
DeviceCoordinator(DeviceCoordinator& coordinator);
|
||||
*/
|
||||
DeviceCoordinator(size_t x, size_t y);
|
||||
DeviceCoordinator();
|
||||
public: /* Accessors */
|
||||
size_t get_x() const;
|
||||
size_t get_y() const;
|
||||
public: /* Mutators */
|
||||
void set(size_t x, size_t y);
|
||||
void set_x(size_t x);
|
||||
void set_y(size_t y);
|
||||
void rotate();
|
||||
void clear();
|
||||
private: /* Internal Mutators */
|
||||
private: /* internal functions */
|
||||
private: /* Internal Data */
|
||||
size_t x_;
|
||||
size_t y_;
|
||||
size_t z_;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -27,6 +27,7 @@
|
|||
/* Include spice support headers*/
|
||||
#include "read_xml_spice_util.h"
|
||||
#include "linkedlist.h"
|
||||
#include "rr_blocks.h"
|
||||
#include "fpga_x2p_types.h"
|
||||
#include "fpga_x2p_globals.h"
|
||||
#include "fpga_x2p_utils.h"
|
||||
|
@ -35,6 +36,7 @@
|
|||
#include "fpga_x2p_pbtypes_utils.h"
|
||||
#include "fpga_x2p_pb_rr_graph.h"
|
||||
#include "fpga_x2p_router.h"
|
||||
#include "fpga_x2p_unique_routing.h"
|
||||
|
||||
/* Get initial value of a Latch/FF output*/
|
||||
int get_ff_output_init_val(t_logical_block* ff_logical_block) {
|
||||
|
@ -3127,6 +3129,7 @@ void spice_backannotate_vpr_post_route_info(t_det_routing_arch RoutingArch,
|
|||
/* Build Array for each Switch block and Connection block */
|
||||
vpr_printf(TIO_MESSAGE_INFO, "Collecting detailed information for each Switch block...\n");
|
||||
alloc_and_build_switch_blocks_info(RoutingArch, num_rr_nodes, rr_node, rr_node_indices);
|
||||
device_rr_switch_block = build_device_rr_switch_blocks(RoutingArch, num_rr_nodes, rr_node, rr_node_indices);
|
||||
|
||||
vpr_printf(TIO_MESSAGE_INFO, "Collecting detailed information for each to Connection block...\n");
|
||||
alloc_and_build_connection_blocks_info(RoutingArch, num_rr_nodes, rr_node, rr_node_indices);
|
||||
|
|
|
@ -46,3 +46,4 @@ char* fpga_spice_bitstream_routing_log_file_postfix = "_routing_bitstream.log";
|
|||
char* default_sdc_folder = "SDC/";
|
||||
|
||||
DeviceRRChan device_rr_chan;
|
||||
DeviceRRSwitchBlock device_rr_switch_block;
|
||||
|
|
|
@ -41,5 +41,6 @@ extern char* fpga_spice_bitstream_logic_block_log_file_postfix;
|
|||
extern char* fpga_spice_bitstream_routing_log_file_postfix;
|
||||
|
||||
extern DeviceRRChan device_rr_chan;
|
||||
extern DeviceRRSwitchBlock device_rr_switch_block;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -80,6 +80,13 @@ RRChan build_one_rr_chan(t_rr_type chan_type, size_t chan_x, size_t chan_y,
|
|||
|
||||
void print_device_rr_chan_stats(DeviceRRChan& device_rr_chan);
|
||||
|
||||
static
|
||||
RRSwitchBlock build_rr_switch_block(int sb_x, int sb_y,
|
||||
t_det_routing_arch RoutingArch,
|
||||
int LL_num_rr_nodes,
|
||||
t_rr_node* LL_rr_node,
|
||||
t_ivec*** LL_rr_node_indices);
|
||||
|
||||
/***** subroutines *****/
|
||||
void assign_switch_block_mirror(t_sb* src, t_sb* des) {
|
||||
assert ( (NULL != src) && (NULL != des) );
|
||||
|
@ -796,6 +803,288 @@ DeviceRRChan build_device_rr_chan(int LL_num_rr_nodes, t_rr_node* LL_rr_node,
|
|||
return LL_device_rr_chan;
|
||||
}
|
||||
|
||||
/* Build arrays for rr_nodes of each Switch Blocks
|
||||
* A Switch Box subckt consists of following ports:
|
||||
* 1. Channel Y [x][y] inputs
|
||||
* 2. Channel X [x+1][y] inputs
|
||||
* 3. Channel Y [x][y-1] outputs
|
||||
* 4. Channel X [x][y] outputs
|
||||
* 5. Grid[x][y+1] Right side outputs pins
|
||||
* 6. Grid[x+1][y+1] Left side output pins
|
||||
* 7. Grid[x+1][y+1] Bottom side output pins
|
||||
* 8. Grid[x+1][y] Top side output pins
|
||||
* 9. Grid[x+1][y] Left side output pins
|
||||
* 10. Grid[x][y] Right side output pins
|
||||
* 11. Grid[x][y] Top side output pins
|
||||
* 12. Grid[x][y+1] Bottom side output pins
|
||||
*
|
||||
* -------------- --------------
|
||||
* | | | |
|
||||
* | Grid | ChanY | Grid |
|
||||
* | [x][y+1] | [x][y+1] | [x+1][y+1] |
|
||||
* | | | |
|
||||
* -------------- --------------
|
||||
* ----------
|
||||
* ChanX | Switch | ChanX
|
||||
* [x][y] | Box | [x+1][y]
|
||||
* | [x][y] |
|
||||
* ----------
|
||||
* -------------- --------------
|
||||
* | | | |
|
||||
* | Grid | ChanY | Grid |
|
||||
* | [x][y] | [x][y] | [x+1][y] |
|
||||
* | | | |
|
||||
* -------------- --------------
|
||||
* For channels chanY with INC_DIRECTION on the top side, they should be marked as outputs
|
||||
* For channels chanY with DEC_DIRECTION on the top side, they should be marked as inputs
|
||||
* For channels chanY with INC_DIRECTION on the bottom side, they should be marked as inputs
|
||||
* For channels chanY with DEC_DIRECTION on the bottom side, they should be marked as outputs
|
||||
* For channels chanX with INC_DIRECTION on the left side, they should be marked as inputs
|
||||
* For channels chanX with DEC_DIRECTION on the left side, they should be marked as outputs
|
||||
* For channels chanX with INC_DIRECTION on the right side, they should be marked as outputs
|
||||
* For channels chanX with DEC_DIRECTION on the right side, they should be marked as inputs
|
||||
*/
|
||||
static
|
||||
RRSwitchBlock build_rr_switch_block(int sb_x, int sb_y,
|
||||
t_det_routing_arch RoutingArch,
|
||||
int LL_num_rr_nodes,
|
||||
t_rr_node* LL_rr_node,
|
||||
t_ivec*** LL_rr_node_indices) {
|
||||
/* Create an object to return */
|
||||
RRSwitchBlock rr_switch_block;
|
||||
|
||||
/* Check */
|
||||
assert((!(0 > sb_x))&&(!(sb_x > (nx + 1))));
|
||||
assert((!(0 > sb_y))&&(!(sb_y > (ny + 1))));
|
||||
|
||||
/* Basic information*/
|
||||
rr_switch_block.init_num_sides(4); /* Fixed number of sides */
|
||||
|
||||
/* Find all rr_nodes of channels */
|
||||
/* Side: TOP => 0, RIGHT => 1, BOTTOM => 2, LEFT => 3 */
|
||||
for (size_t side = 0; side < rr_switch_block.get_num_sides(); ++side) {
|
||||
/* Local variables inside this for loop */
|
||||
Side side_manager(side);
|
||||
int ix = 0;
|
||||
int iy = 0;
|
||||
int chan_width = 0;
|
||||
t_rr_node** chan_rr_node = NULL;
|
||||
int temp_num_opin_rr_nodes[2] = {0,0};
|
||||
t_rr_node** temp_opin_rr_node[2] = {NULL, NULL};
|
||||
enum e_side opin_grid_side[2] = {NUM_SIDES, NUM_SIDES};
|
||||
enum PORTS chan_dir_to_port_dir_mapping[2] = {OUT_PORT, IN_PORT}; /* 0: INC_DIRECTION => ?; 1: DEC_DIRECTION => ? */
|
||||
switch (side) {
|
||||
case 0: /* TOP */
|
||||
/* For the bording, we should take special care */
|
||||
if (sb_y == ny) {
|
||||
rr_switch_block.clear_one_side(side_manager.get_side());
|
||||
break;
|
||||
}
|
||||
/* Routing channels*/
|
||||
ix = sb_x;
|
||||
iy = sb_y + 1;
|
||||
/* Channel width */
|
||||
chan_width = chan_width_y[ix];
|
||||
/* Side: TOP => 0, RIGHT => 1, BOTTOM => 2, LEFT => 3 */
|
||||
chan_rr_node = get_chan_rr_nodes(&chan_width, CHANY, ix, iy,
|
||||
LL_num_rr_nodes, LL_rr_node, LL_rr_node_indices);
|
||||
chan_dir_to_port_dir_mapping[0] = OUT_PORT;
|
||||
chan_dir_to_port_dir_mapping[1] = IN_PORT;
|
||||
|
||||
/* Include Grid[x][y+1] RIGHT side outputs pins */
|
||||
temp_opin_rr_node[0] = get_grid_side_pin_rr_nodes(&temp_num_opin_rr_nodes[0],
|
||||
OPIN, sb_x, sb_y + 1, 1,
|
||||
LL_num_rr_nodes, LL_rr_node, LL_rr_node_indices);
|
||||
/* Include Grid[x+1][y+1] Left side output pins */
|
||||
temp_opin_rr_node[1] = get_grid_side_pin_rr_nodes(&temp_num_opin_rr_nodes[1],
|
||||
OPIN, sb_x + 1, sb_y + 1, 3,
|
||||
LL_num_rr_nodes, LL_rr_node, LL_rr_node_indices);
|
||||
|
||||
/* Assign grid side of OPIN */
|
||||
/* Grid[x][y+1] RIGHT side outputs pins */
|
||||
opin_grid_side[0] = RIGHT;
|
||||
/* Grid[x+1][y+1] left side outputs pins */
|
||||
opin_grid_side[1] = LEFT;
|
||||
break;
|
||||
case 1: /* RIGHT */
|
||||
/* For the bording, we should take special care */
|
||||
if (sb_x == nx) {
|
||||
rr_switch_block.clear_one_side(side_manager.get_side());
|
||||
break;
|
||||
}
|
||||
/* Routing channels*/
|
||||
ix = sb_x + 1;
|
||||
iy = sb_y;
|
||||
/* Channel width */
|
||||
chan_width = chan_width_x[iy];
|
||||
/* Side: TOP => 0, RIGHT => 1, BOTTOM => 2, LEFT => 3 */
|
||||
/* Collect rr_nodes for Tracks for top: chany[x][y+1] */
|
||||
chan_rr_node = get_chan_rr_nodes(&chan_width, CHANX, ix, iy,
|
||||
LL_num_rr_nodes, LL_rr_node, LL_rr_node_indices);
|
||||
chan_dir_to_port_dir_mapping[0] = OUT_PORT;
|
||||
chan_dir_to_port_dir_mapping[1] = IN_PORT;
|
||||
|
||||
/* include Grid[x+1][y+1] Bottom side output pins */
|
||||
temp_opin_rr_node[0] = get_grid_side_pin_rr_nodes(&temp_num_opin_rr_nodes[0],
|
||||
OPIN, sb_x + 1, sb_y + 1, 2,
|
||||
LL_num_rr_nodes, LL_rr_node, LL_rr_node_indices);
|
||||
/* include Grid[x+1][y] Top side output pins */
|
||||
temp_opin_rr_node[1] = get_grid_side_pin_rr_nodes(&temp_num_opin_rr_nodes[1],
|
||||
OPIN, sb_x + 1, sb_y, 0,
|
||||
LL_num_rr_nodes, LL_rr_node, LL_rr_node_indices);
|
||||
/* Assign grid side of OPIN */
|
||||
/* Grid[x+1][y+1] BOTTOM side outputs pins */
|
||||
opin_grid_side[0] = BOTTOM;
|
||||
/* Grid[x+1][y] TOP side outputs pins */
|
||||
opin_grid_side[1] = TOP;
|
||||
break;
|
||||
case 2:
|
||||
/* For the bording, we should take special care */
|
||||
if (sb_y == 0) {
|
||||
rr_switch_block.clear_one_side(side_manager.get_side());
|
||||
break;
|
||||
}
|
||||
/* Routing channels*/
|
||||
ix = sb_x;
|
||||
iy = sb_y;
|
||||
/* Channel width */
|
||||
chan_width = chan_width_y[ix];
|
||||
/* Side: TOP => 0, RIGHT => 1, BOTTOM => 2, LEFT => 3 */
|
||||
/* Collect rr_nodes for Tracks for bottom: chany[x][y] */
|
||||
chan_rr_node = get_chan_rr_nodes(&chan_width, CHANY, ix, iy,
|
||||
LL_num_rr_nodes, LL_rr_node, LL_rr_node_indices);
|
||||
chan_dir_to_port_dir_mapping[0] = IN_PORT;
|
||||
chan_dir_to_port_dir_mapping[1] = OUT_PORT;
|
||||
|
||||
/* TODO: include Grid[x+1][y] Left side output pins */
|
||||
temp_opin_rr_node[0] = get_grid_side_pin_rr_nodes(&temp_num_opin_rr_nodes[0],
|
||||
OPIN, sb_x + 1, sb_y, 3,
|
||||
LL_num_rr_nodes, LL_rr_node, LL_rr_node_indices);
|
||||
/* TODO: include Grid[x][y] Right side output pins */
|
||||
temp_opin_rr_node[1] = get_grid_side_pin_rr_nodes(&temp_num_opin_rr_nodes[1],
|
||||
OPIN, sb_x, sb_y, 1,
|
||||
LL_num_rr_nodes, LL_rr_node, LL_rr_node_indices);
|
||||
/* Assign grid side of OPIN */
|
||||
/* Grid[x+1][y] LEFT side outputs pins */
|
||||
opin_grid_side[0] = LEFT;
|
||||
/* Grid[x][y] RIGHT side outputs pins */
|
||||
opin_grid_side[1] = RIGHT;
|
||||
break;
|
||||
case 3:
|
||||
/* For the bording, we should take special care */
|
||||
if (sb_x == 0) {
|
||||
rr_switch_block.clear_one_side(side_manager.get_side());
|
||||
break;
|
||||
}
|
||||
/* Routing channels*/
|
||||
ix = sb_x;
|
||||
iy = sb_y;
|
||||
/* Channel width */
|
||||
chan_width = chan_width_x[iy];
|
||||
/* Side: TOP => 0, RIGHT => 1, BOTTOM => 2, LEFT => 3 */
|
||||
/* Collect rr_nodes for Tracks for left: chanx[x][y] */
|
||||
chan_rr_node = get_chan_rr_nodes(&chan_width, CHANX, ix, iy,
|
||||
LL_num_rr_nodes, LL_rr_node, LL_rr_node_indices);
|
||||
chan_dir_to_port_dir_mapping[0] = IN_PORT;
|
||||
chan_dir_to_port_dir_mapping[1] = OUT_PORT;
|
||||
|
||||
/* include Grid[x][y+1] Bottom side outputs pins */
|
||||
temp_opin_rr_node[0] = get_grid_side_pin_rr_nodes(&temp_num_opin_rr_nodes[0],
|
||||
OPIN, sb_x, sb_y + 1, 2,
|
||||
LL_num_rr_nodes, LL_rr_node, LL_rr_node_indices);
|
||||
/* include Grid[x][y] Top side output pins */
|
||||
temp_opin_rr_node[1] = get_grid_side_pin_rr_nodes(&temp_num_opin_rr_nodes[1],
|
||||
OPIN, sb_x, sb_y, 0,
|
||||
LL_num_rr_nodes, LL_rr_node, LL_rr_node_indices);
|
||||
|
||||
/* Grid[x][y+1] BOTTOM side outputs pins */
|
||||
opin_grid_side[0] = BOTTOM;
|
||||
/* Grid[x][y] TOP side outputs pins */
|
||||
opin_grid_side[0] = TOP;
|
||||
break;
|
||||
default:
|
||||
vpr_printf(TIO_MESSAGE_ERROR,
|
||||
"(File:%s, [LINE%d])Invalid side index!\n",
|
||||
__FILE__, __LINE__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Fill chan_rr_nodes */
|
||||
for (int itrack = 0; itrack < chan_width; ++itrack) {
|
||||
/* Identify the directionality, record it in rr_node_direction */
|
||||
if (INC_DIRECTION == chan_rr_node[itrack]->direction) {
|
||||
rr_switch_block.add_chan_node(chan_rr_node[itrack], side_manager.get_side(), chan_dir_to_port_dir_mapping[0]);
|
||||
} else {
|
||||
assert (DEC_DIRECTION == chan_rr_node[itrack]->direction);
|
||||
rr_switch_block.add_chan_node(chan_rr_node[itrack], side_manager.get_side(), chan_dir_to_port_dir_mapping[1]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Fill opin_rr_nodes */
|
||||
/* Copy from temp_opin_rr_node to opin_rr_node */
|
||||
for (int inode = 0; inode < temp_num_opin_rr_nodes[0]; ++inode) {
|
||||
/* Grid[x+1][y+1] Bottom side outputs pins */
|
||||
rr_switch_block.add_opin_node(temp_opin_rr_node[0][inode], side_manager.get_side(), opin_grid_side[0]);
|
||||
}
|
||||
for (int inode = 0; inode < temp_num_opin_rr_nodes[1]; ++inode) {
|
||||
/* Grid[x+1][y] TOP side outputs pins */
|
||||
rr_switch_block.add_opin_node(temp_opin_rr_node[1][inode], side_manager.get_side(), opin_grid_side[1]);
|
||||
}
|
||||
|
||||
/* Clean ipin_rr_nodes */
|
||||
/* We do not have any IPIN for a Switch Block */
|
||||
rr_switch_block.clear_ipin_nodes(side_manager.get_side());
|
||||
|
||||
/* Free */
|
||||
temp_num_opin_rr_nodes[0] = 0;
|
||||
my_free(temp_opin_rr_node[0]);
|
||||
temp_num_opin_rr_nodes[1] = 0;
|
||||
my_free(temp_opin_rr_node[1]);
|
||||
/* Set them to NULL, avoid double free errors */
|
||||
temp_opin_rr_node[0] = NULL;
|
||||
temp_opin_rr_node[1] = NULL;
|
||||
opin_grid_side[0] = NUM_SIDES;
|
||||
opin_grid_side[1] = NUM_SIDES;
|
||||
}
|
||||
|
||||
return rr_switch_block;
|
||||
}
|
||||
|
||||
|
||||
/* 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
|
||||
* Each switch block in the FPGA fabric will be an instance of these modules.
|
||||
* We maintain a map from each instance to each module
|
||||
*/
|
||||
DeviceRRSwitchBlock build_device_rr_switch_blocks(t_det_routing_arch RoutingArch,
|
||||
int LL_num_rr_nodes,
|
||||
t_rr_node* LL_rr_node,
|
||||
t_ivec*** LL_rr_node_indices) {
|
||||
/* Create an object */
|
||||
DeviceRRSwitchBlock LL_device_rr_switch_block;
|
||||
|
||||
/* Initialize */
|
||||
DeviceCoordinator device_coordinator(size_t(nx + 1), size_t(ny + 1));
|
||||
LL_device_rr_switch_block.reserve(device_coordinator);
|
||||
|
||||
/* For each switch block, determine the size of array */
|
||||
for (int ix = 0; ix < (nx + 1); ++ix) {
|
||||
for (int iy = 0; iy < (ny + 1); ++iy) {
|
||||
RRSwitchBlock rr_switch_block = build_rr_switch_block(ix, iy, RoutingArch,
|
||||
LL_num_rr_nodes, LL_rr_node, LL_rr_node_indices);
|
||||
DeviceCoordinator sb_coordinator(ix, iy);
|
||||
LL_device_rr_switch_block.add_rr_switch_block(sb_coordinator, rr_switch_block);
|
||||
}
|
||||
}
|
||||
|
||||
/* Report number of unique mirrors */
|
||||
vpr_printf(TIO_MESSAGE_INFO,
|
||||
"Detect %d independent switch blocks from %d switch blocks.\n",
|
||||
LL_device_rr_switch_block.get_num_unique_mirror(), (nx + 1) * (ny + 1) );
|
||||
|
||||
return LL_device_rr_switch_block;
|
||||
}
|
||||
|
||||
|
||||
/* Rotatable will be done in the next step
|
||||
void identify_rotatable_switch_blocks();
|
||||
|
|
|
@ -9,6 +9,16 @@ DeviceRRChan build_device_rr_chan(int LL_num_rr_nodes, t_rr_node* LL_rr_node,
|
|||
t_ivec*** LL_rr_node_indices, int num_segments,
|
||||
t_rr_indexed_data* LL_rr_indexed_data);
|
||||
|
||||
/* 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
|
||||
* Each switch block in the FPGA fabric will be an instance of these modules.
|
||||
* We maintain a map from each instance to each module
|
||||
*/
|
||||
DeviceRRSwitchBlock build_device_rr_switch_blocks(t_det_routing_arch RoutingArch,
|
||||
int LL_num_rr_nodes,
|
||||
t_rr_node* LL_rr_node,
|
||||
t_ivec*** LL_rr_node_indices);
|
||||
|
||||
/* Rotatable will be done in the next step
|
||||
identify_rotatable_switch_blocks();
|
||||
identify_rotatable_connection_blocks();
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
#include <cassert>
|
||||
#include <algorithm>
|
||||
|
||||
#include "rr_blocks.h"
|
||||
|
||||
|
||||
/* Member Functions of Class RRChan */
|
||||
/* accessors */
|
||||
/* Accessors */
|
||||
t_rr_type RRChan::get_type() const {
|
||||
return type_;
|
||||
}
|
||||
|
@ -560,7 +561,133 @@ bool RRSwitchBlock::is_mirror(RRSwitchBlock& cand) const {
|
|||
return true;
|
||||
}
|
||||
|
||||
/* Internal functions */
|
||||
/* Public mutators */
|
||||
/* Allocate the vectors with the given number of sides */
|
||||
void RRSwitchBlock::init_num_sides(size_t num_sides) {
|
||||
/* Initialize the vectors */
|
||||
chan_rr_node_direction_.resize(num_sides);
|
||||
chan_rr_node_.resize(num_sides);
|
||||
ipin_rr_node_.resize(num_sides);
|
||||
ipin_rr_node_grid_side_.resize(num_sides);
|
||||
opin_rr_node_.resize(num_sides);
|
||||
opin_rr_node_grid_side_.resize(num_sides);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Add a node to the chan_rr_node_ list and also assign its direction in chan_rr_node_direction_ */
|
||||
void RRSwitchBlock::add_chan_node(t_rr_node* node, enum e_side node_side, enum PORTS node_direction) {
|
||||
Side side_manager(node_side);
|
||||
assert(validate_side(node_side));
|
||||
/* resize the array if needed, node is placed in the sequence of node->ptc_num */
|
||||
if (size_t(node->ptc_num + 1) > chan_rr_node_[side_manager.to_size_t()].size()) {
|
||||
chan_rr_node_[side_manager.to_size_t()].resize(node->ptc_num + 1); /* resize to the maximum */
|
||||
chan_rr_node_direction_[side_manager.to_size_t()].resize(node->ptc_num + 1); /* resize to the maximum */
|
||||
}
|
||||
/* fill the dedicated element in the vector */
|
||||
chan_rr_node_[side_manager.to_size_t()][node->ptc_num] = node;
|
||||
chan_rr_node_direction_[side_manager.to_size_t()][node->ptc_num] = node_direction;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Add a node to the chan_rr_node_ list and also assign its direction in chan_rr_node_direction_ */
|
||||
void RRSwitchBlock::add_ipin_node(t_rr_node* node, enum e_side node_side, enum e_side grid_side) {
|
||||
Side side_manager(node_side);
|
||||
assert(validate_side(node_side));
|
||||
/* push pack the dedicated element in the vector */
|
||||
ipin_rr_node_[side_manager.to_size_t()].push_back(node);
|
||||
ipin_rr_node_grid_side_[side_manager.to_size_t()].push_back(grid_side);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Add a node to the chan_rr_node_ list and also assign its direction in chan_rr_node_direction_ */
|
||||
void RRSwitchBlock::add_opin_node(t_rr_node* node, enum e_side node_side, enum e_side grid_side) {
|
||||
Side side_manager(node_side);
|
||||
assert(validate_side(node_side));
|
||||
/* push pack the dedicated element in the vector */
|
||||
opin_rr_node_[side_manager.to_size_t()].push_back(node);
|
||||
opin_rr_node_grid_side_[side_manager.to_size_t()].push_back(grid_side);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void RRSwitchBlock::set_num_reserved_conf_bits(size_t num_reserved_conf_bits) {
|
||||
num_reserved_conf_bits_ = num_reserved_conf_bits;
|
||||
return;
|
||||
}
|
||||
|
||||
void RRSwitchBlock::set_num_conf_bits(size_t num_conf_bits) {
|
||||
num_conf_bits_ = num_conf_bits;
|
||||
return;
|
||||
}
|
||||
|
||||
void RRSwitchBlock::clear() {
|
||||
/* Clean all the vectors */
|
||||
assert(validate_num_sides());
|
||||
/* Clear the inner vector of each matrix */
|
||||
for (size_t side = 0; side < get_num_sides(); ++side) {
|
||||
chan_rr_node_direction_[side].clear();
|
||||
chan_rr_node_[side].clear();
|
||||
ipin_rr_node_[side].clear();
|
||||
ipin_rr_node_grid_side_[side].clear();
|
||||
opin_rr_node_[side].clear();
|
||||
opin_rr_node_grid_side_[side].clear();
|
||||
}
|
||||
chan_rr_node_direction_.clear();
|
||||
chan_rr_node_.clear();
|
||||
ipin_rr_node_.clear();
|
||||
ipin_rr_node_grid_side_.clear();
|
||||
opin_rr_node_.clear();
|
||||
opin_rr_node_grid_side_.clear();
|
||||
|
||||
set_num_reserved_conf_bits(0);
|
||||
set_num_conf_bits(0);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Clean the chan_width of a side */
|
||||
void RRSwitchBlock::clear_chan_nodes(enum e_side node_side) {
|
||||
Side side_manager(node_side);
|
||||
assert(validate_side(node_side));
|
||||
|
||||
chan_rr_node_[side_manager.to_size_t()].clear();
|
||||
chan_rr_node_direction_[side_manager.to_size_t()].clear();
|
||||
return;
|
||||
}
|
||||
|
||||
/* Clean the number of IPINs of a side */
|
||||
void RRSwitchBlock::clear_ipin_nodes(enum e_side node_side) {
|
||||
Side side_manager(node_side);
|
||||
assert(validate_side(node_side));
|
||||
|
||||
ipin_rr_node_[side_manager.to_size_t()].clear();
|
||||
ipin_rr_node_grid_side_[side_manager.to_size_t()].clear();
|
||||
return;
|
||||
}
|
||||
|
||||
/* Clean the number of OPINs of a side */
|
||||
void RRSwitchBlock::clear_opin_nodes(enum e_side node_side) {
|
||||
Side side_manager(node_side);
|
||||
assert(validate_side(node_side));
|
||||
|
||||
opin_rr_node_[side_manager.to_size_t()].clear();
|
||||
opin_rr_node_grid_side_[side_manager.to_size_t()].clear();
|
||||
return;
|
||||
}
|
||||
|
||||
/* Clean chan/opin/ipin nodes at one side */
|
||||
void RRSwitchBlock::clear_one_side(enum e_side node_side) {
|
||||
clear_chan_nodes(node_side);
|
||||
clear_ipin_nodes(node_side);
|
||||
clear_opin_nodes(node_side);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* Internal functions for validation */
|
||||
|
||||
/* check if two rr_nodes have a similar set of drive_rr_nodes
|
||||
* for each drive_rr_node:
|
||||
|
@ -665,3 +792,151 @@ bool RRSwitchBlock::validate_track_id(enum e_side side, size_t track_id) const {
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Member Functions of Class RRChan */
|
||||
/* Accessors */
|
||||
|
||||
/* get the max coordinator of the switch block array */
|
||||
DeviceCoordinator DeviceRRSwitchBlock::get_switch_block_range() const {
|
||||
size_t max_y = 0;
|
||||
/* Get the largest size of sub-arrays */
|
||||
for (size_t x = 0; x < rr_switch_block_.size(); ++x) {
|
||||
max_y = std::max(max_y, rr_switch_block_[x].size());
|
||||
}
|
||||
|
||||
DeviceCoordinator coordinator(rr_switch_block_.size(), max_y);
|
||||
return coordinator;
|
||||
}
|
||||
|
||||
/* Get a rr switch block in the array with a coordinator */
|
||||
RRSwitchBlock DeviceRRSwitchBlock::get_switch_block(DeviceCoordinator coordinator) const {
|
||||
assert(validate_coordinator(coordinator));
|
||||
return rr_switch_block_[coordinator.get_x()][coordinator.get_y()];
|
||||
}
|
||||
|
||||
/* Get a rr switch block in the array with a coordinator */
|
||||
RRSwitchBlock DeviceRRSwitchBlock::get_switch_block(size_t x, size_t y) const {
|
||||
DeviceCoordinator coordinator(x, y);
|
||||
return get_switch_block(coordinator);
|
||||
}
|
||||
|
||||
/* get the number of unique mirrors of switch blocks */
|
||||
size_t DeviceRRSwitchBlock::get_num_unique_mirror() const {
|
||||
return unique_mirror_.size();
|
||||
}
|
||||
|
||||
/* get the number of rotatable mirrors of switch blocks */
|
||||
size_t DeviceRRSwitchBlock::get_num_rotatable_mirror() const {
|
||||
return rotatable_mirror_.size();
|
||||
}
|
||||
|
||||
/* Get a rr switch block which a unique mirror */
|
||||
RRSwitchBlock DeviceRRSwitchBlock::get_unique_mirror(size_t index) const {
|
||||
assert (validate_unique_mirror_index(index));
|
||||
|
||||
return rr_switch_block_[unique_mirror_[index].get_x()][unique_mirror_[index].get_y()];
|
||||
}
|
||||
|
||||
/* Get a rr switch block which a unique mirror */
|
||||
RRSwitchBlock DeviceRRSwitchBlock::get_rotatable_mirror(size_t index) const {
|
||||
assert (validate_rotatable_mirror_index(index));
|
||||
|
||||
return rr_switch_block_[rotatable_mirror_[index].get_x()][rotatable_mirror_[index].get_y()];
|
||||
}
|
||||
|
||||
/* Public Mutators */
|
||||
|
||||
/* Pre-allocate the rr_switch_block array that the device requires */
|
||||
void DeviceRRSwitchBlock::reserve(DeviceCoordinator& coordinator) {
|
||||
rr_switch_block_.reserve(coordinator.get_x());
|
||||
for (size_t x = 0; x < coordinator.get_x(); ++x) {
|
||||
rr_switch_block_[x].reserve(coordinator.get_y());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Resize rr_switch_block array is needed*/
|
||||
void DeviceRRSwitchBlock::resize_upon_need(DeviceCoordinator& coordinator) {
|
||||
if (coordinator.get_x() + 1 > rr_switch_block_.capacity()) {
|
||||
rr_switch_block_.resize(coordinator.get_x());
|
||||
}
|
||||
|
||||
if (coordinator.get_y() + 1 > rr_switch_block_[coordinator.get_x()].capacity()) {
|
||||
rr_switch_block_[coordinator.get_x()].resize(coordinator.get_y());
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Add a switch block to the array, which will automatically identify and update the lists of unique mirrors and rotatable mirrors */
|
||||
void DeviceRRSwitchBlock::add_rr_switch_block(DeviceCoordinator& coordinator,
|
||||
RRSwitchBlock& rr_switch_block) {
|
||||
bool is_unique_mirror = true;
|
||||
|
||||
/* Resize upon needs*/
|
||||
resize_upon_need(coordinator);
|
||||
|
||||
/* Add the switch block into array */
|
||||
rr_switch_block_[coordinator.get_x()][coordinator.get_y()] = rr_switch_block;
|
||||
|
||||
/* Traverse the unique_mirror list and check it is an mirror of another */
|
||||
for (size_t mirror_id = 0; mirror_id < get_num_unique_mirror(); ++mirror_id) {
|
||||
if (true == get_switch_block(unique_mirror_[mirror_id]).is_mirror(rr_switch_block)) {
|
||||
/* This is a mirror, raise the flag and we finish */
|
||||
is_unique_mirror = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Add to list if this is a unique mirror*/
|
||||
if (true == is_unique_mirror) {
|
||||
unique_mirror_.push_back(coordinator);
|
||||
}
|
||||
|
||||
/* TODO: add rotatable mirror support */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* clean the content */
|
||||
void DeviceRRSwitchBlock::clear() {
|
||||
/* clean rr_switch_block array */
|
||||
for (size_t x = 0; x < rr_switch_block_.size(); ++x) {
|
||||
rr_switch_block_[x].clear();
|
||||
}
|
||||
rr_switch_block_.clear();
|
||||
|
||||
/* clean unique mirror */
|
||||
unique_mirror_.clear();
|
||||
|
||||
/* clean unique mirror */
|
||||
rotatable_mirror_.clear();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Validate if the (x,y) is the range of this device */
|
||||
bool DeviceRRSwitchBlock::validate_coordinator(DeviceCoordinator& coordinator) const {
|
||||
if (coordinator.get_x() >= rr_switch_block_.capacity()) {
|
||||
return false;
|
||||
}
|
||||
if (coordinator.get_y() >= rr_switch_block_[coordinator.get_x()].capacity()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Validate if the index in the range of unique_mirror vector*/
|
||||
bool DeviceRRSwitchBlock::validate_unique_mirror_index(size_t index) const {
|
||||
if (index >= unique_mirror_.size()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Validate if the index in the range of unique_mirror vector*/
|
||||
bool DeviceRRSwitchBlock::validate_rotatable_mirror_index(size_t index) const {
|
||||
if (index >= rotatable_mirror_.size()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
/* Standard header files required go first */
|
||||
#include <vector>
|
||||
|
||||
#include "device_coordinator.h"
|
||||
#include "vpr_types.h"
|
||||
|
||||
/* RRChan coordinator class */
|
||||
|
@ -134,6 +135,18 @@ class RRSwitchBlock {
|
|||
bool is_node_imply_short_connection(t_rr_node* src_node) const; /* Check if the node imply a short connection inside the SB, which happens to long wires across a FPGA fabric */
|
||||
bool is_mirror(RRSwitchBlock& cand) const; /* check if the candidate SB is a mirror of the current one */
|
||||
public: /* Mutators */
|
||||
void init_num_sides(size_t num_sides); /* Allocate the vectors with the given number of sides */
|
||||
void add_chan_node(t_rr_node* node, enum e_side node_side, enum PORTS node_direction); /* Add a node to the chan_rr_node_ list and also assign its direction in chan_rr_node_direction_ */
|
||||
void add_ipin_node(t_rr_node* node, enum e_side node_side, enum e_side grid_side); /* Add a node to the chan_rr_node_ list and also assign its direction in chan_rr_node_direction_ */
|
||||
void add_opin_node(t_rr_node* node, enum e_side node_side, enum e_side grid_side); /* Add a node to the chan_rr_node_ list and also assign its direction in chan_rr_node_direction_ */
|
||||
void set_num_reserved_conf_bits(size_t num_reserved_conf_bits);
|
||||
void set_num_conf_bits(size_t num_conf_bits);
|
||||
void clear();
|
||||
void clear_chan_nodes(enum e_side node_side); /* Clean the chan_width of a side */
|
||||
void clear_ipin_nodes(enum e_side node_side); /* Clean the number of IPINs of a side */
|
||||
void clear_opin_nodes(enum e_side node_side); /* Clean the number of OPINs of a side */
|
||||
void clear_one_side(enum e_side node_side); /* Clean chan/opin/ipin nodes at one side */
|
||||
private: /* Internal Mutators */
|
||||
private: /* internal functions */
|
||||
bool is_node_mirror (RRSwitchBlock& cand, enum e_side node_side, size_t track_id) const;
|
||||
bool validate_num_sides() const;
|
||||
|
@ -150,5 +163,38 @@ class RRSwitchBlock {
|
|||
size_t num_conf_bits_;
|
||||
};
|
||||
|
||||
/* Object Device Routing Resource Switch Block
|
||||
* This includes:
|
||||
* 1. a collection of RRSwitch blocks, each of which can be used to instance Switch blocks in the top-level netlists
|
||||
* 2. a collection of unique mirrors of RRSwitchBlocks, which can be used to output Verilog / SPICE modules
|
||||
* 3. a colleciton of unique rotatable of RRSwitchBlocks, which can be used to output Verilog / SPICE modules
|
||||
* The rotatable RRSwitchBlocks are more generic mirrors, which allow SwitchBlocks to be wired by rotating the pins,
|
||||
* further reduce the number of Verilog/SPICE modules outputted. This will lead to rapid layout generation
|
||||
*/
|
||||
class DeviceRRSwitchBlock {
|
||||
public: /* Contructors */
|
||||
public: /* Accessors */
|
||||
DeviceCoordinator get_switch_block_range() const; /* get the max coordinator of the switch block array */
|
||||
RRSwitchBlock get_switch_block(DeviceCoordinator coordinator) const; /* Get a rr switch block in the array with a coordinator */
|
||||
RRSwitchBlock get_switch_block(size_t x, size_t y) const; /* Get a rr switch block in the array with a coordinator */
|
||||
size_t get_num_unique_mirror() const; /* get the number of unique mirrors of switch blocks */
|
||||
size_t get_num_rotatable_mirror() const; /* get the number of rotatable mirrors of switch blocks */
|
||||
RRSwitchBlock get_unique_mirror(size_t index) const; /* Get a rr switch block which a unique mirror */
|
||||
RRSwitchBlock get_rotatable_mirror(size_t index) const; /* Get a rr switch block which a unique mirror */
|
||||
public: /* Mutators */
|
||||
void reserve(DeviceCoordinator& coordinator); /* Pre-allocate the rr_switch_block array that the device requires */
|
||||
void resize_upon_need(DeviceCoordinator& coordinator); /* Resize the rr_switch_block array if needed */
|
||||
void add_rr_switch_block(DeviceCoordinator& coordinator, RRSwitchBlock& rr_switch_block); /* 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 */
|
||||
private: /* Validators */
|
||||
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_rotatable_mirror_index(size_t index) const; /* Validate if the index in the range of unique_mirror vector*/
|
||||
private: /* Internal Data */
|
||||
std::vector< std::vector<RRSwitchBlock> > rr_switch_block_;
|
||||
std::vector<DeviceCoordinator> unique_mirror_;
|
||||
std::vector<DeviceCoordinator> rotatable_mirror_;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
|
Loading…
Reference in New Issue