def fork_bus()

in design_utils/des_handler.py [0:0]


    def fork_bus(self, ex_dp, block, migrant_tasks):

        self.pruned_one = False
        ex_dp.hardware_graph.update_graph(block_to_prime_with=block)
        if config.VIS_GR_PER_GEN: vis_hardware(ex_dp)

        pe_neighs = [neigh for neigh in block.neighs if neigh.type == "pe"]   # find pe neighbours
        mem_neighs = [neigh for neigh in block.neighs if neigh.type == "mem"]  # find memory neighbours

        pe_forked = False
        pe_good_to_go = False
        mem_forked = False
        mem_good_to_go = False

        # first check forkability of the neighbouring pe and mem (before attempting to fork either)
        # if either (mem, pe) needs to be forked
        if len(pe_neighs) == 1 or len(mem_neighs) == 1:
            pe_forkability = True
            mem_forkability = True
            # see if you can fork
            if len(pe_neighs) == 1:
                for task_ in migrant_tasks:
                    if not (self.block_forkable(ex_dp, pe_neighs[0]) or self.task_in_block(block,
                                                                                       task_)):
                        pe_forkability = False
                        break
            # see if you can fork
            if len(mem_neighs) == 1:
                for task_ in migrant_tasks:
                    if not (self.block_forkable(ex_dp, mem_neighs[0]) or self.task_in_block(mem_neighs[0],
                                                                                        task_)):
                        mem_forkability = False

            if not (mem_forkability and pe_forkability):
                return False,""

        # now fork the neighbours if necessary
        if len(pe_neighs) == 1:
            pe_forked,_ = self.fork_block(ex_dp,  pe_neighs[0], migrant_tasks)
            ex_dp.hardware_graph.update_graph(block_to_prime_with=block)
        else:
            pe_good_to_go = True

        if len(mem_neighs) == 1:
            mem_forked,_= self.fork_block(ex_dp,  mem_neighs[0], migrant_tasks)
            ex_dp.hardware_graph.update_graph(block_to_prime_with=block)
        else:
            mem_good_to_go = True

        if not((pe_forked or pe_good_to_go) and (mem_forked or mem_good_to_go)):
            return False, ""

        # allocate and attach a similar bus
        alloc_block = self.allocate_similar_block(block, [])



        # at the moment, we don't support the smarter version of attaching the blocks for buses
        if config.RUN_VERIFICATION_PER_GEN or config.RUN_VERIFICATION_PER_IMPROVMENT or config.RUN_VERIFICATION_PER_NEW_CONFIG:
            self.attach_alloc_block(ex_dp, block, alloc_block)
            ex_dp.hardware_graph.update_graph(block_to_prime_with=block)
            #if config.VIS_GR_PER_GEN: vis_hardware(ex_dp)

            # prune blocks (memory and processing elements) from the previous pus
            self.prune(ex_dp, block, alloc_block)
            block.connect(alloc_block)
        else:
            self.attach_alloc_block_to_bus(ex_dp, block, alloc_block, migrant_tasks)


        ex_dp.hardware_graph.update_graph(block_to_prime_with=block)
        return True, alloc_block