def test_remove_gaps(): c = coordinates.Cabinet o0 = "o0" o1 = "o1" o2 = "o2" # Empty case assert transforms.remove_gaps([]) == [] # Singletons (with and without need to move) assert transforms.remove_gaps([(o0, c(0, 0, 0))]) == [(o0, c(0, 0, 0))] assert transforms.remove_gaps([(o0, c(1, 2, 0))]) == [(o0, c(1, 2, 0))] assert transforms.remove_gaps([(o0, c(1, 2, 3))]) == [(o0, c(1, 2, 0))] # With and without gaps assert set(transforms.remove_gaps( [(o0, c(0,0,0)), (o1, c(0,0,1))])) ==\ set([(o0, c(0,0,0)), (o1, c(0,0,1))]) assert set(transforms.remove_gaps( [(o0, c(0,0,0)), (o1, c(0,0,2))])) ==\ set([(o0, c(0,0,0)), (o1, c(0,0,1))]) assert set(transforms.remove_gaps( [(o0, c(0,0,5)), (o1, c(0,0,2))])) ==\ set([(o0, c(0,0,1)), (o1, c(0,0,0))]) # Independent frames with restructuring needs assert set(transforms.remove_gaps( [(o0, c(1,0,5)), (o1, c(0,1,2))])) ==\ set([(o0, c(1,0,0)), (o1, c(0,1,0))]) assert set(transforms.remove_gaps( [(o0, c(0,0,0)), (o1, c(0,0,3)), (o2, c(1,0,3))])) ==\ set([(o0, c(0,0,0)), (o1, c(0,0,1)), (o2, c(1,0,0))])
def cabinetised_boards(cabinet): from spinner import transforms from spinner import utils # Generate folded system hex_boards, folded_boards = utils.folded_torus(10, 8, "shear", "rows", (2, 2)) # Divide into cabinets cabinetised_boards = transforms.cabinetise(folded_boards, cabinet.num_cabinets, cabinet.frames_per_cabinet, cabinet.boards_per_frame) cabinetised_boards = transforms.remove_gaps(cabinetised_boards) return cabinetised_boards
def main(args=None): parser = argparse.ArgumentParser( description="Generate visual maps from the SpiNNaker network topology to " "board locations.") arguments.add_version_args(parser) arguments.add_image_args(parser) arguments.add_topology_args(parser) arguments.add_cabinet_args(parser) # Process command-line arguments args = parser.parse_args(args) (w, h), transformation, uncrinkle_direction, folds =\ arguments.get_topology_from_args(parser, args) cabinet, num_frames = arguments.get_cabinets_from_args(parser, args) aspect_ratio = get_machine_map_aspect_ratio(w, h) output_filename, file_type, image_width, image_height =\ arguments.get_image_from_args(parser, args, aspect_ratio) # Generate folded system hex_boards, folded_boards = folded_torus(w, h, transformation, uncrinkle_direction, folds) # Divide into cabinets cabinetised_boards = transforms.cabinetise(folded_boards, cabinet.num_cabinets, num_frames, cabinet.boards_per_frame) cabinetised_boards = transforms.remove_gaps(cabinetised_boards) # Render the image Context = {"png": PNGContextManager, "pdf": PDFContextManager}[file_type] with Context(output_filename, image_width, image_height) as ctx: draw_machine_map(ctx, image_width, image_height, w, h, hex_boards, cabinetised_boards) return 0
def main(args=None): parser = argparse.ArgumentParser( description="Produce CSV listings of Ethernet connected chip physical and " "network positions.") arguments.add_version_args(parser) arguments.add_topology_args(parser) arguments.add_cabinet_args(parser) # Process command-line arguments args = parser.parse_args(args) (w, h), transformation, uncrinkle_direction, folds =\ arguments.get_topology_from_args(parser, args) cabinet, num_frames = arguments.get_cabinets_from_args(parser, args) # Generate folded system hex_boards, folded_boards = folded_torus(w, h, transformation, uncrinkle_direction, folds) # Divide into cabinets cabinetised_boards = transforms.cabinetise(folded_boards, cabinet.num_cabinets, num_frames, cabinet.boards_per_frame) cabinetised_boards = transforms.remove_gaps(cabinetised_boards) # Generate the output print("cabinet,frame,board,x,y") b2c = dict(cabinetised_boards) for board, hex_coord in sorted(hex_boards, key=(lambda v: topology.to_xy(v[1]))): x, y = topology.to_xy(topology.board_to_chip(hex_coord)) c, f, b = b2c[board] print(",".join(map(str, [c,f,b, x,y]))) return 0
def main(args=None): parser = argparse.ArgumentParser( description= "Produce CSV listings of Ethernet connected chip physical and " "network positions.") arguments.add_version_args(parser) arguments.add_topology_args(parser) arguments.add_cabinet_args(parser) # Process command-line arguments args = parser.parse_args(args) (w, h), transformation, uncrinkle_direction, folds =\ arguments.get_topology_from_args(parser, args) cabinet, num_frames = arguments.get_cabinets_from_args(parser, args) # Generate folded system hex_boards, folded_boards = folded_torus(w, h, transformation, uncrinkle_direction, folds) # Divide into cabinets cabinetised_boards = transforms.cabinetise(folded_boards, cabinet.num_cabinets, num_frames, cabinet.boards_per_frame) cabinetised_boards = transforms.remove_gaps(cabinetised_boards) # Generate the output print("cabinet,frame,board,x,y") b2c = dict(cabinetised_boards) for board, hex_coord in sorted(hex_boards, key=(lambda v: topology.to_xy(v[1]))): x, y = topology.to_xy(topology.board_to_chip(hex_coord)) c, f, b = b2c[board] print(",".join(map(str, [c, f, b, x, y]))) return 0
def main(args=None): parser = argparse.ArgumentParser( description="Generate illustrations of SpiNNaker machine wiring.") arguments.add_version_args(parser) arguments.add_image_args(parser) add_diagram_arguments(parser) arguments.add_topology_args(parser) arguments.add_cabinet_args(parser) arguments.add_subset_args(parser) # Process command-line arguments args = parser.parse_args(args) (w, h), transformation, uncrinkle_direction, folds =\ arguments.get_topology_from_args(parser, args) cabinet, num_frames =\ arguments.get_cabinets_from_args(parser, args) aspect_ratio, focus, wire_thickness, highlights, hide_labels =\ get_diagram_arguments(parser, args, w, h, cabinet, num_frames) output_filename, file_type, image_width, image_height =\ arguments.get_image_from_args(parser, args, aspect_ratio) wire_filter = arguments.get_subset_from_args(parser, args) # Generate folded system hex_boards, folded_boards = folded_torus(w, h, transformation, uncrinkle_direction, folds) # Divide into cabinets cabinetised_boards = transforms.cabinetise(folded_boards, cabinet.num_cabinets, num_frames, cabinet.boards_per_frame) cabinetised_boards = transforms.remove_gaps(cabinetised_boards) # Set up diagram md = MachineDiagram(cabinet) # Create lookup from cabinet coord to chip x/y to enable labelling of boards b2cab = dict(cabinetised_boards) b2chip = dict((b, topology.to_xy(topology.board_to_chip(c))) for b, c in hex_boards) cab2chip = dict((b2cab[b], b2chip[b]) for b, c in cabinetised_boards) # Add labels if not hide_labels: for cabinet_num in range(cabinet.num_cabinets): md.add_label(cabinet_num, cabinet_num) for frame_num in range(cabinet.frames_per_cabinet): md.add_label(frame_num, cabinet_num, frame_num) for board_num in range(cabinet.boards_per_frame): # Only label boards which are actually part of the system xy = cab2chip.get((cabinet_num, frame_num, board_num), None) if xy is not None: md.add_label("{} ({},{})".format(board_num, xy.x, xy.y), cabinet_num, frame_num, board_num) for socket in Direction: name = "".join(w[0] for w in socket.name.split("_")).upper() md.add_label(name, cabinet_num, frame_num, board_num, socket, rgba=(1.0, 1.0, 1.0, 0.7)) # Add highlights for highlight in highlights: md.add_highlight(*highlight, width=cabinet.board_dimensions.x/3.0) # Add wires wire_thickness_m = { "thick" : cabinet.board_dimensions.x / 5.0, "normal" : cabinet.board_dimensions.x / 10.0, "thin" : cabinet.board_dimensions.x / 20.0, }[wire_thickness] b2c = dict(cabinetised_boards) for direction in [Direction.north, Direction.west, Direction.north_east]: for b, c in cabinetised_boards: ob = b.follow_wire(direction) oc = b2c[ob] src = (c.cabinet, c.frame, c.board, direction) dst = (oc.cabinet, oc.frame, oc.board, direction.opposite) if wire_filter((src, dst)): md.add_wire(src, dst, width=wire_thickness_m) # Render the image Context = {"png": PNGContextManager, "pdf": PDFContextManager}[file_type] with Context(output_filename, image_width, image_height) as ctx: md.draw(ctx, image_width, image_height, *(((list(focus) + [None]*3)[:3])*2)) return 0
def main(args=None): parser = argparse.ArgumentParser( description="Print basic wiring statistics for a specified " " configuration of boards.") arguments.add_version_args(parser) arguments.add_topology_args(parser) arguments.add_histogram_args(parser) arguments.add_wire_length_args(parser) arguments.add_cabinet_args(parser) # Process and display command-line arguments args = parser.parse_args(args) (w, h), transformation, uncrinkle_direction, folds =\ arguments.get_topology_from_args(parser, args) histogram_bins = arguments.get_histogram_from_args(parser, args) wire_lengths, min_slack =\ arguments.get_wire_lengths_from_args(parser, args) cabinet, num_frames = arguments.get_cabinets_from_args(parser, args) print(heading("Wiring Statistics", 1)) print(heading("Folding Parameters", 2)) print(table([["Parameter", "Value", "Unit"], ["Number of boards", 3 * w * h, ""], ["System dimensions", "{}x{}".format(w, h), "triads"], ["Transformation", transformation, ""], ["Uncrinkle Direction", uncrinkle_direction, ""], ["Folds", "{}x{}".format(*folds), "pieces"], ["Number of cabinets", cabinet.num_cabinets, ""], ["Number of frames-per-cabinet", num_frames, ""], ["Number of boards-per-frame", cabinet.boards_per_frame, ""], ])) # Generate folded system and report wire-lengths after folding hex_boards, folded_boards = folded_torus(w, h, transformation, uncrinkle_direction, folds) print(heading("Non-cabinetised measurements", 2)) print(avg_wire_length_table(folded_boards, "boards")) # Divide into cabinets and report crossings cabinetised_boards = transforms.cabinetise(folded_boards, cabinet.num_cabinets, num_frames, cabinet.boards_per_frame) cabinetised_boards = transforms.remove_gaps(cabinetised_boards) print(heading("Inter-cabinet/Inter-frame wiring", 2)) print(wire_counts_table(cabinetised_boards)) # Map to real, physical cabinets and measure wire lengths physical_boards = transforms.cabinet_to_physical(cabinetised_boards, cabinet) print(heading("Cabinetised measurements", 2)) print("All wire lengths described in this section do not include any slack.\n") print(avg_wire_length_table(physical_boards, "meters", cabinet.board_wire_offset)) # Generate a histogram of wire lengths print(heading("Wire length histogram", 2)) print("Wire lengths are selected which include at least {} meters " "of slack.\n".format(min_slack)) print(wire_length_table(physical_boards, wire_lengths if wire_lengths else histogram_bins, min_slack, cabinet.board_wire_offset)) return 0
def main(args=None): parser = argparse.ArgumentParser( description= "Textually enumerate every connection required in a machine.") parser.add_argument("--sort-by", "-s", choices=["installation-order", "board", "wire-length"], default="board", help="Specifies the order the connections should be " "listed in the file: installation-order sorts in " "the most sensible order for installation, " "board lists wires on a board-by-board basis, " "wire-length lists in order of wire length.") arguments.add_version_args(parser) arguments.add_topology_args(parser) arguments.add_cabinet_args(parser) arguments.add_wire_length_args(parser) # Process command-line arguments args = parser.parse_args(args) (w, h), transformation, uncrinkle_direction, folds =\ arguments.get_topology_from_args(parser, args) cabinet, num_frames = arguments.get_cabinets_from_args(parser, args) wire_lengths, min_slack = arguments.get_wire_lengths_from_args( parser, args, mandatory=True) # Generate folded system hex_boards, folded_boards = folded_torus(w, h, transformation, uncrinkle_direction, folds) # Divide into cabinets cabinetised_boards = transforms.cabinetise(folded_boards, cabinet.num_cabinets, num_frames, cabinet.boards_per_frame) cabinetised_boards = transforms.remove_gaps(cabinetised_boards) physical_boards = transforms.cabinet_to_physical(cabinetised_boards, cabinet) # Generate wiring plan wires_between_boards, wires_between_frames, wires_between_cabinets =\ generate_wiring_plan(cabinetised_boards, physical_boards, cabinet.board_wire_offset, wire_lengths, min_slack) flat_wiring_plan = flatten_wiring_plan(wires_between_boards, wires_between_frames, wires_between_cabinets, cabinet.board_wire_offset) # Convert wiring plan into cabinet coordinates b2c = dict(cabinetised_boards) wires = [] for ((src_board, src_direction), (dst_board, dst_direction), wire_length) \ in flat_wiring_plan: sc, sf, sb = b2c[src_board] dc, df, db = b2c[dst_board] wires.append(((sc, sf, sb, src_direction), (dc, df, db, dst_direction), wire_length, src_board, dst_board)) b2p = dict(physical_boards) # Order as requested on the command-line if args.sort_by == "board": wires = sorted(wires) elif args.sort_by == "wire-length": wires = sorted(wires, key=(lambda w: (w[2], w[:2]))) elif args.sort_by == "installation-order": # pragma: no branch pass # List is initially in assembly order print("C F B Socket C F B Socket Length") print("-- -- -- ---------- -- -- -- ---------- ------") for ((sc, sf, sb, src_direction), (dc, df, db, dst_direction), wire_length, src_board, dst_board) in wires: print("{:2d} {:2d} {:2d} {:10s} {:2d} {:2d} {:2d} {:10s} {:0.2f}". format(sc, sf, sb, src_direction.name.replace("_", " "), dc, df, db, dst_direction.name.replace("_", " "), wire_length)) return 0
def main(args=None): parser = argparse.ArgumentParser( description= "Interactively guide the user through the process of wiring up a " "SpiNNaker machine.") arguments.add_version_args(parser) parser.add_argument("--no-tts", action="store_true", default=False, help="disable text-to-speech announcements of wiring " "steps") parser.add_argument("--no-auto-advance", action="store_true", default=False, help="disable auto-advancing through wiring steps") parser.add_argument("--fix", action="store_true", default=False, help="detect errors in existing wiring and just show " "corrective steps") parser.add_argument( "--log", type=str, metavar="LOGFILE", help="record the times at which each cable is installed") arguments.add_topology_args(parser) arguments.add_cabinet_args(parser) arguments.add_wire_length_args(parser) arguments.add_bmp_args(parser) arguments.add_proxy_args(parser) arguments.add_subset_args(parser) # Process command-line arguments args = parser.parse_args(args) (w, h), transformation, uncrinkle_direction, folds =\ arguments.get_topology_from_args(parser, args) cabinet, num_frames = arguments.get_cabinets_from_args(parser, args) wire_lengths, min_slack = arguments.get_wire_lengths_from_args( parser, args, mandatory=True) bmp_ips = arguments.get_bmps_from_args(parser, args, cabinet.num_cabinets, num_frames) proxy_host_port = arguments.get_proxy_from_args(parser, args) wire_filter = arguments.get_subset_from_args(parser, args) if cabinet.num_cabinets == num_frames == 1: num_boards = 3 * w * h else: num_boards = cabinet.boards_per_frame # Generate folded system hex_boards, folded_boards = folded_torus(w, h, transformation, uncrinkle_direction, folds) # Divide into cabinets cabinetised_boards = transforms.cabinetise(folded_boards, cabinet.num_cabinets, num_frames, cabinet.boards_per_frame) cabinetised_boards = transforms.remove_gaps(cabinetised_boards) physical_boards = transforms.cabinet_to_physical(cabinetised_boards, cabinet) # Focus on only the boards which are part of the system if cabinet.num_cabinets > 1: focus = [slice(0, cabinet.num_cabinets)] elif num_frames > 1: focus = [0, slice(0, num_frames)] else: focus = [0, 0, slice(0, w * h * 3)] # Generate wiring plan wires_between_boards, wires_between_frames, wires_between_cabinets =\ generate_wiring_plan(cabinetised_boards, physical_boards, cabinet.board_wire_offset, wire_lengths, min_slack) flat_wiring_plan = flatten_wiring_plan(wires_between_boards, wires_between_frames, wires_between_cabinets, cabinet.board_wire_offset) # Create a BMP connection/wiring probe or connect to a proxy if proxy_host_port is None: if len(bmp_ips) == 0: if args.fix: parser.error( "--fix requires that all BMPs be listed with --bmp") bmp_controller = None wiring_probe = None else: bmp_controller = BMPController(bmp_ips) # Create a wiring probe if bmp_controller is not None and (not args.no_auto_advance or args.fix): wiring_probe = WiringProbe(bmp_controller, cabinet.num_cabinets, num_frames, num_boards) else: # Fix is not supported since the proxy client does not recreate the # discover_wires method of WiringProbe. if args.fix: parser.error("--fix cannot be used with --proxy") # The proxy object provides a get_link_target and set_led method compatible # with those provided by bmp_controller and wiring_probe. Since these are # the only methods used, we use the proxy client object in place of # bmp_controller and wiring_probe. bmp_controller = wiring_probe = ProxyClient(*proxy_host_port) # Create a TimingLogger if required if args.log: if os.path.isfile(args.log): logfile = open(args.log, "a") add_header = False else: logfile = open(args.log, "w") add_header = True timing_logger = TimingLogger(logfile, add_header) else: logfile = None timing_logger = None # Convert wiring plan into cabinet coordinates b2c = dict(cabinetised_boards) wires = [] for ((src_board, src_direction), (dst_board, dst_direction), wire_length) \ in flat_wiring_plan: sc, sf, sb = b2c[src_board] dc, df, db = b2c[dst_board] wires.append(((sc, sf, sb, src_direction), (dc, df, db, dst_direction), wire_length)) # Filter wires according to user-specified rules wires = list(filter(wire_filter, wires)) if len(wires) == 0: parser.error("--subset selects no wires") if not args.fix: # If running normally, just run through the full set of wires wiring_plan = wires else: # If running in fix mode, generate a list of fixes to make correct_wires = set((src, dst) for src, dst, length in wires) actual_wires = set(wiring_probe.discover_wires()) to_remove = actual_wires - correct_wires to_add = correct_wires - actual_wires # Remove all bad wires first, then re-add good ones (note ordering now is # just reset to cabinets right-to-left, frames top-to-bottom and boards # left-to-right). wiring_plan = [(src, dst, None) for src, dst in sorted(to_remove)] for src, dst, length in wires: if (src, dst) in to_add: wiring_plan.append((src, dst, length)) if len(wiring_plan) == 0: print("No corrections required.") return 0 # Intialise the GUI and launch the mainloop ui = InteractiveWiringGuide(cabinet=cabinet, wire_lengths=wire_lengths, wires=wiring_plan, bmp_controller=bmp_controller, use_tts=not args.no_tts, focus=focus, wiring_probe=wiring_probe, auto_advance=not args.no_auto_advance, timing_logger=timing_logger) ui.mainloop() if logfile is not None: logfile.close() return 0
def main(args=None): parser = argparse.ArgumentParser( description="Interactively guide the user through the process of wiring up a " "SpiNNaker machine.") arguments.add_version_args(parser) parser.add_argument("--no-tts", action="store_true", default=False, help="disable text-to-speech announcements of wiring " "steps") parser.add_argument("--no-auto-advance", action="store_true", default=False, help="disable auto-advancing through wiring steps") parser.add_argument("--fix", action="store_true", default=False, help="detect errors in existing wiring and just show " "corrective steps") parser.add_argument("--log", type=str, metavar="LOGFILE", help="record the times at which each cable is installed") arguments.add_topology_args(parser) arguments.add_cabinet_args(parser) arguments.add_wire_length_args(parser) arguments.add_bmp_args(parser) arguments.add_proxy_args(parser) arguments.add_subset_args(parser) # Process command-line arguments args = parser.parse_args(args) (w, h), transformation, uncrinkle_direction, folds =\ arguments.get_topology_from_args(parser, args) cabinet, num_frames = arguments.get_cabinets_from_args(parser, args) wire_lengths, min_slack = arguments.get_wire_lengths_from_args( parser, args, mandatory=True) bmp_ips = arguments.get_bmps_from_args(parser, args, cabinet.num_cabinets, num_frames) proxy_host_port = arguments.get_proxy_from_args(parser, args) wire_filter = arguments.get_subset_from_args(parser, args) if cabinet.num_cabinets == num_frames == 1: num_boards = 3 * w * h else: num_boards = cabinet.boards_per_frame # Generate folded system hex_boards, folded_boards = folded_torus(w, h, transformation, uncrinkle_direction, folds) # Divide into cabinets cabinetised_boards = transforms.cabinetise(folded_boards, cabinet.num_cabinets, num_frames, cabinet.boards_per_frame) cabinetised_boards = transforms.remove_gaps(cabinetised_boards) physical_boards = transforms.cabinet_to_physical(cabinetised_boards, cabinet) # Focus on only the boards which are part of the system if cabinet.num_cabinets > 1: focus = [slice(0, cabinet.num_cabinets)] elif num_frames > 1: focus = [0, slice(0, num_frames)] else: focus = [0, 0, slice(0, w*h*3)] # Generate wiring plan wires_between_boards, wires_between_frames, wires_between_cabinets =\ generate_wiring_plan(cabinetised_boards, physical_boards, cabinet.board_wire_offset, wire_lengths, min_slack) flat_wiring_plan = flatten_wiring_plan(wires_between_boards, wires_between_frames, wires_between_cabinets, cabinet.board_wire_offset) # Create a BMP connection/wiring probe or connect to a proxy if proxy_host_port is None: if len(bmp_ips) == 0: if args.fix: parser.error("--fix requires that all BMPs be listed with --bmp") bmp_controller = None wiring_probe = None else: bmp_controller = BMPController(bmp_ips) # Create a wiring probe if bmp_controller is not None and (not args.no_auto_advance or args.fix): wiring_probe = WiringProbe(bmp_controller, cabinet.num_cabinets, num_frames, num_boards) else: # Fix is not supported since the proxy client does not recreate the # discover_wires method of WiringProbe. if args.fix: parser.error("--fix cannot be used with --proxy") # The proxy object provides a get_link_target and set_led method compatible # with those provided by bmp_controller and wiring_probe. Since these are # the only methods used, we use the proxy client object in place of # bmp_controller and wiring_probe. bmp_controller = wiring_probe = ProxyClient(*proxy_host_port) # Create a TimingLogger if required if args.log: if os.path.isfile(args.log): logfile = open(args.log, "a") add_header = False else: logfile = open(args.log, "w") add_header = True timing_logger = TimingLogger(logfile, add_header) else: logfile = None timing_logger = None # Convert wiring plan into cabinet coordinates b2c = dict(cabinetised_boards) wires = [] for ((src_board, src_direction), (dst_board, dst_direction), wire_length) \ in flat_wiring_plan: sc, sf, sb = b2c[src_board] dc, df, db = b2c[dst_board] wires.append(((sc, sf, sb, src_direction), (dc, df, db, dst_direction), wire_length)) # Filter wires according to user-specified rules wires = list(filter(wire_filter, wires)) if len(wires) == 0: parser.error("--subset selects no wires") if not args.fix: # If running normally, just run through the full set of wires wiring_plan = wires else: # If running in fix mode, generate a list of fixes to make correct_wires = set((src, dst) for src, dst, length in wires) actual_wires = set(wiring_probe.discover_wires()) to_remove = actual_wires - correct_wires to_add = correct_wires - actual_wires # Remove all bad wires first, then re-add good ones (note ordering now is # just reset to cabinets right-to-left, frames top-to-bottom and boards # left-to-right). wiring_plan = [(src, dst, None) for src, dst in sorted(to_remove)] for src, dst, length in wires: if (src, dst) in to_add: wiring_plan.append((src, dst, length)) if len(wiring_plan) == 0: print("No corrections required.") return 0 # Intialise the GUI and launch the mainloop ui = InteractiveWiringGuide(cabinet=cabinet, wire_lengths=wire_lengths, wires=wiring_plan, bmp_controller=bmp_controller, use_tts=not args.no_tts, focus=focus, wiring_probe=wiring_probe, auto_advance=not args.no_auto_advance, timing_logger=timing_logger) ui.mainloop() if logfile is not None: logfile.close() return 0
def main(args=None): parser = argparse.ArgumentParser( description="Validate the wiring of a SpiNNaker system.") arguments.add_version_args(parser) parser.add_argument("--verbose", "-v", action="store_true", default=False, help="list all incorrect and missing wires") arguments.add_topology_args(parser) arguments.add_cabinet_args(parser) arguments.add_bmp_args(parser) # Process command-line arguments args = parser.parse_args(args) (w, h), transformation, uncrinkle_direction, folds =\ arguments.get_topology_from_args(parser, args) cabinet, num_frames = arguments.get_cabinets_from_args(parser, args) bmp_ips = arguments.get_bmps_from_args(parser, args, cabinet.num_cabinets, num_frames) if len(bmp_ips) == 0: parser.error("BMP host names must be provided for every frame.") # Generate folded system hex_boards, folded_boards = folded_torus(w, h, transformation, uncrinkle_direction, folds) # Divide into cabinets cabinetised_boards = transforms.cabinetise(folded_boards, cabinet.num_cabinets, num_frames, cabinet.boards_per_frame) cabinetised_boards = transforms.remove_gaps(cabinetised_boards) # Generate list of wires wires = plan.enumerate_wires(cabinetised_boards) # Set up the wiring probe bmp_controller = BMPController(bmp_ips) if cabinet.num_cabinets == 1 and num_frames == 1: num_boards = 3 * w * h else: num_boards = cabinet.boards_per_frame wiring_probe = probe.WiringProbe(bmp_controller, cabinet.num_cabinets, num_frames, num_boards) # Check for the presence of every wire missing = [] b2c = dict(cabinetised_boards) for ((src_board, src_direction), (dst_board, dst_direction)) in wires: src = tuple(list(b2c[src_board]) + [src_direction]) dst = tuple(list(b2c[dst_board]) + [dst_direction]) actual_dst = wiring_probe.get_link_target(*src) actual_src = wiring_probe.get_link_target(*dst) if actual_dst != dst or actual_src != src: missing.append((src, dst)) if missing: sys.stderr.write("{} wires missing or erroneously connected.\n".format( len(missing), len(wires))) if args.verbose: for src, dst in missing: print("C:{} F:{} B:{} {} <--> C:{} F:{} B:{} {}".format( src[0], src[1], src[2], src[3].name.replace("_", " "), dst[0], dst[1], dst[2], dst[3].name.replace("_", " "))) else: print("Add --verbose for a complete list.") return -1 else: sys.stderr.write("All {} wires correctly connected.\n".format(len(wires))) return 0