def visualize_board(cgra_file): from arch import parse_cgra color_index = "imopr" board_meta = parse_cgra(cgra_file)["CGRA"] board_layout = board_meta[0] scale = 30 board_info = board_meta[-1] height, width = board_info["height"], board_info["width"] im, draw = draw_board(width, height, scale) for y in range(height): for x in range(width): blk_type = board_layout[y][x] if blk_type is not None: index = color_index.index(blk_type) color = color_palette[index] draw_cell(draw, (x, y), color, scale) plt.imshow(im) plt.show() basename = os.path.basename(cgra_file) design_name, ext = os.path.splitext(basename) file_dir = os.path.dirname(os.path.realpath(__file__)) output_dir = os.path.join(file_dir, "figures") if os.path.isdir(output_dir): output_png = design_name + "_cgra.png" output_path = os.path.join(output_dir, output_png) im.save(output_path) print("Image saved to", output_path)
def main(): if len(sys.argv) == 2: cgra_info = sys.argv[1] visualize_board(cgra_info) return if len(sys.argv) != 4: print("[Usage]:", sys.argv[0], "<cgra_info>", "[<design.packed>", "<design.place|design.route>]", file=sys.stderr) exit(1) cgra_info = sys.argv[1] packed_file = sys.argv[2] input_file = sys.argv[3] basename = os.path.basename(input_file) design_name, ext = os.path.splitext(basename) from arch import parse_cgra from arch import load_packed_file _, _, _, changed_pe = load_packed_file(packed_file) fold_reg = len(changed_pe) == 0 board_meta = parse_cgra(cgra_info, fold_reg=fold_reg)["CGRA"] if ext == ".place": from arch import parse_placement board_pos, _ = parse_placement(input_file) visualize_placement_cgra(board_meta, board_pos, design_name, changed_pe) elif ext == ".route": from arch import parse_routing_result routing_result = parse_routing_result(input_file) visualize_routing(cgra_info, board_meta, packed_file, routing_result, fold_reg=fold_reg)
def visualize_board(cgra_file): from arch import parse_cgra color_index = "imoprI" layout = parse_cgra(cgra_file)["CGRA"] scale = 30 height, width = layout.height(), layout.width() im, draw = draw_board(width, height, scale) for y in range(height): for x in range(width): blk_type = layout.get_blk_type(x, y) if blk_type is not None: index = color_index.index(blk_type) color = color_palette[index % len(color_palette)] draw_cell(draw, (x, y), color, scale) im.show() basename = os.path.basename(cgra_file) design_name, ext = os.path.splitext(basename) file_dir = os.path.dirname(os.path.realpath(__file__)) output_dir = os.path.join(file_dir, "figures") if os.path.isdir(output_dir): output_png = design_name + "_cgra.png" output_path = os.path.join(output_dir, output_png) im.save(output_path) print("Image saved to", output_path)
def main(): parser = ArgumentParser("CGRA Router") parser.add_argument("-i", "--input", help="Packed netlist file, " + "e.g. harris.packed", required=True, action="store", dest="packed_filename") parser.add_argument("-o", "--output", help="Routing result, " + "e.g. harris.route", required=True, action="store", dest="route_file") parser.add_argument("-c", "--cgra", help="CGRA architecture file", required=True, action="store", dest="arch_filename") parser.add_argument("-p", "--placement", help="Placement file", required=True, action="store", dest="placement_filename") parser.add_argument("--no-reg-fold", help="If set, the placer will treat " + "registers as PE tiles", action="store_true", required=False, dest="no_reg_fold", default=False) parser.add_argument("--no-vis", help="If set, the router won't show " + "visualization result for routing", action="store_true", required=False, dest="no_vis", default=False) args = parser.parse_args() arch_filename = args.arch_filename packed_filename = args.packed_filename route_file = args.route_file vis_opt = not args.no_vis fold_reg = not args.no_reg_fold placement_filename = args.placement_filename meta = parse_cgra(arch_filename, fold_reg=fold_reg)["CGRA"] r = Router(arch_filename, meta, packed_filename, placement_filename) r.route() if vis_opt: r.vis_routing_resource() # r.compute_stats() save_routing_result(r.route_result, route_file)
def main(): if len(sys.argv) != 4: print("Usage:", sys.argv[0], "<cgra_info.txt>", "<netlist.json>", "<netlist.route>", file=sys.stderr) exit(1) cgra_file = sys.argv[1] netlist = sys.argv[2] route_file = sys.argv[3] packed_file = route_file.replace(".route", ".packed") placement_file = route_file.replace(".route", ".place") board_layout = parse_cgra(cgra_file)["CGRA"] routing_result = parse_routing(route_file) placement, _ = parse_placement(placement_file) if hasattr(sys.stdout, 'isatty') and sys.stdout.isatty(): meta = os.popen('stty size', 'r').read().split() cols = int(meta[-1]) cols = int(cols) scale = cols - 15 else: scale = 68 cols = 80 print("-" * cols) print("Area Usage:") usage = compute_area_usage(placement, board_layout) for entry in usage: percentage = usage[entry][0] / usage[entry][1] * 100 num_bar = max(int(percentage / 100 * scale) - 2, 1) print("{0:4s} {1} {2} {3:.2f}%".format(entry.upper(), num_bar * '█', ' ' * (scale - num_bar - 2), percentage)) print("-" * cols) net_wire = compute_total_wire(routing_result) total_wire = sum([net_wire[x] for x in net_wire]) print("Total wire:", total_wire) # timing removed for future development print("-" * cols) r = parse_routing_resource(cgra_file) routing_resource = build_routing_resource(r) resource_usage = compute_routing_usage(routing_result, routing_resource) for bus in resource_usage: print("BUS:", bus) for track in resource_usage[bus]: total, left = resource_usage[bus][track] percentage = (total - left) / total * 100 num_bar = int(percentage / 100 * scale) print("TRACK {0} {1} {2} {3:.2f}%".format( track, num_bar * '█', ' ' * (scale - num_bar - 5), percentage))
def main(): parser = ArgumentParser("CGRA graph creation") parser.add_argument("-i", "--input", help="CGRA info file", required=True, action="store", dest="cgra_filename") parser.add_argument("-o", "--output", help="Graph output folder for " "cyclone router", required=True, action="store", dest="graph_dirname") parser.add_argument("-O", "--override", help="Override the existing one " "if the output file exists", required=False, default=False, action="store_true", dest="override_graph") args = parser.parse_args() cgra_filename = args.cgra_filename graph_dirname = args.graph_dirname override_graph = args.override_graph # if the directory doesn't exit, create one if not os.path.isdir(graph_dirname): print("creating folder", graph_dirname) os.mkdir(graph_dirname) g_16_filename = os.path.join(graph_dirname, GRAPH_16) g_1_filename = os.path.join(graph_dirname, GRAPH_1) if os.path.isfile(g_16_filename) and not override_graph: print("found existing", g_16_filename, "skipped.") exit(0) elif os.path.isfile(g_16_filename): print("override existing graph file") layout = parse_cgra(cgra_filename)["CGRA"] raw_routing_resource = parse_routing_resource(cgra_filename) routing_resource = build_routing_resource(raw_routing_resource) g_1, g_16 = build_routing_graph(routing_resource, layout) pycyclone.io.dump_routing_graph(g_16, g_16_filename) pycyclone.io.dump_routing_graph(g_1, g_1_filename) print("graph saved to", g_1_filename, g_16_filename)
def generate_bitstream(board_filename, netlist_filename, packed_filename, placement_filename, routing_filename, output_filename, io_json, fold_reg=True): netlists, folded_blocks, id_to_name, changed_pe =\ load_packed_file(packed_filename) g = build_graph(netlists) board_meta = arch.parse_cgra(board_filename, True)["CGRA"] placement, _ = parse_placement(placement_filename) route_result = parse_routing_result(routing_filename) tile_mapping = board_meta[-1] board_layout = board_meta[0] io_pad_name = board_meta[-2]["io_pad_name"] io_pad_bit = board_meta[-2]["io_pad_bit"] io16_tile = board_meta[-2]["io16_tile"] connections, instances = read_netlist_json(netlist_filename) output_string = "" # TODO: refactor this name_to_id = {} for blk_id in id_to_name: name_to_id[id_to_name[blk_id]] = blk_id # build PE tiles types pe_tiles = {} type_str = "mpir" for name in instances: instance = instances[name] blk_id = name_to_id[name] if blk_id in folded_blocks: continue blk_id = name_to_id[name] # it might be absorbed already if blk_id not in g.nodes(): continue # it has to be a PE tile assert(blk_id[0] in type_str) pos = placement[blk_id] tile = tile_mapping[pos] # find out the PE type tile_op, print_order = get_tile_op(instance, blk_id, changed_pe) if tile_op is None: continue pins = get_tile_pins(blk_id, tile_op, folded_blocks, instances, changed_pe, id_to_name, connections) # parse pins from the packing pe_tiles[blk_id] = (tile, tile_op, pins, print_order) tab = "\t" * 6 # generate tile mapping # sort them for pretty printing pe_keys = list(pe_tiles.keys()) pe_keys.sort(key=lambda x: int(pe_tiles[x][0])) pe_keys.sort(key=lambda x: pe_tiles[x][-1]) output_string += "# PLACEMENT\n" for blk_id in pe_keys: tile, op, pins, _ = pe_tiles[blk_id] if "mem" in op: output_string += "Tx{:04X}_{}{}#{}\n".format(tile, op, tab, id_to_name[blk_id]) else: output_string += "Tx{:04X}_{}({}){}# {}\n".format(tile, op, ",".join(pins), tab, id_to_name[ blk_id]) # IO info io_pad_info, io_strings = generate_io(id_to_name, io16_tile, io_pad_bit, io_pad_name, placement, tile_mapping) assert len(io_strings) > 0 output_string += "\n\n#IO\n" output_string += "\n".join(io_strings) output_string += "\n\n#ROUTING\n" net_id_list = list(route_result.keys()) net_id_list.sort(key=lambda x: int(x[1:])) for net_id in net_id_list: path = route_result[net_id] output_string += "\n# net id: {}\n".format(net_id) netlist = netlists[net_id] for p in netlist: output_string += "# {}: {}::{}\n".format(p[0], id_to_name[p[0]], p[1]) for index, entry in enumerate(path): path_type = entry[0] if index == 0: assert (path_type == "src") s = handle_src(entry[1], entry[2], tile_mapping, board_layout, fold_reg=fold_reg) output_string += s else: if path_type == "src": s = handle_src(entry[1], entry[2], tile_mapping, board_layout, fold_reg=fold_reg) output_string += s elif path_type == "link": track_out = entry[2][0] assert (track_out[1] == 1) track_in = find_track_in(entry[1][0], track_out, path[:index + 1]) s = handle_link(entry[1], entry[2], track_in, tile_mapping, board_layout) if s not in output_string: # Keyi: # sometimes it will produce legal duplicated routing # tracks. output_string += s elif path_type == "sink": if len(entry) == 4: track_out = entry[-2] assert len(track_out) == 4 and track_out[1] == 1 else: assert len(entry) == 3 track_out = None track_in = find_track_in(entry[-1][0], track_out, path[:index + 1]) s = handle_sink_entry(entry, track_in, tile_mapping, board_layout, folded_blocks, placement, fold_reg=fold_reg) output_string += s else: raise Exception("Unknown stage: " + path_type) output_string += "\n" with open(output_filename, "w+") as f: f.write(output_string) with open(io_json, "w+") as f: json.dump(io_pad_info, f, indent=2, separators=(',', ': '))
def main(): # only the main thread needs it import numpy as np from argparse import ArgumentParser from arch.parser import parse_emb from arch import make_board, parse_cgra, generate_place_on_board, parse_fpga from arch.cgra import place_special_blocks, save_placement, prune_netlist from arch.cgra_packer import load_packed_file from arch.fpga import load_packed_fpga_netlist from arch import mock_board_meta from visualize import visualize_placement_cgra parser = ArgumentParser("CGRA Placer") parser.add_argument("-i", "--input", help="Packed netlist file, " + "e.g. harris.packed", required=True, action="store", dest="packed_filename") parser.add_argument("-e", "--embedding", help="Netlist embedding file, " + "e.g. harris.emb", required=True, action="store", dest="netlist_embedding") parser.add_argument("-o", "--output", help="Placement result, " + "e.g. harris.place", required=True, action="store", dest="placement_filename") parser.add_argument("-c", "--cgra", help="CGRA architecture file", action="store", dest="cgra_arch", default="") parser.add_argument("--no-reg-fold", help="If set, the placer will treat " + "registers as PE tiles", action="store_true", required=False, dest="no_reg_fold", default=False) parser.add_argument("--no-vis", help="If set, the placer won't show " + "visualization result for placement", action="store_true", required=False, dest="no_vis", default=False) parser.add_argument("-s", "--seed", help="Seed for placement. " + "default is 0", type=int, default=0, required=False, action="store", dest="seed") parser.add_argument("-a", "--aws", help="Serverless configuration for " + "detailed placement. If set, will try to connect to " "that arn", dest="aws_config", type=str, required=False, action="store", default="") parser.add_argument("-f", "--fpga", action="store", dest="fpga_arch", default="", help="ISPD FPGA architecture file") parser.add_argument("--mock", action="store", dest="mock_size", default=0, type=int, help="Mock CGRA board with " "provided size") args = parser.parse_args() cgra_arch = args.cgra_arch fpga_arch = args.fpga_arch mock_size = args.mock_size if len(cgra_arch) == 0 ^ len(fpga_arch) == 0 and mock_size == 0: parser.error("Must provide wither --fpga or --cgra") packed_filename = args.packed_filename netlist_embedding = args.netlist_embedding placement_filename = args.placement_filename aws_config = args.aws_config fpga_place = len(fpga_arch) > 0 seed = args.seed print("Using seed", seed, "for placement") # just in case for some library random.seed(seed) np.random.seed(seed) vis_opt = not args.no_vis fold_reg = not args.no_reg_fold # FPGA params override if mock_size > 0: fold_reg = False board_meta = mock_board_meta(mock_size) elif fpga_place: fold_reg = False board_meta = parse_fpga(fpga_arch) else: board_meta = parse_cgra(cgra_arch, fold_reg=fold_reg) print(fold_reg) # Common routine board_name, board_meta = board_meta.popitem() print("INFO: Placing for", board_name) num_dim, raw_emb = parse_emb(netlist_embedding) board = make_board(board_meta) board_info = board_meta[-1] place_on_board = generate_place_on_board(board_meta, fold_reg=fold_reg) fixed_blk_pos = {} special_blocks = set() emb = {} # FPGA if fpga_place: netlists, fixed_blk_pos, _ = load_packed_fpga_netlist(packed_filename) num_of_kernels = None id_to_name = {} for blk_id in raw_emb: id_to_name[blk_id] = blk_id if blk_id[0] == "i": special_blocks.add(blk_id) else: emb[blk_id] = raw_emb[blk_id] # place fixed IO locations for blk_id in fixed_blk_pos: pos = fixed_blk_pos[blk_id] place_on_board(board, blk_id, pos) folded_blocks = {} changed_pe = {} else: # CGRA raw_netlist, folded_blocks, id_to_name, changed_pe = \ load_packed_file(packed_filename) num_of_kernels = get_num_clusters(id_to_name) netlists = prune_netlist(raw_netlist) for blk_id in raw_emb: if blk_id[0] == "i": special_blocks.add(blk_id) else: emb[blk_id] = raw_emb[blk_id] # place the spacial blocks first place_special_blocks(board, special_blocks, fixed_blk_pos, raw_netlist, id_to_name, place_on_board, board_meta) # common routine data_x = np.zeros((len(emb), num_dim)) blks = list(emb.keys()) for i in range(len(blks)): data_x[i] = emb[blks[i]] centroids, cluster_cells, clusters = perform_global_placement( blks, data_x, emb, fixed_blk_pos, netlists, board_meta, fold_reg=fold_reg, num_clusters=num_of_kernels, seed=seed, fpga_place=fpga_place, vis=vis_opt) # placer with each cluster board_pos = perform_detailed_placement(centroids, cluster_cells, clusters, fixed_blk_pos, netlists, fold_reg, seed, board_info, aws_config) # refinement board_pos = refine_global_thunder(board_meta, board_pos, netlists, fixed_blk_pos, fold_reg) for blk_id in board_pos: pos = board_pos[blk_id] place_on_board(board, blk_id, pos) # save the placement file save_placement(board_pos, id_to_name, folded_blocks, placement_filename) basename_file = os.path.basename(placement_filename) design_name, _ = os.path.splitext(basename_file) if vis_opt: visualize_placement_cgra(board_meta, board_pos, design_name, changed_pe)
def main(): parser = ArgumentParser("CGRA Placer") parser.add_argument("-i", "--input", help="Packed netlist file, " + "e.g. harris.packed", required=True, action="store", dest="packed_filename") parser.add_argument("-e", "--embedding", help="Netlist embedding file, " + "e.g. harris.emb", required=True, action="store", dest="netlist_embedding") parser.add_argument("-o", "--output", help="Placement result, " + "e.g. harris.place", required=True, action="store", dest="placement_filename") parser.add_argument("-c", "--cgra", help="CGRA architecture file", required=True, action="store", dest="arch_filename") parser.add_argument("--no-reg-fold", help="If set, the placer will treat " + "registers as PE tiles", action="store_true", required=False, dest="no_reg_fold", default=False) parser.add_argument("--no-vis", help="If set, the placer won't show " + "visualization result for placement", action="store_true", required=False, dest="no_vis", default=False) parser.add_argument("-s", "--seed", help="Seed for placement. " + "default is 0", type=int, default=0, required=False, action="store", dest="seed") args = parser.parse_args() arch_filename = args.arch_filename packed_filename = args.packed_filename netlist_embedding = args.netlist_embedding placement_filename = args.placement_filename seed = args.seed print("Using seed", seed, "for placement") # just in case for some library random.seed(seed) np.random.seed(seed) vis_opt = not args.no_vis fold_reg = not args.no_reg_fold board_meta = parse_cgra(arch_filename, fold_reg=fold_reg) board_name, board_meta = board_meta.popitem() print("INFO: Placing for", board_name) num_dim, raw_emb = parse_emb(netlist_embedding) board = make_board(board_meta) place_on_board = generate_place_on_board(board_meta, fold_reg=fold_reg) is_cell_legal = generate_is_cell_legal(board_meta, fold_reg=fold_reg) fixed_blk_pos = {} emb = {} raw_netlist, folded_blocks, id_to_name, changed_pe = \ load_packed_file(packed_filename) netlists = prune_netlist(raw_netlist) special_blocks = set() for blk_id in raw_emb: if blk_id[0] == "i": special_blocks.add(blk_id) else: emb[blk_id] = raw_emb[blk_id] # place the spacial blocks first place_special_blocks(board, special_blocks, fixed_blk_pos, raw_netlist, id_to_name, place_on_board, board_meta) data_x = np.zeros((len(emb), num_dim)) blks = list(emb.keys()) for i in range(len(blks)): data_x[i] = emb[blks[i]] num_of_kernels = get_num_clusters(id_to_name) centroids, cluster_cells, clusters, fallback = perform_global_placement( blks, data_x, emb, fixed_blk_pos, netlists, board, is_cell_legal, board_meta, fold_reg=fold_reg, num_clusters=num_of_kernels, seed=seed) # anneal with each cluster board_pos = perform_detailed_placement(board, centroids, cluster_cells, clusters, fixed_blk_pos, netlists, raw_netlist, fold_reg, seed, fallback) # do a macro placement # macro_result = macro_placement(board, board_pos, fixed_blk_pos, netlists, # is_cell_legal, board_meta) # board_pos.update(macro_result) # only use deblock when we have lots of clusters # if len(clusters) > 2: # board_pos = perform_deblock_placement(board, board_pos, fixed_blk_pos, # netlists) for blk_id in board_pos: pos = board_pos[blk_id] place_on_board(board, blk_id, pos) # save the placement file save_placement(board_pos, id_to_name, folded_blocks, placement_filename) basename_file = os.path.basename(placement_filename) design_name, _ = os.path.splitext(basename_file) if vis_opt: visualize_placement_cgra(board_meta, board_pos, design_name, changed_pe)
def generate_bitstream(board_filename, netlist_filename, packed_filename, placement_filename, routing_filename, output_filename, io_json): netlists, folded_blocks, id_to_name, changed_pe = \ load_packed_file(packed_filename) blks = get_blks(netlists) board_meta = arch.parse_cgra(board_filename, True)["CGRA"] placement, _ = parse_placement(placement_filename) tile_mapping = board_meta[-1] board_layout = board_meta[0] io_pad_name = board_meta[-2]["io_pad_name"] io_pad_bit = board_meta[-2]["io_pad_bit"] io16_tile = board_meta[-2]["io16_tile"] connections, instances = read_netlist_json(netlist_filename) output_string = "" # TODO: refactor this name_to_id = {} for blk_id in id_to_name: name_to_id[id_to_name[blk_id]] = blk_id # build PE tiles types pe_tiles = {} type_str = "mpirI" for name in instances: instance = instances[name] blk_id = name_to_id[name] if blk_id in folded_blocks: continue blk_id = name_to_id[name] # it might be absorbed already if blk_id not in blks: continue # it has to be a PE tile assert (blk_id[0] in type_str) pos = placement[blk_id] tile = tile_mapping[pos] # find out the PE type tile_op, print_order = get_tile_op(instance, blk_id, changed_pe) if tile_op is None: continue pins = get_tile_pins(blk_id, tile_op, folded_blocks, instances, changed_pe, id_to_name, connections) # parse pins from the packing pe_tiles[blk_id] = (tile, tile_op, pins, print_order) tab = "\t" * 6 # generate tile mapping # sort them for pretty printing pe_keys = list(pe_tiles.keys()) pe_keys.sort(key=lambda x: int(pe_tiles[x][0])) pe_keys.sort(key=lambda x: pe_tiles[x][-1]) output_string += "# PLACEMENT\n" for blk_id in pe_keys: tile, op, pins, _ = pe_tiles[blk_id] if "mem" in op: output_string += "Tx{:04X}_{}{}#{}\n".format( tile, op, tab, id_to_name[blk_id]) else: output_string += "Tx{:04X}_{}({}){}# {}\n".format( tile, op, ",".join(pins), tab, id_to_name[blk_id]) # IO info io_pad_info, io_strings = generate_io(id_to_name, io16_tile, io_pad_bit, io_pad_name, placement, tile_mapping) assert len(io_strings) > 0 output_string += "\n\n#IO\n" output_string += "\n".join(io_strings) output_string += "\n\n#ROUTING\n" routes = generate_routing(routing_filename, tile_mapping, board_layout) net_id_list = list(routes.keys()) net_id_list.sort(key=lambda x: int(x[1:])) for net_id in net_id_list: output_string += "\n# net id: {}\n".format(net_id) netlist = netlists[net_id] for p in netlist: output_string += "# {}: {}::{}\n".format(p[0], id_to_name[p[0]], p[1]) output_string += routes[net_id] output_string += "\n" with open(output_filename, "w+") as f: f.write(output_string) with open(io_json, "w+") as f: json.dump(io_pad_info, f, indent=2, separators=(',', ': '))
def main(): # only the main thread needs it # this is to avoid loading unnecessary crop while calling from aws lambda from argparse import ArgumentParser from arch import parse_cgra, parse_fpga from arch.cgra import place_special_blocks, save_placement, prune_netlist from arch.cgra_packer import load_packed_file from arch.fpga import load_packed_fpga_netlist from arch import mock_board_meta from visualize import visualize_placement_cgra parser = ArgumentParser("CGRA Placer") parser.add_argument("-i", "--input", help="Packed netlist file, " + "e.g. harris.packed", required=True, action="store", dest="packed_filename") parser.add_argument("-o", "--output", help="Placement result, " + "e.g. harris.place", required=True, action="store", dest="placement_filename") parser.add_argument("-c", "--cgra", help="CGRA architecture file", action="store", dest="cgra_arch", default="") parser.add_argument("--no-reg-fold", help="If set, the placer will treat " + "registers as PE tiles", action="store_true", required=False, dest="no_reg_fold", default=False) parser.add_argument("--no-vis", help="If set, the placer won't show " + "visualization result for placement", action="store_true", required=False, dest="no_vis", default=False) parser.add_argument("-s", "--seed", help="Seed for placement. " + "default is 0", type=int, default=0, required=False, action="store", dest="seed") parser.add_argument("-a", "--aws", help="Serverless configuration for " + "detailed placement. If set, will try to connect to " "that arn", dest="aws_config", type=str, required=False, action="store", default="") parser.add_argument("-f", "--fpga", action="store", dest="fpga_arch", default="", help="ISPD FPGA architecture file") parser.add_argument("-l", "--layout", action="store", dest="cgra_layout", default="", help="CGRA layout file") parser.add_argument("--mock", action="store", dest="mock_size", default=0, type=int, help="Mock CGRA board with " "provided size") args = parser.parse_args() cgra_arch = args.cgra_arch fpga_arch = args.fpga_arch cgra_layout = args.cgra_layout mock_size = args.mock_size if sum([len(cgra_arch) != 0, len(fpga_arch) != 0, len(cgra_layout) != 0]) != 1 and \ mock_size == 0: parser.error("Must provide wither --fpga, --cgra, or --layout") packed_filename = args.packed_filename placement_filename = args.placement_filename aws_config = args.aws_config fpga_place = len(fpga_arch) > 0 seed = args.seed print("Using seed", seed, "for placement") vis_opt = not args.no_vis fold_reg = not args.no_reg_fold # FPGA params override if mock_size > 0: fold_reg = False board_meta = mock_board_meta(mock_size) elif fpga_place: fold_reg = False board_meta = parse_fpga(fpga_arch) else: if len(cgra_arch) > 0: board_meta = parse_cgra(cgra_arch) else: board_meta = {"cgra": pythunder.io.load_layout(cgra_layout)} # Common routine board_name, layout = board_meta.popitem() print("INFO: Placing for", board_name) board = make_board(layout) pythunder.io.dump_layout(layout, "cgra.layout") fixed_blk_pos = {} special_blocks = set() # FPGA if fpga_place: netlists, fixed_blk_pos, _ = load_packed_fpga_netlist(packed_filename) id_to_name = {} # place fixed IO locations for blk_id in fixed_blk_pos: pos = fixed_blk_pos[blk_id] place_on_board(board, blk_id, pos) folded_blocks = {} changed_pe = {} else: # CGRA raw_netlist, folded_blocks, id_to_name, changed_pe = \ load_packed_file(packed_filename) netlists = prune_netlist(raw_netlist) for blk in id_to_name: if blk[0] == "i" or blk[0] == "I": special_blocks.add(blk) # place the spacial blocks first place_special_blocks(board, special_blocks, fixed_blk_pos, raw_netlist, place_on_board, layout) # common routine # produce layout structure centroids, cluster_cells, clusters = perform_global_placement( fixed_blk_pos, netlists, layout, seed=seed, vis=vis_opt) # placer with each cluster board_pos = perform_detailed_placement(centroids, cluster_cells, clusters, fixed_blk_pos, netlists, fold_reg, seed, layout, aws_config) # refinement board_pos = refine_global_thunder(layout, board_pos, netlists, fixed_blk_pos, fold_reg) for blk_id in board_pos: pos = board_pos[blk_id] place_on_board(board, blk_id, pos) # save the placement file save_placement(board_pos, id_to_name, folded_blocks, placement_filename) basename_file = os.path.basename(placement_filename) design_name, _ = os.path.splitext(basename_file) if vis_opt: visualize_placement_cgra(layout, board_pos, design_name, changed_pe)
def main(): if len(sys.argv) != 4: print("Usage:", sys.argv[0], "<cgra_info.txt>", "<netlist.json>", "<netlist.route>", file=sys.stderr) exit(1) cgra_file = sys.argv[1] netlist = sys.argv[2] route_file = sys.argv[3] packed_file = route_file.replace(".route", ".packed") placement_file = route_file.replace(".route", ".place") board_meta = parse_cgra(cgra_file)["CGRA"] routing_result = parse_routing_result(route_file) placement, _ = parse_placement(placement_file) if hasattr(sys.stdout, 'isatty') and sys.stdout.isatty(): meta = os.popen('stty size', 'r').read().split() cols = int(meta[-1]) cols = int(cols) scale = cols - 15 else: scale = 68 cols = 80 # print("Latency:") # print("Total:", total_time) # latency_info = compute_latency(net_path, routing_result, placement) # total_time = sum([latency_info[key] for key in latency_info]) # for entry in latency_info: # time = latency_info[entry] # percentage = int(time / total_time * 100) # num_bar = int(percentage / (100 / scale)) # s = "{0:4s} {1} {2} {3}".format(entry.upper(), # num_bar * '█', ' ' * (scale - num_bar), # time) # print(s) print("-" * cols) print("Area Usage:") usage = compute_area_usage(placement, board_meta[0]) for entry in usage: percentage = usage[entry][0] / usage[entry][1] * 100 num_bar = int(percentage / 100 * scale) print("{0:4s} {1} {2} {3:.2f}%".format(entry.upper(), num_bar * '█', ' ' * (scale - num_bar - 2), percentage)) print("-" * cols) net_wire = compute_total_wire(routing_result) total_wire = sum([net_wire[x] for x in net_wire]) print("Total wire:", total_wire) print("-" * cols) total_delay, detailed_delay = find_critical_path_delay(netlist, packed_file, routing_result, placement) print("Critical Path:") clock_speed = 1e6 / total_delay total_delay_formatted = "{:.2f} ns".format(total_delay / 1000) print("Delay:", total_delay_formatted, "Max Clock Speed:", "{0:.2f} MHz".format(clock_speed)) delay_keys = list(detailed_delay.keys()) delay_keys.sort(key=lambda x: detailed_delay[x], reverse=True) for entry in delay_keys: percentage = detailed_delay[entry] / total_delay * 100 num_bar = int(percentage / 100 * scale) print("{0:4s} {1} {2} {3:.2f}%".format(entry.upper(), num_bar * '█', ' ' * (scale - num_bar - 2), percentage)) print("-" * cols) r = parse_routing_resource(cgra_file) routing_resource = build_routing_resource(r) resource_usage = compute_routing_usage(routing_result, routing_resource, board_meta[0]) for bus in resource_usage: print("BUS:", bus) for track in resource_usage[bus]: left = 0 total = 0 for _, l, t in resource_usage[bus][track]: left += l total += t percentage = (total - left) / total * 100 num_bar = int(percentage / 100 * scale) print("TRACK {0} {1} {2} {3:.2f}%".format(track, num_bar * '█', ' ' * (scale - num_bar - 5), percentage))