def test_get_diagram_arguments(argstring, to_check): parser = ArgumentParser() arguments.add_topology_args(parser) arguments.add_cabinet_args(parser) add_diagram_arguments(parser) args = parser.parse_args(argstring.split()) (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) if "wire_thickness" in to_check: assert wire_thickness == to_check.pop("wire_thickness") if "focus" in to_check: assert focus == to_check.pop("focus") if "highlight" in to_check: assert highlights == to_check.pop("highlight") if "hide_labels" in to_check: assert hide_labels == to_check.pop("hide_labels") # Make sure none of the test-cases define something to test which isn't # tested... assert len(to_check) == 0
def main(args=None): parser = argparse.ArgumentParser( description="Start a proxy server to enable multiple interactive wiring " "sessions to interact with the same SpiNNaker machine.") arguments.add_version_args(parser) parser.add_argument("--host", "-H", type=str, default="", help="Host interface to listen on (default: any)") parser.add_argument("--port", "-p", type=int, default=DEFAULT_PORT, help="Port listen on (default: %(default)d)") parser.add_argument("--verbose", "-v", action="count", default=0, help="Increase verbosity.") 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 cabinet.num_cabinets == num_frames == 1: num_boards = 3 * w * h else: num_boards = cabinet.boards_per_frame # Set verbosity level if args.verbose == 1: logging.basicConfig(level=logging.INFO) elif args.verbose >= 2: logging.basicConfig(level=logging.DEBUG) # Create a BMP connection if len(bmp_ips) == 0: parser.error("All BMPs must be supplied using --bmp") bmp_controller = BMPController(bmp_ips) # Create a wiring probe wiring_probe = WiringProbe(bmp_controller, cabinet.num_cabinets, num_frames, num_boards) proxy_server = ProxyServer(bmp_controller, wiring_probe, args.host, args.port) print("Proxy server starting...") proxy_server.main() return 0
def test_get_cabinets_from_args_bad(argstring): parser = ArgumentParser() arguments.add_topology_args(parser) arguments.add_cabinet_args(parser) with pytest.raises(SystemExit): args = parser.parse_args(argstring.split()) cabinet = arguments.get_cabinets_from_args(parser, args)
def test_get_cabinets_from_args_num_cabinets_num_frames(argstring, num_cabinets, num_frames): # Ensure that the number of frames/cabinets required is worked out correctly. parser = ArgumentParser() arguments.add_topology_args(parser) arguments.add_cabinet_args(parser) args = parser.parse_args(argstring.split()) cabinet, actual_num_frames =\ arguments.get_cabinets_from_args(parser, args) actual_num_cabinets = cabinet.num_cabinets assert actual_num_cabinets == num_cabinets assert actual_num_frames == num_frames
def test_get_cabinets_from_args(with_topology, set_num_cabinets, set_num_frames): parser = ArgumentParser() if with_topology: arguments.add_topology_args(parser) arguments.add_cabinet_args(parser) unique_copy = unique.copy() del unique_copy["num_cabinets"] # Construct an argument string to set all possible arguments argstring = " ".join("--{} {}".format(name.replace("_", "-"), " ".join(map(str, vals)) if isinstance(vals, tuple) else str(vals)) for (name, vals) in iteritems(unique_copy)) if with_topology: argstring += " -n 3" if set_num_cabinets: argstring += " --num-cabinets 1" if set_num_frames: argstring += " --num-frames 1" args = parser.parse_args(argstring.split()) cabinet, num_frames = arguments.get_cabinets_from_args(parser, args) # Check all arguments propagated through to the cabinet for name, value in iteritems(unique_copy): if name in board_wire_offset_fields: cabinet.board_wire_offset[board_wire_offset_fields[name]] == value else: assert hasattr(cabinet, name) assert getattr(cabinet, name) == value # Check that the cabinet/frame count is correct if ((not with_topology and not set_num_frames) or (set_num_cabinets and not set_num_frames)): assert cabinet.num_cabinets == 1 assert num_frames == 2 else: assert cabinet.num_cabinets == 1 assert num_frames == 1
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