Example #1
0
 def doc(self) -> str:
     ins = ", ".join([s.doc() for s in self.inputs])
     outs = ", ".join([s.doc() for s in self.outputs])
     signature = f"component {self.name}({ins}) -> ({outs})"
     cells = block("cells", [c.doc() for c in self.cells])
     wires = block("wires", [w.doc() for w in self.wires])
     controls = block("control", [self.controls.doc()])
     return block(signature, [cells, wires, controls])
Example #2
0
 def doc(self) -> str:
     cond = f"if {self.port.doc()} with {self.cond.doc()}"
     true_branch = self.true_branch.doc()
     if isinstance(self.false_branch, Empty):
         false_branch = ""
     else:
         false_branch = block(" else", self.false_branch.doc(), sep="")
     return block(cond, true_branch, sep="") + false_branch
Example #3
0
def emit_dahlia_loop(fd: DahliaFuncDef, body: str, num_dims: int) -> str:
    """Emits a Dahlia loop over `num_dims` with `body`
    nested inside. Many tensor functions share the
    same control flow:
    (1) Iterate `num_dims` times, and
    (2) do some work in the body.

    For example, if body == `X`, then this
    will return:
    ```
    for (let i: ubit<X> = 0..M) {
      for (let j: ubit<Y> = 0..N) {
        X;
      }
    }
    ```
    """
    var_name = CHARACTER_I
    args = fd.dest.comp.args

    # Generate loop headers.
    headers = []
    for i in range(num_dims):
        size = args[i + 1]
        idx_size = args[i + 1 + num_dims]
        headers.append(f'for (let {var_name}: ubit<{idx_size}> = 0..{size})')
        var_name = next_character(var_name)

    headers.reverse()

    # Generate loop blocks.
    for i in range(num_dims):
        b = body if i == 0 else headers[i - 1]
        headers[i] = block(headers[i], b, sep='')
    return headers[-1]
Example #4
0
 def doc(self) -> str:
     static_delay_attr = ("" if self.static_delay == None else
                          f'<"static"={self.static_delay}>')
     return block(
         f"group {self.id.doc()}{static_delay_attr}",
         [c.doc() for c in self.connections],
     )
Example #5
0
def emit_dahlia_definition(fd: DahliaFuncDef, body: str) -> str:
    """Emits a Dahlia definition, e.g.
    `def foo(a: ubit<32>) = { ... }`
    """
    params = emit_dahlia_params(fd)
    return block(f'def {fd.function_id}({params}) =',
                 '\n'.join(body) if isinstance(body, tuple) else body,
                 sep='')
Example #6
0
def emit_dahlia_loop(control_flow: Cell, body: str) -> str:
    """Emits a Dahlia loop over `num_dims` with `body`
    nested inside. Many tensor functions share the
    same control flow:
    (1) Perform specific looping according to `control_flow`,
    (2) and do some work in the body.

    For example, if body == `X`, then this
    will return:
    ```
    for (let i: ubit<X> = 0..M) {
      for (let j: ubit<Y> = 0..N) {
        X;
      }
    }
    ```
    """
    var_name = CHARACTER_I
    # Loop control flow is determined by these parameters.
    num_dims = get_dims(control_flow.comp)
    args = control_flow.comp.args

    # Generate loop headers.
    headers = []
    for i in range(num_dims):
        size = args[i + 1]
        idx_size = args[i + 1 + num_dims]
        headers.append(f'for (let {var_name}: ubit<{idx_size}> = 0..{size})')
        var_name = next_character(var_name)

    headers.reverse()

    # Generate loop blocks.
    for i in range(num_dims):
        b = body if i == 0 else headers[i - 1]
        headers[i] = block(headers[i], b, sep='')
    return headers[-1]
Example #7
0
def emit_dahlia_definition(fd: DahliaFuncDef, body: str) -> str:
    """Emits a Dahlia definition, e.g.
    `def foo(a: ubit<32>) = { ... }`
    """
    params = emit_dahlia_params(fd)
    return block(f'def {fd.function_id}({params}) =', body, sep='')
Example #8
0
 def doc(self) -> str:
     return block(f"while {self.port.doc()} with {self.cond.doc()}",
                  self.body.doc(),
                  sep="")
Example #9
0
 def doc(self) -> str:
     return block("par", [s.doc() for s in self.stmts])