diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_unique_routing.c b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_unique_routing.c index 5119e7f4d..3e88b03a4 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_unique_routing.c +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_unique_routing.c @@ -1294,13 +1294,23 @@ DeviceRRGSB build_device_rr_gsb(boolean output_sb_xml, char* sb_xml_dir, /* Build a list of unique modules for each Switch Block */ /* Build a list of unique modules for each side of each Switch Block */ - LL_drive_rr_gsb.build_sb_unique_module(); + LL_drive_rr_gsb.build_unique_module(); - /* Report number of unique mirrors */ vpr_printf(TIO_MESSAGE_INFO, "Detect %lu routing segments used by switch blocks.\n", LL_drive_rr_gsb.get_num_segments()); + /* Report number of unique CB Modules */ + vpr_printf(TIO_MESSAGE_INFO, + "Detect %d independent connection blocks from %d X-channel connection blocks.\n", + LL_drive_rr_gsb.get_num_cb_unique_module(CHANX), (nx + 0) * (ny + 1) ); + + vpr_printf(TIO_MESSAGE_INFO, + "Detect %d independent connection blocks from %d Y-channel connection blocks.\n", + LL_drive_rr_gsb.get_num_cb_unique_module(CHANY), (nx + 1) * (ny + 0) ); + + + /* Report number of unique SB modules */ vpr_printf(TIO_MESSAGE_INFO, "Detect %d independent switch blocks from %d switch blocks.\n", LL_drive_rr_gsb.get_num_sb_unique_module(), (nx + 1) * (ny + 1) ); diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/rr_blocks.cpp b/vpr7_x2p/vpr/SRC/fpga_x2p/base/rr_blocks.cpp index 3c0fb2ed2..5e2441ad4 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/base/rr_blocks.cpp +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/rr_blocks.cpp @@ -74,7 +74,7 @@ int RRChan::get_node_segment(size_t track_num) const { } /* evaluate if two RRChan is mirror to each other */ -bool RRChan::is_mirror(RRChan& cand) const { +bool RRChan::is_mirror(const RRChan& cand) const { /* If any following element does not match, it is not mirror */ /* 1. type */ if (this->get_type() != cand.get_type()) { @@ -552,6 +552,39 @@ size_t RRGSB::get_max_chan_width() const { return max_chan_width; } +/* Get the number of routing tracks of a X/Y-direction CB */ +size_t RRGSB::get_cb_chan_width(t_rr_type cb_type) const { + return get_chan_width(get_cb_chan_side(cb_type)); +} + +/* Get the sides of ipin_nodes belong to the cb */ +std::vector RRGSB::get_cb_ipin_sides(t_rr_type cb_type) const { + assert (validate_cb_type(cb_type)); + + std::vector ipin_sides; + + /* Make sure a clean start */ + ipin_sides.clear(); + + switch(cb_type) { + case CHANX: + ipin_sides.push_back(TOP); + ipin_sides.push_back(BOTTOM); + break; + case CHANY: + ipin_sides.push_back(RIGHT); + ipin_sides.push_back(LEFT); + break; + default: + vpr_printf(TIO_MESSAGE_ERROR, + "(File:%s, [LINE%d])Invalid type of connection block!\n", + __FILE__, __LINE__); + exit(1); + } + + return ipin_sides; +} + /* Get the direction of a rr_node at a given side and track_id */ enum PORTS RRGSB::get_chan_node_direction(enum e_side side, size_t track_id) const { Side side_manager(side); @@ -701,6 +734,12 @@ enum e_side RRGSB::get_opin_node_grid_side(t_rr_node* opin_node) const { return get_opin_node_grid_side(side, index); } +/* Get the node index in the array, return -1 if not found */ +int RRGSB::get_chan_node_index(enum e_side node_side, t_rr_node* node) const { + assert (validate_side(node_side)); + return get_chan(node_side).get_node_track_id(node); +} + /* Get the node index in the array, return -1 if not found */ int RRGSB::get_node_index(t_rr_node* node, enum e_side node_side, @@ -948,7 +987,7 @@ bool RRGSB::is_sb_node_imply_short_connection(t_rr_node* src_node) const { * Number of channel/opin/ipin rr_nodes are same * If all above are satisfied, the two switch blocks may be mirrors ! */ -bool RRGSB::is_sb_mirrorable(RRGSB& cand) const { +bool RRGSB::is_sb_mirrorable(const RRGSB& cand) const { /* check the numbers of sides */ if (get_num_sides() != cand.get_num_sides()) { return false; @@ -981,20 +1020,64 @@ bool RRGSB::is_sb_mirrorable(RRGSB& cand) const { } /* Make sure the number of conf bits are the same */ - /* TODO: recover this check when the SB conf bits are allocated during setup stage!!! - if ( ( get_num_conf_bits() != cand.get_num_conf_bits() ) - || ( get_num_reserved_conf_bits() != cand.get_num_reserved_conf_bits() ) ) { + if ( ( get_sb_num_conf_bits() != cand.get_sb_num_conf_bits() ) + || ( get_sb_num_reserved_conf_bits() != cand.get_sb_num_reserved_conf_bits() ) ) { return false; } - */ return true; } +/* check if the candidate CB is a mirror of the current one */ +bool RRGSB::is_cb_mirror(const RRGSB& cand, t_rr_type cb_type) const { + /* Check if channel width is the same */ + if ( get_cb_chan_width(cb_type) != cand.get_cb_chan_width(cb_type) ) { + return false; + } + + enum e_side chan_side = get_cb_chan_side(cb_type); + + /* check the numbers/directionality of channel rr_nodes */ + if ( false == get_chan(chan_side).is_mirror(cand.get_chan(chan_side)) ) { + return false; + } + + /* check the equivalence of ipins */ + std::vector ipin_side = get_cb_ipin_sides(cb_type); + for (size_t side = 0; side < ipin_side.size(); ++side) { + /* Ensure we have the same number of IPINs on this side */ + if ( get_num_ipin_nodes(ipin_side[side]) != cand.get_num_ipin_nodes(ipin_side[side]) ) { + return false; + } + for (size_t inode = 0; inode < get_num_ipin_nodes(ipin_side[side]); ++inode) { + if (false == is_cb_node_mirror(cand, cb_type, ipin_side[side], inode)) { + return false; + } + } + } + + /* Make sure the number of conf bits are the same */ + if ( ( get_cb_num_conf_bits(cb_type) != cand.get_cb_num_conf_bits(cb_type) ) + || ( get_cb_num_reserved_conf_bits(cb_type) != cand.get_cb_num_reserved_conf_bits(cb_type) ) ) { + return false; + } + + return true; +} + +/* check if the CB exist in this GSB */ +bool RRGSB::is_cb_exist(t_rr_type cb_type) const { + /* if channel width is zero, there is no CB */ + if ( 0 == get_cb_chan_width(cb_type)) { + return false; + } + return true; +} + /* Determine an initial offset in rotating the candidate Switch Block to find a mirror matching * We try to find the offset in track_id where the two Switch Blocks have their first short connections */ -size_t RRGSB::get_hint_rotate_offset(RRGSB& cand) const { +size_t RRGSB::get_hint_rotate_offset(const RRGSB& cand) const { size_t offset_hint = size_t(-1); assert (get_num_sides() == cand.get_num_sides()); @@ -1019,7 +1102,7 @@ size_t RRGSB::get_hint_rotate_offset(RRGSB& cand) const { } /* check if all the routing segments of a side of candidate SB is a mirror of the current one */ -bool RRGSB::is_sb_side_segment_mirror(RRGSB& cand, enum e_side side, size_t seg_id) const { +bool RRGSB::is_sb_side_segment_mirror(const RRGSB& cand, enum e_side side, size_t seg_id) const { /* Create a side manager */ Side side_manager(side); @@ -1082,7 +1165,7 @@ bool RRGSB::is_sb_side_segment_mirror(RRGSB& cand, enum e_side side, size_t seg_ * 5. check if pin class id and pin id are same * If all above are satisfied, the side of the two switch blocks are mirrors! */ -bool RRGSB::is_sb_side_mirror(RRGSB& cand, enum e_side side) const { +bool RRGSB::is_sb_side_mirror(const RRGSB& cand, enum e_side side) const { /* get a list of segments */ std::vector seg_ids = get_chan(side).get_segment_ids(); @@ -1109,7 +1192,7 @@ bool RRGSB::is_sb_side_mirror(RRGSB& cand, enum e_side side) const { * 5. check if pin class id and pin id are same * If all above are satisfied, the two switch blocks are mirrors! */ -bool RRGSB::is_sb_mirror(RRGSB& cand) const { +bool RRGSB::is_sb_mirror(const RRGSB& cand) const { /* check the numbers of sides */ if (get_num_sides() != cand.get_num_sides()) { return false; @@ -1197,6 +1280,22 @@ DeviceCoordinator RRGSB::get_cb_coordinator(t_rr_type cb_type) const { } } +enum e_side RRGSB::get_cb_chan_side(t_rr_type cb_type) const { + assert (validate_cb_type(cb_type)); + switch(cb_type) { + case CHANX: + return LEFT; + case CHANY: + return TOP; + default: + vpr_printf(TIO_MESSAGE_ERROR, + "(File:%s, [LINE%d])Invalid type of connection block!\n", + __FILE__, __LINE__); + exit(1); + } +} + + DeviceCoordinator RRGSB::get_side_block_coordinator(enum e_side side) const { Side side_manager(side); assert(side_manager.validate()); @@ -1318,11 +1417,14 @@ void RRGSB::set(const RRGSB& src) { for (size_t side = 0; side < src.get_num_sides(); ++side) { Side side_manager(side); /* Copy chan_nodes */ - this->chan_node_[side_manager.get_side()].set(src.get_chan(side_manager.get_side())); - /* Copy chan_node_direction_*/ - this->chan_node_direction_[side_manager.get_side()].clear(); - for (size_t inode = 0; inode < src.get_chan_width(side_manager.get_side()); ++inode) { - this->chan_node_direction_[side_manager.get_side()].push_back(src.get_chan_node_direction(side_manager.get_side(), inode)); + /* skip if there is no channel width */ + if ( 0 < src.get_chan_width(side_manager.get_side()) ) { + this->chan_node_[side_manager.get_side()].set(src.get_chan(side_manager.get_side())); + /* Copy chan_node_direction_*/ + this->chan_node_direction_[side_manager.get_side()].clear(); + for (size_t inode = 0; inode < src.get_chan_width(side_manager.get_side()); ++inode) { + this->chan_node_direction_[side_manager.get_side()].push_back(src.get_chan_node_direction(side_manager.get_side(), inode)); + } } /* Copy opin_node and opin_node_grid_side_ */ @@ -1792,7 +1894,7 @@ void RRGSB::clear_one_side(enum e_side node_side) { * 2. OPIN or IPIN: should have the same side and index * 3. each drive_rr_switch should be the same */ -bool RRGSB::is_sb_node_mirror(RRGSB& cand, +bool RRGSB::is_sb_node_mirror(const RRGSB& cand, enum e_side node_side, size_t track_id) const { /* Ensure rr_nodes are either the output of short-connection or multiplexer */ @@ -1841,6 +1943,64 @@ bool RRGSB::is_sb_node_mirror(RRGSB& cand, return true; } +/* check if two ipin_nodes have a similar set of drive_rr_nodes + * for each drive_rr_node: + * 1. CHANX or CHANY: should have the same side and index + * 2. each drive_rr_switch should be the same + */ +bool RRGSB::is_cb_node_mirror(const RRGSB& cand, t_rr_type cb_type, + enum e_side node_side, + size_t node_id) const { + /* Ensure rr_nodes are either the output of short-connection or multiplexer */ + t_rr_node* node = this->get_ipin_node(node_side, node_id); + t_rr_node* cand_node = cand.get_ipin_node(node_side, node_id); + + if ( node->num_drive_rr_nodes != cand_node->num_drive_rr_nodes ) { + return false; + } + for (size_t inode = 0; inode < size_t(node->num_drive_rr_nodes); ++inode) { + /* node type should be the same */ + if ( node->drive_rr_nodes[inode]->type + != cand_node->drive_rr_nodes[inode]->type) { + return false; + } + /* switch type should be the same */ + if ( node->drive_switches[inode] + != cand_node->drive_switches[inode]) { + return false; + } + + int src_node_id, des_node_id; + enum e_side src_node_side, des_node_side; + enum e_side chan_side = get_cb_chan_side(cb_type); + switch (node->drive_rr_nodes[inode]->type) { + case CHANX: + case CHANY: + /* if the drive rr_nodes are routing tracks, find index */ + src_node_id = this->get_chan_node_index(chan_side, node->drive_rr_nodes[inode]); + des_node_id = cand.get_chan_node_index(chan_side, cand_node->drive_rr_nodes[inode]); + break; + case OPIN: + this->get_node_side_and_index(node->drive_rr_nodes[inode], OUT_PORT, &src_node_side, &src_node_id); + cand.get_node_side_and_index(cand_node->drive_rr_nodes[inode], OUT_PORT, &des_node_side, &des_node_id); + if (src_node_side != des_node_side) { + return false; + } + break; + default: + vpr_printf(TIO_MESSAGE_ERROR, + "(File:%s, [LINE%d])Invalid type of drive_rr_nodes for ipin_node!\n", + __FILE__, __LINE__); + exit(1); + } + if (src_node_id != des_node_id) { + return false; + } + } + + return true; +} + size_t RRGSB::get_track_id_first_short_connection(enum e_side node_side) const { assert(validate_side(node_side)); @@ -1977,11 +2137,28 @@ size_t DeviceRRGSB::get_num_sb_unique_submodule(enum e_side side, size_t seg_ind return sb_unique_submodule_[side_manager.to_size_t()][seg_index].size(); } +/* get the number of unique mirrors of switch blocks */ +size_t DeviceRRGSB::get_num_cb_unique_module(t_rr_type cb_type) const { + assert (validate_cb_type(cb_type)); + switch(cb_type) { + case CHANX: + return cbx_unique_module_.size(); + case CHANY: + return cby_unique_module_.size(); + default: + vpr_printf(TIO_MESSAGE_ERROR, + "(File:%s, [LINE%d])Invalid type of connection block!\n", + __FILE__, __LINE__); + exit(1); + } +} + /* 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 submodule id of a SB */ size_t DeviceRRGSB::get_sb_unique_submodule_id(DeviceCoordinator& coordinator, enum e_side side, size_t seg_id) const { assert (validate_coordinator(coordinator)); @@ -2028,6 +2205,23 @@ RRGSB DeviceRRGSB::get_sb_unique_module(size_t index) const { return rr_gsb_[sb_unique_module_[index].get_x()][sb_unique_module_[index].get_y()]; } +/* Get a rr switch block which a unique mirror */ +RRGSB DeviceRRGSB::get_cb_unique_module(t_rr_type cb_type, size_t index) const { + assert (validate_cb_unique_module_index(cb_type, index)); + assert (validate_cb_type(cb_type)); + switch(cb_type) { + case CHANX: + return rr_gsb_[cbx_unique_module_[index].get_x()][cbx_unique_module_[index].get_y()]; + case CHANY: + return rr_gsb_[cby_unique_module_[index].get_x()][cby_unique_module_[index].get_y()]; + default: + vpr_printf(TIO_MESSAGE_ERROR, + "(File:%s, [LINE%d])Invalid type of connection block!\n", + __FILE__, __LINE__); + exit(1); + } +} + /* Give a coordinator of a rr switch block, and return its unique mirror */ RRGSB DeviceRRGSB::get_sb_unique_module(DeviceCoordinator& coordinator) const { assert(validate_coordinator(coordinator)); @@ -2104,13 +2298,21 @@ void DeviceRRGSB::set_sb_conf_bits_msb(DeviceCoordinator& coordinator, size_t co /* Pre-allocate the rr_switch_block array that the device requires */ void DeviceRRGSB::reserve(DeviceCoordinator& coordinator) { rr_gsb_.resize(coordinator.get_x()); + sb_unique_submodule_id_.resize(coordinator.get_x()); sb_unique_module_id_.resize(coordinator.get_x()); + cbx_unique_module_id_.resize(coordinator.get_x()); + cby_unique_module_id_.resize(coordinator.get_x()); + for (size_t x = 0; x < coordinator.get_x(); ++x) { rr_gsb_[x].resize(coordinator.get_y()); + sb_unique_submodule_id_[x].resize(coordinator.get_y()); sb_unique_module_id_[x].resize(coordinator.get_y()); + + cbx_unique_module_id_[x].resize(coordinator.get_y()); + cby_unique_module_id_[x].resize(coordinator.get_y()); } return; @@ -2133,14 +2335,21 @@ void DeviceRRGSB::reserve_sb_unique_submodule_id(DeviceCoordinator& coordinator) void DeviceRRGSB::resize_upon_need(DeviceCoordinator& coordinator) { if (coordinator.get_x() + 1 > rr_gsb_.size()) { rr_gsb_.resize(coordinator.get_x() + 1); + sb_unique_submodule_id_.resize(coordinator.get_x() + 1); sb_unique_module_id_.resize(coordinator.get_x() + 1); + + cbx_unique_module_id_.resize(coordinator.get_x() + 1); + cby_unique_module_id_.resize(coordinator.get_x() + 1); } if (coordinator.get_y() + 1 > rr_gsb_[coordinator.get_x()].size()) { rr_gsb_[coordinator.get_x()].resize(coordinator.get_y() + 1); sb_unique_submodule_id_[coordinator.get_x()].resize(coordinator.get_y() + 1); sb_unique_module_id_[coordinator.get_x()].resize(coordinator.get_y() + 1); + + cbx_unique_module_id_[coordinator.get_x()].resize(coordinator.get_y() + 1); + cby_unique_module_id_[coordinator.get_x()].resize(coordinator.get_y() + 1); } return; @@ -2158,14 +2367,48 @@ void DeviceRRGSB::add_rr_gsb(DeviceCoordinator& coordinator, return; } +/* 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(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; + DeviceCoordinator gsb_coordinator(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) { + if (true == rr_gsb_[ix][iy].is_cb_mirror(get_cb_unique_module(cb_type, id), 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_coordinator, id); + break; + } + } + /* Add to list if this is a unique mirror*/ + if (true == is_unique_module) { + add_cb_unique_module(cb_type, gsb_coordinator); + /* Record the id of unique mirror */ + set_cb_unique_module_id(cb_type, gsb_coordinator, get_num_cb_unique_module(cb_type)); + } + } + } + return; +} + + /* 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() { /* Make sure a clean start */ clear_sb_unique_module(); - /* build segment id look-up*/ - build_segment_ids(); - /* Build the unique submodule */ build_sb_unique_submodule(); @@ -2176,12 +2419,6 @@ void DeviceRRGSB::build_sb_unique_module() { /* 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) { - /* If we have the same coordinator, this is already not unique_mirror */ - if ( (ix == sb_unique_module_[id].get_x()) - && (iy == sb_unique_module_[id].get_y()) ) { - is_unique_module = false; - break; - } /* 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 @@ -2196,8 +2433,7 @@ void DeviceRRGSB::build_sb_unique_module() { } /* Add to list if this is a unique mirror*/ if (true == is_unique_module) { - DeviceCoordinator coordinator(ix, iy); - sb_unique_module_.push_back(coordinator); + sb_unique_module_.push_back(sb_coordinator); /* Record the id of unique mirror */ sb_unique_module_id_[ix][iy] = sb_unique_module_.size() - 1; } @@ -2267,6 +2503,17 @@ void DeviceRRGSB::add_sb_unique_side_segment_submodule(DeviceCoordinator& coordi return; } +void DeviceRRGSB::build_unique_module() { + build_segment_ids(); + + build_sb_unique_module(); + + build_cb_unique_module(CHANX); + build_cb_unique_module(CHANY); + + return; +} + /* Add a unique side module to the list: * Check if the connections and nodes on the specified side of the rr_sb * If it is similar to any module[side][i] in the list, we build a link from the rr_sb to the unique_module @@ -2284,6 +2531,42 @@ void DeviceRRGSB::add_sb_unique_side_submodule(DeviceCoordinator& coordinator, return; } +void DeviceRRGSB::add_cb_unique_module(t_rr_type cb_type, const DeviceCoordinator& coordinator) { + assert (validate_cb_type(cb_type)); + switch(cb_type) { + case CHANX: + cbx_unique_module_.push_back(coordinator); + return; + case CHANY: + cby_unique_module_.push_back(coordinator); + return; + default: + vpr_printf(TIO_MESSAGE_ERROR, + "(File:%s, [LINE%d])Invalid type of connection block!\n", + __FILE__, __LINE__); + exit(1); + } +} + +void DeviceRRGSB::set_cb_unique_module_id(t_rr_type cb_type, const DeviceCoordinator& coordinator, size_t id) { + assert (validate_cb_type(cb_type)); + size_t x = coordinator.get_x(); + size_t y = coordinator.get_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: + vpr_printf(TIO_MESSAGE_ERROR, + "(File:%s, [LINE%d])Invalid type of connection block!\n", + __FILE__, __LINE__); + exit(1); + } +} + /* build a map of segment_ids */ void DeviceRRGSB::build_segment_ids() { @@ -2320,6 +2603,12 @@ void DeviceRRGSB::clear() { clear_gsb(); /* 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(); @@ -2346,6 +2635,27 @@ void DeviceRRGSB::clear_sb_unique_module_id() { return; } +void DeviceRRGSB::clear_cb_unique_module_id(t_rr_type cb_type) { + 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: + vpr_printf(TIO_MESSAGE_ERROR, + "(File:%s, [LINE%d])Invalid type of connection block!\n", + __FILE__, __LINE__); + exit(1); + } +} + void DeviceRRGSB::clear_sb_unique_submodule_id() { /* clean rr_sb_unique_side_module_id */ for (size_t x = 0; x < sb_unique_submodule_id_.size(); ++x) { @@ -2382,6 +2692,24 @@ void DeviceRRGSB::clear_sb_unique_module() { return; } +void DeviceRRGSB::clear_cb_unique_module(t_rr_type cb_type) { + assert (validate_cb_type(cb_type)); + switch(cb_type) { + case CHANX: + cbx_unique_module_.clear(); + return; + case CHANY: + cby_unique_module_.clear(); + return; + default: + vpr_printf(TIO_MESSAGE_ERROR, + "(File:%s, [LINE%d])Invalid type of connection block!\n", + __FILE__, __LINE__); + exit(1); + } +} + + /* clean the content related to segment_ids */ void DeviceRRGSB::clear_segment_ids() { /* clean segment_ids_ */ @@ -2431,9 +2759,38 @@ bool DeviceRRGSB::validate_sb_unique_submodule_index(size_t index, enum e_side s return true; } +bool DeviceRRGSB::validate_cb_unique_module_index(t_rr_type cb_type, size_t index) const { + assert (validate_cb_type(cb_type)); + switch(cb_type) { + case CHANX: + if (index >= cbx_unique_module_.size()) { + return false; + } + return true; + case CHANY: + if (index >= cbx_unique_module_.size()) { + return false; + } + return true; + default: + vpr_printf(TIO_MESSAGE_ERROR, + "(File:%s, [LINE%d])Invalid type of connection block!\n", + __FILE__, __LINE__); + exit(1); + } +} + bool DeviceRRGSB::validate_segment_index(size_t index) const { if (index >= segment_ids_.size()) { return false; } return true; } + +bool DeviceRRGSB::validate_cb_type(t_rr_type cb_type) const { + if ( (CHANX == cb_type) || (CHANY == cb_type) ) { + return true; + } + return false; +} + diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/rr_blocks.h b/vpr7_x2p/vpr/SRC/fpga_x2p/base/rr_blocks.h index 5742623b1..1a776cf8d 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/base/rr_blocks.h +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/rr_blocks.h @@ -47,7 +47,7 @@ class RRChan { 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 */ + bool is_mirror(const RRChan& cand) const; /* evaluate if two RR_chan is mirror to each other */ std::vector get_segment_ids() const; /* Get a list of segments used in this routing channel */ public: /* Mutators */ void set(const RRChan&); /* copy */ @@ -148,6 +148,8 @@ class RRGSB { public: /* Accessors */ size_t get_num_sides() const; /* Get the number of sides of this SB */ size_t get_chan_width(enum e_side side) const; /* Get the number of routing tracks on a side */ + size_t get_cb_chan_width(t_rr_type cb_type) const; /* Get the number of routing tracks of a X/Y-direction CB */ + std::vector get_cb_ipin_sides(t_rr_type cb_type) const; /* Get the sides of CB ipins in the array */ size_t get_max_chan_width() const; /* Get the maximum number of routing tracks on all sides */ enum PORTS get_chan_node_direction(enum e_side side, size_t track_id) const; /* Get the direction of a rr_node at a given side and track_id */ RRChan get_chan(enum e_side side) const; /* get a rr_node at a given side and track_id */ @@ -161,6 +163,7 @@ class RRGSB { t_rr_node* get_opin_node(enum e_side side, size_t node_id) const; /* get a rr_node at a given side and track_id */ enum e_side get_opin_node_grid_side(enum e_side side, size_t node_id) const; /* get a rr_node at a given side and track_id */ enum e_side get_opin_node_grid_side(t_rr_node* opin_node) const; /* get a rr_node at a given side and track_id */ + int get_chan_node_index(enum e_side node_side, t_rr_node* node) const; int get_node_index(t_rr_node* node, enum e_side node_side, enum PORTS node_direction) const; /* Get the node index in the array, return -1 if not found */ void get_node_side_and_index(t_rr_node* node, enum PORTS node_direction, enum e_side* node_side, int* node_index) const; /* Given a rr_node, try to find its side and index in the Switch block */ bool is_sb_node_exist_opposite_side(t_rr_node* node, enum e_side node_side) const; /* Check if the node exist in the opposite side of this Switch Block */ @@ -178,11 +181,13 @@ class RRGSB { size_t get_cb_conf_bits_lsb(t_rr_type cb_type) const; size_t get_cb_conf_bits_msb(t_rr_type cb_type) const; bool is_sb_node_imply_short_connection(t_rr_node* src_node) const; /* Check if the node imply a short connection inside the SB, which happens to long wires across a FPGA fabric */ - bool is_sb_side_mirror(RRGSB& cand, enum e_side side) const; /* check if a side of candidate SB is a mirror of the current one */ - bool is_sb_side_segment_mirror(RRGSB& cand, enum e_side side, size_t seg_id) const; /* check if all the routing segments of a side of candidate SB is a mirror of the current one */ - bool is_sb_mirror(RRGSB& cand) const; /* check if the candidate SB is a mirror of the current one */ - bool is_sb_mirrorable(RRGSB& cand) const; /* check if the candidate SB satisfy the basic requirements on being a mirror of the current one */ - size_t get_hint_rotate_offset(RRGSB& cand) const; /* Determine an initial offset in rotating the candidate Switch Block to find a mirror matching*/ + bool is_sb_side_mirror(const RRGSB& cand, enum e_side side) const; /* check if a side of candidate SB is a mirror of the current one */ + bool is_sb_side_segment_mirror(const RRGSB& cand, enum e_side side, size_t seg_id) const; /* check if all the routing segments of a side of candidate SB is a mirror of the current one */ + bool is_sb_mirror(const RRGSB& cand) const; /* check if the candidate SB is a mirror of the current one */ + bool is_sb_mirrorable(const RRGSB& cand) const; /* check if the candidate SB satisfy the basic requirements on being a mirror of the current one */ + bool is_cb_mirror(const RRGSB& cand, t_rr_type cb_type) const; /* check if the candidate SB is a mirror of the current one */ + bool is_cb_exist(t_rr_type cb_type) const; /* check if the candidate SB is a mirror of the current one */ + size_t get_hint_rotate_offset(const RRGSB& cand) const; /* Determine an initial offset in rotating the candidate Switch Block to find a mirror matching*/ public: /* Cooridinator conversion and output */ size_t get_sb_x() const; /* get the x coordinator of this switch block */ size_t get_sb_y() const; /* get the y coordinator of this switch block */ @@ -190,6 +195,7 @@ class RRGSB { size_t get_cb_x(t_rr_type cb_type) const; /* get the x coordinator of this X/Y-direction block */ size_t get_cb_y(t_rr_type cb_type) const; /* get the y coordinator of this X/Y-direction block */ DeviceCoordinator get_cb_coordinator(t_rr_type cb_type) const; /* Get the coordinator of the X/Y-direction CB */ + enum e_side get_cb_chan_side(t_rr_type cb_type) const; /* get the side of a Connection block */ DeviceCoordinator get_side_block_coordinator(enum e_side side) const; public: /* Verilog writer */ const char* gen_sb_verilog_module_name() const; @@ -225,6 +231,7 @@ class RRGSB { void swap_ipin_node(enum e_side src_side, enum e_side des_side); /* swap the IPIN rr_nodes on two sides */ void reverse_opin_node(enum e_side side); /* reverse the OPIN rr_nodes on two sides */ void reverse_ipin_node(enum e_side side); /* reverse the IPIN rr_nodes on two sides */ + public: /* Mutators: cleaners */ void clear(); void clear_chan_nodes(enum e_side node_side); /* Clean the chan_width of a side */ void clear_ipin_nodes(enum e_side node_side); /* Clean the number of IPINs of a side */ @@ -233,7 +240,8 @@ class RRGSB { private: /* Internal Mutators */ void mirror_side_chan_node_direction(enum e_side side); /* Mirror the node direction and port direction of routing track nodes on a side */ private: /* internal functions */ - bool is_sb_node_mirror (RRGSB& cand, enum e_side node_side, size_t track_id) const; + bool is_sb_node_mirror (const RRGSB& cand, enum e_side node_side, size_t track_id) const; + bool is_cb_node_mirror (const RRGSB& cand, t_rr_type cb_type, enum e_side node_side, size_t node_id) const; size_t get_track_id_first_short_connection(enum e_side node_side) const; bool validate_num_sides() const; bool validate_side(enum e_side side) const; @@ -278,11 +286,13 @@ class DeviceRRGSB { RRGSB get_gsb(size_t x, size_t y) const; /* Get a rr switch block in the array with a coordinator */ size_t get_num_sb_unique_submodule(enum e_side side, size_t seg_index) const; /* get the number of unique mirrors of switch blocks */ size_t get_num_sb_unique_module() const; /* get the number of unique mirrors of switch blocks */ + size_t get_num_cb_unique_module(t_rr_type cb_type) const; /* get the number of unique mirrors of CBs */ size_t get_sb_unique_submodule_id(DeviceCoordinator& coordinator, enum e_side side, size_t seg_id) const; RRGSB get_sb_unique_submodule(size_t index, enum e_side side, size_t seg_id) const; /* Get a rr switch block which a unique mirror */ RRGSB get_sb_unique_submodule(DeviceCoordinator& coordinator, enum e_side side, size_t seg_id) const; /* Get a rr switch block which a unique mirror */ RRGSB get_sb_unique_module(size_t index) const; /* Get a rr switch block which a unique mirror */ RRGSB get_sb_unique_module(DeviceCoordinator& coordinator) const; /* Get a rr switch block which a unique mirror */ + RRGSB get_cb_unique_module(t_rr_type cb_type, size_t index) const; /* Get a rr switch block which a unique mirror */ size_t get_max_num_sides() const; /* Get the maximum number of sides across the switch blocks */ size_t get_num_segments() const; /* Get the size of segment_ids */ size_t get_segment_id(size_t index) const; /* Get a segment id */ @@ -295,10 +305,12 @@ class DeviceRRGSB { void reserve_sb_unique_submodule_id(DeviceCoordinator& coordinator); /* Pre-allocate the rr_sb_unique_module_id matrix that the device requires */ void resize_upon_need(DeviceCoordinator& coordinator); /* Resize the rr_switch_block array if needed */ void add_rr_gsb(DeviceCoordinator& coordinator, RRGSB& rr_gsb); /* Add a switch block to the array, which will automatically identify and update the lists of unique mirrors and rotatable mirrors */ - void build_sb_unique_module(); /* Add a switch block to the array, which will automatically identify and update the lists of unique mirrors and rotatable mirrors */ + void build_unique_module(); /* Add a switch block to the array, which will automatically identify and update the lists of unique mirrors and rotatable mirrors */ void clear(); /* clean the content */ private: /* Internal cleaners */ void clear_gsb(); /* clean the content */ + void clear_cb_unique_module(t_rr_type cb_type); /* clean the content */ + void clear_cb_unique_module_id(t_rr_type cb_type); /* clean the content */ void clear_sb_unique_module(); /* clean the content */ void clear_sb_unique_module_id(); /* clean the content */ void clear_sb_unique_submodule(); /* clean the content */ @@ -308,13 +320,19 @@ class DeviceRRGSB { bool validate_coordinator(DeviceCoordinator& coordinator) const; /* Validate if the (x,y) is the range of this device */ bool validate_side(enum e_side side) const; /* validate if side is in the range of unique_side_module_ */ bool validate_sb_unique_module_index(size_t index) const; /* Validate if the index in the range of unique_mirror vector*/ + bool validate_cb_unique_module_index(t_rr_type cb_type, size_t index) const; /* Validate if the index in the range of unique_mirror vector*/ bool validate_sb_unique_submodule_index(size_t index, enum e_side side, size_t seg_index) const; /* Validate if the index in the range of unique_module vector */ bool validate_segment_index(size_t index) const; + bool validate_cb_type(t_rr_type cb_type) const; private: /* Internal builders */ void build_segment_ids(); /* build a map of segment_ids */ void add_sb_unique_side_submodule(DeviceCoordinator& coordinator, RRGSB& rr_sb, enum e_side side); void add_sb_unique_side_segment_submodule(DeviceCoordinator& coordinator, RRGSB& rr_sb, enum e_side side, size_t seg_id); + void add_cb_unique_module(t_rr_type cb_type, const DeviceCoordinator& coordinator); + void set_cb_unique_module_id(t_rr_type, const DeviceCoordinator& coordinator, size_t id); void build_sb_unique_submodule(); /* Add a switch block to the array, which will automatically identify and update the lists of unique side module */ + void build_sb_unique_module(); /* Add a switch block to the array, which will automatically identify and update the lists of unique mirrors and rotatable mirrors */ + void build_cb_unique_module(t_rr_type cb_type); /* Add a switch block to the array, which will automatically identify and update the lists of unique side module */ private: /* Internal Data */ std::vector< std::vector > rr_gsb_; @@ -324,6 +342,12 @@ class DeviceRRGSB { std::vector< std::vector< std::vector< std::vector > > > sb_unique_submodule_id_; /* A map from rr_switch_block to its unique_side_module [0..x][0..y][0..num_sides][num_seg-1]*/ std::vector< std::vector > > sb_unique_submodule_; /* For each side of switch block, we identify a list of unique modules based on its connection. This is a matrix [0..num_sides-1][0..num_seg-1][0..num_module], num_sides will the max number of sides of all the rr_switch_blocks */ + std::vector< std::vector > cbx_unique_module_id_; /* A map from rr_gsb to its unique mirror */ + std::vector cbx_unique_module_; /* For each side of connection block, we identify a list of unique modules based on its connection. This is a matrix [0..num_module] */ + + std::vector< std::vector > cby_unique_module_id_; /* A map from rr_gsb to its unique mirror */ + std::vector cby_unique_module_; /* For each side of connection block, we identify a list of unique modules based on its connection. This is a matrix [0..num_module] */ + std::vector segment_ids_; }; diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_routing.c b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_routing.c index a2a507527..67c4aa397 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_routing.c +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_routing.c @@ -2017,7 +2017,7 @@ void dump_verilog_routing_switch_box_unique_side_module(t_sram_orgz_info* cur_sr dump_verilog_formal_verification_sram_ports(fp, cur_sram_orgz_info, cur_num_sram, esti_sram_cnt - 1, - VERILOG_PORT_OUTPUT); + VERILOG_PORT_INPUT); fprintf(fp, "\n"); fprintf(fp, "`endif\n"); } @@ -2189,7 +2189,7 @@ void dump_verilog_routing_switch_box_unique_module(t_sram_orgz_info* cur_sram_or dump_verilog_formal_verification_sram_ports(fp, cur_sram_orgz_info, rr_sb.get_sb_conf_bits_lsb(), rr_sb.get_sb_conf_bits_msb(), - VERILOG_PORT_OUTPUT); + VERILOG_PORT_INPUT); fprintf(fp, "\n"); fprintf(fp, "`endif\n"); } @@ -3319,7 +3319,7 @@ void dump_verilog_routing_connection_box_subckt(t_sram_orgz_info* cur_sram_orgz_ dump_verilog_formal_verification_sram_ports(fp, cur_sram_orgz_info, cur_cb_info->conf_bits_lsb, cur_cb_info->conf_bits_msb - 1, - VERILOG_PORT_OUTPUT); + VERILOG_PORT_INPUT); fprintf(fp, "\n"); fprintf(fp, "`endif\n"); }