openfpga/src/fpga_bitstream/build_fabric_bitstream.cpp
/********************************************************************
 * This function aims to build a bitstream for frame-based configuration protocol
 * It 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 guarenteed 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 
 *
 * For each configuration bits, we will infer its address based on 
 *  - the child index in the configurable children list of current module
 *  - the child index of all the parent modules in their configurable children list 
 *    until the top in the hierarchy
 *
 * The address will be organized as follows:
 *  <Address_in_top> ... <Address_in_parent_module>
 * The address will be decoded to a binary format
 *
 * For each configuration bit, the data_in for the frame-based decoders will be 
 * the same as the configuration bit in bitstream manager.
 *******************************************************************/
This function aims to build a bitstream for frame-based configuration protocol
It 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 guarenteed 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

For each configuration bits, we will infer its address based on
- the child index in the configurable children list of current module
- the child index of all the parent modules in their configurable children list
until the top in the hierarchy

The address will be organized as follows:
 ... 
The address will be decoded to a binary format

For each configuration bit, the data_in for the frame-based decoders will be
the same as the configuration bit in bitstream manager.
This function aims to build a bitstream for frame - based configuration protocol It 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 guarenteed 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 For each configuration bits we will infer its address based on - the child index in the configurable children list of current module - the child index of all the parent modules in their configurable children list until the top in the hierarchy The address will be organized as follows : ... The address will be decoded to a binary format For each configuration bit the data_in for the frame - based decoders will be the same as the configuration bit in bitstream manager .
static 
void rec_build_module_fabric_dependent_frame_bitstream(const BitstreamManager& bitstream_manager,
                                                       const std::vector<ConfigBlockId>& parent_blocks,
                                                       const ModuleManager& module_manager,
                                                       const ModuleId& top_module,
                                                       const ConfigRegionId& config_region,
                                                       const std::vector<ModuleId>& parent_modules,
                                                       const std::vector<char>& addr_code,
                                                       const char& bitstream_dont_care_char,
                                                       FabricBitstream& fabric_bitstream,
                                                       FabricBitRegionId& fabric_bitstream_region) {
  if (0 < bitstream_manager.block_children(parent_blocks.back()).size()) {
    const ConfigBlockId& parent_block = parent_blocks.back();
    const ModuleId& parent_module = parent_modules.back();
    std::vector<ModuleId> configurable_children;
    std::vector<size_t> configurable_child_instances;
    if (top_module == parent_module) {
      configurable_children = module_manager.region_configurable_children(parent_module, config_region);
      configurable_child_instances = module_manager.region_configurable_child_instances(parent_module, config_region);
    } else {
      VTR_ASSERT(top_module != parent_module);
      configurable_children = module_manager.configurable_children(parent_module);
      configurable_child_instances = module_manager.configurable_child_instances(parent_module);
    }
    size_t num_configurable_children = configurable_children.size();
    size_t max_child_addr_code_size = 0;
    bool add_addr_code = true;
    ModuleId decoder_module = ModuleId::INVALID();
    if (0 == num_configurable_children) {
      VTR_ASSERT(0 == bitstream_manager.block_bits(parent_block).size());
      return;
    }
    if (1 == num_configurable_children) {
      add_addr_code = false;
    } else {
      VTR_ASSERT(2 < num_configurable_children);
      num_configurable_children--;
      decoder_module = configurable_children.back();
      for (const ModuleId& child_module : module_manager.configurable_children(parent_module)) {
        if (module_manager.configurable_children(child_module).empty()) {
          continue;
        }
        const ModulePortId& child_addr_port_id = module_manager.find_module_port(child_module, std::string(DECODER_ADDRESS_PORT_NAME));
        const BasicPort& child_addr_port = module_manager.module_port(child_module, child_addr_port_id);
        max_child_addr_code_size = std::max(child_addr_port.get_width(), max_child_addr_code_size);
      }
    }
    for (size_t child_id = 0; child_id < num_configurable_children; ++child_id) {
      ModuleId child_module = configurable_children[child_id]; 
      size_t child_instance = configurable_child_instances[child_id]; 
      std::string instance_name = module_manager.instance_name(parent_module, child_module, child_instance);
      ConfigBlockId child_block = bitstream_manager.find_child_block(parent_block, instance_name); 
      VTR_ASSERT(true == bitstream_manager.valid_block_id(child_block));
      std::vector<ConfigBlockId> child_blocks = parent_blocks;
      child_blocks.push_back(child_block);
      std::vector<ModuleId> child_modules = parent_modules;
      child_modules.push_back(child_module);
      std::vector<char> child_addr_code = addr_code;
      if (true == add_addr_code) { 
        const ModulePortId& decoder_addr_port_id = module_manager.find_module_port(decoder_module, std::string(DECODER_ADDRESS_PORT_NAME));
        const BasicPort& decoder_addr_port = module_manager.module_port(decoder_module, decoder_addr_port_id);
        std::vector<char> addr_bits_vec = itobin_charvec(child_id, decoder_addr_port.get_width());
        if (top_module == parent_module) {
          child_addr_code.insert(child_addr_code.end(), addr_bits_vec.begin(), addr_bits_vec.end());
        } else {
          VTR_ASSERT_SAFE(top_module != parent_module);
          child_addr_code.insert(child_addr_code.begin(), addr_bits_vec.begin(), addr_bits_vec.end());
        }
        const ModulePortId& child_addr_port_id = module_manager.find_module_port(child_module, std::string(DECODER_ADDRESS_PORT_NAME));
        const BasicPort& child_addr_port = module_manager.module_port(child_module, child_addr_port_id);
        if (0 < max_child_addr_code_size - child_addr_port.get_width()) {
          std::vector<char> dummy_codes(max_child_addr_code_size - child_addr_port.get_width(), bitstream_dont_care_char);
          child_addr_code.insert(child_addr_code.begin(), dummy_codes.begin(), dummy_codes.end());
        }
      }
      rec_build_module_fabric_dependent_frame_bitstream(bitstream_manager, child_blocks,
                                                        module_manager,
                                                        top_module,
                                                        config_region,
                                                        child_modules,
                                                        child_addr_code,
                                                        bitstream_dont_care_char,
                                                        fabric_bitstream,
                                                        fabric_bitstream_region);
    }
    VTR_ASSERT(0 == bitstream_manager.block_bits(parent_block).size());
    return;
  }
  std::vector<ModuleId> configurable_children;
  if (top_module == parent_modules.back()) {
    configurable_children = module_manager.region_configurable_children(parent_modules.back(), config_region);
  } else {
    VTR_ASSERT(top_module != parent_modules.back());
    configurable_children = module_manager.configurable_children(parent_modules.back());
  }
  ModuleId decoder_module = configurable_children.back();
  const ModulePortId& decoder_addr_port_id = module_manager.find_module_port(decoder_module, std::string(DECODER_ADDRESS_PORT_NAME));
  const BasicPort& decoder_addr_port = module_manager.module_port(decoder_module, decoder_addr_port_id);
  for (size_t ibit = 0; ibit < bitstream_manager.block_bits(parent_blocks.back()).size(); ++ibit) {
    ConfigBitId config_bit = bitstream_manager.block_bits(parent_blocks.back())[ibit];
    std::vector<char> addr_bits_vec = itobin_charvec(ibit, decoder_addr_port.get_width());
    std::vector<char> child_addr_code = addr_code;
    child_addr_code.insert(child_addr_code.begin(), addr_bits_vec.begin(), addr_bits_vec.end());
    const FabricBitId& fabric_bit = fabric_bitstream.add_bit(config_bit);
    fabric_bitstream.set_bit_address(fabric_bit, child_addr_code);
    fabric_bitstream.set_bit_din(fabric_bit, bitstream_manager.bit_value(config_bit));
    fabric_bitstream.add_bit_to_region(fabric_bitstream_region, fabric_bit);
  }
}
static void rec_build_module_fabric_dependent_frame_bitstream ( const BitstreamManager & bitstream_manager , const std :: vector < ConfigBlockId > & parent_blocks , const ModuleManager & module_manager , const ModuleId & top_module , const ConfigRegionId & config_region , const std :: vector < ModuleId > & parent_modules , const std :: vector < char > & addr_code , const char & bitstream_dont_care_char , FabricBitstream & fabric_bitstream , FabricBitRegionId & fabric_bitstream_region ) { if ( 0 < bitstream_manager . block_children ( parent_blocks . back ( ) ) . size ( ) ) { const ConfigBlockId & parent_block = parent_blocks . back ( ) ; const ModuleId & parent_module = parent_modules . back ( ) ; std :: vector < ModuleId > configurable_children ; std :: vector < size_t > configurable_child_instances ; if ( top_module == parent_module ) { configurable_children = module_manager . region_configurable_children ( parent_module , config_region ) ; configurable_child_instances = module_manager . region_configurable_child_instances ( parent_module , config_region ) ; } else { VTR_ASSERT ( top_module != parent_module ) ; configurable_children = module_manager . configurable_children ( parent_module ) ; configurable_child_instances = module_manager . configurable_child_instances ( parent_module ) ; } size_t num_configurable_children = configurable_children . size ( ) ; size_t max_child_addr_code_size = 0 ; bool add_addr_code = true ; ModuleId decoder_module = ModuleId :: INVALID ( ) ; if ( 0 == num_configurable_children ) { VTR_ASSERT ( 0 == bitstream_manager . block_bits ( parent_block ) . size ( ) ) ; return ; } if ( 1 == num_configurable_children ) { add_addr_code = false ; } else { VTR_ASSERT ( 2 < num_configurable_children ) ; num_configurable_children -- ; decoder_module = configurable_children . back ( ) ; for ( const ModuleId & child_module : module_manager . configurable_children ( parent_module ) ) { if ( module_manager . configurable_children ( child_module ) . empty ( ) ) { continue ; } const ModulePortId & child_addr_port_id = module_manager . find_module_port ( child_module , std :: string ( DECODER_ADDRESS_PORT_NAME ) ) ; const BasicPort & child_addr_port = module_manager . module_port ( child_module , child_addr_port_id ) ; max_child_addr_code_size = std :: max ( child_addr_port . get_width ( ) , max_child_addr_code_size ) ; } } for ( size_t child_id = 0 ; child_id < num_configurable_children ; ++ child_id ) { ModuleId child_module = configurable_children [ child_id ] ; size_t child_instance = configurable_child_instances [ child_id ] ; std :: string instance_name = module_manager . instance_name ( parent_module , child_module , child_instance ) ; ConfigBlockId child_block = bitstream_manager . find_child_block ( parent_block , instance_name ) ; VTR_ASSERT ( true == bitstream_manager . valid_block_id ( child_block ) ) ; std :: vector < ConfigBlockId > child_blocks = parent_blocks ; child_blocks . push_back ( child_block ) ; std :: vector < ModuleId > child_modules = parent_modules ; child_modules . push_back ( child_module ) ; std :: vector < char > child_addr_code = addr_code ; if ( true == add_addr_code ) { const ModulePortId & decoder_addr_port_id = module_manager . find_module_port ( decoder_module , std :: string ( DECODER_ADDRESS_PORT_NAME ) ) ; const BasicPort & decoder_addr_port = module_manager . module_port ( decoder_module , decoder_addr_port_id ) ; std :: vector < char > addr_bits_vec = itobin_charvec ( child_id , decoder_addr_port . get_width ( ) ) ; if ( top_module == parent_module ) { child_addr_code . insert ( child_addr_code . end ( ) , addr_bits_vec . begin ( ) , addr_bits_vec . end ( ) ) ; } else { VTR_ASSERT_SAFE ( top_module != parent_module ) ; child_addr_code . insert ( child_addr_code . begin ( ) , addr_bits_vec . begin ( ) , addr_bits_vec . end ( ) ) ; } const ModulePortId & child_addr_port_id = module_manager . find_module_port ( child_module , std :: string ( DECODER_ADDRESS_PORT_NAME ) ) ; const BasicPort & child_addr_port = module_manager . module_port ( child_module , child_addr_port_id ) ; if ( 0 < max_child_addr_code_size - child_addr_port . get_width ( ) ) { std :: vector < char > dummy_codes ( max_child_addr_code_size - child_addr_port . get_width ( ) , bitstream_dont_care_char ) ; child_addr_code . insert ( child_addr_code . begin ( ) , dummy_codes . begin ( ) , dummy_codes . end ( ) ) ; } } rec_build_module_fabric_dependent_frame_bitstream ( bitstream_manager , child_blocks , module_manager , top_module , config_region , child_modules , child_addr_code , bitstream_dont_care_char , fabric_bitstream , fabric_bitstream_region ) ; } VTR_ASSERT ( 0 == bitstream_manager . block_bits ( parent_block ) . size ( ) ) ; return ; } std :: vector < ModuleId > configurable_children ; if ( top_module == parent_modules . back ( ) ) { configurable_children = module_manager . region_configurable_children ( parent_modules . back ( ) , config_region ) ; } else { VTR_ASSERT ( top_module != parent_modules . back ( ) ) ; configurable_children = module_manager . configurable_children ( parent_modules . back ( ) ) ; } ModuleId decoder_module = configurable_children . back ( ) ; const ModulePortId & decoder_addr_port_id = module_manager . find_module_port ( decoder_module , std :: string ( DECODER_ADDRESS_PORT_NAME ) ) ; const BasicPort & decoder_addr_port = module_manager . module_port ( decoder_module , decoder_addr_port_id ) ; for ( size_t ibit = 0 ; ibit < bitstream_manager . block_bits ( parent_blocks . back ( ) ) . size ( ) ; ++ ibit ) { ConfigBitId config_bit = bitstream_manager . block_bits ( parent_blocks . back ( ) ) [ ibit ] ; std :: vector < char > addr_bits_vec = itobin_charvec ( ibit , decoder_addr_port . get_width ( ) ) ; std :: vector < char > child_addr_code = addr_code ; child_addr_code . insert ( child_addr_code . begin ( ) , addr_bits_vec . begin ( ) , addr_bits_vec . end ( ) ) ; const FabricBitId & fabric_bit = fabric_bitstream . add_bit ( config_bit ) ; fabric_bitstream . set_bit_address ( fabric_bit , child_addr_code ) ; fabric_bitstream . set_bit_din ( fabric_bit , bitstream_manager . bit_value ( config_bit ) ) ; fabric_bitstream . add_bit_to_region ( fabric_bitstream_region , fabric_bit ) ; } }
This function aims to build a bitstream for frame-based configuration protocol
 It 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.
This function aims to build a bitstream for frame - based configuration protocol It 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 .
/* Depth-first search: if we have any children in the parent_block, 
   * we dive to the next level first! 
   */ /* Early exit if there is no configurable children */ /* Ensure that there should be no configuration bits in the parent block */ /* For only 1 configurable child,
     * there is no frame decoder here, we can pass on addr code directly
     */ /* For more than 2 children, there is a decoder in the tail of the list
      * We will not decode that, but will access the address size from that module
      * So, we reduce the number of children by 1
      */ /* The max address code size is the max address code size of all the 
       * configurable children in all the regions
       */ /* Bypass any decoder module (which no configurable children */ /* Get the instance name and ensure it is not empty */ /* Find the child block that matches the instance name! */ /* We must have one valid block id! */ /* Pass on the list of blocks, modules and address lists */ /* Set address, apply binary conversion from the first to the last element in the address list */ /* Find the address port from the decoder module */ /* For top-level module, the child address should be added to the tail 
         * For other modules, the child address should be added to the head
         */ /* Note that the address port size of the child module may be smaller than the maximum
         * of other child modules at this level.
         * We will add dummy '0's to the head of addr_bit_vec.
         *
         * For example:
         *  Decoder is the decoder to access all the child modules
         *  whose address is decoded by the addr_bits_vec
         *  The child modules may use part of the address lines,
         *  we should add dummy '0' to fill the gap
         *
         *  Addr_code for child[0]: '000' + addr_bits_vec
         *  Addr_code for child[1]: '00'  + addr_bits_vec 
         *  Addr_code for child[2]: '0' + addr_bits_vec 
         *
         *                   Addr[6:8]
         *                     |
         *                     v
         *  +-------------------------------------------+
         *  |            Decoder Module                 |
         *  +-------------------------------------------+
         *   
         *     Addr[0:2]       Addr[0:3]        Addr[0:4]
         *        |                |               |
         *        v                v               v
         * +-----------+  +-------------+  +------------+
         * | Child[0]  |  |  Child[1]   |  |  Child[2]  |
         * +-----------+  +-------------+  +------------+
         *
         * Child[2] has the maximum address lines among the children
         *
         */ /* Deposit don't care state for the dummy bits */ /* Go recursively */ /* Ensure that there should be no configuration bits in the parent block */ /* Note that, reach here, it means that this is a leaf node. 
   * A leaf node (a memory module) always has a decoder inside
   * which is the last of configurable children.
   * We will find the address bit and add it to addr_code
   * Then we can add the configuration bits to the fabric_bitstream.
   */ /* Find the address port from the decoder module */ /* Set address */ /* Set data input */ /* Add the bit to the region */