Esempio n. 1
0
def gen_reduce_impl(stmt, arr_size, s_idx):
    """
    Returns a dictionary containing Calyx cells, wires and
    control needed to implement a map statement. Similar
    to gen_map_impl, with an implementation of a body
    of the `reduce` statement instead of an implementation
    of a `map` statement.
    """
    stdlib = Stdlib()
    op_name = "mult" if stmt.op.body.op == "mul" else "add"
    cells = [
        Cell(CompVar(f"le{s_idx}"), stdlib.op("lt", 32, signed=False)),
        Cell(CompVar(f"idx{s_idx}"), stdlib.register(32)),
        Cell(CompVar(f"adder_idx{s_idx}"), stdlib.op("add", 32, signed=False)),
        Cell(CompVar(f"adder_op{s_idx}"),
             stdlib.op(f"{op_name}", 32, signed=False)),
    ]
    wires = [
        emit_cond_group(s_idx, arr_size),
        emit_idx_group(s_idx),
        emit_eval_body_group(s_idx, stmt, 0),
    ]
    control = While(
        port=CompPort(CompVar(f"le{s_idx}"), "out"),
        cond=CompVar(f"cond{s_idx}"),
        body=SeqComp([Enable(f"eval_body{s_idx}"),
                      Enable(f"incr_idx{s_idx}")]),
    )

    return {"cells": cells, "wires": wires, "control": control}
Esempio n. 2
0
def gen_map_impl(stmt, arr_size, bank_factor, s_idx):
    """
    Returns a dictionary containing Calyx cells, wires and
    control needed to implement a map statement. (See gen_stmt_impl
    for format of the dictionary.)

    Generates these groups:
      - a group that implements the body of the map statement
      - a group that increments an index to access the map input array
      - a group that implements the loop condition, checking if the index
        has reached the end of the input array
    """
    stdlib = Stdlib()

    cells = []
    for b in range(bank_factor):
        cells.extend([
            Cell(CompVar(f"le_b{b}_{s_idx}"), stdlib.op("lt", 32,
                                                        signed=False)),
            Cell(CompVar(f"idx_b{b}_{s_idx}"), stdlib.register(32)),
            Cell(
                CompVar(f"adder_idx_b{b}_{s_idx}"),
                stdlib.op("add", 32, signed=False),
            ),
        ])

    op_name = "mult" if stmt.op.body.op == "mul" else "add"
    for b in range(bank_factor):
        cells.append(
            Cell(
                CompVar(f"adder_op_b{b}_{s_idx}"),
                stdlib.op(f"{op_name}", 32, signed=False),
            ))

    wires = []
    for b in range(bank_factor):
        wires.extend([
            emit_cond_group(s_idx, arr_size // bank_factor, b),
            emit_idx_group(s_idx, b),
            emit_eval_body_group(s_idx, stmt, b),
        ])

        map_loops = []
        for b in range(bank_factor):
            b_suffix = f"_b{str(b)}_"
            map_loops.append(
                While(
                    CompPort(CompVar(f"le{b_suffix}{s_idx}"), "out"),
                    CompVar(f"cond{b_suffix}{s_idx}"),
                    SeqComp([
                        Enable(f"eval_body{b_suffix}{s_idx}"),
                        Enable(f"incr_idx{b_suffix}{s_idx}"),
                    ]),
                ))

    control = ParComp(map_loops)

    return {"cells": cells, "wires": wires, "control": control}
Esempio n. 3
0
    def cells():
        stdlib = Stdlib()

        memories = [
            Cell(input, stdlib.mem_d1(input_bitwidth, n, bitwidth), is_external=True),
            Cell(phis, stdlib.mem_d1(input_bitwidth, n, bitwidth), is_external=True),
        ]
        r_regs = [
            Cell(CompVar(f"r{r}"), stdlib.register(input_bitwidth)) for r in range(n)
        ]
        A_regs = [
            Cell(CompVar(f"A{r}"), stdlib.register(input_bitwidth)) for r in range(n)
        ]
        mul_regs = [
            Cell(CompVar(f"mul{i}"), stdlib.register(input_bitwidth))
            for i in range(n // 2)
        ]
        phi_regs = [
            Cell(CompVar(f"phi{r}"), stdlib.register(input_bitwidth)) for r in range(n)
        ]
        mod_pipes = [
            Cell(
                CompVar(f"mod_pipe{r}"),
                stdlib.op("div_pipe", input_bitwidth, signed=True),
            )
            for r in range(n)
        ]
        mult_pipes = [
            Cell(
                CompVar(f"mult_pipe{i}"),
                stdlib.op("mult_pipe", input_bitwidth, signed=True),
            )
            for i in range(n // 2)
        ]
        adds = [
            Cell(CompVar(f"add{i}"), stdlib.op("add", input_bitwidth, signed=True))
            for i in range(n // 2)
        ]
        subs = [
            Cell(CompVar(f"sub{i}"), stdlib.op("sub", input_bitwidth, signed=True))
            for i in range(n // 2)
        ]

        return (
            memories
            + r_regs
            + A_regs
            + mul_regs
            + phi_regs
            + mod_pipes
            + mult_pipes
            + adds
            + subs
        )
Esempio n. 4
0
def emit_mem_decl(name, size, par):
    """
    Returns N memory declarations,
    where N = `par`.
    """
    stdlib = Stdlib()
    banked_mems = []
    for i in range(par):
        banked_mems.append(
            Cell(
                CompVar(f"{name}_b{i}"),
                stdlib.mem_d1(32, size // par, 32),
                is_external=True,
            ))
    return banked_mems
Esempio n. 5
0
def emit(prog):
    """
    Returns a string containing a Calyx program, compiled from `prog`, a MrXL
    program.
    """
    cells, wires, control = [], [], []

    # All arrays must be the same size. The first array we see determines the
    # size that we'll assume for the rest of the program's arrays.
    arr_size = None

    # Collect banking factors.
    name2par = dict()
    for stmt in prog.stmts:
        if isinstance(stmt.op, ast.Map):
            name2par[stmt.dest] = stmt.op.par
            for b in stmt.op.bind:
                name2par[b.src] = stmt.op.par

    # Collect memory and register declarations.
    used_names = []
    stdlib = Stdlib()
    for decl in prog.decls:
        used_names.append(decl.name)
        if decl.type.size:  # A memory
            arr_size = decl.type.size
            cells.extend(
                emit_mem_decl(decl.name, decl.type.size, name2par[decl.name]))
        else:  # A register
            cells.append(Cell(CompVar(decl.name), stdlib.register(32)))

    # Collect implicit memory and register declarations.
    for stmt in prog.stmts:
        if stmt.dest not in used_names:
            if isinstance(stmt.op, ast.Map):
                cells.extend(
                    emit_mem_decl(stmt.dest, arr_size, name2par[stmt.dest]))
            else:
                raise NotImplementedError("Generating register declarations")
                #  cells.append(emit_reg_decl(stmt.dest, 32))
            used_names.append(stmt.dest)

    # Generate Calyx.
    for i, stmt in enumerate(prog.stmts):
        stmt_impl = gen_stmt_impl(stmt, arr_size, name2par, i)
        cells.extend(stmt_impl["cells"])
        wires.extend(stmt_impl["wires"])
        control.append(stmt_impl["control"])

    program = Program(
        imports=[
            Import("primitives/core.futil"),
            Import("primitives/binary_operators.futil"),
        ],
        components=[
            Component(
                name="main",
                inputs=[],
                outputs=[],
                structs=cells + wires,
                controls=SeqComp(control),
            )
        ],
    )
    program.emit()
Esempio n. 6
0
def generate_cells(degree: int, width: int, int_width: int,
                   is_signed: bool) -> List[Cell]:
    stdlib = Stdlib()
    frac_width = width - int_width
    init_cells = [
        Cell(CompVar("exponent_value"), stdlib.register(width)),
        Cell(CompVar("int_x"), stdlib.register(width)),
        Cell(CompVar("frac_x"), stdlib.register(width)),
        Cell(CompVar("m"), stdlib.register(width)),
        Cell(CompVar("and0"), stdlib.op("and", width, signed=False)),
        Cell(CompVar("and1"), stdlib.op("and", width, signed=False)),
        Cell(CompVar("rsh"), stdlib.op("rsh", width, signed=False)),
    ] + ([Cell(CompVar("lt"), stdlib.op("lt", width, signed=is_signed))]
         if is_signed else [])

    pow_registers = [
        Cell(CompVar(f"p{i}"), stdlib.register(width))
        for i in range(2, degree + 1)
    ]
    product_registers = [
        Cell(CompVar(f"product{i}"), stdlib.register(width))
        for i in range(2, degree + 1)
    ]
    sum_registers = [
        Cell(CompVar(f"sum{i}"), stdlib.register(width))
        for i in range(1, (degree // 2) + 1)
    ]
    adds = [
        Cell(
            CompVar(f"add{i}"),
            stdlib.fixed_point_op("add",
                                  width,
                                  int_width,
                                  frac_width,
                                  signed=is_signed),
        ) for i in range(1, (degree // 2) + 1)
    ]
    pipes = [
        Cell(
            CompVar(f"mult_pipe{i}"),
            stdlib.fixed_point_op("mult_pipe",
                                  width,
                                  int_width,
                                  frac_width,
                                  signed=is_signed),
        ) for i in range(1, degree + 1)
    ]
    # One extra `fp_pow` instance to compute e^{int_value}.
    pows = [
        Cell(CompVar(f"pow{i}"), CompInst("fp_pow", []))
        for i in range(1, degree + 1)
    ]
    reciprocal_factorials = []
    for i in range(2, degree + 1):
        fixed_point_value = float_to_fixed_point(1.0 / factorial(i),
                                                 frac_width)
        value = numeric_types.FixedPoint(
            str(fixed_point_value), width, int_width,
            is_signed=is_signed).unsigned_integer()
        reciprocal_factorials.append(
            Cell(CompVar(f"reciprocal_factorial{i}"),
                 stdlib.constant(width, value)))
    # Constant values for the exponent to the fixed point `pow` function.
    constants = [
        Cell(CompVar(f"c{i}"), stdlib.constant(width, i))
        for i in range(2, degree + 1)
    ] + [
        Cell(
            CompVar("one"),
            stdlib.constant(
                width,
                numeric_types.FixedPoint(
                    "1.0", width, int_width,
                    is_signed=is_signed).unsigned_integer(),
            ),
        ),
        Cell(
            CompVar("e"),
            stdlib.constant(
                width,
                numeric_types.FixedPoint(
                    str(float_to_fixed_point(2.7182818284, frac_width)),
                    width,
                    int_width,
                    is_signed=is_signed,
                ).unsigned_integer(),
            ),
        ),
    ]
    if is_signed:
        constants.append(
            Cell(
                CompVar("negative_one"),
                stdlib.constant(
                    width,
                    numeric_types.FixedPoint(
                        "-1.0", width, int_width,
                        is_signed=is_signed).unsigned_integer(),
                ),
            ), )
        pipes.append(
            Cell(
                CompVar("div_pipe"),
                stdlib.fixed_point_op("div_pipe",
                                      width,
                                      int_width,
                                      frac_width,
                                      signed=is_signed),
            ))

    return (init_cells + constants + product_registers + pow_registers +
            sum_registers + adds + pipes + reciprocal_factorials + pows)
Esempio n. 7
0
def generate_fp_pow_component(width: int, int_width: int,
                              is_signed: bool) -> Component:
    """Generates a fixed point `pow` component, which
    computes the value x**y, where y must be an integer.
    """
    stdlib = Stdlib()
    frac_width = width - int_width

    pow = CompVar("pow")
    count = CompVar("count")
    mul = CompVar("mul")
    lt = CompVar("lt")
    incr = CompVar("incr")

    cells = [
        Cell(pow, stdlib.register(width)),
        Cell(count, stdlib.register(width)),
        Cell(
            mul,
            stdlib.fixed_point_op("mult_pipe",
                                  width,
                                  int_width,
                                  frac_width,
                                  signed=is_signed),
        ),
        Cell(lt, stdlib.op("lt", width, signed=is_signed)),
        Cell(incr, stdlib.op("add", width, signed=is_signed)),
    ]
    wires = [
        Group(
            id=CompVar("init"),
            connections=[
                Connect(
                    ConstantPort(
                        width,
                        numeric_types.FixedPoint(
                            "1.0", width, int_width,
                            is_signed=is_signed).unsigned_integer(),
                    ),
                    CompPort(pow, "in"),
                ),
                Connect(ConstantPort(1, 1), CompPort(pow, "write_en")),
                Connect(ConstantPort(width, 0), CompPort(count, "in")),
                Connect(ConstantPort(1, 1), CompPort(count, "write_en")),
                Connect(
                    ConstantPort(1, 1),
                    HolePort(CompVar("init"), "done"),
                    And(
                        Atom(CompPort(pow, "done")),
                        Atom(CompPort(count, "done")),
                    ),
                ),
            ],
        ),
        Group(
            id=CompVar("execute_mul"),
            connections=[
                Connect(ThisPort(CompVar("base")), CompPort(mul, "left")),
                Connect(CompPort(pow, "out"), CompPort(mul, "right")),
                Connect(
                    ConstantPort(1, 1),
                    CompPort(mul, "go"),
                    Not(Atom(CompPort(mul, "done"))),
                ),
                Connect(CompPort(mul, "done"), CompPort(pow, "write_en")),
                Connect(CompPort(mul, "out"), CompPort(pow, "in")),
                Connect(
                    CompPort(pow, "done"),
                    HolePort(CompVar("execute_mul"), "done"),
                ),
            ],
        ),
        Group(
            id=CompVar("incr_count"),
            connections=[
                Connect(ConstantPort(width, 1), CompPort(incr, "left")),
                Connect(CompPort(count, "out"), CompPort(incr, "right")),
                Connect(CompPort(incr, "out"), CompPort(count, "in")),
                Connect(ConstantPort(1, 1), CompPort(count, "write_en")),
                Connect(
                    CompPort(count, "done"),
                    HolePort(CompVar("incr_count"), "done"),
                ),
            ],
        ),
        CombGroup(
            id=CompVar("cond"),
            connections=[
                Connect(CompPort(count, "out"), CompPort(lt, "left")),
                Connect(ThisPort(CompVar("integer_exp")),
                        CompPort(lt, "right")),
            ],
        ),
        Connect(CompPort(CompVar("pow"), "out"), ThisPort(CompVar("out"))),
    ]
    return Component(
        "fp_pow",
        inputs=[
            PortDef(CompVar("base"), width),
            PortDef(CompVar("integer_exp"), width),
        ],
        outputs=[PortDef(CompVar("out"), width)],
        structs=cells + wires,
        controls=SeqComp([
            Enable("init"),
            While(
                CompPort(lt, "out"),
                CompVar("cond"),
                ParComp([Enable("execute_mul"),
                         Enable("incr_count")]),
            ),
        ]),
    )
Esempio n. 8
0
 program = Program(
     imports=[
         Import("primitives/core.futil"),
         Import("primitives/binary_operators.futil")
     ],
     components=generate_exp_taylor_series_approximation(
         degree, width, int_width, is_signed),
 )
 # Append a `main` component for testing purposes.
 program.components.append(
     Component(
         "main",
         inputs=[],
         outputs=[],
         structs=[
             Cell(CompVar("t"),
                  Stdlib().register(width)),
             Cell(CompVar("x"),
                  Stdlib().mem_d1(width, 1, 1),
                  is_external=True),
             Cell(
                 CompVar("ret"),
                 Stdlib().mem_d1(width, 1, 1),
                 is_external=True,
             ),
             Cell(CompVar("e"), CompInst("exp", [])),
             Group(
                 id=CompVar("init"),
                 connections=[
                     Connect(
                         ConstantPort(1, 0),
                         CompPort(CompVar("x"), "addr0"),