add rr_chan obj

This commit is contained in:
tangxifan 2019-05-10 22:50:08 -06:00
parent 9c05a4fb0a
commit 3313eac23b
8 changed files with 371 additions and 14 deletions

View File

@ -31,7 +31,7 @@ find_package(Readline REQUIRED)
#Collect the source files
file(GLOB_RECURSE EXEC_SOURCES SRC/main.c)
file(GLOB_RECURSE EXEC_SOURCES_SHELL SRC/shell_main.c)
file(GLOB_RECURSE LIB_SOURCES SRC/*/*.c SRC/*/*/*.c)
file(GLOB_RECURSE LIB_SOURCES SRC/*/*.c SRC/*/*/*.c SRC/*/*.cpp SRC/*/*/*.cpp)
file(GLOB_RECURSE LIB_HEADERS SRC/*/*.h SRC/*/*/*.h)
files_to_dirs(LIB_HEADERS LIB_INCLUDE_DIRS)

View File

@ -0,0 +1,270 @@
#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;
}

View File

@ -0,0 +1,74 @@
/* IMPORTANT:
* The following preprocessing flags are added to
* avoid compilation error when this headers are included in more than 1 times
*/
#ifndef RR_CHAN_H
#define RR_CHAN_H
/*
* Notes in include header files in a head file
* Only include the neccessary header files
* that is required by the data types in the function/class declarations!
*/
/* Header files should be included in a sequence */
/* Standard header files required go first */
#include <vector>
#include "vpr_types.h"
/* RRChan coordinator class */
/* Object of a channel in a routing resource graph */
class RRChan {
public: /* Accessors */
t_rr_type get_type() const;
size_t get_chan_width() const; /* get the number of tracks in this channel */
int get_node_track_id(t_rr_node* node) const; /* get the track_id of a node */
t_rr_node* get_node(size_t track_num) const; /* get the rr_node with the track_id */
int get_node_segment(t_rr_node* node) const;
int get_node_segment(size_t track_num) const;
bool is_mirror(RRChan& cand) const; /* evaluate if two RR_chan is mirror to each other */
public: /* Mutators */
void set_type(t_rr_type type); /* modify type */
void add_node(t_rr_node* node, size_t node_segment); /* add a node to the array */
void clear(); /* clear the content */
private: /* internal functions */
bool valid_type(t_rr_type type) const;
bool valid_node_id(size_t node_id) const;
private: /* Internal Data */
t_rr_type type_; /* channel type: CHANX or CHANY */
std::vector<t_rr_node*> nodes_; /* rr nodes of each track in the channel */
std::vector<size_t> node_segments_; /* segment of each track */
};
/* Object including all the RR channels in a device,
* 1. the RR channels will be in an 2D array
* 2. Unique Module Name for each channel
* 3. Instance name for each channel
* 4. Detailed internal structure of each channel
* Considering RR channels may share the same structure
* To be memory efficient, we build a list of unique structures
* and link each RR channel to
*/
class DeviceRRChan {
public: /* Accessors */
RRChan get_module(t_rr_type chan_type, size_t module_id) const;
public: /* Mutators */
void init_module_ids(size_t device_height, size_t device_width);
void add_one_chan_module(t_rr_type chan_type, size_t x, size_t y, RRChan rr_chan); /* Add a new unique module of RRChan*/
void clear();
private: /* internal functions */
void clear_chan(t_rr_type chan_type);
void init_chan_module_ids(t_rr_type chan_type, size_t device_width, size_t device_height);
bool valid_chan_type(t_rr_type chan_type) const;
bool valid_coordinator(t_rr_type chan_type, size_t x, size_t y) const;
bool valid_module_id(t_rr_type chan_type, size_t module_id) const;
private: /* Internal Data */
std::vector< std::vector<size_t> > chanx_module_ids_; /* Module id in modules_ for each X-direction rr_channel */
std::vector< std::vector<size_t> > chany_module_ids_; /* Module id in modules_ for each Y-direction rr_channel */
std::vector<RRChan> chanx_modules_; /* Detailed internal structure of each unique module */
std::vector<RRChan> chany_modules_; /* Detailed internal structure of each unique module */
};
#endif

View File

@ -281,7 +281,7 @@ void vpr_fpga_spice(t_vpr_setup vpr_setup,
spice_print_headers(include_dir_path, vpr_crit_path_delay, num_clocks, *(Arch.spice));
/* Generate sub circuits: Inverter, Buffer, Transmission Gate, LUT, DFF, SRAM, MUX*/
generate_spice_subckts(subckt_dir_path, &Arch ,&vpr_setup.RoutingArch);
generate_spice_subckts(subckt_dir_path, &Arch ,&vpr_setup.RoutingArch, vpr_setup.FPGA_SPICE_Opts.compact_routing_hierarchy);
/* Print MUX testbench if needed */
if (vpr_setup.FPGA_SPICE_Opts.SpiceOpts.fpga_spice_print_pb_mux_testbench) {

View File

@ -632,7 +632,8 @@ void fprint_switch_box_interc(FILE* fp,
void fprint_routing_switch_box_subckt(char* subckt_dir,
t_sb cur_sb_info,
int LL_num_rr_nodes, t_rr_node* LL_rr_node,
t_ivec*** LL_rr_node_indices) {
t_ivec*** LL_rr_node_indices,
boolean compact_routing_hierarchy) {
int itrack, inode, side, ix, iy, x, y;
FILE* fp = NULL;
char* fname = NULL;
@ -998,7 +999,9 @@ void fprint_connection_box_interc(FILE* fp,
void fprint_routing_connection_box_subckt(char* subckt_dir,
t_cb cur_cb_info,
int LL_num_rr_nodes, t_rr_node* LL_rr_node,
t_ivec*** LL_rr_node_indices) {
t_ivec*** LL_rr_node_indices,
boolean compact_routing_hierarchy) {
int itrack, inode, side, x, y;
int side_cnt = 0;
FILE* fp = NULL;
@ -1170,7 +1173,8 @@ void generate_spice_routing_resources(char* subckt_dir,
t_arch arch,
t_det_routing_arch* routing_arch,
int LL_num_rr_nodes, t_rr_node* LL_rr_node,
t_ivec*** LL_rr_node_indices) {
t_ivec*** LL_rr_node_indices,
boolean compact_routing_hierarchy) {
int ix, iy;
assert(UNI_DIRECTIONAL == routing_arch->directionality);
@ -1218,7 +1222,8 @@ void generate_spice_routing_resources(char* subckt_dir,
for (iy = 0; iy < (ny + 1); iy++) {
update_spice_models_routing_index_low(ix, iy, SOURCE, arch.spice->num_spice_model, arch.spice->spice_models);
fprint_routing_switch_box_subckt(subckt_dir, sb_info[ix][iy],
LL_num_rr_nodes, LL_rr_node, LL_rr_node_indices);
LL_num_rr_nodes, LL_rr_node, LL_rr_node_indices,
compact_routing_hierarchy);
update_spice_models_routing_index_high(ix, iy, SOURCE, arch.spice->num_spice_model, arch.spice->spice_models);
}
}
@ -1233,7 +1238,8 @@ void generate_spice_routing_resources(char* subckt_dir,
if ((TRUE == is_cb_exist(CHANX, ix, iy))
&&(0 < count_cb_info_num_ipin_rr_nodes(cbx_info[ix][iy]))) {
fprint_routing_connection_box_subckt(subckt_dir, cbx_info[ix][iy],
LL_num_rr_nodes, LL_rr_node, LL_rr_node_indices);
LL_num_rr_nodes, LL_rr_node, LL_rr_node_indices,
compact_routing_hierarchy);
}
update_spice_models_routing_index_high(ix, iy, CHANX, arch.spice->num_spice_model, arch.spice->spice_models);
}
@ -1246,7 +1252,8 @@ void generate_spice_routing_resources(char* subckt_dir,
if ((TRUE == is_cb_exist(CHANY, ix, iy))
&&(0 < count_cb_info_num_ipin_rr_nodes(cby_info[ix][iy]))) {
fprint_routing_connection_box_subckt(subckt_dir, cby_info[ix][iy],
LL_num_rr_nodes, LL_rr_node, LL_rr_node_indices);
LL_num_rr_nodes, LL_rr_node, LL_rr_node_indices,
compact_routing_hierarchy);
}
update_spice_models_routing_index_high(ix, iy, CHANY, arch.spice->num_spice_model, arch.spice->spice_models);
}

View File

@ -43,7 +43,8 @@ void fprint_switch_box_interc(FILE* fp,
void fprint_routing_switch_box_subckt(FILE* fp, t_sb cur_sb_info,
int LL_num_rr_nodes, t_rr_node* LL_rr_node,
t_ivec*** LL_rr_node_indices);
t_ivec*** LL_rr_node_indices,
boolean compact_routing_hierarchy);
void fprint_connection_box_short_interc(FILE* fp,
t_cb cur_cb_info,
@ -59,11 +60,13 @@ void fprint_connection_box_interc(FILE* fp,
void fprint_routing_connection_box_subckt(FILE* fp, t_cb cur_cb_info,
int LL_num_rr_nodes, t_rr_node* LL_rr_node,
t_ivec*** LL_rr_node_indices);
t_ivec*** LL_rr_node_indices,
boolean compact_routing_hierarchy);
void generate_spice_routing_resources(char* subckt_dir,
t_arch arch,
t_det_routing_arch* routing_arch,
int LL_num_rr_nodes, t_rr_node* LL_rr_node,
t_ivec*** LL_rr_node_indices);
t_ivec*** LL_rr_node_indices,
boolean compact_routing_hierarchy);

View File

@ -706,7 +706,8 @@ void generate_spice_wires(char* subckt_dir,
*/
void generate_spice_subckts(char* subckt_dir,
t_arch* arch,
t_det_routing_arch* routing_arch) {
t_det_routing_arch* routing_arch,
boolean compact_routing_hierarchy) {
/* 1.Generate NMOS, PMOS and transmission gate */
vpr_printf(TIO_MESSAGE_INFO,"Writing SPICE NMOS and PMOS...\n");
generate_spice_nmos_pmos(subckt_dir, arch->spice->tech_lib);
@ -736,7 +737,8 @@ void generate_spice_subckts(char* subckt_dir,
/* 6. Generate Routing architecture*/
vpr_printf(TIO_MESSAGE_INFO, "Writing Routing Resources....\n");
generate_spice_routing_resources(subckt_dir, (*arch), routing_arch,
num_rr_nodes, rr_node, rr_node_indices);
num_rr_nodes, rr_node, rr_node_indices,
compact_routing_hierarchy);
/* 7. Generate Logic Blocks */
vpr_printf(TIO_MESSAGE_INFO,"Writing Logic Blocks...\n");

View File

@ -10,4 +10,5 @@ void generate_spice_subckt_tapbuf(FILE* fp,
void generate_spice_subckts(char* subckt_dir,
t_arch* arch,
t_det_routing_arch* routing_arch);
t_det_routing_arch* routing_arch,
boolean compact_routing_hierarchy);