def test_codegen_device(file_tester): program = Program([ Push(0, "short", 8), Pop(0), Push(1), Pop(2, "char", 8), Broadcast(3, "float", 64), Broadcast(4, "int"), Push(5, "double", 32), Reduce(6, "float", 16, "add"), Scatter(7, "double"), Gather(8, "char") ]) mapping = ProgramMapping([program], { "n1:f1": program, "n1:f2": program, "n2:f1": program, "n3:f1": program }) connections = { ("n1:f1", 0): ("n1:f2", 0), ("n1:f2", 1): ("n2:f1", 1), ("n1:f2", 2): ("n3:f1", 1), ("n2:f1", 0): ("n1:f1", 1), } ctx = create_routing_context(connections, mapping) file_tester.check( "smi-device-1.h", generate_program_device(ctx.fpgas[0], ctx.fpgas, ctx.graph, 4))
def get_routing_ctx(program: Program, connections) -> RoutingContext: fpgas = tuple(fpga for (fpga, _) in connections.keys()) + tuple( fpga for (fpga, _) in connections.values()) fpga_map = {fpga: program for fpga in fpgas} for (k, v) in dict(connections).items(): connections[v] = k mapping = ProgramMapping([program], fpga_map) return create_routing_context(connections, mapping)
def codegen_device(routing_file, rewriter, src_dir, dest_dir, device_src, output_program, device_input, include, consecutive_read_limit, max_ranks, p2p_rendezvous): """ Transpiles device code and generates device kernels and host initialization code. :param routing_file: path to a file with FPGA connections and FPGA-to-program mapping :param rewriter: path to the rewriter :param src_dir: root directory of device source files :param dest_dir: root directory of generated device source files :param device_src: path to generated device source file :param output_program: path to generated JSON program description :param device_input: list of device sources :param include: list of include directories for device sources :param consecutive_read_limit: how many reads should be performed in succession from a single channel in CKR/CKS :param max_ranks: maximum number of ranks in the cluster :param p2p_rendezvous: whether to use rendezvous for P2P operations """ paths = list(copy_files(src_dir, dest_dir, device_input)) p2p_rendezvous = True if p2p_rendezvous in (True, 1, "1", "ON") else False with open("rewrite.log", "w") as f: ops = [] include_dirs = set(include.split(" ")) for (src, dest) in paths: ops += rewrite(rewriter, dest, include_dirs, f) ops = sorted(ops, key=lambda op: op.logical_port) program = Program(ops, consecutive_read_limit, max_ranks, p2p_rendezvous) with open(routing_file) as rf: (connections, mapping) = parse_routing_file(rf.read(), ignore_programs=True) program_mapping = ProgramMapping( [program], { fpga: program for fpga in set(fpga for (fpga, _) in connections.keys()) }) ctx = create_routing_context(connections, program_mapping) fpgas = ctx.fpgas if fpgas: write_file( device_src, generate_program_device(fpgas[0], fpgas, ctx.graph, CHANNELS_PER_FPGA)) write_file(output_program, serialize_program(program))
def test_routing_context(): program = Program([]) mapping = ProgramMapping([program], { "n1:f1": program, "n1:f2": program, "n2:f1": program, "n3:f1": program }) connections = { ("n1:f1", 0): ("n1:f2", 0), ("n1:f2", 1): ("n2:f1", 1), ("n1:f2", 2): ("n3:f1", 1), ("n2:f1", 0): ("n1:f1", 1), } ctx = create_routing_context(connections, mapping) fpgas = ctx.fpgas assert ctx.routes[fpgas[0].channels[0]][fpgas[3].channels[3]] == [ fpgas[0].channels[0], fpgas[1].channels[0], fpgas[1].channels[2], fpgas[3].channels[1], fpgas[3].channels[3] ]
def route(routing_file, dest_dir, metadata): """ Creates routing tables and hostfile. :param routing_file: path to a file with FPGA connections and FPGA-to-program mapping :param dest_dir: path to a directory where routing tables and the hostfile will be generated :param metadata: list of program metadata files """ prepare_directory(os.path.abspath(dest_dir)) with open(routing_file) as rf: (connections, mapping) = parse_routing_file(rf.read(), metadata) ctx = create_routing_context(connections, mapping) for fpga in ctx.fpgas: for channel in fpga.channels: cks_table = cks_routing_table(ctx.routes, ctx.fpgas, channel) write_table(channel, "cks", cks_table, dest_dir) ckr_table = ckr_routing_table(channel, CHANNELS_PER_FPGA, fpga.program) write_table(channel, "ckr", ckr_table, dest_dir) with open(os.path.join(dest_dir, "hostfile"), "w") as f: write_nodefile(ctx.fpgas, f)