Exemple #1
0
def generate_constraints(config):
    assert config['CompiledBy'] == 'TAPA'

    board = DeviceManager(config['Board']).getBoard()
    program_json_manager = ProgramJsonManager(
        config['Edges'],
        config['Vertices'],
        config['Area'],
    )
    graph = DataflowGraphTapa(program_json_manager)
    slot_manager = SlotManager(board)
    user_constraint_s2v = collections.defaultdict(list)

    # process optional module constraints
    module_floorplan = config['OptionalFloorplan']
    for region, module_group in module_floorplan.items():
        slot = slot_manager.createSlot(region)
        for mod_name in module_group:
            user_constraint_s2v[slot].append(graph.getVertex(mod_name))

    # generate floorplan
    floorplan = Floorplanner(
        graph,
        user_constraint_s2v,
        slot_manager=slot_manager,
        total_usage=program_json_manager.getVertexTotalArea(),
        board=board,
    )
    floorplan.eightWayPartition()

    # generate topology
    s2v = floorplan.getSlotToVertices()
    topology = Topology(s2v)
    return {
        slot.pblock_name:
        [v.name for v in v_group] + [topology.getTopologyOf(slot)]
        for slot, v_group in s2v.items()
    }
Exemple #2
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