diff --git a/frontends/PyCDE/src/pycde/value.py b/frontends/PyCDE/src/pycde/value.py index c62a38d886..36c42ab998 100644 --- a/frontends/PyCDE/src/pycde/value.py +++ b/frontends/PyCDE/src/pycde/value.py @@ -11,6 +11,8 @@ from circt.dialects import hw, seq import mlir.ir as ir +import re + class Value: @@ -28,8 +30,40 @@ class Value: return StructValue(value, type) return RegularValue(value, type) - def reg(self, clk, rst=None): - return seq.reg(self.value, clk, rst) + _reg_name = re.compile(r"^(.*)__reg(\d+)$") + + def reg(self, clk, rst=None, name=None): + if name is None: + name = self.name + if name is not None: + m = Value._reg_name.match(name) + if m: + basename = m.group(1) + reg_num = m.group(2) + name = f"{basename}__reg{int(reg_num)+1}" + else: + name = name + "__reg1" + return Value.get(seq.reg(self.value, clock=clk, reset=rst, name=name)) + + @property + def name(self): + owner = self.value.owner + if hasattr(owner, "attributes") and "name" in owner.attributes: + return ir.StringAttr(owner.attributes["name"]).value + if isinstance(owner, ir.Block) and isinstance(owner.owner, hw.HWModuleOp): + mod = owner.owner + return ir.StringAttr( + ir.ArrayAttr(mod.attributes["argNames"])[self.value.arg_number]).value + if hasattr(self, "_name"): + return self._name + + @name.setter + def name(self, new: str): + owner = self.value.owner + if hasattr(owner, "attributes"): + owner.attributes["name"] = ir.StringAttr.get(new) + else: + self._name = new class RegularValue(Value): @@ -57,7 +91,10 @@ class ListValue(Value): raise TypeError("Subscript on array must be either int or MLIR int" f" Value, not {type(sub)}.") with get_user_loc(): - return Value.get(hw.ArrayGetOp.create(self.value, idx)) + v = Value.get(hw.ArrayGetOp.create(self.value, idx)) + if self.name and isinstance(idx, int): + v.name = self.name + f"__{idx}" + return v def __len__(self): return self.type.strip.size @@ -81,5 +118,8 @@ class StructValue(Value): fields = ty.get_fields() if attr in [name for name, _ in fields]: with get_user_loc(): - return Value.get(hw.StructExtractOp.create(self.value, attr)) + v = Value.get(hw.StructExtractOp.create(self.value, attr)) + if self.name: + v.name = f"{self.name}__{attr}" + return v raise AttributeError(f"'Value' object has no attribute '{attr}'") diff --git a/frontends/PyCDE/test/syntactic_sugar.py b/frontends/PyCDE/test/syntactic_sugar.py index e89f3d9fd3..f1d06a4ff8 100644 --- a/frontends/PyCDE/test/syntactic_sugar.py +++ b/frontends/PyCDE/test/syntactic_sugar.py @@ -52,7 +52,7 @@ class ComplexPorts: def build(mod): assert len(mod.data_in) == 3 return { - 'a': mod.data_in[0].reg(mod.clk), + 'a': mod.data_in[0].reg(mod.clk).reg(mod.clk), 'b': mod.data_in[mod.sel], 'c': mod.struct_data_in.foo } @@ -84,8 +84,11 @@ sys.generate() sys.print() # CHECK: hw.module @pycde.Comple_Ports(%clk: i1, %data_in: !hw.array<3xi32>, %sel: i2, %struct_data_in: !hw.struct) -> (%a: i32, %b: i32, %c: i32) { # CHECK: %c0_i2 = hw.constant 0 : i2 -# CHECK: [[REG0:%.+]] = hw.array_get %data_in[%c0_i2] : !hw.array<3xi32> -# CHECK: [[REGR:%.+]] = seq.compreg [[REG0]], %clk : i32 +# CHECK: [[REG0:%.+]] = hw.array_get %data_in[%c0_i2] {name = "data_in__0"} : !hw.array<3xi32> +# CHECK: [[REGR1:%.+]] = seq.compreg [[REG0]], %clk {name = "data_in__0__reg1"} : i32 +# CHECK: [[REGR2:%.+]] = seq.compreg [[REGR1]], %clk {name = "data_in__0__reg2"} : i32 # CHECK: [[REG1:%.+]] = hw.array_get %data_in[%sel] : !hw.array<3xi32> -# CHECK: [[REG2:%.+]] = hw.struct_extract %struct_data_in["foo"] : !hw.struct -# CHECK: hw.output [[REGR]], [[REG1]], [[REG2]] : i32, i32, i32 +# CHECK: [[REG2:%.+]] = hw.struct_extract %struct_data_in["foo"] {name = "struct_data_in__foo"} : !hw.struct +# CHECK: hw.output [[REGR2]], [[REG1]], [[REG2]] : i32, i32, i32 + +sys.print_verilog()