diff --git a/frontends/PyCDE/src/pycde/module.py b/frontends/PyCDE/src/pycde/module.py index c5791a257b..375c1804a2 100644 --- a/frontends/PyCDE/src/pycde/module.py +++ b/frontends/PyCDE/src/pycde/module.py @@ -216,14 +216,14 @@ def _module_base(cls, extern: bool, params={}): raise ConnectionError( "`no_connect` is only valid on extern module ports") else: - value = hw.ConstantOp.create(types.i1, 0).result + value = Value.get(hw.ConstantOp.create(types.i1, 0).result) else: value = obj_to_value(input, type) else: backedge = BackedgeBuilder.current().create(type, name, self, loc=loc) self.backedges[idx] = backedge - value = backedge.result - input_ports_values.append(value) + value = Value.get(backedge.result) + input_ports_values.append(value.value) # Set up the op attributes. attributes: dict[str:mlir.ir.Attribute] = {} @@ -465,7 +465,7 @@ class _Generate: unconnected_ports.append(name) outputs.append(None) else: - val = obj_to_value(gen_ret[name], port_type) + val = obj_to_value(gen_ret[name], port_type).value outputs.append(val) gen_ret.pop(name) if len(unconnected_ports) > 0: diff --git a/frontends/PyCDE/src/pycde/pycde_types.py b/frontends/PyCDE/src/pycde/pycde_types.py index 12f9f02d8b..054d6391f7 100644 --- a/frontends/PyCDE/src/pycde/pycde_types.py +++ b/frontends/PyCDE/src/pycde/pycde_types.py @@ -18,7 +18,7 @@ class _Types: self.registered_aliases = OrderedDict() def __getattr__(self, name: str) -> mlir.ir.Type: - return mlir.ir.Type.parse(name) + return self.wrap(mlir.ir.Type.parse(name)) def int(self, width: int, name: str = None): return self.wrap(mlir.ir.IntegerType.get_signless(width), name) @@ -111,9 +111,12 @@ def PyCDEType(type): else: return self - def create(self, obj): + def create(self, obj, name: str = None): """Create a Value of this type from a python object.""" from .support import obj_to_value - return obj_to_value(obj, self, self) + v = obj_to_value(obj, self, self) + if name is not None: + v.name = name + return v return _PyCDEType(type) diff --git a/frontends/PyCDE/src/pycde/support.py b/frontends/PyCDE/src/pycde/support.py index ef4276f36a..3b81975f89 100644 --- a/frontends/PyCDE/src/pycde/support.py +++ b/frontends/PyCDE/src/pycde/support.py @@ -63,6 +63,7 @@ class OpOperandConnect(support.OpOperand): def obj_to_value(x, type, result_type=None): """Convert a python object to a CIRCT value, given the CIRCT type.""" assert x is not None + from .value import Value type = support.type_to_pytype(type) if isinstance(type, hw.TypeAliasType): @@ -72,19 +73,19 @@ def obj_to_value(x, type, result_type=None): result_type = type else: result_type = support.type_to_pytype(result_type) - assert isinstance(result_type, hw.TypeAliasType) + assert isinstance(result_type, hw.TypeAliasType) or result_type == type val = support.get_value(x) # If x is already a valid value, just return it. if val is not None: if val.type != result_type: raise ValueError(f"Expected {result_type}, got {val.type}") - return val + return Value.get(val) if isinstance(x, int): if not isinstance(type, ir.IntegerType): raise ValueError(f"Int can only be converted to hw int, not '{type}'") - return hw.ConstantOp.create(type, x).result + return Value.get(hw.ConstantOp.create(type, x).result) if isinstance(x, list): if not isinstance(type, hw.ArrayType): @@ -95,7 +96,7 @@ def obj_to_value(x, type, result_type=None): f"{len(x)} vs {type.size}") list_of_vals = list(map(lambda x: obj_to_value(x, elemty), x)) # CIRCT's ArrayCreate op takes the array in reverse order. - return hw.ArrayCreateOp.create(reversed(list_of_vals)).result + return Value.get(hw.ArrayCreateOp.create(reversed(list_of_vals)).result) if isinstance(x, dict): if not isinstance(type, hw.StructType): @@ -109,8 +110,9 @@ def obj_to_value(x, type, result_type=None): x.pop(fname) if len(x) > 0: raise ValueError(f"Extra fields specified: {x}") - return hw.StructCreateOp.create(elem_name_values, - result_type=result_type).result + return Value.get( + hw.StructCreateOp.create(elem_name_values, + result_type=result_type).result) raise ValueError(f"Unable to map object '{type(x)}' to MLIR Value") diff --git a/frontends/PyCDE/test/verilog_readablility.py b/frontends/PyCDE/test/verilog_readablility.py new file mode 100644 index 0000000000..e6908ba85b --- /dev/null +++ b/frontends/PyCDE/test/verilog_readablility.py @@ -0,0 +1,43 @@ +# RUN: %PYTHON% %s | FileCheck %s + +from pycde import (Output, Input, module, generator, types, dim, System) + + +@module +class WireNames: + clk = Input(types.i1) + sel = Input(types.i2) + data_in = Input(dim(32, 3)) + + a = Output(types.i32) + b = Output(types.i32) + + @generator + def build(mod): + foo = mod.data_in[0] + foo.name = "foo" + arr_data = dim(32, 4).create([1, 2, 3, 4], "arr_data") + return { + 'a': foo.reg(mod.clk).reg(mod.clk), + 'b': arr_data[mod.sel], + } + + +sys = System([WireNames]) +sys.generate() +sys.print() +# CHECK: hw.module @pycde.WireNames(%clk: i1, %data_in: !hw.array<3xi32>, %sel: i2) -> (%a: i32, %b: i32) { +# CHECK: %c0_i2 = hw.constant 0 : i2 +# CHECK: %0 = hw.array_get %data_in[%c0_i2] {name = "foo"} : !hw.array<3xi32> +# CHECK: %c1_i32 = hw.constant 1 : i32 +# CHECK: %c2_i32 = hw.constant 2 : i32 +# CHECK: %c3_i32 = hw.constant 3 : i32 +# CHECK: %c4_i32 = hw.constant 4 : i32 +# CHECK: %1 = hw.array_create %c4_i32, %c3_i32, %c2_i32, %c1_i32 : i32 +# CHECK: %2 = seq.compreg %0, %clk {name = "foo__reg1"} : i32 +# CHECK: %3 = seq.compreg %2, %clk {name = "foo__reg2"} : i32 +# CHECK: %4 = hw.array_get %1[%sel] : !hw.array<4xi32> +# CHECK: hw.output %3, %4 : i32, i32 +# CHECK: } + +sys.print_verilog()