support switch block submodule Verilog generation by segments
This commit is contained in:
parent
c2d8fa00ba
commit
0f87ae9886
|
@ -1224,6 +1224,11 @@ DeviceRRSwitchBlock build_device_rr_switch_blocks(boolean output_sb_xml, char* s
|
|||
"Backannotated %d switch blocks.\n",
|
||||
(nx + 1) * (ny + 1) );
|
||||
|
||||
LL_device_rr_switch_block.build_segment_ids();
|
||||
vpr_printf(TIO_MESSAGE_INFO,
|
||||
"Detect %lu routing segments used by switch blocks.\n",
|
||||
LL_device_rr_switch_block.get_num_segments());
|
||||
|
||||
if (TRUE == output_sb_xml) {
|
||||
write_device_rr_switch_block_to_xml(sb_xml_dir, LL_device_rr_switch_block);
|
||||
|
||||
|
@ -1247,10 +1252,14 @@ DeviceRRSwitchBlock build_device_rr_switch_blocks(boolean output_sb_xml, char* s
|
|||
/* Report number of unique mirrors */
|
||||
for (size_t side = 0; side < LL_device_rr_switch_block.get_max_num_sides(); ++side) {
|
||||
Side side_manager(side);
|
||||
vpr_printf(TIO_MESSAGE_INFO,
|
||||
"For side %s: Detect %d independent switch blocks from %d switch blocks.\n",
|
||||
side_manager.to_string(), LL_device_rr_switch_block.get_num_unique_module(side_manager.get_side()),
|
||||
(nx + 1) * (ny + 1) );
|
||||
/* get segment ids */
|
||||
for (size_t iseg = 0; iseg < LL_device_rr_switch_block.get_num_segments(); ++iseg) {
|
||||
vpr_printf(TIO_MESSAGE_INFO,
|
||||
"For side %s, segment id %lu: Detect %d independent switch blocks from %d switch blocks.\n",
|
||||
side_manager.to_string(), LL_device_rr_switch_block.get_segment_id(iseg),
|
||||
LL_device_rr_switch_block.get_num_unique_module(side_manager.get_side(), iseg),
|
||||
(nx + 1) * (ny + 1) );
|
||||
}
|
||||
}
|
||||
|
||||
/* Create directory if needed */
|
||||
|
|
|
@ -934,19 +934,8 @@ size_t RRSwitchBlock::get_hint_rotate_offset(RRSwitchBlock& cand) const {
|
|||
return offset_hint;
|
||||
}
|
||||
|
||||
|
||||
/* check if a side of candidate SB is a mirror of the current one
|
||||
* Check the specified side of two switch blocks:
|
||||
* 1. Number of channel/opin/ipin rr_nodes are same
|
||||
* For channel rr_nodes
|
||||
* 2. check if their track_ids (ptc_num) are same
|
||||
* 3. Check if the switches (ids) are same
|
||||
* For opin/ipin rr_nodes,
|
||||
* 4. check if their parent type_descriptors same,
|
||||
* 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 RRSwitchBlock::is_side_mirror(RRSwitchBlock& cand, enum e_side side) const {
|
||||
/* check if all the routing segments of a side of candidate SB is a mirror of the current one */
|
||||
bool RRSwitchBlock::is_side_segment_mirror(RRSwitchBlock& cand, enum e_side side, size_t seg_id) const {
|
||||
/* Create a side manager */
|
||||
Side side_manager(side);
|
||||
|
||||
|
@ -954,12 +943,17 @@ bool RRSwitchBlock::is_side_mirror(RRSwitchBlock& cand, enum e_side side) const
|
|||
assert ( side_manager.to_size_t() < get_num_sides() );
|
||||
assert ( side_manager.to_size_t() < cand.get_num_sides() );
|
||||
|
||||
|
||||
/* check the numbers/directionality of channel rr_nodes */
|
||||
/* Ensure we have the same channel width on this side */
|
||||
if (get_chan_width(side) != cand.get_chan_width(side)) {
|
||||
return false;
|
||||
}
|
||||
for (size_t itrack = 0; itrack < get_chan_width(side); ++itrack) {
|
||||
/* Bypass unrelated segments */
|
||||
if (seg_id != get_chan_node_segment(side, itrack)) {
|
||||
continue;
|
||||
}
|
||||
/* Check the directionality of each node */
|
||||
if (get_chan_node_direction(side, itrack) != cand.get_chan_node_direction(side, itrack)) {
|
||||
return false;
|
||||
|
@ -967,7 +961,7 @@ bool RRSwitchBlock::is_side_mirror(RRSwitchBlock& cand, enum e_side side) const
|
|||
/* Check the track_id of each node
|
||||
* ptc is not necessary, we care the connectivity!
|
||||
if (get_chan_node(side_manager.get_side(), itrack)->ptc_num != cand.get_chan_node(side_manager.get_side(), itrack)->ptc_num) {
|
||||
return false;
|
||||
eturn false;
|
||||
}
|
||||
*/
|
||||
/* For OUT_PORT rr_node, we need to check fan-in */
|
||||
|
@ -990,6 +984,31 @@ bool RRSwitchBlock::is_side_mirror(RRSwitchBlock& cand, enum e_side side) const
|
|||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* check if a side of candidate SB is a mirror of the current one
|
||||
* Check the specified side of two switch blocks:
|
||||
* 1. Number of channel/opin/ipin rr_nodes are same
|
||||
* For channel rr_nodes
|
||||
* 2. check if their track_ids (ptc_num) are same
|
||||
* 3. Check if the switches (ids) are same
|
||||
* For opin/ipin rr_nodes,
|
||||
* 4. check if their parent type_descriptors same,
|
||||
* 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 RRSwitchBlock::is_side_mirror(RRSwitchBlock& cand, enum e_side side) const {
|
||||
|
||||
/* get a list of segments */
|
||||
std::vector<size_t> seg_ids = get_chan(side).get_segment_ids();
|
||||
|
||||
for (size_t iseg = 0; iseg < seg_ids.size(); ++iseg) {
|
||||
if (false == is_side_segment_mirror(cand, side, seg_ids[iseg])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1098,40 +1117,44 @@ char* RRSwitchBlock::gen_verilog_instance_name() const {
|
|||
}
|
||||
|
||||
/* Public Accessors Verilog writer */
|
||||
char* RRSwitchBlock::gen_verilog_side_module_name(enum e_side side) const {
|
||||
char* RRSwitchBlock::gen_verilog_side_module_name(enum e_side side, size_t seg_id) const {
|
||||
char* ret = NULL;
|
||||
Side side_manager(side);
|
||||
|
||||
std::string x_str = std::to_string(get_x());
|
||||
std::string y_str = std::to_string(get_y());
|
||||
std::string seg_id_str = std::to_string(seg_id);
|
||||
std::string side_str(side_manager.to_string());
|
||||
|
||||
ret = (char*)my_malloc(2 + 1 + x_str.length()
|
||||
+ 2 + y_str.length()
|
||||
+ 2 + side_str.length()
|
||||
+ 2 + 3 + seg_id_str.length()
|
||||
+ 1 + 1);
|
||||
|
||||
sprintf(ret, "sb_%lu__%lu__%s_",
|
||||
get_x(), get_y(), side_manager.to_string());
|
||||
sprintf(ret, "sb_%lu__%lu__%s_seg%lu_",
|
||||
get_x(), get_y(), side_manager.to_string(), seg_id);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
char* RRSwitchBlock::gen_verilog_side_instance_name(enum e_side side) const {
|
||||
char* RRSwitchBlock::gen_verilog_side_instance_name(enum e_side side, size_t seg_id) const {
|
||||
char* ret = NULL;
|
||||
Side side_manager(side);
|
||||
|
||||
std::string x_str = std::to_string(get_x());
|
||||
std::string y_str = std::to_string(get_y());
|
||||
std::string seg_id_str = std::to_string(seg_id);
|
||||
std::string side_str(side_manager.to_string());
|
||||
|
||||
ret = (char*)my_malloc(2 + 1 + x_str.length()
|
||||
+ 2 + y_str.length()
|
||||
+ 2 + side_str.length()
|
||||
+ 2 + 3 + seg_id_str.length()
|
||||
+ 4 + 1);
|
||||
|
||||
sprintf(ret, "sb_%lu__%lu__%s__0_",
|
||||
get_x(), get_y(), side_manager.to_string());
|
||||
sprintf(ret, "sb_%lu__%lu__%s_seg%lu_0_",
|
||||
get_x(), get_y(), side_manager.to_string(), seg_id);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -1760,10 +1783,11 @@ RRSwitchBlock DeviceRRSwitchBlock::get_switch_block(DeviceCoordinator& coordinat
|
|||
}
|
||||
|
||||
/* get the number of unique side modules of switch blocks */
|
||||
size_t DeviceRRSwitchBlock::get_num_unique_module(enum e_side side) const {
|
||||
size_t DeviceRRSwitchBlock::get_num_unique_module(enum e_side side, size_t seg_index) const {
|
||||
Side side_manager(side);
|
||||
assert(validate_side(side));
|
||||
return unique_module_[side_manager.to_size_t()].size();
|
||||
assert(validate_segment_index(seg_index));
|
||||
return unique_module_[side_manager.to_size_t()][seg_index].size();
|
||||
}
|
||||
|
||||
/* Get a rr switch block in the array with a coordinator */
|
||||
|
@ -1783,13 +1807,13 @@ size_t DeviceRRSwitchBlock::get_num_rotatable_mirror() const {
|
|||
}
|
||||
|
||||
/* Get a rr switch block which is a unique module of a side of SB */
|
||||
RRSwitchBlock DeviceRRSwitchBlock::get_unique_side_module(size_t index, enum e_side side) const {
|
||||
assert (validate_unique_module_index(index, side));
|
||||
RRSwitchBlock DeviceRRSwitchBlock::get_unique_side_module(size_t index, enum e_side side, size_t seg_id) const {
|
||||
assert (validate_unique_module_index(index, side, seg_id));
|
||||
|
||||
Side side_manager(side);
|
||||
assert (validate_side(side));
|
||||
|
||||
return rr_switch_block_[unique_module_[side_manager.to_size_t()][index].get_x()][unique_module_[side_manager.to_size_t()][index].get_y()];
|
||||
return rr_switch_block_[unique_module_[side_manager.to_size_t()][seg_id][index].get_x()][unique_module_[side_manager.to_size_t()][seg_id][index].get_y()];
|
||||
}
|
||||
|
||||
/* Get a rr switch block which a unique mirror */
|
||||
|
@ -1824,6 +1848,17 @@ size_t DeviceRRSwitchBlock::get_max_num_sides() const {
|
|||
return max_num_sides;
|
||||
}
|
||||
|
||||
/* Get the size of segment_ids */
|
||||
size_t DeviceRRSwitchBlock::get_num_segments() const {
|
||||
return segment_ids_.size();
|
||||
}
|
||||
|
||||
/* Get a segment id */
|
||||
size_t DeviceRRSwitchBlock::get_segment_id(size_t index) const {
|
||||
assert(validate_segment_index(index));
|
||||
return segment_ids_[index];
|
||||
}
|
||||
|
||||
/* Public Mutators */
|
||||
|
||||
/* TODO: TOBE DEPRECATED!!! conf_bits should be initialized when creating a switch block!!! */
|
||||
|
@ -1871,6 +1906,11 @@ void DeviceRRSwitchBlock::reserve_unique_module_id(DeviceCoordinator& coordinato
|
|||
RRSwitchBlock rr_sb = get_switch_block(coordinator);
|
||||
rr_sb_unique_module_id_[coordinator.get_x()][coordinator.get_y()].resize(rr_sb.get_num_sides());
|
||||
|
||||
for (size_t side = 0; side < rr_sb.get_num_sides(); ++side) {
|
||||
Side side_manager(side);
|
||||
rr_sb_unique_module_id_[coordinator.get_x()][coordinator.get_y()][side_manager.to_size_t()].resize(segment_ids_.size());
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1952,19 +1992,22 @@ void DeviceRRSwitchBlock::build_unique_module() {
|
|||
|
||||
/* Allocate the unique_side_module_ */
|
||||
unique_module_.resize(get_max_num_sides());
|
||||
for (size_t side = 0; side < unique_module_.size(); ++side) {
|
||||
unique_module_[side].resize(segment_ids_.size());
|
||||
}
|
||||
|
||||
for (size_t ix = 0; ix < rr_switch_block_.size(); ++ix) {
|
||||
for (size_t iy = 0; iy < rr_switch_block_[ix].size(); ++iy) {
|
||||
DeviceCoordinator coordinator(ix, iy);
|
||||
RRSwitchBlock* rr_sb = &(rr_switch_block_[ix][iy]);
|
||||
RRSwitchBlock rr_sb = rr_switch_block_[ix][iy];
|
||||
|
||||
/* reserve the rr_sb_unique_module_id */
|
||||
reserve_unique_module_id(coordinator);
|
||||
|
||||
for (size_t side = 0; side < rr_sb->get_num_sides(); ++side) {
|
||||
for (size_t side = 0; side < rr_sb.get_num_sides(); ++side) {
|
||||
Side side_manager(side);
|
||||
/* Try to add it to the list */
|
||||
add_unique_side_module(coordinator, *rr_sb, side_manager.get_side());
|
||||
add_unique_side_module(coordinator, rr_sb, side_manager.get_side());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2004,32 +2047,30 @@ void DeviceRRSwitchBlock::add_rotatable_mirror(DeviceCoordinator& coordinator,
|
|||
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
|
||||
* Otherwise, we add the module to the unique_module list
|
||||
*/
|
||||
void DeviceRRSwitchBlock::add_unique_side_module(DeviceCoordinator& coordinator, RRSwitchBlock& rr_sb, enum e_side side) {
|
||||
void DeviceRRSwitchBlock::add_unique_side_segment_module(DeviceCoordinator& coordinator,
|
||||
RRSwitchBlock& rr_sb,
|
||||
enum e_side side,
|
||||
size_t seg_id) {
|
||||
bool is_unique_side_module = true;
|
||||
Side side_manager(side);
|
||||
|
||||
/* add rotatable mirror support */
|
||||
for (size_t id = 0; id < get_num_unique_module(side); ++id) {
|
||||
for (size_t id = 0; id < get_num_unique_module(side, seg_id); ++id) {
|
||||
/* Skip if these may never match as a mirror (violation in basic requirements */
|
||||
if (true == get_switch_block(unique_module_[side_manager.to_size_t()][id]).is_side_mirror(rr_sb, side)) {
|
||||
if (true == get_switch_block(unique_module_[side_manager.to_size_t()][seg_id][id]).is_side_segment_mirror(rr_sb, side, segment_ids_[seg_id])) {
|
||||
/* This is a mirror, raise the flag and we finish */
|
||||
is_unique_side_module = false;
|
||||
/* Record the id of unique mirror */
|
||||
rr_sb_unique_module_id_[coordinator.get_x()][coordinator.get_y()][side_manager.to_size_t()] = id;
|
||||
rr_sb_unique_module_id_[coordinator.get_x()][coordinator.get_y()][side_manager.to_size_t()][seg_id] = id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Add to list if this is a unique mirror*/
|
||||
if (true == is_unique_side_module) {
|
||||
unique_module_[side_manager.to_size_t()].push_back(coordinator);
|
||||
unique_module_[side_manager.to_size_t()][seg_id].push_back(coordinator);
|
||||
/* Record the id of unique mirror */
|
||||
rr_sb_unique_module_id_[coordinator.get_x()][coordinator.get_y()][side_manager.to_size_t()] = unique_module_[side_manager.to_size_t()].size() - 1;
|
||||
rr_sb_unique_module_id_[coordinator.get_x()][coordinator.get_y()][side_manager.to_size_t()][seg_id] = unique_module_[side_manager.to_size_t()][seg_id].size() - 1;
|
||||
/*
|
||||
printf("Detect a rotatable mirror: SB[%lu][%lu]\n", coordinator.get_x(), coordinator.get_y());
|
||||
*/
|
||||
|
@ -2038,6 +2079,50 @@ void DeviceRRSwitchBlock::add_unique_side_module(DeviceCoordinator& coordinator,
|
|||
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
|
||||
* Otherwise, we add the module to the unique_module list
|
||||
*/
|
||||
void DeviceRRSwitchBlock::add_unique_side_module(DeviceCoordinator& coordinator,
|
||||
RRSwitchBlock& rr_sb,
|
||||
enum e_side side) {
|
||||
Side side_manager(side);
|
||||
|
||||
for (size_t iseg = 0; iseg < segment_ids_.size(); ++iseg) {
|
||||
add_unique_side_segment_module(coordinator, rr_sb, side, iseg);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* build a map of segment_ids */
|
||||
void DeviceRRSwitchBlock::build_segment_ids() {
|
||||
/* go through each rr_sb, each side and find the segment_ids */
|
||||
for (size_t ix = 0; ix < rr_switch_block_.size(); ++ix) {
|
||||
for (size_t iy = 0; iy < rr_switch_block_[ix].size(); ++iy) {
|
||||
RRSwitchBlock* rr_sb = &(rr_switch_block_[ix][iy]);
|
||||
for (size_t side = 0 ; side < rr_sb->get_num_sides(); ++side) {
|
||||
Side side_manager(side);
|
||||
/* get a list of segment_ids in this side */
|
||||
std::vector<size_t> cur_seg_ids = rr_sb->get_chan(side_manager.get_side()).get_segment_ids();
|
||||
/* add to the segment_id_ if exist */
|
||||
for (size_t iseg = 0; iseg < cur_seg_ids.size(); ++iseg) {
|
||||
std::vector<size_t>::iterator it = std::find(segment_ids_.begin(), segment_ids_.end(), cur_seg_ids[iseg]);
|
||||
/* find if it exists in the list */
|
||||
if (it != segment_ids_.end()) {
|
||||
/* exist: continue */
|
||||
continue;
|
||||
}
|
||||
/* does not exist, push into the vector */
|
||||
segment_ids_.push_back(cur_seg_ids[iseg]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* clean the content */
|
||||
void DeviceRRSwitchBlock::clear() {
|
||||
/* clean rr_switch_block array */
|
||||
|
@ -2099,6 +2184,15 @@ void DeviceRRSwitchBlock::clear_rotatable_mirror() {
|
|||
return;
|
||||
}
|
||||
|
||||
/* clean the content related to segment_ids */
|
||||
void DeviceRRSwitchBlock::clear_segment_ids() {
|
||||
/* clean segment_ids_ */
|
||||
segment_ids_.clear();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* Validate if the (x,y) is the range of this device */
|
||||
bool DeviceRRSwitchBlock::validate_coordinator(DeviceCoordinator& coordinator) const {
|
||||
if (coordinator.get_x() >= rr_switch_block_.capacity()) {
|
||||
|
@ -2136,12 +2230,20 @@ bool DeviceRRSwitchBlock::validate_rotatable_mirror_index(size_t index) const {
|
|||
}
|
||||
|
||||
/* Validate if the index in the range of unique_mirror vector*/
|
||||
bool DeviceRRSwitchBlock::validate_unique_module_index(size_t index, enum e_side side) const {
|
||||
bool DeviceRRSwitchBlock::validate_unique_module_index(size_t index, enum e_side side, size_t seg_index) const {
|
||||
assert( validate_side(side));
|
||||
assert( validate_segment_index(seg_index));
|
||||
Side side_manager(side);
|
||||
|
||||
if (index >= unique_module_[side_manager.get_side()].size()) {
|
||||
if (index >= unique_module_[side_manager.get_side()][seg_index].size()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DeviceRRSwitchBlock::validate_segment_index(size_t index) const {
|
||||
if (index >= segment_ids_.size()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -163,6 +163,7 @@ class RRSwitchBlock {
|
|||
size_t get_conf_bits_msb() const;
|
||||
bool is_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_side_mirror(RRSwitchBlock& cand, enum e_side side) const; /* check if a side of candidate SB is a mirror of the current one */
|
||||
bool is_side_segment_mirror(RRSwitchBlock& 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_mirror(RRSwitchBlock& cand) const; /* check if the candidate SB is a mirror of the current one */
|
||||
bool is_mirrorable(RRSwitchBlock& 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(RRSwitchBlock& cand) const; /* Determine an initial offset in rotating the candidate Switch Block to find a mirror matching*/
|
||||
|
@ -171,8 +172,8 @@ class RRSwitchBlock {
|
|||
public: /* Verilog writer */
|
||||
char* gen_verilog_module_name() const;
|
||||
char* gen_verilog_instance_name() const;
|
||||
char* gen_verilog_side_module_name(enum e_side side) const;
|
||||
char* gen_verilog_side_instance_name(enum e_side side) const;
|
||||
char* gen_verilog_side_module_name(enum e_side side, size_t seg_id) const;
|
||||
char* gen_verilog_side_instance_name(enum e_side side, size_t seg_id) const;
|
||||
public: /* Mutators */
|
||||
void set(const RRSwitchBlock& src); /* get a copy from a source */
|
||||
void set_coordinator(size_t x, size_t y);
|
||||
|
@ -242,15 +243,17 @@ class DeviceRRSwitchBlock {
|
|||
DeviceCoordinator get_switch_block_range() const; /* get the max coordinator of the switch block array */
|
||||
RRSwitchBlock get_switch_block(DeviceCoordinator& coordinator) const; /* Get a rr switch block in the array with a coordinator */
|
||||
RRSwitchBlock get_switch_block(size_t x, size_t y) const; /* Get a rr switch block in the array with a coordinator */
|
||||
size_t get_num_unique_module(enum e_side side) const; /* get the number of unique mirrors of switch blocks */
|
||||
size_t get_num_unique_module(enum e_side side, size_t seg_index) const; /* get the number of unique mirrors of switch blocks */
|
||||
size_t get_num_unique_mirror() const; /* get the number of unique mirrors of switch blocks */
|
||||
size_t get_num_rotatable_mirror() const; /* get the number of rotatable mirrors of switch blocks */
|
||||
RRSwitchBlock get_unique_side_module(size_t index, enum e_side side) const; /* Get a rr switch block which a unique mirror */
|
||||
RRSwitchBlock get_unique_side_module(size_t index, enum e_side side, size_t seg_id) const; /* Get a rr switch block which a unique mirror */
|
||||
RRSwitchBlock get_unique_mirror(size_t index) const; /* Get a rr switch block which a unique mirror */
|
||||
RRSwitchBlock get_unique_mirror(DeviceCoordinator& coordinator) const; /* Get a rr switch block which a unique mirror */
|
||||
RRSwitchBlock get_rotatable_mirror(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 */
|
||||
public: /* Mutators */
|
||||
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 */
|
||||
public: /* Mutators */
|
||||
void set_rr_switch_block_num_reserved_conf_bits(DeviceCoordinator& coordinator, size_t num_reserved_conf_bits); /* TODO: TOBE DEPRECATED!!! conf_bits should be initialized when creating a switch block!!! */
|
||||
void set_rr_switch_block_conf_bits_lsb(DeviceCoordinator& coordinator, size_t conf_bits_lsb); /* TODO: TOBE DEPRECATED!!! conf_bits should be initialized when creating a switch block!!! */
|
||||
void set_rr_switch_block_conf_bits_msb(DeviceCoordinator& coordinator, size_t conf_bits_msb); /* TODO: TOBE DEPRECATED!!! conf_bits should be initialized when creating a switch block!!! */
|
||||
|
@ -261,27 +264,33 @@ class DeviceRRSwitchBlock {
|
|||
void build_unique_mirror(); /* 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 side module */
|
||||
void add_rotatable_mirror(DeviceCoordinator& coordinator, RRSwitchBlock& rr_sb); /* Add a switch block to the array, which will automatically identify and update the lists of unique mirrors and rotatable mirrors */
|
||||
void add_unique_side_segment_module(DeviceCoordinator& coordinator, RRSwitchBlock& rr_sb, enum e_side side, size_t seg_id);
|
||||
void add_unique_side_module(DeviceCoordinator& coordinator, RRSwitchBlock& rr_sb, enum e_side side);
|
||||
void build_segment_ids(); /* build a map of segment_ids */
|
||||
void clear(); /* clean the content */
|
||||
void clear_unique_module(); /* clean the content */
|
||||
void clear_mirror(); /* clean the content */
|
||||
void clear_rotatable_mirror(); /* clean the content */
|
||||
void clear_segment_ids();
|
||||
private: /* Validators */
|
||||
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_unique_mirror_index(size_t index) const; /* Validate if the index in the range of unique_mirror vector*/
|
||||
bool validate_rotatable_mirror_index(size_t index) const; /* Validate if the index in the range of unique_mirror vector*/
|
||||
bool validate_unique_module_index(size_t index, enum e_side side) const; /* Validate if the index in the range of unique_module vector */
|
||||
bool validate_unique_module_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;
|
||||
private: /* Internal Data */
|
||||
std::vector< std::vector<RRSwitchBlock> > rr_switch_block_;
|
||||
|
||||
std::vector< std::vector< std::vector<size_t> > > rr_sb_unique_module_id_; /* A map from rr_switch_block to its unique_side_module [0..x][0..y][0..num_sides]*/
|
||||
std::vector <std::vector<DeviceCoordinator> > unique_module_; /* 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_module], num_sides will the max number of sides of all the rr_switch_blocks */
|
||||
std::vector< std::vector< std::vector< std::vector<size_t> > > > rr_sb_unique_module_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 <std::vector<DeviceCoordinator> > > unique_module_; /* 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<size_t> > rr_switch_block_mirror_id_; /* A map from rr_switch_block to its unique mirror */
|
||||
std::vector<DeviceCoordinator> unique_mirror_;
|
||||
std::vector< std::vector<size_t> > rr_switch_block_rotatable_mirror_id_; /* A map from rr_switch_block to its unique mirror */
|
||||
std::vector<DeviceCoordinator> rotatable_mirror_;
|
||||
|
||||
std::vector<size_t> segment_ids_;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Binary file not shown.
|
@ -1660,12 +1660,16 @@ int count_verilog_switch_box_reserved_conf_bits(t_sram_orgz_info* cur_sram_orgz_
|
|||
/* Count the number of configuration bits of a Switch Box */
|
||||
static
|
||||
size_t count_verilog_switch_box_side_reserved_conf_bits(t_sram_orgz_info* cur_sram_orgz_info,
|
||||
RRSwitchBlock& rr_sb, enum e_side side) {
|
||||
RRSwitchBlock& rr_sb, enum e_side side, size_t seg_id) {
|
||||
size_t num_reserved_conf_bits = 0;
|
||||
size_t temp_num_reserved_conf_bits = 0;
|
||||
Side side_manager(side);
|
||||
|
||||
for (size_t itrack = 0; itrack < rr_sb.get_chan_width(side); ++itrack) {
|
||||
/* Bypass unwanted segments */
|
||||
if (seg_id != rr_sb.get_chan_node_segment(side, itrack)) {
|
||||
continue;
|
||||
}
|
||||
switch (rr_sb.get_chan_node_direction(side, itrack)) {
|
||||
case OUT_PORT:
|
||||
temp_num_reserved_conf_bits =
|
||||
|
@ -1697,9 +1701,13 @@ size_t count_verilog_switch_box_reserved_conf_bits(t_sram_orgz_info* cur_sram_or
|
|||
|
||||
for (size_t side = 0; side < rr_sb.get_num_sides(); ++side) {
|
||||
Side side_manager(side);
|
||||
temp_num_reserved_conf_bits = count_verilog_switch_box_side_reserved_conf_bits(cur_sram_orgz_info, rr_sb, side_manager.get_side());
|
||||
/* Always select the largest number of reserved conf_bits */
|
||||
num_reserved_conf_bits = std::max(num_reserved_conf_bits, temp_num_reserved_conf_bits);
|
||||
/* get segment ids */
|
||||
std::vector<size_t> seg_ids = rr_sb.get_chan(side_manager.get_side()).get_segment_ids();
|
||||
for (size_t iseg = 0; iseg < seg_ids.size(); ++iseg) {
|
||||
temp_num_reserved_conf_bits = count_verilog_switch_box_side_reserved_conf_bits(cur_sram_orgz_info, rr_sb, side_manager.get_side(), seg_ids[iseg]);
|
||||
/* Always select the largest number of reserved conf_bits */
|
||||
num_reserved_conf_bits = std::max(num_reserved_conf_bits, temp_num_reserved_conf_bits);
|
||||
}
|
||||
}
|
||||
|
||||
return num_reserved_conf_bits;
|
||||
|
@ -1736,11 +1744,16 @@ int count_verilog_switch_box_conf_bits(t_sram_orgz_info* cur_sram_orgz_info,
|
|||
/* Count the number of configuration bits of a Switch Box */
|
||||
static
|
||||
size_t count_verilog_switch_box_side_conf_bits(t_sram_orgz_info* cur_sram_orgz_info,
|
||||
RRSwitchBlock& rr_sb, enum e_side side) {
|
||||
RRSwitchBlock& rr_sb,
|
||||
enum e_side side, size_t seg_id) {
|
||||
size_t num_conf_bits = 0;
|
||||
Side side_manager(side);
|
||||
|
||||
for (size_t itrack = 0; itrack < rr_sb.get_chan_width(side); ++itrack) {
|
||||
/* Bypass unwanted segments */
|
||||
if (seg_id != rr_sb.get_chan_node_segment(side, itrack)) {
|
||||
continue;
|
||||
}
|
||||
switch (rr_sb.get_chan_node_direction(side, itrack)) {
|
||||
case OUT_PORT:
|
||||
num_conf_bits += count_verilog_switch_box_interc_conf_bits(cur_sram_orgz_info, rr_sb, side,
|
||||
|
@ -1767,7 +1780,11 @@ size_t count_verilog_switch_box_conf_bits(t_sram_orgz_info* cur_sram_orgz_info,
|
|||
|
||||
for (size_t side = 0; side < rr_sb.get_num_sides(); ++side) {
|
||||
Side side_manager(side);
|
||||
num_conf_bits += count_verilog_switch_box_side_conf_bits(cur_sram_orgz_info, rr_sb, side_manager.get_side());
|
||||
/* get segment ids */
|
||||
std::vector<size_t> seg_ids = rr_sb.get_chan(side_manager.get_side()).get_segment_ids();
|
||||
for (size_t iseg = 0; iseg < seg_ids.size(); ++iseg) {
|
||||
num_conf_bits += count_verilog_switch_box_side_conf_bits(cur_sram_orgz_info, rr_sb, side_manager.get_side(), seg_ids[iseg]);
|
||||
}
|
||||
}
|
||||
|
||||
return num_conf_bits;
|
||||
|
@ -1809,6 +1826,7 @@ static
|
|||
void dump_verilog_routing_switch_box_unique_side_subckt_portmap(FILE* fp,
|
||||
RRSwitchBlock& rr_sb,
|
||||
enum e_side sb_side,
|
||||
size_t seg_id,
|
||||
boolean dump_port_type) {
|
||||
/* Check file handler*/
|
||||
if (NULL == fp) {
|
||||
|
@ -1828,6 +1846,10 @@ void dump_verilog_routing_switch_box_unique_side_subckt_portmap(FILE* fp,
|
|||
DeviceCoordinator port_coordinator = rr_sb.get_side_block_coordinator(side_manager.get_side());
|
||||
|
||||
for (size_t itrack = 0; itrack < rr_sb.get_chan_width(side_manager.get_side()); ++itrack) {
|
||||
/* Bypass unwanted segments */
|
||||
if (seg_id != rr_sb.get_chan_node_segment(side_manager.get_side(), itrack)) {
|
||||
continue;
|
||||
}
|
||||
switch (rr_sb.get_chan_node_direction(side_manager.get_side(), itrack)) {
|
||||
case OUT_PORT:
|
||||
/* if this is the specified side, we only consider output ports */
|
||||
|
@ -1920,7 +1942,8 @@ void dump_verilog_routing_switch_box_unique_side_subckt_portmap(FILE* fp,
|
|||
*/
|
||||
static
|
||||
void dump_verilog_routing_switch_box_unique_side_module(t_sram_orgz_info* cur_sram_orgz_info,
|
||||
char* verilog_dir, char* subckt_dir, size_t module_id,
|
||||
char* verilog_dir, char* subckt_dir,
|
||||
size_t module_id, size_t seg_id,
|
||||
RRSwitchBlock& rr_sb, enum e_side side) {
|
||||
FILE* fp = NULL;
|
||||
char* fname = NULL;
|
||||
|
@ -1932,9 +1955,9 @@ void dump_verilog_routing_switch_box_unique_side_module(t_sram_orgz_info* cur_sr
|
|||
}
|
||||
|
||||
/* Count the number of configuration bits to be consumed by this Switch block */
|
||||
int num_conf_bits = count_verilog_switch_box_side_conf_bits(cur_sram_orgz_info, rr_sb, side);
|
||||
int num_conf_bits = count_verilog_switch_box_side_conf_bits(cur_sram_orgz_info, rr_sb, side, seg_id);
|
||||
/* Count the number of reserved configuration bits to be consumed by this Switch block */
|
||||
int num_reserved_conf_bits = count_verilog_switch_box_side_reserved_conf_bits(cur_sram_orgz_info, rr_sb, side);
|
||||
int num_reserved_conf_bits = count_verilog_switch_box_side_reserved_conf_bits(cur_sram_orgz_info, rr_sb, side, seg_id);
|
||||
/* Estimate the sram_verilog_model->cnt */
|
||||
int cur_num_sram = get_sram_orgz_info_num_mem_bit(cur_sram_orgz_info);
|
||||
int esti_sram_cnt = cur_num_sram + num_conf_bits;
|
||||
|
@ -1945,26 +1968,28 @@ void dump_verilog_routing_switch_box_unique_side_module(t_sram_orgz_info* cur_sr
|
|||
|
||||
std::string file_description("Unique module for Switch Block side: ");
|
||||
file_description += side_manager.to_string();
|
||||
file_description += "seg";
|
||||
file_description += std::to_string(seg_id);
|
||||
|
||||
/* Create file handler */
|
||||
fp = verilog_create_one_subckt_file(subckt_dir, file_description.c_str(),
|
||||
fname_prefix.c_str(), module_id, -1, &fname);
|
||||
fname_prefix.c_str(), module_id, seg_id, &fname);
|
||||
|
||||
/* Print preprocessing flags */
|
||||
verilog_include_defines_preproc_file(fp, verilog_dir);
|
||||
|
||||
/* Comment lines */
|
||||
fprintf(fp,
|
||||
"//----- Verilog Module of Unique Switch Box[%lu][%lu] at Side %s -----\n",
|
||||
rr_sb.get_x(), rr_sb.get_y(), side_manager.to_string());
|
||||
"//----- Verilog Module of Unique Switch Box[%lu][%lu] at Side %s, Segment id: %lu -----\n",
|
||||
rr_sb.get_x(), rr_sb.get_y(), side_manager.to_string(), seg_id);
|
||||
/* Print the definition of subckt*/
|
||||
fprintf(fp, "module %s ( \n", rr_sb.gen_verilog_side_module_name(side));
|
||||
fprintf(fp, "module %s ( \n", rr_sb.gen_verilog_side_module_name(side, seg_id));
|
||||
/* dump global ports */
|
||||
if (0 < dump_verilog_global_ports(fp, global_ports_head, TRUE)) {
|
||||
fprintf(fp, ",\n");
|
||||
}
|
||||
|
||||
dump_verilog_routing_switch_box_unique_side_subckt_portmap(fp, rr_sb, side, TRUE);
|
||||
dump_verilog_routing_switch_box_unique_side_subckt_portmap(fp, rr_sb, side, seg_id, TRUE);
|
||||
|
||||
/* Put down configuration port */
|
||||
/* output of each configuration bit */
|
||||
|
@ -2005,6 +2030,10 @@ void dump_verilog_routing_switch_box_unique_side_module(t_sram_orgz_info* cur_sr
|
|||
fprintf(fp, "//----- %s side Multiplexers -----\n",
|
||||
side_manager.to_string());
|
||||
for (size_t itrack = 0; itrack < rr_sb.get_chan_width(side_manager.get_side()); ++itrack) {
|
||||
/* Bypass unwanted segments */
|
||||
if (seg_id != rr_sb.get_chan_node_segment(side_manager.get_side(), itrack)) {
|
||||
continue;
|
||||
}
|
||||
assert((CHANX == rr_sb.get_chan_node(side_manager.get_side(), itrack)->type)
|
||||
||(CHANY == rr_sb.get_chan_node(side_manager.get_side(), itrack)->type));
|
||||
/* We care INC_DIRECTION tracks at this side*/
|
||||
|
@ -2175,61 +2204,70 @@ void dump_verilog_routing_switch_box_unique_module(t_sram_orgz_info* cur_sram_or
|
|||
|
||||
/* Get the channel width on this side, if it is zero, we return */
|
||||
if (0 == rr_sb.get_chan_width(side_manager.get_side())) {
|
||||
fprintf(fp, "//----- %s side has zero channel width, module dump skipped -----\n",
|
||||
side_manager.to_string());
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Count the number of configuration bits to be consumed by this Switch block */
|
||||
int side_num_conf_bits = count_verilog_switch_box_side_conf_bits(cur_sram_orgz_info, rr_sb, side_manager.get_side());
|
||||
/* Count the number of reserved configuration bits to be consumed by this Switch block */
|
||||
int side_num_reserved_conf_bits = count_verilog_switch_box_side_reserved_conf_bits(cur_sram_orgz_info, rr_sb, side_manager.get_side());
|
||||
/* get segment ids */
|
||||
std::vector<size_t> seg_ids = rr_sb.get_chan(side_manager.get_side()).get_segment_ids();
|
||||
for (size_t iseg = 0; iseg < seg_ids.size(); ++iseg) {
|
||||
fprintf(fp, "//----- %s side Submodule with Segment id: %lu -----\n",
|
||||
side_manager.to_string(), seg_ids[iseg]);
|
||||
|
||||
/* Cache the sram counter */
|
||||
cur_sram_msb += side_num_conf_bits - 1;
|
||||
/* Count the number of configuration bits to be consumed by this Switch block */
|
||||
int side_num_conf_bits = count_verilog_switch_box_side_conf_bits(cur_sram_orgz_info, rr_sb, side_manager.get_side(), seg_ids[iseg]);
|
||||
/* Count the number of reserved configuration bits to be consumed by this Switch block */
|
||||
int side_num_reserved_conf_bits = count_verilog_switch_box_side_reserved_conf_bits(cur_sram_orgz_info, rr_sb, side_manager.get_side(), seg_ids[iseg]);
|
||||
|
||||
/* Instanciate the subckt*/
|
||||
fprintf(fp,
|
||||
"%s %s ( \n",
|
||||
rr_sb.gen_verilog_side_module_name(side_manager.get_side()),
|
||||
rr_sb.gen_verilog_side_instance_name(side_manager.get_side()));
|
||||
/* dump global ports */
|
||||
if (0 < dump_verilog_global_ports(fp, global_ports_head, FALSE)) {
|
||||
fprintf(fp, ",\n");
|
||||
/* Cache the sram counter */
|
||||
cur_sram_msb += side_num_conf_bits - 1;
|
||||
|
||||
/* Instanciate the subckt*/
|
||||
fprintf(fp,
|
||||
"%s %s ( \n",
|
||||
rr_sb.gen_verilog_side_module_name(side_manager.get_side(), seg_ids[iseg]),
|
||||
rr_sb.gen_verilog_side_instance_name(side_manager.get_side(), seg_ids[iseg]));
|
||||
/* dump global ports */
|
||||
if (0 < dump_verilog_global_ports(fp, global_ports_head, FALSE)) {
|
||||
fprintf(fp, ",\n");
|
||||
}
|
||||
|
||||
dump_verilog_routing_switch_box_unique_side_subckt_portmap(fp, rr_sb, side_manager.get_side(), seg_ids[iseg], FALSE);
|
||||
|
||||
/* Put down configuration port */
|
||||
/* output of each configuration bit */
|
||||
/* Reserved sram ports */
|
||||
dump_verilog_reserved_sram_ports(fp, cur_sram_orgz_info,
|
||||
0,
|
||||
side_num_reserved_conf_bits - 1,
|
||||
VERILOG_PORT_INPUT);
|
||||
if (0 < side_num_reserved_conf_bits) {
|
||||
fprintf(fp, ",\n");
|
||||
}
|
||||
/* Normal sram ports */
|
||||
dump_verilog_sram_ports(fp, cur_sram_orgz_info,
|
||||
cur_sram_lsb,
|
||||
cur_sram_msb,
|
||||
VERILOG_PORT_INPUT);
|
||||
|
||||
/* Dump ports only visible during formal verification*/
|
||||
if (0 < num_conf_bits) {
|
||||
fprintf(fp, "\n");
|
||||
fprintf(fp, "`ifdef %s\n", verilog_formal_verification_preproc_flag);
|
||||
fprintf(fp, ",\n");
|
||||
dump_verilog_formal_verification_sram_ports(fp, cur_sram_orgz_info,
|
||||
cur_sram_lsb,
|
||||
cur_sram_msb,
|
||||
VERILOG_PORT_OUTPUT);
|
||||
fprintf(fp, "\n");
|
||||
fprintf(fp, "`endif\n");
|
||||
}
|
||||
fprintf(fp, "); \n");
|
||||
|
||||
/* Update sram_lsb */
|
||||
cur_sram_lsb = cur_sram_msb + 1;
|
||||
}
|
||||
|
||||
dump_verilog_routing_switch_box_unique_side_subckt_portmap(fp, rr_sb, side_manager.get_side(), FALSE);
|
||||
|
||||
/* Put down configuration port */
|
||||
/* output of each configuration bit */
|
||||
/* Reserved sram ports */
|
||||
dump_verilog_reserved_sram_ports(fp, cur_sram_orgz_info,
|
||||
0,
|
||||
side_num_reserved_conf_bits - 1,
|
||||
VERILOG_PORT_INPUT);
|
||||
if (0 < side_num_reserved_conf_bits) {
|
||||
fprintf(fp, ",\n");
|
||||
}
|
||||
/* Normal sram ports */
|
||||
dump_verilog_sram_ports(fp, cur_sram_orgz_info,
|
||||
cur_sram_lsb,
|
||||
cur_sram_msb,
|
||||
VERILOG_PORT_INPUT);
|
||||
|
||||
/* Dump ports only visible during formal verification*/
|
||||
if (0 < num_conf_bits) {
|
||||
fprintf(fp, "\n");
|
||||
fprintf(fp, "`ifdef %s\n", verilog_formal_verification_preproc_flag);
|
||||
fprintf(fp, ",\n");
|
||||
dump_verilog_formal_verification_sram_ports(fp, cur_sram_orgz_info,
|
||||
cur_sram_lsb,
|
||||
cur_sram_msb,
|
||||
VERILOG_PORT_OUTPUT);
|
||||
fprintf(fp, "\n");
|
||||
fprintf(fp, "`endif\n");
|
||||
}
|
||||
fprintf(fp, "); \n");
|
||||
|
||||
/* Update sram_lsb */
|
||||
cur_sram_lsb = cur_sram_msb + 1;
|
||||
}
|
||||
|
||||
fprintf(fp, "endmodule\n");
|
||||
|
@ -3409,9 +3447,12 @@ void dump_verilog_routing_resources(t_sram_orgz_info* cur_sram_orgz_info,
|
|||
/* Output unique side modules */
|
||||
for (size_t side = 0; side < device_rr_switch_block.get_max_num_sides(); ++side) {
|
||||
Side side_manager(side);
|
||||
for (size_t isb = 0; isb < device_rr_switch_block.get_num_unique_module(side_manager.get_side()); ++isb) {
|
||||
RRSwitchBlock unique_mirror = device_rr_switch_block.get_unique_side_module(isb, side_manager.get_side());
|
||||
dump_verilog_routing_switch_box_unique_side_module(cur_sram_orgz_info, verilog_dir, subckt_dir, isb, unique_mirror, side_manager.get_side());
|
||||
for (size_t iseg = 0; iseg < device_rr_switch_block.get_num_segments(); ++iseg) {
|
||||
for (size_t isb = 0; isb < device_rr_switch_block.get_num_unique_module(side_manager.get_side(), iseg); ++isb) {
|
||||
RRSwitchBlock unique_mirror = device_rr_switch_block.get_unique_side_module(isb, side_manager.get_side(), iseg);
|
||||
size_t seg_id = device_rr_switch_block.get_segment_id(iseg);
|
||||
dump_verilog_routing_switch_box_unique_side_module(cur_sram_orgz_info, verilog_dir, subckt_dir, isb, seg_id, unique_mirror, side_manager.get_side());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue