diff --git a/openfpga/src/annotation/device_rr_gsb.cpp b/openfpga/src/annotation/device_rr_gsb.cpp index 78ce8e16b..ccbda2bbc 100644 --- a/openfpga/src/annotation/device_rr_gsb.cpp +++ b/openfpga/src/annotation/device_rr_gsb.cpp @@ -1,8 +1,12 @@ /************************************************************************ * Member functions for class DeviceRRGSB ***********************************************************************/ + #include "device_rr_gsb.h" +#include +#include + #include "rr_gsb_utils.h" #include "vtr_assert.h" #include "vtr_log.h" @@ -171,6 +175,18 @@ void DeviceRRGSB::reserve(const vtr::Point& coordinate) { cby_unique_module_id_[x].resize(coordinate.y()); } } +void DeviceRRGSB::reserve_unique_modules(const vtr::Point& coordinate) { + sb_unique_module_id_.resize(coordinate.x()); + cbx_unique_module_id_.resize(coordinate.x()); + cby_unique_module_id_.resize(coordinate.x()); + + for (size_t x = 0; x < coordinate.x(); ++x) { + sb_unique_module_id_[x].resize(coordinate.y()); + + cbx_unique_module_id_[x].resize(coordinate.y()); + cby_unique_module_id_[x].resize(coordinate.y()); + } +} /* Resize rr_switch_block array is needed*/ void DeviceRRGSB::resize_upon_need(const vtr::Point& coordinate) { @@ -410,6 +426,18 @@ void DeviceRRGSB::clear() { clear_sb_unique_module_id(); } +void DeviceRRGSB::clear_unique_modules() { + /* 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(); +} + void DeviceRRGSB::clear_gsb() { /* clean gsb array */ for (size_t x = 0; x < rr_gsb_.size(); ++x) { @@ -551,4 +579,144 @@ size_t DeviceRRGSB::get_cb_unique_module_index( return cb_unique_module_id; } +void DeviceRRGSB::preload_unique_cbx_module( + const vtr::Point block_coordinate, + const std::vector> instance_coords) { + /* Add to list if this is a unique mirror*/ + size_t limit_x = cbx_unique_module_id_.size(); + size_t limit_y = cbx_unique_module_id_[0].size(); + + VTR_ASSERT(block_coordinate.x() < limit_x); + VTR_ASSERT(block_coordinate.y() < limit_y); + add_cb_unique_module(CHANX, block_coordinate); + /* Record the id of unique mirror */ + set_cb_unique_module_id(CHANX, block_coordinate, + get_num_cb_unique_module(CHANX) - 1); + + /* Traverse the unique_mirror list and set up its module id */ + for (auto instance_location : instance_coords) { + /* Record the id of unique mirror */ + VTR_ASSERT(instance_location.x() < limit_x); + VTR_ASSERT(instance_location.y() < limit_y); + set_cb_unique_module_id( + CHANX, instance_location, + cbx_unique_module_id_[block_coordinate.x()][block_coordinate.y()]); + } +} + +void DeviceRRGSB::preload_unique_cby_module( + const vtr::Point block_coordinate, + const std::vector> instance_coords) { + /* Add to list if this is a unique mirror*/ + size_t limit_x = cby_unique_module_id_.size(); + size_t limit_y = cby_unique_module_id_[0].size(); + + VTR_ASSERT(block_coordinate.x() < limit_x); + VTR_ASSERT(block_coordinate.y() < limit_y); + add_cb_unique_module(CHANY, block_coordinate); + /* Record the id of unique mirror */ + set_cb_unique_module_id(CHANY, block_coordinate, + get_num_cb_unique_module(CHANY) - 1); + + /* Traverse the unique_mirror list and set up its module id */ + for (auto instance_location : instance_coords) { + /* Record the id of unique mirror */ + VTR_ASSERT(instance_location.x() < limit_x); + VTR_ASSERT(instance_location.y() < limit_y); + set_cb_unique_module_id( + CHANY, instance_location, + cby_unique_module_id_[block_coordinate.x()][block_coordinate.y()]); + } +} + +void DeviceRRGSB::preload_unique_sb_module( + const vtr::Point block_coordinate, + const std::vector> instance_coords) { + /*input block coordinate should be within gsb coord range*/ + VTR_ASSERT(block_coordinate.x() < sb_unique_module_id_.size()); + VTR_ASSERT(block_coordinate.y() < sb_unique_module_id_[0].size()); + sb_unique_module_.push_back(block_coordinate); + /* Record the id of unique module */ + sb_unique_module_id_[block_coordinate.x()][block_coordinate.y()] = + sb_unique_module_.size() - 1; + + /* each mirror instance of the unique module will have the same module id as + * the unique module */ + for (auto instance_location : instance_coords) { + VTR_ASSERT(instance_location.x() < sb_unique_module_id_.size()); + VTR_ASSERT(instance_location.y() < sb_unique_module_id_[0].size()); + sb_unique_module_id_[instance_location.x()][instance_location.y()] = + sb_unique_module_id_[block_coordinate.x()][block_coordinate.y()]; + } +} + +void DeviceRRGSB::get_id_unique_sb_block_map( + std::map>& id_unique_block_map) const { + for (size_t id = 0; id < get_num_sb_unique_module(); ++id) { + const auto& unique_block_coord = sb_unique_module_[id]; + auto unique_module_id = + sb_unique_module_id_[unique_block_coord.x()][unique_block_coord.y()]; + id_unique_block_map[unique_module_id] = unique_block_coord; + } +} + +void DeviceRRGSB::get_id_sb_instance_map( + std::map>>& id_instance_map) const { + for (size_t location_x = 0; location_x < sb_unique_module_id_.size(); + ++location_x) { + for (size_t location_y = 0; location_y < sb_unique_module_id_[0].size(); + ++location_y) { + auto unique_module_id = sb_unique_module_id_[location_x][location_y]; + vtr::Point instance_coord(location_x, location_y); + id_instance_map[unique_module_id].push_back(instance_coord); + } + } +} + +void DeviceRRGSB::get_id_unique_cbx_block_map( + std::map>& id_unique_block_map) const { + for (size_t id = 0; id < get_num_cb_unique_module(CHANX); ++id) { + const auto& unique_block_coord = cbx_unique_module_[id]; + auto unique_module_id = + cbx_unique_module_id_[unique_block_coord.x()][unique_block_coord.y()]; + id_unique_block_map[unique_module_id] = unique_block_coord; + } +} + +void DeviceRRGSB::get_id_cbx_instance_map( + std::map>>& id_instance_map) const { + for (size_t location_x = 0; location_x < cbx_unique_module_id_.size(); + ++location_x) { + for (size_t location_y = 0; location_y < cbx_unique_module_id_[0].size(); + ++location_y) { + auto unique_module_id = cbx_unique_module_id_[location_x][location_y]; + vtr::Point instance_coord(location_x, location_y); + id_instance_map[unique_module_id].push_back(instance_coord); + } + } +} + +void DeviceRRGSB::get_id_unique_cby_block_map( + std::map>& id_unique_block_map) const { + for (size_t id = 0; id < get_num_cb_unique_module(CHANY); ++id) { + const auto& unique_block_coord = cby_unique_module_[id]; + auto unique_module_id = + cby_unique_module_id_[unique_block_coord.x()][unique_block_coord.y()]; + id_unique_block_map[unique_module_id] = unique_block_coord; + } +} + +void DeviceRRGSB::get_id_cby_instance_map( + std::map>>& id_instance_map) const { + for (size_t location_x = 0; location_x < cby_unique_module_id_.size(); + ++location_x) { + for (size_t location_y = 0; location_y < cby_unique_module_id_[0].size(); + ++location_y) { + auto unique_module_id = cby_unique_module_id_[location_x][location_y]; + vtr::Point instance_coord(location_x, location_y); + id_instance_map[unique_module_id].push_back(instance_coord); + } + } +} + } /* End namespace openfpga*/ diff --git a/openfpga/src/annotation/device_rr_gsb.h b/openfpga/src/annotation/device_rr_gsb.h index b278985c6..f9a151f05 100644 --- a/openfpga/src/annotation/device_rr_gsb.h +++ b/openfpga/src/annotation/device_rr_gsb.h @@ -68,11 +68,14 @@ class DeviceRRGSB { size_t get_cb_unique_module_index(const t_rr_type& cb_type, const vtr::Point& coordinate) const; - public: /* Mutators */ + public: /* Mutators */ + void build_gsb_unique_module(); /* Add a switch block to the array, which will + automatically identify and update the lists + of unique mirrors and rotatable mirrors */ void reserve( const vtr::Point& coordinate); /* Pre-allocate the rr_switch_block array that the device requires */ - void reserve_sb_unique_submodule_id( + void reserve_unique_modules( const vtr::Point& coordinate); /* Pre-allocate the rr_sb_unique_module_id matrix that the device requires */ @@ -95,8 +98,31 @@ class DeviceRRGSB { 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 preload_unique_cbx_module( + const vtr::Point block_coordinate, + const std::vector> instance_coords); + void preload_unique_cby_module( + const vtr::Point block_coordinate, + const std::vector> instance_coords); + void preload_unique_sb_module( + const vtr::Point block_coordinate, + const std::vector> instance_coords); + void clear_unique_modules(); + void get_id_sb_instance_map( + std::map>>& id_instance_map) const; + void get_id_unique_sb_block_map( + std::map>& id_unique_block_map) const; + void get_id_cbx_instance_map( + std::map>>& id_instance_map) const; + void get_id_unique_cbx_block_map( + std::map>& id_unique_block_map) const; + void get_id_cby_instance_map( + std::map>>& id_instance_map) const; + void get_id_unique_cby_block_map( + std::map>& id_unique_block_map) const; + + private: /* Internal cleaners */ + void clear_gsb(); /* clean the content */ void clear_cb_unique_module(const t_rr_type& cb_type); /* clean the content */ void clear_cb_unique_module_id( const t_rr_type& cb_type); /* clean the content */ @@ -133,10 +159,8 @@ class DeviceRRGSB { const t_rr_type& cb_type); /* Add a switch block to the array, which will automatically identify and update the lists of unique side module */ - void build_gsb_unique_module(); /* Add a switch block to the array, which will - automatically identify and update the lists - of unique mirrors and rotatable mirrors */ - private: /* Internal Data */ + + private: /* Internal Data */ std::vector> rr_gsb_; std::vector> diff --git a/openfpga/src/base/openfpga_build_fabric_template.h b/openfpga/src/base/openfpga_build_fabric_template.h index b36903a22..357b70288 100644 --- a/openfpga/src/base/openfpga_build_fabric_template.h +++ b/openfpga/src/base/openfpga_build_fabric_template.h @@ -20,6 +20,7 @@ #include "read_xml_io_name_map.h" #include "read_xml_module_name_map.h" #include "read_xml_tile_config.h" +#include "read_write_xml_unique_blocks.h" #include "rename_modules.h" #include "vtr_log.h" #include "vtr_time.h" @@ -100,6 +101,7 @@ int build_fabric_template(T& openfpga_ctx, const Command& cmd, const CommandContext& cmd_context) { CommandOptionId opt_frame_view = cmd.option("frame_view"); CommandOptionId opt_compress_routing = cmd.option("compress_routing"); + CommandOptionId opt_preload = cmd.option("preload_unique_blocks"); CommandOptionId opt_duplicate_grid_pin = cmd.option("duplicate_grid_pin"); CommandOptionId opt_gen_random_fabric_key = cmd.option("generate_random_fabric_key"); @@ -142,11 +144,15 @@ int build_fabric_template(T& openfpga_ctx, const Command& cmd, } } - if (true == cmd_context.option_enable(cmd, opt_compress_routing)) { + if (true == cmd_context.option_enable(cmd, opt_compress_routing) && + false == cmd_context.option_enable(cmd, opt_preload)) { compress_routing_hierarchy_template( openfpga_ctx, cmd_context.option_enable(cmd, opt_verbose)); /* Update flow manager to enable compress routing */ openfpga_ctx.mutable_flow_manager().set_compress_routing(true); + } else if (true == cmd_context.option_enable(cmd, opt_compress_routing) && + true == cmd_context.option_enable(cmd, opt_preload)){ + openfpga_ctx.mutable_flow_manager().set_compress_routing(true); } VTR_LOG("\n"); @@ -472,6 +478,54 @@ int write_fabric_pin_physical_location_template( cmd_context.option_enable(cmd, opt_verbose)); } +template +int read_unique_blocks_template(T& openfpga_ctx, const Command& cmd, + const CommandContext& cmd_context) { + CommandOptionId opt_verbose = cmd.option("verbose"); + CommandOptionId opt_file = cmd.option("file"); + CommandOptionId opt_type = cmd.option("type"); + + /* Check the option '--file' is enabled or not + * Actually, it must be enabled as the shell interface will check + * before reaching this fuction + */ + VTR_ASSERT(true == cmd_context.option_enable(cmd, opt_file)); + VTR_ASSERT(false == cmd_context.option_value(cmd, opt_file).empty()); + + std::string file_name = cmd_context.option_value(cmd, opt_file); + std::string file_type = cmd_context.option_value(cmd, opt_type); + /* Write hierarchy to a file */ + if (file_type == "xml") { + return read_xml_unique_blocks(openfpga_ctx, file_name.c_str(), + file_type.c_str(), + cmd_context.option_enable(cmd, opt_verbose)); + } else { + VTR_LOG_ERROR("file type %s not supported", file_type); + } +} + +template +int write_unique_blocks_template(T& openfpga_ctx, const Command& cmd, + const CommandContext& cmd_context) { + CommandOptionId opt_verbose = cmd.option("verbose"); + CommandOptionId opt_file = cmd.option("file"); + CommandOptionId opt_type = cmd.option("type"); + + /* Check the option '--file' is enabled or not + * Actually, it must be enabled as the shell interface will check + * before reaching this fuction + */ + VTR_ASSERT(true == cmd_context.option_enable(cmd, opt_file)); + VTR_ASSERT(false == cmd_context.option_value(cmd, opt_file).empty()); + + std::string file_name = cmd_context.option_value(cmd, opt_file); + std::string file_type = cmd_context.option_value(cmd, opt_type); + + /* Write hierarchy to a file */ + return write_xml_unique_blocks(openfpga_ctx, file_name.c_str(), + file_type.c_str(), + cmd_context.option_enable(cmd, opt_verbose)); +} } /* end namespace openfpga */ #endif diff --git a/openfpga/src/base/openfpga_setup_command_template.h b/openfpga/src/base/openfpga_setup_command_template.h index 53e43f00f..fe5662000 100644 --- a/openfpga/src/base/openfpga_setup_command_template.h +++ b/openfpga/src/base/openfpga_setup_command_template.h @@ -391,6 +391,10 @@ ShellCommandId add_build_fabric_command_template( "Compress the number of unique routing modules by " "identifying the unique GSBs"); + /* Add an option '--preload_unique_blocks' */ + shell_cmd.add_option("preload_unique_blocks", false, + "preload unique routing modules from user input xml file"); + /* Add an option '--duplicate_grid_pin' */ shell_cmd.add_option("duplicate_grid_pin", false, "Duplicate the pins on the same side of a grid"); @@ -930,6 +934,80 @@ ShellCommandId add_write_fabric_pin_physical_location_command_template( return shell_cmd_id; } +/******************************************************************** + * - Add a command to Shell environment: read_unique_blocks + * - Add associated options + * - Add command dependency + *******************************************************************/ +template +ShellCommandId add_read_unique_blocks_command_template( + openfpga::Shell& shell, const ShellCommandClassId& cmd_class_id, + const std::vector& dependent_cmds, const bool& hidden) { + Command shell_cmd("read_unique_blocks"); + + /* Add an option '--file' */ + CommandOptionId opt_file = + shell_cmd.add_option("file", true, "specify the unique blocks xml file"); + shell_cmd.set_option_require_value(opt_file, openfpga::OPT_STRING); + + /* Add an option '--type' */ + CommandOptionId opt_type = shell_cmd.add_option( + "type", true, "specify the type of the unique blocks xml file"); + shell_cmd.set_option_require_value(opt_type, openfpga::OPT_STRING); + + /* Add an option '--verbose' */ + shell_cmd.add_option("verbose", false, "Show verbose outputs"); + + /* Add command 'compact_routing_hierarchy' to the Shell */ + ShellCommandId shell_cmd_id = + shell.add_command(shell_cmd, "Preload unique blocks from xml file", hidden); + shell.set_command_class(shell_cmd_id, cmd_class_id); + shell.set_command_execute_function(shell_cmd_id, + read_unique_blocks_template); + + /* Add command dependency to the Shell */ + shell.set_command_dependency(shell_cmd_id, dependent_cmds); + + return shell_cmd_id; +} + +/******************************************************************** + * - Add a command to Shell environment: write_unique_blocks + * - Add associated options + * - Add command dependency + *******************************************************************/ +template +ShellCommandId add_write_unique_blocks_command_template( + openfpga::Shell& shell, const ShellCommandClassId& cmd_class_id, + const std::vector& dependent_cmds, const bool& hidden) { + Command shell_cmd("write_unique_blocks"); + + /* Add an option '--file' */ + CommandOptionId opt_file = + shell_cmd.add_option("file", true, "specify the unique blocks xml file"); + shell_cmd.set_option_require_value(opt_file, openfpga::OPT_STRING); + + /* Add an option '--type' */ + CommandOptionId opt_type = shell_cmd.add_option( + "type", true, "specify the type of the unique blocks xml file"); + shell_cmd.set_option_require_value(opt_type, openfpga::OPT_STRING); + + /* Add an option '--verbose' */ + shell_cmd.add_option("verbose", false, "Show verbose outputs"); + + /* Add command 'compact_routing_hierarchy' to the Shell */ + ShellCommandId shell_cmd_id = + shell.add_command(shell_cmd, "Preload unique blocks from xml file", hidden); + shell.set_command_class(shell_cmd_id, cmd_class_id); + shell.set_command_execute_function(shell_cmd_id, + write_unique_blocks_template); + + /* Add command dependency to the Shell */ + shell.set_command_dependency(shell_cmd_id, dependent_cmds); + + return shell_cmd_id; +} + template void add_setup_command_templates(openfpga::Shell& shell, const bool& hidden = false) { @@ -1181,8 +1259,21 @@ void add_setup_command_templates(openfpga::Shell& shell, add_write_fabric_pin_physical_location_command_template( shell, openfpga_setup_cmd_class, cmd_dependency_write_fabric_pin_physical_location, hidden); -} + /******************************** + * Command 'read_unique_blocks' + */ + add_read_unique_blocks_command_template( + shell, openfpga_setup_cmd_class, std::vector(), + hidden); + + /******************************** + * Command 'write_unique_blocks' + */ + add_write_unique_blocks_command_template( + shell, openfpga_setup_cmd_class, std::vector(), + hidden); +} } /* end namespace openfpga */ #endif diff --git a/openfpga/src/fabric/read_write_xml_unique_blocks.h b/openfpga/src/fabric/read_write_xml_unique_blocks.h new file mode 100644 index 000000000..e3ab6cb90 --- /dev/null +++ b/openfpga/src/fabric/read_write_xml_unique_blocks.h @@ -0,0 +1,300 @@ +#ifndef READ_WRITE_XML_UNIQUE_BLOCKS_H +#define READ_WRITE_XML_UNIQUE_BLOCKS_H + +/******************************************************************** + * This file includes the top-level function of this library + * which reads an XML of unique routing blocks to the associated + * data structures device_rr_gsb + *******************************************************************/ + +#include + +/* Headers from pugi XML library */ +#include "pugixml.hpp" +#include "pugixml_util.hpp" + +/* Headers from vtr util library */ +#include "vtr_assert.h" +#include "vtr_log.h" +#include "vtr_time.h" + +/* Headers from libopenfpga util library */ +#include "openfpga_port_parser.h" + +/* Headers from libarchfpga */ +#include "arch_error.h" +#include "device_rr_gsb_utils.h" +#include "openfpga_digest.h" +#include "read_write_xml_unique_blocks.h" +#include "read_xml_util.h" +#include "rr_gsb.h" +#include "write_xml_utils.h" + +/******************************************************************** + * Parse XML codes of a to an object of device_rr_gsb + * instance is the mirror module of unique module. + *******************************************************************/ +vtr::Point read_xml_unique_instance_info( + pugi::xml_node& xml_instance_info, const pugiutil::loc_data& loc_data) { + int instance_x = get_attribute(xml_instance_info, "x", loc_data).as_int(); + int instance_y = get_attribute(xml_instance_info, "y", loc_data).as_int(); + vtr::Point instance_coordinate(instance_x, instance_y); + return instance_coordinate; +} + +template +void report_unique_module_status_read(T& openfpga_ctx, bool verbose_output) { + /* Report the stats */ + VTR_LOGV( + verbose_output, + "Read %lu unique X-direction connection blocks ", + openfpga_ctx.device_rr_gsb().get_num_cb_unique_module(CHANX)); + + VTR_LOGV( + verbose_output, + "Read %lu unique Y-direction connection blocks from a total of %d " + "(compression rate=%.2f%)\n", + openfpga_ctx.device_rr_gsb().get_num_cb_unique_module(CHANY), + find_device_rr_gsb_num_cb_modules(openfpga_ctx.device_rr_gsb(), CHANY), + 100. * + ((float)find_device_rr_gsb_num_cb_modules(openfpga_ctx.device_rr_gsb(), + CHANY) / + (float)openfpga_ctx.device_rr_gsb().get_num_cb_unique_module(CHANY) - + 1.)); + + VTR_LOGV( + verbose_output, + "Read %lu unique switch blocks from a total of %d (compression " + "rate=%.2f%)\n", + openfpga_ctx.device_rr_gsb().get_num_sb_unique_module(), + find_device_rr_gsb_num_sb_modules(openfpga_ctx.device_rr_gsb(), + g_vpr_ctx.device().rr_graph), + 100. * ((float)find_device_rr_gsb_num_sb_modules( + openfpga_ctx.device_rr_gsb(), g_vpr_ctx.device().rr_graph) / + (float)openfpga_ctx.device_rr_gsb().get_num_sb_unique_module() - + 1.)); + + VTR_LOG( + "Read %lu unique general switch blocks from a total of %d " + "(compression " + "rate=%.2f%)\n", + openfpga_ctx.device_rr_gsb().get_num_gsb_unique_module(), + find_device_rr_gsb_num_gsb_modules(openfpga_ctx.device_rr_gsb(), + g_vpr_ctx.device().rr_graph), + 100. * ((float)find_device_rr_gsb_num_gsb_modules( + openfpga_ctx.device_rr_gsb(), g_vpr_ctx.device().rr_graph) / + (float)openfpga_ctx.device_rr_gsb().get_num_gsb_unique_module() - + 1.)); +} + + +template +void report_unique_module_status_write(T& openfpga_ctx, bool verbose_output) { + /* Report the stats */ + VTR_LOGV( + verbose_output, + "Write %lu unique X-direction connection blocks from a total of %d " + "(compression rate=%.2f%)\n", + openfpga_ctx.device_rr_gsb().get_num_cb_unique_module(CHANX), + find_device_rr_gsb_num_cb_modules(openfpga_ctx.device_rr_gsb(), CHANX), + 100. * + ((float)find_device_rr_gsb_num_cb_modules(openfpga_ctx.device_rr_gsb(), + CHANX) / + (float)openfpga_ctx.device_rr_gsb().get_num_cb_unique_module(CHANX) - + 1.)); + + VTR_LOGV( + verbose_output, + "Write %lu unique Y-direction connection blocks from a total of %d " + "(compression rate=%.2f%)\n", + openfpga_ctx.device_rr_gsb().get_num_cb_unique_module(CHANY), + find_device_rr_gsb_num_cb_modules(openfpga_ctx.device_rr_gsb(), CHANY), + 100. * + ((float)find_device_rr_gsb_num_cb_modules(openfpga_ctx.device_rr_gsb(), + CHANY) / + (float)openfpga_ctx.device_rr_gsb().get_num_cb_unique_module(CHANY) - + 1.)); + + VTR_LOGV( + verbose_output, + "Write %lu unique switch blocks from a total of %d (compression " + "rate=%.2f%)\n", + openfpga_ctx.device_rr_gsb().get_num_sb_unique_module(), + find_device_rr_gsb_num_sb_modules(openfpga_ctx.device_rr_gsb(), + g_vpr_ctx.device().rr_graph), + 100. * ((float)find_device_rr_gsb_num_sb_modules( + openfpga_ctx.device_rr_gsb(), g_vpr_ctx.device().rr_graph) / + (float)openfpga_ctx.device_rr_gsb().get_num_sb_unique_module() - + 1.)); + + VTR_LOG( + "Write %lu unique general switch blocks from a total of %d " + "(compression " + "rate=%.2f%)\n", + openfpga_ctx.device_rr_gsb().get_num_gsb_unique_module(), + find_device_rr_gsb_num_gsb_modules(openfpga_ctx.device_rr_gsb(), + g_vpr_ctx.device().rr_graph), + 100. * ((float)find_device_rr_gsb_num_gsb_modules( + openfpga_ctx.device_rr_gsb(), g_vpr_ctx.device().rr_graph) / + (float)openfpga_ctx.device_rr_gsb().get_num_gsb_unique_module() - + 1.)); +} +/******************************************************************** + * Parse XML codes about to an object of device_rr_gsb + *******************************************************************/ +template +int read_xml_unique_blocks(T& openfpga_ctx, const char* file_name, + const char* file_type, bool verbose_output) { + vtr::ScopedStartFinishTimer timer("Read unique blocks xml file"); + /* Parse the file */ + pugi::xml_document doc; + pugiutil::loc_data loc_data; + VTR_ASSERT(strcmp(file_type, "xml") == 0); + try { + loc_data = pugiutil::load_xml(doc, file_name); + + pugi::xml_node xml_root = get_single_child(doc, "unique_blocks", loc_data); + + /* get device_rr_gsb data type and initialize it*/ + openfpga::DeviceRRGSB& device_rr_gsb = openfpga_ctx.mutable_device_rr_gsb(); + /* clear unique modules */ + device_rr_gsb.clear_unique_modules(); + vtr::Point grid_coord(g_vpr_ctx.device().grid.width() - 1, + g_vpr_ctx.device().grid.height() - 1); + device_rr_gsb.reserve_unique_modules(grid_coord); + /* load unique blocks xml file and set up device_rr_gdb */ + for (pugi::xml_node xml_block_info : xml_root.children()) { + /* Error out if the XML child has an invalid name! */ + if (xml_block_info.name() == std::string("block")) { + std::string type = + get_attribute(xml_block_info, "type", loc_data).as_string(); + int block_x = get_attribute(xml_block_info, "x", loc_data).as_int(); + int block_y = get_attribute(xml_block_info, "y", loc_data).as_int(); + vtr::Point block_coordinate(block_x, block_y); + std::vector> instance_coords; + for (pugi::xml_node xml_instance_info : xml_block_info.children()) { + if (xml_instance_info.name() == std::string("instance")) { + auto instance_coordinate = + read_xml_unique_instance_info(xml_instance_info, loc_data); + instance_coords.push_back(instance_coordinate); + } + } + /* get block coordinate and instance coordinate, try to setup device rr + * gsb */ + if (type == "sb") { + device_rr_gsb.preload_unique_sb_module(block_coordinate, + instance_coords); + } else if (type == "cby") { + device_rr_gsb.preload_unique_cby_module(block_coordinate, + instance_coords); + } else if (type == "cbx") { + device_rr_gsb.preload_unique_cbx_module(block_coordinate, + instance_coords); + } else { + VTR_LOG_ERROR("Unexpected type!"); + } + } else { + bad_tag(xml_block_info, loc_data, xml_root, {"block"}); + return 1; + } + } + device_rr_gsb.build_gsb_unique_module(); + if (verbose_output) { + report_unique_module_status_read(openfpga_ctx, true); + } + } catch (pugiutil::XmlError& e) { + archfpga_throw(file_name, e.line(), "%s", e.what()); + } + + return 0; +} + +int write_xml_block( + std::map>& id_unique_block_map, + std::map>>& id_instance_map, + std::fstream& fp, std::string type) { + /* Validate the file stream */ + if (false == openfpga::valid_file_stream(fp)) { + return 2; + } + for (const auto& pair : id_unique_block_map) { + openfpga::write_tab_to_file(fp, 1); + fp << "" + << "\n"; + + for (const auto& instance_info : id_instance_map[pair.first]) { + if (instance_info.x() == pair.second.x() && + instance_info.y() == pair.second.y()) { + ; + }else{ + openfpga::write_tab_to_file(fp, 2); + fp << "" + << "\n"; + } + } + openfpga::write_tab_to_file(fp, 1); + fp << "" + << "\n"; + } + + return 0; +} + +template +int write_xml_unique_blocks(const T& openfpga_ctx, const char* fname, + const char* file_type, bool verbose_output) { + vtr::ScopedStartFinishTimer timer("Write unique blocks..."); + VTR_ASSERT(strcmp(file_type, "xml") == 0); + /* Create a file handler */ + std::fstream fp; + /* Open the file stream */ + fp.open(std::string(fname), std::fstream::out | std::fstream::trunc); + + /* Validate the file stream */ + openfpga::check_file_stream(fname, fp); + + /* Write the root node */ + fp << "" + << "\n"; + + int err_code = 0; + std::map> id_unique_block_map; + std::map>> id_instance_map; + openfpga_ctx.device_rr_gsb().get_id_unique_sb_block_map(id_unique_block_map); + openfpga_ctx.device_rr_gsb().get_id_sb_instance_map(id_instance_map); + err_code += write_xml_block(id_unique_block_map, id_instance_map, fp, "sb"); + + id_unique_block_map.clear(); + id_instance_map.clear(); + openfpga_ctx.device_rr_gsb().get_id_unique_cbx_block_map(id_unique_block_map); + openfpga_ctx.device_rr_gsb().get_id_cbx_instance_map(id_instance_map); + err_code += write_xml_block(id_unique_block_map, id_instance_map, fp, "cbx"); + + id_unique_block_map.clear(); + id_instance_map.clear(); + openfpga_ctx.device_rr_gsb().get_id_unique_cby_block_map(id_unique_block_map); + openfpga_ctx.device_rr_gsb().get_id_cby_instance_map(id_instance_map); + err_code += write_xml_block(id_unique_block_map, id_instance_map, fp, "cby"); + + /* Finish writing the root node */ + fp << "" + << "\n"; + + /* Close the file stream */ + fp.close(); + if (verbose_output) { + report_unique_module_status_write(openfpga_ctx, true); + } + return err_code; +} + +#endif