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])
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
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]
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], )
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='')
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]
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='')
def doc(self) -> str: return block(f"while {self.port.doc()} with {self.cond.doc()}", self.body.doc(), sep="")
def doc(self) -> str: return block("par", [s.doc() for s in self.stmts])