diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_backannotate_utils.c b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_backannotate_utils.c index 9a219dcd3..8d1558e1d 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_backannotate_utils.c +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_backannotate_utils.c @@ -3129,7 +3129,6 @@ void spice_backannotate_vpr_post_route_info(t_det_routing_arch RoutingArch, /* Build Array for each Switch block and Connection block */ vpr_printf(TIO_MESSAGE_INFO, "Collecting detailed information for each Switch block...\n"); alloc_and_build_switch_blocks_info(RoutingArch, num_rr_nodes, rr_node, rr_node_indices); - device_rr_switch_block = build_device_rr_switch_blocks(num_rr_nodes, rr_node, rr_node_indices); vpr_printf(TIO_MESSAGE_INFO, "Collecting detailed information for each to Connection block...\n"); alloc_and_build_connection_blocks_info(RoutingArch, num_rr_nodes, rr_node, rr_node_indices); diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_setup.c b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_setup.c index c16950462..fd1857e0e 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_setup.c +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_setup.c @@ -1400,6 +1400,7 @@ void fpga_x2p_setup(t_vpr_setup vpr_setup, /* Assign Gobal variable: build the Routing Resource Channels */ device_rr_chan = build_device_rr_chan(num_rr_nodes, rr_node, rr_node_indices, Arch->num_segments, rr_indexed_data); + device_rr_switch_block = build_device_rr_switch_blocks(num_rr_nodes, rr_node, rr_node_indices); /* Rotatable will be done in the next step identify_rotatable_switch_blocks(); 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 920340d1e..ee681c73f 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 @@ -1037,6 +1037,7 @@ RRSwitchBlock build_rr_switch_block(int sb_x, int sb_y, rr_switch_block.clear_ipin_nodes(side_manager.get_side()); /* Free */ + my_free(chan_rr_node); temp_num_opin_rr_nodes[0] = 0; my_free(temp_opin_rr_node[0]); temp_num_opin_rr_nodes[1] = 0; @@ -1082,6 +1083,10 @@ DeviceRRSwitchBlock build_device_rr_switch_blocks(int LL_num_rr_nodes, "Detect %d independent switch blocks from %d switch blocks.\n", LL_device_rr_switch_block.get_num_unique_mirror(), (nx + 1) * (ny + 1) ); + vpr_printf(TIO_MESSAGE_INFO, + "Detect %d rotatable unique switch blocks from %d switch blocks.\n", + LL_device_rr_switch_block.get_num_rotatable_mirror(), (nx + 1) * (ny + 1) ); + return LL_device_rr_switch_block; } 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 6d79b5646..e56832b46 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/base/rr_blocks.cpp +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/rr_blocks.cpp @@ -336,6 +336,16 @@ size_t RRSwitchBlock::get_chan_width(enum e_side side) const { return chan_node_[side_manager.to_size_t()].size(); } +/* Get the maximum number of routing tracks on all sides */ +size_t RRSwitchBlock::get_max_chan_width() const { + size_t max_chan_width = 0; + for (size_t side = 0; side < get_num_sides(); ++side) { + Side side_manager(side); + max_chan_width = std::max(max_chan_width, get_chan_width(side_manager.get_side())); + } + return max_chan_width; +} + /* Get the direction of a rr_node at a given side and track_id */ enum PORTS RRSwitchBlock::get_chan_node_direction(enum e_side side, size_t track_id) const { Side side_manager(side); @@ -783,12 +793,12 @@ void RRSwitchBlock::rotate_chan_node(size_t offset) { size_t rotate_begin = 0; size_t rotate_end = 0; /* Partition the chan nodes on this side, depending on its length */ + /* skip this side if there is no nodes */ + if (0 == get_chan_width(side_manager.get_side())) { + continue; + } for (size_t inode = 0; inode < get_chan_width(side_manager.get_side()) - 1; ++inode) { - if ( ( (chan_node_[side][inode]->xlow != chan_node_[side][inode + 1]->xlow) - || (chan_node_[side][inode]->ylow != chan_node_[side][inode + 1]->ylow) - || (chan_node_[side][inode]->xhigh != chan_node_[side][inode + 1]->xhigh) - || (chan_node_[side][inode]->yhigh != chan_node_[side][inode + 1]->yhigh) - || (chan_node_direction_[side][inode] != chan_node_direction_[side][inode + 1])) + if ( ( abs(chan_node_[side][inode]->yhigh - chan_node_[side][inode]->ylow + chan_node_[side][inode]->xhigh - chan_node_[side][inode]->xlow) != abs(chan_node_[side][inode + 1]->yhigh - chan_node_[side][inode + 1]->ylow + chan_node_[side][inode + 1]->xhigh - chan_node_[side][inode + 1]->xlow)) || ( inode == get_chan_width(side_manager.get_side()) - 2) ) { /* Record the upper bound */ if ( inode == get_chan_width(side_manager.get_side()) - 2) { @@ -797,7 +807,13 @@ void RRSwitchBlock::rotate_chan_node(size_t offset) { rotate_end = inode; } /* Make sure offset is in range */ - assert (offset < rotate_end - rotate_begin); + /* skip this side if there is no nodes */ + if (0 >= rotate_end - rotate_begin) { + /* Update the lower bound */ + rotate_begin = inode + 1; + continue; + } + assert(offset < rotate_end - rotate_begin + 1); /* Find a group split, rotate */ std::rotate(chan_node_.begin() + rotate_begin, chan_node_.begin() + rotate_begin + offset, @@ -822,6 +838,10 @@ void RRSwitchBlock::rotate_opin_node(size_t offset) { Side side_manager(side); size_t rotate_begin = 0; size_t rotate_end = 0; + /* skip this side if there is no nodes */ + if (0 == get_num_opin_nodes(side_manager.get_side())) { + continue; + } /* Partition the opin nodes on this side, depending on grids */ for (size_t inode = 0; inode < get_num_opin_nodes(side_manager.get_side()) - 1; ++inode) { if ( ( (opin_node_[side][inode]->xlow != opin_node_[side][inode + 1]->xlow) @@ -836,8 +856,14 @@ void RRSwitchBlock::rotate_opin_node(size_t offset) { } else { rotate_end = inode; } + /* skip this side if there is no nodes */ + if (0 >= rotate_end - rotate_begin) { + /* Update the lower bound */ + rotate_begin = inode + 1; + continue; + } /* Make sure offset is in range */ - assert (offset < rotate_end - rotate_begin); + assert (offset < rotate_end - rotate_begin + 1); /* Find a group split, rotate */ std::rotate(opin_node_.begin() + rotate_begin, opin_node_.begin() + rotate_begin + offset, @@ -1153,9 +1179,12 @@ void DeviceRRSwitchBlock::set_rr_switch_block_conf_bits_msb(DeviceCoordinator& c void DeviceRRSwitchBlock::reserve(DeviceCoordinator& coordinator) { rr_switch_block_.resize(coordinator.get_x()); rr_switch_block_mirror_id_.resize(coordinator.get_x()); + rr_switch_block_rotatable_mirror_id_.resize(coordinator.get_x()); + for (size_t x = 0; x < coordinator.get_x(); ++x) { rr_switch_block_[x].resize(coordinator.get_y()); rr_switch_block_mirror_id_[x].resize(coordinator.get_y()); + rr_switch_block_rotatable_mirror_id_[x].resize(coordinator.get_y()); } return; } @@ -1165,11 +1194,13 @@ void DeviceRRSwitchBlock::resize_upon_need(DeviceCoordinator& coordinator) { if (coordinator.get_x() + 1 > rr_switch_block_.capacity()) { rr_switch_block_.resize(coordinator.get_x()); rr_switch_block_mirror_id_.resize(coordinator.get_x()); + rr_switch_block_rotatable_mirror_id_.resize(coordinator.get_x()); } if (coordinator.get_y() + 1 > rr_switch_block_[coordinator.get_x()].capacity()) { rr_switch_block_[coordinator.get_x()].resize(coordinator.get_y()); rr_switch_block_mirror_id_[coordinator.get_x()].resize(coordinator.get_y()); + rr_switch_block_rotatable_mirror_id_[coordinator.get_x()].resize(coordinator.get_y()); } return; @@ -1179,6 +1210,7 @@ void DeviceRRSwitchBlock::resize_upon_need(DeviceCoordinator& coordinator) { void DeviceRRSwitchBlock::add_rr_switch_block(DeviceCoordinator& coordinator, RRSwitchBlock& rr_switch_block) { bool is_unique_mirror = true; + bool is_rotatable_mirror = true; /* Resize upon needs*/ resize_upon_need(coordinator); @@ -1203,7 +1235,33 @@ void DeviceRRSwitchBlock::add_rr_switch_block(DeviceCoordinator& coordinator, rr_switch_block_mirror_id_[coordinator.get_x()][coordinator.get_y()] = unique_mirror_.size() - 1; } - /* TODO: add rotatable mirror support */ + /* add rotatable mirror support */ + for (size_t mirror_id = 0; mirror_id < get_num_rotatable_mirror(); ++mirror_id) { + RRSwitchBlock rotate_mirror = rr_switch_block; + /* Try to rotate as many times as the maximum channel width in this switch block + * This may not fully cover all the rotation possibility but may be enough now + */ + for (size_t offset = 0; offset < rr_switch_block.get_max_chan_width(); ++offset) { + rotate_mirror.rotate(1); + if (true == get_switch_block(unique_mirror_[mirror_id]).is_mirror(rotate_mirror)) { + /* This is a mirror, raise the flag and we finish */ + is_rotatable_mirror = false; + /* Record the id of unique mirror */ + rr_switch_block_rotatable_mirror_id_[coordinator.get_x()][coordinator.get_y()] = mirror_id; + break; + } + } + if (false == is_rotatable_mirror) { + break; + } + } + /* Add to list if this is a unique mirror*/ + if (true == is_rotatable_mirror) { + rotatable_mirror_.push_back(coordinator); + /* Record the id of unique mirror */ + rr_switch_block_rotatable_mirror_id_[coordinator.get_x()][coordinator.get_y()] = rotatable_mirror_.size() - 1; + } + return; } 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 bbd665bc9..aba328fa8 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/base/rr_blocks.h +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/rr_blocks.h @@ -126,6 +126,7 @@ class RRSwitchBlock { DeviceCoordinator get_coordinator() const; /* Get the number of sides of this SB */ 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_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 */ t_rr_node* get_chan_node(enum e_side side, size_t track_id) const; /* get a rr_node at a given side and track_id */ size_t get_num_ipin_nodes(enum e_side side) const; /* Get the number of IPIN rr_nodes on a side */ @@ -223,6 +224,7 @@ class DeviceRRSwitchBlock { private: /* Internal Data */ std::vector< std::vector > rr_switch_block_; std::vector< std::vector > rr_switch_block_mirror_id_; /* A map from rr_switch_block to its unique mirror */ + std::vector< std::vector > rr_switch_block_rotatable_mirror_id_; /* A map from rr_switch_block to its unique mirror */ std::vector unique_mirror_; std::vector rotatable_mirror_; }; diff --git a/vpr7_x2p/vpr/go_fpga_verilog.sh b/vpr7_x2p/vpr/go_fpga_verilog.sh index 969ebceb3..05c2a589a 100755 --- a/vpr7_x2p/vpr/go_fpga_verilog.sh +++ b/vpr7_x2p/vpr/go_fpga_verilog.sh @@ -39,6 +39,6 @@ rm -rf $verilog_output_dirpath/$verilog_output_dirname #valgrind ./vpr $arch_xml_file $blif_file --full_stats --nodisp --activity_file $act_file --fpga_verilog --fpga_verilog_dir $verilog_output_dirpath/$verilog_output_dirname --fpga_x2p_rename_illegal_port --fpga_bitstream_generator --fpga_verilog_print_top_testbench --fpga_verilog_print_input_blif_testbench --fpga_verilog_include_timing --fpga_verilog_include_signal_init --fpga_verilog_print_modelsim_autodeck $modelsim_ini_file --fpga_verilog_print_formal_verification_top_netlist --fpga_verilog_print_autocheck_top_testbench $verilog_reference --fpga_verilog_print_user_defined_template --route_chan_width $vpr_route_chan_width --fpga_verilog_print_sdc_pnr --fpga_verilog_print_sdc_analysis --fpga_verilog_print_report_timing_tcl -./vpr $arch_xml_file $blif_file --full_stats --nodisp --activity_file $act_file --fpga_verilog --fpga_verilog_dir $verilog_output_dirpath/$verilog_output_dirname\_compact --fpga_x2p_rename_illegal_port --fpga_bitstream_generator --fpga_verilog_print_top_testbench --fpga_verilog_print_input_blif_testbench --fpga_verilog_include_timing --fpga_verilog_include_signal_init --fpga_verilog_print_modelsim_autodeck $modelsim_ini_file --fpga_verilog_print_formal_verification_top_netlist --fpga_verilog_print_autocheck_top_testbench $verilog_reference --fpga_verilog_print_user_defined_template --route_chan_width $vpr_route_chan_width --fpga_x2p_compact_routing_hierarchy --fpga_verilog_print_sdc_pnr --fpga_verilog_print_sdc_analysis --fpga_verilog_print_report_timing_tcl +#./vpr $arch_xml_file $blif_file --full_stats --nodisp --activity_file $act_file --fpga_verilog --fpga_verilog_dir $verilog_output_dirpath/$verilog_output_dirname\_compact --fpga_x2p_rename_illegal_port --fpga_bitstream_generator --fpga_verilog_print_top_testbench --fpga_verilog_print_input_blif_testbench --fpga_verilog_include_timing --fpga_verilog_include_signal_init --fpga_verilog_print_modelsim_autodeck $modelsim_ini_file --fpga_verilog_print_formal_verification_top_netlist --fpga_verilog_print_autocheck_top_testbench $verilog_reference --fpga_verilog_print_user_defined_template --route_chan_width $vpr_route_chan_width --fpga_x2p_compact_routing_hierarchy --fpga_verilog_print_sdc_pnr --fpga_verilog_print_sdc_analysis --fpga_verilog_print_report_timing_tcl