add rr_chan obj
This commit is contained in:
parent
9c05a4fb0a
commit
3313eac23b
|
@ -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)
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue