From 3313eac23b9888dcf0c222c54eaec2a859caf918 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 10 May 2019 22:50:08 -0600 Subject: [PATCH] add rr_chan obj --- vpr7_x2p/vpr/CMakeLists.txt | 2 +- vpr7_x2p/vpr/SRC/fpga_x2p/base/rr_chan.cpp | 270 ++++++++++++++++++ vpr7_x2p/vpr/SRC/fpga_x2p/base/rr_chan.h | 74 +++++ vpr7_x2p/vpr/SRC/fpga_x2p/spice/spice_api.c | 2 +- .../vpr/SRC/fpga_x2p/spice/spice_routing.c | 19 +- .../vpr/SRC/fpga_x2p/spice/spice_routing.h | 9 +- .../vpr/SRC/fpga_x2p/spice/spice_subckt.c | 6 +- .../vpr/SRC/fpga_x2p/spice/spice_subckt.h | 3 +- 8 files changed, 371 insertions(+), 14 deletions(-) create mode 100644 vpr7_x2p/vpr/SRC/fpga_x2p/base/rr_chan.cpp create mode 100644 vpr7_x2p/vpr/SRC/fpga_x2p/base/rr_chan.h diff --git a/vpr7_x2p/vpr/CMakeLists.txt b/vpr7_x2p/vpr/CMakeLists.txt index 4804e8933..5c6c054c6 100644 --- a/vpr7_x2p/vpr/CMakeLists.txt +++ b/vpr7_x2p/vpr/CMakeLists.txt @@ -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) diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/rr_chan.cpp b/vpr7_x2p/vpr/SRC/fpga_x2p/base/rr_chan.cpp new file mode 100644 index 000000000..dee691da1 --- /dev/null +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/rr_chan.cpp @@ -0,0 +1,270 @@ +#include + +#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; +} + diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/rr_chan.h b/vpr7_x2p/vpr/SRC/fpga_x2p/base/rr_chan.h new file mode 100644 index 000000000..7df3fd16c --- /dev/null +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/rr_chan.h @@ -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 + +#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 nodes_; /* rr nodes of each track in the channel */ + std::vector 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 > chanx_module_ids_; /* Module id in modules_ for each X-direction rr_channel */ + std::vector< std::vector > chany_module_ids_; /* Module id in modules_ for each Y-direction rr_channel */ + std::vector chanx_modules_; /* Detailed internal structure of each unique module */ + std::vector chany_modules_; /* Detailed internal structure of each unique module */ +}; + +#endif + diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/spice/spice_api.c b/vpr7_x2p/vpr/SRC/fpga_x2p/spice/spice_api.c index 93ed199ec..0bf2ae089 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/spice/spice_api.c +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/spice/spice_api.c @@ -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) { diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/spice/spice_routing.c b/vpr7_x2p/vpr/SRC/fpga_x2p/spice/spice_routing.c index 3157fc9de..4946a9e94 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/spice/spice_routing.c +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/spice/spice_routing.c @@ -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); } diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/spice/spice_routing.h b/vpr7_x2p/vpr/SRC/fpga_x2p/spice/spice_routing.h index 46e51c531..291bb3c08 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/spice/spice_routing.h +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/spice/spice_routing.h @@ -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); diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/spice/spice_subckt.c b/vpr7_x2p/vpr/SRC/fpga_x2p/spice/spice_subckt.c index ba2d77839..a5753caf9 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/spice/spice_subckt.c +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/spice/spice_subckt.c @@ -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"); diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/spice/spice_subckt.h b/vpr7_x2p/vpr/SRC/fpga_x2p/spice/spice_subckt.h index d3eb8b9e2..309c2634d 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/spice/spice_subckt.h +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/spice/spice_subckt.h @@ -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);