def DefineAdd(N=None, cout=False, cin=False, width=None): if N is None: if width is None: raise ValueError("Either N or width must be not None") N = width elif width is not None: warning("Both N and width are not None, using N") has_cout = cout has_cin = cin if not has_cout and not has_cin: return DefineCoreirAdd(N) class Add(mantle.primitives.DeclareAdd(N, cin=has_cin, cout=has_cout)): @classmethod def definition(add): width = N if has_cout: width += 1 CoreirAdd = DefineCoreirAdd(width) coreir_add = CoreirAdd() I0 = add.I0 I1 = add.I1 if has_cout: I0 = concat(add.I0, bits(0, n=1)) I1 = concat(add.I1, bits(0, n=1)) if has_cin: coreir_add_cin = CoreirAdd() wire(coreir_add_cin.I0, concat(bits(add.CIN), bits(0, n=width - 1))) wire(coreir_add_cin.I1, I0) I0 = coreir_add_cin.O wire(I0, coreir_add.I0) wire(I1, coreir_add.I1) O = coreir_add.O if has_cout: COUT = O[-1] O = O[:-1] wire(O, add.O) if has_cout: wire(COUT, add.COUT) return Add
def compileinstance(dot, instance): instance_backend_name = str(instance.name) instance_cls_name = str(instance.__class__.__name__) inputs = [] outputs = [] for name, port in instance.interface.ports.items(): if port.isinput(): inputs.append('<{0}> {0}'.format(str(name))) value = port.value() if not value: logging.warning(f'Input {port.debug_name} not connected to an output') continue else: outputs.append('<{0}> {0}'.format(str(name))) value = port # if isinstance(value, ArrayType): # for index, subport in enumerate(value.ts): # s += "{}.{}[{}] <= {}\n".format(instance_backend_name, name, index, get_name(subport)) # else: value_name = get_name(dot, value) if port.isinput(): # s += "{}.{} <= {}\n".format(instance_backend_name, name, value_name) dot.edge(value_name, '{}:{}'.format(instance_backend_name, name)) else: # s += "{} <= {}.{}\n".format(value_name, instance_backend_name, name) dot.edge('{}:{}'.format(instance_backend_name, name), value_name) instance_label = '{' + '|'.join(inputs) + '}|' if instance.decl is not None: instance_label += '{} ({})\\n{}'.format(instance.decl.varname, instance_backend_name, instance_cls_name) else: instance_label += '{}\\n{}'.format(instance_backend_name, instance_cls_name) instance_label += '|{' + '|'.join(outputs) + '}' dot.node(instance_backend_name, '{' + instance_label + '}')
def visit_If(self, node): # Flatten in case there's a nest If statement that returns a list node.body = self.flatten(map(self.visit, node.body)) if not hasattr(node, "orelse"): raise NotImplementedError("If without else") node.orelse = self.flatten(map(self.visit, node.orelse)) seen = OrderedDict() for stmt in node.body: if not isinstance(stmt, ast.Assign): # TODO: Print info from original source file/line raise CircuitDefinitionSyntaxError( f"Expected only assignment statements in if statement, got" f" {type(stmt)}") if len(stmt.targets) > 1: raise NotImplementedError("Assigning more than one value") key = ast.dump(stmt.targets[0]) if key in seen: if self.filename: # TODO: Print the line number report_transformer_warning( "Assigning to value twice inside `if` block," " taking the last value (first value is ignored)", self.filename, node.lineno + self.starting_line, self.lines[node.lineno]) else: warning( "Assigning to value twice inside `if` block," " taking the last value (first value is ignored)") seen[key] = stmt orelse_seen = set() for stmt in node.orelse: key = ast.dump(stmt.targets[0]) if key in seen: if key in orelse_seen: if self.filename: report_transformer_warning( "Assigning to value twice inside `else` block," " taking the last value (first value is ignored)", self.filename, node.lineno + self.starting_line, self.lines[node.lineno]) else: warning( "Assigning to value twice inside `else` block," " taking the last value (first value is ignored)") orelse_seen.add(key) seen[key].value = ast.Call( ast.Name("phi", ast.Load()), [ast.List([stmt.value, seen[key].value], ast.Load()), node.test], []) else: if self.filename: report_transformer_warning( "NOT IMPLEMENTED: Assigning to a variable once in" " `else` block (not in then block)", self.filename, node.lineno + self.starting_line, self.lines[node.lineno]) else: warning( "NOT IMPLEMENTED: Assigning to a variable once in" " `else` block (not in then block)") raise NotImplementedError() return [node for node in seen.values()]
def report_transformer_warning(message, filename, lineno, line): warning(f"\033[1m{make_relative(filename)}:{lineno}: {message}") warning(line)