diff --git a/openfpga/src/fpga_bitstream/build_fabric_bitstream.cpp b/openfpga/src/fpga_bitstream/build_fabric_bitstream.cpp new file mode 100644 index 000000000..241aee04d --- /dev/null +++ b/openfpga/src/fpga_bitstream/build_fabric_bitstream.cpp @@ -0,0 +1,131 @@ +/******************************************************************** + * This file includes functions to build fabric dependent bitstream + *******************************************************************/ +#include +#include + +/* Headers from vtrutil library */ +#include "vtr_assert.h" +#include "vtr_log.h" +#include "vtr_time.h" + +#include "openfpga_naming.h" + +#include "bitstream_manager_utils.h" +#include "build_fabric_bitstream.h" + +/* begin namespace openfpga */ +namespace openfpga { + +/******************************************************************** + * This function will walk through all the configurable children under a module + * in a recursive way, following a Depth-First Search (DFS) strategy + * For each configuration child, we use its instance name as a key to spot the + * configuration bits in bitstream manager. + * Note that it is guarentee that the instance name in module manager is + * consistent with the block names in bitstream manager + * We use this link to reorganize the bitstream in the sequence of memories as we stored + * in the configurable_children) and configurable_child_instances() of each module of module manager + *******************************************************************/ +static +void rec_build_module_fabric_dependent_bitstream(const BitstreamManager& bitstream_manager, + const ConfigBlockId& parent_block, + const ModuleManager& module_manager, + const ModuleId& parent_module, + std::vector& fabric_bitstream) { + + /* Depth-first search: if we have any children in the parent_block, + * we dive to the next level first! + */ + if (0 < bitstream_manager.block_children(parent_block).size()) { + for (size_t child_id = 0; child_id < module_manager.configurable_children(parent_module).size(); ++child_id) { + ModuleId child_module = module_manager.configurable_children(parent_module)[child_id]; + size_t child_instance = module_manager.configurable_child_instances(parent_module)[child_id]; + /* Get the instance name and ensure it is not empty */ + std::string instance_name = module_manager.instance_name(parent_module, child_module, child_instance); + + /* Find the child block that matches the instance name! */ + ConfigBlockId child_block = bitstream_manager.find_child_block(parent_block, instance_name); + /* We must have one valid block id! */ + if (true != bitstream_manager.valid_block_id(child_block)) + VTR_ASSERT(true == bitstream_manager.valid_block_id(child_block)); + + /* Go recursively */ + rec_build_module_fabric_dependent_bitstream(bitstream_manager, child_block, + module_manager, child_module, + fabric_bitstream); + } + /* Ensure that there should be no configuration bits in the parent block */ + VTR_ASSERT(0 == bitstream_manager.block_bits(parent_block).size()); + } + + /* Note that, reach here, it means that this is a leaf node. + * We add the configuration bits to the fabric_bitstream, + * And then, we can return + */ + for (const ConfigBitId& config_bit : bitstream_manager.block_bits(parent_block)) { + fabric_bitstream.push_back(config_bit); + } +} + +/******************************************************************** + * A top-level function re-organizes the bitstream for a specific + * FPGA fabric, where configuration bits are organized in the sequence + * that can be directly loaded to the FPGA configuration protocol. + * Support: + * 1. Configuration chain + * 2. Memory decoders + * This function does NOT modify the bitstream database + * Instead, it builds a vector of ids for configuration bits in bitstream manager + * + * This function can be called ONLY after the function build_device_bitstream() + * Note that this function does NOT decode bitstreams from circuit implementation + * It was done in the function build_device_bitstream() + *******************************************************************/ +std::vector build_fabric_dependent_bitstream(const BitstreamManager& bitstream_manager, + const ModuleManager& module_manager) { + std::vector fabric_bitstream; + + vtr::ScopedStartFinishTimer timer("\nBuild fabric dependent bitstream\n"); + + /* Get the top module name in module manager, which is our starting point */ + std::string top_module_name = generate_fpga_top_module_name(); + ModuleId top_module = module_manager.find_module(top_module_name); + VTR_ASSERT(true == module_manager.valid_module_id(top_module)); + + /* Find the top block in bitstream manager, which has not parents */ + std::vector top_block = find_bitstream_manager_top_blocks(bitstream_manager); + /* Make sure we have only 1 top block and its name matches the top module */ + VTR_ASSERT(1 == top_block.size()); + VTR_ASSERT(0 == top_module_name.compare(bitstream_manager.block_name(top_block[0]))); + + rec_build_module_fabric_dependent_bitstream(bitstream_manager, top_block[0], + module_manager, top_module, + fabric_bitstream); + + /* Time-consuming sanity check: Uncomment these codes only for debugging!!! + * Check which configuration bits are not touched + */ + /* + for (const ConfigBitId& config_bit : bitstream_manager.bits()) { + std::vector::iterator it = std::find(fabric_bitstream.begin(), fabric_bitstream.end(), config_bit); + if (it == fabric_bitstream.end()) { + std::vector block_hierarchy = find_bitstream_manager_block_hierarchy(bitstream_manager, bitstream_manager.bit_parent_block(config_bit)); + std::string block_hierarchy_name; + for (const ConfigBlockId& temp_block : block_hierarchy) { + block_hierarchy_name += std::string("/") + bitstream_manager.block_name(temp_block); + } + vpr_printf(TIO_MESSAGE_INFO, + "bit (parent_block = %s) is not touched!\n", + block_hierarchy_name.c_str()); + } + } + */ + + /* Ensure our fabric bitstream is in the same size as device bistream */ + VTR_ASSERT(bitstream_manager.bits().size() == fabric_bitstream.size()); + + return fabric_bitstream; +} + +} /* end namespace openfpga */ diff --git a/openfpga/src/fpga_bitstream/build_fabric_bitstream.h b/openfpga/src/fpga_bitstream/build_fabric_bitstream.h new file mode 100644 index 000000000..47d46084c --- /dev/null +++ b/openfpga/src/fpga_bitstream/build_fabric_bitstream.h @@ -0,0 +1,23 @@ +#ifndef BUILD_FABRIC_BITSTREAM_H +#define BUILD_FABRIC_BITSTREAM_H + +/******************************************************************** + * Include header files that are required by function declaration + *******************************************************************/ +#include +#include "bitstream_manager.h" +#include "module_manager.h" + +/******************************************************************** + * Function declaration + *******************************************************************/ + +/* begin namespace openfpga */ +namespace openfpga { + +std::vector build_fabric_dependent_bitstream(const BitstreamManager& bitstream_manager, + const ModuleManager& module_manager); + +} /* end namespace openfpga */ + +#endif