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 spice support headers*/
|
||||||
#include "read_xml_spice_util.h"
|
#include "read_xml_spice_util.h"
|
||||||
#include "linkedlist.h"
|
#include "linkedlist.h"
|
||||||
|
#include "rr_blocks.h"
|
||||||
#include "fpga_x2p_types.h"
|
#include "fpga_x2p_types.h"
|
||||||
#include "fpga_x2p_globals.h"
|
#include "fpga_x2p_globals.h"
|
||||||
#include "fpga_x2p_utils.h"
|
#include "fpga_x2p_utils.h"
|
||||||
|
@ -35,6 +36,7 @@
|
||||||
#include "fpga_x2p_pbtypes_utils.h"
|
#include "fpga_x2p_pbtypes_utils.h"
|
||||||
#include "fpga_x2p_pb_rr_graph.h"
|
#include "fpga_x2p_pb_rr_graph.h"
|
||||||
#include "fpga_x2p_router.h"
|
#include "fpga_x2p_router.h"
|
||||||
|
#include "fpga_x2p_unique_routing.h"
|
||||||
|
|
||||||
/* Get initial value of a Latch/FF output*/
|
/* Get initial value of a Latch/FF output*/
|
||||||
int get_ff_output_init_val(t_logical_block* ff_logical_block) {
|
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 */
|
/* Build Array for each Switch block and Connection block */
|
||||||
vpr_printf(TIO_MESSAGE_INFO, "Collecting detailed information for each Switch block...\n");
|
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);
|
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");
|
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);
|
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/";
|
char* default_sdc_folder = "SDC/";
|
||||||
|
|
||||||
DeviceRRChan device_rr_chan;
|
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 char* fpga_spice_bitstream_routing_log_file_postfix;
|
||||||
|
|
||||||
extern DeviceRRChan device_rr_chan;
|
extern DeviceRRChan device_rr_chan;
|
||||||
|
extern DeviceRRSwitchBlock device_rr_switch_block;
|
||||||
|
|
||||||
#endif
|
#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);
|
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 *****/
|
/***** subroutines *****/
|
||||||
void assign_switch_block_mirror(t_sb* src, t_sb* des) {
|
void assign_switch_block_mirror(t_sb* src, t_sb* des) {
|
||||||
assert ( (NULL != src) && (NULL != 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;
|
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
|
/* Rotatable will be done in the next step
|
||||||
void identify_rotatable_switch_blocks();
|
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_ivec*** LL_rr_node_indices, int num_segments,
|
||||||
t_rr_indexed_data* LL_rr_indexed_data);
|
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
|
/* Rotatable will be done in the next step
|
||||||
identify_rotatable_switch_blocks();
|
identify_rotatable_switch_blocks();
|
||||||
identify_rotatable_connection_blocks();
|
identify_rotatable_connection_blocks();
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
#include "rr_blocks.h"
|
#include "rr_blocks.h"
|
||||||
|
|
||||||
|
|
||||||
/* Member Functions of Class RRChan */
|
/* Member Functions of Class RRChan */
|
||||||
/* accessors */
|
/* Accessors */
|
||||||
t_rr_type RRChan::get_type() const {
|
t_rr_type RRChan::get_type() const {
|
||||||
return type_;
|
return type_;
|
||||||
}
|
}
|
||||||
|
@ -560,7 +561,133 @@ bool RRSwitchBlock::is_mirror(RRSwitchBlock& cand) const {
|
||||||
return true;
|
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
|
/* check if two rr_nodes have a similar set of drive_rr_nodes
|
||||||
* for each drive_rr_node:
|
* 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;
|
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 */
|
/* Standard header files required go first */
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "device_coordinator.h"
|
||||||
#include "vpr_types.h"
|
#include "vpr_types.h"
|
||||||
|
|
||||||
/* RRChan coordinator class */
|
/* 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_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 */
|
bool is_mirror(RRSwitchBlock& cand) const; /* check if the candidate SB is a mirror of the current one */
|
||||||
public: /* Mutators */
|
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 */
|
private: /* internal functions */
|
||||||
bool is_node_mirror (RRSwitchBlock& cand, enum e_side node_side, size_t track_id) const;
|
bool is_node_mirror (RRSwitchBlock& cand, enum e_side node_side, size_t track_id) const;
|
||||||
bool validate_num_sides() const;
|
bool validate_num_sides() const;
|
||||||
|
@ -150,5 +163,38 @@ class RRSwitchBlock {
|
||||||
size_t num_conf_bits_;
|
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
|
#endif
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue