Example #1
0
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))
Example #2
0
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)
Example #3
0
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))
Example #4
0
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]
    ]
Example #5
0
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)