2020-06-12 11:41:34 -05:00
|
|
|
/***************************************************************************************
|
|
|
|
* Output fabric key of Module Graph to file formats
|
|
|
|
***************************************************************************************/
|
|
|
|
/* Headers from vtrutil library */
|
|
|
|
#include "vtr_log.h"
|
|
|
|
#include "vtr_assert.h"
|
|
|
|
#include "vtr_time.h"
|
|
|
|
|
|
|
|
/* Headers from openfpgautil library */
|
|
|
|
#include "openfpga_digest.h"
|
|
|
|
|
|
|
|
/* Headers from archopenfpga library */
|
|
|
|
#include "write_xml_fabric_key.h"
|
|
|
|
|
|
|
|
#include "openfpga_naming.h"
|
|
|
|
|
2021-09-22 13:09:46 -05:00
|
|
|
#include "memory_utils.h"
|
|
|
|
|
2020-06-12 11:41:34 -05:00
|
|
|
#include "fabric_key_writer.h"
|
|
|
|
|
|
|
|
/* begin namespace openfpga */
|
|
|
|
namespace openfpga {
|
|
|
|
|
|
|
|
/***************************************************************************************
|
|
|
|
* Write the fabric key of top module to an XML file
|
|
|
|
* We will use the writer API in libfabrickey
|
|
|
|
*
|
|
|
|
* Return 0 if successful
|
|
|
|
* Return 1 if there are more serious bugs in the architecture
|
|
|
|
* Return 2 if fail when creating files
|
|
|
|
***************************************************************************************/
|
|
|
|
int write_fabric_key_to_xml_file(const ModuleManager& module_manager,
|
|
|
|
const std::string& fname,
|
2021-09-24 17:15:32 -05:00
|
|
|
const ConfigProtocol& config_protocol,
|
2021-10-11 11:40:02 -05:00
|
|
|
const MemoryBankShiftRegisterBanks& blwl_sr_banks,
|
2020-06-12 11:41:34 -05:00
|
|
|
const bool& verbose) {
|
|
|
|
std::string timer_message = std::string("Write fabric key to XML file '") + fname + std::string("'");
|
|
|
|
|
|
|
|
std::string dir_path = format_dir_path(find_path_dir_name(fname));
|
|
|
|
|
|
|
|
/* Create directories */
|
|
|
|
create_directory(dir_path);
|
|
|
|
|
|
|
|
/* Start time count */
|
|
|
|
vtr::ScopedStartFinishTimer timer(timer_message);
|
|
|
|
|
|
|
|
/* Use default name if user does not provide one */
|
|
|
|
VTR_ASSERT(true != fname.empty());
|
|
|
|
|
|
|
|
/* Find top-level module */
|
|
|
|
std::string top_module_name = generate_fpga_top_module_name();
|
|
|
|
ModuleId top_module = module_manager.find_module(top_module_name);
|
|
|
|
if (true != module_manager.valid_module_id(top_module)) {
|
|
|
|
VTR_LOGV_ERROR(verbose,
|
|
|
|
"Unable to find the top-level module '%s'!\n",
|
|
|
|
top_module_name.c_str());
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Build a fabric key database by visiting all the configurable children */
|
|
|
|
FabricKey fabric_key;
|
2020-06-12 11:50:23 -05:00
|
|
|
size_t num_keys = module_manager.configurable_children(top_module).size();
|
2020-07-06 17:42:33 -05:00
|
|
|
|
2020-06-12 11:41:34 -05:00
|
|
|
fabric_key.reserve_keys(num_keys);
|
|
|
|
|
2020-09-28 19:13:07 -05:00
|
|
|
size_t num_regions = module_manager.regions(top_module).size();
|
|
|
|
fabric_key.reserve_regions(num_regions);
|
2020-06-12 11:41:34 -05:00
|
|
|
|
2021-10-10 23:14:14 -05:00
|
|
|
/* Create regions and build a id map */
|
|
|
|
std::map<ConfigRegionId, FabricRegionId> region_id_map;
|
2020-09-28 19:13:07 -05:00
|
|
|
for (const ConfigRegionId& config_region : module_manager.regions(top_module)) {
|
|
|
|
FabricRegionId fabric_region = fabric_key.create_region();
|
2021-10-10 23:14:14 -05:00
|
|
|
region_id_map[config_region] = fabric_region;
|
|
|
|
}
|
2021-09-22 13:09:46 -05:00
|
|
|
|
2021-10-10 23:14:14 -05:00
|
|
|
/* Create regions for the keys and load keys by region */
|
|
|
|
for (const ConfigRegionId& config_region : module_manager.regions(top_module)) {
|
2021-10-11 11:40:02 -05:00
|
|
|
/* Must have a valid one-to-one region mapping */
|
|
|
|
auto result = region_id_map.find(config_region);
|
|
|
|
VTR_ASSERT_SAFE(result != region_id_map.end());
|
|
|
|
FabricRegionId fabric_region = result->second;
|
|
|
|
|
2021-09-22 13:09:46 -05:00
|
|
|
/* Each configuration protocol has some child which should not be in the list. They are typically decoders */
|
|
|
|
size_t curr_region_num_config_child = module_manager.region_configurable_children(top_module, config_region).size();
|
2021-09-24 17:15:32 -05:00
|
|
|
size_t num_child_to_skip = estimate_num_configurable_children_to_skip_by_config_protocol(config_protocol, curr_region_num_config_child);
|
2021-09-22 13:09:46 -05:00
|
|
|
curr_region_num_config_child -= num_child_to_skip;
|
|
|
|
|
|
|
|
fabric_key.reserve_region_keys(fabric_region, curr_region_num_config_child);
|
2020-06-27 15:59:53 -05:00
|
|
|
|
2021-09-22 13:09:46 -05:00
|
|
|
for (size_t ichild = 0; ichild < curr_region_num_config_child; ++ichild) {
|
2020-09-28 19:13:07 -05:00
|
|
|
ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[ichild];
|
|
|
|
size_t child_instance = module_manager.region_configurable_child_instances(top_module, config_region)[ichild];
|
2021-09-21 17:55:11 -05:00
|
|
|
vtr::Point<int> child_coord = module_manager.region_configurable_child_coordinates(top_module, config_region)[ichild];
|
2020-09-28 19:13:07 -05:00
|
|
|
|
|
|
|
FabricKeyId key = fabric_key.create_key();
|
|
|
|
fabric_key.set_key_name(key, module_manager.module_name(child_module));
|
|
|
|
fabric_key.set_key_value(key, child_instance);
|
2020-09-27 21:54:58 -05:00
|
|
|
|
2020-09-28 19:13:07 -05:00
|
|
|
if (false == module_manager.instance_name(top_module, child_module, child_instance).empty()) {
|
|
|
|
fabric_key.set_key_alias(key, module_manager.instance_name(top_module, child_module, child_instance));
|
|
|
|
}
|
|
|
|
|
2021-09-21 17:55:11 -05:00
|
|
|
/* Add key coordinate */
|
|
|
|
fabric_key.set_key_coordinate(key, child_coord);
|
|
|
|
|
2020-09-28 19:13:07 -05:00
|
|
|
/* Add keys to the region */
|
|
|
|
fabric_key.add_key_to_region(fabric_region, key);
|
|
|
|
}
|
2020-06-12 11:41:34 -05:00
|
|
|
}
|
|
|
|
|
2021-10-11 11:40:02 -05:00
|
|
|
/* Skip invalid region, some architecture may not have BL/WL banks */
|
|
|
|
if (0 < blwl_sr_banks.regions().size()) {
|
|
|
|
/* Add BL shift register bank information, if there is any */
|
|
|
|
for (const ConfigRegionId& config_region : module_manager.regions(top_module)) {
|
|
|
|
auto result = region_id_map.find(config_region);
|
|
|
|
/* Must have a valid one-to-one region mapping */
|
|
|
|
VTR_ASSERT_SAFE(result != region_id_map.end());
|
|
|
|
FabricRegionId fabric_region = result->second;
|
|
|
|
for (const FabricBitLineBankId& bank : blwl_sr_banks.bl_banks(config_region)) {
|
|
|
|
FabricBitLineBankId fabric_bank = fabric_key.create_bl_shift_register_bank(fabric_region);
|
|
|
|
for (const BasicPort& data_port : blwl_sr_banks.bl_bank_data_ports(config_region, bank)) {
|
|
|
|
fabric_key.add_data_port_to_bl_shift_register_bank(fabric_region, fabric_bank, data_port);
|
|
|
|
}
|
2021-10-10 23:14:14 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-11 11:40:02 -05:00
|
|
|
/* Add WL shift register bank information, if there is any */
|
|
|
|
for (const ConfigRegionId& config_region : module_manager.regions(top_module)) {
|
|
|
|
auto result = region_id_map.find(config_region);
|
|
|
|
/* Must have a valid one-to-one region mapping */
|
|
|
|
VTR_ASSERT_SAFE(result != region_id_map.end());
|
|
|
|
FabricRegionId fabric_region = result->second;
|
|
|
|
|
|
|
|
for (const FabricWordLineBankId& bank : blwl_sr_banks.wl_banks(config_region)) {
|
|
|
|
FabricWordLineBankId fabric_bank = fabric_key.create_wl_shift_register_bank(fabric_region);
|
|
|
|
for (const BasicPort& data_port : blwl_sr_banks.wl_bank_data_ports(config_region, bank)) {
|
|
|
|
fabric_key.add_data_port_to_wl_shift_register_bank(fabric_region, fabric_bank, data_port);
|
|
|
|
}
|
2021-10-10 23:14:14 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-12 11:41:34 -05:00
|
|
|
VTR_LOGV(verbose,
|
2020-09-28 19:13:07 -05:00
|
|
|
"Created %lu regions and %lu keys for the top module %s.\n",
|
|
|
|
num_regions, num_keys, top_module_name.c_str());
|
2020-06-12 11:41:34 -05:00
|
|
|
|
|
|
|
/* Call the XML writer for fabric key */
|
|
|
|
int err_code = write_xml_fabric_key(fname.c_str(), fabric_key);
|
|
|
|
|
|
|
|
return err_code;
|
|
|
|
}
|
|
|
|
|
|
|
|
} /* end namespace openfpga */
|