OpenFPGA/vpr7_x2p/vpr/SRC/fpga_x2p/base/rr_chan.cpp

271 lines
7.0 KiB
C++

#include <cassert>
#include "rr_chan.h"
/* Member Functions of Class RRChan */
/* accessors */
t_rr_type RRChan::get_type() const {
return type_;
}
/* get the number of tracks in this channel */
size_t RRChan::get_chan_width() const {
return nodes_.size();
}
/* get the track_id of a node */
int RRChan::get_node_track_id(t_rr_node* node) const {
/* if the given node is NULL, we return an invalid id */
if (NULL == node) {
return -1; /* FIXME: use a strong id!!! */
}
/* check each member and return if we find a match in content */
for (size_t inode = 0; inode < nodes_.size(); ++inode) {
if (node == nodes_[inode]) {
return inode;
}
}
return -1;
}
/* get the rr_node with the track_id */
t_rr_node* RRChan::get_node(size_t track_num) const {
if ( false == valid_node_id(track_num) ) {
return NULL;
}
return nodes_[track_num];
}
/* get the segment id of a node */
int RRChan::get_node_segment(t_rr_node* node) const {
int node_id = get_node_track_id(node);
if ( false == valid_node_id(node_id)) {
return -1;
}
return get_node_segment(node_id);
}
/* get the segment id of a node */
int RRChan::get_node_segment(size_t track_num) const {
if ( false == valid_node_id(track_num)) {
return -1;
}
return node_segments_[track_num];
}
/* evaluate if two RRChan is mirror to each other */
bool RRChan::is_mirror(RRChan& cand) const {
/* If any following element does not match, it is not mirror */
/* 1. type */
if (this->get_type() != cand.get_type()) {
return false;
}
/* 2. track_width */
if (this->get_chan_width() != cand.get_chan_width()) {
return false;
}
/* 3. for each node */
for (size_t inode = 0; inode < this->get_chan_width(); ++inode) {
/* 3.1 check node type */
if (this->get_node(inode)->type != cand.get_node(inode)->type) {
return false;
}
/* 3.2 check node directionality */
if (this->get_node(inode)->direction != cand.get_node(inode)->direction) {
return false;
}
/* 3.3 check node segment */
if (this->get_node_segment(inode) != cand.get_node_segment(inode)) {
return false;
}
}
return true;
}
/* Mutators */
/* modify type */
void RRChan::set_type(t_rr_type type) {
assert(valid_type(type));
type_ = type;
return;
}
/* add a node to the array */
void RRChan::add_node(t_rr_node* node, size_t node_segment) {
/* resize the array if needed, node is placed in the sequence of node->ptc_num */
if (size_t(node->ptc_num) > (nodes_.size() + 1)) {
nodes_.resize(node->ptc_num + 1); /* resize to the maximum */
node_segments_.resize(node->ptc_num + 1); /* resize to the maximum */
}
/* fill the dedicated element in the vector */
nodes_[node->ptc_num] = node;
node_segments_[node->ptc_num] = node_segment;
return;
}
/* Clear content */
void RRChan::clear() {
nodes_.clear();
node_segments_.clear();
return;
}
/* Internal functions */
/* for type, only valid type is CHANX and CHANY */
bool RRChan::valid_type(t_rr_type type) const {
if ((CHANX == type) && (CHANY == type)) {
return true;
}
return false;
}
/* check if the node id is valid */
bool RRChan::valid_node_id(size_t node_id) const {
if ( (size_t(-1) < node_id) && (node_id < nodes_.size()) ) {
return true;
}
return false;
}
/* Member Functions of Class DeviceRRChan */
/* accessors */
RRChan DeviceRRChan::get_module(t_rr_type chan_type, size_t module_id) const {
assert(valid_module_id(chan_type, module_id));
if (CHANX == chan_type) {
return chanx_modules_[module_id];
} else if (CHANY == chan_type) {
return chany_modules_[module_id];
}
}
void DeviceRRChan::init_module_ids(size_t device_width, size_t device_height) {
init_chan_module_ids(CHANX, device_width, device_height);
init_chan_module_ids(CHANY, device_width, device_height);
return;
}
void DeviceRRChan::init_chan_module_ids(t_rr_type chan_type, size_t device_width, size_t device_height) {
assert(valid_chan_type(chan_type));
if (CHANX == chan_type) {
chanx_module_ids_.resize(device_width);
for (size_t x = 0; x < chanx_module_ids_.size(); ++x) {
chanx_module_ids_[x].resize(device_height);
}
} else if (CHANY == chan_type) {
chany_module_ids_.resize(device_width);
for (size_t x = 0; x < chany_module_ids_.size(); ++x) {
chany_module_ids_[x].resize(device_height);
}
}
return;
}
void DeviceRRChan::add_one_chan_module(t_rr_type chan_type, size_t x, size_t y, RRChan rr_chan) {
assert(valid_coordinator(chan_type, x, y));
if (CHANX == chan_type) {
/* Find if the module is unique */
for (size_t i = 0; i < chanx_modules_.size(); ++i) {
if ( true == chanx_modules_[i].is_mirror(rr_chan)) {
/* Find a mirror in the list, assign ids and return */
chanx_module_ids_[x][y] = i;
return;
}
}
/* Reach here, it means this is a unique module */
/* add to the module list */
chanx_modules_.push_back(rr_chan);
chanx_module_ids_[x][y] = chanx_modules_.size() - 1;
} else if (CHANY == chan_type) {
/* Find if the module is unique */
for (size_t i = 0; i < chany_modules_.size(); ++i) {
if ( true == chany_modules_[i].is_mirror(rr_chan)) {
/* Find a mirror in the list, assign ids and return */
chany_module_ids_[x][y] = i;
return;
}
}
/* Reach here, it means this is a unique module */
/* add to the module list */
chany_modules_.push_back(rr_chan);
chany_module_ids_[x][y] = chany_modules_.size() - 1;
}
return;
}
void DeviceRRChan::clear() {
clear_chan(CHANX);
clear_chan(CHANY);
}
void DeviceRRChan::clear_chan(t_rr_type chan_type) {
assert(valid_chan_type(chan_type));
if (CHANX == chan_type) {
chanx_modules_.clear();
} else if (CHANY == chan_type) {
chany_modules_.clear();
}
return;
}
/* for type, only valid type is CHANX and CHANY */
bool DeviceRRChan::valid_chan_type(t_rr_type chan_type) const {
if ((CHANX == chan_type) && (CHANY == chan_type)) {
return true;
}
return false;
}
/* check if the coordinator is in range */
bool DeviceRRChan::valid_coordinator(t_rr_type chan_type, size_t x, size_t y) const {
assert(valid_chan_type(chan_type));
if (CHANX == chan_type) {
if (!( (size_t(-1) < x) && (x < chanx_module_ids_.size()) )) {
return false;
}
if (!( (size_t(-1) < y) && (y < chanx_module_ids_[x].size()) )) {
return false;
}
} else if (CHANY == chan_type) {
if (!( (size_t(-1) < x) && (x < chany_module_ids_.size()) )) {
return false;
}
if (!( (size_t(-1) < y) && (y < chany_module_ids_[x].size()) )) {
return false;
}
}
return true;
}
/* check if the node id is valid */
bool DeviceRRChan::valid_module_id(t_rr_type chan_type, size_t module_id) const {
assert(valid_chan_type(chan_type));
if (CHANX == chan_type) {
if ( (size_t(-1) < module_id) && (module_id < chanx_modules_.size()) ) {
return true;
}
} else if (CHANY == chan_type) {
if ( (size_t(-1) < module_id) && (module_id < chany_modules_.size()) ) {
return true;
}
}
return false;
}