def emit_dahlia_params(fd: DahliaFuncDef) -> str: """Emits a comma-separated string of Dahlia memory declarations, e.g. `X: ubit<32> [1][10], a: ufix<8, 2>[3]` """ cells = [] for cell in fd.args + [fd.dest]: cell_str = f"{cell.id.name}: {fd.data_type}" dims = get_dims(cell.comp) args = cell.comp.args for i in range(0, dims): cell_str += f"[{args[i + 1]}]" cells.append(cell_str) return ", ".join(cells)
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]