Example #1
0
  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()
Example #2
0
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
Example #3
0
    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)
Example #4
0
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
Example #5
0
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)
Example #6
0
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