openfpga/src/fpga_bitstream/build_fabric_bitstream.cpp
/********************************************************************
 * Main function to build a fabric-dependent bitstream
 * by considering the configuration protocol types 
 *******************************************************************/
Main function to build a fabric-dependent bitstream
by considering the configuration protocol types
Main function to build a fabric - dependent bitstream by considering the configuration protocol types
static 
void build_module_fabric_dependent_bitstream(const ConfigProtocol& config_protocol,
                                             const BitstreamManager& bitstream_manager,
                                             const ConfigBlockId& top_block,
                                             const ModuleManager& module_manager,
                                             const ModuleId& top_module,
                                             FabricBitstream& fabric_bitstream) {
  switch (config_protocol.type()) {
  case CONFIG_MEM_STANDALONE: {
    fabric_bitstream.reserve_bits(bitstream_manager.num_bits());
    for (const ConfigRegionId& config_region : module_manager.regions(top_module)) {
      FabricBitRegionId fabric_bitstream_region = fabric_bitstream.add_region();
      rec_build_module_fabric_dependent_chain_bitstream(bitstream_manager, top_block,
                                                        module_manager, top_module, 
                                                        top_module,
                                                        config_region,
                                                        fabric_bitstream,
                                                        fabric_bitstream_region);
    }
    break;
  }
  case CONFIG_MEM_SCAN_CHAIN: { 
    fabric_bitstream.reserve_bits(bitstream_manager.num_bits());
    for (const ConfigRegionId& config_region : module_manager.regions(top_module)) {
      FabricBitRegionId fabric_bitstream_region = fabric_bitstream.add_region();
      rec_build_module_fabric_dependent_chain_bitstream(bitstream_manager, top_block,
                                                        module_manager, top_module, 
                                                        top_module,
                                                        config_region,
                                                        fabric_bitstream,
                                                        fabric_bitstream_region);
      fabric_bitstream.reverse_region_bits(fabric_bitstream_region);
    }
    break;
  }
  case CONFIG_MEM_MEMORY_BANK: { 
    ModulePortId bl_addr_port = module_manager.find_module_port(top_module, std::string(DECODER_BL_ADDRESS_PORT_NAME));
    BasicPort bl_addr_port_info = module_manager.module_port(top_module, bl_addr_port);
    ModulePortId wl_addr_port = module_manager.find_module_port(top_module, std::string(DECODER_WL_ADDRESS_PORT_NAME));
    BasicPort wl_addr_port_info = module_manager.module_port(top_module, wl_addr_port);
    fabric_bitstream.set_use_address(true);
    fabric_bitstream.set_use_wl_address(true);
    fabric_bitstream.set_bl_address_length(bl_addr_port_info.get_width());
    fabric_bitstream.set_wl_address_length(wl_addr_port_info.get_width());
    fabric_bitstream.reserve_bits(bitstream_manager.num_bits());
    for (const ConfigRegionId& config_region : module_manager.regions(top_module)) {
      size_t cur_mem_index = 0;
      std::vector<ModuleId> configurable_children = module_manager.region_configurable_children(top_module, config_region);
      VTR_ASSERT(2 <= configurable_children.size()); 
      ModuleId bl_decoder_module = configurable_children[configurable_children.size() - 2];
      ModuleId wl_decoder_module = configurable_children[configurable_children.size() - 1];
      ModulePortId bl_port = module_manager.find_module_port(bl_decoder_module, std::string(DECODER_DATA_OUT_PORT_NAME));
      BasicPort bl_port_info = module_manager.module_port(bl_decoder_module, bl_port);
      ModulePortId wl_port = module_manager.find_module_port(wl_decoder_module, std::string(DECODER_DATA_OUT_PORT_NAME));
      BasicPort wl_port_info = module_manager.module_port(wl_decoder_module, wl_port);
      FabricBitRegionId fabric_bitstream_region = fabric_bitstream.add_region();
      rec_build_module_fabric_dependent_memory_bank_bitstream(bitstream_manager, top_block,
                                                              module_manager, top_module, top_module, 
                                                              config_region,
                                                              bl_addr_port_info.get_width(),
                                                              wl_addr_port_info.get_width(),
                                                              bl_port_info.get_width(),
                                                              wl_port_info.get_width(),
                                                              cur_mem_index,
                                                              fabric_bitstream,
                                                              fabric_bitstream_region);
    }
    break;
  }
  case CONFIG_MEM_FRAME_BASED: {
    ModulePortId addr_port = module_manager.find_module_port(top_module, std::string(DECODER_ADDRESS_PORT_NAME));
    BasicPort addr_port_info = module_manager.module_port(top_module, addr_port);
    fabric_bitstream.set_use_address(true);
    fabric_bitstream.reserve_bits(bitstream_manager.num_bits());
    fabric_bitstream.set_address_length(addr_port_info.get_width());
    char bitstream_dont_care_char = DONT_CARE_CHAR;
    if (1 == module_manager.regions(top_module).size()) {
      bitstream_dont_care_char = '0';
    }
    size_t max_decoder_addr_size = 0;
    for (const ConfigRegionId& config_region : module_manager.regions(top_module)) {
      std::vector<ModuleId> configurable_children = module_manager.region_configurable_children(top_module, config_region);
      if ( (0 == configurable_children.size())
        || (1 == configurable_children.size())) {
        continue;
      }
      ModuleId decoder_module = configurable_children.back();
      ModulePortId decoder_addr_port_id = module_manager.find_module_port(decoder_module, DECODER_ADDRESS_PORT_NAME);
      BasicPort decoder_addr_port = module_manager.module_port(decoder_module, decoder_addr_port_id);
      max_decoder_addr_size = std::max(max_decoder_addr_size, decoder_addr_port.get_width()); 
    }
    for (const ConfigRegionId& config_region : module_manager.regions(top_module)) {
      std::vector<ModuleId> configurable_children = module_manager.region_configurable_children(top_module, config_region);
      if (0 == configurable_children.size()) {
        continue;
      }
      ModuleId decoder_module = configurable_children.back();
      ModulePortId decoder_addr_port_id = module_manager.find_module_port(decoder_module, DECODER_ADDRESS_PORT_NAME);
      BasicPort decoder_addr_port = module_manager.module_port(decoder_module, decoder_addr_port_id);
      VTR_ASSERT(max_decoder_addr_size >= decoder_addr_port.get_width());
      std::vector<char> idle_addr_bits(max_decoder_addr_size - decoder_addr_port.get_width(), bitstream_dont_care_char);
      FabricBitRegionId fabric_bitstream_region = fabric_bitstream.add_region();
      rec_build_module_fabric_dependent_frame_bitstream(bitstream_manager,
                                                        std::vector<ConfigBlockId>(1, top_block),
                                                        module_manager,
                                                        top_module,
                                                        config_region,
                                                        std::vector<ModuleId>(1, top_module),
	  												    idle_addr_bits,
                                                        bitstream_dont_care_char,
                                                        fabric_bitstream,
                                                        fabric_bitstream_region);
    }
    break;
  }
  default:
    VTR_LOGF_ERROR(__FILE__, __LINE__,
                   "Invalid SRAM organization.\n");
    exit(1);
  }
  VTR_ASSERT(bitstream_manager.num_bits() == fabric_bitstream.num_bits());
}
static void build_module_fabric_dependent_bitstream ( const ConfigProtocol & config_protocol , const BitstreamManager & bitstream_manager , const ConfigBlockId & top_block , const ModuleManager & module_manager , const ModuleId & top_module , FabricBitstream & fabric_bitstream ) { switch ( config_protocol . type ( ) ) { case CONFIG_MEM_STANDALONE : { fabric_bitstream . reserve_bits ( bitstream_manager . num_bits ( ) ) ; for ( const ConfigRegionId & config_region : module_manager . regions ( top_module ) ) { FabricBitRegionId fabric_bitstream_region = fabric_bitstream . add_region ( ) ; rec_build_module_fabric_dependent_chain_bitstream ( bitstream_manager , top_block , module_manager , top_module , top_module , config_region , fabric_bitstream , fabric_bitstream_region ) ; } break ; } case CONFIG_MEM_SCAN_CHAIN : { fabric_bitstream . reserve_bits ( bitstream_manager . num_bits ( ) ) ; for ( const ConfigRegionId & config_region : module_manager . regions ( top_module ) ) { FabricBitRegionId fabric_bitstream_region = fabric_bitstream . add_region ( ) ; rec_build_module_fabric_dependent_chain_bitstream ( bitstream_manager , top_block , module_manager , top_module , top_module , config_region , fabric_bitstream , fabric_bitstream_region ) ; fabric_bitstream . reverse_region_bits ( fabric_bitstream_region ) ; } break ; } case CONFIG_MEM_MEMORY_BANK : { ModulePortId bl_addr_port = module_manager . find_module_port ( top_module , std :: string ( DECODER_BL_ADDRESS_PORT_NAME ) ) ; BasicPort bl_addr_port_info = module_manager . module_port ( top_module , bl_addr_port ) ; ModulePortId wl_addr_port = module_manager . find_module_port ( top_module , std :: string ( DECODER_WL_ADDRESS_PORT_NAME ) ) ; BasicPort wl_addr_port_info = module_manager . module_port ( top_module , wl_addr_port ) ; fabric_bitstream . set_use_address ( true ) ; fabric_bitstream . set_use_wl_address ( true ) ; fabric_bitstream . set_bl_address_length ( bl_addr_port_info . get_width ( ) ) ; fabric_bitstream . set_wl_address_length ( wl_addr_port_info . get_width ( ) ) ; fabric_bitstream . reserve_bits ( bitstream_manager . num_bits ( ) ) ; for ( const ConfigRegionId & config_region : module_manager . regions ( top_module ) ) { size_t cur_mem_index = 0 ; std :: vector < ModuleId > configurable_children = module_manager . region_configurable_children ( top_module , config_region ) ; VTR_ASSERT ( 2 <= configurable_children . size ( ) ) ; ModuleId bl_decoder_module = configurable_children [ configurable_children . size ( ) - 2 ] ; ModuleId wl_decoder_module = configurable_children [ configurable_children . size ( ) - 1 ] ; ModulePortId bl_port = module_manager . find_module_port ( bl_decoder_module , std :: string ( DECODER_DATA_OUT_PORT_NAME ) ) ; BasicPort bl_port_info = module_manager . module_port ( bl_decoder_module , bl_port ) ; ModulePortId wl_port = module_manager . find_module_port ( wl_decoder_module , std :: string ( DECODER_DATA_OUT_PORT_NAME ) ) ; BasicPort wl_port_info = module_manager . module_port ( wl_decoder_module , wl_port ) ; FabricBitRegionId fabric_bitstream_region = fabric_bitstream . add_region ( ) ; rec_build_module_fabric_dependent_memory_bank_bitstream ( bitstream_manager , top_block , module_manager , top_module , top_module , config_region , bl_addr_port_info . get_width ( ) , wl_addr_port_info . get_width ( ) , bl_port_info . get_width ( ) , wl_port_info . get_width ( ) , cur_mem_index , fabric_bitstream , fabric_bitstream_region ) ; } break ; } case CONFIG_MEM_FRAME_BASED : { ModulePortId addr_port = module_manager . find_module_port ( top_module , std :: string ( DECODER_ADDRESS_PORT_NAME ) ) ; BasicPort addr_port_info = module_manager . module_port ( top_module , addr_port ) ; fabric_bitstream . set_use_address ( true ) ; fabric_bitstream . reserve_bits ( bitstream_manager . num_bits ( ) ) ; fabric_bitstream . set_address_length ( addr_port_info . get_width ( ) ) ; char bitstream_dont_care_char = DONT_CARE_CHAR ; if ( 1 == module_manager . regions ( top_module ) . size ( ) ) { bitstream_dont_care_char = ' ' ; } size_t max_decoder_addr_size = 0 ; for ( const ConfigRegionId & config_region : module_manager . regions ( top_module ) ) { std :: vector < ModuleId > configurable_children = module_manager . region_configurable_children ( top_module , config_region ) ; if ( ( 0 == configurable_children . size ( ) ) || ( 1 == configurable_children . size ( ) ) ) { continue ; } ModuleId decoder_module = configurable_children . back ( ) ; ModulePortId decoder_addr_port_id = module_manager . find_module_port ( decoder_module , DECODER_ADDRESS_PORT_NAME ) ; BasicPort decoder_addr_port = module_manager . module_port ( decoder_module , decoder_addr_port_id ) ; max_decoder_addr_size = std :: max ( max_decoder_addr_size , decoder_addr_port . get_width ( ) ) ; } for ( const ConfigRegionId & config_region : module_manager . regions ( top_module ) ) { std :: vector < ModuleId > configurable_children = module_manager . region_configurable_children ( top_module , config_region ) ; if ( 0 == configurable_children . size ( ) ) { continue ; } ModuleId decoder_module = configurable_children . back ( ) ; ModulePortId decoder_addr_port_id = module_manager . find_module_port ( decoder_module , DECODER_ADDRESS_PORT_NAME ) ; BasicPort decoder_addr_port = module_manager . module_port ( decoder_module , decoder_addr_port_id ) ; VTR_ASSERT ( max_decoder_addr_size >= decoder_addr_port . get_width ( ) ) ; std :: vector < char > idle_addr_bits ( max_decoder_addr_size - decoder_addr_port . get_width ( ) , bitstream_dont_care_char ) ; FabricBitRegionId fabric_bitstream_region = fabric_bitstream . add_region ( ) ; rec_build_module_fabric_dependent_frame_bitstream ( bitstream_manager , std :: vector < ConfigBlockId > ( 1 , top_block ) , module_manager , top_module , config_region , std :: vector < ModuleId > ( 1 , top_module ) , idle_addr_bits , bitstream_dont_care_char , fabric_bitstream , fabric_bitstream_region ) ; } break ; } default : VTR_LOGF_ERROR ( __FILE__ , __LINE__ , " \n " ) ; exit ( 1 ) ; } VTR_ASSERT ( bitstream_manager . num_bits ( ) == fabric_bitstream . num_bits ( ) ) ; }
Main function to build a fabric-dependent bitstream
 by considering the configuration protocol types
Main function to build a fabric - dependent bitstream by considering the configuration protocol types
/* Reserve bits before build-up */ /* Reserve bits before build-up */ /* Find global BL address port size */ /* Find global WL address port size */ /* Reserve bits before build-up */ /* Build bitstreams by region */ /* Find port information for local BL and WL decoder in this region */ /* Build the bitstream for all the blocks in this region */ /* Find address port size */ /* Reserve bits before build-up */ /* Avoid use don't care if there is only a region */ /* Find the maximum decoder address among all the configurable regions */ /* Bypass the regions that have no decoders */ /* Bypass non-configurable regions */ /* Find the idle address bit which should be added to the head of the address bit
       * This depends on the number of address bits required by this region
       * For example:
       *   Top-level address is addr[0:4]
       *   There are 4 decoders in the top-level module, whose address sizes are
       *     decoder A: addr[0:4]
       *     decoder B: addr[0:3]
       *     decoder C: addr[0:2]
       *     decoder D: addr[0:3]
       *   For decoder A, the address fit well
       *   For decoder B, an idle bit should be added '0' + addr[0:3] 
       *   For decoder C, two idle bits should be added '00' + addr[0:2] 
       *   For decoder D, an idle bit should be added '0' + addr[0:3] 
       */ /* 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<ConfigBitId>::iterator it = std::find(fabric_bitstream.begin(), fabric_bitstream.end(), config_bit);
    if (it == fabric_bitstream.end()) {
      std::vector<ConfigBlockId> 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 */