Merge branch 'preloading' of github.com:lnis-uofu/OpenFPGA
This commit is contained in:
commit
9c061e0ab5
|
@ -1,8 +1,12 @@
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
* Member functions for class DeviceRRGSB
|
* Member functions for class DeviceRRGSB
|
||||||
***********************************************************************/
|
***********************************************************************/
|
||||||
|
|
||||||
#include "device_rr_gsb.h"
|
#include "device_rr_gsb.h"
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
#include "rr_gsb_utils.h"
|
#include "rr_gsb_utils.h"
|
||||||
#include "vtr_assert.h"
|
#include "vtr_assert.h"
|
||||||
#include "vtr_log.h"
|
#include "vtr_log.h"
|
||||||
|
@ -171,6 +175,18 @@ void DeviceRRGSB::reserve(const vtr::Point<size_t>& coordinate) {
|
||||||
cby_unique_module_id_[x].resize(coordinate.y());
|
cby_unique_module_id_[x].resize(coordinate.y());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
void DeviceRRGSB::reserve_unique_modules(const vtr::Point<size_t>& 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*/
|
/* Resize rr_switch_block array is needed*/
|
||||||
void DeviceRRGSB::resize_upon_need(const vtr::Point<size_t>& coordinate) {
|
void DeviceRRGSB::resize_upon_need(const vtr::Point<size_t>& coordinate) {
|
||||||
|
@ -410,6 +426,18 @@ void DeviceRRGSB::clear() {
|
||||||
clear_sb_unique_module_id();
|
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() {
|
void DeviceRRGSB::clear_gsb() {
|
||||||
/* clean gsb array */
|
/* clean gsb array */
|
||||||
for (size_t x = 0; x < rr_gsb_.size(); ++x) {
|
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;
|
return cb_unique_module_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DeviceRRGSB::preload_unique_cbx_module(
|
||||||
|
const vtr::Point<size_t> block_coordinate,
|
||||||
|
const std::vector<vtr::Point<size_t>> 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<size_t> block_coordinate,
|
||||||
|
const std::vector<vtr::Point<size_t>> 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<size_t> block_coordinate,
|
||||||
|
const std::vector<vtr::Point<size_t>> 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<int, vtr::Point<size_t>>& 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<int, std::vector<vtr::Point<size_t>>>& 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<size_t> 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<int, vtr::Point<size_t>>& 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<int, std::vector<vtr::Point<size_t>>>& 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<size_t> 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<int, vtr::Point<size_t>>& 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<int, std::vector<vtr::Point<size_t>>>& 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<size_t> instance_coord(location_x, location_y);
|
||||||
|
id_instance_map[unique_module_id].push_back(instance_coord);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} /* End namespace openfpga*/
|
} /* End namespace openfpga*/
|
||||||
|
|
|
@ -69,10 +69,13 @@ class DeviceRRGSB {
|
||||||
const vtr::Point<size_t>& coordinate) const;
|
const vtr::Point<size_t>& 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(
|
void reserve(
|
||||||
const vtr::Point<size_t>& coordinate); /* Pre-allocate the rr_switch_block
|
const vtr::Point<size_t>& coordinate); /* Pre-allocate the rr_switch_block
|
||||||
array that the device requires */
|
array that the device requires */
|
||||||
void reserve_sb_unique_submodule_id(
|
void reserve_unique_modules(
|
||||||
const vtr::Point<size_t>&
|
const vtr::Point<size_t>&
|
||||||
coordinate); /* Pre-allocate the rr_sb_unique_module_id matrix that the
|
coordinate); /* Pre-allocate the rr_sb_unique_module_id matrix that the
|
||||||
device requires */
|
device requires */
|
||||||
|
@ -95,6 +98,29 @@ class DeviceRRGSB {
|
||||||
automatically identify and update the lists
|
automatically identify and update the lists
|
||||||
of unique mirrors and rotatable mirrors */
|
of unique mirrors and rotatable mirrors */
|
||||||
void clear(); /* clean the content */
|
void clear(); /* clean the content */
|
||||||
|
void preload_unique_cbx_module(
|
||||||
|
const vtr::Point<size_t> block_coordinate,
|
||||||
|
const std::vector<vtr::Point<size_t>> instance_coords);
|
||||||
|
void preload_unique_cby_module(
|
||||||
|
const vtr::Point<size_t> block_coordinate,
|
||||||
|
const std::vector<vtr::Point<size_t>> instance_coords);
|
||||||
|
void preload_unique_sb_module(
|
||||||
|
const vtr::Point<size_t> block_coordinate,
|
||||||
|
const std::vector<vtr::Point<size_t>> instance_coords);
|
||||||
|
void clear_unique_modules();
|
||||||
|
void get_id_sb_instance_map(
|
||||||
|
std::map<int, std::vector<vtr::Point<size_t>>>& id_instance_map) const;
|
||||||
|
void get_id_unique_sb_block_map(
|
||||||
|
std::map<int, vtr::Point<size_t>>& id_unique_block_map) const;
|
||||||
|
void get_id_cbx_instance_map(
|
||||||
|
std::map<int, std::vector<vtr::Point<size_t>>>& id_instance_map) const;
|
||||||
|
void get_id_unique_cbx_block_map(
|
||||||
|
std::map<int, vtr::Point<size_t>>& id_unique_block_map) const;
|
||||||
|
void get_id_cby_instance_map(
|
||||||
|
std::map<int, std::vector<vtr::Point<size_t>>>& id_instance_map) const;
|
||||||
|
void get_id_unique_cby_block_map(
|
||||||
|
std::map<int, vtr::Point<size_t>>& id_unique_block_map) const;
|
||||||
|
|
||||||
private: /* Internal cleaners */
|
private: /* Internal cleaners */
|
||||||
void clear_gsb(); /* clean the content */
|
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(const t_rr_type& cb_type); /* clean the content */
|
||||||
|
@ -133,9 +159,7 @@ class DeviceRRGSB {
|
||||||
const t_rr_type&
|
const t_rr_type&
|
||||||
cb_type); /* Add a switch block to the array, which will automatically
|
cb_type); /* Add a switch block to the array, which will automatically
|
||||||
identify and update the lists of unique side module */
|
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<std::vector<RRGSB>> rr_gsb_;
|
std::vector<std::vector<RRGSB>> rr_gsb_;
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "read_xml_io_name_map.h"
|
#include "read_xml_io_name_map.h"
|
||||||
#include "read_xml_module_name_map.h"
|
#include "read_xml_module_name_map.h"
|
||||||
#include "read_xml_tile_config.h"
|
#include "read_xml_tile_config.h"
|
||||||
|
#include "read_write_xml_unique_blocks.h"
|
||||||
#include "rename_modules.h"
|
#include "rename_modules.h"
|
||||||
#include "vtr_log.h"
|
#include "vtr_log.h"
|
||||||
#include "vtr_time.h"
|
#include "vtr_time.h"
|
||||||
|
@ -100,6 +101,7 @@ int build_fabric_template(T& openfpga_ctx, const Command& cmd,
|
||||||
const CommandContext& cmd_context) {
|
const CommandContext& cmd_context) {
|
||||||
CommandOptionId opt_frame_view = cmd.option("frame_view");
|
CommandOptionId opt_frame_view = cmd.option("frame_view");
|
||||||
CommandOptionId opt_compress_routing = cmd.option("compress_routing");
|
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_duplicate_grid_pin = cmd.option("duplicate_grid_pin");
|
||||||
CommandOptionId opt_gen_random_fabric_key =
|
CommandOptionId opt_gen_random_fabric_key =
|
||||||
cmd.option("generate_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<T>(
|
compress_routing_hierarchy_template<T>(
|
||||||
openfpga_ctx, cmd_context.option_enable(cmd, opt_verbose));
|
openfpga_ctx, cmd_context.option_enable(cmd, opt_verbose));
|
||||||
/* Update flow manager to enable compress routing */
|
/* Update flow manager to enable compress routing */
|
||||||
openfpga_ctx.mutable_flow_manager().set_compress_routing(true);
|
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");
|
VTR_LOG("\n");
|
||||||
|
@ -472,6 +478,54 @@ int write_fabric_pin_physical_location_template(
|
||||||
cmd_context.option_enable(cmd, opt_verbose));
|
cmd_context.option_enable(cmd, opt_verbose));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
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 <class T>
|
||||||
|
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 */
|
} /* end namespace openfpga */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -391,6 +391,10 @@ ShellCommandId add_build_fabric_command_template(
|
||||||
"Compress the number of unique routing modules by "
|
"Compress the number of unique routing modules by "
|
||||||
"identifying the unique GSBs");
|
"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' */
|
/* Add an option '--duplicate_grid_pin' */
|
||||||
shell_cmd.add_option("duplicate_grid_pin", false,
|
shell_cmd.add_option("duplicate_grid_pin", false,
|
||||||
"Duplicate the pins on the same side of a grid");
|
"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;
|
return shell_cmd_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* - Add a command to Shell environment: read_unique_blocks
|
||||||
|
* - Add associated options
|
||||||
|
* - Add command dependency
|
||||||
|
*******************************************************************/
|
||||||
|
template <class T>
|
||||||
|
ShellCommandId add_read_unique_blocks_command_template(
|
||||||
|
openfpga::Shell<T>& shell, const ShellCommandClassId& cmd_class_id,
|
||||||
|
const std::vector<ShellCommandId>& 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<T>);
|
||||||
|
|
||||||
|
/* 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 <class T>
|
||||||
|
ShellCommandId add_write_unique_blocks_command_template(
|
||||||
|
openfpga::Shell<T>& shell, const ShellCommandClassId& cmd_class_id,
|
||||||
|
const std::vector<ShellCommandId>& 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<T>);
|
||||||
|
|
||||||
|
/* Add command dependency to the Shell */
|
||||||
|
shell.set_command_dependency(shell_cmd_id, dependent_cmds);
|
||||||
|
|
||||||
|
return shell_cmd_id;
|
||||||
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
void add_setup_command_templates(openfpga::Shell<T>& shell,
|
void add_setup_command_templates(openfpga::Shell<T>& shell,
|
||||||
const bool& hidden = false) {
|
const bool& hidden = false) {
|
||||||
|
@ -1181,8 +1259,21 @@ void add_setup_command_templates(openfpga::Shell<T>& shell,
|
||||||
add_write_fabric_pin_physical_location_command_template<T>(
|
add_write_fabric_pin_physical_location_command_template<T>(
|
||||||
shell, openfpga_setup_cmd_class,
|
shell, openfpga_setup_cmd_class,
|
||||||
cmd_dependency_write_fabric_pin_physical_location, hidden);
|
cmd_dependency_write_fabric_pin_physical_location, hidden);
|
||||||
}
|
|
||||||
|
|
||||||
|
/********************************
|
||||||
|
* Command 'read_unique_blocks'
|
||||||
|
*/
|
||||||
|
add_read_unique_blocks_command_template<T>(
|
||||||
|
shell, openfpga_setup_cmd_class, std::vector<openfpga::ShellCommandId>(),
|
||||||
|
hidden);
|
||||||
|
|
||||||
|
/********************************
|
||||||
|
* Command 'write_unique_blocks'
|
||||||
|
*/
|
||||||
|
add_write_unique_blocks_command_template<T>(
|
||||||
|
shell, openfpga_setup_cmd_class, std::vector<openfpga::ShellCommandId>(),
|
||||||
|
hidden);
|
||||||
|
}
|
||||||
} /* end namespace openfpga */
|
} /* end namespace openfpga */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -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 <string>
|
||||||
|
|
||||||
|
/* 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 <instance> to an object of device_rr_gsb
|
||||||
|
* instance is the mirror module of unique module.
|
||||||
|
*******************************************************************/
|
||||||
|
vtr::Point<size_t> 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<size_t> instance_coordinate(instance_x, instance_y);
|
||||||
|
return instance_coordinate;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
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 <class T>
|
||||||
|
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 <unique_blocks> to an object of device_rr_gsb
|
||||||
|
*******************************************************************/
|
||||||
|
template <class T>
|
||||||
|
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<size_t> 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<size_t> block_coordinate(block_x, block_y);
|
||||||
|
std::vector<vtr::Point<size_t>> 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<int, vtr::Point<size_t>>& id_unique_block_map,
|
||||||
|
std::map<int, std::vector<vtr::Point<size_t>>>& 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 << "<block";
|
||||||
|
write_xml_attribute(fp, "type", type.c_str());
|
||||||
|
write_xml_attribute(fp, "x", pair.second.x());
|
||||||
|
write_xml_attribute(fp, "y", pair.second.y());
|
||||||
|
|
||||||
|
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 << "<instance";
|
||||||
|
write_xml_attribute(fp, "x", instance_info.x());
|
||||||
|
write_xml_attribute(fp, "y", instance_info.y());
|
||||||
|
|
||||||
|
fp << "/>"
|
||||||
|
<< "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
openfpga::write_tab_to_file(fp, 1);
|
||||||
|
fp << "</block>"
|
||||||
|
<< "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
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 << "<unique_blocks>"
|
||||||
|
<< "\n";
|
||||||
|
|
||||||
|
int err_code = 0;
|
||||||
|
std::map<int, vtr::Point<size_t>> id_unique_block_map;
|
||||||
|
std::map<int, std::vector<vtr::Point<size_t>>> 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 << "</unique_blocks>"
|
||||||
|
<< "\n";
|
||||||
|
|
||||||
|
/* Close the file stream */
|
||||||
|
fp.close();
|
||||||
|
if (verbose_output) {
|
||||||
|
report_unique_module_status_write(openfpga_ctx, true);
|
||||||
|
}
|
||||||
|
return err_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue