New, copy, clone or duplicate?

We often need to declare a local Signal with the same properties as a port. I used localsignal = Signal(intbv(0)[len(portsignal):]) but this only works for intbv types. Chris taught me: localsignal = Signal(portsignal._val) which is a bit shorter. I don’t remember whether this also works for bool().
Now to write generic code I deemed it more interesting to have a method to create this new signal. So I added a new() method to the Signal class, but then I found out that Python has a hidden __new__() so I changed the name to copy(). Of course this now collides somewhat with Python’s copy() and deepcopy(). I don’t like the name clone although this may be the best match. How about using duplicate() or shortened: dup()?
The rationale for having this functionality is that new types like Array (MEP-112 under development) and StructType (No MEP yet) would benefit from such an easier method to create a new object.

Regards,

Josy

Other Python objects have a copy method, that would probably be the correct approach. Example both list and dict objects have a copy method.

but in Python copy() is shallow; to get a new Signal (or Array or …) it would have to be deepcopy(). I would like to stay away from the Python semantics and avoid any flak :worried:
Also copy() and deepcopy should (?) be implemented as hooks; __copy__() and __deepcopy__(), and then be used as:

import copy

. . . 

a = copy.deepcopy(b)

Which is very well understood by experienced Python user, but takes a bit of study for the VHDL, Verilog user base.
Where as a dup() would be a method:


a = b.dup()

I think we might differ in opinion on this one. Following the “Python way” has served us well, i.e. we leverage their language design experience. I would propose the __copy__ and __deepcopy__ but also add a shortcut with a copy method.

x = Signal(sigtype)
y = x.copy()

a = [sigtype for _ in range(16)]
b = copy.deepcopy(a)

Hi, looking at _Signal.py I would like to propose localsignal = Signal(portsignal).
We usually pass an instance of something to the Signal constructor and that is then deepcopied.

I see your point, and agree, to some extent.
The __copy__() hook would not be of much use, as we can’t do much with a shallow copy.
Implementing __deepcopy__() is then what we need, calling the short-cut copy() could create some confusion.
Am I right in reading your second example as: Python’s copy() function will iterate through the list and call on the _deepcopy__() from sigtype?

This will not work for all (present and future) types, e.g. if the portsignal is an Array we can’t expect the Signal class to handle it …

I see… Signal(Array([1,0,1])) will not work? No .next for Arrays?

@smldis you can do this with:

localsignal = Signal(portsignal.val)

I think that is reasonable for shallow init.

that’s better! I was just trying to point out that syntax like intbv(intbv(0)[8:]) is something familiar in myhdl codebase. In general this could be extended to every myhdl “types” and even Signals.

At the moment I have Array(shape, type) loosely modelled after the numpy ndarray. It has a.next property,of course! And a few extra goodies …

Chris,
I just found out that _intbv.py has (almost) identical code for __copy__ and __deepcopy__. If we adopt this further copy() would be acceptable for the shortcut method. (and would be almost identical code too). This will simplify my code for Array() (and StructType())

Regards,

Josy