OpenFPGA/openfpga/src/annotation/device_rr_gsb.cpp

489 lines
16 KiB
C++

/************************************************************************
* Member functions for class DeviceRRGSB
***********************************************************************/
#include "vtr_log.h"
#include "vtr_assert.h"
#include "device_rr_gsb.h"
/* namespace openfpga begins */
namespace openfpga {
/************************************************************************
* Constructors
***********************************************************************/
/************************************************************************
* Public accessors
***********************************************************************/
/* get the max coordinate of the switch block array */
vtr::Point<size_t> DeviceRRGSB::get_gsb_range() const {
size_t max_y = 0;
/* Get the largest size of sub-arrays */
for (size_t x = 0; x < rr_gsb_.size(); ++x) {
max_y = std::max(max_y, rr_gsb_[x].size());
}
vtr::Point<size_t> coordinate(rr_gsb_.size(), max_y);
return coordinate;
}
/* Get a rr switch block in the array with a coordinate */
const RRGSB& DeviceRRGSB::get_gsb(const vtr::Point<size_t>& coordinate) const {
VTR_ASSERT(validate_coordinate(coordinate));
return rr_gsb_[coordinate.x()][coordinate.y()];
}
/* Get a rr switch block in the array with a coordinate */
const RRGSB& DeviceRRGSB::get_gsb(const size_t& x, const size_t& y) const {
vtr::Point<size_t> coordinate(x, y);
return get_gsb(coordinate);
}
/* get the number of unique mirrors of switch blocks */
size_t DeviceRRGSB::get_num_cb_unique_module(const t_rr_type& cb_type) const {
VTR_ASSERT (validate_cb_type(cb_type));
switch(cb_type) {
case CHANX:
return cbx_unique_module_.size();
case CHANY:
return cby_unique_module_.size();
default:
VTR_LOG_ERROR("Invalid type of connection block!\n");
exit(1);
}
}
/* Identify if a GSB actually exists at a location */
bool DeviceRRGSB::is_gsb_exist(const vtr::Point<size_t> coord) const {
/* Out of range, does not exist */
if (false == validate_coordinate(coord)) {
return false;
}
/* If the GSB is empty, it does not exist */
if (true == get_gsb(coord).is_cb_exist(CHANX)) {
return true;
}
if (true == get_gsb(coord).is_cb_exist(CHANY)) {
return true;
}
if (true == get_gsb(coord).is_sb_exist()) {
return true;
}
return false;
}
/* get the number of unique mirrors of switch blocks */
size_t DeviceRRGSB::get_num_sb_unique_module() const {
return sb_unique_module_.size();
}
/* get the number of unique mirrors of switch blocks */
size_t DeviceRRGSB::get_num_gsb_unique_module() const {
return gsb_unique_module_.size();
}
/* Get a rr switch block which a unique mirror */
const RRGSB& DeviceRRGSB::get_sb_unique_module(const size_t& index) const {
VTR_ASSERT (validate_sb_unique_module_index(index));
return rr_gsb_[sb_unique_module_[index].x()][sb_unique_module_[index].y()];
}
/* Get a rr switch block which a unique mirror */
const RRGSB& DeviceRRGSB::get_cb_unique_module(const t_rr_type& cb_type, const size_t& index) const {
VTR_ASSERT (validate_cb_unique_module_index(cb_type, index));
VTR_ASSERT (validate_cb_type(cb_type));
switch(cb_type) {
case CHANX:
return rr_gsb_[cbx_unique_module_[index].x()][cbx_unique_module_[index].y()];
case CHANY:
return rr_gsb_[cby_unique_module_[index].x()][cby_unique_module_[index].y()];
default:
VTR_LOG_ERROR("Invalid type of connection block!\n");
exit(1);
}
}
/* Give a coordinate of a rr switch block, and return its unique mirror */
const RRGSB& DeviceRRGSB::get_cb_unique_module(const t_rr_type& cb_type, const vtr::Point<size_t>& coordinate) const {
VTR_ASSERT(validate_cb_type(cb_type));
VTR_ASSERT(validate_coordinate(coordinate));
size_t cb_unique_module_id;
switch(cb_type) {
case CHANX:
cb_unique_module_id = cbx_unique_module_id_[coordinate.x()][coordinate.y()];
break;
case CHANY:
cb_unique_module_id = cby_unique_module_id_[coordinate.x()][coordinate.y()];
break;
default:
VTR_LOG_ERROR("Invalid type of connection block!\n");
exit(1);
}
return get_cb_unique_module(cb_type, cb_unique_module_id);
}
/* Give a coordinate of a rr switch block, and return its unique mirror */
const RRGSB& DeviceRRGSB::get_sb_unique_module(const vtr::Point<size_t>& coordinate) const {
VTR_ASSERT(validate_coordinate(coordinate));
size_t sb_unique_module_id = sb_unique_module_id_[coordinate.x()][coordinate.y()];
return get_sb_unique_module(sb_unique_module_id);
}
/************************************************************************
* Public mutators
***********************************************************************/
/* Pre-allocate the rr_switch_block array that the device requires */
void DeviceRRGSB::reserve(const vtr::Point<size_t>& coordinate) {
rr_gsb_.resize(coordinate.x());
gsb_unique_module_id_.resize(coordinate.x());
sb_unique_module_id_.resize(coordinate.x());
cbx_unique_module_id_.resize(coordinate.x());
cby_unique_module_id_.resize(coordinate.x());
for (size_t x = 0; x < coordinate.x(); ++x) {
rr_gsb_[x].resize(coordinate.y());
gsb_unique_module_id_[x].resize(coordinate.y());
sb_unique_module_id_[x].resize(coordinate.y());
cbx_unique_module_id_[x].resize(coordinate.y());
cby_unique_module_id_[x].resize(coordinate.y());
}
}
/* Resize rr_switch_block array is needed*/
void DeviceRRGSB::resize_upon_need(const vtr::Point<size_t>& coordinate) {
if (coordinate.x() + 1 > rr_gsb_.size()) {
rr_gsb_.resize(coordinate.x() + 1);
sb_unique_module_id_.resize(coordinate.x() + 1);
cbx_unique_module_id_.resize(coordinate.x() + 1);
cby_unique_module_id_.resize(coordinate.x() + 1);
}
if (coordinate.y() + 1 > rr_gsb_[coordinate.x()].size()) {
rr_gsb_[coordinate.x()].resize(coordinate.y() + 1);
sb_unique_module_id_[coordinate.x()].resize(coordinate.y() + 1);
cbx_unique_module_id_[coordinate.x()].resize(coordinate.y() + 1);
cby_unique_module_id_[coordinate.x()].resize(coordinate.y() + 1);
}
}
/* Add a switch block to the array, which will automatically identify and update the lists of unique mirrors and rotatable mirrors */
void DeviceRRGSB::add_rr_gsb(const vtr::Point<size_t>& coordinate,
const RRGSB& rr_gsb) {
/* Resize upon needs*/
resize_upon_need(coordinate);
/* Add the switch block into array */
rr_gsb_[coordinate.x()][coordinate.y()] = rr_gsb;
}
/* Get a rr switch block in the array with a coordinate */
RRGSB& DeviceRRGSB::get_mutable_gsb(const vtr::Point<size_t>& coordinate) {
VTR_ASSERT(validate_coordinate(coordinate));
return rr_gsb_[coordinate.x()][coordinate.y()];
}
/* Get a rr switch block in the array with a coordinate */
RRGSB& DeviceRRGSB::get_mutable_gsb(const size_t& x, const size_t& y) {
vtr::Point<size_t> coordinate(x, y);
return get_mutable_gsb(coordinate);
}
/* Add a switch block to the array, which will automatically identify and update the lists of unique mirrors and rotatable mirrors */
void DeviceRRGSB::build_cb_unique_module(const RRGraph& rr_graph, const t_rr_type& cb_type) {
/* Make sure a clean start */
clear_cb_unique_module(cb_type);
for (size_t ix = 0; ix < rr_gsb_.size(); ++ix) {
for (size_t iy = 0; iy < rr_gsb_[ix].size(); ++iy) {
bool is_unique_module = true;
vtr::Point<size_t> gsb_coordinate(ix, iy);
/* Bypass non-exist CB */
if ( false == rr_gsb_[ix][iy].is_cb_exist(cb_type) ) {
continue;
}
/* Traverse the unique_mirror list and check it is an mirror of another */
for (size_t id = 0; id < get_num_cb_unique_module(cb_type); ++id) {
const RRGSB& unique_module = get_cb_unique_module(cb_type, id);
if (true == rr_gsb_[ix][iy].is_cb_mirror(rr_graph, unique_module, cb_type)) {
/* This is a mirror, raise the flag and we finish */
is_unique_module = false;
/* Record the id of unique mirror */
set_cb_unique_module_id(cb_type, gsb_coordinate, id);
break;
}
}
/* Add to list if this is a unique mirror*/
if (true == is_unique_module) {
add_cb_unique_module(cb_type, gsb_coordinate);
/* Record the id of unique mirror */
set_cb_unique_module_id(cb_type, gsb_coordinate, get_num_cb_unique_module(cb_type) - 1);
}
}
}
}
/* Add a switch block to the array, which will automatically identify and update the lists of unique mirrors and rotatable mirrors */
void DeviceRRGSB::build_sb_unique_module(const RRGraph& rr_graph) {
/* Make sure a clean start */
clear_sb_unique_module();
/* Build the unique module */
for (size_t ix = 0; ix < rr_gsb_.size(); ++ix) {
for (size_t iy = 0; iy < rr_gsb_[ix].size(); ++iy) {
bool is_unique_module = true;
vtr::Point<size_t> sb_coordinate(ix, iy);
/* Traverse the unique_mirror list and check it is an mirror of another */
for (size_t id = 0; id < get_num_sb_unique_module(); ++id) {
/* Check if the two modules have the same submodules,
* if so, these two modules are the same, indicating the sb is not unique.
* else the sb is unique
*/
const RRGSB& unique_module = get_sb_unique_module(id);
if (true == rr_gsb_[ix][iy].is_sb_mirror(rr_graph, unique_module)) {
/* This is a mirror, raise the flag and we finish */
is_unique_module = false;
/* Record the id of unique mirror */
sb_unique_module_id_[ix][iy] = id;
break;
}
}
/* Add to list if this is a unique mirror*/
if (true == is_unique_module) {
sb_unique_module_.push_back(sb_coordinate);
/* Record the id of unique mirror */
sb_unique_module_id_[ix][iy] = sb_unique_module_.size() - 1;
}
}
}
}
/* Add a switch block to the array, which will automatically identify and update the lists of unique mirrors and rotatable mirrors */
/* Find repeatable GSB block in the array */
void DeviceRRGSB::build_gsb_unique_module() {
/* Make sure a clean start */
clear_gsb_unique_module();
for (size_t ix = 0; ix < rr_gsb_.size(); ++ix) {
for (size_t iy = 0; iy < rr_gsb_[ix].size(); ++iy) {
bool is_unique_module = true;
vtr::Point<size_t> gsb_coordinate(ix, iy);
/* Traverse the unique_mirror list and check it is an mirror of another */
for (size_t id = 0; id < get_num_gsb_unique_module(); ++id) {
/* We have alreay built sb and cb unique module list
* We just need to check if the unique module id of SBs, CBX and CBY are the same or not
*/
const vtr::Point<size_t>& gsb_unique_module_coordinate = gsb_unique_module_[id];
if ((sb_unique_module_id_[ix][iy] == sb_unique_module_id_[gsb_unique_module_coordinate.x()][gsb_unique_module_coordinate.y()])
&& (cbx_unique_module_id_[ix][iy] == cbx_unique_module_id_[gsb_unique_module_coordinate.x()][gsb_unique_module_coordinate.y()])
&& (cby_unique_module_id_[ix][iy] == cby_unique_module_id_[gsb_unique_module_coordinate.x()][gsb_unique_module_coordinate.y()])) {
/* This is a mirror, raise the flag and we finish */
is_unique_module = false;
/* Record the id of unique mirror */
gsb_unique_module_id_[ix][iy] = id;
break;
}
}
/* Add to list if this is a unique mirror*/
if (true == is_unique_module) {
add_gsb_unique_module(gsb_coordinate);
/* Record the id of unique mirror */
gsb_unique_module_id_[ix][iy] = get_num_gsb_unique_module() - 1;
}
}
}
}
void DeviceRRGSB::build_unique_module(const RRGraph& rr_graph) {
build_sb_unique_module(rr_graph);
build_cb_unique_module(rr_graph, CHANX);
build_cb_unique_module(rr_graph, CHANY);
build_gsb_unique_module();
}
void DeviceRRGSB::add_gsb_unique_module(const vtr::Point<size_t>& coordinate) {
gsb_unique_module_.push_back(coordinate);
}
void DeviceRRGSB::add_cb_unique_module(const t_rr_type& cb_type, const vtr::Point<size_t>& coordinate) {
VTR_ASSERT (validate_cb_type(cb_type));
switch(cb_type) {
case CHANX:
cbx_unique_module_.push_back(coordinate);
return;
case CHANY:
cby_unique_module_.push_back(coordinate);
return;
default:
VTR_LOG_ERROR("Invalid type of connection block!\n");
exit(1);
}
}
void DeviceRRGSB::set_cb_unique_module_id(const t_rr_type& cb_type, const vtr::Point<size_t>& coordinate, size_t id) {
VTR_ASSERT(validate_cb_type(cb_type));
size_t x = coordinate.x();
size_t y = coordinate.y();
switch(cb_type) {
case CHANX:
cbx_unique_module_id_[x][y] = id;
return;
case CHANY:
cby_unique_module_id_[x][y] = id;
return;
default:
VTR_LOG_ERROR("Invalid type of connection block!\n");
exit(1);
}
}
/************************************************************************
* Public clean-up functions:
***********************************************************************/
/* clean the content */
void DeviceRRGSB::clear() {
clear_gsb();
clear_gsb_unique_module();
clear_gsb_unique_module_id();
/* clean unique module lists */
clear_cb_unique_module(CHANX);
clear_cb_unique_module_id(CHANX);
clear_cb_unique_module(CHANY);
clear_cb_unique_module_id(CHANY);
clear_sb_unique_module();
clear_sb_unique_module_id();
}
void DeviceRRGSB::clear_gsb() {
/* clean gsb array */
for (size_t x = 0; x < rr_gsb_.size(); ++x) {
rr_gsb_[x].clear();
}
rr_gsb_.clear();
}
void DeviceRRGSB::clear_gsb_unique_module_id() {
/* clean rr_switch_block array */
for (size_t x = 0; x < rr_gsb_.size(); ++x) {
gsb_unique_module_id_[x].clear();
}
}
void DeviceRRGSB::clear_sb_unique_module_id() {
/* clean rr_switch_block array */
for (size_t x = 0; x < rr_gsb_.size(); ++x) {
sb_unique_module_id_[x].clear();
}
}
void DeviceRRGSB::clear_cb_unique_module_id(const t_rr_type& cb_type) {
VTR_ASSERT (validate_cb_type(cb_type));
switch(cb_type) {
case CHANX:
for (size_t x = 0; x < rr_gsb_.size(); ++x) {
cbx_unique_module_id_[x].clear();
}
return;
case CHANY:
for (size_t x = 0; x < rr_gsb_.size(); ++x) {
cby_unique_module_id_[x].clear();
}
return;
default:
VTR_LOG_ERROR("Invalid type of connection block!\n");
exit(1);
}
}
/* clean the content related to unique_mirrors */
void DeviceRRGSB::clear_gsb_unique_module() {
/* clean unique mirror */
gsb_unique_module_.clear();
}
/* clean the content related to unique_mirrors */
void DeviceRRGSB::clear_sb_unique_module() {
/* clean unique mirror */
sb_unique_module_.clear();
}
void DeviceRRGSB::clear_cb_unique_module(const t_rr_type& cb_type) {
VTR_ASSERT (validate_cb_type(cb_type));
switch(cb_type) {
case CHANX:
cbx_unique_module_.clear();
return;
case CHANY:
cby_unique_module_.clear();
return;
default:
VTR_LOG_ERROR("Invalid type of connection block!\n");
exit(1);
}
}
/************************************************************************
* Internal validators
***********************************************************************/
/* Validate if the (x,y) is the range of this device */
bool DeviceRRGSB::validate_coordinate(const vtr::Point<size_t>& coordinate) const {
if (coordinate.x() >= rr_gsb_.capacity()) {
return false;
}
return (coordinate.y() < rr_gsb_[coordinate.x()].capacity());
}
/* Validate if the index in the range of unique_mirror vector*/
bool DeviceRRGSB::validate_sb_unique_module_index(const size_t& index) const {
return (index < sb_unique_module_.size());
}
bool DeviceRRGSB::validate_cb_unique_module_index(const t_rr_type& cb_type, const size_t& index) const {
VTR_ASSERT(validate_cb_type(cb_type));
switch(cb_type) {
case CHANX:
return (index < cbx_unique_module_.size());
case CHANY:
return (index < cby_unique_module_.size());
default:
VTR_LOG_ERROR("Invalid type of connection block!\n");
exit(1);
}
return false;
}
bool DeviceRRGSB::validate_cb_type(const t_rr_type& cb_type) const {
return ((CHANX == cb_type) || (CHANY == cb_type));
}
} /* End namespace openfpga*/