Ejemplo n.º 1
0
    def basicSetup(self):
        self.device_manager = DeviceManager(self.config["Board"])
        self.board = self.device_manager.getBoard()

        self.top_rtl_name = self.config["TopName"]
        self.hls_prj_path = os.path.abspath(self.config["HLSProjectPath"])
        self.hls_solution_name = self.config["HLSSolutionName"]
        if "LoggingLevel" in self.config:
            self.logging_level = self.config["LoggingLevel"]
        else:
            self.logging_level = "INFO"

        if "Target" in self.config:
            self.target = self.config["Target"]
        else:
            self.target = "hw"
Ejemplo n.º 2
0
  def basicSetup(self):
    if "BundleToDDRMapping" in self.config:
      # reserve area for ddrs
      ddr_list = list(set(self.config["BundleToDDRMapping"].values()))
      assert len(ddr_list) == len(self.config["BundleToDDRMapping"].values())
      self.device_manager = DeviceManager(self.config["Board"], ddr_list, True)
    else:
      self.device_manager = DeviceManager(self.config["Board"], [], True)
    
    self.board = self.device_manager.getBoard()

    self.top_rtl_name = self.config["TopName"]
    self.hls_prj_path = os.path.abspath(self.config["HLSProjectPath"])
    self.hls_solution_name = self.config["HLSSolutionName"]
    if "LoggingLevel" in self.config:
      self.logging_level = self.config["LoggingLevel"]
    else:
      self.logging_level = "INFO"

    if "Target" in self.config:
      self.target = self.config["Target"]
    else:
      self.target = "hw"
Ejemplo n.º 3
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()
Ejemplo n.º 4
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
Ejemplo n.º 5
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()
    }
Ejemplo n.º 6
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
Ejemplo n.º 7
0
class Manager:
    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)

        # TODO: code gen

    def basicSetup(self):
        self.device_manager = DeviceManager(self.config["Board"])
        self.board = self.device_manager.getBoard()

        self.top_rtl_name = self.config["TopName"]
        self.hls_prj_path = os.path.abspath(self.config["HLSProjectPath"])
        self.hls_solution_name = self.config["HLSSolutionName"]
        if "LoggingLevel" in self.config:
            self.logging_level = self.config["LoggingLevel"]
        else:
            self.logging_level = "INFO"

        if "Target" in self.config:
            self.target = self.config["Target"]
        else:
            self.target = "hw"

    def loggingSetup(self):
        root = logging.getLogger()
        root.setLevel(logging.DEBUG)
        formatter = logging.Formatter(
            "[%(levelname)s: %(funcName)25s() ] %(message)s")

        debug_file_handler = logging.FileHandler(
            filename='autobridge-debug.log', mode='w')
        debug_file_handler.setLevel(logging.DEBUG)
        info_file_handler = logging.FileHandler(filename='autobridge-info.log',
                                                mode='w')
        info_file_handler.setLevel(logging.INFO)
        stdout_handler = logging.StreamHandler(sys.stdout)
        stdout_handler.setLevel(logging.INFO)

        handlers = [debug_file_handler, info_file_handler, stdout_handler]
        for handler in handlers:
            handler.setFormatter(formatter)
            root.addHandler(handler)

    def parseUserConstraints(self, graph, slot_manager):
        user_constraint_s2v = defaultdict(list)
        if "Floorplan" in self.config:
            user_fp_json = self.config["Floorplan"]
            for region, v_name_group in user_fp_json.items():
                slot = slot_manager.createSlot(region)
                for v_name in v_name_group:
                    user_constraint_s2v[slot].append(graph.getVertex(v_name))

        return user_constraint_s2v

    def runFloorplanning(self,
                         graph,
                         user_constraint_s2v,
                         slot_manager,
                         hls_prj_manager,
                         grouping_constraints=[]):
        floorplan = Floorplanner(
            graph,
            user_constraint_s2v,
            slot_manager=slot_manager,
            total_usage=hls_prj_manager.getTotalArea(),
            board=self.device_manager.getBoard(),
            user_max_usage_ratio=self.config['AreaUtilizationRatio'],
            grouping_constrants=grouping_constraints)

        if 'FloorplanMethod' in self.config:
            choice = self.config['FloorplanMethod']
            if choice == 'IterativeDivisionToFourCRs':
                floorplan.naiveFineGrainedFloorplan()
            elif choice == 'IterativeDivisionToHalfSLR':
                floorplan.coarseGrainedFloorplan()
            elif choice == 'IterativeDivisionToTwoCRs':
                floorplan.naiveTwoCRGranularityFloorplan()
            elif choice == 'EightWayDivisionToHalfSLR':
                floorplan.eightWayPartition()
            else:
                assert False, f'unsupported floorplan method: {choice}'
        else:
            floorplan.coarseGrainedFloorplan()  # by default

        floorplan.printFloorplan()
        return floorplan

    def help(self):
        manual = {
            "Board":
            "Choose between U250 and U280",
            "TopName":
            "The name of the top-level function of the HLS design",
            "HLSProjectPath":
            "Absolute path to the post-csynth HLS project",
            "HLSSolutionName":
            "Name of the solution of the HLS project",
            "FloorplanMethod":
            "Choose between IterativeDivisionToFourCRs and IterativeDivisionToHalfSLR",
            "AreaUtilizationRatio":
            "Allowed resource usage in each slot",
            "Floorplan (optional)": {
                "This is a comment":
                "User could dictate the final location of given modules",
                "Region": ["RTL module 1", "RTL module 2"]
            },
            "LoggingLevel (optional)":
            "Choose between DEBUG, INFO, WARNING, CRITICAL, ERROR"
        }
        print(json.dumps(manual, indent=2))
Ejemplo n.º 8
0
class Manager:

  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, top_rtl_parser)

    # grid routing of edges 
    global_router = GlobalRouting(floorplan, top_rtl_parser, slot_manager)

    # latency balancing
    rebalance = LatencyBalancing(graph, floorplan, global_router)

    generate_new_rtl_top(top_rtl_parser.top_module_ast, graph.getNameToEdgeMap(), top_rtl_parser.getTopModuleName(), floorplan)
    generate_floorplan_constraints(floorplan, global_router)
  
  def basicSetup(self):
    if "BundleToDDRMapping" in self.config:
      # reserve area for ddrs
      ddr_list = list(set(self.config["BundleToDDRMapping"].values()))
      assert len(ddr_list) == len(self.config["BundleToDDRMapping"].values())
      self.device_manager = DeviceManager(self.config["Board"], ddr_list, True)
    else:
      self.device_manager = DeviceManager(self.config["Board"], [], True)
    
    self.board = self.device_manager.getBoard()

    self.top_rtl_name = self.config["TopName"]
    self.hls_prj_path = os.path.abspath(self.config["HLSProjectPath"])
    self.hls_solution_name = self.config["HLSSolutionName"]
    if "LoggingLevel" in self.config:
      self.logging_level = self.config["LoggingLevel"]
    else:
      self.logging_level = "INFO"

    if "Target" in self.config:
      self.target = self.config["Target"]
    else:
      self.target = "hw"

  def loggingSetup(self):
    root = logging.getLogger()
    root.setLevel(logging.DEBUG)
    formatter = logging.Formatter("[%(levelname)s: %(funcName)25s() ] %(message)s")
    
    debug_file_handler = logging.FileHandler(filename='autobridge-debug.log', mode='w')
    debug_file_handler.setLevel(logging.DEBUG)
    info_file_handler = logging.FileHandler(filename='autobridge-info.log', mode='w')
    info_file_handler.setLevel(logging.INFO)
    stdout_handler = logging.StreamHandler(sys.stdout)
    stdout_handler.setLevel(logging.INFO)

    handlers = [debug_file_handler, info_file_handler, stdout_handler]
    for handler in handlers:
      handler.setFormatter(formatter)
      root.addHandler(handler)

  def parseUserConstraints(self, graph, slot_manager):
    user_constraint_s2v = defaultdict(list)
    
    def get_interface_module_name(bundle_name):
      top_name = self.config["TopName"]
      return f'{top_name}_{bundle_name}_m_axi_U'

    def get_s_axi_control_name():
      top_name = self.config["TopName"]
      return f'{top_name}_control_s_axi_U'

    # constrain the s_axi_control to SLR 0
    CONTROL_S_AXI_LOCATION = 0

    if "BundleToDDRMapping" in self.config:
      # properly constrain the interface modules
      board = self.device_manager.getBoard()
      for bundle, ddr in self.config["BundleToDDRMapping"].items():
        ddr_pblock = board.getDDRPblock(ddr)
        slot = slot_manager.createSlot(ddr_pblock)
        v_name = get_interface_module_name(bundle)
        try:
          v = graph.getVertex(v_name)
        except:
          logging.error(f'Naming convention of interface modules has changed!')
          exit(1)

        user_constraint_s2v[slot].append(v)
        logging.info(f'Constrain interface module {v_name} to {ddr_pblock}')

      # constrain the s_axi_control
      s_axi_slot = slot_manager.createSlot(board.getDDRPblock(CONTROL_S_AXI_LOCATION))
      try:
        s_axi_vertex = graph.getVertex(get_s_axi_control_name())
      except:
        logging.error(f'Naming convention of s_axi_control has changed!')
        exit(1)
      user_constraint_s2v[s_axi_slot].append(s_axi_vertex)
      logging.info(f'Constrain s_axi_control {v_name} to {board.getDDRPblock(CONTROL_S_AXI_LOCATION)}')

    if "Floorplan" in self.config:
      user_fp_json = self.config["Floorplan"]
      for region, v_name_group in user_fp_json.items():
        slot = slot_manager.createSlot(region)
        for v_name in v_name_group:
          user_constraint_s2v[slot].append(graph.getVertex(v_name))

    return user_constraint_s2v

  def runFloorplanning(
      self, 
      graph, 
      user_constraint_s2v, 
      slot_manager, 
      hls_prj_manager,
      top_rtl_parser,
      grouping_constraints=[]):

    grouping_constraints += top_rtl_parser.getStrictGroupingConstraints()
    
    floorplan = Floorplanner(
      graph, 
      user_constraint_s2v, 
      slot_manager=slot_manager, 
      total_usage=hls_prj_manager.getTotalArea(), 
      board=self.device_manager.getBoard(),
      user_max_usage_ratio=self.config['AreaUtilizationRatio'],
      grouping_constraints=grouping_constraints)
    
    if 'FloorplanMethod' in self.config:
      choice = self.config['FloorplanMethod']
      if choice == 'IterativeDivisionToFourCRs':
        floorplan.naiveFineGrainedFloorplan()
      elif choice == 'IterativeDivisionToHalfSLR':
        floorplan.coarseGrainedFloorplan()
      elif choice == 'IterativeDivisionToTwoCRs':
        floorplan.naiveTwoCRGranularityFloorplan()
      elif choice == 'EightWayDivisionToHalfSLR':
        floorplan.eightWayPartition()
      else:
        assert False, f'unsupported floorplan method: {choice}'
    else:
      floorplan.coarseGrainedFloorplan() # by default

    floorplan.printFloorplan()
    return floorplan

  def help(self):
    manual = {
      "Board" : "Choose between U250 and U280",
      "TopName" : "The name of the top-level function of the HLS design",
      "HLSProjectPath" : "Absolute path to the post-csynth HLS project",
      "HLSSolutionName" : "Name of the solution of the HLS project",
      "FloorplanMethod" : "Choose between IterativeDivisionToFourCRs and IterativeDivisionToHalfSLR",
      "AreaUtilizationRatio" : "Allowed resource usage in each slot",
      "Floorplan (optional)" : {
        "This is a comment" : "User could dictate the final location of given modules",
        "Region" : [
          "RTL module 1",
          "RTL module 2"
        ]
      },
      "LoggingLevel (optional)": "Choose between DEBUG, INFO, WARNING, CRITICAL, ERROR"
    }
    print(json.dumps(manual, indent=2))