def __init__(self, config): self.__setupLogging(logging.DEBUG) self.config = config assert self.config['CompiledBy'] == 'TAPA' self.board = DeviceManager(config['Board']).getBoard() self.program_json_manager = ProgramJsonManager( config['ProjectPath'], config['Edges'], config['Vertices'], ) self.graph = DataflowGraphTapa(self.program_json_manager) slot_manager = SlotManager(self.board) user_constraint_s2v = self.parseUserConstraints(slot_manager) self.fp = Floorplanner(self.graph, user_constraint_s2v, slot_manager=slot_manager, total_usage=self.program_json_manager.getVertexTotalArea(), board=self.board) self.fp.coarseGrainedFloorplan()
def get_floorplan_output_bundle(config): assert config['CompiledBy'] == 'TAPA' board = DeviceManager( board_name=config['Board'], ddr_list=config.get('DDR', []), is_vitis_enabled=True, ).getBoard() program_json_manager = ProgramJsonManager( config['Edges'], config['Vertices'], config['Area'], ) graph = DataflowGraphTapa(program_json_manager) slot_manager = SlotManager(board) # which modules must be assigned to the same slot grouping_constraints: List[List[str]] = config.get('GroupingConstraints', []) # process optional module pre-assignment constraints module_floorplan = config['OptionalFloorplan'] pre_assignment = {} for region, module_group in module_floorplan.items(): for mod_name in module_group: pre_assignment[mod_name] = region kwargs = {} ref_usage_ratio = config.get('MaxUsage') if ref_usage_ratio is not None: kwargs['ref_usage_ratio'] = ref_usage_ratio # generate floorplan v2s = autobridge_floorplan.get_floorplan(graph, slot_manager, grouping_constraints, pre_assignment, **kwargs) s2v = util.invert_v2s(v2s) topology = Topology(s2v) return v2s, s2v, topology
def __init__(self, config_file_path): assert os.path.isfile(config_file_path) self.config = json.loads(open(config_file_path, 'r').read()) self.basicSetup() self.loggingSetup() hls_prj_manager = HLSProjectManager(self.top_rtl_name, self.hls_prj_path, self.hls_solution_name) top_rtl_parser = TopRTLParser(hls_prj_manager.getTopRTLPath()) graph = DataflowGraph(hls_prj_manager, top_rtl_parser) slot_manager = SlotManager(self.board) user_constraint_s2v = self.parseUserConstraints(graph, slot_manager) floorplan = self.runFloorplanning(graph, user_constraint_s2v, slot_manager, hls_prj_manager) # grid routing of edges global_router = GlobalRouting(floorplan, top_rtl_parser, slot_manager) # latency balancing rebalance = LatencyBalancing(graph, floorplan, global_router)
def annotate_floorplan(config: Dict) -> Dict: cli_logger = set_general_logger(config) print_start(config) init_logging(config) if not is_device_supported(config): return config analyze_input(config) board = DeviceManager( board_name=get_board_num(config), ddr_list=get_ddr_list(config), is_vitis_enabled=True, ).getBoard() program_json_manager = ProgramJsonManager( config['edges'], get_vertex_section(config), get_area_section(config), ) graph = DataflowGraphTapa(program_json_manager) slot_manager = SlotManager(board) # which modules must be assigned to the same slot grouping_constraints: List[List[str]] = config.get('grouping_constraints', []) # process optional module pre-assignment constraints module_floorplan = config['floorplan_pre_assignments'] pre_assignment = {} for region, module_group in module_floorplan.items(): for mod_name in module_group: pre_assignment[mod_name] = region kwargs = get_floorplan_params(config) # generate floorplan # slot_list includes all possible slot regardless of whether it is empty v2s, slot_list = autobridge_floorplan.get_floorplan( graph, slot_manager, grouping_constraints, pre_assignment, **kwargs, ) # if floorplan failed if v2s is None: cli_logger.critical('\n*** CRITICAL WARNING: AutoBridge fails to find a solution. Please refer to the log for details.\n') config['floorplan_status'] = 'FAILED' print_end() return config slot_to_usage = util.get_slot_utilization(v2s) # route the FIFO pipelines router = ILPRouter( list(graph.edges.values()), v2s, slot_to_usage, slot_list, ) fifo_to_path: Dict[Edge, List[Slot]] = router.route_design() fifo_name_to_depth = latency_balancing(graph, fifo_to_path) annotated_config = get_annotated_config(v2s, slot_list, fifo_to_path, slot_to_usage, fifo_name_to_depth, config) analyze_result(annotated_config) print_end() return annotated_config
def get_four_way_partition_slots(slot_manager: SlotManager) -> List[Slot]: """ get all the eight slots after eight-way partition """ partition_order = [Dir.horizontal, Dir.horizontal] return slot_manager.getLeafSlotsAfterPartition(partition_order)
def get_floorplan( graph: DataflowGraph, slot_manager: SlotManager, grouping_constraints_in_str: List[List[str]], pre_assignments_in_str: Dict[str, str], floorplan_strategy: str = 'HALF_SLR_LEVEL_FLOORPLANNING', threshold_for_iterative: int = 200, floorplan_opt_priority: str = 'AREA_PRIORITIZED', min_area_limit: float = 0.65, max_area_limit: float = 0.85, min_slr_width_limit: int = 10000, max_slr_width_limit: int = 15000, max_search_time: int = 600, hbm_port_v_name_list: List[str] = [] ) -> Tuple[Dict[Vertex, Slot], List[Slot]]: """ main entrance of the floorplan part return (1) mapping from vertex to slot (2) a list of all potential slots Note that an empty slot will not be in (1), but will occur in (2) """ # get initial v2s init_slot = slot_manager.getInitialSlot() init_v2s = {v: init_slot for v in graph.getAllVertices()} actual_usage = get_actual_usage(init_v2s.keys(), slot_manager.getInitialSlot()) if max_area_limit < actual_usage: max_area_limit = actual_usage + 0.1 cli_logger.warning( 'The specified max_area_limit is less than the actual usage of the design: %f. ' 'Adjust max_area_limit to %f', actual_usage, max_area_limit) if min_area_limit < actual_usage: min_area_limit = actual_usage cli_logger.warning( 'Adjust the min_area_limit to the actual usage of the design: %f', actual_usage) cli_logger.info('') cli_logger.info('Floorplan parameters:') cli_logger.info('') cli_logger.info(' floorplan_strategy: %s', floorplan_strategy) cli_logger.info(' threshold for switching to iterative partitioning: %d', threshold_for_iterative) cli_logger.info(' floorplan_opt_priority: %s', floorplan_opt_priority) cli_logger.info(' min_area_limit: %f', min_area_limit) cli_logger.info(' max_area_limit: %f', max_area_limit) cli_logger.info(' min_slr_width_limit: %d', min_slr_width_limit) cli_logger.info(' max_slr_width_limit: %d', max_slr_width_limit) cli_logger.info(' max_search_time per solving: %d', max_search_time) cli_logger.info('') cli_logger.info( 'Start floorplanning, please check the log for the progress...\n') # get grouping constraints of Vertex grouping_constraints: List[List[Vertex]] = [[ graph.getVertex(v_name) for v_name in v_name_group ] for v_name_group in grouping_constraints_in_str] _logger.info(f'The following modules are grouped to the same location:') for grouping in grouping_constraints_in_str: _logger.info(' ' + ', '.join(grouping)) # get pre_assignment in Vertex pre_assignments = { graph.getVertex(v_name): slot_manager.createSlot(pblock) for v_name, pblock in pre_assignments_in_str.items() } # get the hbm port vertices hbm_port_v_list = [ graph.getVertex(v_name) for v_name in hbm_port_v_name_list ] for v_name in hbm_port_v_name_list: _logger.info('Binding of HBM vertex %s is subject to change', v_name) print_pre_assignment(pre_assignments) print_vertex_areas(init_v2s.keys(), slot_manager.getInitialSlot()) params = { 'floorplan_opt_priority': floorplan_opt_priority, 'min_area_limit': min_area_limit, 'max_area_limit': max_area_limit, 'min_slr_width_limit': min_slr_width_limit, 'max_slr_width_limit': max_slr_width_limit, 'max_search_time': max_search_time, 'hbm_port_v_list': hbm_port_v_list, } # choose floorplan method num_vertices = len(graph.getAllVertices()) v2s: Dict[Vertex, Slot] = {} # if user specifies floorplan methods if floorplan_strategy == 'SLR_LEVEL_FLOORPLANNING': _logger.info(f'user specifies to floorplan into SLR-level slots') v2s = partition(init_v2s, slot_manager, grouping_constraints, pre_assignments, partition_method='FOUR_WAY_PARTITION', **params) if v2s: return v2s, get_four_way_partition_slots(slot_manager) else: return None, None elif floorplan_strategy == 'QUICK_FLOORPLANNING': _logger.info(f'user specifies to prioritize speed') v2s = iterative_bipartition(init_v2s, slot_manager, grouping_constraints, pre_assignments) if v2s: return v2s, get_eight_way_partition_slots(slot_manager) else: return None, None else: if floorplan_strategy != 'HALF_SLR_LEVEL_FLOORPLANNING': raise NotImplementedError('unrecognized floorplan strategy %s', floorplan_strategy) # empirically select the floorplan method if num_vertices < threshold_for_iterative: _logger.info( f'There are {num_vertices} vertices in the design, use eight way partition' ) if num_vertices > 100: _logger.warning( 'Over 100 vertices. May have a long solving time. Reduce threshold_for_iterative to skip to iterative bi-partitioning.' ) v2s = partition(init_v2s, slot_manager, grouping_constraints, pre_assignments, partition_method='EIGHT_WAY_PARTITION', **params) if v2s: return v2s, get_eight_way_partition_slots(slot_manager) else: _logger.warning( f'Please check if any function in the design is too large') _logger.info( f'Use four-way partition because eight-way partition failed or there are too many vertices ({num_vertices})' ) v2s = partition(init_v2s, slot_manager, grouping_constraints, pre_assignments, partition_method='FOUR_WAY_PARTITION', **params) if v2s: final_v2s = iterative_bipartition(v2s, slot_manager, grouping_constraints, pre_assignments, partition_order=[Dir.vertical]) if final_v2s: return final_v2s, get_eight_way_partition_slots(slot_manager) else: return v2s, get_four_way_partition_slots(slot_manager) _logger.error( f'AutoBridge fails to partition the design at the SLR level. Either the design is too large, or the functions/modules are too large.' ) return None, None